@dative-gpi/foundation-shared-components 0.0.88 → 0.0.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/components/FSButton.vue +23 -7
  2. package/components/FSCalendar.vue +3 -1
  3. package/components/FSCalendarTwin.vue +16 -6
  4. package/components/FSCard.vue +9 -3
  5. package/components/FSCheckbox.vue +6 -2
  6. package/components/FSClickable.vue +33 -9
  7. package/components/FSDialog.vue +9 -5
  8. package/components/FSDialogMenu.vue +80 -0
  9. package/components/FSDialogSubmit.vue +0 -1
  10. package/components/FSEditImage.vue +196 -34
  11. package/components/FSImage.vue +21 -7
  12. package/components/FSLink.vue +4 -2
  13. package/components/FSOptionGroup.vue +51 -69
  14. package/components/FSOptionItem.vue +15 -6
  15. package/components/FSRadioGroup.vue +11 -3
  16. package/components/FSToggleSet.vue +22 -60
  17. package/components/FSWindow.vue +2 -0
  18. package/components/autocompletes/FSAutocompleteLanguage.vue +28 -22
  19. package/components/autocompletes/FSAutocompleteTimeZone.vue +117 -17
  20. package/components/buttons/FSButtonFileMini.vue +6 -1
  21. package/components/fields/FSAutocompleteField.vue +139 -72
  22. package/components/fields/FSBaseField.vue +134 -0
  23. package/components/fields/FSColorField.vue +1 -1
  24. package/components/fields/FSDateField.vue +124 -35
  25. package/components/fields/FSDateTimeField.vue +171 -63
  26. package/components/fields/FSIconField.vue +4 -2
  27. package/components/fields/FSNumberField.vue +9 -3
  28. package/components/fields/FSPasswordField.vue +15 -5
  29. package/components/fields/FSRichTextField.vue +34 -18
  30. package/components/fields/FSSearchField.vue +24 -8
  31. package/components/fields/FSSelectField.vue +254 -93
  32. package/components/fields/FSTagField.vue +15 -9
  33. package/components/fields/FSTextArea.vue +31 -59
  34. package/components/fields/FSTextField.vue +22 -70
  35. package/components/fields/FSTimeField.vue +20 -55
  36. package/components/fields/FSTimeSlotField.vue +13 -59
  37. package/components/lists/FSDataIteratorItem.vue +16 -4
  38. package/components/lists/FSDataTableUI.vue +420 -184
  39. package/components/lists/FSDraggable.vue +26 -13
  40. package/components/lists/FSFilterButton.vue +10 -4
  41. package/components/lists/FSHeaderButton.vue +3 -1
  42. package/components/lists/FSHiddenButton.vue +3 -1
  43. package/composables/useAutocomplete.ts +6 -7
  44. package/composables/useSlots.ts +6 -18
  45. package/package.json +4 -4
  46. package/styles/components/fs_base_field.scss +12 -0
  47. package/styles/components/fs_dialog.scss +10 -2
  48. package/styles/components/fs_dialog_menu.scss +11 -0
  49. package/styles/components/fs_draggable.scss +12 -0
  50. package/styles/components/fs_edit_image.scss +29 -2
  51. package/styles/components/fs_text_area.scss +0 -13
  52. package/styles/components/fs_text_field.scss +1 -14
  53. package/styles/components/index.scss +2 -0
  54. package/styles/globals/overrides.scss +4 -0
  55. package/components/autocompletes/FSAutocompleteOrganisation.vue +0 -77
@@ -1,59 +1,96 @@
1
1
  <template>
2
- <FSCol gap="16px">
3
- <FSRow align="bottom-center"
2
+ <FSCol
3
+ gap="16px"
4
+ >
5
+ <FSRow
6
+ align="bottom-center"
4
7
  :wrap="isExtraSmall ? false : true"
5
- width="fill">
6
- <template v-if="$props.showSearch">
7
- <FSSearchField prependInnerIcon="mdi-magnify"
8
+ width="fill"
9
+ >
10
+ <template
11
+ v-if="$props.showSearch"
12
+ >
13
+ <FSSearchField
14
+ prependInnerIcon="mdi-magnify"
8
15
  :hideHeader="true"
9
- v-model="innerSearch" />
10
- <FSButton v-if="filterableHeaders.length > 0"
16
+ v-model="innerSearch"
17
+ />
18
+ <FSButton
19
+ v-if="filterableHeaders.length > 0"
11
20
  prependIcon="mdi-filter-variant"
12
21
  :variant="showFilters ? 'full' : 'standard'"
13
- @click="showFilters = !showFilters" />
22
+ @click="showFilters = !showFilters"
23
+ />
14
24
  </template>
15
- <slot v-if="!isExtraSmall"
16
- name="toolbar" />
25
+ <slot
26
+ v-if="!isExtraSmall"
27
+ name="toolbar"
28
+ />
17
29
  <v-spacer />
