@mythpe/quasar-ui-qui 0.0.27 → 0.0.28-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 (93) hide show
  1. package/index.d.ts +13 -0
  2. package/package.json +17 -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/MCkeditor.vue +403 -0
  14. package/src/components/form/MColor.vue +122 -0
  15. package/src/components/form/MDate.vue +50 -0
  16. package/src/components/form/MEditor.vue +285 -0
  17. package/src/components/form/MEmail.vue +43 -0
  18. package/src/components/form/MField.vue +148 -0
  19. package/src/components/form/MFile.vue +215 -0
  20. package/src/components/form/MForm.vue +89 -0
  21. package/src/components/form/MHidden.vue +86 -0
  22. package/src/components/form/MHiddenInput.vue +58 -0
  23. package/src/components/form/MInput.vue +178 -0
  24. package/src/components/form/MInputFieldControl.vue +27 -0
  25. package/src/components/form/MInputLabel.vue +38 -0
  26. package/src/components/form/MMobile.vue +43 -0
  27. package/src/components/form/MOptions.vue +255 -0
  28. package/src/components/form/MOtp.vue +292 -0
  29. package/src/components/form/MPassword.vue +73 -0
  30. package/src/components/form/MPicker.vue +313 -0
  31. package/src/components/form/MRadio.vue +181 -0
  32. package/src/components/form/MSelect.vue +352 -0
  33. package/src/components/form/MTime.vue +48 -0
  34. package/src/components/form/MToggle.vue +211 -0
  35. package/src/components/form/MUploader.vue +511 -0
  36. package/src/components/form/index.ts +65 -0
  37. package/src/components/grid/MBlock.vue +39 -18
  38. package/src/components/grid/MCol.vue +11 -15
  39. package/src/components/grid/MColumn.vue +12 -1
  40. package/src/components/grid/MContainer.vue +22 -13
  41. package/src/components/grid/MHelpRow.vue +13 -12
  42. package/src/components/grid/MRow.vue +31 -10
  43. package/src/components/grid/index.ts +16 -0
  44. package/src/components/index.ts +15 -0
  45. package/src/components/modal/MDialog.vue +58 -0
  46. package/src/components/modal/MModalMenu.vue +62 -0
  47. package/src/components/modal/MTooltip.vue +39 -0
  48. package/src/components/modal/index.ts +5 -0
  49. package/src/components/parials/UploaderItem.vue +298 -0
  50. package/src/components/parials/index.ts +3 -0
  51. package/src/components/transition/MFadeTransition.vue +27 -0
  52. package/src/components/transition/MFadeXTransition.vue +26 -0
  53. package/src/components/transition/MTransition.vue +44 -0
  54. package/src/components/transition/index.ts +13 -0
  55. package/src/components/typography/MTypingString.vue +8 -0
  56. package/src/components/typography/index.ts +11 -0
  57. package/src/composable/index.ts +12 -0
  58. package/src/composable/useBindInput.ts +209 -0
  59. package/src/composable/useError.ts +11 -0
  60. package/src/composable/useMyth.ts +311 -0
  61. package/src/composable/useValue.ts +12 -0
  62. package/src/index.common.js +19 -1
  63. package/src/index.esm.js +18 -3
  64. package/src/index.js +19 -0
  65. package/src/index.sass +9 -26
  66. package/src/index.ts +18 -4
  67. package/src/index.umd.js +17 -2
  68. package/src/style/m-container.sass +13 -0
  69. package/src/style/main.sass +146 -0
  70. package/src/style/print.sass +14 -0
  71. package/src/style/transition.sass +40 -0
  72. package/src/types/api-helpers.d.ts +62 -0
  73. package/src/types/components.d.ts +1108 -27
  74. package/src/types/index.d.ts +21 -1
  75. package/src/types/install-options.d.ts +19 -0
  76. package/src/types/lodash.d.ts +26 -0
  77. package/src/types/m-datatable.d.ts +316 -0
  78. package/src/types/m-geolocation.d.ts +16 -0
  79. package/src/types/m-helpers.d.ts +97 -0
  80. package/src/types/plugin-props-option.d.ts +305 -0
  81. package/src/types/quasar-helpers.d.ts +7 -0
  82. package/src/types/theme.d.ts +12 -0
  83. package/src/utils/Helpers.ts +293 -0
  84. package/src/utils/Str.ts +211 -0
  85. package/src/utils/index.ts +13 -0
  86. package/src/utils/myth.ts +109 -0
  87. package/src/utils/vee-rules.ts +32 -0
  88. package/src/utils/vue-plugin.ts +163 -0
  89. package/tsconfig.json +9 -13
  90. package/src/myth.ts +0 -30
  91. package/src/types/myth.ts +0 -42
  92. package/src/vue-plugin.ts +0 -41
  93. package/types.d.ts +0 -1
