@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,292 @@
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 { isNaN } from 'lodash'
15
+ import { computed, nextTick, onBeforeUnmount, onBeforeUpdate, ref, watch, watchEffect } from 'vue'
16
+ import { date } from 'quasar'
17
+ import type { MOtpProps as Props } from '../../types'
18
+ import { useMyth } from '../../composable'
19
+ import { myth } from '../../utils'
20
+
21
+ export interface P {
22
+ // modelValue?: Props['modelValue'];
23
+ inputLength?: Props['inputLength'];
24
+ numeric?: Props['numeric'];
25
+ time?: Props['time'];
26
+ hideTime?: Props['hideTime'];
27
+ hideSendAgain?: Props['hideSendAgain'];
28
+ topLabel?: Props['topLabel'];
29
+ topLabelProps?: Props['topLabelProps'];
30
+ autofocus?: Props['autofocus'];
31
+ errors?: Props['errors'];
32
+ }
33
+
34
+ type Emits = {
35
+ (e: 'end'): void;
36
+ (e: 'send'): void;
37
+ }
38
+ const emit = defineEmits<Emits>()
39
+ const { __ } = useMyth()
40
+ const { props: pluginOptions } = myth
41
+ const props = withDefaults(defineProps<P>(), {
42
+ // modelValue: undefined,
43
+ inputLength: () => 6,
44
+ numeric: () => !0,
45
+ time: () => 120,
46
+ hideTime: () => !1,
47
+ hideSendAgain: () => !1,
48
+ topLabel: undefined,
49
+ topLabelProps: undefined,
50
+ autofocus: () => !1,
51
+ errors: () => ([])
52
+ })
53
+ const modelValue = defineModel<Props['modelValue']>({ required: !1, default: undefined })
54
+ const otpErrors = computed(() => props.errors ? props.errors : [])
55
+ const length = computed<number>(() => parseInt(props.inputLength?.toString() || '0'))
56
+ const fields = ref<any>([])
57
+ const fieldValues = ref<(string | number | null | undefined)[]>([])
58
+ watchEffect(() => {
59
+ fieldValues.value = (modelValue.value || '').toString().split('').slice(0, length.value)
60
+ })
61
+
62
+ const composite = computed(() => {
63
+ const nonNullFields = fieldValues.value.filter(v => (v || v?.toString() !== '0'))
64
+ if (length.value !== nonNullFields.length) {
65
+ return ''
66
+ }
67
+ return nonNullFields.join('')
68
+ })
69
+
70
+ watch(composite, () => {
71
+ if (composite.value) {
72
+ if (props.numeric !== !1) {
73
+ if (!isNaN(composite.value) && composite.value?.toString()?.length?.toString() === props.inputLength.toString()) {
74
+ modelValue.value = composite.value
75
+ }
76
+ } else {
77
+ modelValue.value = composite.value
78
+ }
79
+ }
80
+ })
81
+
82
+ // make sure to reset the refs before each update
83
+ onBeforeUpdate(() => {
84
+ fields.value = []
85
+ })
86
+
87
+ const updateFieldRef = (element: any, index: number) => {
88
+ if (element) {
89
+ fields.value[index] = element
90
+ }
91
+ }
92
+
93
+ const focus = (index: number) => {
94
+ if (index >= 0) {
95
+ if (index < length.value) {
96
+ fields.value[index]?.select()
97
+ } else {
98
+ if (composite.value) {
99
+ fields.value[index - 1]?.blur()
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ const blur = (index: number) => {
106
+ fields.value[index]?.blur()
107
+ }
108
+
109
+ const onUpdate = (value: string | number | null, index: number) => {
110
+ if (value) {
111
+ if (props.numeric !== !1 && isNaN(value)) {
112
+ nextTick(() => {
113
+ setTimeout(() => {
114
+ focus(index)
115
+ }, 100)
116
+ })
117
+ return
118
+ }
119
+ focus(index + 1)
120
+ if (index === (length.value - 1)) {
121
+ blur(index)
122
+ }
123
+ }
124
+ }
125
+
126
+ const onKeyDown = (evt: KeyboardEvent, index: number) => {
127
+ if (props.numeric !== !1 && evt.key && evt.key.toString() !== '0' && !parseInt(evt.key) && evt.key?.length === 1) {
128
+ evt.preventDefault()
129
+ }
130
+ }
131
+ const onKeyUp = (evt: KeyboardEvent, index: number) => {
132
+ const key = evt.key
133
+ if (['Tab', 'Shift', 'Meta', 'Control', 'Alt', 'Enter', ' '].includes(key)) {
134
+ return
135
+ }
136
+
137
+ if (['Delete'].includes(key)) {
138
+ focus(index - 1)
139
+ return
140
+ }
141
+
142
+ if (key === 'ArrowLeft' || key === 'Backspace') {
143
+ focus(index - 1)
144
+ } else if (key === 'ArrowRight') {
145
+ focus(index + 1)
146
+ }
147
+
148
+ // The input is fill & replace the value
149
+ // if (key.length === 1) {
150
+ // onUpdate(key, index)
151
+ // const t = [...fieldValues.value]
152
+ // t[index] = key
153
+ // fieldValues.value = t
154
+ // }
155
+ }
156
+ const onPaste = (evt: ClipboardEvent, index: number) => {
157
+ const value: any = evt.clipboardData?.getData('text')?.toString() || ''
158
+ if (props.numeric !== !1 && isNaN(value)) {
159
+ evt.preventDefault()
160
+ return
161
+ }
162
+ if (value?.length > 0) {
163
+ fieldValues.value = value.slice(0, length.value).split('').map((e: string) => parseInt(e) || 0)
164
+ blur(index)
165
+ }
166
+ }
167
+
168
+ const seconds = ref<number>(0)
169
+ const temp = ref<number>(0)
170
+ watch(() => seconds.value, v => (temp.value = v))
171
+ const startTiming = () => {
172
+ if (props.hideTime) {
173
+ return
174
+ }
175
+
176
+ if (seconds.value > 0) {
177
+ --seconds.value
178
+ if (!seconds.value) {
179
+ emit('end')
180
+ }
181
+ }
182
+ }
183
+ const getTime = computed<string | null>(() => {
184
+ const nullValue = null
185
+ if (props.hideTime) {
186
+ return nullValue
187
+ }
188
+ if (seconds.value < 1) {
189
+ return '00:00'
190
+ }
191
+
192
+ const newDate = date.buildDate({ minutes: 0, seconds: seconds.value, milliseconds: 0 })
193
+ const m = newDate.getMinutes()
194
+ const s = newDate.getSeconds()
195
+ return `${(m < 9 ? '0' : '') + m}:${(s < 9 ? '0' : '') + s}`
196
+ })
197
+ const disabled = computed(() => seconds.value > 0)
198
+ let interval: any = null
199
+ const clear = () => {
200
+ interval && clearInterval(interval)
201
+ }
202
+ const start = () => {
203
+ if (props.hideTime) {
204
+ return
205
+ }
206
+ clear()
207
+ seconds.value = parseInt(props.time?.toString()) || 120
208
+ interval = setInterval(() => startTiming(), 1000)
209
+ }
210
+ watch(() => props.time, () => start(), { immediate: !0, deep: !0 })
211
+ onBeforeUnmount(() => clear())
212
+ const onSend = () => {
213
+ if (disabled.value) {
214
+ return
215
+ }
216
+ emit('send')
217
+ }
218
+ defineExpose({ start })
219
+ defineOptions({
220
+ name: 'MOtp',
221
+ inheritAttrs: !1
222
+ })
223
+ </script>
224
+
225
+ <template>
226
+ <MCol
227
+ auto
228
+ class="text-center"
229
+ v-bind="$attrs"
230
+ >
231
+ <slot name="before-all" />
232
+ <MRow
233
+ v-if="!!topLabel"
234
+ class="justify-start q-mb-md text-body1"
235
+ v-bind="topLabelProps"
236
+ >
237
+ <div>
238
+ {{ __(topLabel) }}
239
+ </div>
240
+ </MRow>
241
+ <div :class="`row ${$q.lang.rtl ? 'reverse' : ''} q-gutter-x-sm justify-center`">
242
+ <q-input
243
+ v-for="i in length"
244
+ :key="i"
245
+ :ref="el => updateFieldRef(el, i - 1)"
246
+ v-model="fieldValues[i - 1]"
247
+ :autofocus="autofocus && i === 1"
248
+ :error="otpErrors.length > 0"
249
+ hide-bottom-space
250
+ input-class="text-center"
251
+ maxlength="1"
252
+ no-error-icon
253
+ outlined
254
+ style="width: 6ch"
255
+ v-bind="{...pluginOptions.otp as any,...$attrs}"
256
+ @keydown="onKeyDown($event, i - 1)"
257
+ @keyup="onKeyUp($event, i - 1)"
258
+ @paste.prevent="onPaste($event,i - 1)"
259
+ @update:model-value="onUpdate($event, i - 1)"
260
+ />
261
+ </div>
262
+ <div
263
+ v-if="otpErrors.length > 0"
264
+ class="q-my-md text-negative"
265
+ >
266
+ {{ otpErrors[0] }}
267
+ </div>
268
+ <slot name="after-input" />
269
+ <MFadeTransition>
270
+ <div
271
+ v-if="!hideTime"
272
+ class="q-mt-sm"
273
+ >
274
+ <span>{{ __('myth.otp.expire_line') }}:&nbsp;</span>
275
+ <span>{{ getTime }}</span>
276
+ </div>
277
+ </MFadeTransition>
278
+ <MFadeTransition>
279
+ <div
280
+ v-if="!hideSendAgain"
281
+ class="q-mt-sm"
282
+ >
283
+ <span>{{ __('myth.otp.send_again_title') }}&nbsp;</span>
284
+ <span
285
+ :class="{'text-decoration-underline':!0, disabled,'cursor-pointer': !disabled}"
286
+ @click="onSend()"
287
+ >{{ __('myth.otp.send_again_btn') }}</span>
288
+ </div>
289
+ </MFadeTransition>
290
+ <slot name="after-all" />
291
+ </MCol>
292
+ </template>
@@ -0,0 +1,73 @@
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 type { MInputSlots, MPasswordProps as Props } from '../../types'
14
+ import MInput from './MInput.vue'
15
+ import { ref, useTemplateRef } from 'vue'
16
+
17
+ type P = {
18
+ name?: Props['name'];
19
+ icon?: Props['icon'];
20
+ noToggle?: Props['noToggle'];
21
+ }
22
+
23
+ withDefaults(defineProps<P>(), {
24
+ name: () => '',
25
+ icon: () => !1,
26
+ noToggle: () => !1
27
+ })
28
+ const modelValue = defineModel<Props['modelValue']>({ required: !1, default: undefined })
29
+ const inputType = ref<'text' | 'password'>('password')
30
+ const togglePassword = () => {
31
+ inputType.value = inputType.value === 'text' ? 'password' : 'text'
32
+ }
33
+ const input = useTemplateRef<InstanceType<typeof MInput>>('input')
34
+ defineExpose<{ input: typeof input }>({ input })
35
+ defineOptions({
36
+ name: 'MPassword',
37
+ inheritAttrs: !1
38
+ })
39
+ </script>
40
+
41
+ <template>
42
+ <MInput
43
+ ref="input"
44
+ v-model="modelValue"
45
+ :name="name"
46
+ v-bind="{...$attrs,type:inputType}"
47
+ >
48
+ <template
49
+ v-if="icon && !Boolean($slots.prepend)"
50
+ #prepend
51
+ >
52
+ <q-icon name="password" />
53
+ </template>
54
+ <template
55
+ v-if="!noToggle && !Boolean($slots.prepend)"
56
+ #append
57
+ >
58
+ <q-btn
59
+ :icon="'ion-ios-eye' + (inputType !== 'password' ? '-off' : '')"
60
+ flat
61
+ round
62
+ @click="togglePassword()"
63
+ />
64
+ </template>
65
+ <template
66
+ v-for="(_,slot) in $slots as Readonly<MInputSlots>"
67
+ :key="slot"
68
+ #[slot]
69
+ >
70
+ <slot :name="slot" />
71
+ </template>
72
+ </MInput>
73
+ </template>
@@ -0,0 +1,313 @@
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, reactive, ref, toValue, useTemplateRef } from 'vue'
14
+ import type { MPickerProps as Props } from '../../types'
15
+ import { useBindInput, useMyth } from '../../composable'
16
+ import { useField } from 'vee-validate'
17
+ import { QDate, QField, QFieldSlots, QTime } from 'quasar'
18
+ import { myth } from '../../utils'
19
+
20
+ const defSeparator = ' - '
21
+ const props = withDefaults(defineProps<Omit<Props, 'prefix'>>(), {
22
+ name: '',
23
+ type: undefined,
24
+ fillMask: undefined,
25
+ reverseFillMask: undefined,
26
+ unmaskedValue: undefined,
27
+ error: undefined,
28
+ noErrorIcon: undefined,
29
+ reactiveRules: undefined,
30
+ lazyRules: undefined,
31
+ stackLabel: undefined,
32
+ hideHint: undefined,
33
+ dark: undefined,
34
+ loading: undefined,
35
+ clearable: undefined,
36
+ filled: undefined,
37
+ outlined: undefined,
38
+ borderless: undefined,
39
+ standout: undefined,
40
+ labelSlot: undefined,
41
+ bottomSlots: undefined,
42
+ hideBottomSpace: undefined,
43
+ counter: undefined,
44
+ rounded: undefined,
45
+ square: undefined,
46
+ dense: undefined,
47
+ itemAligned: undefined,
48
+ disable: undefined,
49
+ readonly: undefined,
50
+ autofocus: undefined,
51
+ autogrow: undefined,
52
+ viewMode: undefined,
53
+ auto: undefined,
54
+ col: undefined,
55
+ xs: undefined,
56
+ sm: undefined,
57
+ md: undefined,
58
+ lg: undefined,
59
+ xl: undefined,
60
+ required: undefined,
61
+ autocomplete: undefined,
62
+ topLabel: undefined,
63
+ mobile: undefined,
64
+ email: undefined,
65
+ float: undefined,
66
+ landscape: undefined,
67
+ flat: undefined,
68
+ bordered: undefined,
69
+ yearsInMonthView: undefined,
70
+ noUnset: undefined,
71
+ todayBtn: undefined,
72
+ minimal: undefined,
73
+ multiple: undefined,
74
+ range: undefined,
75
+ emitImmediately: undefined,
76
+ format24h: undefined,
77
+ withSeconds: undefined,
78
+ nowBtn: undefined,
79
+ useChoice: undefined
80
+ })
81
+
82
+ defineModel<Props['modelValue']>({ required: !1, default: undefined })
83
+ const helper = useBindInput<Props>(() => props, 'picker', () => ({ choose: !0 }))
84
+ const { hasTopLabel, getLabel, getPlaceholder, inputRules, getAutocompleteAttribute, getProp } = helper
85
+ const { __ } = useMyth()
86
+ const options = computed(() => myth.props.value)
87
+ const theme = computed(() => myth.themeInput)
88
+ const inputScope = useField<Props['modelValue']>(() => props.name, inputRules, {
89
+ syncVModel: !0,
90
+ label: getLabel,
91
+ ...toValue<any>(props.fieldOptions)
92
+ })
93
+ const scopes = reactive(inputScope)
94
+ const { value, errorMessage, handleChange } = inputScope
95
+
96
+ const isDate = computed(() => props.type !== 'time')
97
+ // const mask = computed(() => {
98
+ // if (props.range || props.multiple) {
99
+ // return undefined
100
+ // // return isDate.value ? '####/##/## - ####-##-##' : '##:## - ##:##'
101
+ // }
102
+ // return isDate.value ? '####/##/##' : '##:##'
103
+ // })
104
+ const format = computed(() => isDate.value ? 'YYYY/MM/DD' : 'HH:mm')
105
+ const dateRef = ref<string | null>(null)
106
+ const onBeforeShow = () => {
107
+ dateRef.value = value.value || null
108
+ }
109
+ const onBeforeHide = () => {
110
+ dateRef.value = null
111
+ }
112
+ const saveDialog = () => {
113
+ let newVal: any = dateRef.value
114
+ if (typeof newVal === 'object' && isDate.value) {
115
+ const values: any[] = Object.values(newVal)
116
+ for (const aKey in values) {
117
+ if (typeof values[aKey] === 'object') {
118
+ values[aKey] = Object.values(values[aKey])
119
+ }
120
+ }
121
+ newVal = values
122
+ }
123
+ handleChange(newVal, !!errorMessage.value)
124
+ }
125
+
126
+ const dateElm = useTemplateRef<InstanceType<typeof QDate>>('dateElm')
127
+ const timeElm = useTemplateRef<InstanceType<typeof QTime>>('timeElm')
128
+ defineExpose<{ input: typeof dateElm | typeof timeElm }>({ input: isDate.value ? dateElm : timeElm })
129
+ defineOptions({
130
+ name: 'MPicker',
131
+ inheritAttrs: !1
132
+ })
133
+ </script>
134
+
135
+ <template>
136
+ <MCol
137
+ :auto="auto"
138
+ :class="[$attrs.class,{'m--input__required':inputRules?.required!==undefined,'m--input__error':!!errorMessage,'m--input__view':viewMode}]"
139
+ :col="col"
140
+ :lg="lg"
141
+ :md="md"
142
+ :name="name"
143
+ :sm="sm"
144
+ :xs="xs"
145
+ >
146
+ <slot
147
+ name="top-input"
148
+ v-bind="scopes"
149
+ />
150
+ <slot name="top-label">
151
+ <MInputLabel
152
+ v-if="hasTopLabel"
153
+ :field="scopes"
154
+ >
155
+ <MHelpRow
156
+ :text="help"
157
+ tooltip
158
+ />
159
+ </MInputLabel>
160
+ </slot>
161
+ <slot name="caption">
162
+ <div
163
+ v-if="!!caption"
164
+ class="m--input__caption"
165
+ >
166
+ {{ __(caption) }}
167
+ </div>
168
+ </slot>
169
+ <q-field
170
+ ref="input"
171
+ v-model="value"
172
+ :error="!!errorMessage"
173
+ :error-message="errorMessage"
174
+ :hint="__(hint)"
175
+ :label="hasTopLabel ? undefined : getLabel"
176
+ v-bind="{
177
+ ...options.input as any,
178
+ ...options.field as any,
179
+ ...theme,
180
+ ...$attrs,
181
+ autocomplete:getAutocompleteAttribute,
182
+ stackLabel: !0
183
+ }"
184
+ >
185
+ <template #control>
186
+ <slot name="control">
187
+ <div
188
+ v-if="!disable && !readonly && !viewMode && !!getPlaceholder && !value"
189
+ class="q-placeholder"
190
+ >
191
+ {{ getPlaceholder }}
192
+ </div>
193
+ <template v-else-if="viewMode && viewModeValue">
194
+ <div>{{ viewModeValue?.toString() }}</div>
195
+ </template>
196
+ <template v-else>
197
+ <div>
198
+ <template v-if="value && Array.isArray(value)">
199
+ {{ value.join(rangeSeparator || options.picker?.rangeSeparator || defSeparator) }}
200
+ </template>
201
+ <template v-else>
202
+ {{ value?.toString() }}
203
+ </template>
204
+ </div>
205
+ </template>
206
+ </slot>
207
+ </template>
208
+ <template #append>
209
+ <q-btn
210
+ v-if="!disable && !readonly && !viewMode"
211
+ :icon="isDate ? 'ion-ios-calendar' : 'ion-ios-clock'"
212
+ flat
213
+ round
214
+ v-bind="{...options?.pickerBtn, ...btnProps}"
215
+ >
216
+ <q-popup-proxy
217
+ cover
218
+ no-shake
219
+ persistent
220
+ transition-hide="jump-down"
221
+ transition-show="jump-up"
222
+ @before-show="onBeforeShow()"
223
+ @before-hide="onBeforeHide()"
224
+ >
225
+ <q-card>
226
+ <q-date
227
+ v-if="isDate"
228
+ ref="dateElm"
229
+ v-bind="{
230
+ ...options.date as any,
231
+ ...props,
232
+ ...$attrs,
233
+ todayBtn: getProp('todayBtn') === undefined ? !0 : getProp('todayBtn'),
234
+ mask:format,
235
+ multiple,
236
+ range,
237
+ modelValue: dateRef ?? null
238
+ }"
239
+ @update:model-value="dateRef = $event ?? null"
240
+ >
241
+ <template #default>
242
+ <div class="row items-center justify-end">
243
+ <MBtn
244
+ v-close-popup
245
+ :label="__('close')"
246
+ color="negative"
247
+ flat
248
+ />
249
+ <MBtn
250
+ v-close-popup
251
+ :label="__('save')"
252
+ flat
253
+ @click="saveDialog()"
254
+ />
255
+ </div>
256
+ </template>
257
+ </q-date>
258
+ <q-time
259
+ v-else
260
+ ref="timeElm"
261
+ v-bind="{
262
+ ...$props,
263
+ ...options.time,
264
+ ...$attrs,
265
+ mask:format,
266
+ nowBtn: getProp('nowBtn') === undefined? !0 : getProp('nowBtn'),
267
+ modelValue: dateRef ?? null
268
+ }"
269
+ @update:model-value="dateRef = $event ?? null"
270
+ >
271
+ <div class="row items-center justify-end">
272
+ <MBtn
273
+ v-close-popup
274
+ :label="__('close')"
275
+ color="negative"
276
+ flat
277
+ />
278
+ <MBtn
279
+ v-close-popup
280
+ :label="__('save')"
281
+ flat
282
+ @click="saveDialog()"
283
+ />
284
+ </div>
285
+ </q-time>
286
+ </q-card>
287
+ </q-popup-proxy>
288
+ </q-btn>
289
+ </template>
290
+
291
+ <template
292
+ v-for="(_,slot) in $slots as Readonly<QFieldSlots>"
293
+ :key="slot"
294
+ #[slot]
295
+ >
296
+ <slot :name="slot" />
297
+ </template>
298
+ </q-field>
299
+ <slot
300
+ name="help"
301
+ v-bind="scopes"
302
+ >
303
+ <MHelpRow
304
+ v-if="!hasTopLabel"
305
+ :text="help"
306
+ />
307
+ </slot>
308
+ <slot
309
+ name="bottom-input"
310
+ v-bind="scopes"
311
+ />
312
+ </MCol>
313
+ </template>