18
- <FSRow v-if="!$props.disableTable && !$props.disableIterator"
19
- align="center-right">
20
- <FSOptionGroup :values="modeOptions"
30
+ <FSRow
31
+ v-if="!$props.disableTable && !$props.disableIterator"
32
+ align="center-right"
33
+ >
34
+ <FSOptionGroup
35
+ :values="modeOptions"
21
36
  :singleColor="true"
22
37
  :required="true"
23
- v-model="innerMode" />
38
+ v-model="innerMode"
39
+ />
24
40
  </FSRow>
25
41
  </FSRow>
26
- <FSRow v-if="isExtraSmall && hasToolbar">
42
+ <FSRow
43
+ v-if="isExtraSmall && hasToolbar"
44
+ >
27
45
  <FSWrapGroup>
28
- <slot name="toolbar" />
46
+ <slot
47
+ name="toolbar"
48
+ />
29
49
  </FSWrapGroup>
30
50
  </FSRow>
31
- <FSRow v-if="showFiltersRow">
32
- <template v-if="showFilters">
33
- <FSFilterButton v-for="(header, index) in filterableHeaders"
51
+ <FSRow
52
+ v-if="showFiltersRow"
53
+ >
54
+ <template
55
+ v-if="showFilters"
56
+ >
57
+ <FSFilterButton
58
+ v-for="(header, index) in filterableHeaders"
34
59
  :key="index"
35
60
  :header="header"
36
61
  :filters="filters[header.value]"
37
- @update:filter="(value) => toggleFilter(header.value, value)">
38
- <template #default="{ filter }">
39
- <slot :name="filterSlot(header)"
40
- v-bind="{ filter }" />
62
+ @update:filter="(value) => toggleFilter(header.value, value)"
63
+ >
64
+ <template
65
+ #default="{ filter }"
66
+ >
67
+ <slot
68
+ :name="filterSlot(header)"
69
+ v-bind="{ filter }"
70
+ />
41
71
  </template>
42
72
  </FSFilterButton>
43
- <FSChip v-if="resetable"
73
+ <FSChip
74
+ v-if="resetable"
44
75
  variant="standard"
45
76
  :label="$tr('ui.data-table.reset-filters', 'Reset')"
46
77
  :color="ColorEnum.Error"
47
78
  :editable="true"
48
- @click="resetFilter" />
79
+ @click="resetFilter"
80
+ />
49
81
  </template>
50
- <FSHiddenButton v-if="innerMode === 'table' && hiddenHeaders.length > 0"
82
+ <FSHiddenButton
83
+ v-if="innerMode === 'table' && hiddenHeaders.length > 0"
51
84
  :headers="hiddenHeaders"
52
85
  :color="$props.color"
53
- @update:show="(value) => updateHeader(value, 'hidden', false)" />
86
+ @update:show="(value) => updateHeader(value, 'hidden', false)"
87
+ />
54
88
  </FSRow>
55
- <template v-if="innerMode === 'table'">
56
- <v-data-table v-if="!isExtraSmall"
89
+ <template
90
+ v-if="innerMode === 'table'"
91
+ >
92
+ <v-data-table
93
+ v-if="!isExtraSmall"
57
94
  :selectStrategy="$props.singleSelect ? 'single' : 'all'"
58
95
  :itemValue="$props.itemValue"
59
96
  :showSelect="$props.showSelect"
@@ -76,66 +113,121 @@
76
113
  @dragover.prevent
77
114
  @drop:row="(event, row) => onDrop(event, row, 'tr.v-data-table__tr')"
78
115
  @dragover="onDragOver($event, 'tr.v-data-table__tr', 'tbody')"
79
- @dragleave="onDragLeave">
80
- <template #no-data>
81
- <FSText font="text-overline">
116
+ @dragleave="onDragLeave"
117
+ >
118
+ <template
119
+ #no-data
120
+ >
121
+ <FSText
122
+ font="text-overline"
123
+ >
82
124
  {{ $tr("ui.data-table.empty", "No data") }}
83
125
  </FSText>
84
126
  </template>
85
- <template #header.data-table-select="props">
86
- <FSRow v-if="!$props.singleSelect"
127
+ <template
128
+ #header.data-table-select="props"
129
+ >
130
+ <FSRow
131
+ v-if="!$props.singleSelect"
87
132
  class="fs-data-table-select"
88
133
  align="bottom-center"
89
- width="hug">
90
- <FSCheckbox :indeterminate="props.someSelected && !props.allSelected"
134
+ width="hug"
135
+ >
136
+ <FSCheckbox
137
+ :indeterminate="props.someSelected && !props.allSelected"
91
138
  :modelValue="props.allSelected"
92
- @update:modelValue="toggleSelectAll(props.allSelected)" />
139
+ @update:modelValue="toggleSelectAll(props.allSelected)"
140
+ />
93
141
  </FSRow>