@@ -0,0 +1,43 @@
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 { MInputProps as Props, MInputSlots } from '../../types'
14
+ import { useTemplateRef } from 'vue'
15
+ import MInput from './MInput.vue'
16
+ import { myth } from '../../utils'
17
+
18
+ const modelValue = defineModel<Props['modelValue']>({ required: !1, default: undefined })
19
+ const input = useTemplateRef<InstanceType<typeof MInput>>('input')
20
+ const { props: options } = myth
21
+ defineExpose<{ input: typeof input }>({ input })
22
+ defineOptions({
23
+ name: 'MMobile',
24
+ inheritAttrs: !1
25
+ })
26
+ </script>
27
+
28
+ <template>
29
+ <MInput
30
+ ref="input"
31
+ v-model="modelValue"
32
+ type="tel"
33
+ v-bind="{...options.mobile as any,...$attrs}"
34
+ >
35
+ <template
36
+ v-for="(_,slot) in $slots as Readonly<MInputSlots>"
37
+ :key="slot"
38
+ #[slot]
39
+ >
40
+ <slot :name="slot" />
41
+ </template>
42
+ </MInput>
43
+ </template>
@@ -0,0 +1,255 @@
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 { useField } from 'vee-validate'
15
+ import type { MOptionsOptionContext, MOptionsProps as Props } from '../../types'
16
+ import { reactive, toValue, useTemplateRef } from 'vue'
17
+ import { QField, QOptionGroup, type QOptionGroupSlots } from 'quasar'
18
+ import { useBindInput, useMyth } from '../../composable'
19
+ import { myth } from '../../utils'
20
+
21
+ type P = {
22
+ name: Props['name'];
23
+ auto?: Props['auto'];
24
+ col?: Props['col'];
25
+ xs?: Props['xs'];
26
+ sm?: Props['sm'];
27
+ md?: Props['md'];
28
+ lg?: Props['lg'];
29
+ xl?: Props['xl'];
30
+ label?: Props['label'];
31
+ caption?: Props['caption'];
32
+ hint?: Props['hint'];
33
+ placeholder?: Props['placeholder'];
34
+ help?: Props['help'];
35
+ required?: Props['required'];
36
+ rules?: Props['rules'];
37
+ viewMode?: Props['viewMode'];
38
+ viewModeValue?: Props['viewModeValue'];
39
+ topLabel?: Props['topLabel'];
40
+ color?: Props['color'];
41
+ type?: Props['type'];
42
+ keepColor?: Props['keepColor'];
43
+ service?: Props['service'];
44
+ fullWidth?: Props['fullWidth'];
45
+ fitWidth?: Props['fullWidth'];
46
+ fieldOptions?: Props['fieldOptions'];
47
+ }
48
+
49
+ const props = withDefaults(defineProps<P>(), {
50
+ name: () => '',
51
+ auto: undefined,
52
+ col: undefined,
53
+ xs: undefined,
54
+ sm: undefined,
55
+ md: undefined,
56
+ lg: undefined,
57
+ xl: undefined,
58
+ label: undefined,
59
+ caption: undefined,
60
+ hint: undefined,
61
+ placeholder: undefined,
62
+ help: undefined,
63
+ required: undefined,
64
+ rules: undefined,
65
+ viewMode: () => !1,
66
+ viewModeValue: undefined,
67
+ topLabel: undefined,
68
+ color: () => 'primary',
69
+ type: 'radio',
70
+ keepColor: undefined,
71
+ service: undefined,
72
+ fullWidth: () => !1,
73
+ fitWidth: () => !1,
74
+ fieldOptions: undefined
75
+ })
76
+ defineModel<Props['modelValue']>({ required: !1, default: undefined })
77
+ const loading = defineModel<Props['loading']>('loading', { required: !1, default: !1 })
78
+ const options = defineModel<MOptionsOptionContext[]>('options', { required: !1, default: undefined })
79
+ const helper = useBindInput<P>(() => props, 'options')
80
+ const { getLabel, inputRules, getProp } = helper
81
+ const inputScope = useField<Props['modelValue']>(() => props.name, inputRules, {
82
+ syncVModel: !0,
83
+ label: getLabel,
84
+ ...toValue<any>(props.fieldOptions)
85
+ })
86
+ const { value, errorMessage, handleChange, handleBlur } = inputScope
87
+
88
+ const listeners = {
89
+ blur: (v: any) => handleBlur(v, !0),
90
+ 'update:modelValue': (v: Props['modelValue']) => handleChange(v, !!errorMessage.value)
91
+ }
92
+ const input = useTemplateRef<InstanceType<typeof QField> | InstanceType<typeof QOptionGroup>>('input')
93
+ const scopes = reactive(inputScope)
94
+ defineExpose<typeof scopes & { input: typeof input }>({ input, ...scopes })
95
+ const { alertError, __ } = useMyth()
96
+ const { props: pluginProps } = myth
97
+ const fetchData = async () => {
98
+ if (props.service) {
99
+ loading.value = !0
100
+ try {
101
+ const { _data } = await props.service()
102
+ options.value = _data as any
103
+ } catch (e: any) {
104
+ alertError(e?._message || e?.message || 'Failed to fetch data')
105
+ } finally {
106
+ loading.value = !1
107
+ }
108
+ }
109
+ }
110
+ fetchData()
111
+ defineOptions({
112
+ name: 'MOptions',
113
+ inheritAttrs: !1
114
+ })
115
+ </script>
116
+
117
+ <template>
118
+ <MCol
119
+ :auto="auto"
120
+ :class="[$attrs.class,{'m--input__required':inputRules?.required!==undefined,'m--input__error':!!errorMessage,'m--input__view':viewMode}]"
121
+ :col="col"
122
+ :lg="lg"
123
+ :md="md"
124
+ :name="name"
125
+ :sm="sm"
126
+ :xs="xs"
127
+ >
128
+ <slot
129
+ name="top-input"
130
+ v-bind="scopes"
131
+ />
132
+ <slot name="top-label">
133
+ <MInputLabel
134
+ v-if="!!getLabel"
135
+ :field="scopes"
136
+ >
137
+ <MHelpRow
138
+ v-if="!!help"
139
+ :text="help"
140
+ tooltip
141
+ />
142
+ <MTransition>
143
+ <q-spinner-dots
144
+ v-if="loading"
145
+ color="primary"
146
+ size="25px"
147
+ />
148
+ </MTransition>
149
+ </MInputLabel>
150
+ </slot>
151
+ <slot name="caption">
152
+ <div
153
+ v-if="!!caption"
154
+ class="m--input__caption"
155
+ >
156
+ {{ __(caption) }}
157
+ </div>
158
+ </slot>
159
+ <MTransition>
160
+ <div
161
+ v-if="!!errorMessage"
162
+ class="text-negative text-caption"
163
+ >
164
+ <q-icon
165
+ v-if="!!errorMessage"
166
+ color="negative"
167
+ name="ion-ios-information-circle-outline"
168
+ size="20px"
169
+ />
170
+ {{ errorMessage }}
171
+ </div>
172
+ </MTransition>
173
+ <component
174
+ :is="viewMode ? QField : QOptionGroup"
175
+ ref="input"
176
+ :class="{'m--options': !0, 'm--options__full_width': fullWidth, 'm--options__fit_width': fitWidth }"
177
+ :color="!!errorMessage ? 'negative' : getProp('color')"
178
+ :error="viewMode ? !!errorMessage : undefined"
179
+ :error-message="viewMode ? errorMessage : undefined"
180
+ :hint="viewMode ? __(hint) : undefined"
181
+ :keep-color="!!errorMessage ? !0 : getProp('keepColor')"
182
+ :label="getLabel"
183
+ :model-value="value"
184
+ :options="options"
185
+ :type="viewMode ? undefined : type"
186
+ v-bind="{ ...pluginProps.options as any,...( viewMode ? pluginProps.field : {} ), ...$attrs, ...( viewMode ? { stackLabel: !0 } : {} ) }"
187
+ v-on="listeners"
188
+ >
189
+ <template
190
+ v-for="(_,slot) in $slots as Readonly<QOptionGroupSlots>"
191
+ :key="slot"
192
+ #[slot]="inputSlot"
193
+ >
194
+ <slot
195
+ :name="slot"
196
+ v-bind="inputSlot || {}"
197
+ />
198
+ </template>
199
+ <template
200
+ v-if="viewMode"
201
+ #control
202
+ >
203
+ <slot name="control">
204
+ <MInputFieldControl>
205
+ {{ viewModeValue ?? value }}
206
+ </MInputFieldControl>
207
+ </slot>
208
+ </template>
209
+ </component>
210
+ <slot
211
+ name="help"
212
+ v-bind="scopes"
213
+ >
214
+ <MHelpRow
215
+ v-if="!getLabel"
216
+ :text="help"
217
+ />
218
+ </slot>
219
+ <slot
220
+ name="bottom-input"
221
+ v-bind="scopes"
222
+ />
223
+ <slot
224
+ :options="options"
225
+ v-bind="scopes"
226
+ />
227
+ </MCol>
228
+ </template>
229
+
230
+ <style lang="sass">
231
+ $c: calc(100% / 3)
232
+
233
+ .m--options
234
+ .q-checkbox__inner,
235
+ .q-radio__inner,
236
+ .q-toggle__inner
237
+ align-self: flex-start
238
+
239
+ &__full_width
240
+ > div
241
+ .q-checkbox,
242
+ .q-radio,
243
+ .q-toggle,
244
+ .q-checkbox__label,
245
+ .q-radio__label,
246
+ .q-toggle__label
247
+ width: 100%
248
+
249
+ &__fit_width
250
+ margin-left: 0
251
+
252
+ > div
253
+ width: calc(100% / 3)
254
+ margin-left: 0
255
+ </style>
@@ -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>