@carbon/vue 3.0.21 → 3.0.23

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 (54) hide show
  1. package/README.md +2 -3
  2. package/dist/carbon-vue-3.common.js +750 -1169
  3. package/dist/carbon-vue-3.common.js.map +1 -1
  4. package/dist/carbon-vue-3.umd.js +750 -1169
  5. package/dist/carbon-vue-3.umd.js.map +1 -1
  6. package/dist/carbon-vue-3.umd.min.js +4 -4
  7. package/dist/carbon-vue-3.umd.min.js.map +1 -1
  8. package/package.json +10 -7
  9. package/src/components/CvAspectRatio/CvAspectRatio.stories.js +2 -5
  10. package/src/components/CvBreadcrumb/CvBreadcrumb.stories.js +2 -5
  11. package/src/components/CvButton/CvButton.stories.js +1 -3
  12. package/src/components/CvButton/CvButtonSet.stories.js +2 -6
  13. package/src/components/CvButton/CvButtonSkeleton.stories.js +1 -3
  14. package/src/components/CvButton/CvIconButton.stories.js +1 -3
  15. package/src/components/CvCheckbox/CvCheckbox.stories.js +1 -2
  16. package/src/components/CvCodeSnippet/CvCodeSnippet.stories.js +1 -2
  17. package/src/components/CvComboBox/CvComboBox.stories.js +2 -5
  18. package/src/components/CvCopyButton/CvCopyButton.stories.js +2 -5
  19. package/src/components/CvDataTable/CvDataTable.stories.mdx +61 -30
  20. package/src/components/CvDataTable/CvDataTable.vue +73 -103
  21. package/src/components/CvDataTable/CvDataTableHeading.vue +25 -45
  22. package/src/components/CvDataTable/CvDataTableRow.vue +52 -51
  23. package/src/components/CvDataTable/_CvDataTableRowInner.vue +9 -18
  24. package/src/components/CvDatePicker/CvDatePicker.stories.js +2 -5
  25. package/src/components/CvDatePicker/CvDatePicker.vue +1 -1
  26. package/src/components/CvLink/CvLink.stories.js +1 -2
  27. package/src/components/CvList/CvList.stories.js +2 -5
  28. package/src/components/CvLoading/CvLoading.stories.js +2 -5
  29. package/src/components/CvMultiSelect/CvMultiSelect.vue +4 -1
  30. package/src/components/CvNotification/CvInlineNotification.stories.js +2 -2
  31. package/src/components/CvNotification/CvToastNotification.stories.js +2 -2
  32. package/src/components/CvNumberInput/CvNumberInput.stories.js +2 -6
  33. package/src/components/CvNumberInput/CvNumberInputSkeleton.stories.js +2 -6
  34. package/src/components/CvRadioButton/CvRadioButton.stories.js +2 -5
  35. package/src/components/CvSkeletonText/CvSkeletonText.stories.js +2 -5
  36. package/src/components/CvSlider/CvSlider.stories.js +2 -6
  37. package/src/components/CvSlider/CvSliderSkeleton.stories.js +2 -6
  38. package/src/components/CvStructuredList/CvStructuredList.stories.js +2 -5
  39. package/src/components/CvTag/CvTag.stories.js +2 -5
  40. package/src/components/CvTag/CvTagSkeleton.stories.js +2 -5
  41. package/src/components/CvTextArea/CvTextArea.stories.js +2 -6
  42. package/src/components/CvTextArea/CvTextAreaSkeleton.stories.js +2 -6
  43. package/src/components/CvTextInput/CvTextInput.stories.js +2 -5
  44. package/src/components/CvToggle/CvToggle.stories.js +2 -5
  45. package/src/components/CvTooltip/CvDefinitionTooltip.stories.js +2 -6
  46. package/src/components/CvTooltip/CvInteractiveTooltip.stories.js +2 -6
  47. package/src/components/CvTooltip/CvTooltip.stories.js +2 -6
  48. package/src/components/CvUIShell/CvContent.stories.js +22 -0
  49. package/src/components/CvUIShell/CvContent.vue +14 -0
  50. package/src/index.js +1 -0
  51. package/src/use/overflow.js +2 -2
  52. package/telemetry.yml +1 -1
  53. package/dist/web-types.json +0 -5555
  54. package/src/components/CvDataTable/cvDataTableStore.js +0 -314
