@mythpe/js-helpers
Version:
Library of plugins & shortcuts that use JavaScript, also includes the Vue3 plugin with quasar apps
973 lines (928 loc) • 23.7 kB
TypeScript
/*
* MyTh Ahmed Faiz Copyright © 2016-2024 All rights reserved.
* Email: mythpe@gmail.com
* Mobile: +966590470092
* Website: https://www.4myth.com
* Github: https://github.com/mythpe
*/
import { AxiosRequestConfig } from 'axios'
import {
QAvatarProps,
QAvatarSlots,
QBtnProps,
QBtnSlots,
QCheckboxProps,
QDateProps,
QEditorProps,
QEditorSlots,
QFieldSlots,
QFileProps,
QFileSlots,
QImgProps,
QInputProps,
QInputSlots,
QOptionGroupProps,
QOptionGroupSlots,
QRadioProps,
QSelectProps,
QTimeProps,
QToggleProps,
QUploaderProps,
QUploaderSlots
} from 'quasar'
import { FieldContext, FieldOptions, FormContext, FormOptions, FormState } from 'vee-validate'
import { MaybeRefOrGetter, UnwrapNestedRefs, VNode, ComputedRef, Ref, ShallowRef, WritableComputedRef } from 'vue'
import { MColProps, ViewModeProps } from '../grid/models'
import { EditorConfig } from 'ckeditor5'
import { HelpersStubSchema } from '../../types'
export type BaseInputFieldPropContext = FieldContext<any>;
export type BaseInputFieldProps = {
/**
* Context of field input.
*/
field: UnwrapNestedRefs<BaseInputFieldPropContext>;
readonly label?: string | undefined;
}
export type InputRulesContext = string | string[] | Record<string, any> | undefined;
export type InputErrorsContext = string[];
export type InputFormErrorsContext = Record<string, InputErrorsContext> | undefined;
export type InputHelpProps = {
/**
* Information text with Icon.
*/
readonly help?: string;
}
export type InputHelpSlots = {
/**
* VNode bottom of input & before 'bottom-input slot'.
*/
help: () => VNode[];
}
export type BaseInputFormProps = {
/**
* Input name.
*/
readonly name: string;
/**
* Input model value.
* can be used instead of initialValue.
*/
modelValue?: any;
/**
* Input Label.
*/
readonly label?: string | undefined;
/**
* Caption under label.
*/
readonly caption?: string | undefined;
/**
* Input Hint.
*/
readonly hint?: string | undefined;
/**
* Input Placeholder.
*/
readonly placeholder?: string | undefined;
/**
* Input Required validation.
*/
readonly required?: boolean;
/**
* Input Validation Rules.
*/
readonly rules?: InputRulesContext;
/**
* Input Error Messages.
*/
// errors?: InputErrorsContext;
/**
* Form Error Messages.
*/
// formErrors?: InputFormErrorsContext;
/**
* Input autocomplete attribute.
* if true, will set from input name.
* if false, will set 'off'.
* else, will set the attribute value.
* Default: undefined.
*/
readonly autocomplete?: boolean | string | undefined;
/**
* Inputs Top Label.
*/
readonly topLabel?: boolean;
/**
* Mobile Rule.
*/
readonly mobile?: boolean | string | number | undefined;
/**
* Email Rule.
*/
readonly email?: boolean;
/**
* Number Rule.
*/
readonly float?: boolean;
/**
* vee-validate Field Options.
*/
readonly fieldOptions?: Partial<FieldOptions> | MaybeRefOrGetter<Partial<FieldOptions>>;
}
export type BaseInputsProps = ViewModeProps & InputHelpProps & Omit<MColProps, 'name'> & BaseInputFormProps;
export type BaseInputsSlots = InputHelpSlots & {
/**
* VNode top of input & top of 'top label slot'.
*/
'top-input': () => VNode[];
/**
* The label top on input
*/
'top-label': () => VNode[];
/**
* VNode top of input & after top label.
*/
caption: () => VNode[];
/**
* Field main content
*/
default: () => VNode[];
/**
* VNode bottom of input.
*/
'bottom-input': () => VNode[];
}
export declare type GenericFormValues = Record<any, any>;
export interface MBtnProps extends QBtnProps {
color?: string | undefined
noCaps?: boolean | undefined
}
export interface MBtnSlots extends QBtnSlots {
/**
* Use for custom content, instead of relying on 'icon' and 'label' props
*/
default: () => VNode[];
/**
* Override the default QSpinner when in 'loading' state
*/
loading: () => VNode[];
}
export interface MInputProps extends Omit<QInputProps, 'rules' | 'name' | 'modelValue' | 'label' | 'hint'>, BaseInputsProps {
//
}
export type MPasswordProps = MInputProps & {
/**
* icon prepend it to password input.
*/
icon?: boolean | undefined;
/**
* toggle password append icon.
*/
noToggle?: boolean | undefined;
}
export type MInputSlots = QInputSlots & QFieldSlots & BaseInputsSlots
export type MFieldProps = Omit<MInputProps, 'viewMode' | 'viewModeValue' | 'fieldOptions'>
export type MFieldSlots = MInputSlots
export type MHiddenInputSlots = object
export type MHiddenInputProps = Pick<BaseInputFormProps, 'rules' | 'required'> & {
/**
* Input name.
*/
name: string;
/**
* Input model value.
*/
modelValue?: any;
}
export type MHiddenProps = MHiddenInputProps & Pick<ViewModeProps, 'viewMode'> & Omit<MColProps, 'name'>
export type MHiddenSlots = {
/**
* Field main content
*/
default: () => VNode[];
}
export type MOptionsOptionContext = Omit<QToggleProps, 'modelValue'> & Omit<QRadioProps, 'modelValue'> & Omit<QCheckboxProps, 'modelValue'> & {
/**
* Label to display along the component
*/
label: string;
/**
* Value of the option that will be used by the component model
*/
value: any;
/**
* If true, the option will be disabled
*/
disable?: boolean;
/**
* Any other props from QToggle, QCheckbox, or QRadio
*/
}
export type MOptionsProps = Omit<QOptionGroupProps, 'name' | 'modelValue' | 'options'> & Omit<BaseInputsProps, 'autocomplete', 'modelValue'> & {
modelValue?: any;
/**
* Array of objects with value, label, and disable (optional) props. The binary components will be created according to this array; Props from QToggle, QCheckbox or QRadio can also be added as key/value pairs to control the components singularly
*/
options?: MOptionsOptionContext[];
/**
* Get options by function. any send the current value to this function to get options.
*/
service?: ((value: any) => Promise<void>) | undefined;
/**
* Service loading.
*/
loading?: boolean | undefined;
/**
* Set content to be full width.
*/
fullWidth?: boolean;
/**
* Set width of content to be equals.
* Default is: 33.33333333%
*/
fitWidth?: boolean;
}
export type MOptionsSlots = QOptionGroupSlots & QFieldSlots & BaseInputsSlots
export type MFileProps =
Omit<QFileProps, 'modelValue' | 'rules' | 'name' | 'label' | 'hint'>
& Omit<BaseInputsProps, 'autocomplete'>
& {
accept?: string | undefined;
images?: boolean;
svg?: boolean;
video?: boolean;
pdf?: boolean;
excel?: boolean;
}
export type MFileSlots = QFileSlots & BaseInputsSlots
export type MPickerProps =
Omit<MInputProps, 'modelValue' | 'type'>
& Omit<QDateProps, 'modelValue' | 'options'>
& Omit<QTimeProps, 'modelValue'>
& {
/**
* Initial value of the picker.
* Default is: null.
*/
modelValue?: any;
/**
* Type of picker. 'date' or 'time'.
* Default is: 'date'.
*/
type?: 'date' | 'time';
/**
* QBtn props for append button.
*/
btnProps?: QBtnProps;
/**
* Value of separator for range picker.
* Default is: ' - '.
*/
rangeSeparator?: string;
}
export type MPickerSlots = MInputSlots
export type MDateProps = Omit<MPickerProps, 'type'>
export type MDateSlots = MPickerSlots
export type MTimeProps = Omit<MPickerProps, 'type'>
export type MTimeSlots = MPickerSlots
export type MSelectModelEmit = { value: any | null; model: object | null }
export type MSelectProps = Omit<QSelectProps, 'rules' | 'name' | 'modelValue' | 'label' | 'hint' | 'autocomplete'> & BaseInputsProps & {
/**
* Input search functionality. useInput prop for this feature.
*/
search?: string | null | undefined;
/**
* Minimum characters to start searching. Default is 1.
*/
searchLength?: string | number;
/**
* hide the default empty list message.
*/
hideEmptyList?: boolean | undefined;
/**
* Disable filter functionality.
*/
noFilter?: boolean | undefined;
/**
* Set mode of component to axios of filter & search.
* if set to true, component will fetch data from api and don't do filter functionality.
*/
axiosMode?: boolean | undefined;
/**
* Fetch Data on mounted
*/
// iniData?: boolean;
}
export type MSelectSlots = QInputSlots & QFieldSlots & BaseInputsSlots
type ParamsReq = Record<string, any>;
export type MAxiosProps = Omit<MSelectProps, 'options' | 'axiosMode'> & {
/**
* Request method. Default is GET.
*/
service: ((config?: AxiosRequestConfig) => Promise<any>) | string;
/**
* Send request as guest request. If false, send request as authenticated user. Default is true.
*/
guest?: boolean | MaybeRefOrGetter<boolean>;
/**
* Request params.
*/
params?: Ref<ParamsReq> | ShallowRef<ParamsReq> | WritableComputedRef<ParamsReq> | ComputedRef<ParamsReq> | (() => ParamsReq);
/**
* Request relations.
*/
requestWith?: MaybeRefOrGetter<string> | undefined;
/**
* Component items.
*/
items?: any[];
/**
* The name of the attribute to be used as a label
*/
attributeName?: string;
/**
* Do fetch asynchronous
*/
lazy?: boolean;
/**
* emit model as Object value.
* @param value
*/
// 'on:model': (value: MSelectModelEmit) => void;
}
export type MAxiosSlots = MSelectSlots
export type BaseCheckboxProps = Omit<BaseInputsProps, 'topLabel'> & {
/**
* Input row props.
*/
rowProps?: Record<string, any>;
/**
* Input column props.
*/
colProps?: Record<string, any>;
}
export type MCheckboxProps = Omit<QCheckboxProps, 'name' | 'modelValue' | 'label'> & BaseCheckboxProps
export type MCheckboxSlots = Omit<BaseInputsSlots, 'top-label'> & {
/**
* VNode before field main content.
*/
before: () => VNode[];
/**
* VNode after field main content.
*/
after: () => VNode[];
}
export type MRadioProps = Omit<QRadioProps, 'name' | 'modelValue' | 'label'> & BaseCheckboxProps
export type MRadioSlots = MCheckboxSlots
export type MToggleProps =
Omit<BaseInputsProps, 'placeholder' | 'topLabel' | 'autocomplete'>
& Omit<QToggleProps, 'modelValue' | 'label' | 'name'>
& {
/**
* Customize the label when the toggle is true.
* Default is: Yes.
*/
activeLabel?: string;
/**
* Customize the label when the toggle is false.
* Default is: No.
*/
inactiveLabel?: string;
/**
* Set labels of toggle to status, Active & Inactive.
*/
status?: boolean;
/**
* Input row props.
*/
rowProps?: Record<string, any>;
/**
* Input column props.
*/
colProps?: Record<string, any>;
}
export type MToggleSlots = MCheckboxSlots & Pick<BaseInputsProps, 'topLabel'>;
export interface MFormProps {
/**
* Form HTML element attributes.
*/
formProps?: Record<string, any>;
/**
* Default options of useForm.
*/
opts?: FormOptions<Record<string, any>>;
/**
* The target to which the page will be scrolled.
* Default is: Window.
*/
target?: HTMLElement | string | undefined;
/**
* Emit values instead controlled values.
* Default is: false.
*/
emitValues?: boolean;
/**
* Watch to reset form values.
*/
readonly state?: MaybeRefOrGetter<Partial<FormState<Record<string, any>>>>;
/**
* Watch to reset form values.
*/
readonly form?: MaybeRefOrGetter<Record<string, any>>;
/**
* Watch to set form values.
*/
readonly values?: MaybeRefOrGetter<Record<string, any>>;
/**
* Watch to set form errors.
*/
readonly errors?: MaybeRefOrGetter<Record<string, string | string[]>>;
/**
* Apply padding to form.
*/
readonly padding?: boolean;
}
export type MFormScope = FormContext<Record<string, any>>;
export interface MFormSlots {
default: (scope: MFormScope) => VNode[];
}
export type MAvatarViewerModelValue = File | null | undefined;
export type MAvatarViewerProps = QAvatarProps & MColProps & {
/**
* Comma separated list of unique file type specifiers. Maps to 'accept' attribute of native input type=file element
*/
accept?: string;
/**
* Add accept file type.
*/
images?: boolean;
/**
* Add accept svg type.
*/
svg?: boolean;
/**
* Add accept video type.
*/
video?: boolean;
/**
* Add accept pdf type.
*/
pdf?: boolean;
/**
* Add accept excel type.
*/
excel?: boolean;
/**
* Show text if no image
*/
avatarText?: string;
/**
* How the image will fit into the container; Equivalent of the object-fit prop; Can be coordinated with 'position' prop
* Default value: cover
*/
fit?: QImgProps['fit'];
/**
* Can clear the input & not required
*/
clearable?: boolean;
/**
* The label that will appear above the image
*/
label?: string;
/**
* List of error messages.
*/
errors?: InputErrorsContext;
/**
* List of form errors.
*/
formErrors?: InputFormErrorsContext;
/**
* Model of the component;
* Must be FileList or Array if using 'multiple' prop;
* Either use this property (along with a listener for 'update:modelValue' event) OR use v-model directive
*/
modelValue?: MAvatarViewerModelValue;
/**
* The name of the file for the image used and the field.
* Example: name='avatar' { avatar: https://4myth.com, avatarBlob: Blob, avatarRemoved: !0 | !1 }
*/
name?: string;
/**
* Avatar url.
* (along with a listener for 'update:url' event) OR use v-model directive
*/
url?: string;
/**
* value if user remove the image
* (along with a listener for 'update:removed' event) OR use v-model directive
*/
removed?: boolean;
/**
* Input hint.
*/
hint?: string;
hintProps?: Record<string, any>;
caption?: string;
captionProps?: Record<string, any>;
/**
* Help text after label.
*/
help?: string;
/**
* Set input to readonly.
*/
readonly?: boolean;
/**
* Loading for skeleton.
*/
loading?: boolean;
}
export interface MAvatarViewerSlots extends QAvatarSlots {
/**
* Field main content
*/
default: () => VNode[];
hint: () => VNode[];
}
export type MUploaderMediaItem = {
id: number;
value: number;
name: string;
file_name: string;
type: string;
size: number;
size_to_string: string;
url: string;
download_url: string;
icon: string;
description: string;
attachment_type: string;
attachment_type_id: number;
attachment_type_id_to_string: string;
user_id: number | null;
user_id_to_string: string;
order_column: number;
[k: string]: any;
};
export type MUploaderServiceType = Pick<HelpersStubSchema, 'getUploadAttachmentsUrl' | 'updateAttachment' | 'uploadAttachments' | 'deleteAttachment'>
export interface MUploaderProps extends Omit<QUploaderProps, 'formFields' | 'headers' | 'url'>, MColProps, Pick<BaseInputsProps, 'fieldOptions'> {
/**
* Name fo field input, Attachments key name.
* Default is: 'attachments'
*/
name?: string;
/**
* Put component in disabled mode
*/
disable?: boolean;
/**
* Put component in readonly mode
*/
readonly?: boolean;
/**
* Comma separated list of unique file type specifiers. Maps to 'accept' attribute of native input type=file element
*/
accept?: string;
/**
* Support for uploading images
*/
images?: boolean;
/**
* Support for uploading svg
*/
svg?: boolean;
/**
* Support for uploading videos
*/
video?: boolean;
/**
* Support for uploading pdf
*/
pdf?: boolean;
/**
* Support for uploading excel
*/
excel?: boolean;
/**
* Upload files immediately when added
*/
autoUpload?: boolean;
/**
* Field name for each file upload; This goes into the following header: 'Content-Disposition: form-data; name="__HERE__"; filename="somefile.png"; If using a function then for best performance, reference it from your scope and do not define it inline
* Default value: (file) => file.name
* @param files The current file being processed
* @returns Field name for the current file upload
*/
fieldName?: string | ((files: File) => string);
/**
* Collection send to API
*/
collection?: string | number | symbol;
/**
* Field Attachment Type
*/
attachmentType?: any;
/**
* return attachments after upload;
* Default current collection name;
*/
returnType?: 'all' | 'current' | undefined;
/**
* Object with additional fields definitions (used by Form to be uploaded);
*/
formFields?: Record<string, any>;
/**
* Extra headers
*/
headers?: Record<string, any>;
/**
* Label for the uploader
*/
label?: string | null | undefined;
/**
* The Attachments list.
*/
modelValue?: MUploaderMediaItem[];
/**
* Hide delete media items from uploader, no delete media For API
*/
hideDeleteMedia?: boolean;
/**
* Show update button of media.
*/
updateBtn?: boolean;
/**
* User APi service for upload & delete
*/
service: string | MUploaderServiceType;
/**
* The ID of model will use in attachments
*/
modelId?: string | number | undefined;
uploading?: boolean | undefined;
defaultFileIcon?: string | undefined;
deleteMediaIcon?: string | undefined;
uploadFilesIcon?: string | undefined;
pickFilesIcon?: string | undefined;
removeUploadedIcon?: string | undefined;
removeQueuedIcon?: string | undefined;
abortUploadIcon?: string | undefined;
downloadFileIcon?: string | undefined;
errorsIcon?: string | undefined;
iconsSize?: string | undefined;
displayMode?: 'list' | 'card' | undefined;
shadow?: string | undefined;
/**
* Media Item Label Field.
* Default is: name.
*/
mediaLabel?: string | undefined;
}
export interface MUploaderSlots extends QUploaderSlots {
/**
* Field main content
*/
default: () => VNode[];
/**
* list of item will be display
*/
// list: (scope: { item: MUploaderMediaItem, index: number }) => VNode[];
/**
* list of item will be display
*/
'item-list': (scope: { item: MUploaderMediaItem, index: number }) => VNode[];
}
export type MUploaderXhrInfo = { files: readonly any[]; xhr: any; }
export type MEditorProps = Omit<QEditorProps, 'modelValue' | 'placeholder'> & BaseInputsProps
export type MEditorSlots = QEditorSlots & BaseInputsSlots
export type MCkeditorProps = Omit<BaseInputsProps, 'hint' | 'topLabel' | 'placeholder' | 'autocomplete'> & {
/**
* Editor language.
* Default value: ar.
*/
lang: 'ar' | 'en';
/**
* Specifies the configuration of the editor.
* https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editorconfig-EditorConfig.html
*/
config?: ((config: EditorConfig) => EditorConfig) | undefined;
/**
* By default, the editor component creates a <div> container which is used as an element passed to the editor (for example, ClassicEditor#element).
* The element can be configured, so for example to create a <textarea>, use the following directive:
* tag-name="textarea"
* Default value: div.
*/
tagName?: string;
/**
* This directive controls the isReadOnly property of the editor.
* Default value: false.
*/
disabled?: boolean;
/**
* Allows disabling the two-way data binding mechanism.
* Default value: false.
*/
disableTwoWayDataBinding?: boolean;
}
export type MCkeditorSlots = BaseInputsSlots
export interface MOtpProps extends Omit<QInputProps, 'modelValue'> {
modelValue?: string | number;
inputLength?: string | number;
numeric?: boolean;
time?: string | number;
hideTime?: boolean;
hideSendAgain?: boolean;
topLabel?: string | undefined;
topLabelProps?: any | undefined;
errors?: string[];
}
export interface MOtpSlots extends QInputSlots {
default: () => VNode[];
'before-all': () => VNode[];
'after-all': () => VNode[];
'after-input': () => VNode[];
}
export type MInputFieldControlProps = any;
export type MInputFieldControlSlots = {
default: () => VNode[];
}
export type MInputLabelProps = BaseInputFieldProps;
export type MInputLabelSlots = {
default: () => VNode[];
}
export type SignaturePadWaterMark = {
/**
* Watermark text. default is: ''
* e.g. "Your Name", "Your Company", "Date"
*/
text: string;
/**
* Mark font. Default is: '20px sans-serif'
*/
font: string;
/**
* Fill Text and Stroke Text, 'all' | 'stroke' | 'fill'.
* Default is: 'fill'.
*/
style: 'all' | 'stroke' | 'fill';
/**
* Fill color.
* Default is: '#333'
*/
fillStyle: CSSStyleDeclaration['color'];
/**
* Stroke Color.
* Default is: '#333'.
*/
strokeStyle: CSSStyleDeclaration['color'];
/**
* Fill positionX.
* Default is: 20
*/
x: number;
/**
* fill positionY.
* Default is: 20
*/
y: number;
/**
* Stroke positionX.
* Default is: 40
*/
sx: number;
/**
* Stroke positionY.
* Default is: 40
*/
sy: number;
}
export type MSignaturePadProps = Omit<MColProps, 'name'> & Pick<BaseInputsProps, 'fieldOptions'> & {
/**
* Base64 data of the signature.
*/
modelValue?: string | null | undefined;
/**
* Name of field.
* Default is: signature.
*/
name?: string;
/**
* Signature pen color.
* Default is: 'rgb(0, 0, 0)'
*/
color?: CSSStyleDeclaration['color'];
/**
* Signature pad background color.
* Default is: 'rgb(255,255,255)'
*/
bg?: CSSStyleDeclaration['backgroundColor'];
/**
* Parent container width.
* Need units like 100px or 100%
* Default is: '100%'
*/
width?: string;
/**
* Parent container height.
* Need units like 100px or 100%
* Default is: '200px'
*/
height?: string;
/**
* Canvas is cleared on window resize.
* Default is: false.
*/
clearOnResize?: boolean;
/**
* Disable Signature pad.
* Default is: false.
*/
disabled?: boolean;
/**
* Add Required validation.
* Default is: false.
*/
required?: boolean;
/**
* Signature pad label.
* Default is: undefined.
*/
label?: string | undefined | null;
/**
* Props of signature pad label.
* Default is: undefined.
*/
labelProps?: Record<string, any>;
/**
* Signature pad center label.
* Default is: false.
*/
center?: boolean | undefined;
/**
* Default value for signature url.
* Default is: undefined.
*/
url?: string | undefined;
/**
* Hide control buttons.
* Default is: false.
*/
noBtn?: boolean;
/**
* Size of signature pad label.
* Default is: false.
*/
large?: boolean;
/**
* Signature pad watermark text.
* Default is: undefined.
*/
waterMark?: SignaturePadWaterMark;
}
export type MSignaturePadMethods = {
/**
* Save image as PNG/JPEG/SVG
* @param type
*/
save: (type: 'image/jpeg' | 'image/svg+xml') => string;
/**
* Clear canvas
*/
clear: () => void;
/**
* Returns true if canvas is empty.
* otherwise returns false
*/
isEmpty: () => boolean;
/**
* Remove the last step of pen.
*/
undo: () => void;
/**
* Reset Pad state.
*/
reset: () => void;
/**
* Add Text Watermark.
*/
addWaterMark: (opt: SignaturePadWaterMark) => void;
/**
* Draws signature image from data URL.
*/
fromDataURL: (url: string) => void;
}
export type MSignaturePadSlots = {
'top-input': () => VNode[];
default: () => VNode[];
pad: (scope: {
width: MSignaturePadProps['width'];
height: MSignaturePadProps['height'];
reset: MSignaturePadMethods['reset'];
save: MSignaturePadMethods['save'];
clear: MSignaturePadMethods['clear'];
undo: MSignaturePadMethods['undo']
}) => VNode[];
'bottom-input': () => VNode[];
}
export {}