@dative-gpi/foundation-shared-components 0.0.87 → 0.0.89

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 +61 -72
  14. package/components/FSOptionItem.vue +22 -7
  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 +433 -181
  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,48 +1,96 @@
1
1
  <template>
2
- <FSCol gap="16px">
3
- <FSRow align="bottom-center">
4
- <template v-if="$props.showSearch">
5
- <FSSearchField prependInnerIcon="mdi-magnify"
2
+ <FSCol
3
+ gap="16px"
4
+ >
5
+ <FSRow
6
+ align="bottom-center"
7
+ :wrap="isExtraSmall ? false : true"
8
+ width="fill"
9
+ >
10
+ <template
11
+ v-if="$props.showSearch"
12
+ >
13
+ <FSSearchField
14
+ prependInnerIcon="mdi-magnify"
6
15
  :hideHeader="true"
7
- v-model="innerSearch" />
8
- <FSButton v-if="filterableHeaders.length > 0"
16
+ v-model="innerSearch"
17
+ />
18
+ <FSButton
19
+ v-if="filterableHeaders.length > 0"
9
20
  prependIcon="mdi-filter-variant"
10
21
  :variant="showFilters ? 'full' : 'standard'"
11
- @click="showFilters = !showFilters" />
22
+ @click="showFilters = !showFilters"
23
+ />
12
24
  </template>
13
- <slot name="toolbar" />
25
+ <slot
26
+ v-if="!isExtraSmall"
27
+ name="toolbar"
28
+ />
14
29
  <v-spacer />
15
- <FSOptionGroup v-if="!$props.disableTable && !$props.disableIterator"
16
- :values="modeOptions"
17
- :required="true"
18
- v-model="innerMode" />
30
+ <FSRow
31
+ v-if="!$props.disableTable && !$props.disableIterator"
32
+ align="center-right"
33
+ >
34
+ <FSOptionGroup
35
+ :values="modeOptions"
36
+ :singleColor="true"
37
+ :required="true"
38
+ v-model="innerMode"
39
+ />
40
+ </FSRow>
19
41
  </FSRow>
20
- <FSRow v-if="showFiltersRow">
21
- <template v-if="showFilters">
22
- <FSFilterButton v-for="(header, index) in filterableHeaders"
42
+ <FSRow
43
+ v-if="isExtraSmall && hasToolbar"
44
+ >
45
+ <FSWrapGroup>
46
+ <slot
47
+ name="toolbar"
48
+ />
49
+ </FSWrapGroup>
50
+ </FSRow>
51
+ <FSRow
52
+ v-if="showFiltersRow"
53
+ >
54
+ <template
55
+ v-if="showFilters"
56
+ >
57
+ <FSFilterButton
58
+ v-for="(header, index) in filterableHeaders"
23
59
  :key="index"
24
60
  :header="header"
25
61
  :filters="filters[header.value]"
26
- @update:filter="(value) => toggleFilter(header.value, value)">
27
- <template #default="{ filter }">
28
- <slot :name="filterSlot(header)"
29
- 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
+ />
30
71
  </template>
31
72
  </FSFilterButton>
32
- <FSChip v-if="resetable"
73
+ <FSChip
74
+ v-if="resetable"
33
75
  variant="standard"
34
76
  :label="$tr('ui.data-table.reset-filters', 'Reset')"
35
77
  :color="ColorEnum.Error"
36
78
  :editable="true"
37
- @click="resetFilter" />
79
+ @click="resetFilter"
80
+ />
38
81
  </template>
39
- <FSHiddenButton v-if="innerMode === 'table' && hiddenHeaders.length > 0"
82
+ <FSHiddenButton
83
+ v-if="innerMode === 'table' && hiddenHeaders.length > 0"
40
84
  :headers="hiddenHeaders"
41
85
  :color="$props.color"
42
- @update:show="(value) => updateHeader(value, 'hidden', false)" />
86
+ @update:show="(value) => updateHeader(value, 'hidden', false)"
87
+ />
43
88
  </FSRow>