94
142
  </template>
95
- <template #item.data-table-select="props">
96
- <FSRow class="fs-data-table-select"
143
+ <template
144
+ #item.data-table-select="props"
145
+ >
146
+ <FSRow
147
+ class="fs-data-table-select"
97
148
  align="bottom-center"
98
- width="hug">
99
- <FSCheckbox :modelValue="innerValue.includes(props.item[$props.itemValue])"
100
- @update:modelValue="toggleSelect(props.item)" />
149
+ width="hug"
150
+ >
151
+ <FSCheckbox
152
+ :modelValue="innerValue.includes(props.item[$props.itemValue])"
153
+ @update:modelValue="toggleSelect(props.item)"
154
+ />
101
155
  </FSRow>
102
156
  </template>
103
- <template #item.data-table-draggable="props">
104
- <FSDraggable elementSelector="tr.v-data-table__tr"
157
+ <template
158
+ #item.data-table-draggable="props"
159
+ >
160
+ <FSDraggable
161
+ elementSelector="tr.v-data-table__tr"
105
162
  :disabled="draggableDisabled"
106
163
  :item="props"
107
- @update:dragend="(event, dragged) => onDragEnd(event, dragged, 'tbody')">
108
- <FSRow class="fs-data-table-draggable"
164
+ @update:dragend="(event, dragged) => onDragEnd(event, dragged, 'tbody')"
165
+ >
166
+ <FSRow
167
+ class="fs-data-table-draggable"
109
168
  align="bottom-center"
110
- width="hug">
111
- <FSIcon size="l">
169
+ width="hug"
170
+ >
171
+ <FSIcon
172
+ size="l"
173
+ >
112
174
  mdi-drag-vertical
113
175
  </FSIcon>
114
176
  </FSRow>
115
177
  </FSDraggable>
116
178
  </template>
117
- <template #header.data-table-group="props">
118
- <slot name="header.data-table-group"
119
- v-bind="props" />
179
+ <template
180
+ #header.data-table-group="props"
181
+ >
182
+ <slot
183
+ name="header.data-table-group"
184
+ v-bind="props"
185
+ />
120
186
  </template>
121
- <template #item.data-table-group="props">
122
- <slot name="item.data-table-group"
123
- v-bind="props" />
187
+ <template
188
+ #item.data-table-group="props"
189
+ >
190
+ <slot
191
+ name="item.data-table-group"
192
+ v-bind="props"
193
+ />
124
194
  </template>
125
- <template #group-header="props">
126
- <template :ref="() => { if (!props.isGroupOpen(props.item)) { props.toggleGroup(props.item) } }" />
127
- <tr class="fs-data-table-group-header">
195
+ <template
196
+ #group-header="props"
197
+ >
198
+ <template
199
+ :ref="() => { if (!props.isGroupOpen(props.item)) { props.toggleGroup(props.item) } }"
200
+ />
201
+ <tr
202
+ class="fs-data-table-group-header"
203
+ >
128
204
  <td />
129
- <td class="fs-data-table-group-header"
130
- :colspan="extraHeaders.concat(innerHeaders).length + 1">
131
- <slot name="group-header"
132
- v-bind="props">
133
- <FSCard padding="12px 16px">
134
- <FSRow align="center-left"
135
- width="hug">
205
+ <td
206
+ class="fs-data-table-group-header"
207
+ :colspan="extraHeaders.concat(innerHeaders).length + 1"
208
+ >
209
+ <slot
210
+ name="group-header"
211
+ v-bind="{ ...props, toggleSelectGroup }"
212
+ >
213
+ <FSCard
214
+ padding="12px 16px"
215
+ >
216
+ <FSRow
217
+ align="center-left"
218
+ width="hug"
219
+ >
220
+ <FSCheckbox
221
+ v-if="showSelect"
222
+ :modelValue="props.item.items.every((item) => innerValue.includes(item.key))"
223
+ :indeterminate="innerValue.some((id) => props.item.items.some((item) => item.key === id)) && !props.item.items.every((item) => innerValue.includes(item.key))"
224
+ @update:modelValue="toggleSelectGroup(props.item)"
225
+ />
136
226
  <FSText>
137
- <slot name="group-header-title"
138
- v-bind="props">
227
+ <slot
228
+ name="group-header-title"
229
+ v-bind="props"
230
+ >
139
231
  {{ props.item.value }}
140
232
  </slot>
141
233
  </FSText>
@@ -145,58 +237,98 @@
145
237
  </td>
146
238
  </tr>
147
239
  </template>
148
- <template v-for="(header, index) in headersSlots"
149
- #[header.slotName]="props">
150
- <slot :name="header.slotName"
151
- v-bind="props">
152
- <FSRow align="center-left"
240
+ <template
241
+ v-for="(header, index) in headersSlots"
242
+ #[header.slotName]="props"
243
+ >
244
+ <slot
245
+ :name="header.slotName"
246
+ v-bind="props"
247
+ >
248
+ <FSRow
249
+ align="center-left"
153
250
  :wrap="false"