@@ -132,7 +132,7 @@
132
132
  <thead>
133
133
  <tr>
134
134
  <th
135
- v-if="hasExpandingRows"
135
+ v-if="expandable"
136
136
  :class="`${carbonPrefix}--table-expand`"
137
137
  :data-previous-value="
138
138
  dataExpandAll ? 'collapsed' : 'expanded'
@@ -183,7 +183,7 @@
183
183
  </tr>
184
184
  </thead>
185
185
 
186
- <component :is="hasExpandingRows ? Empty : 'tbody'">
186
+ <component :is="expandable ? Empty : 'tbody'">
187
187
  <slot name="data">
188
188
  <cv-data-table-row
189
189
  v-for="(row, rowIndex) in data"
@@ -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);
@@ -378,11 +360,7 @@ const search = ref(null);
378
360
 
379
361
  /** @type {Ref<Set<String>>} */
380
362
  const expandingRowIds = ref(new Set());
381
- const hasExpandingRows = computed(() => {
382
- return expandingRowIds.value.size > 0;
383
- });
384
363
  provide('expanding-row-ids', expandingRowIds);
385
- provide('has-expanding-rows', hasExpandingRows);
386
364
  onMounted(() => {
387
365
  if (props.expandable) expandingRowIds.value.add('table-expand-row');
388
366
  });
@@ -393,6 +371,7 @@ watch(
393
371
  else expandingRowIds.value.delete('table-expand-row');
394
372
  }
395
373
  );
374
+ const clearSearchVisible = ref(false);
396
375
 