44
- <template v-if="innerMode === 'table'">
45
- <v-data-table v-if="!isExtraSmall"
89
+ <template
90
+ v-if="innerMode === 'table'"
91
+ >
92
+ <v-data-table
93
+ v-if="!isExtraSmall"
46
94
  :selectStrategy="$props.singleSelect ? 'single' : 'all'"
47
95
  :itemValue="$props.itemValue"
48
96
  :showSelect="$props.showSelect"
@@ -65,66 +113,121 @@
65
113
  @dragover.prevent
66
114
  @drop:row="(event, row) => onDrop(event, row, 'tr.v-data-table__tr')"
67
115
  @dragover="onDragOver($event, 'tr.v-data-table__tr', 'tbody')"
68
- @dragleave="onDragLeave">
69
- <template #no-data>
70
- <FSText font="text-overline">
116
+ @dragleave="onDragLeave"
117
+ >
118
+ <template
119
+ #no-data
120
+ >
121
+ <FSText
122
+ font="text-overline"
123
+ >
71
124
  {{ $tr("ui.data-table.empty", "No data") }}
72
125
  </FSText>
73
126
  </template>
74
- <template #header.data-table-select="props">
75
- <FSRow v-if="!$props.singleSelect"
127
+ <template
128
+ #header.data-table-select="props"
129
+ >
130
+ <FSRow
131
+ v-if="!$props.singleSelect"
76
132
  class="fs-data-table-select"
77
133
  align="bottom-center"
78
- width="hug">
79
- <FSCheckbox :indeterminate="props.someSelected && !props.allSelected"
134
+ width="hug"
135
+ >
136
+ <FSCheckbox
137
+ :indeterminate="props.someSelected && !props.allSelected"
80
138
  :modelValue="props.allSelected"
81
- @update:modelValue="toggleSelectAll(props.allSelected)" />
139
+ @update:modelValue="toggleSelectAll(props.allSelected)"
140
+ />
82
141
  </FSRow>
83
142
  </template>
84
- <template #item.data-table-select="props">
85
- <FSRow class="fs-data-table-select"
143
+ <template
144
+ #item.data-table-select="props"
145
+ >
146
+ <FSRow
147
+ class="fs-data-table-select"
86
148
  align="bottom-center"
87
- width="hug">
88
- <FSCheckbox :modelValue="innerValue.includes(props.item[$props.itemValue])"
89
- @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
+ />
90
155
  </FSRow>
91
156
  </template>
92
- <template #item.data-table-draggable="props">
93
- <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"
94
162
  :disabled="draggableDisabled"
95
163
  :item="props"
96
- @update:dragend="(event, dragged) => onDragEnd(event, dragged, 'tbody')">
97
- <FSRow class="fs-data-table-draggable"
164
+ @update:dragend="(event, dragged) => onDragEnd(event, dragged, 'tbody')"
165
+ >
166
+ <FSRow
167
+ class="fs-data-table-draggable"
98
168
  align="bottom-center"
99
- width="hug">
100
- <FSIcon size="l">
169
+ width="hug"
170
+ >
171
+ <FSIcon
172
+ size="l"
173
+ >
101
174
  mdi-drag-vertical
102
175
  </FSIcon>
103
176
  </FSRow>
104
177
  </FSDraggable>
105
178
  </template>
106
- <template #header.data-table-group="props">
107
- <slot name="header.data-table-group"
108
- 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
+ />
109
186
  </template>
110
- <template #item.data-table-group="props">
111
- <slot name="item.data-table-group"
112
- 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
+ />
113
194
  </template>
114
- <template #group-header="props">
115
- <template :ref="() => { if (!props.isGroupOpen(props.item)) { props.toggleGroup(props.item) } }" />
116
- <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
+ >
117
204
  <td />
118
- <td class="fs-data-table-group-header"
119
- :colspan="extraHeaders.concat(innerHeaders).length + 1">
120
- <slot name="group-header"
121
- v-bind="props">
122
- <FSCard padding="12px 16px">
123
- <FSRow align="center-left"
124
- 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
+ />
125
226
  <FSText>