154
- :key="index">
155
- <slot :name="`${header.slotName}-prepend`" />
156
- <slot :name="`${header.slotName}-title`">
251
+ :key="index"
252
+ >
253
+ <slot
254
+ :name="`${header.slotName}-prepend`"
255
+ />
256
+ <slot
257
+ :name="`${header.slotName}-title`"
258
+ >
157
259
  <FSText>
158
260
  {{ header.text }}
159
261
  </FSText>
160
262
  </slot>
161
- <slot :name="`${header.slotName}-append`" />
263
+ <slot
264
+ :name="`${header.slotName}-append`"
265
+ />
162
266
  <v-spacer />
163
- <slot :name="`${header.slotName}-configuration`">
164
- <FSHeaderButton :first="index === 0"
267
+ <slot
268
+ :name="`${header.slotName}-configuration`"
269
+ >
270
+ <FSHeaderButton
271
+ :first="index === 0"
165
272
  :last="index === headersSlots.length - 1"
166
273
  @update:hide="updateHeader(header, 'hidden', !header.hidden)"
167
274
  @update:left="updateHeader(header, 'index', -1)"
168
- @update:right="updateHeader(header, 'index', 1)" />
169
- <FSButton v-if="header.sortable"
275
+ @update:right="updateHeader(header, 'index', 1)"
276
+ />
277
+ <FSButton
278
+ v-if="header.sortable"
170
279
  variant="icon"
171
280
  :color="sortColor(header, props)"
172
- :icon="sortIcon(header, props)" />
281
+ :icon="sortIcon(header, props)"
282
+ />
173
283
  </slot>
174
284
  </FSRow>
175
285
  </slot>
176
286
  </template>
177
- <template v-for="(item, index) in itemsSlots"
178
- #[item.slotName]="props">
179
- <div class="fs-td-color">
180
- <slot :name="item.slotName"
181
- v-bind="props">
182
- <FSRow align="center-left"
183
- :key="index">
184
- <FSSpan font="text-overline">
287
+ <template
288
+ v-for="(item, index) in itemsSlots"
289
+ #[item.slotName]="props"
290
+ >
291
+ <div
292
+ class="fs-td-color"
293
+ >
294
+ <slot
295
+ :name="item.slotName"
296
+ v-bind="props"
297
+ >
298
+ <FSRow
299
+ align="center-left"
300
+ :key="index"
301
+ >
302
+ <FSSpan
303
+ font="text-overline"
304
+ >
185
305
  {{ props.item[item.value] }}
186
306
  </FSSpan>
187
307
  </FSRow>
188
308
  </slot>
189
309
  </div>
190
310
  </template>
191
- <template #bottom>
192
- <FSRow class="fs-data-table-footer"
311
+ <template
312
+ #bottom
313
+ >
314
+ <FSRow
315
+ class="fs-data-table-footer"
193
316
  align="center-right"
194
317
  padding="16px"
195
- gap="24px">
196
- <template v-if="$props.modelValue.length">
197
- <template v-if="$props.modelValue.length >= innerItems.length">
198
- <FSRow gap="2px">
199
- <FSText font="text-button">
318
+ gap="24px"
319
+ >
320
+ <template
321
+ v-if="$props.modelValue.length"
322
+ >
323
+ <template
324
+ v-if="$props.modelValue.length >= innerItems.length"
325
+ >
326
+ <FSRow
327
+ gap="2px"
328
+ >
329
+ <FSText
330
+ font="text-button"
331
+ >
200
332
  {{ $tr("ui.data-table.all-selected-bold", "Warning:") }}
201
333
  </FSText>
202
334
  <FSText>
@@ -204,50 +336,70 @@
204
336
  </FSText>
205
337
  </FSRow>
206
338
  </template>
207
- <template v-else>
339
+ <template
340
+ v-else
341
+ >
208
342
  <FSText>
209
- {{ $tr("ui.data-table.some-selected", "{0} element(s) selected", $props.modelValue.length.toString())
210
- }}
343
+ {{ $tr("ui.data-table.some-selected", "{0} element(s) selected", $props.modelValue.length.toString()) }}
211
344
  </FSText>
212
345
  </template>
213
346
  </template>
214
347
  <v-spacer />
215
- <FSRow align="center-right"
348
+ <FSRow
349
+ align="center-right"
216
350
  width="hug"
217
- :wrap="false">
218
- <FSText font="text-overline">
351
+ :wrap="false"
352
+ >
353
+ <FSText
354
+ font="text-overline"
355
+ >
219
356
  {{ $tr("ui.data-table.rows-per-page", "Rows per page") }}
