@dative-gpi/foundation-shared-components 1.0.36 → 1.0.37

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