126
- <slot name="group-header-title"
127
- v-bind="props">
227
+ <slot
228
+ name="group-header-title"
229
+ v-bind="props"
230
+ >
128
231
  {{ props.item.value }}
129
232
  </slot>
130
233
  </FSText>
@@ -134,58 +237,98 @@
134
237
  </td>
135
238
  </tr>
136
239
  </template>
137
- <template v-for="(header, index) in headersSlots"
138
- #[header.slotName]="props">
139
- <slot :name="header.slotName"
140
- v-bind="props">
141
- <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"
142
250
  :wrap="false"
143
- :key="index">
144
- <slot :name="`${header.slotName}-prepend`" />
145
- <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
+ >
146
259
  <FSText>
147
260
  {{ header.text }}
148
261
  </FSText>
149
262
  </slot>
150
- <slot :name="`${header.slotName}-append`" />
263
+ <slot
264
+ :name="`${header.slotName}-append`"
265
+ />
151
266
  <v-spacer />
152
- <slot :name="`${header.slotName}-configuration`">
153
- <FSHeaderButton :first="index === 0"
267
+ <slot
268
+ :name="`${header.slotName}-configuration`"
269
+ >
270
+ <FSHeaderButton
271
+ :first="index === 0"
154
272
  :last="index === headersSlots.length - 1"
155
273
  @update:hide="updateHeader(header, 'hidden', !header.hidden)"
156
274
  @update:left="updateHeader(header, 'index', -1)"
157
- @update:right="updateHeader(header, 'index', 1)" />
158
- <FSButton v-if="header.sortable"
275
+ @update:right="updateHeader(header, 'index', 1)"
276
+ />
277
+ <FSButton
278
+ v-if="header.sortable"
159
279
  variant="icon"
160
280
  :color="sortColor(header, props)"
161
- :icon="sortIcon(header, props)" />
281
+ :icon="sortIcon(header, props)"
282
+ />
162
283
  </slot>
163
284
  </FSRow>
164
285
  </slot>
165
286
  </template>
166
- <template v-for="(item, index) in itemsSlots"
167
- #[item.slotName]="props">
168
- <div class="fs-td-color">
169
- <slot :name="item.slotName"
170
- v-bind="props">
171
- <FSRow align="center-left"
172
- :key="index">
173
- <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
+ >
174
305
  {{ props.item[item.value] }}
175
306
  </FSSpan>
176
307
  </FSRow>
177
308
  </slot>
178
309
  </div>
179
310
  </template>
180
- <template #bottom>
181
- <FSRow class="fs-data-table-footer"
311
+ <template
312
+ #bottom
313
+ >
314
+ <FSRow
315
+ class="fs-data-table-footer"
182
316
  align="center-right"
183
317
  padding="16px"
184
- gap="24px">
185
- <template v-if="$props.modelValue.length">
186
- <template v-if="$props.modelValue.length >= innerItems.length">
187
- <FSRow gap="2px">
188
- <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
+ >
189
332
  {{ $tr("ui.data-table.all-selected-bold", "Warning:") }}
190
333
  </FSText>
191
334
  <FSText>
@@ -193,50 +336,70 @@
193
336
  </FSText>
194
337
  </FSRow>
195
338
  </template>
196
- <template v-else>
339
+ <template
340
+ v-else
341
+ >
197
342
  <FSText>
198
- {{ $tr("ui.data-table.some-selected", "{0} element(s) selected", $props.modelValue.length.toString())
199
- }}
343
+ {{ $tr("ui.data-table.some-selected", "{0} element(s) selected", $props.modelValue.length.toString()) }}
200
344
  </FSText>
201
345
  </template>
202
346
  </template>
203
347
  <v-spacer />
204
- <FSRow align="center-right"
348
+ <FSRow
349
+ align="center-right"
205
350
  width="hug"
206
- :wrap="false">
207
- <FSText font="text-overline">
351
+ :wrap="false"
352
+ >
353
+ <FSText
354
+ font="text-overline"
355
+ >
208
356
  {{ $tr("ui.data-table.rows-per-page", "Rows per page") }}
209
357
  </FSText>
