@mythpe/quasar-ui-qui 0.0.26-dev → 0.0.27-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/index.d.ts +0 -4
  2. package/package.json +2 -1
  3. package/src/components/datatable/MDatatable.vue +2305 -0
  4. package/src/components/datatable/MDtAvatar.vue +49 -0
  5. package/src/components/datatable/MDtBtn.vue +153 -0
  6. package/src/components/datatable/MDtContextmenuItems.vue +54 -0
  7. package/src/components/datatable/index.ts +6 -0
  8. package/src/components/form/MAvatarViewer.vue +6 -3
  9. package/src/components/form/MAxios.vue +7 -4
  10. package/src/components/form/MCheckbox.vue +33 -9
  11. package/src/components/form/MDate.vue +4 -1
  12. package/src/components/form/MEmail.vue +4 -1
  13. package/src/components/form/MField.vue +4 -1
  14. package/src/components/form/MFile.vue +5 -2
  15. package/src/components/form/MForm.vue +4 -1
  16. package/src/components/form/MHiddenInput.vue +4 -1
  17. package/src/components/form/MInput.vue +1 -1
  18. package/src/components/form/MInputLabel.vue +4 -1
  19. package/src/components/form/MMobile.vue +4 -1
  20. package/src/components/form/MOptions.vue +255 -0
  21. package/src/components/form/MOtp.vue +292 -0
  22. package/src/components/form/MRadio.vue +5 -2
  23. package/src/components/form/MSelect.vue +4 -1
  24. package/src/components/form/MTime.vue +4 -1
  25. package/src/components/form/MToggle.vue +211 -0
  26. package/src/components/form/MUploader.vue +511 -0
  27. package/src/components/form/index.ts +9 -1
  28. package/src/components/grid/MColumn.vue +4 -1
  29. package/src/components/grid/MHelpRow.vue +5 -1
  30. package/src/components/index.ts +3 -0
  31. package/src/components/modal/MDialog.vue +58 -0
  32. package/src/components/modal/MModalMenu.vue +62 -0
  33. package/src/components/modal/MTooltip.vue +39 -0
  34. package/src/components/modal/index.ts +5 -0
  35. package/src/components/parials/UploaderItem.vue +298 -0
  36. package/src/components/parials/index.ts +3 -0
  37. package/src/components/transition/MTransition.vue +4 -1
  38. package/src/composable/useBindInput.ts +1 -1
  39. package/src/composable/useMyth.ts +20 -11
  40. package/src/index.sass +2 -1
  41. package/src/style/main.sass +104 -0
  42. package/src/style/print.sass +14 -0
  43. package/src/style/transition.sass +40 -0
  44. package/src/types/api-helpers.d.ts +11 -72
  45. package/src/types/components.d.ts +411 -105
  46. package/src/types/index.d.ts +5 -139
  47. package/src/types/install-options.d.ts +19 -0
  48. package/src/types/m-datatable.d.ts +316 -0
  49. package/src/types/m-geolocation.d.ts +16 -0
  50. package/src/types/m-helpers.d.ts +97 -0
  51. package/src/types/plugin-props-option.d.ts +301 -0
  52. package/src/utils/myth.ts +15 -1
  53. package/src/utils/vue-plugin.ts +34 -2
  54. package/src/types/dt.d.ts +0 -144
