@fy-/fws-vue 2.1.6 → 2.1.8
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.
- package/components/fws/CmsArticleBoxed.vue +23 -20
- package/components/fws/CmsArticleSingle.vue +74 -68
- package/components/fws/DataTable.vue +132 -125
- package/components/fws/FilterData.vue +99 -101
- package/components/fws/UserData.vue +33 -32
- package/components/fws/UserFlow.vue +163 -155
- package/components/fws/UserOAuth2.vue +73 -72
- package/components/fws/UserProfile.vue +98 -101
- package/components/fws/UserProfileStrict.vue +65 -64
- package/components/ssr/ClientOnly.ts +7 -7
- package/components/ui/DefaultBreadcrumb.vue +13 -13
- package/components/ui/DefaultConfirm.vue +35 -34
- package/components/ui/DefaultDateSelection.vue +19 -17
- package/components/ui/DefaultDropdown.vue +25 -25
- package/components/ui/DefaultDropdownLink.vue +15 -14
- package/components/ui/DefaultGallery.vue +179 -168
- package/components/ui/DefaultInput.vue +121 -126
- package/components/ui/DefaultLoader.vue +17 -17
- package/components/ui/DefaultModal.vue +35 -33
- package/components/ui/DefaultNotif.vue +50 -52
- package/components/ui/DefaultPaging.vue +92 -95
- package/components/ui/DefaultSidebar.vue +29 -25
- package/components/ui/DefaultTagInput.vue +121 -119
- package/components/ui/transitions/CollapseTransition.vue +1 -1
- package/components/ui/transitions/ExpandTransition.vue +1 -1
- package/components/ui/transitions/FadeTransition.vue +1 -1
- package/components/ui/transitions/ScaleTransition.vue +1 -1
- package/components/ui/transitions/SlideTransition.vue +3 -3
- package/composables/event-bus.ts +10 -8
- package/composables/rest.ts +59 -56
- package/composables/seo.ts +111 -95
- package/composables/ssr.ts +64 -62
- package/composables/templating.ts +57 -57
- package/composables/translations.ts +13 -13
- package/env.d.ts +6 -4
- package/index.ts +101 -98
- package/package.json +7 -7
- package/stores/serverRouter.ts +25 -25
- package/stores/user.ts +79 -72
- package/types.d.ts +65 -65
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import { useTranslation } from
|
|
5
|
-
import DefaultTagInput from
|
|
6
|
-
//import VueTailwindDatepicker from "vue-tailwind-datepicker";
|
|
2
|
+
import type { ErrorObject } from '@vuelidate/core'
|
|
3
|
+
import { computed, ref, toRef } from 'vue'
|
|
4
|
+
import { useTranslation } from '../../composables/translations'
|
|
5
|
+
import DefaultTagInput from './DefaultTagInput.vue'
|
|
6
|
+
// import VueTailwindDatepicker from "vue-tailwind-datepicker";
|
|
7
7
|
|
|
8
|
-
type modelValueType = string | number | string[] | number[] | undefined
|
|
8
|
+
type modelValueType = string | number | string[] | number[] | undefined
|
|
9
9
|
|
|
10
|
-
type checkboxValueType = any[] | Set<any> | undefined | boolean
|
|
10
|
+
type checkboxValueType = any[] | Set<any> | undefined | boolean
|
|
11
11
|
const props = withDefaults(
|
|
12
12
|
defineProps<{
|
|
13
|
-
id: string
|
|
14
|
-
showLabel?: boolean
|
|
15
|
-
label?: string
|
|
16
|
-
type?: string
|
|
17
|
-
placeholder?: string
|
|
18
|
-
autocomplete?: string
|
|
19
|
-
mask?: string
|
|
20
|
-
checkboxTrueValue?: string | boolean
|
|
21
|
-
checkboxFalseValue?: string | boolean
|
|
22
|
-
req?: boolean
|
|
23
|
-
linkIcon?: string
|
|
24
|
-
modelValue?: modelValueType
|
|
25
|
-
checkboxValue?: checkboxValueType
|
|
26
|
-
options?: string[][]
|
|
27
|
-
dpOptions?: Record<string, any
|
|
28
|
-
help?: string
|
|
29
|
-
error?: string
|
|
30
|
-
color?: string
|
|
31
|
-
errorVuelidate?: ErrorObject[]
|
|
32
|
-
disabled?: boolean
|
|
33
|
-
maxLengthPerTag?: number
|
|
34
|
-
disableDatesUnder18?: boolean
|
|
35
|
-
copyButton?: boolean
|
|
36
|
-
maxRange?: number
|
|
37
|
-
minRange?: number
|
|
13
|
+
id: string
|
|
14
|
+
showLabel?: boolean
|
|
15
|
+
label?: string
|
|
16
|
+
type?: string
|
|
17
|
+
placeholder?: string
|
|
18
|
+
autocomplete?: string
|
|
19
|
+
mask?: string
|
|
20
|
+
checkboxTrueValue?: string | boolean
|
|
21
|
+
checkboxFalseValue?: string | boolean
|
|
22
|
+
req?: boolean
|
|
23
|
+
linkIcon?: string
|
|
24
|
+
modelValue?: modelValueType
|
|
25
|
+
checkboxValue?: checkboxValueType
|
|
26
|
+
options?: string[][]
|
|
27
|
+
dpOptions?: Record<string, any>
|
|
28
|
+
help?: string
|
|
29
|
+
error?: string
|
|
30
|
+
color?: string
|
|
31
|
+
errorVuelidate?: ErrorObject[]
|
|
32
|
+
disabled?: boolean
|
|
33
|
+
maxLengthPerTag?: number
|
|
34
|
+
disableDatesUnder18?: boolean
|
|
35
|
+
copyButton?: boolean
|
|
36
|
+
maxRange?: number
|
|
37
|
+
minRange?: number
|
|
38
38
|
}>(),
|
|
39
39
|
{
|
|
40
40
|
showLabel: true,
|
|
41
|
-
type:
|
|
41
|
+
type: 'text',
|
|
42
42
|
req: false,
|
|
43
43
|
options: () => [],
|
|
44
44
|
checkboxTrueValue: true,
|
|
@@ -51,71 +51,71 @@ const props = withDefaults(
|
|
|
51
51
|
copyButton: false,
|
|
52
52
|
dpOptions: () => ({}),
|
|
53
53
|
},
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
if (!props.disableDatesUnder18) return false
|
|
57
|
-
const today = new Date()
|
|
54
|
+
)
|
|
55
|
+
/* function disableDatesAdult(date: Date) {
|
|
56
|
+
if (!props.disableDatesUnder18) return false
|
|
57
|
+
const today = new Date()
|
|
58
58
|
const date18YearsAgo = new Date(
|
|
59
59
|
today.getFullYear() - 18,
|
|
60
60
|
today.getMonth(),
|
|
61
61
|
today.getDate(),
|
|
62
|
-
)
|
|
62
|
+
)
|
|
63
63
|
|
|
64
|
-
return date >= date18YearsAgo
|
|
65
|
-
}
|
|
64
|
+
return date >= date18YearsAgo
|
|
65
|
+
} */
|
|
66
66
|
|
|
67
|
-
const translate = useTranslation()
|
|
68
|
-
const inputRef = ref<HTMLInputElement>()
|
|
69
|
-
const errorProps = toRef(props,
|
|
70
|
-
const errorVuelidateProps = toRef(props,
|
|
67
|
+
const translate = useTranslation()
|
|
68
|
+
const inputRef = ref<HTMLInputElement>()
|
|
69
|
+
const errorProps = toRef(props, 'error')
|
|
70
|
+
const errorVuelidateProps = toRef(props, 'errorVuelidate')
|
|
71
71
|
const checkErrors = computed(() => {
|
|
72
|
-
if (errorProps.value) return errorProps.value
|
|
72
|
+
if (errorProps.value) return errorProps.value
|
|
73
73
|
if (errorVuelidateProps.value && errorVuelidateProps.value.length > 0) {
|
|
74
|
-
const err = `vuelidate_validator_${errorVuelidateProps.value[0].$validator.toString()}
|
|
75
|
-
return translate(err)
|
|
74
|
+
const err = `vuelidate_validator_${errorVuelidateProps.value[0].$validator.toString()}`
|
|
75
|
+
return translate(err)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
return null
|
|
79
|
-
})
|
|
78
|
+
return null
|
|
79
|
+
})
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
if (inputRef.value) inputRef.value.focus()
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (inputRef.value) inputRef.value.blur()
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (inputRef.value) return inputRef.value
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
function focus() {
|
|
82
|
+
if (inputRef.value) inputRef.value.focus()
|
|
83
|
+
}
|
|
84
|
+
function blur() {
|
|
85
|
+
if (inputRef.value) inputRef.value.blur()
|
|
86
|
+
}
|
|
87
|
+
function getInputRef() {
|
|
88
|
+
if (inputRef.value) return inputRef.value
|
|
89
|
+
}
|
|
90
|
+
const emit = defineEmits([
|
|
91
|
+
'update:modelValue',
|
|
92
|
+
'update:checkboxValue',
|
|
93
|
+
'focus',
|
|
94
|
+
'blur',
|
|
95
|
+
])
|
|
96
|
+
function handleFocus() {
|
|
97
|
+
emit('focus', props.id)
|
|
98
|
+
}
|
|
94
99
|
|
|
95
|
-
|
|
96
|
-
emit(
|
|
97
|
-
}
|
|
100
|
+
function handleBlur() {
|
|
101
|
+
emit('blur', props.id)
|
|
102
|
+
}
|
|
98
103
|
|
|
99
|
-
const emit = defineEmits([
|
|
100
|
-
"update:modelValue",
|
|
101
|
-
"update:checkboxValue",
|
|
102
|
-
"focus",
|
|
103
|
-
"blur",
|
|
104
|
-
]);
|
|
105
104
|
const model = computed({
|
|
106
105
|
get: () => props.modelValue,
|
|
107
106
|
set: (items) => {
|
|
108
|
-
emit(
|
|
107
|
+
emit('update:modelValue', items)
|
|
109
108
|
},
|
|
110
|
-
})
|
|
109
|
+
})
|
|
111
110
|
const modelCheckbox = computed({
|
|
112
111
|
get: () => props.checkboxValue,
|
|
113
112
|
set: (items) => {
|
|
114
|
-
emit(
|
|
113
|
+
emit('update:checkboxValue', items)
|
|
115
114
|
},
|
|
116
|
-
})
|
|
117
|
-
defineExpose({ focus, blur, getInputRef })
|
|
115
|
+
})
|
|
116
|
+
defineExpose({ focus, blur, getInputRef })
|
|
118
117
|
</script>
|
|
118
|
+
|
|
119
119
|
<template>
|
|
120
120
|
<div>
|
|
121
121
|
<template
|
|
@@ -160,25 +160,25 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
160
160
|
class="relative"
|
|
161
161
|
>
|
|
162
162
|
<label
|
|
163
|
-
:for="id"
|
|
164
163
|
v-if="label"
|
|
164
|
+
:for="id"
|
|
165
165
|
class="block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white"
|
|
166
|
-
|
|
166
|
+
>{{ label }}
|
|
167
167
|
<template v-if="type === 'range'"> ({{ model }}) </template>
|
|
168
168
|
</label>
|
|
169
169
|
<input
|
|
170
|
+
:id="id"
|
|
170
171
|
ref="inputRef"
|
|
172
|
+
v-model="model"
|
|
171
173
|
:type="type === 'datepicker' ? 'date' : type"
|
|
172
|
-
:id="id"
|
|
173
174
|
:name="id"
|
|
174
175
|
:class="{
|
|
175
|
-
error: checkErrors,
|
|
176
|
+
'error': checkErrors,
|
|
176
177
|
'bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm rounded-lg focus:ring-fv-primary-500 focus:border-fv-primary-500 block w-full p-2.5 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500':
|
|
177
178
|
type !== 'range',
|
|
178
179
|
'w-full h-2 bg-fv-neutral-200 rounded-lg appearance-none cursor-pointer dark:bg-fv-neutral-700':
|
|
179
180
|
type === 'range',
|
|
180
181
|
}"
|
|
181
|
-
v-model="model"
|
|
182
182
|
:autocomplete="autocomplete"
|
|
183
183
|
:min="type === 'range' ? minRange : undefined"
|
|
184
184
|
:max="type === 'range' ? maxRange : undefined"
|
|
@@ -188,16 +188,15 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
188
188
|
:required="req"
|
|
189
189
|
@focus="handleFocus"
|
|
190
190
|
@blur="handleBlur"
|
|
191
|
-
|
|
191
|
+
>
|
|
192
192
|
<template v-if="type === 'range'">
|
|
193
193
|
<span
|
|
194
194
|
class="text-sm text-gray-500 dark:text-gray-400 absolute start-0 -bottom-6"
|
|
195
|
-
|
|
195
|
+
>Min ({{ minRange }})
|
|
196
196
|
</span>
|
|
197
197
|
<span
|
|
198
198
|
class="text-sm text-gray-500 dark:text-gray-400 absolute start-1/3 -translate-x-1/2 rtl:translate-x-1/2 -bottom-6"
|
|
199
|
-
|
|
200
|
-
>
|
|
199
|
+
>{{ ((maxRange - minRange) / 3 + minRange).toFixed(0) }}</span>
|
|
201
200
|
<span
|
|
202
201
|
class="text-sm text-gray-500 dark:text-gray-400 absolute start-2/3 -translate-x-1/2 rtl:translate-x-1/2 -bottom-6"
|
|
203
202
|
>
|
|
@@ -205,8 +204,7 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
205
204
|
</span>
|
|
206
205
|
<span
|
|
207
206
|
class="text-sm text-gray-500 dark:text-gray-400 absolute end-0 -bottom-6"
|
|
208
|
-
|
|
209
|
-
>
|
|
207
|
+
>Max ({{ maxRange }})</span>
|
|
210
208
|
</template>
|
|
211
209
|
</div>
|
|
212
210
|
<!--
|
|
@@ -232,50 +230,49 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
232
230
|
</div>
|
|
233
231
|
-->
|
|
234
232
|
|
|
235
|
-
<div v-if="type
|
|
233
|
+
<div v-if="type === 'chips' || type === 'tags'">
|
|
236
234
|
<label
|
|
237
|
-
:for="id"
|
|
238
235
|
v-if="label || placeholder"
|
|
236
|
+
:for="id"
|
|
239
237
|
class="block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white"
|
|
240
|
-
|
|
238
|
+
>{{ label ? label : placeholder }}
|
|
241
239
|
</label>
|
|
242
240
|
<!-- @vue-skip -->
|
|
243
241
|
<DefaultTagInput
|
|
244
|
-
v-model="model"
|
|
245
242
|
:id="id"
|
|
243
|
+
v-model="model"
|
|
246
244
|
:disabled="disabled"
|
|
247
245
|
:color="color"
|
|
248
246
|
:error="checkErrors"
|
|
249
|
-
:
|
|
247
|
+
:copy-button="copyButton"
|
|
250
248
|
:help="help"
|
|
251
249
|
:max-lenght-per-tag="maxLengthPerTag"
|
|
252
250
|
/>
|
|
253
251
|
</div>
|
|
254
|
-
<div
|
|
252
|
+
<div v-else-if="type === 'textarea-grow'" class="group relative">
|
|
255
253
|
<label
|
|
256
254
|
v-if="label"
|
|
257
255
|
:for="id"
|
|
258
256
|
class="block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white"
|
|
259
|
-
|
|
260
|
-
>
|
|
257
|
+
>{{ label }}</label>
|
|
261
258
|
<div class="grow-wrap">
|
|
262
259
|
<!-- @vue-skip -->
|
|
263
260
|
<textarea
|
|
264
261
|
:id="id"
|
|
265
|
-
:name="id"
|
|
266
262
|
ref="inputRef"
|
|
263
|
+
v-model="model"
|
|
264
|
+
:name="id"
|
|
267
265
|
:class="{
|
|
268
266
|
error: checkErrors,
|
|
269
267
|
}"
|
|
270
|
-
v-model="model"
|
|
271
268
|
:placeholder="placeholder"
|
|
272
269
|
:disabled="disabled"
|
|
273
270
|
:aria-describedby="help ? `${id}-help` : id"
|
|
274
271
|
:required="req"
|
|
272
|
+
class="block p-2.5 w-full text-sm text-fv-neutral-900 bg-fv-neutral-50 rounded-lg border border-fv-neutral-300 focus:ring-fv-primary-500 focus:border-fv-primary-500 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500"
|
|
275
273
|
@focus="handleFocus"
|
|
276
274
|
@blur="handleBlur"
|
|
277
|
-
|
|
278
|
-
></textarea>
|
|
275
|
+
/>
|
|
279
276
|
</div>
|
|
280
277
|
<div
|
|
281
278
|
v-if="dpOptions.counterMax && model"
|
|
@@ -289,30 +286,29 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
289
286
|
{{ dpOptions.counterMax }} characters
|
|
290
287
|
</div>
|
|
291
288
|
</div>
|
|
292
|
-
<div
|
|
289
|
+
<div v-else-if="type === 'textarea'" class="group relative">
|
|
293
290
|
<label
|
|
294
291
|
v-if="label"
|
|
295
292
|
:for="id"
|
|
296
293
|
class="block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white"
|
|
297
|
-
|
|
298
|
-
>
|
|
294
|
+
>{{ label }}</label>
|
|
299
295
|
<!-- @vue-skip -->
|
|
300
296
|
<textarea
|
|
301
297
|
:id="id"
|
|
302
|
-
:name="id"
|
|
303
298
|
ref="inputRef"
|
|
299
|
+
v-model="model"
|
|
300
|
+
:name="id"
|
|
304
301
|
:class="{
|
|
305
302
|
error: checkErrors,
|
|
306
303
|
}"
|
|
307
|
-
v-model="model"
|
|
308
304
|
:placeholder="placeholder"
|
|
309
305
|
:disabled="disabled"
|
|
310
306
|
:aria-describedby="help ? `${id}-help` : id"
|
|
311
307
|
:required="req"
|
|
308
|
+
class="block p-2.5 w-full text-sm text-fv-neutral-900 bg-fv-neutral-50 rounded-lg border border-fv-neutral-300 focus:ring-fv-primary-500 focus:border-fv-primary-500 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500"
|
|
312
309
|
@focus="handleFocus"
|
|
313
310
|
@blur="handleBlur"
|
|
314
|
-
|
|
315
|
-
></textarea>
|
|
311
|
+
/>
|
|
316
312
|
<div
|
|
317
313
|
v-if="dpOptions.counterMax && model"
|
|
318
314
|
class="text-sm text-fv-neutral-500 dark:text-fv-neutral-400"
|
|
@@ -325,32 +321,31 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
325
321
|
{{ dpOptions.counterMax }} characters
|
|
326
322
|
</div>
|
|
327
323
|
</div>
|
|
328
|
-
<div
|
|
324
|
+
<div v-else-if="type === 'select'" class="relative">
|
|
329
325
|
<label
|
|
330
|
-
:for="id"
|
|
331
326
|
v-if="label"
|
|
327
|
+
:for="id"
|
|
332
328
|
class="block mb-2 text-sm font-medium text-fv-neutral-900 dark:text-white"
|
|
333
|
-
|
|
334
|
-
>
|
|
329
|
+
>{{ label }}</label>
|
|
335
330
|
<select
|
|
336
331
|
:id="id"
|
|
337
|
-
:name="id"
|
|
338
332
|
ref="inputRef"
|
|
339
333
|
v-model="model"
|
|
334
|
+
:name="id"
|
|
340
335
|
:disabled="disabled"
|
|
341
336
|
:aria-describedby="help ? `${id}-help` : id"
|
|
342
337
|
:required="req"
|
|
343
|
-
@focus="handleFocus"
|
|
344
|
-
@blur="handleBlur"
|
|
345
338
|
:class="{
|
|
346
339
|
error: checkErrors,
|
|
347
340
|
}"
|
|
348
341
|
class="bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm rounded-lg focus:ring-fv-primary-500 focus:border-fv-primary-500 block w-full p-2.5 dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-400 dark:text-white dark:focus:ring-fv-primary-500 dark:focus:border-fv-primary-500"
|
|
342
|
+
@focus="handleFocus"
|
|
343
|
+
@blur="handleBlur"
|
|
349
344
|
>
|
|
350
345
|
<option
|
|
351
346
|
v-for="opt in options"
|
|
352
|
-
:value="opt[0]"
|
|
353
347
|
:key="opt[0].toString()"
|
|
348
|
+
:value="opt[0]"
|
|
354
349
|
>
|
|
355
350
|
{{ opt[1] }}
|
|
356
351
|
</option>
|
|
@@ -366,18 +361,18 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
366
361
|
}"
|
|
367
362
|
>
|
|
368
363
|
<input
|
|
369
|
-
type="checkbox"
|
|
370
364
|
v-model="modelCheckbox"
|
|
365
|
+
type="checkbox"
|
|
371
366
|
:true-value="checkboxTrueValue"
|
|
372
367
|
:false-value="checkboxFalseValue"
|
|
373
368
|
:disabled="disabled"
|
|
374
369
|
class="sr-only peer"
|
|
375
370
|
@focus="handleFocus"
|
|
376
371
|
@blur="handleBlur"
|
|
377
|
-
|
|
372
|
+
>
|
|
378
373
|
<div
|
|
379
374
|
class="relative flex-0 flex-shrink-0 w-11 h-6 bg-fv-neutral-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-fv-primary-300 dark:peer-focus:ring-fv-primary-800 rounded-full peer dark:bg-fv-neutral-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-fv-neutral-300 after:border after:rounded-full after:w-5 after:h-5 after:transition-all dark:border-fv-neutral-600 peer-checked:bg-fv-primary-600"
|
|
380
|
-
|
|
375
|
+
/>
|
|
381
376
|
<span
|
|
382
377
|
class="ms-3 text-sm font-medium text-fv-neutral-900 dark:text-fv-neutral-300"
|
|
383
378
|
>
|
|
@@ -390,34 +385,33 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
390
385
|
</span>
|
|
391
386
|
</label>
|
|
392
387
|
</template>
|
|
393
|
-
<template v-else-if="type
|
|
388
|
+
<template v-else-if="type === 'checkbox' || type === 'radio'">
|
|
394
389
|
<div class="flex mb-4">
|
|
395
390
|
<div class="flex items-center h-5">
|
|
396
391
|
<input
|
|
397
392
|
:id="id"
|
|
393
|
+
v-model="modelCheckbox"
|
|
398
394
|
:class="{
|
|
399
395
|
error: checkErrors,
|
|
400
396
|
}"
|
|
401
397
|
:aria-describedby="help ? `${id}-help` : id"
|
|
402
398
|
:type="type"
|
|
403
|
-
@focus="handleFocus"
|
|
404
|
-
@blur="handleBlur"
|
|
405
399
|
:true-value="checkboxTrueValue"
|
|
406
400
|
:false-value="checkboxFalseValue"
|
|
407
|
-
v-model="modelCheckbox"
|
|
408
401
|
:disabled="disabled"
|
|
409
402
|
class="w-4 h-4 text-fv-primary-600 bg-fv-neutral-100 border-fv-neutral-300 rounded focus:ring-fv-primary-500 dark:focus:ring-fv-primary-600 dark:ring-offset-fv-neutral-800 dark:focus:ring-offset-fv-neutral-800 focus:ring-2 dark:bg-fv-neutral-700 dark:border-fv-neutral-600"
|
|
410
|
-
|
|
403
|
+
@focus="handleFocus"
|
|
404
|
+
@blur="handleBlur"
|
|
405
|
+
>
|
|
411
406
|
</div>
|
|
412
407
|
<div class="ms-2 text-sm">
|
|
413
408
|
<label
|
|
414
409
|
:for="id"
|
|
415
410
|
class="font-medium text-fv-neutral-900 dark:text-fv-neutral-300"
|
|
416
|
-
|
|
417
|
-
>
|
|
411
|
+
>{{ label }}</label>
|
|
418
412
|
<p
|
|
419
|
-
:id="`${id}-help`"
|
|
420
413
|
v-if="help"
|
|
414
|
+
:id="`${id}-help`"
|
|
421
415
|
class="text-xs font-normal text-fv-neutral-500 dark:text-fv-neutral-400"
|
|
422
416
|
>
|
|
423
417
|
{{ help }}
|
|
@@ -430,14 +424,15 @@ defineExpose({ focus, blur, getInputRef });
|
|
|
430
424
|
</p>
|
|
431
425
|
|
|
432
426
|
<p
|
|
427
|
+
v-if="help && !['checkbox', 'radio', 'toggle'].includes(type)"
|
|
433
428
|
:id="`${id}-help`"
|
|
434
429
|
class="mt-1 text-sm text-fv-neutral-500 dark:text-fv-neutral-400"
|
|
435
|
-
v-if="help && !['checkbox', 'radio', 'toggle'].includes(type)"
|
|
436
430
|
>
|
|
437
431
|
{{ help }}
|
|
438
432
|
</p>
|
|
439
433
|
</div>
|
|
440
434
|
</template>
|
|
435
|
+
|
|
441
436
|
<style scoped>
|
|
442
437
|
input,
|
|
443
438
|
textarea,
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { onMounted, onUnmounted, ref } from
|
|
3
|
-
import { useEventBus } from
|
|
2
|
+
import { onMounted, onUnmounted, ref } from 'vue'
|
|
3
|
+
import { useEventBus } from '../../composables/event-bus'
|
|
4
4
|
|
|
5
5
|
const props = withDefaults(
|
|
6
6
|
defineProps<{
|
|
7
|
-
image: string
|
|
8
|
-
force?: boolean
|
|
9
|
-
id?: string
|
|
7
|
+
image: string
|
|
8
|
+
force?: boolean
|
|
9
|
+
id?: string
|
|
10
10
|
}>(),
|
|
11
11
|
{
|
|
12
12
|
force: false,
|
|
13
|
-
id:
|
|
13
|
+
id: '',
|
|
14
14
|
},
|
|
15
|
-
)
|
|
16
|
-
const eventBus = useEventBus()
|
|
17
|
-
const loading = ref<boolean>(false)
|
|
15
|
+
)
|
|
16
|
+
const eventBus = useEventBus()
|
|
17
|
+
const loading = ref<boolean>(false)
|
|
18
18
|
function setLoading(value: boolean) {
|
|
19
|
-
loading.value = value
|
|
19
|
+
loading.value = value
|
|
20
20
|
}
|
|
21
21
|
onMounted(() => {
|
|
22
|
-
if (props.id) eventBus.on(`${props.id}-loading`, setLoading)
|
|
23
|
-
else eventBus.on(
|
|
24
|
-
})
|
|
22
|
+
if (props.id) eventBus.on(`${props.id}-loading`, setLoading)
|
|
23
|
+
else eventBus.on('loading', setLoading)
|
|
24
|
+
})
|
|
25
25
|
onUnmounted(() => {
|
|
26
|
-
if (props.id) eventBus.off(`${props.id}-loading`, setLoading)
|
|
27
|
-
else eventBus.off(
|
|
28
|
-
})
|
|
26
|
+
if (props.id) eventBus.off(`${props.id}-loading`, setLoading)
|
|
27
|
+
else eventBus.off('loading', setLoading)
|
|
28
|
+
})
|
|
29
29
|
</script>
|
|
30
30
|
|
|
31
31
|
<template>
|
|
@@ -40,7 +40,7 @@ onUnmounted(() => {
|
|
|
40
40
|
:src="image"
|
|
41
41
|
:alt="$t('global_loading')"
|
|
42
42
|
class="w-full h-full relative"
|
|
43
|
-
|
|
43
|
+
>
|
|
44
44
|
</div>
|
|
45
45
|
</div>
|
|
46
46
|
</template>
|
|
@@ -2,47 +2,49 @@
|
|
|
2
2
|
import {
|
|
3
3
|
Dialog,
|
|
4
4
|
DialogPanel,
|
|
5
|
-
DialogTitle,
|
|
6
5
|
TransitionRoot,
|
|
7
|
-
} from
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { useEventBus } from
|
|
6
|
+
} from '@headlessui/vue'
|
|
7
|
+
import { XCircleIcon } from '@heroicons/vue/24/solid'
|
|
8
|
+
import { h, onMounted, onUnmounted, ref } from 'vue'
|
|
9
|
+
import { useEventBus } from '../../composables/event-bus'
|
|
10
|
+
|
|
11
11
|
const props = withDefaults(
|
|
12
12
|
defineProps<{
|
|
13
|
-
id: string
|
|
14
|
-
title?: string
|
|
15
|
-
onOpen?: Function
|
|
16
|
-
onClose?: Function
|
|
17
|
-
closeIcon?:
|
|
18
|
-
mSize?: string
|
|
19
|
-
ofy?: string
|
|
13
|
+
id: string
|
|
14
|
+
title?: string
|
|
15
|
+
onOpen?: Function
|
|
16
|
+
onClose?: Function
|
|
17
|
+
closeIcon?: object
|
|
18
|
+
mSize?: string
|
|
19
|
+
ofy?: string
|
|
20
20
|
}>(),
|
|
21
21
|
{
|
|
22
22
|
closeIcon: () => h(XCircleIcon),
|
|
23
|
-
mSize:
|
|
24
|
-
ofy:
|
|
23
|
+
mSize: 'w-full',
|
|
24
|
+
ofy: 'overflow-y-auto',
|
|
25
25
|
},
|
|
26
|
-
)
|
|
26
|
+
)
|
|
27
27
|
|
|
28
|
-
const eventBus = useEventBus()
|
|
28
|
+
const eventBus = useEventBus()
|
|
29
29
|
|
|
30
|
-
const isOpen = ref<boolean>(false)
|
|
31
|
-
|
|
30
|
+
const isOpen = ref<boolean>(false)
|
|
31
|
+
function setModal(value: boolean) {
|
|
32
32
|
if (value === true) {
|
|
33
|
-
if (props.onOpen) props.onOpen()
|
|
34
|
-
}
|
|
35
|
-
|
|
33
|
+
if (props.onOpen) props.onOpen()
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
if (props.onClose) props.onClose()
|
|
36
37
|
}
|
|
37
|
-
isOpen.value = value
|
|
38
|
-
}
|
|
38
|
+
isOpen.value = value
|
|
39
|
+
}
|
|
39
40
|
onMounted(() => {
|
|
40
|
-
eventBus.on(`${props.id}Modal`, setModal)
|
|
41
|
-
})
|
|
41
|
+
eventBus.on(`${props.id}Modal`, setModal)
|
|
42
|
+
})
|
|
42
43
|
onUnmounted(() => {
|
|
43
|
-
eventBus.off(`${props.id}Modal`, setModal)
|
|
44
|
-
})
|
|
44
|
+
eventBus.off(`${props.id}Modal`, setModal)
|
|
45
|
+
})
|
|
45
46
|
</script>
|
|
47
|
+
|
|
46
48
|
<template>
|
|
47
49
|
<TransitionRoot
|
|
48
50
|
:show="isOpen"
|
|
@@ -56,9 +58,9 @@ onUnmounted(() => {
|
|
|
56
58
|
>
|
|
57
59
|
<Dialog
|
|
58
60
|
:open="isOpen"
|
|
59
|
-
@close="setModal"
|
|
60
61
|
class="fixed inset-0 overflow-y-auto"
|
|
61
62
|
style="z-index: 40"
|
|
63
|
+
@close="setModal"
|
|
62
64
|
>
|
|
63
65
|
<DialogPanel
|
|
64
66
|
class="flex absolute backdrop-blur-[8px] inset-0 flex-col items-center justify-center min-h-screen text-fv-neutral-800 dark:text-fv-neutral-300 bg-fv-neutral-900/[.20] dark:bg-fv-neutral-50/[.20]"
|
|
@@ -69,24 +71,24 @@ onUnmounted(() => {
|
|
|
69
71
|
style="z-index: 42"
|
|
70
72
|
>
|
|
71
73
|
<div
|
|
72
|
-
class="flex items-center justify-between p-2 w-full border-b rounded-t dark:border-fv-neutral-700"
|
|
73
74
|
v-if="title"
|
|
75
|
+
class="flex items-center justify-between p-2 w-full border-b rounded-t dark:border-fv-neutral-700"
|
|
74
76
|
>
|
|
75
|
-
<slot name="before"
|
|
77
|
+
<slot name="before" />
|
|
76
78
|
<h2
|
|
77
|
-
class="text-xl font-semibold text-fv-neutral-900 dark:text-white"
|
|
78
79
|
v-if="title"
|
|
80
|
+
class="text-xl font-semibold text-fv-neutral-900 dark:text-white"
|
|
79
81
|
v-html="title"
|
|
80
82
|
/>
|
|
81
83
|
<button
|
|
82
|
-
@click="setModal(false)"
|
|
83
84
|
class="text-fv-neutral-400 bg-transparent hover:bg-fv-neutral-200 hover:text-fv-neutral-900 rounded-lg text-sm w-8 h-8 ml-auto inline-flex justify-center items-center dark:hover:bg-fv-neutral-600 dark:hover:text-white"
|
|
85
|
+
@click="setModal(false)"
|
|
84
86
|
>
|
|
85
87
|
<component :is="closeIcon" class="w-7 h-7" />
|
|
86
88
|
</button>
|
|
87
89
|
</div>
|
|
88
90
|
<div class="p-3 space-y-3">
|
|
89
|
-
<slot
|
|
91
|
+
<slot />
|
|
90
92
|
</div>
|
|
91
93
|
</div>
|
|
92
94
|
</DialogPanel>
|