@simsustech/quasar-components 0.4.7 → 0.5.0

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.
@@ -1,27 +1,31 @@
1
1
  <template>
2
- <q-input
3
- v-bind="attrs"
4
- :rules="validations"
5
- :model-value="modelValue"
6
- :label="`${label}${required ? '*' : ''}`"
7
- :placeholder="lang.datePicker.placeholder"
8
- mask="date"
9
- class="q-pr-md"
10
- @update:model-value="update"
11
- >
12
- <template v-slot:append>
2
+ <q-field :model-value="modelValue" bottom-slots :rules="validations">
3
+ <template #control>
4
+ <component
5
+ :is="QInput"
6
+ v-for="part in format.split('-')"
7
+ :key="part"
8
+ borderless
9
+ v-bind="dateProps[part]"
10
+ />
11
+ </template>
12
+
13
+ <template #append>
13
14
  <q-icon
14
15
  v-if="clearable"
15
16
  name="clear"
16
17
  class="cursor-pointer"
17
- @click="$emit('update:modelValue', null)"
18
+ @click="emit('update:modelValue', null)"
18
19
  />
19
20
  <q-icon name="event" class="cursor-pointer">
21
+ <q-tooltip v-if="formattedDate">
22
+ {{ formattedDate }}
23
+ </q-tooltip>
20
24
  <q-popup-proxy cover transition-show="scale" transition-hide="scale">
21
25
  <q-date
22
26
  v-bind="date"
23
- :model-value="modelValue"
24
- @update:model-value="$emit('update:modelValue', $event)"
27
+ :model-value="modelValue?.replaceAll('-', '/')"
28
+ @update:model-value="setDate"
25
29
  >
26
30
  <div class="row items-center justify-end">
27
31
  <q-btn
@@ -35,51 +39,170 @@
35
39
  </q-popup-proxy>
36
40
  </q-icon>
37
41
  </template>
38
- </q-input>
42
+ </q-field>
39
43
  </template>
40
44
 
41
45
  <script setup lang="ts">
42
- import { ref, watch, useAttrs, toRefs } from 'vue'
43
- import { QDateProps, QInput, useQuasar } from 'quasar'
44
- import { useLang, loadLang } from './lang'
46
+ import { ref, watch, toRefs, computed } from 'vue'
47
+ import {
48
+ QDate,
49
+ QDateProps,
50
+ QInput,
51
+ QInputProps,
52
+ QuasarLanguageCodes
53
+ } from 'quasar'
54
+ import { useLang } from './lang'
45
55
 
46
56
  export interface Props {
47
- modelValue?: string | null
57
+ modelValue: string | null
58
+ format?: 'YYYY-MM-DD' | 'DD-MM-YYYY' | 'MM-DD-YYYY'
59
+ locale?: QuasarLanguageCodes
48
60
  label?: string
49
61
  required?: boolean
50
62
  clearable?: boolean
51
63
  date?: Partial<QDateProps>
52
64
  }
53
- const props = defineProps<Props>()
65
+ const props = withDefaults(defineProps<Props>(), {
66
+ format: 'YYYY-MM-DD',
67
+ locale: 'en-US',
68
+ label: '',
69
+ date: () => ({})
70
+ })
54
71
  const emit = defineEmits<{
55
72
  (e: 'update:modelValue', val: string | null): void
56
73
  }>()
57
- const attrs = useAttrs()
74
+ // const attrs = useAttrs()
58
75
 
59
76
  const lang = useLang()
60
77
 