220
357
  </FSText>
221
- <FSSelectField class="fs-data-table-rows-per-page"
358
+ <FSSelectField
359
+ class="fs-data-table-rows-per-page"
222
360
  :clearable="false"
223
361
  :hideHeader="true"
224
362
  :items="rowsPerPageOptions"
225
- v-model="innerRowsPerPage" />
363
+ v-model="innerRowsPerPage"
364
+ />
226
365
  </FSRow>
227
- <FSToggleSet v-if="innerRowsPerPage !== -1"
366
+ <FSToggleSet
367
+ v-if="innerRowsPerPage !== -1"
228
368
  class="fs-data-table-pagination"
229
369
  variant="slide"
230
370
  :dash="pageOptions.length > 8"
231
371
  :values="pageOptions"
232
372
  :required="true"
233
- v-model="innerPage" />
373
+ v-model="innerPage"
374
+ />
234
375
  </FSRow>
235
376
  </template>
236
- <template v-for="(_, name) in innerSlots"
237
- #[name]="props">
238
- <slot :name="name"
239
- v-bind="props" />
377
+ <template
378
+ v-for="(_, name) in innerSlots"
379
+ #[name]="props"
380
+ >
381
+ <slot
382
+ :name="name"
383
+ v-bind="props"
384
+ />
240
385
  </template>
241
386
  </v-data-table>
242
- <v-data-iterator v-else
387
+ <v-data-iterator
388
+ v-else
243
389
  class="fs-data-table-iterator"
244
390
  :items="innerItems"
245
391
  :page="innerPage"
246
- :itemsPerPage="innerRowsPerPage">
247
- <template #default="{ items }">
248
- <FSCol class="fs-data-iterator-container"
249
- width="fill">
250
- <FSDraggable v-for="(item, index) in items"
392
+ :itemsPerPage="innerRowsPerPage"
393
+ >
394
+ <template
395
+ #default="{ items }"
396
+ >
397
+ <FSCol
398
+ class="fs-data-iterator-container"
399
+ width="fill"
400
+ >
401
+ <FSDraggable
402
+ v-for="(item, index) in items"
251
403
  elementSelector=".fs-draggable-item"
252
404
  :disabled="draggableDisabled"
253
405
  :item="item"
@@ -256,10 +408,14 @@
256
408
  @dragover="(event) => onDragOver(event, '.fs-draggable-item', '.fs-data-iterator-container')"
257
409
  @drop="(event) => onDrop(event, item, '.fs-draggable-item')"
258
410
  @dragleave="onDragLeave"
259
- @dragover.prevent>
260
- <slot name="item.iterator"
261
- v-bind="{ item, index }">
262
- <FSDataIteratorItem v-if="item.type === 'item'"
411
+ @dragover.prevent
412
+ >
413
+ <slot
414
+ name="item.iterator"
415
+ v-bind="{ item, index }"
416
+ >
417
+ <FSDataIteratorItem
418
+ v-if="item.type === 'item'"
263
419
  :itemColor="$props.rowColor ? $props.rowColor(item.raw) : ColorEnum.Background"
264
420
  :headers="innerHeaders.filter(h => !$props.sneakyHeaders.includes(h.value))"
265
421
  :showSelect="$props.showSelect"
@@ -268,38 +424,65 @@
268
424
  :item="item.raw"
269
425
  :key="index"
270
426
  :modelValue="innerValue.includes(item.raw[$props.itemValue])"
271
- @update:modelValue="toggleSelect">
272
- <template #item.top="props">
273
- <slot name="item.top"
274
- v-bind="props" />
427
+ @update:modelValue="toggleSelect"
428
+ >
429
+ <template
430
+ #item.top="props"
431
+ >
432
+ <slot
433
+ name="item.top"
434
+ v-bind="props"
435
+ />
275
436
  </template>
276
- <template v-for="(item, index) in itemsSlots"
277
- #[item.slotName]="props">
278
- <slot :name="item.slotName"
279
- v-bind="props">
280
- <FSSpan font="text-overline">
437
+ <template
438
+ v-for="item in itemsSlots"
439
+ #[item.slotName]="props"
440
+ >
441
+ <slot
442
+ :name="item.slotName"
443
+ v-bind="props"
444
+ >
445
+ <FSSpan
446
+ font="text-overline"
447
+ >
281
448
  {{ props.item[item.value] }}
282
449
  </FSSpan>
283
450
  </slot>
284
451
  </template>
285
- <template #item.bottom="props">
286
- <slot name="item.bottom"
287
- v-bind="props" />
452
+ <template
453
+ #item.bottom="props"
454
+ >
455
+ <slot
456
+ name="item.bottom"
457
+ v-bind="props"
458
+ />
288
459
  </template>
289
460
  </FSDataIteratorItem>
290
461
  </slot>
291
462
  </FSDraggable>
292
463
  </FSCol>
