@dative-gpi/foundation-shared-components 0.0.40 → 0.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/fields/FSRichTextField.vue +24 -2
- package/components/lists/FSDataIteratorItem.vue +1 -1
- package/components/lists/FSDataTableUI.vue +319 -71
- package/components/lists/FSDraggable.vue +177 -0
- package/composables/useColors.ts +1 -1
- package/package.json +4 -4
- package/styles/components/fs_data_table.scss +1 -1
- package/styles/components/fs_draggable.scss +25 -0
- package/styles/components/index.scss +1 -0
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
import { $createParagraphNode, $getSelection, $isElementNode, $isRangeSelection, $setSelection, CAN_UNDO_COMMAND, createEditor, ElementNode, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, ParagraphNode, UNDO_COMMAND } from "lexical";
|
|
164
164
|
import { $createHeadingNode, HeadingNode, HeadingTagType, registerRichText } from "@lexical/rich-text";
|
|
165
165
|
import { createEmptyHistoryState, registerHistory } from "@lexical/history";
|
|
166
|
-
import { computed, defineComponent, onMounted, PropType, ref } from "vue";
|
|
166
|
+
import { computed, defineComponent, onMounted, PropType, ref, watch } from "vue";
|
|
167
167
|
import { $createLinkNode, $isLinkNode, LinkNode } from "@lexical/link";
|
|
168
168
|
import { $wrapNodes } from "@lexical/selection";
|
|
169
169
|
|
|
@@ -243,9 +243,11 @@ export default defineComponent({
|
|
|
243
243
|
const isStrikethrough = ref(false);
|
|
244
244
|
|
|
245
245
|
const id = `${Math.random()}-editor`;
|
|
246
|
+
const emptyState = "{\"root\":{\"children\":[{\"children\":[],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}";
|
|
246
247
|
|
|
247
|
-
const linkUrl = ref("https://");
|
|
248
248
|
|
|
249
|
+
const linkUrl = ref("https://");
|
|
250
|
+
|
|
249
251
|
const config = {
|
|
250
252
|
namespace: "MyEditor",
|
|
251
253
|
theme: {
|
|
@@ -285,6 +287,11 @@ export default defineComponent({
|
|
|
285
287
|
editor.setEditorState(editor.parseEditorState(props.modelValue));
|
|
286
288
|
});
|
|
287
289
|
}
|
|
290
|
+
else {
|
|
291
|
+
editor.update((): void => {
|
|
292
|
+
editor.setEditorState(editor.parseEditorState(emptyState));
|
|
293
|
+
});
|
|
294
|
+
}
|
|
288
295
|
});
|
|
289
296
|
|
|
290
297
|
const readonly = computed((): boolean => {
|
|
@@ -533,6 +540,21 @@ export default defineComponent({
|
|
|
533
540
|
isLink.value = false;
|
|
534
541
|
}
|
|
535
542
|
|
|
543
|
+
watch(() => props.modelValue, () => {
|
|
544
|
+
if (props.modelValue != JSON.stringify(editor.getEditorState().toJSON())) {
|
|
545
|
+
if (props.modelValue != null) {
|
|
546
|
+
editor.update(() => {
|
|
547
|
+
editor.setEditorState(editor.parseEditorState(props.modelValue));
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
editor.update(() => {
|
|
552
|
+
editor.setEditorState(editor.parseEditorState(emptyState));
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
|
|
536
558
|
return {
|
|
537
559
|
readonly,
|
|
538
560
|
style,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
/>
|
|
18
18
|
<slot name="toolbar" />
|
|
19
19
|
<v-spacer />
|
|
20
|
-
<
|
|
20
|
+
<FSOptionGroup
|
|
21
21
|
v-if="!$props.disableTable && !$props.disableIterator"
|
|
22
22
|
:values="modeOptions"
|
|
23
23
|
:required="true"
|
|
@@ -36,7 +36,10 @@
|
|
|
36
36
|
@update:filter="(value) => toggleFilter(header.value, value)"
|
|
37
37
|
>
|
|
38
38
|
<template #default="{ filter }">
|
|
39
|
-
<slot
|
|
39
|
+
<slot
|
|
40
|
+
:name="filterSlot(header)"
|
|
41
|
+
v-bind="{ filter }"
|
|
42
|
+
/>
|
|
40
43
|
</template>
|
|
41
44
|
</FSFilterButton>
|
|
42
45
|
<FSChip
|
|
@@ -68,7 +71,7 @@
|
|
|
68
71
|
:items="innerItems"
|
|
69
72
|
:fixedHeader="true"
|
|
70
73
|
:multiSort="false"
|
|
71
|
-
:hover="
|
|
74
|
+
:hover="!$props.sortDraggable"
|
|
72
75
|
:style="style"
|
|
73
76
|
:class="classes"
|
|
74
77
|
:page="innerPage"
|
|
@@ -77,6 +80,10 @@
|
|
|
77
80
|
@auxclick:row="onClickRow"
|
|
78
81
|
@click:row="onClickRow"
|
|
79
82
|
@update:sortBy="innerSortBy = $event ? $event[0] : null"
|
|
83
|
+
@dragover.prevent
|
|
84
|
+
@drop:row="(event, row) => onDrop(event, row, 'tr.v-data-table__tr')"
|
|
85
|
+
@dragover="onDragOver($event, 'tr.v-data-table__tr', 'tbody')"
|
|
86
|
+
@dragleave="onDragLeave"
|
|
80
87
|
>
|
|
81
88
|
<template #no-data>
|
|
82
89
|
<FSText
|
|
@@ -111,11 +118,37 @@
|
|
|
111
118
|
/>
|
|
112
119
|
</FSRow>
|
|
113
120
|
</template>
|
|
121
|
+
<template #[`item.data-table-draggable`]="props">
|
|
122
|
+
<FSDraggable
|
|
123
|
+
elementSelector="tr.v-data-table__tr"
|
|
124
|
+
:disabled="draggableDisabled"
|
|
125
|
+
:item="props"
|
|
126
|
+
@update:dragend="(event, dragged) => onDragEnd(event, dragged, 'tbody')"
|
|
127
|
+
>
|
|
128
|
+
<FSRow
|
|
129
|
+
class="fs-data-table-draggable"
|
|
130
|
+
align="bottom-center"
|
|
131
|
+
width="hug"
|
|
132
|
+
>
|
|
133
|
+
<FSIcon
|
|
134
|
+
size="l"
|
|
135
|
+
>
|
|
136
|
+
mdi-drag-vertical
|
|
137
|
+
</FSIcon>
|
|
138
|
+
</FSRow>
|
|
139
|
+
</FSDraggable>
|
|
140
|
+
</template>
|
|
114
141
|
<template #[`header.data-table-group`]="props">
|
|
115
|
-
<slot
|
|
142
|
+
<slot
|
|
143
|
+
name="header.data-table-group"
|
|
144
|
+
v-bind="props"
|
|
145
|
+
/>
|
|
116
146
|
</template>
|
|
117
147
|
<template #[`item.data-table-group`]="props">
|
|
118
|
-
<slot
|
|
148
|
+
<slot
|
|
149
|
+
name="item.data-table-group"
|
|
150
|
+
v-bind="props"
|
|
151
|
+
/>
|
|
119
152
|
</template>
|
|
120
153
|
<template #group-header="props">
|
|
121
154
|
<template :ref="() => { if (!props.isGroupOpen(props.item)) { props.toggleGroup(props.item) } }" />
|
|
@@ -125,27 +158,39 @@
|
|
|
125
158
|
class="fs-data-table-group-header"
|
|
126
159
|
:colspan="extraHeaders.concat(innerHeaders).length + 1"
|
|
127
160
|
>
|
|
128
|
-
<slot
|
|
129
|
-
|
|
130
|
-
|
|
161
|
+
<slot
|
|
162
|
+
name="group-header"
|
|
163
|
+
v-bind="props"
|
|
131
164
|
>
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
width="hug"
|
|
165
|
+
<FSCard
|
|
166
|
+
padding="12px 16px"
|
|
135
167
|
>
|
|
136
|
-
<
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
168
|
+
<FSRow
|
|
169
|
+
align="center-left"
|
|
170
|
+
width="hug"
|
|
171
|
+
>
|
|
172
|
+
<FSText>
|
|
173
|
+
<slot
|
|
174
|
+
name="group-header-title"
|
|
175
|
+
v-bind="props"
|
|
176
|
+
>
|
|
177
|
+
{{ props.item.value }}
|
|
178
|
+
</slot>
|
|
179
|
+
</FSText>
|
|
180
|
+
</FSRow>
|
|
181
|
+
</FSCard>
|
|
143
182
|
</slot>
|
|
144
183
|
</td>
|
|
145
184
|
</tr>
|
|
146
185
|
</template>
|
|
147
|
-
<template
|
|
148
|
-
|
|
186
|
+
<template
|
|
187
|
+
v-for="(header, index) in headersSlots"
|
|
188
|
+
#[header.slotName]="props"
|
|
189
|
+
>
|
|
190
|
+
<slot
|
|
191
|
+
:name="header.slotName"
|
|
192
|
+
v-bind="props"
|
|
193
|
+
>
|
|
149
194
|
<FSRow
|
|
150
195
|
align="center-left"
|
|
151
196
|
:wrap="false"
|
|
@@ -177,8 +222,14 @@
|
|
|
177
222
|
</FSRow>
|
|
178
223
|
</slot>
|
|
179
224
|
</template>
|
|
180
|
-
<template
|
|
181
|
-
|
|
225
|
+
<template
|
|
226
|
+
v-for="(item, index) in itemsSlots"
|
|
227
|
+
#[item.slotName]="props"
|
|
228
|
+
>
|
|
229
|
+
<slot
|
|
230
|
+
:name="item.slotName"
|
|
231
|
+
v-bind="props"
|
|
232
|
+
>
|
|
182
233
|
<FSRow
|
|
183
234
|
align="center-left"
|
|
184
235
|
:key="index"
|
|
@@ -249,8 +300,14 @@
|
|
|
249
300
|
/>
|
|
250
301
|
</FSRow>
|
|
251
302
|
</template>
|
|
252
|
-
<template
|
|
253
|
-
|
|
303
|
+
<template
|
|
304
|
+
v-for="(_, name) in innerSlots"
|
|
305
|
+
#[name]="props"
|
|
306
|
+
>
|
|
307
|
+
<slot
|
|
308
|
+
:name="name"
|
|
309
|
+
v-bind="props"
|
|
310
|
+
/>
|
|
254
311
|
</template>
|
|
255
312
|
</v-data-table>
|
|
256
313
|
<v-data-iterator
|
|
@@ -263,25 +320,49 @@
|
|
|
263
320
|
<template #default="{ items }">
|
|
264
321
|
<FSCol
|
|
265
322
|
width="fill"
|
|
323
|
+
class="fs-data-iterator-container"
|
|
266
324
|
>
|
|
267
|
-
<
|
|
268
|
-
|
|
325
|
+
<FSDraggable
|
|
326
|
+
v-for="(item, index) in items"
|
|
327
|
+
elementSelector=".fs-draggable-item"
|
|
328
|
+
:disabled="draggableDisabled"
|
|
329
|
+
:item="item"
|
|
330
|
+
:key="index"
|
|
331
|
+
@update:dragend="(event, dragged) => onDragEnd(event, dragged, '.fs-data-iterator-container')"
|
|
332
|
+
@dragover="onDragOver($event, '.fs-draggable-item', '.fs-data-iterator-container')"
|
|
333
|
+
@drop="(event) => onDrop(event, item, '.fs-draggable-item')"
|
|
334
|
+
@dragleave="onDragLeave"
|
|
335
|
+
@dragover.prevent
|
|
336
|
+
>
|
|
337
|
+
<slot
|
|
338
|
+
name="item.iterator"
|
|
339
|
+
v-bind="{ item, index }"
|
|
340
|
+
>
|
|
269
341
|
<FSDataIteratorItem
|
|
270
342
|
v-if="item.type === 'item'"
|
|
271
|
-
:key="index"
|
|
272
|
-
:item="item.raw"
|
|
273
|
-
:color="$props.color"
|
|
274
|
-
:itemTo="$props.itemTo"
|
|
275
|
-
:showSelect="$props.showSelect"
|
|
276
343
|
:headers="innerHeaders.filter(h => !$props.sneakyHeaders.includes(h.value))"
|
|
277
344
|
:modelValue="innerValue.includes(item.raw[$props.itemValue])"
|
|
345
|
+
:showSelect="$props.showSelect"
|
|
346
|
+
:itemTo="$props.itemTo"
|
|
347
|
+
:color="$props.color"
|
|
348
|
+
:item="item.raw"
|
|
349
|
+
:key="index"
|
|
278
350
|
@update:modelValue="toggleSelect"
|
|
279
351
|
>
|
|
280
352
|
<template #[`item.top`]="props">
|
|
281
|
-
<slot
|
|
353
|
+
<slot
|
|
354
|
+
name="item.top"
|
|
355
|
+
v-bind="props"
|
|
356
|
+
/>
|
|
282
357
|
</template>
|
|
283
|
-
<template
|
|
284
|
-
|
|
358
|
+
<template
|
|
359
|
+
v-for="(item, index) in itemsSlots"
|
|
360
|
+
#[item.slotName]="props"
|
|
361
|
+
>
|
|
362
|
+
<slot
|
|
363
|
+
:name="item.slotName"
|
|
364
|
+
v-bind="props"
|
|
365
|
+
>
|
|
285
366
|
<FSText
|
|
286
367
|
:key="index"
|
|
287
368
|
>
|
|
@@ -290,11 +371,14 @@
|
|
|
290
371
|
</slot>
|
|
291
372
|
</template>
|
|
292
373
|
<template #[`item.bottom`]="props">
|
|
293
|
-
<slot
|
|
374
|
+
<slot
|
|
375
|
+
name="item.bottom"
|
|
376
|
+
v-bind="props"
|
|
377
|
+
/>
|
|
294
378
|
</template>
|
|
295
379
|
</FSDataIteratorItem>
|
|
296
380
|
</slot>
|
|
297
|
-
</
|
|
381
|
+
</FSDraggable>
|
|
298
382
|
</FSCol>
|
|
299
383
|
</template>
|
|
300
384
|
<template #footer>
|
|
@@ -368,24 +452,48 @@
|
|
|
368
452
|
<template #default="{ items }">
|
|
369
453
|
<FSRow
|
|
370
454
|
width="hug"
|
|
455
|
+
class="fs-data-iterator-container"
|
|
371
456
|
>
|
|
372
|
-
<
|
|
373
|
-
|
|
457
|
+
<FSDraggable
|
|
458
|
+
v-for="(item, index) in items.filter((item) => item.type === 'item')"
|
|
459
|
+
elementSelector=".fs-draggable-item"
|
|
460
|
+
:disabled="draggableDisabled"
|
|
461
|
+
:item="item"
|
|
462
|
+
:key="index"
|
|
463
|
+
@update:dragend="(event, dragged) => onDragEnd(event, dragged, '.fs-data-iterator-container')"
|
|
464
|
+
@dragover="onDragOver($event, '.fs-draggable-item', '.fs-data-iterator-container')"
|
|
465
|
+
@drop="(event) => onDrop(event, item, '.fs-draggable-item')"
|
|
466
|
+
@dragleave="onDragLeave"
|
|
467
|
+
@dragover.prevent
|
|
468
|
+
>
|
|
469
|
+
<slot
|
|
470
|
+
name="item.tile"
|
|
471
|
+
v-bind="{ index, item: item.raw, toggleSelect }"
|
|
472
|
+
>
|
|
374
473
|
<FSDataIteratorItem
|
|
375
|
-
:key="index"
|
|
376
|
-
:item="item.raw"
|
|
377
|
-
:color="$props.color"
|
|
378
|
-
:itemTo="$props.itemTo"
|
|
379
|
-
:showSelect="$props.showSelect"
|
|
380
474
|
:headers="innerHeaders.filter(h => !$props.sneakyHeaders.includes(h.value))"
|
|
381
475
|
:modelValue="innerValue.includes(item.raw[$props.itemValue])"
|
|
476
|
+
:showSelect="$props.showSelect"
|
|
477
|
+
:itemTo="$props.itemTo"
|
|
478
|
+
:color="$props.color"
|
|
479
|
+
:item="item.raw"
|
|
480
|
+
:key="index"
|
|
382
481
|
@update:modelValue="toggleSelect"
|
|
383
482
|
>
|
|
384
483
|
<template #[`item.top`]="props">
|
|
385
|
-
<slot
|
|
484
|
+
<slot
|
|
485
|
+
name="item.top"
|
|
486
|
+
v-bind="props"
|
|
487
|
+
/>
|
|
386
488
|
</template>
|
|
387
|
-
<template
|
|
388
|
-
|
|
489
|
+
<template
|
|
490
|
+
v-for="(item, index) in itemsSlots"
|
|
491
|
+
#[item.slotName]="props"
|
|
492
|
+
>
|
|
493
|
+
<slot
|
|
494
|
+
:name="item.slotName"
|
|
495
|
+
v-bind="props"
|
|
496
|
+
>
|
|
389
497
|
<FSText
|
|
390
498
|
:key="index"
|
|
391
499
|
>
|
|
@@ -394,11 +502,14 @@
|
|
|
394
502
|
</slot>
|
|
395
503
|
</template>
|
|
396
504
|
<template #[`item.bottom`]="props">
|
|
397
|
-
<slot
|
|
505
|
+
<slot
|
|
506
|
+
name="item.bottom"
|
|
507
|
+
v-bind="props"
|
|
508
|
+
/>
|
|
398
509
|
</template>
|
|
399
510
|
</FSDataIteratorItem>
|
|
400
511
|
</slot>
|
|
401
|
-
</
|
|
512
|
+
</FSDraggable>
|
|
402
513
|
</FSRow>
|
|
403
514
|
</template>
|
|
404
515
|
</v-data-iterator>
|
|
@@ -421,11 +532,13 @@ import FSSelectField from "../fields/FSSelectField.vue";
|
|
|
421
532
|
import FSFilterButton from "./FSFilterButton.vue";
|
|
422
533
|
import FSHiddenButton from "./FSHiddenButton.vue";
|
|
423
534
|
import FSHeaderButton from "./FSHeaderButton.vue";
|
|
424
|
-
import
|
|
535
|
+
import FSOptionGroup from "../FSOptionGroup.vue";
|
|
425
536
|
import FSToggleSet from "../FSToggleSet.vue";
|
|
537
|
+
import FSDraggable from "./FSDraggable.vue";
|
|
426
538
|
import FSCheckbox from "../FSCheckbox.vue";
|
|
427
539
|
import FSCard from "../FSCard.vue";
|
|
428
540
|
import FSChip from "../FSChip.vue";
|
|
541
|
+
import FSIcon from "../FSIcon.vue";
|
|
429
542
|
import FSText from "../FSText.vue";
|
|
430
543
|
import FSRow from "../FSRow.vue";
|
|
431
544
|
import FSCol from "../FSCol.vue";
|
|
@@ -439,11 +552,13 @@ export default defineComponent({
|
|
|
439
552
|
FSHeaderButton,
|
|
440
553
|
FSSearchField,
|
|
441
554
|
FSSelectField,
|
|
442
|
-
|
|
555
|
+
FSOptionGroup,
|
|
556
|
+
FSDraggable,
|
|
443
557
|
FSToggleSet,
|
|
444
558
|
FSCheckbox,
|
|
445
559
|
FSCard,
|
|
446
560
|
FSChip,
|
|
561
|
+
FSIcon,
|
|
447
562
|
FSText,
|
|
448
563
|
FSRow,
|
|
449
564
|
FSCol
|
|
@@ -541,9 +656,19 @@ export default defineComponent({
|
|
|
541
656
|
type: Number,
|
|
542
657
|
required: false,
|
|
543
658
|
default: 20
|
|
659
|
+
},
|
|
660
|
+
sortDraggable: {
|
|
661
|
+
type: Boolean,
|
|
662
|
+
required: false,
|
|
663
|
+
default: false
|
|
664
|
+
},
|
|
665
|
+
includeDraggable: {
|
|
666
|
+
type: Boolean,
|
|
667
|
+
required: false,
|
|
668
|
+
default: false
|
|
544
669
|
}
|
|
545
670
|
},
|
|
546
|
-
emits: ["update:modelValue", "update:headers", "update:filters", "update:mode", "update:sortBy", "update:rowsPerPage", "update:page", "click:row"],
|
|
671
|
+
emits: ["update:modelValue", "update:headers", "update:filters", "update:mode", "update:sortBy", "update:rowsPerPage", "update:page", "update:include", "update:items", "click:row"],
|
|
547
672
|
setup(props, { emit }) {
|
|
548
673
|
const { isExtraSmall } = useBreakpoints();
|
|
549
674
|
const { $tr } = useTranslationsProvider();
|
|
@@ -583,6 +708,8 @@ export default defineComponent({
|
|
|
583
708
|
delete slots["no-data"];
|
|
584
709
|
delete slots["header.data-table-select"];
|
|
585
710
|
delete slots["item.data-table-select"];
|
|
711
|
+
delete slots["header.data-table-draggable"];
|
|
712
|
+
delete slots["item.data-table-draggable"];
|
|
586
713
|
delete slots["header.data-table-group"];
|
|
587
714
|
delete slots["item.data-table-group"];
|
|
588
715
|
delete slots["group-header"];
|
|
@@ -606,8 +733,8 @@ export default defineComponent({
|
|
|
606
733
|
|
|
607
734
|
const style = computed((): { [code: string]: string } & Partial<CSSStyleDeclaration> => {
|
|
608
735
|
return {
|
|
609
|
-
"--fs-data-table-background-color"
|
|
610
|
-
"--fs-data-table-border-color"
|
|
736
|
+
"--fs-data-table-background-color": backgrounds.base,
|
|
737
|
+
"--fs-data-table-border-color": lights.base
|
|
611
738
|
};
|
|
612
739
|
});
|
|
613
740
|
|
|
@@ -620,13 +747,19 @@ export default defineComponent({
|
|
|
620
747
|
});
|
|
621
748
|
|
|
622
749
|
const extraHeaders = computed((): any[] => {
|
|
623
|
-
const extra = [];
|
|
750
|
+
const extra: { key: string, width: string }[] = [];
|
|
624
751
|
if (props.groupBy) {
|
|
625
752
|
extra.push({
|
|
626
753
|
key: "data-table-group",
|
|
627
754
|
width: "0%"
|
|
628
755
|
});
|
|
629
756
|
}
|
|
757
|
+
if (props.sortDraggable || props.includeDraggable) {
|
|
758
|
+
extra.push({
|
|
759
|
+
key: "data-table-draggable",
|
|
760
|
+
width: "0%"
|
|
761
|
+
});
|
|
762
|
+
}
|
|
630
763
|
if (props.showSelect) {
|
|
631
764
|
extra.push({
|
|
632
765
|
key: "data-table-select",
|
|
@@ -716,6 +849,31 @@ export default defineComponent({
|
|
|
716
849
|
}
|
|
717
850
|
});
|
|
718
851
|
|
|
852
|
+
const onClickRow = computed(() => {
|
|
853
|
+
if (!!getCurrentInstance()?.vnode.props?.["onClick:row"] || props.itemTo) {
|
|
854
|
+
return (event: PointerEvent, row: any) => {
|
|
855
|
+
if (props.itemTo && router) {
|
|
856
|
+
if (event.metaKey || event.ctrlKey || event.button === 1) {
|
|
857
|
+
window.open(router.resolve(props.itemTo(row.item)).href, "_blank");
|
|
858
|
+
}
|
|
859
|
+
else {
|
|
860
|
+
router.push(props.itemTo(row.item));
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
emit("click:row", row.item);
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
else {
|
|
869
|
+
return null;
|
|
870
|
+
}
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
const draggableDisabled = computed(() => {
|
|
874
|
+
return (!props.sortDraggable && !props.includeDraggable) || !(innerSortBy.value === null || innerSortBy.value === undefined);
|
|
875
|
+
});
|
|
876
|
+
|
|
719
877
|
const toggleSelectAll = (allSelected: boolean): void => {
|
|
720
878
|
if (allSelected) {
|
|
721
879
|
innerValue.value = [];
|
|
@@ -875,11 +1033,11 @@ export default defineComponent({
|
|
|
875
1033
|
if (!intersectionObserver.value) {
|
|
876
1034
|
intersectionObserver.value = new IntersectionObserver(entries => {
|
|
877
1035
|
entries.forEach((entry) => {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
}
|
|
1036
|
+
if (entry.boundingClientRect.bottom < window.innerHeight * 1.25) {
|
|
1037
|
+
if (innerItems.value.length > size.value) {
|
|
1038
|
+
size.value = Math.min(size.value + props.sizeIterator, innerItems.value.length);
|
|
882
1039
|
}
|
|
1040
|
+
}
|
|
883
1041
|
});
|
|
884
1042
|
}, { threshold: [0.9] });
|
|
885
1043
|
}
|
|
@@ -890,26 +1048,111 @@ export default defineComponent({
|
|
|
890
1048
|
}
|
|
891
1049
|
}
|
|
892
1050
|
|
|
893
|
-
const
|
|
894
|
-
if (
|
|
895
|
-
return
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
1051
|
+
const changeIndex = (oldIndex: number, newIndex: number) => {
|
|
1052
|
+
if (oldIndex === newIndex) {
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
const items = innerItems.value.slice();
|
|
1056
|
+
const itemToMove = items.splice(oldIndex, 1)[0];
|
|
1057
|
+
items.splice(newIndex, 0, itemToMove);
|
|
1058
|
+
return items;
|
|
1059
|
+
};
|
|
1060
|
+
|
|
1061
|
+
const resetRowIndex = (initialIndex: number, currentIndex: number, draggedElement: HTMLElement, tbodyElement: HTMLElement) => {
|
|
1062
|
+
if (initialIndex > currentIndex) {
|
|
1063
|
+
tbodyElement.children[initialIndex].insertAdjacentElement("afterend", draggedElement);
|
|
1064
|
+
}
|
|
1065
|
+
else {
|
|
1066
|
+
tbodyElement.children[initialIndex].insertAdjacentElement("beforebegin", draggedElement);
|
|
1067
|
+
}
|
|
1068
|
+
};
|
|
1069
|
+
|
|
1070
|
+
const onDragOver = (event: DragEvent, elementSelector: string, elementContainerSelector: string) => {
|
|
1071
|
+
const dragged = document.querySelector(".fs-draggable-dragging") as HTMLElement;
|
|
1072
|
+
|
|
1073
|
+
if (dragged != null) {
|
|
1074
|
+
const target = (event.target as HTMLElement)?.closest(elementSelector);
|
|
1075
|
+
|
|
1076
|
+
if (target != null) {
|
|
1077
|
+
if (props.includeDraggable) {
|
|
1078
|
+
if (!props.sortDraggable) {
|
|
1079
|
+
target.classList.add("fs-dropzone-include");
|
|
899
1080
|
}
|
|
900
1081
|
else {
|
|
901
|
-
|
|
1082
|
+
const rowHeight = target.clientHeight;
|
|
1083
|
+
const y = event.clientY - target.getBoundingClientRect().top;
|
|
1084
|
+
|
|
1085
|
+
if (y > rowHeight * (3 / 4)) {
|
|
1086
|
+
target.insertAdjacentElement("afterend", dragged);
|
|
1087
|
+
target.classList.remove("fs-dropzone-include");
|
|
1088
|
+
}
|
|
1089
|
+
else if (y < rowHeight * (1 / 4)) {
|
|
1090
|
+
target.insertAdjacentElement("beforebegin", dragged);
|
|
1091
|
+
target.classList.remove("fs-dropzone-include");
|
|
1092
|
+
}
|
|
1093
|
+
else if (dragged?.getAttribute("data-initial-index") !== null) {
|
|
1094
|
+
target.classList.add("fs-dropzone-include");
|
|
1095
|
+
const tbodyElement = (event.target as HTMLElement)?.closest(elementContainerSelector) as HTMLElement;
|
|
1096
|
+
resetRowIndex(+dragged?.getAttribute('data-initial-index'), Array.from(tbodyElement.children).indexOf(dragged), dragged, tbodyElement);
|
|
1097
|
+
}
|
|
902
1098
|
}
|
|
903
1099
|
}
|
|
904
|
-
else {
|
|
905
|
-
|
|
1100
|
+
else if (props.sortDraggable) {
|
|
1101
|
+
const rowHeight = target.clientHeight;
|
|
1102
|
+
const y = event.clientY - target.getBoundingClientRect().top;
|
|
1103
|
+
if (y > rowHeight / 2) {
|
|
1104
|
+
target.insertAdjacentElement("afterend", dragged);
|
|
1105
|
+
}
|
|
1106
|
+
else {
|
|
1107
|
+
target.insertAdjacentElement("beforebegin", dragged);
|
|
1108
|
+
}
|
|
906
1109
|
}
|
|
907
|
-
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
908
1112
|
}
|
|
909
|
-
|
|
910
|
-
|
|
1113
|
+
};
|
|
1114
|
+
|
|
1115
|
+
const onDragLeave = (event: DragEvent) => {
|
|
1116
|
+
const dropzone = (event.target as HTMLElement)?.closest(".fs-dropzone-include");
|
|
1117
|
+
if (dropzone && !(event.relatedTarget as HTMLElement)?.closest(".fs-dropzone-include")) {
|
|
1118
|
+
dropzone.classList.remove("fs-dropzone-include");
|
|
911
1119
|
}
|
|
912
|
-
}
|
|
1120
|
+
};
|
|
1121
|
+
|
|
1122
|
+
const onDragEnd = (event: DragEvent, draggedElement: HTMLElement, elementContainerSelector: string) => {
|
|
1123
|
+
const initialIndex = +(draggedElement.getAttribute("data-initial-index") ?? -1);
|
|
1124
|
+
|
|
1125
|
+
if (draggedElement != null && initialIndex !== -1) {
|
|
1126
|
+
if (props.sortDraggable) {
|
|
1127
|
+
const tbodyElement = (event.target as HTMLElement)?.closest(elementContainerSelector) as HTMLElement;
|
|
1128
|
+
const currentIndex = Array.from(tbodyElement.children).indexOf(draggedElement);
|
|
1129
|
+
const newItems = changeIndex(initialIndex, currentIndex);
|
|
1130
|
+
|
|
1131
|
+
if (newItems !== null && newItems !== undefined) {
|
|
1132
|
+
emit("update:items", newItems);
|
|
1133
|
+
}
|
|
1134
|
+
resetRowIndex(initialIndex, currentIndex, draggedElement, tbodyElement);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
const onDrop = (event: DragEvent, row: any, elementSelector: string) => {
|
|
1140
|
+
const draggedElement = document.querySelector(".fs-draggable-dragging");
|
|
1141
|
+
|
|
1142
|
+
if (draggedElement != null) {
|
|
1143
|
+
const target = (event.target as HTMLElement)?.closest(elementSelector);
|
|
1144
|
+
const draggedData = JSON.parse(event.dataTransfer?.getData("text/plain") ?? "");
|
|
1145
|
+
const itemsData = draggedData.item ?? draggedData.raw;
|
|
1146
|
+
const rowData = row.item ?? row.raw;
|
|
1147
|
+
|
|
1148
|
+
if (target != null) {
|
|
1149
|
+
if (props.includeDraggable && itemsData[props.itemValue] != rowData[props.itemValue]) {
|
|
1150
|
+
emit("update:include", { draggedItem: itemsData, targetItem: rowData })
|
|
1151
|
+
}
|
|
1152
|
+
target.closest(".fs-dropzone-include")?.classList.remove("fs-dropzone-include");
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
913
1156
|
|
|
914
1157
|
onMounted(() => {
|
|
915
1158
|
computeFilters();
|
|
@@ -975,6 +1218,7 @@ export default defineComponent({
|
|
|
975
1218
|
size,
|
|
976
1219
|
onClickRow,
|
|
977
1220
|
isExtraSmall,
|
|
1221
|
+
draggableDisabled,
|
|
978
1222
|
toggleSelectAll,
|
|
979
1223
|
toggleSelect,
|
|
980
1224
|
updateHeader,
|
|
@@ -983,6 +1227,10 @@ export default defineComponent({
|
|
|
983
1227
|
filterSlot,
|
|
984
1228
|
sortColor,
|
|
985
1229
|
sortIcon,
|
|
1230
|
+
onDrop,
|
|
1231
|
+
onDragOver,
|
|
1232
|
+
onDragLeave,
|
|
1233
|
+
onDragEnd
|
|
986
1234
|
};
|
|
987
1235
|
}
|
|
988
1236
|
})
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:draggable="!$props.disabled"
|
|
4
|
+
:class="classes"
|
|
5
|
+
@touchstart="onTouchStart"
|
|
6
|
+
@touchmove="onTouchMove"
|
|
7
|
+
@touchend="onTouchEnd"
|
|
8
|
+
@dragstart="onDragStart"
|
|
9
|
+
@dragend="onDragEnd"
|
|
10
|
+
@dragover.prevent
|
|
11
|
+
>
|
|
12
|
+
<slot />
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script lang="ts">
|
|
17
|
+
import { computed, defineComponent, ref } from "vue";
|
|
18
|
+
|
|
19
|
+
export default defineComponent({
|
|
20
|
+
name: "FSDraggable",
|
|
21
|
+
props: {
|
|
22
|
+
elementSelector: {
|
|
23
|
+
type: String,
|
|
24
|
+
default: null,
|
|
25
|
+
},
|
|
26
|
+
item: {
|
|
27
|
+
type: Object,
|
|
28
|
+
default: null,
|
|
29
|
+
},
|
|
30
|
+
disabled: {
|
|
31
|
+
type: Boolean,
|
|
32
|
+
default: false,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
emits: ["update:dragstart", "update:dragend"],
|
|
36
|
+
setup(props, { emit }) {
|
|
37
|
+
let prevDragOverTarget: EventTarget | null = null;
|
|
38
|
+
|
|
39
|
+
const draggedElementCopy = ref<HTMLElement|null>(null);
|
|
40
|
+
const touchStartX = ref(0);
|
|
41
|
+
const touchStartY = ref(0);
|
|
42
|
+
const touchEndX = ref(0);
|
|
43
|
+
const touchEndY = ref(0);
|
|
44
|
+
|
|
45
|
+
const classes = computed((): string[] => {
|
|
46
|
+
const classNames = ["fs-draggable-item"];
|
|
47
|
+
if (!props.disabled) {
|
|
48
|
+
classNames.push("fs-draggable-enabled");
|
|
49
|
+
}
|
|
50
|
+
return classNames;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const onTouchStart = (event: TouchEvent) => {
|
|
54
|
+
if (props.disabled) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
event.preventDefault();
|
|
58
|
+
const touch = event.touches[0];
|
|
59
|
+
touchStartX.value = touch.clientX;
|
|
60
|
+
touchStartY.value = touch.clientY;
|
|
61
|
+
|
|
62
|
+
const dragged = (event.target as HTMLElement)?.closest(props.elementSelector) as HTMLElement;
|
|
63
|
+
dragged.classList.add("fs-draggable-dragging");
|
|
64
|
+
dragged.dataset.initialIndex = props.item?.index ?? props.item?.value;
|
|
65
|
+
|
|
66
|
+
draggedElementCopy.value = dragged.cloneNode(true) as HTMLElement;
|
|
67
|
+
draggedElementCopy.value.style.position = "fixed";
|
|
68
|
+
draggedElementCopy.value.style.left = `${touchStartX.value - 25}px`;
|
|
69
|
+
draggedElementCopy.value.style.top = `${touchStartY.value - 25}px`;
|
|
70
|
+
draggedElementCopy.value.style.zIndex = "1000";
|
|
71
|
+
draggedElementCopy.value.style.pointerEvents = "none";
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const onTouchMove = (event: TouchEvent) => {
|
|
75
|
+
if (props.disabled) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
const touch = event.touches[0];
|
|
80
|
+
touchEndX.value = touch.clientX;
|
|
81
|
+
touchEndY.value = touch.clientY;
|
|
82
|
+
|
|
83
|
+
draggedElementCopy.value.style.left = `${touchEndX.value - 25}px`;
|
|
84
|
+
draggedElementCopy.value.style.top = `${touchEndY.value - 25}px`;
|
|
85
|
+
document.body.appendChild(draggedElementCopy.value);
|
|
86
|
+
const dragOverTarget = document.elementFromPoint(touchEndX.value, touchEndY.value)?.closest(props.elementSelector);
|
|
87
|
+
|
|
88
|
+
if (dragOverTarget) {
|
|
89
|
+
const dragOverEvent = new Event("dragover", {
|
|
90
|
+
bubbles: true,
|
|
91
|
+
cancelable: true
|
|
92
|
+
});
|
|
93
|
+
dragOverTarget?.dispatchEvent(dragOverEvent);
|
|
94
|
+
if (dragOverTarget !== prevDragOverTarget) {
|
|
95
|
+
const dragLeaveEvent = new Event("dragleave", {
|
|
96
|
+
bubbles: true,
|
|
97
|
+
cancelable: true
|
|
98
|
+
});
|
|
99
|
+
prevDragOverTarget?.dispatchEvent(dragLeaveEvent);
|
|
100
|
+
}
|
|
101
|
+
prevDragOverTarget = dragOverTarget;
|
|
102
|
+
}
|
|
103
|
+
else if (prevDragOverTarget) {
|
|
104
|
+
const dragLeaveEvent = new Event("dragleave", {
|
|
105
|
+
bubbles: true,
|
|
106
|
+
cancelable: true
|
|
107
|
+
});
|
|
108
|
+
prevDragOverTarget?.dispatchEvent(dragLeaveEvent);
|
|
109
|
+
prevDragOverTarget = null;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const onTouchEnd = (event: TouchEvent) => {
|
|
114
|
+
if (props.disabled) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
const dragged = (event.target as HTMLElement)?.closest(props.elementSelector);
|
|
119
|
+
draggedElementCopy.value.remove();
|
|
120
|
+
draggedElementCopy.value = null;
|
|
121
|
+
|
|
122
|
+
const dropTarget = document.elementFromPoint(touchEndX.value, touchEndY.value);
|
|
123
|
+
const dragEndEvent = new Event("dragend");
|
|
124
|
+
Object.defineProperty(dragEndEvent, "srcElement", {
|
|
125
|
+
get: function () { return event.target; }
|
|
126
|
+
});
|
|
127
|
+
emit("update:dragend", dragEndEvent, dragged);
|
|
128
|
+
|
|
129
|
+
const dropEvent = new DragEvent("drop", {
|
|
130
|
+
bubbles: true,
|
|
131
|
+
cancelable: true,
|
|
132
|
+
});
|
|
133
|
+
dropEvent.dataTransfer?.setData("text/plain", JSON.stringify(props.item));
|
|
134
|
+
dropTarget?.dispatchEvent(dropEvent);
|
|
135
|
+
|
|
136
|
+
touchStartX.value = 0;
|
|
137
|
+
touchStartY.value = 0;
|
|
138
|
+
touchEndX.value = 0;
|
|
139
|
+
touchEndY.value = 0;
|
|
140
|
+
dragged.classList.remove("fs-draggable-dragging");
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const onDragStart = (event: DragEvent) => {
|
|
144
|
+
if (props.disabled) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const dragged = (event.target as HTMLElement)?.closest(props.elementSelector) as HTMLElement;
|
|
149
|
+
dragged.dataset.initialIndex = props.item?.index ?? props.item?.value;
|
|
150
|
+
event.dataTransfer?.setDragImage(dragged, 25, 25);
|
|
151
|
+
|
|
152
|
+
if (event.dataTransfer) {
|
|
153
|
+
event.dataTransfer.dropEffect = "move";
|
|
154
|
+
event.dataTransfer.effectAllowed = "move";
|
|
155
|
+
}
|
|
156
|
+
dragged?.classList.add("fs-draggable-dragging");
|
|
157
|
+
event.dataTransfer?.setData("text/plain", JSON.stringify(props.item));
|
|
158
|
+
emit("update:dragstart", event);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const onDragEnd = (event: DragEvent) => {
|
|
162
|
+
const dragged = (event.target as HTMLElement)?.closest(props.elementSelector);
|
|
163
|
+
dragged?.classList.remove("fs-draggable-dragging");
|
|
164
|
+
emit("update:dragend", event, dragged);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
classes,
|
|
169
|
+
onTouchStart,
|
|
170
|
+
onTouchMove,
|
|
171
|
+
onTouchEnd,
|
|
172
|
+
onDragStart,
|
|
173
|
+
onDragEnd
|
|
174
|
+
};
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
</script>
|
package/composables/useColors.ts
CHANGED
|
@@ -71,7 +71,7 @@ export const useColors = () => {
|
|
|
71
71
|
soft: getSoft(seed).hex(),
|
|
72
72
|
softContrast: getContrast(seed, dark).hex(),
|
|
73
73
|
base: seed.hex(),
|
|
74
|
-
baseContrast: getContrast(seed,
|
|
74
|
+
baseContrast: getContrast(seed, dark).hex(),
|
|
75
75
|
dark: dark.hex(),
|
|
76
76
|
darkContrast: getContrast(dark, light).hex()
|
|
77
77
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dative-gpi/foundation-shared-components",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.42",
|
|
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": "0.0.
|
|
14
|
-
"@dative-gpi/foundation-shared-services": "0.0.
|
|
13
|
+
"@dative-gpi/foundation-shared-domain": "0.0.42",
|
|
14
|
+
"@dative-gpi/foundation-shared-services": "0.0.42",
|
|
15
15
|
"@fontsource/montserrat": "^5.0.16",
|
|
16
16
|
"@lexical/clipboard": "^0.12.5",
|
|
17
17
|
"@lexical/history": "^0.12.5",
|
|
@@ -32,5 +32,5 @@
|
|
|
32
32
|
"sass": "^1.69.5",
|
|
33
33
|
"sass-loader": "^13.3.2"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "b04bea74796441bbb7176bcdd7d1a23317faa2b8"
|
|
36
36
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.fs-draggable-dragging {
|
|
2
|
+
opacity: 0.4;
|
|
3
|
+
filter: blur(1px);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.fs-dropzone-include {
|
|
7
|
+
transition: all 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
|
8
|
+
filter: brightness(0.85) contrast(1.1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.fs-draggable-item {
|
|
12
|
+
transition: all 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
div.fs-dropzone-include {
|
|
16
|
+
transform: scale(1.04);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.fs-draggable-enabled {
|
|
20
|
+
cursor: move ;
|
|
21
|
+
cursor: grab ;
|
|
22
|
+
cursor: -moz-grab ;
|
|
23
|
+
cursor: -webkit-grab ;
|
|
24
|
+
user-select: none;
|
|
25
|
+
}
|