@carbon/vue 3.0.20 → 3.0.22
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/dist/carbon-vue-3.common.js +4420 -4885
- package/dist/carbon-vue-3.common.js.map +1 -1
- package/dist/carbon-vue-3.umd.js +4422 -4887
- package/dist/carbon-vue-3.umd.js.map +1 -1
- package/dist/carbon-vue-3.umd.min.js +4 -4
- package/dist/carbon-vue-3.umd.min.js.map +1 -1
- package/dist/web-types.json +14 -1
- package/package.json +4 -4
- package/src/components/CvAspectRatio/CvAspectRatio.stories.js +2 -5
- package/src/components/CvBreadcrumb/CvBreadcrumb.stories.js +2 -5
- package/src/components/CvButton/CvButton.stories.js +1 -3
- package/src/components/CvButton/CvButtonSet.stories.js +2 -6
- package/src/components/CvButton/CvButtonSkeleton.stories.js +1 -3
- package/src/components/CvButton/CvIconButton.stories.js +1 -3
- package/src/components/CvCheckbox/CvCheckbox.stories.js +5 -4
- package/src/components/CvCodeSnippet/CvCodeSnippet.stories.js +1 -2
- package/src/components/CvComboBox/CvComboBox.stories.js +2 -5
- package/src/components/CvCopyButton/CvCopyButton.stories.js +2 -5
- package/src/components/CvDataTable/CvDataTable.stories.mdx +82 -12
- package/src/components/CvDataTable/CvDataTable.vue +71 -96
- package/src/components/CvDataTable/CvDataTableHeading.vue +25 -45
- package/src/components/CvDataTable/CvDataTableRow.vue +50 -49
- package/src/components/CvDataTable/_CvDataTableRowInner.vue +9 -18
- package/src/components/CvDatePicker/CvDatePicker.stories.js +101 -27
- package/src/components/CvDatePicker/CvDatePicker.vue +4 -2
- package/src/components/CvLink/CvLink.stories.js +1 -2
- package/src/components/CvList/CvList.stories.js +2 -5
- package/src/components/CvLoading/CvLoading.stories.js +2 -5
- package/src/components/CvMultiSelect/CvMultiSelect.vue +4 -1
- package/src/components/CvNotification/CvInlineNotification.stories.js +2 -2
- package/src/components/CvNotification/CvToastNotification.stories.js +2 -2
- package/src/components/CvNumberInput/CvNumberInput.stories.js +2 -6
- package/src/components/CvNumberInput/CvNumberInputSkeleton.stories.js +2 -6
- package/src/components/CvRadioButton/CvRadioButton.stories.js +2 -5
- package/src/components/CvSkeletonText/CvSkeletonText.stories.js +2 -5
- package/src/components/CvSlider/CvSlider.stories.js +2 -6
- package/src/components/CvSlider/CvSliderSkeleton.stories.js +2 -6
- package/src/components/CvStructuredList/CvStructuredList.stories.js +2 -5
- package/src/components/CvTag/CvTag.stories.js +2 -5
- package/src/components/CvTag/CvTagSkeleton.stories.js +2 -5
- package/src/components/CvTextArea/CvTextArea.stories.js +2 -6
- package/src/components/CvTextArea/CvTextAreaSkeleton.stories.js +2 -6
- package/src/components/CvTextInput/CvTextInput.stories.js +2 -5
- package/src/components/CvToggle/CvToggle.stories.js +2 -5
- package/src/components/CvTooltip/CvDefinitionTooltip.stories.js +2 -6
- package/src/components/CvTooltip/CvInteractiveTooltip.stories.js +2 -6
- package/src/components/CvTooltip/CvTooltip.stories.js +2 -6
- package/src/use/overflow.js +2 -2
- package/src/components/CvDataTable/cvDataTableStore.js +0 -314
|
@@ -236,11 +236,9 @@ import CvPagination from '../CvPagination';
|
|
|
236
236
|
import Search16 from '@carbon/icons-vue/es/search/16';
|
|
237
237
|
import Close16 from '@carbon/icons-vue/es/close/16';
|
|
238
238
|
import ChevronRight16 from '@carbon/icons-vue/es/chevron--right/16';
|
|
239
|
-
import { getBus, removeBus } from '../../global/component-utils/event-bus';
|
|
240
239
|
import {
|
|
241
240
|
computed,
|
|
242
241
|
nextTick,
|
|
243
|
-
onBeforeMount,
|
|
244
242
|
onMounted,
|
|
245
243
|
onUnmounted,
|
|
246
244
|
onUpdated,
|
|
@@ -251,8 +249,6 @@ import {
|
|
|
251
249
|
provide,
|
|
252
250
|
} from 'vue';
|
|
253
251
|
import { props as propsCvId, useCvId } from '../../use/cvId';
|
|
254
|
-
//TODO: Remove this store and replace with provide/inject
|
|
255
|
-
import store from './cvDataTableStore';
|
|
256
252
|
import Empty from '../CvEmpty/_CvEmpty.vue';
|
|
257
253
|
|
|
258
254
|
const props = defineProps({
|
|
@@ -356,20 +352,6 @@ watch(
|
|
|
356
352
|
() => (isSkeleton.value = props.skeleton)
|
|
357
353
|
);
|
|
358
354
|
|
|
359
|
-
let bus = undefined;
|
|
360
|
-
onBeforeMount(() => {
|
|
361
|
-
bus = getBus(uid.value);
|
|
362
|
-
bus.on('cv:check-change', onRowCheckChange);
|
|
363
|
-
bus.on('cv:click', onMenuItemClick);
|
|
364
|
-
bus.on('cv:sort', onSort);
|
|
365
|
-
bus.on('cv:expanded-change', onCvExpandedChange);
|
|
366
|
-
store.addTable(uid);
|
|
367
|
-
});
|
|
368
|
-
onUnmounted(() => {
|
|
369
|
-
removeBus(uid.value);
|
|
370
|
-
store.removeTable(uid.value);
|
|
371
|
-
});
|
|
372
|
-
|
|
373
355
|
watch(() => props.rowsSelected, updateRowsSelected);
|
|
374
356
|
|
|
375
357
|
const searchContainer = ref(null);
|
|
@@ -393,6 +375,7 @@ watch(
|
|
|
393
375
|
else expandingRowIds.value.delete('table-expand-row');
|
|
394
376
|
}
|
|
395
377
|
);
|
|
378
|
+
const clearSearchVisible = ref(false);
|
|
396
379
|
|
|
397
380
|
onMounted(() => {
|
|
398
381
|
if (searchContainer.value) {
|
|
@@ -416,6 +399,8 @@ onUpdated(checkSlots);
|
|
|
416
399
|
const hasActions = ref(false);
|
|
417
400
|
const hasToolbar = ref(false);
|
|
418
401
|
const hasBatchActions = ref(false);
|
|
402
|
+
const isHelper = ref(false);
|
|
403
|
+
|
|
419
404
|
provide('has-batch-actions', hasBatchActions);
|
|
420
405
|
|
|
421
406
|
function checkSlots() {
|
|
@@ -442,9 +427,11 @@ function columnHeading(c) {
|
|
|
442
427
|
}
|
|
443
428
|
}
|
|
444
429
|
|
|
430
|
+
const sortableHeadings = ref(new Set());
|
|
431
|
+
provide('sortableHeadings', sortableHeadings);
|
|
445
432
|
const isSortable = computed(() => {
|
|
446
433
|
// is any column sortable
|
|
447
|
-
return props.sortable ||
|
|
434
|
+
return props.sortable || sortableHeadings.value.size > 0;
|
|
448
435
|
});
|
|
449
436
|
|
|
450
437
|
function isColSortable(c) {
|
|
@@ -453,7 +440,6 @@ function isColSortable(c) {
|
|
|
453
440
|
return (col && col.sortable) || props.sortable;
|
|
454
441
|
}
|
|
455
442
|
|
|
456
|
-
const isHelper = ref(false);
|
|
457
443
|
const hasTableHeader = computed(() => {
|
|
458
444
|
return props.title || isHelper.value;
|
|
459
445
|
});
|
|
@@ -482,13 +468,15 @@ const internalPagination = computed(() => {
|
|
|
482
468
|
return false;
|
|
483
469
|
});
|
|
484
470
|
|
|
485
|
-
const
|
|
471
|
+
const rowIds = ref(new Set());
|
|
472
|
+
provide('row-ids', rowIds);
|
|
473
|
+
|
|
486
474
|
const internalNumberOfItems = computed(() => {
|
|
487
475
|
const internal = internalPagination.value;
|
|
488
476
|
if (internal.numberOfItems !== undefined) {
|
|
489
477
|
return internal.numberOfItems;
|
|
490
478
|
} else {
|
|
491
|
-
return
|
|
479
|
+
return rowIds.value.size;
|
|
492
480
|
}
|
|
493
481
|
});
|
|
494
482
|
|
|
@@ -527,6 +515,19 @@ function checkSearchExpand(force) {
|
|
|
527
515
|
}
|
|
528
516
|
|
|
529
517
|
const dataRowsSelected = ref(props.rowsSelected);
|
|
518
|
+
provide('rows-selected', dataRowsSelected);
|
|
519
|
+
|
|
520
|
+
const headingChecked = ref(false);
|
|
521
|
+
watch(
|
|
522
|
+
() => dataRowsSelected,
|
|
523
|
+
() => {
|
|
524
|
+
headingChecked.value =
|
|
525
|
+
rowIds.value.size > 0 &&
|
|
526
|
+
dataRowsSelected.value.length === rowIds.value.size;
|
|
527
|
+
},
|
|
528
|
+
{ deep: true }
|
|
529
|
+
);
|
|
530
|
+
|
|
530
531
|
const batchActive = computed(() => {
|
|
531
532
|
return (
|
|
532
533
|
props.stickyBatchActive ||
|
|
@@ -535,29 +536,8 @@ const batchActive = computed(() => {
|
|
|
535
536
|
);
|
|
536
537
|
});
|
|
537
538
|
|
|
538
|
-
const headingChecked = ref(false);
|
|
539
|
-
|
|
540
|
-
watch(
|
|
541
|
-
() => store.state[uid.value],
|
|
542
|
-
() => {
|
|
543
|
-
const rows = store.rows(uid);
|
|
544
|
-
headingChecked.value = dataRowsSelected.value.length === rows.length;
|
|
545
|
-
},
|
|
546
|
-
{ deep: true }
|
|
547
|
-
);
|
|
548
539
|
function updateRowsSelected() {
|
|
549
|
-
dataRowsSelected.value = [];
|
|
550
|
-
const rows = store.rows(uid);
|
|
551
|
-
for (const i in rows) {
|
|
552
|
-
let child = rows[i];
|
|
553
|
-
const checked = props.rowsSelected.includes(child.value);
|
|
554
|
-
store.updateRow(uid, { id: child.id, isChecked: checked });
|
|
555
|
-
|
|
556
|
-
if (checked) {
|
|
557
|
-
dataRowsSelected.value.push(child.value);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
headingChecked.value = dataRowsSelected.value.length === rows.length;
|
|
540
|
+
dataRowsSelected.value = [...props.rowsSelected];
|
|
561
541
|
}
|
|
562
542
|
|
|
563
543
|
const emit = defineEmits([
|
|
@@ -571,7 +551,6 @@ const emit = defineEmits([
|
|
|
571
551
|
'pagination',
|
|
572
552
|
]);
|
|
573
553
|
const searchValue = ref(props.initialSearchValue);
|
|
574
|
-
const clearSearchVisible = ref(false);
|
|
575
554
|
function onClearClick() {
|
|
576
555
|
searchValue.value = '';
|
|
577
556
|
clearSearchVisible.value = false;
|
|
@@ -583,87 +562,83 @@ function onClearClick() {
|
|
|
583
562
|
}
|
|
584
563
|
function onHeadingCheckChange() {
|
|
585
564
|
// check /uncheck all children
|
|
586
|
-
dataRowsSelected.value = [];
|
|
587
|
-
|
|
588
|
-
for (const child of rows) {
|
|
589
|
-
if (headingChecked.value) {
|
|
590
|
-
dataRowsSelected.value.push(child.value);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
if (child.isChecked !== headingChecked.value) {
|
|
594
|
-
store.updateRow(uid, { id: child.id, isChecked: headingChecked.value });
|
|
595
|
-
|
|
596
|
-
emit('row-select-change', {
|
|
597
|
-
value: child.value,
|
|
598
|
-
selected: headingChecked.value,
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
emit('row-select-changes', dataRowsSelected.value);
|
|
603
|
-
emit('update:rowsSelected', dataRowsSelected.value);
|
|
565
|
+
if (headingChecked.value) dataRowsSelected.value = [...rowIds.value];
|
|
566
|
+
else dataRowsSelected.value = [];
|
|
604
567
|
}
|
|
605
568
|
function deselect() {
|
|
606
569
|
headingChecked.value = false;
|
|
607
570
|
onHeadingCheckChange();
|
|
608
571
|
}
|
|
609
|
-
function onRowCheckChange(payload) {
|
|
610
|
-
const { value, checked } = payload;
|
|
611
|
-
let modelSet = new Set(dataRowsSelected.value);
|
|
612
|
-
|
|
613
|
-
if (!checked) {
|
|
614
|
-
modelSet.delete(value);
|
|
615
|
-
} else {
|
|
616
|
-
modelSet.add(value);
|
|
617
|
-
}
|
|
618
|
-
dataRowsSelected.value = Array.from(modelSet);
|
|
619
|
-
const rows = store.rows(uid);
|
|
620
|
-
headingChecked.value = dataRowsSelected.value.length === rows.length;
|
|
621
572
|
|
|
573
|
+
const previousEmit = ref([...props.rowsSelected]);
|
|
574
|
+
watch(
|
|
575
|
+
dataRowsSelected,
|
|
576
|
+
() => {
|
|
577
|
+
// was tempted to use Set.symmetricDifference but support for that was only
|
|
578
|
+
// add in Feb/June 2024
|
|
579
|
+
const diff = dataRowsSelected.value
|
|
580
|
+
.filter(x => !previousEmit.value.includes(x))
|
|
581
|
+
.concat(
|
|
582
|
+
previousEmit.value.filter(x => !dataRowsSelected.value.includes(x))
|
|
583
|
+
);
|
|
584
|
+
if (diff.length > 0) {
|
|
585
|
+
emit('row-select-changes', dataRowsSelected.value);
|
|
586
|
+
emit('update:rowsSelected', dataRowsSelected.value);
|
|
587
|
+
previousEmit.value = [...dataRowsSelected.value];
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
{ deep: true }
|
|
591
|
+
);
|
|
592
|
+
function onRowCheckChange(value, checked) {
|
|
622
593
|
emit('row-select-change', { value, selected: checked });
|
|
623
|
-
emit('row-select-changes', dataRowsSelected.value);
|
|
624
|
-
emit('update:rowsSelected', dataRowsSelected.value);
|
|
625
594
|
}
|
|
595
|
+
provide('cv:check-change', onRowCheckChange);
|
|
596
|
+
|
|
626
597
|
function onMenuItemClick(val) {
|
|
627
598
|
emit('overflow-menu-click', val);
|
|
628
599
|
}
|
|
600
|
+
provide('cv:click', onMenuItemClick);
|
|
601
|
+
|
|
629
602
|
function onInternalSearch() {
|
|
630
603
|
clearSearchVisible.value = searchValue.value.length > 0;
|
|
631
604
|
// eslint-disable-next-line vue/require-explicit-emits
|
|
632
605
|
emit('search', searchValue.value);
|
|
633
606
|
}
|
|
607
|
+
|
|
608
|
+
const headingIds = ref(new Set());
|
|
609
|
+
provide('heading-ids', headingIds);
|
|
610
|
+
const currentSortHeadingId = ref(null);
|
|
611
|
+
provide('current-sort-heading-id', currentSortHeadingId);
|
|
634
612
|
function onSort(payload) {
|
|
635
613
|
const { heading, value } = payload;
|
|
636
|
-
const headings =
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
const column = headings[colIndex];
|
|
640
|
-
if (column.id === heading.id) {
|
|
641
|
-
store.updateHeading(uid, { ...column, order: value });
|
|
642
|
-
index = colIndex;
|
|
643
|
-
} else {
|
|
644
|
-
store.updateHeading(uid, { ...column, order: 'none' });
|
|
645
|
-
}
|
|
646
|
-
}
|
|
614
|
+
const headings = Array.from(headingIds.value);
|
|
615
|
+
currentSortHeadingId.value = heading.id;
|
|
616
|
+
const index = headings.indexOf(heading.id);
|
|
647
617
|
emit('sort', { index, order: value, name: heading.name });
|
|
648
618
|
}
|
|
619
|
+
provide('cv:sort', onSort);
|
|
649
620
|
|
|
650
621
|
// are all rows expanded
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
622
|
+
/** @type {Ref<Set<String>>} */
|
|
623
|
+
const expandedRowIds = ref(new Set());
|
|
624
|
+
provide('expanded-row-ids', expandedRowIds);
|
|
625
|
+
|
|
626
|
+
const dataExpandAll = computed(
|
|
627
|
+
() => expandedRowIds.value.size === rowIds.value.size
|
|
628
|
+
);
|
|
654
629
|
function toggleExpandAll() {
|
|
655
630
|
const toggle = !dataExpandAll.value;
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
631
|
+
if (toggle) {
|
|
632
|
+
rowIds.value.forEach(rowId => expandedRowIds.value.add(rowId));
|
|
633
|
+
} else expandedRowIds.value.clear();
|
|
660
634
|
}
|
|
661
635
|
|
|
662
636
|
/**
|
|
663
637
|
* A child row is changed
|
|
664
|
-
* @param {{
|
|
638
|
+
* @param {{id:string, value:string, expandable:string, isExpanded:boolean, isChecked:boolean}} row
|
|
665
639
|
*/
|
|
666
640
|
function onCvExpandedChange(row) {
|
|
667
641
|
emit('row-expanded', row);
|
|
668
642
|
}
|
|
643
|
+
provide('cv:expanded-change', onCvExpandedChange);
|
|
669
644
|
</script>
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<th
|
|
3
|
-
:id="cvId"
|
|
4
|
-
ref="el"
|
|
5
|
-
:aria-sort="internalOrder"
|
|
6
|
-
:style="skeleton && headingStyle"
|
|
7
|
-
>
|
|
2
|
+
<th :id="cvId" :aria-sort="internalOrder" :style="skeleton && headingStyle">
|
|
8
3
|
<button
|
|
9
4
|
v-if="sortable"
|
|
10
5
|
type="button"
|
|
@@ -46,9 +41,7 @@ import Arrows16 from '@carbon/icons-vue/es/arrows--vertical/16';
|
|
|
46
41
|
import CvEmpty from '../CvEmpty/_CvEmpty.vue';
|
|
47
42
|
import { props as propsCvId, useCvId } from '../../use/cvId';
|
|
48
43
|
import { carbonPrefix } from '../../global/settings';
|
|
49
|
-
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
50
|
-
import { getBus } from '../../global/component-utils/event-bus';
|
|
51
|
-
import store from './cvDataTableStore';
|
|
44
|
+
import { computed, onBeforeUnmount, onMounted, ref, watch, inject } from 'vue';
|
|
52
45
|
|
|
53
46
|
const nextOrder = {
|
|
54
47
|
ascending: 'descending',
|
|
@@ -67,69 +60,56 @@ const props = defineProps({
|
|
|
67
60
|
});
|
|
68
61
|
const cvId = useCvId(props, true);
|
|
69
62
|
const dataOrder = ref(props.order);
|
|
70
|
-
const parent = ref(null);
|
|
71
63
|
watch(
|
|
72
64
|
() => props.order,
|
|
73
65
|
() => {
|
|
74
66
|
if (dataOrder.value !== props.order) {
|
|
75
67
|
dataOrder.value = props.order;
|
|
76
|
-
store.updateHeading(parent, {
|
|
77
|
-
id: cvId.value,
|
|
78
|
-
order: dataOrder.value,
|
|
79
|
-
});
|
|
80
68
|
onSortClick();
|
|
81
69
|
}
|
|
82
70
|
}
|
|
83
71
|
);
|
|
72
|
+
const sortableHeaders = inject('sortableHeadings', ref(new Set()));
|
|
84
73
|
watch(
|
|
85
74
|
() => props.sortable,
|
|
86
75
|
() => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
sortable: props.sortable,
|
|
90
|
-
});
|
|
76
|
+
if (props.sortable) sortableHeaders.value.add(cvId.value);
|
|
77
|
+
else sortableHeaders.value.delete(cvId.value);
|
|
91
78
|
}
|
|
92
79
|
);
|
|
93
80
|
|
|
94
|
-
|
|
95
|
-
const el = ref(null);
|
|
81
|
+
const headingIds = inject('heading-ids', ref(new Set()));
|
|
96
82
|
onMounted(() => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const exists = store.findHeading(parent, cvId);
|
|
103
|
-
if (exists)
|
|
104
|
-
console.error(
|
|
105
|
-
`CvDataTable: Duplicate ID specified for CvDataTableHeading, may cause issues. {id: ${cvId.value}, name: ${props.name}`
|
|
106
|
-
);
|
|
107
|
-
else
|
|
108
|
-
store.updateHeading(parent, {
|
|
109
|
-
id: cvId.value,
|
|
110
|
-
name: props.name,
|
|
111
|
-
order: dataOrder.value,
|
|
112
|
-
sortable: props.sortable,
|
|
113
|
-
});
|
|
83
|
+
headingIds.value.add(cvId.value);
|
|
84
|
+
if (props.sortable) {
|
|
85
|
+
sortableHeaders.value.add(cvId.value);
|
|
86
|
+
if (props.order !== 'none') onSortClick();
|
|
87
|
+
}
|
|
114
88
|
});
|
|
115
89
|
|
|
116
90
|
onBeforeUnmount(() => {
|
|
117
|
-
|
|
91
|
+
headingIds.value.delete(cvId.value);
|
|
92
|
+
sortableHeaders.value.delete(cvId.value);
|
|
118
93
|
});
|
|
119
|
-
|
|
120
|
-
|
|
94
|
+
|
|
95
|
+
const notifyHeaderSort = inject('cv:sort');
|
|
96
|
+
function onSortClick(ev) {
|
|
97
|
+
// If this is a click event, update to next sort order. Otherwise, this is
|
|
98
|
+
// being called from a watcher.
|
|
99
|
+
if (ev) dataOrder.value = nextOrder[dataOrder.value];
|
|
100
|
+
notifyHeaderSort({
|
|
121
101
|
heading: { id: cvId.value, name: props.name },
|
|
122
|
-
value:
|
|
102
|
+
value: dataOrder.value,
|
|
123
103
|
});
|
|
124
104
|
}
|
|
105
|
+
|
|
106
|
+
const currentSortHeadingId = inject('current-sort-heading-id', ref(null));
|
|
125
107
|
const internalOrder = computed(() => {
|
|
126
108
|
if (!props.sortable) {
|
|
127
109
|
return undefined;
|
|
128
110
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return heading.order;
|
|
132
|
-
else return 'none';
|
|
111
|
+
if (currentSortHeadingId.value !== cvId.value) return 'none';
|
|
112
|
+
return dataOrder.value;
|
|
133
113
|
});
|
|
134
114
|
|
|
135
115
|
const headingLabelTag = computed(() => {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
ref="row"
|
|
9
9
|
:row-id="cvId"
|
|
10
10
|
v-bind="$attrs"
|
|
11
|
+
:value="value"
|
|
11
12
|
:expanding-row="dataExpandable"
|
|
12
13
|
:expanded="dataExpanded"
|
|
13
14
|
@expanded-change="onExpandedChange"
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
v-bind="$attrs"
|
|
33
34
|
:id="cvId"
|
|
34
35
|
ref="row"
|
|
36
|
+
:value="rowValue"
|
|
35
37
|
class="cv-data-table-row"
|
|
36
38
|
:row-id="cvId"
|
|
37
39
|
@checked-change="onCheckedChange"
|
|
@@ -48,100 +50,99 @@ import {
|
|
|
48
50
|
computed,
|
|
49
51
|
onBeforeUnmount,
|
|
50
52
|
onMounted,
|
|
51
|
-
onUpdated,
|
|
52
53
|
ref,
|
|
53
54
|
useAttrs,
|
|
54
55
|
useSlots,
|
|
55
56
|
watch,
|
|
56
57
|
inject,
|
|
58
|
+
onUpdated,
|
|
57
59
|
} from 'vue';
|
|
58
|
-
import store from './cvDataTableStore';
|
|
59
|
-
import { getBus } from '../../global/component-utils/event-bus';
|
|
60
60
|
|
|
61
61
|
const props = defineProps({
|
|
62
|
+
/** The value associated with the input (required for tables with batch actions) */
|
|
63
|
+
value: { type: String, default: undefined },
|
|
64
|
+
/** This row will be initially expanded */
|
|
62
65
|
expanded: Boolean,
|
|
63
66
|
...propsCvId,
|
|
64
67
|
});
|
|
65
68
|
const cvId = useCvId(props, true);
|
|
69
|
+
// For historical reasons we have a prop named "value" but this makes the code
|
|
70
|
+
// hard to read since .value is used for refs. So it would be props.value
|
|
71
|
+
// which is weird. Let's shadow this as "rowValue"
|
|
72
|
+
const rowValue = ref(props.value);
|
|
73
|
+
watch(
|
|
74
|
+
() => props.value,
|
|
75
|
+
() => (rowValue.value = props.value)
|
|
76
|
+
);
|
|
66
77
|
|
|
67
78
|
/** @type {Ref<Set<String>>} */
|
|
68
79
|
const expandingRowIds = inject('expanding-row-ids', ref(new Set()));
|
|
69
80
|
const dataExpandable = ref(false);
|
|
70
81
|
watch(dataExpandable, () => {
|
|
71
|
-
if (dataExpandable.value) expandingRowIds.value
|
|
82
|
+
if (dataExpandable.value) expandingRowIds.value.add(cvId.value);
|
|
72
83
|
else expandingRowIds.value?.delete(cvId.value);
|
|
73
84
|
});
|
|
74
85
|
const dataSomeExpandingRows = computed(() => {
|
|
75
86
|
return expandingRowIds.value?.size > 0;
|
|
76
87
|
});
|
|
77
|
-
|
|
78
88
|
const attrs = useAttrs();
|
|
89
|
+
const rowIds = inject('row-ids', ref(new Set()));
|
|
90
|
+
const expandedRowIds = inject('expanded-row-ids', ref(new Set()));
|
|
91
|
+
|
|
79
92
|
const slots = useSlots();
|
|
80
93
|
const row = ref(null);
|
|
81
|
-
const
|
|
82
|
-
let bus;
|
|
83
|
-
onMounted(() => {
|
|
84
|
-
const el = row.value?.$el;
|
|
85
|
-
const pe = el?.closest('.cv-data-table');
|
|
86
|
-
parent.value = pe?.getAttribute('id');
|
|
87
|
-
if (parent.value) {
|
|
88
|
-
bus = getBus(parent);
|
|
89
|
-
store.getTable(parent);
|
|
90
|
-
} else console.warn('data table not found');
|
|
94
|
+
const rowsSelected = inject('rows-selected');
|
|
91
95
|
|
|
96
|
+
onMounted(() => {
|
|
92
97
|
dataExpandable.value = !!slots.expandedContent;
|
|
93
|
-
|
|
94
|
-
if (
|
|
95
|
-
console.error(
|
|
96
|
-
`CvDataTable: Duplicate ID specified for CvDataTableRow, may cause issues. {id: ${cvId.value}, value: ${attrs.value}}`
|
|
97
|
-
);
|
|
98
|
-
else
|
|
99
|
-
store.updateRow(parent, {
|
|
100
|
-
id: cvId.value,
|
|
101
|
-
value: attrs.value,
|
|
102
|
-
expandable: dataExpandable.value,
|
|
103
|
-
isExpanded: props.expanded,
|
|
104
|
-
isChecked: false,
|
|
105
|
-
});
|
|
98
|
+
rowIds.value.add(cvId.value);
|
|
99
|
+
if (props.expanded) expandedRowIds.value.add(cvId.value);
|
|
106
100
|
});
|
|
107
101
|
onUpdated(() => {
|
|
108
|
-
const curr = dataExpandable.value;
|
|
109
102
|
dataExpandable.value = !!slots.expandedContent;
|
|
110
|
-
if (dataExpandable.value !== curr)
|
|
111
|
-
store.updateRow(parent, {
|
|
112
|
-
id: cvId.value,
|
|
113
|
-
expandable: dataExpandable.value,
|
|
114
|
-
});
|
|
115
103
|
});
|
|
116
104
|
onBeforeUnmount(() => {
|
|
117
|
-
|
|
105
|
+
rowIds.value.delete(cvId.value);
|
|
106
|
+
expandingRowIds.value.delete(cvId.value);
|
|
107
|
+
expandedRowIds.value.delete(cvId.value);
|
|
108
|
+
const index = rowsSelected.value.indexOf(rowValue.value);
|
|
109
|
+
if (index > -1) rowsSelected.value.splice(index, 1);
|
|
118
110
|
});
|
|
119
111
|
const dataExpanded = computed(() => {
|
|
120
|
-
return Boolean(props.expanded ||
|
|
112
|
+
return Boolean(props.expanded || expandedRowIds.value.has(cvId.value));
|
|
121
113
|
});
|
|
122
114
|
watch(
|
|
123
115
|
() => props.expanded,
|
|
124
116
|
() => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
isExpanded: props.expanded,
|
|
128
|
-
});
|
|
117
|
+
if (props.expanded) expandedRowIds.value.add(cvId.value);
|
|
118
|
+
else expandingRowIds.value.delete(cvId.value);
|
|
129
119
|
}
|
|
130
120
|
);
|
|
131
121
|
|
|
122
|
+
const notifyExpandedChange = inject('cv:expanded-change');
|
|
123
|
+
|
|
132
124
|
function onExpandedChange(val) {
|
|
133
|
-
|
|
134
|
-
store.updateRow(parent, {
|
|
125
|
+
notifyExpandedChange({
|
|
135
126
|
id: cvId.value,
|
|
127
|
+
value: rowValue.value,
|
|
128
|
+
expandable: expandingRowIds.value.has(cvId.value),
|
|
136
129
|
isExpanded: val,
|
|
130
|
+
isChecked: rowsSelected.value.includes(rowValue.value),
|
|
137
131
|
});
|
|
138
|
-
bus?.emit('cv:expanded-change', row);
|
|
139
132
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
133
|
+
|
|
134
|
+
// Manage the checkmark on the row. Notify the table if it changes.
|
|
135
|
+
const notifyCheckedChange = inject('cv:check-change');
|
|
136
|
+
function onCheckedChange(isChecked) {
|
|
137
|
+
if (!rowsSelected.value) return;
|
|
138
|
+
const index = rowsSelected.value.indexOf(rowValue.value);
|
|
139
|
+
if (isChecked) {
|
|
140
|
+
// if the row value is not already in the rowsSelected array, add it.
|
|
141
|
+
if (index === -1) rowsSelected.value.push(rowValue.value);
|
|
142
|
+
} else {
|
|
143
|
+
// if the row value is in the rowsSelected array, delete it.
|
|
144
|
+
if (index > -1) rowsSelected.value.splice(index, 1);
|
|
145
|
+
}
|
|
146
|
+
notifyCheckedChange(attrs.value, isChecked);
|
|
146
147
|
}
|
|
147
148
|
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<tr
|
|
3
|
-
ref="el"
|
|
4
3
|
class="cv-data-table-row-inner"
|
|
4
|
+
:data-value="value"
|
|
5
5
|
:class="{
|
|
6
6
|
[`${carbonPrefix}--parent-row`]: expandingRow,
|
|
7
7
|
[`${carbonPrefix}--expandable-row`]: dataExpanded,
|
|
@@ -76,8 +76,6 @@ import {
|
|
|
76
76
|
watch,
|
|
77
77
|
inject,
|
|
78
78
|
} from 'vue';
|
|
79
|
-
import store from './cvDataTableStore';
|
|
80
|
-
import { getBus } from '../../global/component-utils/event-bus';
|
|
81
79
|
|
|
82
80
|
const props = defineProps({
|
|
83
81
|
ariaLabelForBatchCheckbox: { type: String, default: undefined },
|
|
@@ -124,21 +122,11 @@ function checkSlots() {
|
|
|
124
122
|
onMounted(checkSlots);
|
|
125
123
|
onUpdated(checkSlots);
|
|
126
124
|
|
|
127
|
-
const el = ref(null);
|
|
128
|
-
const parent = ref(null);
|
|
129
|
-
let bus;
|
|
130
|
-
onMounted(() => {
|
|
131
|
-
const pe = el.value.closest('.cv-data-table');
|
|
132
|
-
parent.value = pe?.getAttribute('id');
|
|
133
|
-
if (parent.value) {
|
|
134
|
-
store.getTable(parent);
|
|
135
|
-
bus = getBus(parent);
|
|
136
|
-
} else console.warn('data table not found');
|
|
137
|
-
});
|
|
138
125
|
const hasBatchActions = inject('has-batch-actions', ref(false));
|
|
139
126
|
|
|
127
|
+
const emitClick = inject('cv:click');
|
|
140
128
|
function onMenuItemClick(val) {
|
|
141
|
-
|
|
129
|
+
emitClick(val);
|
|
142
130
|
}
|
|
143
131
|
|
|
144
132
|
const emit = defineEmits(['expanded-change', 'checked-change']);
|
|
@@ -165,11 +153,14 @@ watch(
|
|
|
165
153
|
emit('checked-change', dataExpanded.value);
|
|
166
154
|
}
|
|
167
155
|
);
|
|
156
|
+
const rowsSelected = inject('rows-selected');
|
|
168
157
|
watch(
|
|
169
|
-
() =>
|
|
158
|
+
() => rowsSelected,
|
|
170
159
|
() => {
|
|
171
|
-
|
|
172
|
-
|
|
160
|
+
// For historical reasons we have a prop named "value" but this makes the code
|
|
161
|
+
// below look weird since .value is used for refs. So just a note that this
|
|
162
|
+
// is not a ref is a prop named "value"
|
|
163
|
+
const isChecked = rowsSelected.value.includes(props.value);
|
|
173
164
|
if (isChecked !== undefined) {
|
|
174
165
|
dataChecked.value = isChecked;
|
|
175
166
|
}
|