293
464
  </template>
294
- <template #footer>
295
- <FSRow class="fs-data-table-footer"
465
+ <template
466
+ #footer
467
+ >
468
+ <FSRow
469
+ class="fs-data-table-footer"
296
470
  align="center-right"
297
471
  padding="16px"
298
- gap="24px">
299
- <template v-if="$props.modelValue.length">
300
- <template v-if="$props.modelValue.length >= innerItems.length">
301
- <FSRow gap="2px">
302
- <FSText font="text-button">
472
+ gap="24px"
473
+ >
474
+ <template
475
+ v-if="$props.modelValue.length"
476
+ >
477
+ <template
478
+ v-if="$props.modelValue.length >= innerItems.length"
479
+ >
480
+ <FSRow
481
+ gap="2px"
482
+ >
483
+ <FSText
484
+ font="text-button"
485
+ >
303
486
  {{ $tr("ui.data-table.all-selected-bold", "Warning:") }}
304
487
  </FSText>
305
488
  <FSText>
@@ -307,47 +490,67 @@
307
490
  </FSText>
308
491
  </FSRow>
309
492
  </template>
310
- <template v-else>
493
+ <template
494
+ v-else
495
+ >
311
496
  <FSText>
312
- {{ $tr("ui.data-table.some-selected", "{0} element(s) selected", $props.modelValue.length.toString())
313
- }}
497
+ {{ $tr("ui.data-table.some-selected", "{0} element(s) selected", $props.modelValue.length.toString()) }}
314
498
  </FSText>
315
499
  </template>
316
500
  </template>
317
501
  <v-spacer />
318
- <FSRow align="center-right"
319
- :wrap="false">
320
- <FSText font="text-overline">
502
+ <FSRow
503
+ align="center-right"
504
+ :wrap="false"
505
+ >
506
+ <FSText
507
+ font="text-overline"
508
+ >
321
509
  {{ $tr("ui.data-table.rows-per-page", "Rows per page") }}
322
510
  </FSText>
323
- <FSRow width="120px">
324
- <FSSelectField class="fs-data-table-rows-per-page"
511
+ <FSRow
512
+ width="120px"
513
+ >
514
+ <FSSelectField
515
+ class="fs-data-table-rows-per-page"
325
516
  :clearable="false"
326
517
  :hideHeader="true"
327
518
  :items="rowsPerPageOptions"
328
- v-model="innerRowsPerPage" />
519
+ v-model="innerRowsPerPage"
520
+ />
329
521
  </FSRow>
330
522
  </FSRow>
331
- <FSToggleSet v-if="innerRowsPerPage !== -1"
523
+ <FSToggleSet
524
+ v-if="innerRowsPerPage !== -1"
332
525
  class="fs-data-table-pagination"
333
526
  variant="slide"
334
527
  :dash="pageOptions.length > 8"
335
528
  :values="pageOptions"
336
529
  :required="true"
337
- v-model="innerPage" />
530
+ v-model="innerPage"
531
+ />
338
532
  </FSRow>
339
533
  </template>
340
534
  </v-data-iterator>
341
535
  </template>
342
- <template v-else>
343
- <v-data-iterator class="fs-data-table-iterator"
536
+ <template
537
+ v-else
538
+ >
539
+ <v-data-iterator
540
+ class="fs-data-table-iterator"
344
541
  :items="innerItems"
345
- :itemsPerPage="size">
346
- <template #default="{ items }">
347
- <FSRow width="hug"
542
+ :itemsPerPage="size"
543
+ >
544
+ <template
545
+ #default="{ items }"
546
+ >
547
+ <FSRow
548
+ width="hug"
348
549
  class="fs-data-iterator-container"
349
- :gap="$props.tileGap">
350
- <FSDraggable v-for="(item, index) in items.filter((item) => item.type === 'item')"
550
+ :gap="$props.tileGap"
551
+ >
552
+ <FSDraggable
553
+ v-for="(item, index) in items.filter((item) => item.type === 'item')"
351
554
  elementSelector=".fs-draggable-item"
352
555
  :disabled="draggableDisabled"
353
556
  :item="item"
@@ -356,10 +559,14 @@
356
559
  @dragover="(event) => onDragOver(event, '.fs-draggable-item', '.fs-data-iterator-container')"
357
560
  @drop="(event) => onDrop(event, item, '.fs-draggable-item')"
358
561
  @dragleave="onDragLeave"
359
- @dragover.prevent>
360
- <slot name="item.tile"
361
- v-bind="{ index, item: item.raw, toggleSelect }">
362
- <FSDataIteratorItem :itemColor="$props.rowColor ? $props.rowColor(item.raw) : ColorEnum.Background"
562
+ @dragover.prevent
563
+ >
564
+ <slot
565
+ name="item.tile"
566
+ v-bind="{ index, item: item.raw, toggleSelect }"
567
+ >
568
+ <FSDataIteratorItem
569
+ :itemColor="$props.rowColor ? $props.rowColor(item.raw) : ColorEnum.Background"
363
570
  :headers="innerHeaders.filter(h => !$props.sneakyHeaders.includes(h.value))"