210
- <FSSelectField class="fs-data-table-rows-per-page"
358
+ <FSSelectField
359
+ class="fs-data-table-rows-per-page"
211
360
  :clearable="false"
212
361
  :hideHeader="true"
213
362
  :items="rowsPerPageOptions"
214
- v-model="innerRowsPerPage" />
363
+ v-model="innerRowsPerPage"
364
+ />
215
365
  </FSRow>
216
- <FSToggleSet v-if="innerRowsPerPage !== -1"
366
+ <FSToggleSet
367
+ v-if="innerRowsPerPage !== -1"
217
368
  class="fs-data-table-pagination"
218
369
  variant="slide"
219
370
  :dash="pageOptions.length > 8"
220
371
  :values="pageOptions"
221
372
  :required="true"
222
- v-model="innerPage" />
373
+ v-model="innerPage"
374
+ />
223
375
  </FSRow>
224
376
  </template>
225
- <template v-for="(_, name) in innerSlots"
226
- #[name]="props">
227
- <slot :name="name"
228
- 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
+ />
229
385
  </template>
230
386
  </v-data-table>
231
- <v-data-iterator v-else
387
+ <v-data-iterator
388
+ v-else
232
389
  class="fs-data-table-iterator"
233
390
  :items="innerItems"
234
391
  :page="innerPage"
235
- :itemsPerPage="innerRowsPerPage">
236
- <template #default="{ items }">
237
- <FSCol class="fs-data-iterator-container"
238
- width="fill">
239
- <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"
240
403
  elementSelector=".fs-draggable-item"
241
404
  :disabled="draggableDisabled"
242
405
  :item="item"
@@ -245,10 +408,14 @@
245
408
  @dragover="(event) => onDragOver(event, '.fs-draggable-item', '.fs-data-iterator-container')"
246
409
  @drop="(event) => onDrop(event, item, '.fs-draggable-item')"
247
410
  @dragleave="onDragLeave"
248
- @dragover.prevent>
249
- <slot name="item.iterator"
250
- v-bind="{ item, index }">
251
- <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'"
252
419
  :itemColor="$props.rowColor ? $props.rowColor(item.raw) : ColorEnum.Background"
253
420
  :headers="innerHeaders.filter(h => !$props.sneakyHeaders.includes(h.value))"
254
421
  :showSelect="$props.showSelect"
@@ -257,38 +424,65 @@
257
424
  :item="item.raw"
258
425
  :key="index"
259
426
  :modelValue="innerValue.includes(item.raw[$props.itemValue])"
260
- @update:modelValue="toggleSelect">
261
- <template #item.top="props">
262
- <slot name="item.top"
263
- 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
+ />
264
436
  </template>
265
- <template v-for="(item, index) in itemsSlots"
266
- #[item.slotName]="props">
267
- <slot :name="item.slotName"
268
- v-bind="props">
269
- <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
+ >
270
448
  {{ props.item[item.value] }}
271
449
  </FSSpan>
272
450
  </slot>
273
451
  </template>
274
- <template #item.bottom="props">
275
- <slot name="item.bottom"
276
- v-bind="props" />
452
+ <template
453
+ #item.bottom="props"
454
+ >
455
+ <slot
456
+ name="item.bottom"
457
+ v-bind="props"
458
+ />
277
459
  </template>
278
460
  </FSDataIteratorItem>
279
461
  </slot>
280
462
  </FSDraggable>
281
463
  </FSCol>
282
464
  </template>
283
- <template #footer>
284
- <FSRow class="fs-data-table-footer"
465
+ <template
466
+ #footer
467
+ >
468
+ <FSRow
469
+ class="fs-data-table-footer"
285
470
  align="center-right"
286
471
  padding="16px"
287
- gap="24px">
288
- <template v-if="$props.modelValue.length">
289
- <template v-if="$props.modelValue.length >= innerItems.length">
290
- <FSRow gap="2px">
291
- <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
+ >
292
486
  {{ $tr("ui.data-table.all-selected-bold", "Warning:") }}
293
487
  </FSText>
294
488
  <FSText>
