@mythpe/quasar-ui-qui 0.0.26 → 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 (92) hide show
  1. package/index.d.ts +13 -0
  2. package/package.json +15 -8
  3. package/src/boot/register.ts +14 -0
  4. package/src/components/datatable/MDatatable.vue +2305 -0
  5. package/src/components/datatable/MDtAvatar.vue +49 -0
  6. package/src/components/datatable/MDtBtn.vue +153 -0
  7. package/src/components/datatable/MDtContextmenuItems.vue +54 -0
  8. package/src/components/datatable/index.ts +6 -0
  9. package/src/components/form/MAvatarViewer.vue +327 -0
  10. package/src/components/form/MAxios.vue +144 -0
  11. package/src/components/form/MBtn.vue +271 -93
  12. package/src/components/form/MCheckbox.vue +150 -0
  13. package/src/components/form/MColor.vue +122 -0
  14. package/src/components/form/MDate.vue +50 -0
  15. package/src/components/form/MEditor.vue +285 -0
  16. package/src/components/form/MEmail.vue +43 -0
  17. package/src/components/form/MField.vue +148 -0
  18. package/src/components/form/MFile.vue +215 -0
  19. package/src/components/form/MForm.vue +89 -0
  20. package/src/components/form/MHidden.vue +86 -0
  21. package/src/components/form/MHiddenInput.vue +58 -0
  22. package/src/components/form/MInput.vue +178 -0
  23. package/src/components/form/MInputFieldControl.vue +27 -0
  24. package/src/components/form/MInputLabel.vue +38 -0
  25. package/src/components/form/MMobile.vue +43 -0
  26. package/src/components/form/MOptions.vue +255 -0
  27. package/src/components/form/MOtp.vue +292 -0
  28. package/src/components/form/MPassword.vue +73 -0
  29. package/src/components/form/MPicker.vue +313 -0
  30. package/src/components/form/MRadio.vue +181 -0
  31. package/src/components/form/MSelect.vue +352 -0
  32. package/src/components/form/MTime.vue +48 -0
  33. package/src/components/form/MToggle.vue +211 -0
  34. package/src/components/form/MUploader.vue +511 -0
  35. package/src/components/form/index.ts +63 -0
  36. package/src/components/grid/MBlock.vue +39 -18
  37. package/src/components/grid/MCol.vue +11 -15
  38. package/src/components/grid/MColumn.vue +12 -1
  39. package/src/components/grid/MContainer.vue +22 -13
  40. package/src/components/grid/MHelpRow.vue +13 -12
  41. package/src/components/grid/MRow.vue +31 -10
  42. package/src/components/grid/index.ts +16 -0
  43. package/src/components/index.ts +15 -0
  44. package/src/components/modal/MDialog.vue +58 -0
  45. package/src/components/modal/MModalMenu.vue +62 -0
  46. package/src/components/modal/MTooltip.vue +39 -0
  47. package/src/components/modal/index.ts +5 -0
  48. package/src/components/parials/UploaderItem.vue +298 -0
  49. package/src/components/parials/index.ts +3 -0
  50. package/src/components/transition/MFadeTransition.vue +27 -0
  51. package/src/components/transition/MFadeXTransition.vue +26 -0
  52. package/src/components/transition/MTransition.vue +44 -0
  53. package/src/components/transition/index.ts +13 -0
  54. package/src/components/typography/MTypingString.vue +8 -0
  55. package/src/components/typography/index.ts +11 -0
  56. package/src/composable/index.ts +12 -0
  57. package/src/composable/useBindInput.ts +209 -0
  58. package/src/composable/useError.ts +11 -0
  59. package/src/composable/useMyth.ts +311 -0
  60. package/src/composable/useValue.ts +12 -0
  61. package/src/index.common.js +19 -1
  62. package/src/index.esm.js +18 -3
  63. package/src/index.js +19 -0
  64. package/src/index.sass +9 -26
  65. package/src/index.ts +18 -4
  66. package/src/index.umd.js +17 -2
  67. package/src/style/m-container.sass +13 -0
  68. package/src/style/main.sass +146 -0
  69. package/src/style/print.sass +14 -0
  70. package/src/style/transition.sass +40 -0
  71. package/src/types/api-helpers.d.ts +62 -0
  72. package/src/types/components.d.ts +1075 -27
  73. package/src/types/index.d.ts +21 -1
  74. package/src/types/install-options.d.ts +19 -0
  75. package/src/types/lodash.d.ts +26 -0
  76. package/src/types/m-datatable.d.ts +316 -0
  77. package/src/types/m-geolocation.d.ts +16 -0
  78. package/src/types/m-helpers.d.ts +97 -0
  79. package/src/types/plugin-props-option.d.ts +301 -0
  80. package/src/types/quasar-helpers.d.ts +7 -0
  81. package/src/types/theme.d.ts +12 -0
  82. package/src/utils/Helpers.ts +293 -0
  83. package/src/utils/Str.ts +211 -0
  84. package/src/utils/index.ts +13 -0
  85. package/src/utils/myth.ts +109 -0
  86. package/src/utils/vee-rules.ts +32 -0
  87. package/src/utils/vue-plugin.ts +161 -0
  88. package/tsconfig.json +9 -13
  89. package/src/myth.ts +0 -30
  90. package/src/types/myth.ts +0 -42
  91. package/src/vue-plugin.ts +0 -41
  92. package/types.d.ts +0 -1