@@ -0,0 +1,511 @@
1
+ <!--
2
+ - MyTh Ahmed Faiz Copyright © 2016-2024 All rights reserved.
3
+ - Email: mythpe@gmail.com
4
+ - Mobile: +966590470092
5
+ - Website: https://www.4myth.com
6
+ - Github: https://github.com/mythpe
7
+ -->
8
+ <script
9
+ lang="ts"
10
+ setup
11
+ >
12
+ import { QList, type QRejectedEntry, QUploader, type QUploaderFactoryObject } from 'quasar'
13
+ import { computed, nextTick, reactive, useTemplateRef, watch } from 'vue'
14
+ import { useBindInput, useError, useMyth, useValue } from '../../composable'
15
+ import type { MUploaderMediaItem, MUploaderProps as Props, MUploaderXhrInfo } from '../../types'
16
+ import { useFieldArray, useFieldValue, useFormValues, useResetForm } from 'vee-validate'
17
+
18
+ interface P {
19
+ name?: Props['name'];
20
+ auto?: Props['auto'];
21
+ col?: Props['col'];
22
+ xs?: Props['xs'];
23
+ sm?: Props['sm'];
24
+ md?: Props['md'];
25
+ lg?: Props['lg'];
26
+ xl?: Props['xl'];
27
+ disable?: Props['disable'];
28
+ readonly?: Props['readonly'];
29
+ accept?: Props['accept'];
30
+ images?: Props['images'];
31
+ svg?: Props['svg'];
32
+ video?: Props['video'];
33
+ pdf?: Props['pdf'];
34
+ excel?: Props['excel'];
35
+ autoUpload?: Props['autoUpload'];
36
+ fieldName?: Props['fieldName'];
37
+ collection?: Props['collection'];
38
+ attachmentType?: Props['attachmentType'];
39
+ returnType?: Props['returnType'];
40
+ formFields?: Props['formFields'];
41
+ headers?: Props['headers'];
42
+ label?: Props['label'];
43
+ hideDeleteMedia?: Props['hideDeleteMedia'];
44
+ hideUploadBtn?: Props['hideUploadBtn'];
45
+ updateBtn?: Props['updateBtn'];
46
+ service: Props['service'];
47
+ modelId?: Props['modelId'];
48
+ batch?: Props['batch'];
49
+ defaultFileIcon?: Props['defaultFileIcon'];
50
+ deleteMediaIcon?: Props['deleteMediaIcon'];
51
+ uploadFilesIcon?: Props['uploadFilesIcon'];
52
+ pickFilesIcon?: Props['pickFilesIcon'];
53
+ removeUploadedIcon?: Props['removeUploadedIcon'];
54
+ removeQueuedIcon?: Props['removeQueuedIcon'];
55
+ abortUploadIcon?: Props['abortUploadIcon'];
56
+ downloadFileIcon?: Props['downloadFileIcon'];
57
+ errorsIcon?: Props['errorsIcon'];
58
+ iconsSize?: Props['iconsSize'];
59
+ displayMode?: Props['displayMode'];
60
+ shadow?: Props['shadow'];
61
+ fieldOptions?: Props['fieldOptions'];
62
+ mediaLabel?: Props['mediaLabel'];
63
+ }
64
+
65
+ const props = withDefaults(defineProps<P>(), {
66
+ name: () => 'attachments',
67
+ auto: undefined,
68
+ col: undefined,
69
+ xs: undefined,
70
+ sm: undefined,
71
+ md: undefined,
72
+ lg: undefined,
73
+ xl: undefined,
74
+ readonly: undefined,
75
+ disable: undefined,
76
+ accept: undefined,
77
+ images: () => !1,
78
+ svg: () => !1,
79
+ video: () => !1,
80
+ pdf: () => !1,
81
+ excel: () => !1,
82
+ autoUpload: () => !0,
83
+ fieldName: 'attachment',
84
+ collection: undefined,
85
+ attachmentType: undefined,
86
+ returnType: undefined,
87
+ formFields: undefined,
88
+ headers: undefined,
89
+ label: undefined,
90
+ hideDeleteMedia: undefined,
91
+ hideUploadBtn: undefined,
92
+ updateBtn: () => !1,
93
+ service: undefined,
94
+ modelId: undefined,
95
+ defaultFileIcon: () => 'o_file_present',
96
+ deleteMediaIcon: () => 'ion-ios-trash',
97
+ uploadFilesIcon: () => 'o_cloud_upload',
98
+ pickFilesIcon: () => 'o_upload_file',
99
+ removeUploadedIcon: () => 'o_done_all',
100
+ removeQueuedIcon: () => 'o_clear_all',
101
+ abortUploadIcon: () => 'o_clear',
102
+ downloadFileIcon: () => 'o_download',
103
+ errorsIcon: () => 'o_error_outline',
104
+ batch: () => !1,
105
+ iconsSize: () => '30px',
106
+ displayMode: () => 'card',
107
+ shadow: () => 'shadow-5',
108
+ fieldOptions: undefined,
109
+ mediaLabel: () => 'name'
110
+ })
111
+
112
+ type Emits = {
113
+ (e: 'startUpload', event: {
114
+ files: readonly File[];
115
+ url: string;
116
+ method: string;
117
+ headers: { name: string; value: string; }[];
118
+ formFields: { name: string; value: string; }[];
119
+ }): void;
120
+
121
+ (e: 'failed', error: MUploaderXhrInfo): void;
122
+
123
+ (e: 'rejected', files: QRejectedEntry[]): void;
124
+
125
+ (e: 'uploaded', error: MUploaderXhrInfo): void;
126
+
127
+ (e: 'delete-media', media: MUploaderMediaItem, result: boolean): void;
128
+
129
+ (e: 'remove-file', file: File): void;
130
+ }
131
+ const emit = defineEmits<Emits>()
132
+
133
+ type Form = Record<string, any>;
134
+ const $myth = useMyth()
135
+ const { alertError, alertSuccess, __ } = $myth
136
+ const { mOptions, api, mAxios, baseUrl } = reactive($myth)
137
+ const fieldId = useFieldValue<string | undefined>('id')
138
+ const modelIdProp = computed(() => props.modelId !== undefined ? props.modelId : fieldId.value)
139
+ const modelValue = defineModel<Props['modelValue']>({ required: !1, default: undefined })
140
+ const { field } = useValue<Props['modelValue']>(() => props.name)
141
+ watch(field, v => (modelValue.value = v), { deep: !0 })
142
+ const { error, setErrors } = useError(() => props.name)
143
+ const resetForm = useResetForm<Form>()
144
+ const formValues = useFormValues<Form>()
145
+ const { fields: attachments } = useFieldArray<MUploaderMediaItem | File>(() => props.name)
146
+
147
+ // const setFormValues = useSetFormValues()
148
+ // const setFormTouched = useSetFormTouched()
149
+ // const error = useFieldError(() => props.name)
150
+ // const setErrors = useSetFieldError(() => props.name)
151
+ // const setFormValues = useSetFormValues()
152
+ // const setTouched = useSetFieldTouched(() => props.name)
153
+ // const modelValue = computed<Props['modelValue']>({
154
+ // get: () => value.value || [],
155
+ // set: (v) => {
156
+ // setFormValues({ [props.name]: v }, !1)
157
+ // model.value = v
158
+ // setTouched(!1)
159
+ // }
160
+ // })
161
+ // const { value: modelValue, error, setErrors, resetField } = useField<Props['modelValue']>(() => props.name, undefined, {
162
+ // syncVModel: !0,
163
+ // label: () => __(props.label),
164
+ // validateOnValueUpdate: !1,
165
+ // ...toValue<any>(props.fieldOptions)
166
+ // })
167
+ const setModelValue = async (value: Props['modelValue']) => {
168
+ const name = props.name
169
+ resetForm({ values: { ...formValues.value, [name]: value }, errors: { [name]: undefined }, touched: { [name]: !1 } })
170
+ }
171
+ const uploader = useTemplateRef<InstanceType<typeof QUploader>>('uploader')
172
+ const uploading = defineModel<boolean>('uploading', { required: !1, default: () => !1 })
173
+ const { accepts } = useBindInput<any>(() => props, 'uploader')
174
+ const iconsSizeProp = computed(() => mOptions.uploaderOptions?.iconsSize || props.iconsSize)
175
+
176
+ /* Events Callback */
177
+ const startUpload = async (files: readonly File[]): Promise<QUploaderFactoryObject> => {
178
+ return new Promise((resolve, reject) => {
179
+ if (!modelIdProp.value) {
180
+ reject()
181
+ return
182
+ }
183
+ try {
184
+ const common = mAxios?.defaults?.headers.common || {}
185
+ const headers: { name: string; value: string; }[] = []
186
+ setErrors([])
187
+ for (const i in common) {
188
+ if (common[i]) {
189
+ headers.push({
190
+ name: i,
191
+ value: common[i] as string
192
+ })
193
+ }
194
+ }
195
+ if (props.headers) {
196
+ for (const f in props.headers) {
197
+ if (props.headers[f]) {
198
+ headers.push({
199
+ name: f,
200
+ value: props.headers[f]
201
+ })
202
+ }
203
+ }
204
+ }
205
+ const formFields: { name: string; value: string; }[] = []
206
+ if (props.formFields) {
207
+ for (const f in props.formFields) {
208
+ if (props.formFields[f]) {
209
+ formFields.push({
210
+ name: f,
211
+ value: props.formFields[f]
212
+ })
213
+ }
214
+ }
215
+ }
216
+ if (props.collection) {
217
+ formFields.push({ name: 'collection', value: props.collection as string })
218
+ }
219
+ if (props.attachmentType) {
220
+ formFields.push({ name: 'attachment_type', value: props.attachmentType })
221
+ }
222
+ if (props.returnType) {
223
+ formFields.push({ name: 'return', value: props.returnType })
224
+ }
225
+ const url: string = typeof props.service === 'string'
226
+ ? api?.[props.service]?.getUploadAttachmentsUrl(modelIdProp.value)
227
+ : props.service.getUploadAttachmentsUrl(modelIdProp.value)
228
+ const resolveValue = {
229
+ url: `${baseUrl}/${url}`,
230
+ method: 'POST',
231
+ headers,
232
+ formFields
233
+ }
234
+ emit('startUpload', {
235
+ files,
236
+ url: `${baseUrl}/${url}`,
237
+ method: 'POST',
238
+ headers,
239
+ formFields
240
+ })
241
+ resolve(resolveValue)
242
+ } catch (e) {
243
+ reject(e)
244
+ console.error(e)
245
+ }
246
+ })
247
+ }
248
+ const onReject = (rejectedEntries: QRejectedEntry[]) => {
249
+ alertError(__('myth.errors.uploaderRejectedEntries', { c: rejectedEntries.length }))
250
+ emit('rejected', rejectedEntries)
251
+ }
252
+ const onError = (info: MUploaderXhrInfo) => {
253
+ const { xhr } = info
254
+ try {
255
+ if (xhr.responseText) {
256
+ const response = JSON.parse(xhr.responseText)
257
+ response?.message && alertError(response.message)
258
+ if (response.errors) {
259
+ const name = typeof props.fieldName === 'function' ? props.fieldName({} as File) : props.fieldName
260
+ if (response.errors[name]) {
261
+ setErrors(response.errors[name])
262
+ } else {
263
+ setErrors(Object.values(response.errors) || [])
264
+ }
265
+ }
266
+ }
267
+ } catch (e: any) {
268
+ e?.message && alertError(e.message)
269
+ } finally {
270
+ emit('failed', info)
271
+ }
272
+ }
273
+ const onFinishUpload = ({ files, xhr }: MUploaderXhrInfo) => {
274
+ try {
275
+ if (xhr.responseText) {
276
+ const response = JSON.parse(xhr.responseText)
277
+ if (response?.data?.length !== undefined) {
278
+ setModelValue(response.data ?? [])
279
+ files.forEach(f => uploader.value?.removeFile(f))
280
+ }
281
+ if (response?.message) {
282
+ alertSuccess(response.message)
283
+ }
284
+ }
285
+ } catch (e: any) {
286
+ e?.message && alertError(e.message)
287
+ } finally {
288
+ nextTick(() => emit('uploaded', { files, xhr }))
289
+ }
290
+ }
291
+
292
+ const onDeleteUploaderFile = (file: File) => {
293
+ uploader.value?.removeFile(file)
294
+ emit('remove-file', file)
295
+ }
296
+ const onDeleteMedia = (media: MUploaderMediaItem, result: boolean) => emit('delete-media', media, result)
297
+ watch(() => uploader.value?.isUploading, (v) => {
298
+ uploading.value = Boolean(v)
299
+ })
300
+ defineOptions({
301
+ name: 'MUploader',
302
+ inheritAttrs: !1
303
+ })
304
+ </script>
305
+
306
+ <template>
307
+ <MCol
308
+ v-if="!!modelIdProp"
309
+ :auto="auto"
310
+ :class="$attrs.class"
311
+ :col="col"
312
+ :lg="lg"
313
+ :md="md"
314
+ :name="name"
315
+ :sm="sm"
316
+ :xs="xs"
317
+ >
318
+ <MFadeTransition>
319
+ <div
320
+ v-if="!!error"
321
+ class="row items-center q-pa-sm bg-negative text-white q-mb-xs rounded-borders"
322
+ >
323
+ <q-icon
324
+ :name="errorsIcon"
325
+ left
326
+ />
327
+ {{ error }}
328
+ </div>
329
+ </MFadeTransition>
330
+ <q-uploader
331
+ ref="uploader"
332
+ :accept="accepts.join(',')"
333
+ :auto-upload="autoUpload"
334
+ :batch="batch"
335
+ :disable="disable"
336
+ :factory="startUpload"
337
+ :field-name="fieldName"
338
+ :label="__(label)"
339
+ :readonly="readonly"
340
+ style="width: 100%;max-height: 450px;"
341
+ v-bind="{...mOptions.uploader as any,...$attrs}"
342
+ @failed="onError"
343
+ @rejected="onReject"
344
+ @uploaded="onFinishUpload"
345
+ >
346
+ <template #header="scope">
347
+ <MRow class="row no-wrap items-center q-pa-sm q-gutter-xs">
348
+ <q-spinner
349
+ v-if="scope.isUploading"
350
+ class="q-uploader__spinner"
351
+ />
352
+ <div class="col">
353
+ <div class="q-uploader__title">
354
+ {{ __(label) }}
355
+ </div>
356
+ <div class="q-uploader__subtitle">
357
+ {{ scope.uploadSizeLabel }} / {{ scope.uploadProgressLabel }}
358
+ </div>
359
+ </div>
360
+ <q-btn
361
+ v-if="scope.queuedFiles.length > 0"
362
+ :icon="removeQueuedIcon"
363
+ :label="__('myth.uploader.clearAll')"
364
+ dense
365
+ flat
366
+ @click="scope.removeQueuedFiles"
367
+ />
368
+ <q-btn
369
+ v-if="scope.uploadedFiles.length > 0"
370
+ :icon="removeUploadedIcon"
371
+ :label="__('myth.uploader.removeUploadedFiles')"
372
+ dense
373
+ flat
374
+ @click="scope.removeUploadedFiles"
375
+ />
376
+ <q-btn
377
+ v-if="scope.canAddFiles && !hideUploadBtn"
378
+ :icon="pickFilesIcon"
379
+ :label="__('myth.uploader.pickFiles')"
380
+ dense
381
+ flat
382
+ @click="scope.pickFiles"
383
+ >
384
+ <q-uploader-add-trigger />
385
+ </q-btn>
386
+ <q-btn
387
+ v-if="scope.canUpload && !hideUploadBtn"
388
+ :icon="uploadFilesIcon"
389
+ :label="__('myth.uploader.uploadFiles')"
390
+ dense
391
+ flat
392
+ @click="scope.upload"
393
+ />
394
+ <q-btn
395
+ v-if="scope.isUploading"
396
+ :icon="abortUploadIcon"
397
+ :label="__('myth.uploader.abortUpload')"
398
+ dense
399
+ flat
400
+ @click="scope.abort"
401
+ />
402
+ </MRow>
403
+ <slot
404
+ name="header"
405
+ v-bind="scope as QUploader"
406
+ />
407
+ </template>
408
+
409
+ <template #list="scope">
410
+ <div
411
+ v-if="!scope.files.length && !attachments?.length"
412
+ key="m--uploader-no-data"
413
+ class="absolute-full"
414
+ >
415
+ <div class="full-width full-height overflow-hidden">
416
+ <MRow class="full-height justify-center items-center">
417
+ <MCol
418
+ auto
419
+ class="text-h6 text-center"
420
+ >
421
+ <q-icon
422
+ left
423
+ name="error_outline"
424
+ />
425
+ <span v-text="__('myth.select.noData')" />
426
+ </MCol>
427
+ </MRow>
428
+ </div>
429
+ </div>
430
+ <template v-else-if="!!$slots.list">
431
+ <slot
432
+ :items="attachments"
433
+ name="list"
434
+ v-bind="scope"
435
+ />
436
+ </template>
437
+ <MRow
438
+ v-else-if="!!$slots['item-list']"
439
+ class="q-col-gutter-sm"
440
+ >
441
+ <template
442
+ v-for="(file,i) in [...scope.files,...(attachments || [])]"
443
+ :key="`item-${i}`"
444
+ >
445
+ <slot
446
+ :index="i"
447
+ :item="file as MUploaderMediaItem"
448
+ name="item-list"
449
+ />
450
+ </template>
451
+ </MRow>
452
+ <q-list
453
+ v-else
454
+ :class="{'row': displayMode === 'card','q-gutter-sm': displayMode === 'card'}"
455
+ :separator="displayMode === 'list' ? !0 : undefined"
456
+ >
457
+ <template
458
+ v-for="(file,i) in scope.files"
459
+ :key="`fi-${i}`"
460
+ >
461
+ <UploaderItem
462
+ :collection="collection"
463
+ :default-file-icon="defaultFileIcon"
464
+ :delete-media-icon="deleteMediaIcon"
465
+ :display-mode="displayMode"
466
+ :download-file-icon="downloadFileIcon"
467
+ :hide-delete-media="hideDeleteMedia"
468
+ :icons-size="iconsSizeProp"
469
+ :media-label="mediaLabel"
470
+ :model-id="modelIdProp"
471
+ :model-value="file"
472
+ :name="name"
473
+ :return-type="returnType"
474
+ :scope="scope"
475
+ :service="service"
476
+ @remove-file="onDeleteUploaderFile"
477
+ @delete-media="onDeleteMedia"
478
+ />
479
+ </template>
480
+ <template v-if="attachments">
481
+ <template
482
+ v-for="f in attachments"
483
+ :key="f.key"
484
+ >
485
+ <UploaderItem
486
+ :collection="collection"
487
+ :default-file-icon="defaultFileIcon"
488
+ :delete-media-icon="deleteMediaIcon"
489
+ :display-mode="displayMode"
490
+ :download-file-icon="downloadFileIcon"
491
+ :hide-delete-media="hideDeleteMedia"
492
+ :icons-size="iconsSizeProp"
493
+ :media-label="mediaLabel"
494
+ :model-id="modelIdProp"
495
+ :model-value="f.value"
496
+ :name="name"
497
+ :return-type="returnType"
498
+ :scope="scope"
499
+ :service="service"
500
+ :update-btn="updateBtn"
501
+ @values="setModelValue"
502
+ @remove-file="onDeleteUploaderFile"
503
+ @delete-media="onDeleteMedia"
504
+ />
505
+ </template>
506
+ </template>
507
+ </q-list>
508
+ </template>
509
+ </q-uploader>
510
+ </MCol>
511
+ </template>
@@ -23,11 +23,15 @@ import MInput from './MInput.vue'
23
23
  import MInputFieldControl from './MInputFieldControl.vue'