61
- const $q = useQuasar()
62
- if (lang.value.isoName !== $q.lang.isoName) loadLang($q.lang.isoName)
63
- watch($q.lang, () => {
64
- loadLang($q.lang.isoName)
78
+ const { modelValue, format, locale } = toRefs(props)
79
+
80
+ const year = ref<number>()
81
+ const month = ref<number>()
82
+ const day = ref<number>()
83
+
84
+ const setYear: InstanceType<typeof QInput>['$props']['onUpdate:modelValue'] = (
85
+ val
86
+ ) => {
87
+ const nr = Number(val)
88
+ if (nr && nr > 1e3 && nr < 1e4) year.value = nr
89
+ }
90
+
91
+ const setMonth: InstanceType<typeof QInput>['$props']['onUpdate:modelValue'] = (
92
+ val
93
+ ) => {
94
+ const nr = Number(val)
95
+ if (nr && nr > 0 && nr < 13) month.value = nr
96
+ else month.value = undefined
97
+ }
98
+
99
+ const setDay: InstanceType<typeof QInput>['$props']['onUpdate:modelValue'] = (
100
+ val
101
+ ) => {
102
+ const nr = Number(val)
103
+ if (nr && nr > 0 && nr < 32) day.value = nr
104
+ else day.value = undefined
105
+ }
106
+
107
+ const setInternalDate = (
108
+ dateString?: string | null,
109
+ separator: '-' | '/' = '-'
110
+ ) => {
111
+ if (dateString) {
112
+ const [yearPart, monthPart, dayPart] = dateString.split(separator)
113
+ if (yearPart && monthPart && dayPart) {
114
+ year.value = Number(yearPart)
115
+ month.value = Number(monthPart)
116
+ day.value = Number(dayPart)
117
+ }
118
+ }
119
+ }
120
+
121
+ const setDate: InstanceType<typeof QDate>['$props']['onUpdate:modelValue'] = (
122
+ value
123
+ ) => {
124
+ setInternalDate(value, '/')
125
+ }
126
+
127
+ watch([year, month, day], () => {
128
+ const date = `${year.value}-${String(month.value).padStart(2, '0')}-${String(day.value).padStart(2, '0')}`
129
+ if (Date.parse(date)) {
130
+ emit('update:modelValue', date)
131
+ } else {
132
+ emit('update:modelValue', '')
133
+ }
65
134
  })
66
135
 
67
- const { modelValue } = toRefs(props)
136
+ const formattedDate = computed(() => {
137
+ if (modelValue.value)
138
+ return new Date(Date.parse(modelValue.value)).toLocaleDateString(
139
+ locale.value,
140
+ {
141
+ weekday: 'long',
142
+ year: 'numeric',
143
+ month: 'short',
144
+ day: 'numeric'
145
+ }
146
+ )
147
+ return ''
148
+ })
68
149
 
69
- const update = (val: string | number | null) => {
70
- if (typeof val === 'string' || val === null) emit('update:modelValue', val)
150
+ watch(modelValue, (newVal) => {
151
+ if (newVal) setInternalDate(newVal)
152
+ else if (newVal === null) {
153
+ year.value = undefined
154
+ month.value = undefined
155
+ day.value = undefined
156
+ }
157
+ })
158
+ setInternalDate(modelValue.value)
159
+
160
+ const goToNextElement = (e: KeyboardEvent) => {
161
+ if (['Minus', 'Slash'].includes(e.code)) {
162
+ e.preventDefault()
163
+ const next = (e.currentTarget as HTMLElement).parentElement?.parentElement
164
+ ?.parentElement?.parentElement?.nextElementSibling
165
+ if (next) {
166
+ ;(next as HTMLElement).focus()
167
+ }
168
+ }
71
169
  }
72
- watch(
73
- () => modelValue?.value,
74
- (newVal) => {
75
- if (newVal === '') emit('update:modelValue', null)
170
+
171
+ const dateProps = computed<Record<string, QInputProps>>(() => ({
172
+ YYYY: {
173
+ modelValue: year.value,
174
+ placeholder: lang.value.datePicker.YYYY,
175
+ style: 'max-width: 6ch',
176
+ suffix: format.value === 'YYYY-MM-DD' ? '-' : undefined,
177
+ class: format.value !== 'YYYY-MM-DD' ? 'q-mb-none q-ml-xs' : undefined,
178
+ 'onUpdate:modelValue': setYear,
179
+ onKeydown: goToNextElement
180
+ },
181
+ MM: {
182
+ modelValue: month.value ? String(month.value).padStart(2, '0') : '',
183
+ placeholder: lang.value.datePicker.MM,
184
+ style: 'max-width: 4ch',
185
+ suffix: '-',
186
+ class: 'q-ml-xs',
187
+ 'onUpdate:modelValue': setMonth,
188
+ onKeydown: goToNextElement
189
+ },
190
+ DD: {
191
+ modelValue: day.value ? String(day.value).padStart(2, '0') : '',
192
+ placeholder: lang.value.datePicker.DD,
193
+ style: 'max-width: 4ch',
194
+ suffix: format.value === 'DD-MM-YYYY' ? '-' : undefined,
195
+ class: format.value === 'YYYY-MM-DD' ? 'q-ml-xs' : undefined,
196
+ 'onUpdate:modelValue': setDay,
197
+ onKeydown: goToNextElement
76
198
  }
77
- )
199
+ }))
78
200
 
79
201
  const validations = ref<((val: string) => boolean | string)[]>([
80
202
  (v) => {
81
203
  if (v !== null)
82
- return /^\d{4}\/(0?[1-9]|1[012])\/(0?[1-9]|[12][0-9]|3[01])$/.test(v)
204
+ // return /^\d{4}\/(0?[1-9]|1[012])\/(0?[1-9]|[12][0-9]|3[01])$/.test(v)
205
+ return /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/.test(v)
83
206
  return true
84
207
  }
85
208
  ])
@@ -89,3 +212,16 @@ if (props.required)
89
212
  (val: string) => !!val || lang.value.validations.fieldRequired
90
213
  )
91
214
  </script>
215
+
216
+ <style>
217
+ .q-field--auto-height .q-field__control,
218
+ .q-field--auto-height .q-field__native {
219
+ min-height: 1em;
220
+ }
221
+ .q-field--borderless .q-field__bottom,
222
+ .q-field--borderless.q-field--dense .q-field__control,
223
+ .q-field--standard .q-field__bottom,
224
+ .q-field--standard.q-field--dense .q-field__control {
225
+ padding-top: 0;
226
+ }
227
+ </style>
@@ -13,6 +13,8 @@
13
13
  </template>
14
14
 
15
15
  <script lang="ts">
16
+ import { QInput, QEditor } from 'quasar'
17
+
16
18
  export default {
17
19
  name: 'EmailInput'
18
20
  }
@@ -36,6 +36,9 @@ const lang: Language = {
36
36
  },
37
37
  datePicker: {
38
38
  placeholder: 'YYYY/MM/DD',
39
+ YYYY: 'YYYY',
40
+ MM: 'MM',
41
+ DD: 'DD',
39
42
  validations: {
40
43
  unavailableRange: 'The selected period contains unavailable dates.'
41
44
  }
@@ -34,6 +34,9 @@ export interface Language {
34
34
  }
35
35
  datePicker: {
36
36
  placeholder: string
37
+ YYYY: string
38
+ MM: string
39
+ DD: string
37
40
  validations: {
38
41
  unavailableRange: string
39
42
  }
@@ -36,6 +36,9 @@ const lang: Language = {
36
36
  },
37
37
  datePicker: {
38
38
  placeholder: 'JJJJ/MM/DD',
39
+ YYYY: 'JJJJ',
40
+ MM: 'MM',
41
+ DD: 'DD',
39
42
  validations: {
40
43
  unavailableRange: 'De geselecteerde periode bevat ongeschikbare datums.'
41
44
  }
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "rootDir": "src/"
3
+ "rootDir": "src/",
4
+ "skipLibCheck": true
4
5
  },
5
6
  "extends": "./tsconfig.node.json",
6
7
  "include": ["./src/vite-plugin.ts", "./src/virtualModules.ts"]
package/tsconfig.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "target": "esnext",
4
4
  "useDefineForClassFields": true,
5
5
  "module": "esnext",
6
- "moduleResolution": "node",
6
+ "moduleResolution": "bundler",
7
7
  "strict": true,
8
8
  "jsx": "preserve",
9
9
  "sourceMap": true,
@@ -2,7 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "composite": true,
4
4
  "module": "esnext",
5
- "moduleResolution": "node",
5
+ "moduleResolution": "Bundler",
6
6
  "outDir": "./dist",
7
7
  "declaration": true
8
8
  },
@@ -5,7 +5,7 @@
5
5
  "lib": ["esnext", "DOM"],
6
6
  "strict": true,
7
7
  "skipLibCheck": true,
8
- "moduleResolution": "node",
8
+ "moduleResolution": "Bundler",
9
9
  "declaration": true,
10
10
  "outDir": "dist",
11
11
  "emitDeclarationOnly": true,
File without changes
File without changes
File without changes