364
571
  :showSelect="$props.showSelect"
365
572
  :itemTo="$props.itemTo"
@@ -367,23 +574,38 @@
367
574
  :item="item.raw"
368
575
  :key="index"
369
576
  :modelValue="innerValue.includes(item.raw[$props.itemValue])"
370
- @update:modelValue="toggleSelect">
371
- <template #item.top="props">
372
- <slot name="item.top"
373
- v-bind="props" />
577
+ @update:modelValue="toggleSelect"
578
+ >
579
+ <template
580
+ #item.top="props"
581
+ >
582
+ <slot
583
+ name="item.top"
584
+ v-bind="props"
585
+ />
374
586
  </template>
375
- <template v-for="(item, index) in itemsSlots"
376
- #[item.slotName]="props">
377
- <slot :name="item.slotName"
378
- v-bind="props">
379
- <FSSpan font="text-overline">
587
+ <template
588
+ v-for="item in itemsSlots"
589
+ #[item.slotName]="props"
590
+ >
591
+ <slot
592
+ :name="item.slotName"
593
+ v-bind="props"
594
+ >
595
+ <FSSpan
596
+ font="text-overline"
597
+ >
380
598
  {{ props.item[item.value] }}
381
599
  </FSSpan>
382
600
  </slot>
383
601
  </template>
384
- <template #item.bottom="props">
385
- <slot name="item.bottom"
386
- v-bind="props" />
602
+ <template
603
+ #item.bottom="props"
604
+ >
605
+ <slot
606
+ name="item.bottom"
607
+ v-bind="props"
608
+ />
387
609
  </template>
388
610
  </FSDataIteratorItem>
389
611
  </slot>
@@ -392,12 +614,14 @@
392
614
  </template>
393
615
  </v-data-iterator>
394
616
  </template>
395
- <div class="fs-data-table-intersection" />
617
+ <div
618
+ class="fs-data-table-intersection"
619
+ />
396
620
  </FSCol>
397
621
  </template>
398
622
 
399
623
  <script lang="ts">
400
- import { computed, defineComponent, getCurrentInstance, onMounted, onUnmounted, PropType, ref, Slot, watch } from "vue";
624
+ import { computed, defineComponent, getCurrentInstance, onMounted, onUnmounted, PropType, ref, Ref, Slot, watch } from "vue";
401
625
  import { useRouter } from "vue-router";
402
626
 
403
627
  import { ColorEnum, FSDataTableColumn, FSDataTableFilter, FSDataTableOrder, FSToggle } from "@dative-gpi/foundation-shared-components/models";