24
24
  import MInputLabel from './MInputLabel.vue'
25
25
  import MMobile from './MMobile.vue'
26
+ import MOptions from './MOptions.vue'
27
+ import MOtp from './MOtp.vue'
26
28
  import MPassword from './MPassword.vue'
27
29
  import MPicker from './MPicker.vue'
28
30
  import MRadio from './MRadio.vue'
29
31
  import MSelect from './MSelect.vue'
30
32
  import MTime from './MTime.vue'
33
+ import MToggle from './MToggle.vue'
34
+ import MUploader from './MUploader.vue'
31
35
 
32
36
  export {
33
37
  MAxios,
@@ -47,9 +51,13 @@ export {
47
51
  MInputFieldControl,
48
52
  MInputLabel,
49
53
  MMobile,
54
+ MOptions,
55
+ MOtp,
50
56
  MPassword,
51
57
  MPicker,
52
58
  MRadio,
53
59
  MSelect,
54
- MTime
60
+ MTime,
61
+ MToggle,
62
+ MUploader
55
63
  }
@@ -6,7 +6,10 @@
6
6
  - Github: https://github.com/mythpe
7
7
  -->
8
8
 
9
- <script lang="ts" setup>
9
+ <script
10
+ lang="ts"
11
+ setup
12
+ >
10
13
  defineOptions({
11
14
  name: 'MColumn',
12
15
  inheritAttrs: !1
@@ -13,7 +13,11 @@
13
13
  import { useMyth } from '../../composable'
14
14
  import type { MHelpRowProps } from '../../types'
15
15
 
16
- defineProps<MHelpRowProps>()
16
+ withDefaults(defineProps<MHelpRowProps>(), {
17
+ text: undefined,
18
+ icon: undefined,
19
+ tooltip: !1
20
+ })
17
21
  const { __ } = useMyth()
18
22
  defineOptions({
19
23
  name: 'MHelpRow',
@@ -6,7 +6,10 @@
6
6
  * Github: https://github.com/mythpe
7
7
  */
8
8
 
9
+ export * from './datatable'
9
10
  export * from './form'
10
11
  export * from './grid'
12
+ export * from './modal'
13
+ export * from './parials'
11
14
  export * from './typography'
12
15
  export * from './transition'
@@ -0,0 +1,58 @@
1
+ <!--
2
+ - MyTh Ahmed Faiz Copyright © 2016-2024 All rights reserved.
3
+ - Email: mythpe@gmail.com
4
+ - Mobile: +966590470092
5
+ - Website: https://www.4myth.com
6
+ - Github: https://github.com/mythpe
7
+ -->
8
+
9
+ <script
10
+ lang="ts"
11
+ setup
12
+ >
13
+
14
+ import { computed, reactive } from 'vue'
15
+ import type { MDialogProps as Props } from '../../types'
16
+ import { useMyth } from '../../composable'
17
+
18
+ interface P {
19
+ slide?: Props['slide'] | undefined;
20
+ from?: Props['from']
21
+ }
22
+
23
+ const props = withDefaults(defineProps<P>(), {
24
+ slide: () => !1,
25
+ from: () => 'left'
26
+ })
27
+ const slideProp = computed(() => props.slide !== undefined && props.slide !== !1 && props.slide !== null)
28
+ const map = {
29
+ left: 'right',
30
+ right: 'left',
31
+ up: 'down',
32
+ down: 'up'
33
+ }
34
+
35
+ const slideHide = computed<string>(() => 'slide-' + props.from)
36
+ const slideShow = computed<string>(() => 'slide-' + map[props.from])
37
+ const { mOptions } = reactive(useMyth())
38
+ defineOptions({
39
+ name: 'MDialog',
40
+ inheritAttrs: !1
41
+ })
42
+ </script>
43
+
44
+ <template>
45
+ <q-dialog
46
+ :transition-hide="$q.screen.lt.md ? slideHide : (slideProp ? slideHide : 'jump-down')"
47
+ :transition-show="$q.screen.lt.md ? slideShow : (slideProp ? slideShow : 'jump-up')"
48
+ allow-focus-outside
49
+ maximized
50
+ no-backdrop-dismiss
51
+ no-esc-dismiss
52
+ no-shake
53
+ persistent
54
+ v-bind="{...mOptions.dialog,...$attrs}"
55
+ >
56
+ <slot />
57
+ </q-dialog>
58
+ </template>
@@ -0,0 +1,62 @@
1
+ <!--
2
+ - MyTh Ahmed Faiz Copyright © 2016-2024 All rights reserved.
3
+ - Email: mythpe@gmail.com
4
+ - Mobile: +966590470092
5
+ - Website: https://www.4myth.com
6
+ - Github: https://github.com/mythpe
7
+ -->
8
+ <script
9
+ lang="ts"
10
+ setup
11
+ >
12
+
13
+ import type { MModalMenuProps } from '../../types'
14
+ import { useMyth } from '../../composable'
15
+ import { reactive } from 'vue'
16
+
17
+ interface Props {
18
+ noCloseBtn?: MModalMenuProps['noCloseBtn'];
19
+ position?: MModalMenuProps['position'];
20
+ }
21
+
22
+ const { mOptions, __ } = reactive(useMyth())
23
+ withDefaults(defineProps<Props>(), {
24
+ noCloseBtn: () => !1,
25
+ position: () => 'bottom'
26
+ })
27
+ defineOptions({
28
+ name: 'MModalMenu',
29
+ inheritAttrs: !1
30
+ })
31
+ </script>
32
+
33
+ <template>
34
+ <q-popup-proxy
35
+ :position="position"
36
+ allow-focus-outside
37
+ class="m--modal_menu shadow-24"
38
+ maximized
39
+ no-backdrop-dismiss
40
+ no-shake
41
+ v-bind="{...mOptions.modalMenu,...$attrs}"
42
+ >
43
+ <q-card v-bind="mOptions.modalMenuOptions?.card">
44
+ <slot />
45
+ <template v-if="!noCloseBtn">
46
+ <q-separator class="lt-md" />
47
+ <q-item
48
+ v-close-popup
49
+ class="lt-md"
50
+ clickable
51
+ v-bind="mOptions.modalMenuOptions?.closeBtn"
52
+ >
53
+ <q-item-section>
54
+ <q-item-label header>
55
+ {{ __('myth.titles.close') }}
56
+ </q-item-label>
57
+ </q-item-section>
58
+ </q-item>
59
+ </template>
60
+ </q-card>
61
+ </q-popup-proxy>
62
+ </template>