397
376
  onMounted(() => {
398
377
  if (searchContainer.value) {
@@ -416,6 +395,8 @@ onUpdated(checkSlots);
416
395
  const hasActions = ref(false);
417
396
  const hasToolbar = ref(false);
418
397
  const hasBatchActions = ref(false);
398
+ const isHelper = ref(false);
399
+
419
400
  provide('has-batch-actions', hasBatchActions);
420
401
 
421
402
  function checkSlots() {
@@ -442,9 +423,11 @@ function columnHeading(c) {
442
423
  }
443
424
  }
444
425
 
426
+ const sortableHeadings = ref(new Set());
427
+ provide('sortableHeadings', sortableHeadings);
445
428
  const isSortable = computed(() => {
446
429
  // is any column sortable
447
- return props.sortable || store.someSortableHeadings(uid.value);
430
+ return props.sortable || sortableHeadings.value.size > 0;
448
431
  });
449
432
 
450
433
  function isColSortable(c) {
@@ -453,7 +436,6 @@ function isColSortable(c) {
453
436
  return (col && col.sortable) || props.sortable;
454
437
  }
455
438
 
456
- const isHelper = ref(false);
457
439
  const hasTableHeader = computed(() => {
458
440
  return props.title || isHelper.value;
459
441
  });
@@ -482,13 +464,15 @@ const internalPagination = computed(() => {
482
464
  return false;
483
465
  });
484
466
 
485
- const registeredRows = ref([]);
467
+ const rowIds = ref(new Set());
468
+ provide('row-ids', rowIds);
469
+
486
470
  const internalNumberOfItems = computed(() => {
487
471
  const internal = internalPagination.value;
488
472
  if (internal.numberOfItems !== undefined) {
489
473
  return internal.numberOfItems;
490
474
  } else {
491
- return registeredRows.value.length;
475
+ return rowIds.value.size;
492
476
  }
493
477
  });
494
478
 
@@ -527,38 +511,29 @@ function checkSearchExpand(force) {
527
511
  }
528
512
 
529
513
  const dataRowsSelected = ref(props.rowsSelected);
530
- const batchActive = computed(() => {
531
- return (
532
- props.stickyBatchActive ||
533
- dataRowsSelected.value.length > 0 ||
534
- headingChecked.value
535
- );
536
- });
514
+ provide('rows-selected', dataRowsSelected);
537
515
 
538
516
  const headingChecked = ref(false);
539
-
540
517
  watch(
541
- () => store.state[uid.value],
518
+ () => dataRowsSelected,
542
519
  () => {
543
- const rows = store.rows(uid);
544
520
  headingChecked.value =
545
- rows.length > 0 && dataRowsSelected.value.length === rows.length;
521
+ rowIds.value.size > 0 &&
522
+ dataRowsSelected.value.length === rowIds.value.size;
546
523
  },
547
524
  { deep: true }
548
525
  );
526
+
527
+ const batchActive = computed(() => {
528
+ return (
529
+ props.stickyBatchActive ||
530
+ dataRowsSelected.value.length > 0 ||
531
+ headingChecked.value
532
+ );
533
+ });
534
+
549
535
  function updateRowsSelected() {
550
- dataRowsSelected.value = [];
551
- const rows = store.rows(uid);
552
- for (const i in rows) {
553
- let child = rows[i];
554
- const checked = props.rowsSelected.includes(child.value);
555
- store.updateRow(uid, { id: child.id, isChecked: checked });
556
-
557
- if (checked) {
558
- dataRowsSelected.value.push(child.value);
559
- }
560
- }
561
- headingChecked.value = dataRowsSelected.value.length === rows.length;
536
+ dataRowsSelected.value = [...props.rowsSelected];
562
537
  }
563
538
 
564
539
  const emit = defineEmits([
@@ -572,7 +547,6 @@ const emit = defineEmits([
572
547
  'pagination',
573
548
  ]);
574
549
  const searchValue = ref(props.initialSearchValue);
575
- const clearSearchVisible = ref(false);
576
550
  function onClearClick() {
577
551
  searchValue.value = '';
578
552
  clearSearchVisible.value = false;
@@ -584,87 +558,83 @@ function onClearClick() {
584
558
  }
585
559
  function onHeadingCheckChange() {
586
560
  // check /uncheck all children
587
- dataRowsSelected.value = [];
588
- const rows = store.rows(uid);
589
- for (const child of rows) {
590
- if (headingChecked.value) {
591
- dataRowsSelected.value.push(child.value);
592
- }
593
-
594
- if (child.isChecked !== headingChecked.value) {
595
- store.updateRow(uid, { id: child.id, isChecked: headingChecked.value });
596
-
597
- emit('row-select-change', {
598
- value: child.value,
599
- selected: headingChecked.value,
600
- });
601
- }
602
- }
603
- emit('row-select-changes', dataRowsSelected.value);
604
- emit('update:rowsSelected', dataRowsSelected.value);
561
+ if (headingChecked.value) dataRowsSelected.value = [...rowIds.value];
562
+ else dataRowsSelected.value = [];
605
563
  }
606
564
  function deselect() {
607
565
  headingChecked.value = false;
608
566
  onHeadingCheckChange();
609
567
  }
610
- function onRowCheckChange(payload) {
611
- const { value, checked } = payload;
612
- let modelSet = new Set(dataRowsSelected.value);
613
-
614
- if (!checked) {
615
- modelSet.delete(value);
616
- } else {
617
- modelSet.add(value);
618
- }
619
- dataRowsSelected.value = Array.from(modelSet);
620
- const rows = store.rows(uid);
621
- headingChecked.value = dataRowsSelected.value.length === rows.length;
622
568
 
569
+ const previousEmit = ref([...props.rowsSelected]);
570
+ watch(
571
+ dataRowsSelected,
572
+ () => {
573
+ // was tempted to use Set.symmetricDifference but support for that was only
574
+ // add in Feb/June 2024
575
+ const diff = dataRowsSelected.value
576
+ .filter(x => !previousEmit.value.includes(x))
577
+ .concat(
578
+ previousEmit.value.filter(x => !dataRowsSelected.value.includes(x))
579
+ );
580
+ if (diff.length > 0) {
581
+ emit('row-select-changes', dataRowsSelected.value);
582
+ emit('update:rowsSelected', dataRowsSelected.value);
583
+ previousEmit.value = [...dataRowsSelected.value];
584
+ }
585
+ },
586
+ { deep: true }
587
+ );
588
+ function onRowCheckChange(value, checked) {
623
589
  emit('row-select-change', { value, selected: checked });
624
- emit('row-select-changes', dataRowsSelected.value);
625
- emit('update:rowsSelected', dataRowsSelected.value);
626
590
  }
591
+ provide('cv:check-change', onRowCheckChange);
592
+
627
593
  function onMenuItemClick(val) {
628
594
  emit('overflow-menu-click', val);
629
595
  }
596
+ provide('cv:click', onMenuItemClick);
597
+
630
598
  function onInternalSearch() {
631
599
  clearSearchVisible.value = searchValue.value.length > 0;
632
600
  // eslint-disable-next-line vue/require-explicit-emits
633
601
  emit('search', searchValue.value);
634
602
  }
603
+
604
+ const headingIds = ref(new Set());
605
+ provide('heading-ids', headingIds);
606
+ const currentSortHeadingId = ref(null);
607
+ provide('current-sort-heading-id', currentSortHeadingId);
635
608
  function onSort(payload) {
636
609
  const { heading, value } = payload;
637
- const headings = store.headings(uid);
638
- let index;
639
- for (let colIndex in headings) {
640
- const column = headings[colIndex];
641
- if (column.id === heading.id) {
642
- store.updateHeading(uid, { ...column, order: value });
643
- index = colIndex;
644
- } else {
645
- store.updateHeading(uid, { ...column, order: 'none' });
646
- }
647
- }
610
+ const headings = Array.from(headingIds.value);
611
+ currentSortHeadingId.value = heading.id;
612
+ const index = headings.indexOf(heading.id);
648
613
  emit('sort', { index, order: value, name: heading.name });
649
614
  }
615
+ provide('cv:sort', onSort);
650
616
 
651
617
  // are all rows expanded
652
- const dataExpandAll = computed(() => {
653
- return store.allExpandedRows(uid);
654
- });
618
+ /** @type {Ref<Set<String>>} */
619
+ const expandedRowIds = ref(new Set());
620
+ provide('expanded-row-ids', expandedRowIds);
621
+
622
+ const dataExpandAll = computed(
623
+ () => expandedRowIds.value.size === rowIds.value.size
624
+ );
655
625
  function toggleExpandAll() {
656
626
  const toggle = !dataExpandAll.value;
657
- const rows = store.rows(uid);
658
- for (const row of rows) {
659
- store.updateRow(uid, { id: row.id, isExpanded: toggle });
660
- }
627
+ if (toggle) {
628
+ rowIds.value.forEach(rowId => expandedRowIds.value.add(rowId));
629
+ } else expandedRowIds.value.clear();
661
630
  }
662
631
 
663
632
  /**
664
633
  * A child row is changed
665
- * @param {{kind:string, uid:string, value:string, isExpanded:boolean}} row
634
+ * @param {{id:string, value:string, expandable:string, isExpanded:boolean, isChecked:boolean}} row
666
635
  */
667
636
  function onCvExpandedChange(row) {
668
637
  emit('row-expanded', row);
669
638
  }
639
+ provide('cv:expanded-change', onCvExpandedChange);
670
640
  </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
- store.updateHeading(parent, {
88
- id: cvId.value,
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
- let bus = undefined;
95
- const el = ref(null);
81
+ const headingIds = inject('heading-ids', ref(new Set()));
96
82
  onMounted(() => {
97
- const pe = el.value.closest('.cv-data-table');
98
- parent.value = pe?.getAttribute('id');
99
- if (parent.value) bus = getBus(parent);
100
- else console.warn('data table not found');
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
- store.removeHeading(parent, cvId);
91
+ headingIds.value.delete(cvId.value);
92
+ sortableHeaders.value.delete(cvId.value);
118
93
  });
119
- function onSortClick() {
120
- bus?.emit('cv:sort', {
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: nextOrder[internalOrder.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
- const heading = store.findHeading(parent, cvId);
130
- if (['ascending', 'descending', 'none'].includes(heading?.order))
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(() => {
@@ -33,7 +33,7 @@
33
33
  v-bind="$attrs"
34
34
  :id="cvId"
35
35
  ref="row"
36
- :value="value"
36
+ :value="rowValue"
37
37
  class="cv-data-table-row"
38
38
  :row-id="cvId"
39
39
  @checked-change="onCheckedChange"
@@ -50,15 +50,13 @@ import {
50
50
  computed,
51
51
  onBeforeUnmount,
52
52
  onMounted,
53
- onUpdated,
54
53
  ref,
55
54
  useAttrs,
56
55
  useSlots,
57
56
  watch,
58
57
  inject,
58
+ onUpdated,
59
59
  } from 'vue';
60
- import store from './cvDataTableStore';
61
- import { getBus } from '../../global/component-utils/event-bus';
62
60
 
63
61
  const props = defineProps({
64
62
  /** The value associated with the input (required for tables with batch actions) */
@@ -68,85 +66,88 @@ const props = defineProps({
68
66
  ...propsCvId,
69
67
  });
70
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
+ );
71
77
 
72
78
  /** @type {Ref<Set<String>>} */
73
79
  const expandingRowIds = inject('expanding-row-ids', ref(new Set()));
74
80
  const dataExpandable = ref(false);
75
- watch(dataExpandable, () => {
76
- if (dataExpandable.value) expandingRowIds.value?.add(cvId.value);
81
+ watch(dataExpandable, value => {
82
+ if (value && !expandingRowIds.value.has('table-expand-row')) {
83
+ console.warn(
84
+ `row ${cvId.value} is expandable but the expandable property is not set to true on the table`
85
+ );
86
+ }
87
+ if (dataExpandable.value) expandingRowIds.value.add(cvId.value);
77
88
  else expandingRowIds.value?.delete(cvId.value);
78
89
  });
79
90
  const dataSomeExpandingRows = computed(() => {
80
91
  return expandingRowIds.value?.size > 0;
81
92
  });
82
-
83
93
  const attrs = useAttrs();
94
+ const rowIds = inject('row-ids', ref(new Set()));
95
+ const expandedRowIds = inject('expanded-row-ids', ref(new Set()));
96
+
84
97
  const slots = useSlots();
85
98
  const row = ref(null);
86
- const parent = ref(null);
87
- let bus;
88
- onMounted(() => {
89
- const el = row.value?.$el;
90
- const pe = el?.closest('.cv-data-table');
91
- parent.value = pe?.getAttribute('id');
92
- if (parent.value) {
93
- bus = getBus(parent);
94
- store.getTable(parent);
95
- } else console.warn('data table not found');
99
+ const rowsSelected = inject('rows-selected');
96
100
 
101
+ onMounted(() => {
97
102
  dataExpandable.value = !!slots.expandedContent;
98
- const exists = store.findRow(parent, cvId);
99
- if (exists)
100
- console.error(
101
- `CvDataTable: Duplicate ID specified for CvDataTableRow, may cause issues. {id: ${cvId.value}, value: ${attrs.value}}`
102
- );
103
- else
104
- store.updateRow(parent, {
105
- id: cvId.value,
106
- value: attrs.value,
107
- expandable: dataExpandable.value,
108
- isExpanded: props.expanded,
109
- isChecked: false,
110
- });
103
+ rowIds.value.add(cvId.value);
104
+ if (props.expanded) expandedRowIds.value.add(cvId.value);
111
105
  });
112
106
  onUpdated(() => {
113
- const curr = dataExpandable.value;
114
107
  dataExpandable.value = !!slots.expandedContent;
115
- if (dataExpandable.value !== curr)
116
- store.updateRow(parent, {
117
- id: cvId.value,
118
- expandable: dataExpandable.value,
119
- });
120
108
  });
121
109
  onBeforeUnmount(() => {
122
- store.removeRow(parent, cvId);
110
+ rowIds.value.delete(cvId.value);
111
+ expandingRowIds.value.delete(cvId.value);
112
+ expandedRowIds.value.delete(cvId.value);
113
+ const index = rowsSelected.value.indexOf(rowValue.value);
114
+ if (index > -1) rowsSelected.value.splice(index, 1);
123
115
  });
124
116
  const dataExpanded = computed(() => {
125
- return Boolean(props.expanded || store.isRowExpanded(parent, cvId));
117
+ return Boolean(props.expanded || expandedRowIds.value.has(cvId.value));
126
118
  });
127
119
  watch(
128
120
  () => props.expanded,
129
121
  () => {
130
- store.updateRow(parent, {
131
- id: cvId.value,
132
- isExpanded: props.expanded,
133
- });
122
+ if (props.expanded) expandedRowIds.value.add(cvId.value);
123
+ else expandingRowIds.value.delete(cvId.value);
134
124
  }
135
125
  );
136
126
 
127
+ const notifyExpandedChange = inject('cv:expanded-change');
128
+
137
129
  function onExpandedChange(val) {
138
- const row = store.findRow(parent, cvId);
139
- store.updateRow(parent, {
130
+ notifyExpandedChange({
140
131
  id: cvId.value,
132
+ value: rowValue.value,
133
+ expandable: expandingRowIds.value.has(cvId.value),
141
134
  isExpanded: val,
135
+ isChecked: rowsSelected.value.includes(rowValue.value),
142
136
  });
143
- bus?.emit('cv:expanded-change', row);
144
137
  }
145
- function onCheckedChange(val) {
146
- store.updateRow(parent, {
147
- id: cvId.value,
148
- isChecked: val,
149
- });
150
- bus?.emit('cv:check-change', { value: props.value, checked: val });
138
+
139
+ // Manage the checkmark on the row. Notify the table if it changes.
140
+ const notifyCheckedChange = inject('cv:check-change');
141
+ function onCheckedChange(isChecked) {
142
+ if (!rowsSelected.value) return;
143
+ const index = rowsSelected.value.indexOf(rowValue.value);
144
+ if (isChecked) {
145
+ // if the row value is not already in the rowsSelected array, add it.
146
+ if (index === -1) rowsSelected.value.push(rowValue.value);
147
+ } else {
148
+ // if the row value is in the rowsSelected array, delete it.
149
+ if (index > -1) rowsSelected.value.splice(index, 1);
150
+ }
151
+ notifyCheckedChange(attrs.value, isChecked);
151
152
  }
152
153
  </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
- bus.emit('cv:click', val);
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
- () => store.state[parent.value]?.rows,
158
+ () => rowsSelected,
170
159
  () => {
171
- const row = store.findRow(parent, props.rowId);
172
- const isChecked = row?.isChecked;
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
  }
@@ -1,7 +1,4 @@
1
- import {
2
- sbCompPrefix,
3
- storyParametersObject,
4
- } from '../../global/storybook-utils';
1
+ import { storyParametersObject } from '../../global/storybook-utils';
5
2
 
6
3
  import { CvDatePicker } from '.';
7
4
  import { CvDatePickerSkeleton } from '.';
@@ -20,7 +17,7 @@ tomorrow.setDate(now.getDate() + 1);
20
17
  nextWeek.setDate(now.getDate() + 7);
21
18
 
22
19
  export default {
23
- title: `${sbCompPrefix}/CvDatePicker`,
20
+ title: 'Component/CvDatePicker',
24
21
  component: CvDatePicker,
25
22
  parameters: {
26
23
  a11y: {
@@ -311,7 +311,7 @@ watch(
311
311
  () => props.calOptions,
312
312
  () => {
313
313
  for (const [key, value] of Object.entries(props.calOptions)) {
314
- calendar.value.set(key, value);
314
+ calendar.value?.set(key, value);
315
315
  }
316
316
  },
317
317
  { deep: true }