@@ -296,47 +490,67 @@
296
490
  </FSText>
297
491
  </FSRow>
298
492
  </template>
299
- <template v-else>
493
+ <template
494
+ v-else
495
+ >
300
496
  <FSText>
301
- {{ $tr("ui.data-table.some-selected", "{0} element(s) selected", $props.modelValue.length.toString())
302
- }}
497
+ {{ $tr("ui.data-table.some-selected", "{0} element(s) selected", $props.modelValue.length.toString()) }}
303
498
  </FSText>
304
499
  </template>
305
500
  </template>
306
501
  <v-spacer />
307
- <FSRow align="center-right"
308
- :wrap="false">
309
- <FSText font="text-overline">
502
+ <FSRow
503
+ align="center-right"
504
+ :wrap="false"
505
+ >
506
+ <FSText
507
+ font="text-overline"
508
+ >
310
509
  {{ $tr("ui.data-table.rows-per-page", "Rows per page") }}
311
510
  </FSText>
312
- <FSRow width="120px">
313
- <FSSelectField class="fs-data-table-rows-per-page"
511
+ <FSRow
512
+ width="120px"
513
+ >
514
+ <FSSelectField
515
+ class="fs-data-table-rows-per-page"
314
516
  :clearable="false"
315
517
  :hideHeader="true"
316
518
  :items="rowsPerPageOptions"
317
- v-model="innerRowsPerPage" />
519
+ v-model="innerRowsPerPage"
520
+ />
318
521
  </FSRow>
319
522
  </FSRow>
320
- <FSToggleSet v-if="innerRowsPerPage !== -1"
523
+ <FSToggleSet
524
+ v-if="innerRowsPerPage !== -1"
321
525
  class="fs-data-table-pagination"
322
526
  variant="slide"
323
527
  :dash="pageOptions.length > 8"
324
528
  :values="pageOptions"
325
529
  :required="true"
326
- v-model="innerPage" />
530
+ v-model="innerPage"
531
+ />
327
532
  </FSRow>
328
533
  </template>
329
534
  </v-data-iterator>
330
535
  </template>
331
- <template v-else>
332
- <v-data-iterator class="fs-data-table-iterator"
536
+ <template
537
+ v-else
538
+ >
539
+ <v-data-iterator
540
+ class="fs-data-table-iterator"
333
541
  :items="innerItems"
334
- :itemsPerPage="size">
335
- <template #default="{ items }">
336
- <FSRow width="hug"
542
+ :itemsPerPage="size"
543
+ >
544
+ <template
545
+ #default="{ items }"
546
+ >
547
+ <FSRow
548
+ width="hug"
337
549
  class="fs-data-iterator-container"
338
- :gap="$props.tileGap">
339
- <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')"
340
554
  elementSelector=".fs-draggable-item"
341
555
  :disabled="draggableDisabled"
342
556
  :item="item"
@@ -345,10 +559,14 @@
345
559
  @dragover="(event) => onDragOver(event, '.fs-draggable-item', '.fs-data-iterator-container')"
346
560
  @drop="(event) => onDrop(event, item, '.fs-draggable-item')"
347
561
  @dragleave="onDragLeave"
348
- @dragover.prevent>
349
- <slot name="item.tile"
350
- v-bind="{ index, item: item.raw, toggleSelect }">
351
- <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"
352
570
  :headers="innerHeaders.filter(h => !$props.sneakyHeaders.includes(h.value))"
353
571
  :showSelect="$props.showSelect"
354
572
  :itemTo="$props.itemTo"
@@ -356,23 +574,38 @@
356
574
  :item="item.raw"
357
575
  :key="index"
358
576
  :modelValue="innerValue.includes(item.raw[$props.itemValue])"
359
- @update:modelValue="toggleSelect">
360
- <template #item.top="props">
361
- <slot name="item.top"
362
- 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
+ />
363
586
  </template>
364
- <template v-for="(item, index) in itemsSlots"
365
- #[item.slotName]="props">
366
- <slot :name="item.slotName"
367
- v-bind="props">
368
- <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
+ >
369
598
  {{ props.item[item.value] }}