@@ -0,0 +1,49 @@
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 { useMyth } from '../../composable'
15
+
16
+ interface Props {
17
+ width?: string | undefined
18
+ src?: string | undefined
19
+ href?: string | undefined;
20
+ }
21
+
22
+ withDefaults(defineProps<Props>(), {
23
+ width: '50px',
24
+ src: undefined,
25
+ href: undefined
26
+ })
27
+ const { openWindow } = useMyth()
28
+ defineOptions({
29
+ name: 'MDtAvatar',
30
+ inheritAttrs: !1
31
+ })
32
+ </script>
33
+
34
+ <template>
35
+ <q-avatar
36
+ rounded
37
+ v-bind="$attrs"
38
+ >
39
+ <q-img
40
+ v-if="src"
41
+ :height="width"
42
+ :src="src"
43
+ :width="width"
44
+ class="cursor-pointer"
45
+ fit="contain"
46
+ @click="openWindow(Boolean(href) ? href: src)"
47
+ />
48
+ </q-avatar>
49
+ </template>
@@ -0,0 +1,153 @@
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 } from 'vue'
15
+ import { useMyth } from '../../composable'
16
+
17
+ interface Props {
18
+ show?: boolean | undefined;
19
+ update?: boolean | undefined;
20
+ destroy?: boolean | undefined;
21
+ tooltip?: string | null | undefined;
22
+ color?: string | undefined;
23
+ icon?: string | undefined;
24
+ listItem?: boolean | undefined;
25
+ label?: string | undefined;
26
+ round?: boolean | undefined;
27
+ dense?: boolean | undefined;
28
+ fabMini?: boolean | undefined;
29
+ }
30
+
31
+ const props = withDefaults(defineProps<Props>(), {
32
+ show: undefined,
33
+ update: undefined,
34
+ destroy: undefined,
35
+ color: undefined,
36
+ icon: undefined,
37
+ tooltip: undefined,
38
+ listItem: undefined,
39
+ label: undefined,
40
+ round: undefined,
41
+ dense: undefined,
42
+ fabMini: undefined
43
+ })
44
+ type Events = {
45
+ (e: 'click', evt: Event): void;
46
+ }
47
+ const emit = defineEmits<Events>()
48
+
49
+ const hasTooltip = computed(() => !!props.tooltip || !!props.show || !!props.update || !!props.destroy)
50
+ const { __, mOptions } = useMyth()
51
+ const getTooltip = computed(() => {
52
+ if (props.tooltip !== undefined) {
53
+ return props.tooltip ? __(props.tooltip) : props.tooltip
54
+ } else if (props.show) {
55
+ return __('labels.show')
56
+ } else if (props.update) {
57
+ return __('labels.update')
58
+ } else if (props.destroy) {
59
+ return __('labels.destroy')
60
+ }
61
+ return props.tooltip
62
+ })
63
+ const getIcon = computed(() => {
64
+ if (props.show) {
65
+ return 'ion-ios-eye'
66
+ } else if (props.update) {
67
+ return 'ion-ios-create'
68
+ } else if (props.destroy) {
69
+ return 'ion-ios-trash'
70
+ }
71
+ return props.icon
72
+ })
73
+ const getColor = computed<string | undefined>(() => {
74
+ if (props.color !== undefined) {
75
+ return props.color
76
+ }
77
+ if (props.show) {
78
+ return mOptions.value?.dt?.contextmenu?.btnStyle?.showColor
79
+ } else if (props.update) {
80
+ return mOptions.value?.dt?.contextmenu?.btnStyle?.updateColor
81
+ } else if (props.destroy) {
82
+ return mOptions.value?.dt?.contextmenu?.btnStyle?.destroyColor
83
+ }
84
+ return props.color
85
+ })
86
+ // const getLabel = computed(() => {
87
+ // if (props.label) {
88
+ // return __(props.label)
89
+ // } else if (props.show) {
90
+ // return __('labels.show')
91
+ // } else if (props.update) {
92
+ // return __('labels.update')
93
+ // } else if (props.destroy) {
94
+ // return __('labels.destroy')
95
+ // }
96
+ // return props.label
97
+ // })
98
+
99
+ defineOptions({
100
+ name: 'MDtBtn',
101
+ inheritAttrs: !1
102
+ })
103
+ </script>
104
+
105
+ <template>
106
+ <q-item
107
+ v-if="listItem"
108
+ v-close-popup
109
+ clickable
110
+ v-bind="{...mOptions.dt?.MDtBtn?.item?.props,...$attrs}"
111
+ @click="emit('click',$event)"
112
+ >
113
+ <q-item-section
114
+ side
115
+ v-bind="mOptions.dt?.MDtBtn?.item?.avatarProps"
116
+ >
117
+ <q-icon
118
+ :color="getColor"
119
+ :name="getIcon"
120
+ v-bind="mOptions.dt?.MDtBtn?.item?.iconProps"
121
+ />
122
+ </q-item-section>
123
+ <q-item-section v-bind="mOptions.dt?.MDtBtn?.item?.labelSectionProps">
124
+ <q-item-label v-bind="mOptions.dt?.MDtBtn?.item?.itemLabelProps">
125
+ <slot>
126
+ {{ label ? __(label) : label }}
127
+ </slot>
128
+ </q-item-label>
129
+ </q-item-section>
130
+ </q-item>
131
+ <q-btn
132
+ v-else
133
+ v-bind="{
134
+ ...mOptions.dt?.MDtBtn?.btn?.props,
135
+ ...$attrs,
136
+ fabMini: fabMini !== undefined ? fabMini : ( mOptions.dt?.btn?.fabMini !== undefined ? mOptions.dt.btn.fabMini : label === undefined),
137
+ round: round !== undefined ? round : ( mOptions.dt?.btn?.round !== undefined ? mOptions.dt.btn.round : label === undefined),
138
+ dense: dense !== undefined ? dense : ( mOptions.dt?.btn?.dense !== undefined ? mOptions.dt.btn.dense : label === undefined),
139
+ label: label !== undefined ? __(label) : label,
140
+ icon: getIcon,
141
+ color: getColor
142
+ }"
143
+ @click="emit('click',$event)"
144
+ >
145
+ <q-tooltip
146
+ v-if="hasTooltip"
147
+ class="m--dt-btn-tooltip"
148
+ >
149
+ {{ getTooltip }}
150
+ </q-tooltip>
151
+ <slot />
152
+ </q-btn>
153
+ </template>
@@ -0,0 +1,54 @@
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 type { MDatatableDialogsOptions, MDatatableProps } from '../../types'
15
+ import { computed, UnwrapRef } from 'vue'
16
+ import { useMyth } from '../../composable'
17
+
18
+ interface Props {
19
+ items: MDatatableProps['contextItems'],
20
+ item: UnwrapRef<MDatatableDialogsOptions['item']>,
21
+ index: UnwrapRef<MDatatableDialogsOptions['index']>,
22
+ displayMode?: 'icon' | 'item'
23
+ }
24
+
25
+ const props = withDefaults(defineProps<Props>(), {
26
+ items: () => ([]),
27
+ item: undefined,
28
+ index: undefined,
29
+ displayMode: () => 'icon'
30
+ })
31
+ const itemMode = computed(() => props.displayMode === 'item')
32
+ const { __ } = useMyth()
33
+ defineOptions({ name: 'MDtContextmenuItems', inheritAttrs: !1 })
34
+ </script>
35
+
36
+ <template>
37
+ <template v-if="item !== undefined && index !== undefined">
38
+ <template
39
+ v-for="(m,i) in items"
40
+ :key="`MDtContextmenuItems-i${i}`"
41
+ >
42
+ <MDtBtn
43
+ v-if="typeof m.showIf === 'function' ? m.showIf(item,index) : m.showIf"
44
+ :[m.name]="!0"
45
+ :label="itemMode && m.label === undefined ? __(m.tooltip || m.attr?.label || m.attr?.tooltip ||m.name) : (m.label !== undefined ? __(m.label || m.name) :
46
+ undefined)"
47
+ :list-item="itemMode"
48
+ :tooltip="m.tooltip !== undefined ? m.tooltip : (m.label === undefined ? m.name : undefined)"
49
+ v-bind="m.attr"
50
+ @click="m.click ? m.click(item,index) : undefined"
51
+ />
52
+ </template>
53
+ </template>
54
+ </template>
@@ -0,0 +1,6 @@
1
+ import MDatatable from './MDatatable.vue'
2
+ import MDtAvatar from './MDtAvatar.vue'
3
+ import MDtBtn from './MDtBtn.vue'
4
+ import MDtContextmenuItems from './MDtContextmenuItems.vue'
5
+
6
+ export { MDatatable, MDtAvatar, MDtBtn, MDtContextmenuItems }
@@ -0,0 +1,327 @@
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
+ import { computed, nextTick, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'
14
+
15
+ import MFile from './MFile.vue'
16
+ import type { MAvatarViewerProps as Props } from '../../types'
17
+ import { useField, useFieldError } from 'vee-validate'
18
+ import { useBindInput, useMyth } from '../../composable'
19
+
20
+ interface P {
21
+ auto?: Props['auto'];
22
+ col?: Props['col'];
23
+ xs?: Props['xs'];
24
+ sm?: Props['sm'];
25
+ md?: Props['md'];
26
+ lg?: Props['lg'];
27
+ xl?: Props['xl'];
28
+ accept?: Props['accept'];
29
+ images?: Props['images'];
30
+ svg?: Props['svg'];
31
+ video?: Props['video'];
32
+ pdf?: Props['pdf'];
33
+ excel?: Props['excel'];
34
+ size?: Props['size'];
35
+ avatarText?: Props['avatarText'];
36
+ fit?: Props['fit'];
37
+ clearable?: Props['clearable'];
38
+ label?: Props['label'];
39
+ rounded?: Props['rounded'];
40
+ name?: Props['name'];
41
+ caption?: Props['caption'];
42
+ captionProps?: Props['captionProps'];
43
+ hint?: Props['hint'];
44
+ hintProps?: Props['hintProps'];
45
+ formErrors?: Props['formErrors'];
46
+ help?: Props['help'];
47
+ readonly?: Props['readonly'];
48
+ loading?: Props['loading'];
49
+ required?: Props['required'];
50
+ rules?: Props['rules'];
51
+ }
52
+
53
+ const props = withDefaults(defineProps<P>(), {
54
+ auto: undefined,
55
+ col: undefined,
56
+ xs: undefined,
57
+ sm: undefined,
58
+ md: undefined,
59
+ lg: undefined,
60
+ xl: undefined,
61
+ accept: undefined,
62
+ images: !0,
63
+ svg: !0,
64
+ video: !1,
65
+ pdf: !1,
66
+ excel: !1,
67
+ size: () => '100px',
68
+ avatarText: undefined,
69
+ fit: () => 'contain',
70
+ clearable: undefined,
71
+ label: undefined,
72
+ rounded: undefined,
73
+ name: 'avatar',
74
+ hint: undefined,
75
+ hintProps: undefined,
76
+ caption: undefined,
77
+ captionProps: undefined,
78
+ formErrors: () => ({}),
79
+ help: undefined,
80
+ readonly: () => !1,
81
+ loading: () => !1,
82
+ required: undefined,
83
+ rules: () => ({})
84
+ })
85
+ type Emits = {
86
+ (e: 'click', evt?: Event): void;
87
+ }
88
+ const emit = defineEmits<Emits>()
89
+ const { __ } = useMyth()
90
+ const { accepts } = useBindInput<any>(() => props, 'avatarViewer')
91
+ const modelValueScope = useField<Props['modelValue']>(() => props.name, undefined, {
92
+ syncVModel: !0
93
+ })
94
+ const { value: modelValue, handleReset } = modelValueScope
95
+ const errorMessage = useFieldError(() => props.name)
96
+ const removedScope = useField<Props['removed']>(() => `${props.name}_removed`, undefined, {
97
+ syncVModel: 'removed'
98
+ })
99
+ const { handleChange: handleRemoved } = removedScope
100
+
101
+ const urlScope = useField<Props['url']>(() => `${props.name}_url`, undefined, {
102
+ syncVModel: 'url'
103
+ })
104
+ const { value: url, handleChange: handleUrl } = urlScope
105
+
106
+ const fileRef = useTemplateRef<typeof MFile>('fileRef')
107
+ const pickFiles = () => fileRef.value?.pickFiles()
108
+ const removeFile = () => fileRef.value?.removeAtIndex(0)
109
+
110
+ /**
111
+ * Blob file to url helpers
112
+ */
113
+ const blobUrl = ref<string | null>(null)
114
+ const isLoaded = ref(!1)
115
+ const revoke = () => {
116
+ if (blobUrl.value) {
117
+ URL.revokeObjectURL(blobUrl.value)
118
+ blobUrl.value = null
119
+ }
120
+ }
121
+ const toUrl = (data?: any) => {
122
+ revoke()
123
+ blobUrl.value = URL.createObjectURL(data)
124
+ return blobUrl
125
+ }
126
+
127
+ const hasSrc = computed(() => !!modelValue.value || !!url.value)
128
+
129
+ /**
130
+ * Check if blob value is a File & not image
131
+ */
132
+ const isFile = computed(() => {
133
+ if (!(modelValue.value instanceof File)) {
134
+ return !1
135
+ }
136
+ return modelValue.value instanceof File && modelValue.value?.type.slice(0, 6) !== 'image/'
137
+ })
138
+ const getAvatarText = computed(() => props.avatarText ? props.avatarText.slice(0, 1).toUpperCase() : undefined)
139
+ const loadingSrc = ref(!1)
140
+ const onClick = (e?: Event) => {
141
+ if (props.readonly) {
142
+ if (loadingSrc.value) {
143
+ loadingSrc.value = !1
144
+ }
145
+ return
146
+ }
147
+ loadingSrc.value = !0
148
+ nextTick(() => {
149
+ if (hasSrc.value && !props.required) {
150
+ onClearInput()
151
+ handleReset()
152
+ loadingSrc.value = !1
153
+ return
154
+ }
155
+ handleReset()
156
+ pickFiles()
157
+ nextTick(() => {
158
+ emit('click', e)
159
+ loadingSrc.value = !1
160
+ })
161
+ })
162
+ }
163
+ const onClearInput = () => {
164
+ removeFile()
165
+ handleRemoved(!0, !1)
166
+ handleUrl(undefined, !1)
167
+ }
168
+ onBeforeUnmount(() => {
169
+ revoke()
170
+ removeFile()
171
+ handleRemoved(undefined, !1)
172
+ })
173
+ watch(modelValue, (v) => {
174
+ if (props.readonly) {
175
+ return
176
+ }
177
+ if (v instanceof File) {
178
+ nextTick(() => toUrl(v))
179
+ }
180
+ })
181
+
182
+ defineOptions({
183
+ name: 'MAvatarViewer',
184
+ inheritAttrs: !1
185
+ })
186
+ </script>
187
+
188
+ <template>
189
+ <MCol
190
+ :auto="auto"
191
+ :class="$attrs.class"
192
+ :col="col"
193
+ :lg="lg"
194
+ :md="md"
195
+ :name="name"
196
+ :sm="sm"
197
+ :xs="xs"
198
+ >
199
+ <MColumn class="items-center">
200
+ <MTransition>
201
+ <div
202
+ v-if="!!label"
203
+ key="label"
204
+ class="row items-center"
205
+ >
206
+ <q-skeleton
207
+ v-if="loading"
208
+ class="q-mb-md"
209
+ height="22px"
210
+ width="80px"
211
+ />
212
+ <div
213
+ v-else
214
+ :class="`text-h6 q-px-sm rounded-borders q-mb-sm ${!!errorMessage ? 'text-negative' : ''}`"
215
+ >
216
+ {{ __(label) }}
217
+ <span
218
+ v-if="!clearable"
219
+ class="text-negative"
220
+ >*</span>
221
+ </div>
222
+ <MHelpRow
223
+ v-if="!!help && !loading"
224
+ :text="help"
225
+ tooltip
226
+ />
227
+ </div>
228
+ <slot name="hint">
229
+ <div
230
+ v-if="!!hint && !loading"
231
+ key="hint"
232
+ class="m--input__hint"
233
+ v-bind="hintProps"
234
+ >
235
+ <span>{{ __(hint) }}</span>
236
+ </div>
237
+ </slot>
238
+ <div
239
+ key="avatar"
240
+ :class="`rounded-borders q-mb-sm ${!!errorMessage ? 'q-pa-xs bg-negative' : ''}`"
241
+ >
242
+ <q-skeleton
243
+ v-if="loading"
244
+ :size="size"
245
+ type="QAvatar"
246
+ />
247
+ <q-avatar
248
+ v-else
249
+ :color="!!errorMessage ? 'negative' : ((!isLoaded || !hasSrc || isFile) ? 'primary' : undefined)"
250
+ :icon="isFile ? 'o_description' : undefined"
251
+ :rounded="rounded === undefined ? hasSrc : rounded"
252
+ :size="size"
253
+ text-color="white"
254
+ >
255
+ <q-img
256
+ v-if="hasSrc && !isFile"
257
+ :fit="fit"
258
+ :height="size"
259
+ :src="blobUrl || url"
260
+ ratio="1"
261
+ @error="isLoaded = !0"
262
+ @load="isLoaded = !0"
263
+ >
264
+ <template #loading>
265
+ <div class="text-white">
266
+ <q-spinner-ios />
267
+ </div>
268
+ </template>
269
+ </q-img>
270
+ <div
271
+ v-if="getAvatarText && !hasSrc"
272
+ class="text-white text-h3"
273
+ v-text="getAvatarText"
274
+ />
275
+ </q-avatar>
276
+ </div>
277
+ <div
278
+ v-if="!readonly"
279
+ key="btn"
280
+ class="q-mb-sm"
281
+ >
282
+ <q-skeleton
283
+ v-if="loading"
284
+ type="QBtn"
285
+ />
286
+ <MBtn
287
+ v-else
288
+ :color="!hasSrc ? 'positive' : 'secondary'"
289
+ :disable="!isLoaded && !!url"
290
+ :icon="hasSrc ? 'ion-ios-close' : 'ion-ios-attach'"
291
+ :label="__( clearable && hasSrc ? 'remove' : ( !clearable && hasSrc ? 'change' : 'choose') )"
292
+ :loading="loadingSrc"
293
+ @click="onClick"
294
+ />
295
+ </div>
296
+ <div
297
+ v-if="!!errorMessage"
298
+ key="errors"
299
+ class="q-mb-sm"
300
+ >
301
+ <span class="text-body2 text-negative">{{ errorMessage }}</span>
302
+ </div>
303
+ </MTransition>
304
+ <slot name="caption">
305
+ <div
306
+ v-if="!!caption"
307
+ class="m--input__caption"
308
+ v-bind="captionProps"
309
+ >
310
+ {{ __(caption) }}
311
+ </div>
312
+ </slot>
313
+ </MColumn>
314
+ <slot />
315
+ <MFile
316
+ key="file"
317
+ ref="fileRef"
318
+ v-model="modelValue"
319
+ :accept="accepts.join(',')"
320
+ :clearable="clearable"
321
+ :name="name || ''"
322
+ :required="required"
323
+ :rules="rules"
324
+ class="hidden"
325
+ />
326
+ </MCol>
327
+ </template>