@@ -585,12 +809,12 @@ export default defineComponent({
585
809
  const lights = getColors(ColorEnum.Light);
586
810
 
587
811
  const filters = ref<{ [key: string]: FSDataTableFilter[] }>({});
812
+ const innerSearch: Ref<string | null> = ref(null);
588
813
  const innerRowsPerPage = ref(props.rowsPerPage);
589
814
  const innerValue = ref(props.modelValue);
590
815
  const innerSortBy = ref(props.sortBy);
591
816
  const innerMode = ref(props.mode);
592
817
  const innerPage = ref(props.page);
593
- const innerSearch = ref(null);
594
818
  const showFilters = ref(true);
595
819
  const resetable = ref(false);
596
820
 
@@ -634,14 +858,14 @@ export default defineComponent({
634
858
  delete slots[filterSlot(header)];
635
859
  }
636
860
  for (const header of headersSlots.value) {
637
- delete slots[header.slotName];
861
+ delete slots[header.slotName!];
638
862
  delete slots[header.slotName + "-prepend"];
639
863
  delete slots[header.slotName + "-title"];
640
864
  delete slots[header.slotName + "-append"];
641
865
  delete slots[header.slotName + "-configuration"];
642
866
  }
643
867
  for (const item of itemsSlots.value) {
644
- delete slots[item.slotName];
868
+ delete slots[item.slotName!];
645
869
  }
646
870
  return slots;
647
871
  });
@@ -710,7 +934,7 @@ export default defineComponent({
710
934
  const innerItems = computed((): any[] => {
711
935
  const activeFilters: { key: string, filter: FSDataTableFilter }[] = Object.keys(filters.value).reduce((acc, key) => {
712
936
  return acc.concat(filters.value[key].filter((filter) => filter.hidden).map((filter) => ({ key, filter })));
713
- }, []);
937
+ }, [] as { key: string, filter: FSDataTableFilter }[]);
714
938
  if (props.items && props.items.length) {
715
939
  return props.items.filter((item) => {
716
940
  if (props.selectedOnly && !innerValue.value.includes(item[props.itemValue])) {
@@ -721,7 +945,7 @@ export default defineComponent({
721
945
  return false;
722
946
  }
723
947
  }
724
- if (activeFilters.some(af => af.filter.filter(af.filter.value, item[af.key], item))) {
948
+ if (activeFilters.some(af => af.filter.filter && af.filter.filter(af.filter.value, item[af.key], item))) {
725
949
  return false;
726
950
  }
727
951
  return true;
@@ -800,6 +1024,16 @@ export default defineComponent({
800
1024
  emit("update:modelValue", innerValue.value);
801
1025
  };
802
1026
 
1027
+ const toggleSelectGroup = (group: any): void => {
1028
+ if (group.items.every((item: any) => innerValue.value.includes(item.key))) {
1029
+ innerValue.value = innerValue.value.filter((id) => !group.items.some((item: any) => item.key === id));
1030
+ }
1031
+ else {
1032
+ innerValue.value = [...new Set(innerValue.value.concat(group.items.map((item: any) => item.key)))];
1033
+ }
1034
+ emit("update:modelValue", innerValue.value);
1035
+ };
1036
+
803
1037
  const toggleSelect = (item: any): void => {
804
1038
  const index = innerValue.value.indexOf(item[props.itemValue]);
805
1039
  if (index > -1) {
@@ -947,7 +1181,7 @@ export default defineComponent({
947
1181
  switch (innerMode.value) {
948
1182
  case "table":
949
1183
  if (intersectionObserver.value && document.querySelector(".fs-data-table-intersection")) {
950
- intersectionObserver.value.unobserve(document.querySelector(".fs-data-table-intersection"));
1184
+ intersectionObserver.value.unobserve(document.querySelector(".fs-data-table-intersection")!);
951
1185
  }
952
1186
  return;
953
1187
  case "iterator":
@@ -963,7 +1197,7 @@ export default defineComponent({
963
1197
  }, { threshold: [0.9] });
964
1198
  }
965
1199
  if (document.querySelector(".fs-data-table-intersection")) {
966
- intersectionObserver.value.observe(document.querySelector(".fs-data-table-intersection"));
1200
+ intersectionObserver.value.observe(document.querySelector(".fs-data-table-intersection")!);
967
1201
  }
968
1202
  return;
969
1203
  }
@@ -1012,6 +1246,7 @@ export default defineComponent({
1012
1246
 
1013
1247
  if (dragged != null) {
1014
1248
  const target = (event.target as HTMLElement)?.closest(elementSelector);
1249
+ dragged.classList.remove("fs-draggable-dragging-grabbegin");
1015
1250
 
1016
1251
  if (target != null && (target !== dragged || (props.sortDraggable && props.includeDraggable))) {
1017
1252
  if (props.includeDraggable) {
@@ -1033,7 +1268,7 @@ export default defineComponent({
1033
1268
  else if (dragged?.getAttribute("data-initial-index") !== null) {
1034
1269
  target.classList.add("fs-dropzone-include");
1035
1270
  const tbodyElement = (event.target as HTMLElement)?.closest(elementContainerSelector) as HTMLElement;
1036
- resetRowIndex(+dragged?.getAttribute('data-initial-index'), Array.from(tbodyElement.children).indexOf(dragged), dragged, tbodyElement);
1271
+ resetRowIndex(+dragged?.getAttribute('data-initial-index')!, Array.from(tbodyElement.children).indexOf(dragged), dragged, tbodyElement);
1037
1272
  }
1038
1273
  }
1039
1274
  }
@@ -1087,11 +1322,11 @@ export default defineComponent({
1087
1322
  };
1088
1323
 
1089
1324
  const onDrop = (event: DragEvent, row: any, elementSelector: string) => {
1090
- const draggedElement = document.querySelector(".fs-draggable-dragging");
1325
+ const draggedElement = document.querySelector(".fs-draggable-dragging") as HTMLElement;
1091
1326
 
1092
1327
  if (draggedElement != null) {
1093
1328
  const target = (event.target as HTMLElement)?.closest(elementSelector);
1094
- const draggedData = JSON.parse(event.dataTransfer?.getData("text/plain") ?? "");
1329
+ const draggedData = JSON.parse(event.dataTransfer?.getData("text/plain") ?? draggedElement.dataset.item ?? '{}');
1095
1330
  const itemsData = draggedData.item ?? draggedData.raw;
1096
1331
  const rowData = row.item ?? row.raw;
1097
1332
 
@@ -1172,6 +1407,7 @@ export default defineComponent({
1172
1407
  isExtraSmall,
1173
1408
  draggableDisabled,
1174
1409
  toggleSelectAll,
1410
+ toggleSelectGroup,
1175
1411
  toggleSelect,
1176
1412
  updateHeader,
1177
1413
  toggleFilter,