@dative-gpi/foundation-shared-components 1.0.34 → 1.0.35
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/autocompletes/FSAutocompleteLanguage.vue +18 -39
- package/components/autocompletes/FSAutocompleteTimeZone.vue +19 -37
- package/components/fields/FSAutocompleteField.vue +419 -251
- package/components/fields/FSAutocompleteTag.vue +100 -0
- package/components/fields/FSTextField.vue +11 -7
- package/composables/useAddress.ts +2 -2
- package/package.json +4 -4
- package/components/autocompletes/FSAutocompleteTag.vue +0 -138
|
@@ -20,45 +20,66 @@
|
|
|
20
20
|
<template
|
|
21
21
|
v-if="isExtraSmall"
|
|
22
22
|
>
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
>
|
|
39
|
-
<template
|
|
40
|
-
v-for="(_, name) in $slots"
|
|
41
|
-
v-slot:[name]="slotData"
|
|
42
|
-
>
|
|
43
|
-
<slot
|
|
44
|
-
:name="name"
|
|
45
|
-
v-bind="slotData"
|
|
46
|
-
/>
|
|
47
|
-
</template>
|
|
48
|
-
<template
|
|
49
|
-
v-if="mobileSelectionProps"
|
|
50
|
-
#prepend-inner
|
|
51
|
-
>
|
|
52
|
-
<slot
|
|
53
|
-
name="selection-mobile"
|
|
54
|
-
v-bind="mobileSelectionProps"
|
|
55
|
-
/>
|
|
56
|
-
</template>
|
|
57
|
-
<template
|
|
58
|
-
#append-inner
|
|
23
|
+
<FSCol>
|
|
24
|
+
<FSTextField
|
|
25
|
+
:validationValue="$props.modelValue"
|
|
26
|
+
:description="$props.description"
|
|
27
|
+
:hideHeader="$props.hideHeader"
|
|
28
|
+
:clearable="$props.clearable"
|
|
29
|
+
:editable="$props.editable"
|
|
30
|
+
:required="$props.required"
|
|
31
|
+
:label="$props.label"
|
|
32
|
+
:rules="$props.rules"
|
|
33
|
+
:messages="messages"
|
|
34
|
+
:readonly="true"
|
|
35
|
+
:modelValue="mobileValue"
|
|
36
|
+
@click="openMobileOverlay"
|
|
37
|
+
v-bind="$attrs"
|
|
59
38
|
>
|
|
60
|
-
<
|
|
61
|
-
|
|
39
|
+
<template
|
|
40
|
+
v-for="(_, name) in $slots"
|
|
41
|
+
v-slot:[name]="slotData"
|
|
42
|
+
>
|
|
43
|
+
<slot
|
|
44
|
+
:name="name"
|
|
45
|
+
v-bind="slotData"
|
|
46
|
+
/>
|
|
47
|
+
</template>
|
|
48
|
+
<template
|
|
49
|
+
#prepend-inner
|
|
50
|
+
>
|
|
51
|
+
<slot
|
|
52
|
+
v-if="selectedItem"
|
|
53
|
+
name="item-prepend"
|
|
54
|
+
v-bind="{ item: selectedItem }"
|
|
55
|
+
/>
|
|
56
|
+
</template>
|
|
57
|
+
<template
|
|
58
|
+
#clear
|
|
59
|
+
>
|
|
60
|
+
<FSRow
|
|
61
|
+
:wrap="false"
|
|
62
|
+
>
|
|
63
|
+
<slot
|
|
64
|
+
v-if="selectedItem"
|
|
65
|
+
name="item-append"
|
|
66
|
+
v-bind="{ item: selectedItem }"
|
|
67
|
+
/>
|
|
68
|
+
<slot
|
|
69
|
+
name="clear"
|
|
70
|
+
>
|
|
71
|
+
<FSButton
|
|
72
|
+
v-if="$props.clearable && $props.editable && !!$props.modelValue"
|
|
73
|
+
icon="mdi-close"
|
|
74
|
+
variant="icon"
|
|
75
|
+
:color="ColorEnum.Dark"
|
|
76
|
+
@click="$emit('update:modelValue', null)"
|
|
77
|
+
/>
|
|
78
|
+
</slot>
|
|
79
|
+
</FSRow>
|
|
80
|
+
</template>
|
|
81
|
+
<template
|
|
82
|
+
#append-inner
|
|
62
83
|
>
|
|
63
84
|
<FSButton
|
|
64
85
|
icon="mdi-chevron-down"
|
|
@@ -67,9 +88,45 @@
|
|
|
67
88
|
:color="ColorEnum.Dark"
|
|
68
89
|
@click="openMobileOverlay"
|
|
69
90
|
/>
|
|
70
|
-
</
|
|
71
|
-
</
|
|
72
|
-
|
|
91
|
+
</template>
|
|
92
|
+
</FSTextField>
|
|
93
|
+
<FSSlideGroup
|
|
94
|
+
v-if="$props.multiple && Array.isArray($props.modelValue)"
|
|
95
|
+
>
|
|
96
|
+
<FSCard
|
|
97
|
+
v-for="(item, index) in $props.items.filter((item: any) => $props.modelValue.includes(item[$props.itemValue!]))"
|
|
98
|
+
variant="standard"
|
|
99
|
+
:height="['40px', '36px']"
|
|
100
|
+
:color="ColorEnum.Light"
|
|
101
|
+
:border="false"
|
|
102
|
+
:key="index"
|
|
103
|
+
>
|
|
104
|
+
<FSRow
|
|
105
|
+
align="center-left"
|
|
106
|
+
padding="0 8px"
|
|
107
|
+
:wrap="false"
|
|
108
|
+
>
|
|
109
|
+
<slot
|
|
110
|
+
name="item-prepend"
|
|
111
|
+
v-bind="{ item }"
|
|
112
|
+
/>
|
|
113
|
+
<FSSpan>
|
|
114
|
+
{{ item[$props.itemTitle!] }}
|
|
115
|
+
</FSSpan>
|
|
116
|
+
<slot
|
|
117
|
+
name="item-append"
|
|
118
|
+
v-bind="{ item }"
|
|
119
|
+
/>
|
|
120
|
+
<FSButton
|
|
121
|
+
icon="mdi-close"
|
|
122
|
+
variant="icon"
|
|
123
|
+
:color="ColorEnum.Dark"
|
|
124
|
+
@click="() => onCheckboxChange(item[$props.itemValue!])"
|
|
125
|
+
/>
|
|
126
|
+
</FSRow>
|
|
127
|
+
</FSCard>
|
|
128
|
+
</FSSlideGroup>
|
|
129
|
+
</FSCol>
|
|
73
130
|
<FSDialogMenu
|
|
74
131
|
v-model="dialog"
|
|
75
132
|
>
|
|
@@ -84,7 +141,6 @@
|
|
|
84
141
|
:maxHeight="maxHeight"
|
|
85
142
|
>
|
|
86
143
|
<FSCol
|
|
87
|
-
v-if="$props.multiple"
|
|
88
144
|
gap="12px"
|
|
89
145
|
>
|
|
90
146
|
<FSRow
|
|
@@ -92,40 +148,89 @@
|
|
|
92
148
|
:key="index"
|
|
93
149
|
>
|
|
94
150
|
<FSCheckbox
|
|
95
|
-
|
|
151
|
+
v-if="$props.multiple"
|
|
152
|
+
:label="item[$props.itemTitle!]"
|
|
96
153
|
:editable="$props.editable"
|
|
97
|
-
:modelValue="$props.modelValue?.includes(item[$props.itemValue])"
|
|
98
|
-
@update:modelValue="() => onCheckboxChange(item[$props.itemValue])"
|
|
154
|
+
:modelValue="$props.modelValue?.includes(item[$props.itemValue!])"
|
|
155
|
+
@update:modelValue="() => onCheckboxChange(item[$props.itemValue!])"
|
|
99
156
|
>
|
|
100
157
|
<template
|
|
101
158
|
#label="{ font }"
|
|
102
159
|
>
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
160
|
+
<FSRow
|
|
161
|
+
align="center-left"
|
|
162
|
+
:wrap="false"
|
|
163
|
+
>
|
|
164
|
+
<slot
|
|
165
|
+
name="item-prepend"
|
|
166
|
+
v-bind="{ item }"
|
|
167
|
+
/>
|
|
168
|
+
<FSSpan
|
|
169
|
+
:font="font"
|
|
170
|
+
>
|
|
171
|
+
{{ item[$props.itemTitle!] }}
|
|
172
|
+
</FSSpan>
|
|
173
|
+
</FSRow>
|
|
107
174
|
</template>
|
|
108
175
|
</FSCheckbox>
|
|
176
|
+
<FSRadio
|
|
177
|
+
v-else
|
|
178
|
+
:selected="$props.modelValue === item[$props.itemValue!]"
|
|
179
|
+
:label="item[$props.itemTitle!]"
|
|
180
|
+
:editable="$props.editable"
|
|
181
|
+
:item="item"
|
|
182
|
+
:modelValue="item[$props.itemValue!]"
|
|
183
|
+
@update:modelValue="() => onRadioChange(item[$props.itemValue!])"
|
|
184
|
+
>
|
|
185
|
+
<template
|
|
186
|
+
#label="{ font }"
|
|
187
|
+
>
|
|
188
|
+
<FSRow
|
|
189
|
+
align="center-left"
|
|
190
|
+
:wrap="false"
|
|
191
|
+
>
|
|
192
|
+
<slot
|
|
193
|
+
name="item-prepend"
|
|
194
|
+
v-bind="{ item }"
|
|
195
|
+
/>
|
|
196
|
+
<FSSpan
|
|
197
|
+
:font="font"
|
|
198
|
+
>
|
|
199
|
+
{{ item[$props.itemTitle!] }}
|
|
200
|
+
</FSSpan>
|
|
201
|
+
</FSRow>
|
|
202
|
+
</template>
|
|
203
|
+
</FSRadio>
|
|
204
|
+
<FSRow
|
|
205
|
+
align="center-right"
|
|
206
|
+
>
|
|
207
|
+
<slot
|
|
208
|
+
name="item-append"
|
|
209
|
+
v-bind="{ item }"
|
|
210
|
+
/>
|
|
211
|
+
</FSRow>
|
|
109
212
|
</FSRow>
|
|
110
213
|
</FSCol>
|
|
111
|
-
<FSRadioGroup
|
|
112
|
-
v-else
|
|
113
|
-
gap="12px"
|
|
114
|
-
:values="searchItems.map((item: any) => ({ value: item[$props.itemValue], label: item[$props.itemTitle], item: item }))"
|
|
115
|
-
:editable="$props.editable"
|
|
116
|
-
:modelValue="$props.modelValue"
|
|
117
|
-
@update:modelValue="onRadioChange"
|
|
118
|
-
>
|
|
119
|
-
<template
|
|
120
|
-
#label="{ item, font }"
|
|
121
|
-
>
|
|
122
|
-
<slot
|
|
123
|
-
name="item-label"
|
|
124
|
-
v-bind="mobileItemProps(item, font)"
|
|
125
|
-
/>
|
|
126
|
-
</template>
|
|
127
|
-
</FSRadioGroup>
|
|
128
214
|
</FSFadeOut>
|
|
215
|
+
<FSRow
|
|
216
|
+
v-if="allowAddItem"
|
|
217
|
+
padding="4px 3px"
|
|
218
|
+
>
|
|
219
|
+
<FSButton
|
|
220
|
+
variant="icon"
|
|
221
|
+
:label="$tr('ui.autocomplete.add-item', 'Add new item')"
|
|
222
|
+
:color="ColorEnum.Primary"
|
|
223
|
+
@click="$emit('add:item', search)"
|
|
224
|
+
/>
|
|
225
|
+
</FSRow>
|
|
226
|
+
<FSRow
|
|
227
|
+
v-if="!allowAddItem && searchItems.length === 0"
|
|
228
|
+
padding="4px 3px"
|
|
229
|
+
>
|
|
230
|
+
<FSSpan>
|
|
231
|
+
{{ $tr("ui.common.no-data", "No data") }}
|
|
232
|
+
</FSSpan>
|
|
233
|
+
</FSRow>
|
|
129
234
|
</template>
|
|
130
235
|
</FSDialogMenu>
|
|
131
236
|
</template>
|
|
@@ -161,175 +266,231 @@
|
|
|
161
266
|
/>
|
|
162
267
|
</template>
|
|
163
268
|
</FSToggleSet>
|
|
164
|
-
<
|
|
269
|
+
<FSCol
|
|
165
270
|
v-else
|
|
166
|
-
class="fs-autocomplete-field"
|
|
167
|
-
variant="outlined"
|
|
168
|
-
:clearable="$props.clearable && $props.editable && !!$props.modelValue"
|
|
169
|
-
:itemTitle="$props.itemTitle"
|
|
170
|
-
:itemValue="$props.itemValue"
|
|
171
|
-
:readonly="!$props.editable"
|
|
172
|
-
:multiple="$props.multiple"
|
|
173
|
-
:validateOn="validateOn"
|
|
174
|
-
:autoSelectFirst="true"
|
|
175
|
-
:persistentClear="true"
|
|
176
|
-
:listProps="listStyle"
|
|
177
|
-
:returnObject="false"
|
|
178
|
-
:items="$props.items"
|
|
179
|
-
:rules="$props.rules"
|
|
180
|
-
:hideDetails="true"
|
|
181
|
-
:menuIcon="null"
|
|
182
|
-
:class="classes"
|
|
183
|
-
:style="style"
|
|
184
|
-
:modelValue="$props.modelValue"
|
|
185
|
-
@update:modelValue="$emit('update:modelValue', $event)"
|
|
186
|
-
@click="onClick"
|
|
187
|
-
v-model:search="search"
|
|
188
|
-
v-bind="$attrs"
|
|
189
271
|
>
|
|
190
|
-
<
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
272
|
+
<v-autocomplete
|
|
273
|
+
class="fs-autocomplete-field"
|
|
274
|
+
variant="outlined"
|
|
275
|
+
:clearable="$props.clearable && $props.editable && !!$props.modelValue"
|
|
276
|
+
:itemTitle="$props.itemTitle"
|
|
277
|
+
:itemValue="$props.itemValue"
|
|
278
|
+
:readonly="!$props.editable"
|
|
279
|
+
:multiple="$props.multiple"
|
|
280
|
+
:validateOn="validateOn"
|
|
281
|
+
:autoSelectFirst="true"
|
|
282
|
+
:persistentClear="true"
|
|
283
|
+
:listProps="listStyle"
|
|
284
|
+
:returnObject="false"
|
|
285
|
+
:items="$props.items"
|
|
286
|
+
:rules="$props.rules"
|
|
287
|
+
:hideDetails="true"
|
|
288
|
+
:menuIcon="null"
|
|
289
|
+
:class="classes"
|
|
290
|
+
:style="style"
|
|
291
|
+
:modelValue="$props.modelValue"
|
|
292
|
+
@update:modelValue="onSingleChange"
|
|
293
|
+
@click="onClick"
|
|
294
|
+
v-model:search="search"
|
|
295
|
+
v-bind="$attrs"
|
|
201
296
|
>
|
|
202
|
-
<
|
|
203
|
-
v-
|
|
297
|
+
<template
|
|
298
|
+
v-for="(_, name) in autocompleteSlots"
|
|
299
|
+
v-slot:[name]="slotData"
|
|
204
300
|
>
|
|
205
|
-
<
|
|
206
|
-
|
|
301
|
+
<slot
|
|
302
|
+
:name="`autocomplete-${name}`"
|
|
303
|
+
v-bind="slotData"
|
|
304
|
+
/>
|
|
305
|
+
</template>
|
|
306
|
+
<template
|
|
307
|
+
#item="{ props, item }"
|
|
308
|
+
>
|
|
309
|
+
<v-list-item
|
|
310
|
+
v-bind="{ ...props, title: '' }"
|
|
207
311
|
>
|
|
208
|
-
<
|
|
209
|
-
|
|
210
|
-
:
|
|
211
|
-
@click="props.onClick"
|
|
312
|
+
<FSRow
|
|
313
|
+
align="center-left"
|
|
314
|
+
:wrap="false"
|
|
212
315
|
>
|
|
213
|
-
<
|
|
214
|
-
|
|
316
|
+
<FSCheckbox
|
|
317
|
+
v-if="$props.multiple"
|
|
318
|
+
:modelValue="$props.modelValue?.includes(item.raw[$props.itemValue!])"
|
|
319
|
+
@click="props.onClick"
|
|
215
320
|
>
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
v-bind="{ item, font }"
|
|
321
|
+
<template
|
|
322
|
+
#label="{ font }"
|
|
219
323
|
>
|
|
324
|
+
<slot
|
|
325
|
+
name="item-prepend"
|
|
326
|
+
v-bind="{ item: item.raw }"
|
|
327
|
+
/>
|
|
220
328
|
<FSSpan
|
|
221
329
|
:font="font"
|
|
222
330
|
>
|
|
223
|
-
{{ item.raw[$props.itemTitle] }}
|
|
331
|
+
{{ item.raw[$props.itemTitle!] }}
|
|
224
332
|
</FSSpan>
|
|
225
|
-
</
|
|
226
|
-
</
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
v-else
|
|
230
|
-
>
|
|
231
|
-
<slot
|
|
232
|
-
name="item-label"
|
|
233
|
-
v-bind="{
|
|
234
|
-
item,
|
|
235
|
-
font: $props.modelValue === item.raw[$props.itemTitle] ? 'text-button' : 'text-body'
|
|
236
|
-
}"
|
|
333
|
+
</template>
|
|
334
|
+
</FSCheckbox>
|
|
335
|
+
<template
|
|
336
|
+
v-else
|
|
237
337
|
>
|
|
338
|
+
<slot
|
|
339
|
+
name="item-prepend"
|
|
340
|
+
v-bind="{ item: item.raw }"
|
|
341
|
+
/>
|
|
238
342
|
<FSSpan
|
|
239
|
-
:font="$props.modelValue === item.raw[$props.itemTitle] ? 'text-button' : 'text-body'"
|
|
343
|
+
:font="$props.modelValue === item.raw[$props.itemTitle!] ? 'text-button' : 'text-body'"
|
|
240
344
|
>
|
|
241
|
-
{{ item.raw[$props.itemTitle] }}
|
|
345
|
+
{{ item.raw[$props.itemTitle!] }}
|
|
242
346
|
</FSSpan>
|
|
243
|
-
</
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
347
|
+
</template>
|
|
348
|
+
<FSRow
|
|
349
|
+
align="center-right"
|
|
350
|
+
>
|
|
351
|
+
<slot
|
|
352
|
+
name="item-append"
|
|
353
|
+
v-bind="{ item: item.raw }"
|
|
354
|
+
/>
|
|
355
|
+
</FSRow>
|
|
356
|
+
</FSRow>
|
|
357
|
+
</v-list-item>
|
|
358
|
+
</template>
|
|
359
|
+
<template
|
|
360
|
+
#prepend-inner
|
|
361
|
+
>
|
|
362
|
+
<slot
|
|
363
|
+
v-if="selectedItem && addExtra"
|
|
364
|
+
name="item-prepend"
|
|
365
|
+
v-bind="{ item: selectedItem }"
|
|
366
|
+
/>
|
|
367
|
+
</template>
|
|
368
|
+
<template
|
|
369
|
+
v-if="$props.multiple"
|
|
370
|
+
#selection="{ index }"
|
|
371
|
+
>
|
|
372
|
+
<FSSpan
|
|
373
|
+
v-if="index === $props.modelValue.length - 1 && addExtra"
|
|
374
|
+
>
|
|
375
|
+
{{ $props.placeholder }}
|
|
376
|
+
</FSSpan>
|
|
377
|
+
</template>
|
|
378
|
+
<template
|
|
379
|
+
#clear
|
|
253
380
|
>
|
|
254
381
|
<FSRow
|
|
255
|
-
gap="16px"
|
|
256
382
|
:wrap="false"
|
|
257
383
|
>
|
|
258
384
|
<slot
|
|
259
|
-
v-if="
|
|
260
|
-
name="
|
|
385
|
+
v-if="selectedItem"
|
|
386
|
+
name="item-append"
|
|
387
|
+
v-bind="{ item: selectedItem }"
|
|
261
388
|
/>
|
|
389
|
+
<slot
|
|
390
|
+
name="clear"
|
|
391
|
+
>
|
|
392
|
+
<FSButton
|
|
393
|
+
v-if="$props.clearable && $props.editable && !!$props.modelValue"
|
|
394
|
+
icon="mdi-close"
|
|
395
|
+
variant="icon"
|
|
396
|
+
:color="ColorEnum.Dark"
|
|
397
|
+
@click="$emit('update:modelValue', null)"
|
|
398
|
+
/>
|
|
399
|
+
</slot>
|
|
400
|
+
</FSRow>
|
|
401
|
+
</template>
|
|
402
|
+
<template
|
|
403
|
+
#append-inner
|
|
404
|
+
>
|
|
405
|
+
<slot
|
|
406
|
+
name="append-inner"
|
|
407
|
+
>
|
|
262
408
|
<FSButton
|
|
263
|
-
|
|
264
|
-
icon="mdi-close"
|
|
409
|
+
icon="mdi-chevron-down"
|
|
265
410
|
variant="icon"
|
|
411
|
+
:editable="$props.editable"
|
|
266
412
|
:color="ColorEnum.Dark"
|
|
267
|
-
@click="$emit('update:modelValue', null)"
|
|
268
413
|
/>
|
|
269
|
-
</
|
|
270
|
-
</
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
#append-inner
|
|
274
|
-
>
|
|
275
|
-
<slot
|
|
276
|
-
name="append-inner"
|
|
277
|
-
>
|
|
278
|
-
<FSButton
|
|
279
|
-
icon="mdi-chevron-down"
|
|
280
|
-
variant="icon"
|
|
281
|
-
:editable="$props.editable"
|
|
282
|
-
:color="ColorEnum.Dark"
|
|
283
|
-
/>
|
|
284
|
-
</slot>
|
|
285
|
-
</template>
|
|
286
|
-
<template
|
|
287
|
-
#append-item
|
|
288
|
-
>
|
|
289
|
-
<FSRow
|
|
290
|
-
v-if="showSearch && !searchItems.map((item: any) => item[$props.itemTitle]).some(s=>s.toLowerCase() == search.toLowerCase())"
|
|
291
|
-
padding="17px"
|
|
414
|
+
</slot>
|
|
415
|
+
</template>
|
|
416
|
+
<template
|
|
417
|
+
#append-item
|
|
292
418
|
>
|
|
293
|
-
<
|
|
294
|
-
v-if="
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
419
|
+
<FSRow
|
|
420
|
+
v-if="allowAddItem"
|
|
421
|
+
padding="17px"
|
|
422
|
+
>
|
|
423
|
+
<FSButton
|
|
424
|
+
variant="icon"
|
|
425
|
+
:label="$tr('ui.autocomplete.add-item', 'Add new item')"
|
|
426
|
+
:color="ColorEnum.Primary"
|
|
427
|
+
@click="$emit('add:item', search)"
|
|
428
|
+
/>
|
|
429
|
+
</FSRow>
|
|
430
|
+
</template>
|
|
305
431
|
<template
|
|
306
|
-
|
|
432
|
+
#no-data
|
|
307
433
|
>
|
|
434
|
+
<FSRow
|
|
435
|
+
v-if="!allowAddItem"
|
|
436
|
+
padding="17px"
|
|
437
|
+
>
|
|
438
|
+
<FSSpan>
|
|
439
|
+
{{ $tr("ui.common.no-data", "No data") }}
|
|
440
|
+
</FSSpan>
|
|
441
|
+
</FSRow>
|
|
308
442
|
</template>
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
443
|
+
</v-autocomplete>
|
|
444
|
+
<FSSlideGroup
|
|
445
|
+
v-if="$props.multiple && Array.isArray($props.modelValue)"
|
|
446
|
+
>
|
|
447
|
+
<FSCard
|
|
448
|
+
v-for="(item, index) in $props.items.filter((item: any) => $props.modelValue.includes(item[$props.itemValue!]))"
|
|
449
|
+
variant="standard"
|
|
450
|
+
:height="['40px', '36px']"
|
|
451
|
+
:color="ColorEnum.Light"
|
|
452
|
+
:border="false"
|
|
453
|
+
:key="index"
|
|
312
454
|
>
|
|
313
|
-
<
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
455
|
+
<FSRow
|
|
456
|
+
align="center-left"
|
|
457
|
+
padding="0 8px"
|
|
458
|
+
>
|
|
459
|
+
<slot
|
|
460
|
+
name="item-prepend"
|
|
461
|
+
v-bind="{ item }"
|
|
462
|
+
/>
|
|
463
|
+
<FSSpan>
|
|
464
|
+
{{ item[$props.itemTitle!] }}
|
|
465
|
+
</FSSpan>
|
|
466
|
+
<slot
|
|
467
|
+
name="item-append"
|
|
468
|
+
v-bind="{ item }"
|
|
469
|
+
/>
|
|
470
|
+
<FSButton
|
|
471
|
+
icon="mdi-close"
|
|
472
|
+
variant="icon"
|
|
473
|
+
:color="ColorEnum.Dark"
|
|
474
|
+
@click="() => onCheckboxChange(item[$props.itemValue!])"
|
|
475
|
+
/>
|
|
476
|
+
</FSRow>
|
|
477
|
+
</FSCard>
|
|
478
|
+
</FSSlideGroup>
|
|
479
|
+
</FSCol>
|
|
319
480
|
</FSBaseField>
|
|
320
481
|
</template>
|
|
321
482
|
</template>
|
|
322
483
|
</template>
|
|
323
484
|
|
|
324
485
|
<script lang="ts">
|
|
325
|
-
import { computed, defineComponent, type PropType, ref, type StyleValue } from "vue";
|
|
486
|
+
import { computed, defineComponent, type PropType, ref, type StyleValue, type Slot } from "vue";
|
|
326
487
|
|
|
327
488
|
import { useBreakpoints, useColors, useRules, useSlots } from "@dative-gpi/foundation-shared-components/composables";
|
|
328
489
|
import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
|
|
329
490
|
|
|
330
491
|
import FSSearchField from "./FSSearchField.vue";
|
|
331
492
|
import FSDialogMenu from "../FSDialogMenu.vue";
|
|
332
|
-
import
|
|
493
|
+
import FSSlideGroup from "../FSSlideGroup.vue";
|
|
333
494
|
import FSToggleSet from "../FSToggleSet.vue";
|
|
334
495
|
import FSBaseField from "./FSBaseField.vue";
|
|
335
496
|
import FSTextField from "./FSTextField.vue";
|
|
@@ -337,6 +498,8 @@ import FSCheckbox from "../FSCheckbox.vue";
|
|
|
337
498
|
import FSFadeOut from "../FSFadeOut.vue";
|
|
338
499
|
import FSButton from "../FSButton.vue";
|
|
339
500
|
import FSLoader from "../FSLoader.vue";
|
|
501
|
+
import FSRadio from "../FSRadio.vue";
|
|
502
|
+
import FSCard from "../FSCard.vue";
|
|
340
503
|
import FSSpan from "../FSSpan.vue";
|
|
341
504
|
import FSCol from "../FSCol.vue";
|
|
342
505
|
import FSRow from "../FSRow.vue";
|
|
@@ -347,7 +510,7 @@ export default defineComponent({
|
|
|
347
510
|
components: {
|
|
348
511
|
FSSearchField,
|
|
349
512
|
FSDialogMenu,
|
|
350
|
-
|
|
513
|
+
FSSlideGroup,
|
|
351
514
|
FSBaseField,
|
|
352
515
|
FSTextField,
|
|
353
516
|
FSToggleSet,
|
|
@@ -355,6 +518,8 @@ export default defineComponent({
|
|
|
355
518
|
FSFadeOut,
|
|
356
519
|
FSButton,
|
|
357
520
|
FSLoader,
|
|
521
|
+
FSRadio,
|
|
522
|
+
FSCard,
|
|
358
523
|
FSSpan,
|
|
359
524
|
FSCol,
|
|
360
525
|
FSRow
|
|
@@ -365,6 +530,11 @@ export default defineComponent({
|
|
|
365
530
|
required: false,
|
|
366
531
|
default: null
|
|
367
532
|
},
|
|
533
|
+
placeholder: {
|
|
534
|
+
type: String as PropType<string | null>,
|
|
535
|
+
required: false,
|
|
536
|
+
default: null
|
|
537
|
+
},
|
|
368
538
|
description: {
|
|
369
539
|
type: String as PropType<string | null>,
|
|
370
540
|
required: false,
|
|
@@ -457,6 +627,7 @@ export default defineComponent({
|
|
|
457
627
|
|
|
458
628
|
const dialog = ref(false);
|
|
459
629
|
const search = ref("");
|
|
630
|
+
const addExtra = ref(true);
|
|
460
631
|
|
|
461
632
|
const style = computed((): StyleValue => {
|
|
462
633
|
if (!props.editable) {
|
|
@@ -479,21 +650,21 @@ export default defineComponent({
|
|
|
479
650
|
};
|
|
480
651
|
});
|
|
481
652
|
|
|
482
|
-
const autocompleteSlots = computed((): any => {
|
|
483
|
-
return Object.keys(slots).filter(k => k.startsWith("autocomplete-")).reduce((acc, key) => {
|
|
653
|
+
const autocompleteSlots = computed((): { [key: string]: Slot<any> } => {
|
|
654
|
+
return Object.keys(slots).filter(k => k.startsWith("autocomplete-")).reduce((acc: { [key: string]: Slot<any> }, key) => {
|
|
484
655
|
acc[key.substring("autocomplete-".length)] = slots[key];
|
|
485
656
|
return acc;
|
|
486
657
|
}, {});
|
|
487
658
|
});
|
|
488
659
|
|
|
489
|
-
const toggleSetSlots = computed((): any => {
|
|
490
|
-
return Object.keys(slots).filter(k => k.startsWith("toggle-set-")).reduce((acc, key) => {
|
|
660
|
+
const toggleSetSlots = computed((): { [key: string]: Slot<any> } => {
|
|
661
|
+
return Object.keys(slots).filter(k => k.startsWith("toggle-set-")).reduce((acc: { [key: string]: Slot<any> }, key) => {
|
|
491
662
|
acc[key.substring("toggle-set-".length)] = slots[key];
|
|
492
663
|
return acc;
|
|
493
664
|
}, {});
|
|
494
665
|
});
|
|
495
666
|
|
|
496
|
-
const listStyle = computed(():
|
|
667
|
+
const listStyle = computed((): { style: StyleValue } => {
|
|
497
668
|
return {
|
|
498
669
|
style: style.value
|
|
499
670
|
};
|
|
@@ -509,12 +680,42 @@ export default defineComponent({
|
|
|
509
680
|
|
|
510
681
|
const messages = computed((): string[] => props.messages ?? getMessages(props.modelValue, props.rules));
|
|
511
682
|
|
|
512
|
-
const searchItems = computed(() => {
|
|
683
|
+
const searchItems = computed((): any[] => {
|
|
513
684
|
return props.items.filter((item: any) => {
|
|
514
685
|
return item[props.itemTitle].toLowerCase().includes(search.value.toLowerCase());
|
|
515
686
|
});
|
|
516
687
|
});
|
|
517
688
|
|
|
689
|
+
const selectedItem = computed((): any => {
|
|
690
|
+
if (props.multiple) {
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
if (Array.isArray(props.modelValue) && props.modelValue.length > 0) {
|
|
694
|
+
return props.items.find((item: any) => item[props.itemValue] === props.modelValue[0]) ?? null;
|
|
695
|
+
}
|
|
696
|
+
else if (props.modelValue) {
|
|
697
|
+
return props.items.find((item: any) => item[props.itemValue] === props.modelValue) ?? null;
|
|
698
|
+
}
|
|
699
|
+
return null;
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
const selectedItems = computed((): any[] => {
|
|
703
|
+
if (Array.isArray(props.modelValue) && props.modelValue.length > 0) {
|
|
704
|
+
return props.items.filter((item: any) => props.modelValue.includes(item[props.itemValue]));
|
|
705
|
+
}
|
|
706
|
+
else if (props.modelValue) {
|
|
707
|
+
const item = props.items.find((item: any) => item[props.itemValue] === props.modelValue);
|
|
708
|
+
if (item) {
|
|
709
|
+
return [item];
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
return [];
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
const allowAddItem = computed((): boolean => {
|
|
716
|
+
return props.showSearch && search.value.trim().length > 0;
|
|
717
|
+
});
|
|
718
|
+
|
|
518
719
|
const maxHeight = computed(() => {
|
|
519
720
|
const other = 8 + 8 // Paddings
|
|
520
721
|
+ (isMobileSized ? 36 : 40) + 8; // Header
|
|
@@ -523,58 +724,14 @@ export default defineComponent({
|
|
|
523
724
|
|
|
524
725
|
const mobileValue = computed((): string | null => {
|
|
525
726
|
if (props.multiple) {
|
|
526
|
-
|
|
527
|
-
return props.modelValue.map((value: any) => {
|
|
528
|
-
const item = props.items.find((item: object) => item[props.itemValue] === value);
|
|
529
|
-
if (item) {
|
|
530
|
-
return item[props.itemTitle];
|
|
531
|
-
}
|
|
532
|
-
}).filter(value => !!value).join(", ");
|
|
533
|
-
}
|
|
727
|
+
return props.placeholder;
|
|
534
728
|
}
|
|
535
|
-
if (
|
|
536
|
-
|
|
537
|
-
if (item) {
|
|
538
|
-
return item[props.itemTitle];
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return null;
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
const mobileSelectionProps = computed((): any | null => {
|
|
545
|
-
const item = props.items.find((item: any) => item[props.itemValue] === props.modelValue);
|
|
546
|
-
if (item) {
|
|
547
|
-
return {
|
|
548
|
-
item: {
|
|
549
|
-
title: "",
|
|
550
|
-
value: item[props.itemValue],
|
|
551
|
-
props: {
|
|
552
|
-
title: item[props.itemTitle],
|
|
553
|
-
value: item[props.itemValue]
|
|
554
|
-
},
|
|
555
|
-
raw: { ...item }
|
|
556
|
-
},
|
|
557
|
-
font: "text-body"
|
|
558
|
-
};
|
|
729
|
+
if (selectedItem.value) {
|
|
730
|
+
return selectedItem.value[props.itemTitle];
|
|
559
731
|
}
|
|
560
732
|
return null;
|
|
561
733
|
});
|
|
562
734
|
|
|
563
|
-
const mobileItemProps = (item: any, font: "text-body" | "text-button" | null): any => {
|
|
564
|
-
return {
|
|
565
|
-
item: {
|
|
566
|
-
title: "",
|
|
567
|
-
value: item[props.itemValue],
|
|
568
|
-
props: {
|
|
569
|
-
title: item[props.itemTitle],
|
|
570
|
-
value: item[props.itemValue]
|
|
571
|
-
},
|
|
572
|
-
raw: { ...item }
|
|
573
|
-
},
|
|
574
|
-
font
|
|
575
|
-
}
|
|
576
|
-
};
|
|
577
|
-
|
|
578
735
|
const openMobileOverlay = () => {
|
|
579
736
|
if (!props.editable) {
|
|
580
737
|
return;
|
|
@@ -583,11 +740,13 @@ export default defineComponent({
|
|
|
583
740
|
};
|
|
584
741
|
|
|
585
742
|
const onRadioChange = (value: string | null) => {
|
|
743
|
+
addExtra.value = true;
|
|
586
744
|
emit("update:modelValue", value);
|
|
587
745
|
dialog.value = false;
|
|
588
746
|
};
|
|
589
747
|
|
|
590
748
|
const onCheckboxChange = (value: string) => {
|
|
749
|
+
addExtra.value = true;
|
|
591
750
|
if (Array.isArray(props.modelValue)) {
|
|
592
751
|
if (props.modelValue.includes(value)) {
|
|
593
752
|
emit("update:modelValue", props.modelValue.filter((item: any) => item !== value));
|
|
@@ -609,23 +768,32 @@ export default defineComponent({
|
|
|
609
768
|
}
|
|
610
769
|
};
|
|
611
770
|
|
|
612
|
-
const
|
|
771
|
+
const onSingleChange = (value: string) => {
|
|
772
|
+
addExtra.value = true;
|
|
773
|
+
emit("update:modelValue", value);
|
|
774
|
+
};
|
|
775
|
+
|
|
776
|
+
const onClick = (): void => {
|
|
777
|
+
addExtra.value = false;
|
|
613
778
|
if (props.modelValue && !props.multiple) {
|
|
614
|
-
search.value="";
|
|
615
|
-
}
|
|
779
|
+
search.value = "";
|
|
780
|
+
}
|
|
616
781
|
};
|
|
617
782
|
|
|
618
783
|
return {
|
|
619
|
-
mobileSelectionProps,
|
|
620
784
|
autocompleteSlots,
|
|
621
785
|
toggleSetSlots,
|
|
786
|
+
selectedItems,
|
|
622
787
|
isExtraSmall,
|
|
788
|
+
allowAddItem,
|
|
789
|
+
selectedItem,
|
|
623
790
|
mobileValue,
|
|
624
791
|
searchItems,
|
|
625
792
|
validateOn,
|
|
626
793
|
ColorEnum,
|
|
627
794
|
listStyle,
|
|
628
795
|
maxHeight,
|
|
796
|
+
addExtra,
|
|
629
797
|
messages,
|
|
630
798
|
classes,
|
|
631
799
|
dialog,
|
|
@@ -634,7 +802,7 @@ export default defineComponent({
|
|
|
634
802
|
style,
|
|
635
803
|
openMobileOverlay,
|
|
636
804
|
onCheckboxChange,
|
|
637
|
-
|
|
805
|
+
onSingleChange,
|
|
638
806
|
onRadioChange,
|
|
639
807
|
onClick
|
|
640
808
|
};
|