370
599
  </FSSpan>
371
600
  </slot>
372
601
  </template>
373
- <template #item.bottom="props">
374
- <slot name="item.bottom"
375
- v-bind="props" />
602
+ <template
603
+ #item.bottom="props"
604
+ >
605
+ <slot
606
+ name="item.bottom"
607
+ v-bind="props"
608
+ />
376
609
  </template>
377
610
  </FSDataIteratorItem>
378
611
  </slot>
@@ -381,12 +614,14 @@
381
614
  </template>
382
615
  </v-data-iterator>
383
616
  </template>
384
- <div class="fs-data-table-intersection" />
617
+ <div
618
+ class="fs-data-table-intersection"
619
+ />
385
620
  </FSCol>
386
621
  </template>
387
622
 
388
623
  <script lang="ts">
389
- 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";
390
625
  import { useRouter } from "vue-router";
391
626
 
392
627
  import { ColorEnum, FSDataTableColumn, FSDataTableFilter, FSDataTableOrder, FSToggle } from "@dative-gpi/foundation-shared-components/models";
@@ -574,12 +809,12 @@ export default defineComponent({
574
809
  const lights = getColors(ColorEnum.Light);
575
810
 
576
811
  const filters = ref<{ [key: string]: FSDataTableFilter[] }>({});
812
+ const innerSearch: Ref<string | null> = ref(null);
577
813
  const innerRowsPerPage = ref(props.rowsPerPage);
578
814
  const innerValue = ref(props.modelValue);
579
815
  const innerSortBy = ref(props.sortBy);
580
816
  const innerMode = ref(props.mode);
581
817
  const innerPage = ref(props.page);
582
- const innerSearch = ref(null);
583
818
  const showFilters = ref(true);
584
819
  const resetable = ref(false);
585
820
 
@@ -602,6 +837,10 @@ export default defineComponent({
602
837
  return (props.showSearch && showFilters.value && filterableHeaders.value.length > 0) || hiddenHeaders.value.length > 0;
603
838
  });
604
839
 
840
+ const hasToolbar = computed((): boolean => {
841
+ return !!useSlots().slots["toolbar"];
842
+ });
843
+
605
844
  const innerSlots = computed((): { [label: string]: Slot<any> } => {
606
845
  const slots = { ...useSlots().slots };
607
846
  delete slots["toolbar"];
@@ -619,21 +858,21 @@ export default defineComponent({
619
858
  delete slots[filterSlot(header)];
620
859
  }
621
860
  for (const header of headersSlots.value) {
622
- delete slots[header.slotName];
861
+ delete slots[header.slotName!];
623
862
  delete slots[header.slotName + "-prepend"];
624
863
  delete slots[header.slotName + "-title"];
625
864
  delete slots[header.slotName + "-append"];
626
865
  delete slots[header.slotName + "-configuration"];
627
866
  }
628
867
  for (const item of itemsSlots.value) {
629
- delete slots[item.slotName];
868
+ delete slots[item.slotName!];
630
869
  }
631
870
  return slots;
632
871
  });
633
872
 
634
873
  const style = computed((): { [key: string]: string | undefined } => {
635
874
  return {
636
- "--fs-data-table-background-color": backgrounds.light,
875
+ "--fs-data-table-background-color": backgrounds.base,
637
876
  "--fs-data-table-border-color": lights.base,
638
877
  "--fs-data-table-row-gap": sizeToVar(props.rowGap)
639
878
  };
@@ -695,7 +934,7 @@ export default defineComponent({
695
934
  const innerItems = computed((): any[] => {
696
935
  const activeFilters: { key: string, filter: FSDataTableFilter }[] = Object.keys(filters.value).reduce((acc, key) => {
697
936
  return acc.concat(filters.value[key].filter((filter) => filter.hidden).map((filter) => ({ key, filter })));
698
- }, []);
937
+ }, [] as { key: string, filter: FSDataTableFilter }[]);
699
938
  if (props.items && props.items.length) {
700
939
  return props.items.filter((item) => {
701
940
  if (props.selectedOnly && !innerValue.value.includes(item[props.itemValue])) {
@@ -706,7 +945,7 @@ export default defineComponent({
706
945
  return false;
707
946
  }
708
947
  }
709
- 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))) {
710
949
  return false;
711
950
  }
712
951
  return true;
@@ -785,6 +1024,16 @@ export default defineComponent({
785
1024
  emit("update:modelValue", innerValue.value);
786
1025
  };
787
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
+
788
1037
  const toggleSelect = (item: any): void => {
789
1038
  const index = innerValue.value.indexOf(item[props.itemValue]);
790
1039
  if (index > -1) {
@@ -932,7 +1181,7 @@ export default defineComponent({
932
1181
  switch (innerMode.value) {
933
1182
  case "table":
934
1183
  if (intersectionObserver.value && document.querySelector(".fs-data-table-intersection")) {
935
- intersectionObserver.value.unobserve(document.querySelector(".fs-data-table-intersection"));
1184
+ intersectionObserver.value.unobserve(document.querySelector(".fs-data-table-intersection")!);
936
1185
  }
937
1186
  return;
938
1187
  case "iterator":
@@ -948,7 +1197,7 @@ export default defineComponent({
948
1197
  }, { threshold: [0.9] });
949
1198
  }
950
1199
  if (document.querySelector(".fs-data-table-intersection")) {
951
- intersectionObserver.value.observe(document.querySelector(".fs-data-table-intersection"));
1200
+ intersectionObserver.value.observe(document.querySelector(".fs-data-table-intersection")!);
952
1201
  }
953
1202
  return;
954
1203
  }
@@ -997,6 +1246,7 @@ export default defineComponent({
997
1246
 
998
1247
  if (dragged != null) {
999
1248
  const target = (event.target as HTMLElement)?.closest(elementSelector);
1249
+ dragged.classList.remove("fs-draggable-dragging-grabbegin");
1000
1250
 
1001
1251
  if (target != null && (target !== dragged || (props.sortDraggable && props.includeDraggable))) {
1002
1252
  if (props.includeDraggable) {
@@ -1018,7 +1268,7 @@ export default defineComponent({
1018
1268
  else if (dragged?.getAttribute("data-initial-index") !== null) {
1019
1269
  target.classList.add("fs-dropzone-include");
1020
1270
  const tbodyElement = (event.target as HTMLElement)?.closest(elementContainerSelector) as HTMLElement;
1021
- 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);
1022
1272
  }
1023
1273
  }
1024
1274
  }
@@ -1072,11 +1322,11 @@ export default defineComponent({
1072
1322
  };
1073
1323
 
1074
1324
  const onDrop = (event: DragEvent, row: any, elementSelector: string) => {
1075
- const draggedElement = document.querySelector(".fs-draggable-dragging");
1325
+ const draggedElement = document.querySelector(".fs-draggable-dragging") as HTMLElement;
1076
1326
 
1077
1327
  if (draggedElement != null) {
1078
1328
  const target = (event.target as HTMLElement)?.closest(elementSelector);
1079
- const draggedData = JSON.parse(event.dataTransfer?.getData("text/plain") ?? "");
1329
+ const draggedData = JSON.parse(event.dataTransfer?.getData("text/plain") ?? draggedElement.dataset.item ?? '{}');
1080
1330
  const itemsData = draggedData.item ?? draggedData.raw;
1081
1331
  const rowData = row.item ?? row.raw;
1082
1332
 
@@ -1135,6 +1385,7 @@ export default defineComponent({
1135
1385
  innerMode,
1136
1386
  modeOptions,
1137
1387
  innerPage,
1388
+ hasToolbar,
1138
1389
  pageOptions,
1139
1390
  showFilters,
1140
1391
  showFiltersRow,
@@ -1156,6 +1407,7 @@ export default defineComponent({
1156
1407
  isExtraSmall,
1157
1408
  draggableDisabled,
1158
1409
  toggleSelectAll,
1410
+ toggleSelectGroup,
1159
1411
  toggleSelect,
1160
1412
  updateHeader,
1161
1413
  toggleFilter,