@vueye-table/headless 3.0.0-alpha.8 → 3.0.0-alpha.9
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/index.d.ts +237 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +396 -79
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { injectDataGrid, injectDataTable, provideDataGrid, provideDataTable, useDataGrid, useVirtualColumns, useVirtualRows } from "@vueye-table/vue";
|
|
2
2
|
import { Fragment, computed, defineComponent, h, inject, nextTick, onMounted, onScopeDispose, provide, ref, shallowRef, useId, watch } from "vue";
|
|
3
|
+
import { getRowItemKey, gridCommand } from "@vueye-table/core";
|
|
3
4
|
|
|
4
5
|
//#region src/shared.ts
|
|
5
6
|
/** The element a component renders. Every headless component accepts `as`. */
|
|
@@ -76,14 +77,16 @@ const DataTableSelectRow = defineComponent({
|
|
|
76
77
|
setup(props, { slots }) {
|
|
77
78
|
const table = injectDataTable("<DataTableSelectRow>");
|
|
78
79
|
return () => {
|
|
79
|
-
const selected = table.isSelected(props.row.key);
|
|
80
|
+
const selected = table.tree ? props.row.selection === "all" : table.isSelected(props.row.key);
|
|
81
|
+
const indeterminate = table.tree && props.row.selection === "some";
|
|
80
82
|
const toggle = () => table.toggleRow(props.row.key);
|
|
81
83
|
return slots.default?.({
|
|
82
84
|
selected,
|
|
85
|
+
indeterminate,
|
|
83
86
|
toggle
|
|
84
87
|
}) ?? checkbox({
|
|
85
88
|
checked: selected,
|
|
86
|
-
indeterminate
|
|
89
|
+
indeterminate,
|
|
87
90
|
label: props.label,
|
|
88
91
|
disabled: table.selectionMode === "none",
|
|
89
92
|
onChange: toggle
|
|
@@ -262,14 +265,16 @@ const DataTableStatus = defineComponent({
|
|
|
262
265
|
loadError: table.loadError,
|
|
263
266
|
canLoadMore: table.canLoadMore,
|
|
264
267
|
retry: () => table.retry(),
|
|
265
|
-
loadNext: () => table.loadNext()
|
|
268
|
+
loadNext: () => table.loadNext(),
|
|
269
|
+
loadingChildrenCount: table.tree ? table.processedRows.filter((row) => row.childStatus === "loading").length : 0,
|
|
270
|
+
childErrorCount: table.tree ? table.processedRows.filter((row) => row.childStatus === "error").length : 0
|
|
266
271
|
};
|
|
267
272
|
const count = `Loaded ${table.loadedRowCount.toLocaleString()} ${table.loadedRowCount === 1 ? "row" : "rows"}`;
|
|
268
273
|
const text = table.loadingMode ? table.loadState === "error" ? `${count}. Could not load rows. Retry loading.` : table.loadState === "aborted" ? `${count}. Loading stopped.` : table.loadState === "loading" || table.loadState === "streaming" ? `${count}…` : `${count}${table.loadState === "done" ? ". All rows loaded." : "."}` : table.rowCount === 0 ? "No rows" : `${table.pageStart}–${table.pageEnd} of ${table.rowCount} rows` + (table.selectedCount > 0 ? `, ${table.selectedCount} selected` : "");
|
|
269
274
|
return h(props.as, {
|
|
270
275
|
role: "status",
|
|
271
276
|
"aria-live": "polite"
|
|
272
|
-
}, slots.default?.(slotProps) ?? text);
|
|
277
|
+
}, slots.default?.(slotProps) ?? text + (slotProps.loadingChildrenCount ? " Loading children…" : "") + (slotProps.childErrorCount ? " Could not load children. Retry children in the affected row." : ""));
|
|
273
278
|
};
|
|
274
279
|
}
|
|
275
280
|
});
|
|
@@ -556,6 +561,269 @@ function virtualRow(binding, row) {
|
|
|
556
561
|
return binding.rowItems.find((item) => item.renderItem.kind === "row" && item.renderItem.row.key === row.key);
|
|
557
562
|
}
|
|
558
563
|
|
|
564
|
+
//#endregion
|
|
565
|
+
//#region src/hierarchy.ts
|
|
566
|
+
const hierarchyProps = {
|
|
567
|
+
treeColumn: {
|
|
568
|
+
type: String,
|
|
569
|
+
default: void 0
|
|
570
|
+
},
|
|
571
|
+
keepAliveDetail: {
|
|
572
|
+
type: Boolean,
|
|
573
|
+
default: false
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
const hierarchyKey = Symbol("vueye-table-hierarchy");
|
|
577
|
+
function provideHierarchy(table, props) {
|
|
578
|
+
const focus = shallowRef();
|
|
579
|
+
const focusKey = computed(() => table.rows.some((row) => row.key === focus.value) ? focus.value : table.rows[0]?.key);
|
|
580
|
+
const context = {
|
|
581
|
+
id: `vt-tree-${useId()}`,
|
|
582
|
+
table,
|
|
583
|
+
get treeColumn() {
|
|
584
|
+
return props.treeColumn;
|
|
585
|
+
},
|
|
586
|
+
get keepAliveDetail() {
|
|
587
|
+
return props.keepAliveDetail;
|
|
588
|
+
},
|
|
589
|
+
focus,
|
|
590
|
+
get focusKey() {
|
|
591
|
+
return focusKey.value;
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
provide(hierarchyKey, context);
|
|
595
|
+
return context;
|
|
596
|
+
}
|
|
597
|
+
function injectHierarchy() {
|
|
598
|
+
return inject(hierarchyKey, void 0);
|
|
599
|
+
}
|
|
600
|
+
function resolveTreeColumn(table, column) {
|
|
601
|
+
return table.columns.find((candidate) => candidate.id === column)?.id ?? table.columns[0]?.id;
|
|
602
|
+
}
|
|
603
|
+
function itemId(context, row, detail = false) {
|
|
604
|
+
return context ? `${context.id}-${encodeURIComponent(getRowItemKey(row.key, detail ? "detail" : "row"))}` : void 0;
|
|
605
|
+
}
|
|
606
|
+
const siblingCache = /* @__PURE__ */ new WeakMap();
|
|
607
|
+
function hierarchyRowAttrs(table, row, context) {
|
|
608
|
+
if (!table.tree) return {};
|
|
609
|
+
let positions = siblingCache.get(table.processedRows);
|
|
610
|
+
if (!positions) {
|
|
611
|
+
const groups = /* @__PURE__ */ new Map();
|
|
612
|
+
for (const candidate of table.processedRows) {
|
|
613
|
+
const group = groups.get(candidate.parentKey) ?? [];
|
|
614
|
+
group.push(candidate);
|
|
615
|
+
groups.set(candidate.parentKey, group);
|
|
616
|
+
}
|
|
617
|
+
const indices = new Map(table.processedRows.map((candidate, index) => [candidate.key, index]));
|
|
618
|
+
const result = /* @__PURE__ */ new Map();
|
|
619
|
+
for (const group of groups.values()) group.forEach((candidate, index) => result.set(candidate.key, {
|
|
620
|
+
position: index + 1,
|
|
621
|
+
size: group.length,
|
|
622
|
+
index: indices.get(candidate.key)
|
|
623
|
+
}));
|
|
624
|
+
positions = result;
|
|
625
|
+
siblingCache.set(table.processedRows, result);
|
|
626
|
+
}
|
|
627
|
+
const position = positions.get(row.key);
|
|
628
|
+
return {
|
|
629
|
+
id: itemId(context, row),
|
|
630
|
+
"data-tree-key": getRowItemKey(row.key),
|
|
631
|
+
"aria-level": row.depth + 1,
|
|
632
|
+
"aria-expanded": row.canExpand ? String(row.isExpanded) : void 0,
|
|
633
|
+
"aria-setsize": position?.size,
|
|
634
|
+
"aria-posinset": position?.position,
|
|
635
|
+
"aria-rowindex": position ? position.index + 2 : void 0,
|
|
636
|
+
"aria-busy": row.childStatus === "loading" ? "true" : void 0
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
/** Row-focused table navigation; cell-focused grids use the same pure core commands. */
|
|
640
|
+
function treeKeydown(event, context, virtual) {
|
|
641
|
+
const table = context.table;
|
|
642
|
+
const target = event.target;
|
|
643
|
+
if (!table.tree || !target?.closest) return;
|
|
644
|
+
if (target.closest("input, textarea, select, [contenteditable=true]") || target.closest("button") && !target.closest("[data-expand-toggle]")) return;
|
|
645
|
+
const key = target.closest("tr")?.getAttribute("data-tree-key");
|
|
646
|
+
const index = table.rows.findIndex((row) => getRowItemKey(row.key) === key);
|
|
647
|
+
const row = table.rows[index];
|
|
648
|
+
if (!row) return;
|
|
649
|
+
const command = gridCommand(event, {
|
|
650
|
+
canExpand: row.canExpand,
|
|
651
|
+
expanded: row.isExpanded
|
|
652
|
+
});
|
|
653
|
+
let next = row;
|
|
654
|
+
if (command?.type === "tree") {
|
|
655
|
+
if (command.action === "expand" || command.action === "collapse") table.toggleExpanded(row.key, command.action === "expand");
|
|
656
|
+
else if (command.action === "siblings") for (const sibling of table.processedRows.filter((candidate) => candidate.parentKey === row.parentKey && candidate.canExpand)) table.toggleExpanded(sibling.key, true);
|
|
657
|
+
else if (command.action === "child") next = table.rows.find((candidate) => candidate.parentKey === row.key) ?? row;
|
|
658
|
+
else next = table.rows.find((candidate) => candidate.key === row.parentKey) ?? row;
|
|
659
|
+
} else if (event.key === "ArrowDown" || event.key === "ArrowUp") next = table.rows[index + (event.key === "ArrowDown" ? 1 : -1)] ?? row;
|
|
660
|
+
else if (event.key === "Home" || event.key === "End") next = table.rows[event.key === "Home" ? 0 : table.rows.length - 1] ?? row;
|
|
661
|
+
else return;
|
|
662
|
+
event.preventDefault();
|
|
663
|
+
context.focus.value = next.key;
|
|
664
|
+
virtual?.rows.scrollToKey(next.key);
|
|
665
|
+
const id = itemId(context, next);
|
|
666
|
+
nextTick(() => target.closest("table")?.ownerDocument.getElementById(id ?? "")?.focus());
|
|
667
|
+
}
|
|
668
|
+
const expandToggleProps = {
|
|
669
|
+
row: rowProp,
|
|
670
|
+
controls: {
|
|
671
|
+
type: String,
|
|
672
|
+
default: void 0
|
|
673
|
+
},
|
|
674
|
+
expandLabel: {
|
|
675
|
+
type: String,
|
|
676
|
+
default: "Expand row"
|
|
677
|
+
},
|
|
678
|
+
collapseLabel: {
|
|
679
|
+
type: String,
|
|
680
|
+
default: "Collapse row"
|
|
681
|
+
}
|
|
682
|
+
};
|
|
683
|
+
const treeCellProps = {
|
|
684
|
+
row: rowProp,
|
|
685
|
+
as: asProp("div")
|
|
686
|
+
};
|
|
687
|
+
const DataTableExpandToggle = defineComponent({
|
|
688
|
+
name: "DataTableExpandToggle",
|
|
689
|
+
props: expandToggleProps,
|
|
690
|
+
slots: Object,
|
|
691
|
+
setup(props, { slots }) {
|
|
692
|
+
const table = injectDataTable("<DataTableExpandToggle>");
|
|
693
|
+
const context = injectHierarchy();
|
|
694
|
+
const grid = injectDataGrid();
|
|
695
|
+
return () => props.row.canExpand ? h("button", {
|
|
696
|
+
type: "button",
|
|
697
|
+
"data-expand-toggle": "",
|
|
698
|
+
tabindex: table.tree ? -1 : void 0,
|
|
699
|
+
"aria-expanded": String(props.row.isExpanded),
|
|
700
|
+
"aria-controls": props.controls ?? (!table.tree ? itemId(context, props.row, true) : props.row.isExpanded ? table.rows.filter((row) => row.parentKey === props.row.key).map((row) => itemId(context, row)).filter(Boolean).join(" ") || void 0 : void 0),
|
|
701
|
+
"aria-label": props.row.isExpanded ? props.collapseLabel : props.expandLabel,
|
|
702
|
+
onMousedown: (event) => event.stopPropagation(),
|
|
703
|
+
onDblclick: (event) => event.stopPropagation(),
|
|
704
|
+
onClick: (event) => {
|
|
705
|
+
event.stopPropagation();
|
|
706
|
+
if (grid?.table === table) grid.focusCell({
|
|
707
|
+
row: table.rows.indexOf(props.row),
|
|
708
|
+
column: Math.max(0, table.columns.findIndex((column) => column.id === resolveTreeColumn(table, context?.treeColumn)))
|
|
709
|
+
});
|
|
710
|
+
table.toggleExpanded(props.row.key);
|
|
711
|
+
if (grid?.table === table) nextTick(() => event.target.closest("table")?.focus());
|
|
712
|
+
}
|
|
713
|
+
}, slots.default?.({
|
|
714
|
+
row: props.row,
|
|
715
|
+
expanded: props.row.isExpanded
|
|
716
|
+
}) ?? (props.row.isExpanded ? props.collapseLabel : props.expandLabel)) : null;
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
const DataTableTreeCell = defineComponent({
|
|
720
|
+
name: "DataTableTreeCell",
|
|
721
|
+
props: treeCellProps,
|
|
722
|
+
slots: Object,
|
|
723
|
+
setup(props, { slots }) {
|
|
724
|
+
const table = injectDataTable("<DataTableTreeCell>");
|
|
725
|
+
const context = injectHierarchy();
|
|
726
|
+
const grid = injectDataGrid();
|
|
727
|
+
return () => h(props.as, {
|
|
728
|
+
class: "vt-tree-cell",
|
|
729
|
+
"data-tree-cell": "",
|
|
730
|
+
style: { paddingInlineStart: `calc(var(--vt-tree-indent, 1.25rem) * ${props.row.depth})` }
|
|
731
|
+
}, [
|
|
732
|
+
h("span", { class: "vt-tree-toggle" }, slots.toggle?.({ row: props.row }) ?? h(DataTableExpandToggle, { row: props.row })),
|
|
733
|
+
h("span", { class: "vt-tree-label" }, [slots.default?.()]),
|
|
734
|
+
props.row.childStatus === "loading" ? h("span", { class: "vt-tree-loading" }, "Loading children…") : null,
|
|
735
|
+
props.row.childStatus === "error" ? h("span", { class: "vt-tree-error" }, ["Could not load children. ", h("button", {
|
|
736
|
+
type: "button",
|
|
737
|
+
class: "vt-tree-retry",
|
|
738
|
+
onMousedown: (event) => event.stopPropagation(),
|
|
739
|
+
onClick: (event) => {
|
|
740
|
+
event.stopPropagation();
|
|
741
|
+
const element = event.currentTarget.closest("table");
|
|
742
|
+
if (grid?.table === table) grid.focusCell({
|
|
743
|
+
row: table.rows.indexOf(props.row),
|
|
744
|
+
column: Math.max(0, table.columns.findIndex((column) => column.id === resolveTreeColumn(table, context?.treeColumn)))
|
|
745
|
+
});
|
|
746
|
+
table.toggleExpanded(props.row.key, true);
|
|
747
|
+
nextTick(() => {
|
|
748
|
+
if (grid?.table === table) element?.focus();
|
|
749
|
+
else element?.ownerDocument.getElementById(itemId(context, props.row) ?? "")?.focus();
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
}, "Retry children")]) : null
|
|
753
|
+
]);
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
/** One full-width detail; retained collapsed content remains hidden and unmeasured. */
|
|
757
|
+
const DataTableDetailRow = defineComponent({
|
|
758
|
+
name: "DataTableDetailRow",
|
|
759
|
+
props: {
|
|
760
|
+
row: rowProp,
|
|
761
|
+
colspan: {
|
|
762
|
+
type: Number,
|
|
763
|
+
default: void 0
|
|
764
|
+
},
|
|
765
|
+
hidden: {
|
|
766
|
+
type: Boolean,
|
|
767
|
+
default: false
|
|
768
|
+
},
|
|
769
|
+
keepAlive: {
|
|
770
|
+
type: Boolean,
|
|
771
|
+
default: void 0
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
slots: Object,
|
|
775
|
+
setup(props, { slots }) {
|
|
776
|
+
const table = injectDataTable("<DataTableDetailRow>");
|
|
777
|
+
const context = injectHierarchy();
|
|
778
|
+
const virtual = injectVirtual();
|
|
779
|
+
let opened = false;
|
|
780
|
+
return () => {
|
|
781
|
+
if (props.row.isExpanded && !props.hidden) opened = true;
|
|
782
|
+
if (!opened || (!props.row.isExpanded || props.hidden) && !(props.keepAlive ?? context?.keepAliveDetail)) return null;
|
|
783
|
+
const hidden = props.hidden || !props.row.isExpanded;
|
|
784
|
+
return h("tr", {
|
|
785
|
+
id: itemId(context, props.row, true),
|
|
786
|
+
"data-detail": "",
|
|
787
|
+
hidden,
|
|
788
|
+
...virtual && !hidden ? { ref: (target) => virtual.rows.measureElement(target, getRowItemKey(props.row.key, "detail")) } : {}
|
|
789
|
+
}, [h("td", {
|
|
790
|
+
colspan: Math.max(1, props.colspan ?? table.columns.length),
|
|
791
|
+
class: "vt-detail-cell"
|
|
792
|
+
}, [slots.default?.({ row: props.row })])]);
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
function createDetails(table, slot, colspan) {
|
|
797
|
+
const context = injectHierarchy();
|
|
798
|
+
const visited = /* @__PURE__ */ new Set();
|
|
799
|
+
const render = (row, rowIndex, hidden = false) => {
|
|
800
|
+
if (!hidden && context?.keepAliveDetail) visited.add(row.key);
|
|
801
|
+
return h(DataTableDetailRow, {
|
|
802
|
+
key: getRowItemKey(row.key, "detail"),
|
|
803
|
+
row,
|
|
804
|
+
colspan: colspan(),
|
|
805
|
+
hidden
|
|
806
|
+
}, { default: () => slot()?.({
|
|
807
|
+
row,
|
|
808
|
+
rowIndex
|
|
809
|
+
}) });
|
|
810
|
+
};
|
|
811
|
+
return {
|
|
812
|
+
render,
|
|
813
|
+
retained(visible) {
|
|
814
|
+
if (!context?.keepAliveDetail) return [];
|
|
815
|
+
return [...visited].flatMap((key) => {
|
|
816
|
+
const index = table.rows.findIndex((row) => row.key === key);
|
|
817
|
+
if (index < 0) {
|
|
818
|
+
visited.delete(key);
|
|
819
|
+
return [];
|
|
820
|
+
}
|
|
821
|
+
return visible.has(key) ? [] : [render(table.rows[index], index, true)];
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
|
|
559
827
|
//#endregion
|
|
560
828
|
//#region src/table.ts
|
|
561
829
|
/**
|
|
@@ -571,16 +839,20 @@ const DataTableRoot = defineComponent({
|
|
|
571
839
|
required: true
|
|
572
840
|
},
|
|
573
841
|
as: asProp("table"),
|
|
574
|
-
...virtualProps
|
|
842
|
+
...virtualProps,
|
|
843
|
+
...hierarchyProps
|
|
575
844
|
},
|
|
576
845
|
setup(props, { slots }) {
|
|
577
846
|
provideDataTable(props.table);
|
|
847
|
+
const hierarchy = provideHierarchy(props.table, props);
|
|
578
848
|
const element = shallowRef();
|
|
579
849
|
const render = (virtual) => h(props.as, {
|
|
580
|
-
|
|
850
|
+
role: props.table.tree ? "treegrid" : void 0,
|
|
851
|
+
"aria-rowcount": (props.table.tree ? props.table.processedRows.length : props.table.rowCount) + 1,
|
|
581
852
|
"aria-colcount": props.table.columns.length,
|
|
582
853
|
"aria-busy": props.table.loadState === "loading" || props.table.loadState === "streaming" ? "true" : void 0,
|
|
583
854
|
"data-empty": flag(props.table.rowCount === 0),
|
|
855
|
+
onKeydown: (event) => treeKeydown(event, hierarchy, virtual),
|
|
584
856
|
...virtual ? {
|
|
585
857
|
ref: element,
|
|
586
858
|
"data-virtual": ""
|
|
@@ -729,20 +1001,28 @@ const DataTableBody = defineComponent({
|
|
|
729
1001
|
setup(props, { slots }) {
|
|
730
1002
|
const table = injectDataTable("<DataTableBody>");
|
|
731
1003
|
const virtual = injectVirtual();
|
|
1004
|
+
const details = createDetails(table, () => slots.detail, () => props.colspan ?? table.columns.length);
|
|
732
1005
|
return () => {
|
|
733
1006
|
if (props.virtual && !virtual) return h(VirtualDataTableBody, props, slots);
|
|
734
|
-
if (virtual) return renderTableBody(table, virtual, props.as, props.colspan, slots);
|
|
1007
|
+
if (virtual) return renderTableBody(table, virtual, props.as, props.colspan, slots, details);
|
|
735
1008
|
let content = slots.default?.({ rows: table.rows });
|
|
736
|
-
if (!content) content = table.rows.length === 0 && slots.empty ? h("tr", { "data-empty": "" }, [h("td", { colspan: Math.max(1, table.columns.length) }, slots.empty())]) : table.
|
|
737
|
-
key:
|
|
738
|
-
row
|
|
739
|
-
|
|
1009
|
+
if (!content) content = table.rows.length === 0 && slots.empty ? h("tr", { "data-empty": "" }, [h("td", { colspan: Math.max(1, table.columns.length) }, slots.empty())]) : table.renderItems.map((item) => item.kind === "row" ? slots.row ? h(Fragment, { key: item.key }, [slots.row(item)]) : h(DataTableRow, {
|
|
1010
|
+
key: item.key,
|
|
1011
|
+
row: item.row,
|
|
1012
|
+
rowIndex: item.rowIndex
|
|
1013
|
+
}) : details.render(item.row, item.rowIndex));
|
|
1014
|
+
const visibleDetails = new Set(table.renderItems.filter((item) => item.kind === "detail").map((item) => item.row.key));
|
|
1015
|
+
const retained = slots.default ? [] : details.retained(visibleDetails);
|
|
740
1016
|
const sentinel = loadSentinel(table, props.colspan ?? table.columns.length);
|
|
741
|
-
return h(props.as,
|
|
1017
|
+
return h(props.as, [
|
|
1018
|
+
...Array.isArray(content) ? content : content ? [content] : [],
|
|
1019
|
+
...retained,
|
|
1020
|
+
...sentinel ? [sentinel] : []
|
|
1021
|
+
]);
|
|
742
1022
|
};
|
|
743
1023
|
}
|
|
744
1024
|
});
|
|
745
|
-
function renderTableBody(table, virtual, as, colspan, slots, element) {
|
|
1025
|
+
function renderTableBody(table, virtual, as, colspan, slots, details, element) {
|
|
746
1026
|
const width = colspan ?? table.columns.length;
|
|
747
1027
|
const attrs = element ? { ref: element } : {};
|
|
748
1028
|
const content = slots.default?.({ rows: virtual.rowItems.filter((item) => item.renderItem.kind === "row").map((item) => item.renderItem.row) });
|
|
@@ -753,15 +1033,15 @@ function renderTableBody(table, virtual, as, colspan, slots, element) {
|
|
|
753
1033
|
rowSpacer(virtual.rows.paddingEnd, width, "gap-end"),
|
|
754
1034
|
...loadSentinel(table, width) ? [loadSentinel(table, width)] : []
|
|
755
1035
|
]);
|
|
756
|
-
return h(as, attrs, [
|
|
757
|
-
key: item.key,
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
"
|
|
763
|
-
|
|
764
|
-
|
|
1036
|
+
return h(as, attrs, [
|
|
1037
|
+
...renderRows(virtual, width, (item) => item.renderItem.kind === "row" ? slots.row ? h(Fragment, { key: item.key }, [slots.row(item.renderItem)]) : h(DataTableRow, {
|
|
1038
|
+
key: item.key,
|
|
1039
|
+
row: item.renderItem.row,
|
|
1040
|
+
rowIndex: item.renderItem.rowIndex
|
|
1041
|
+
}) : details.render(item.renderItem.row, item.renderItem.rowIndex)),
|
|
1042
|
+
...details.retained(new Set(virtual.rowItems.filter((item) => item.renderItem.kind === "detail").map((item) => item.renderItem.row.key))),
|
|
1043
|
+
...loadSentinel(table, width) ? [loadSentinel(table, width)] : []
|
|
1044
|
+
]);
|
|
765
1045
|
}
|
|
766
1046
|
const VirtualDataTableBody = defineComponent({
|
|
767
1047
|
name: "DataTableVirtualBody",
|
|
@@ -778,7 +1058,8 @@ const VirtualDataTableBody = defineComponent({
|
|
|
778
1058
|
const table = injectDataTable("<DataTableBody>");
|
|
779
1059
|
const element = shallowRef();
|
|
780
1060
|
const virtual = createComponentVirtual(table, virtualOptions(props), () => element.value?.closest("table"));
|
|
781
|
-
|
|
1061
|
+
const details = createDetails(table, () => slots.detail, () => props.colspan ?? table.columns.length);
|
|
1062
|
+
return () => renderTableBody(table, virtual, props.as, props.colspan, slots, details, element);
|
|
782
1063
|
}
|
|
783
1064
|
});
|
|
784
1065
|
/** A body row; `aria-selected` and `data-selected` follow the selection. */
|
|
@@ -796,6 +1077,7 @@ const DataTableRow = defineComponent({
|
|
|
796
1077
|
setup(props, { slots }) {
|
|
797
1078
|
const table = injectDataTable("<DataTableRow>");
|
|
798
1079
|
const virtual = injectVirtual();
|
|
1080
|
+
const hierarchy = injectHierarchy();
|
|
799
1081
|
return () => {
|
|
800
1082
|
const { row } = props;
|
|
801
1083
|
const selected = table.isSelected(row.key);
|
|
@@ -806,6 +1088,11 @@ const DataTableRow = defineComponent({
|
|
|
806
1088
|
"aria-selected": table.selectionMode === "none" ? void 0 : String(selected),
|
|
807
1089
|
"data-selected": flag(selected),
|
|
808
1090
|
"data-key": String(row.key),
|
|
1091
|
+
...hierarchyRowAttrs(table, row, hierarchy),
|
|
1092
|
+
tabindex: table.tree ? (hierarchy?.focusKey ?? table.rows[0]?.key) === row.key ? 0 : -1 : void 0,
|
|
1093
|
+
onFocus: () => {
|
|
1094
|
+
if (hierarchy) hierarchy.focus.value = row.key;
|
|
1095
|
+
},
|
|
809
1096
|
...virtual && item ? {
|
|
810
1097
|
ref: (element) => virtual.rows.measureElement(element, item.key),
|
|
811
1098
|
"data-virtual-row": ""
|
|
@@ -829,22 +1116,29 @@ const DataTableCell = defineComponent({
|
|
|
829
1116
|
props: {
|
|
830
1117
|
row: rowProp,
|
|
831
1118
|
column: columnProp,
|
|
832
|
-
as: asProp("td")
|
|
1119
|
+
as: asProp("td"),
|
|
1120
|
+
tree: {
|
|
1121
|
+
type: Boolean,
|
|
1122
|
+
default: true
|
|
1123
|
+
}
|
|
833
1124
|
},
|
|
834
1125
|
setup(props, { slots }) {
|
|
1126
|
+
const table = injectDataTable("<DataTableCell>");
|
|
1127
|
+
const hierarchy = injectHierarchy();
|
|
835
1128
|
return () => {
|
|
836
1129
|
const { row, column } = props;
|
|
837
1130
|
const value = row.getValue(column.id);
|
|
838
1131
|
const display = row.getDisplay(column.id);
|
|
839
|
-
|
|
840
|
-
"data-column": column.id,
|
|
841
|
-
"data-align": column.align
|
|
842
|
-
}, slots.default?.({
|
|
1132
|
+
const content = () => slots.default?.({
|
|
843
1133
|
row,
|
|
844
1134
|
column,
|
|
845
1135
|
value,
|
|
846
1136
|
display
|
|
847
|
-
}) ?? display
|
|
1137
|
+
}) ?? display;
|
|
1138
|
+
return h(props.as, {
|
|
1139
|
+
"data-column": column.id,
|
|
1140
|
+
"data-align": column.align
|
|
1141
|
+
}, props.tree && table.tree && column.id === resolveTreeColumn(table, hierarchy?.treeColumn) ? h(DataTableTreeCell, { row }, { default: content }) : content());
|
|
848
1142
|
};
|
|
849
1143
|
}
|
|
850
1144
|
});
|
|
@@ -893,6 +1187,7 @@ const DataGridRoot = defineComponent({
|
|
|
893
1187
|
default: void 0
|
|
894
1188
|
},
|
|
895
1189
|
...virtualProps,
|
|
1190
|
+
...hierarchyProps,
|
|
896
1191
|
/** Width reserved before data columns, for a row-number/header column. */
|
|
897
1192
|
gutter: {
|
|
898
1193
|
type: Number,
|
|
@@ -901,8 +1196,9 @@ const DataGridRoot = defineComponent({
|
|
|
901
1196
|
},
|
|
902
1197
|
setup(props, { slots, expose }) {
|
|
903
1198
|
provideDataTable(props.table);
|
|
904
|
-
const grid = useDataGrid(props.table);
|
|
1199
|
+
const grid = useDataGrid(props.table, { treeColumn: () => props.treeColumn });
|
|
905
1200
|
provideDataGrid(grid);
|
|
1201
|
+
provideHierarchy(props.table, props);
|
|
906
1202
|
const element = ref();
|
|
907
1203
|
const id = `vt-grid-${useId()}`;
|
|
908
1204
|
const focus = () => {
|
|
@@ -964,11 +1260,11 @@ const DataGridRoot = defineComponent({
|
|
|
964
1260
|
return h(props.as, {
|
|
965
1261
|
ref: element,
|
|
966
1262
|
id,
|
|
967
|
-
role: "grid",
|
|
1263
|
+
role: props.table.tree ? "treegrid" : "grid",
|
|
968
1264
|
tabindex: 0,
|
|
969
1265
|
"aria-label": props.label,
|
|
970
1266
|
"aria-multiselectable": "true",
|
|
971
|
-
"aria-rowcount": (binding ? props.table.rowCount : props.table.rows.length) + 1,
|
|
1267
|
+
"aria-rowcount": (props.table.tree ? props.table.processedRows.length : binding ? props.table.rowCount : props.table.rows.length) + 1,
|
|
972
1268
|
"aria-colcount": props.table.columns.length,
|
|
973
1269
|
"aria-busy": props.table.loadState === "loading" || props.table.loadState === "streaming" ? "true" : void 0,
|
|
974
1270
|
"aria-activedescendant": focusPosition && !grid.editor ? cellId(id, focusPosition.row, focusPosition.column) : void 0,
|
|
@@ -1015,12 +1311,18 @@ const DataGridBody = defineComponent({
|
|
|
1015
1311
|
colspan: {
|
|
1016
1312
|
type: Number,
|
|
1017
1313
|
default: void 0
|
|
1314
|
+
},
|
|
1315
|
+
treeCell: {
|
|
1316
|
+
type: Boolean,
|
|
1317
|
+
default: true
|
|
1018
1318
|
}
|
|
1019
1319
|
},
|
|
1020
1320
|
setup(props, { slots }) {
|
|
1021
1321
|
const table = injectDataTable("<DataGridBody>");
|
|
1022
1322
|
const { grid } = useGrid("<DataGridBody>");
|
|
1023
1323
|
const virtual = injectVirtual();
|
|
1324
|
+
const hierarchy = injectHierarchy();
|
|
1325
|
+
const details = createDetails(table, () => slots.detail, () => props.colspan ?? table.columns.length + (slots.rowHeader ? 1 : 0));
|
|
1024
1326
|
const element = ref();
|
|
1025
1327
|
const render = (binding) => {
|
|
1026
1328
|
if (binding && slots.default) {
|
|
@@ -1028,53 +1330,60 @@ const DataGridBody = defineComponent({
|
|
|
1028
1330
|
const content = slots.default({ rows: binding.rowItems.filter((item) => item.renderItem.kind === "row").map((item) => item.renderItem.row) });
|
|
1029
1331
|
return h(props.as, { ref: element }, sentinel ? [...content, sentinel] : content);
|
|
1030
1332
|
}
|
|
1031
|
-
if (binding) return h(props.as, { ref: element }, [
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1333
|
+
if (binding) return h(props.as, { ref: element }, [
|
|
1334
|
+
...renderRows(binding, props.colspan ?? table.columns.length + (slots.rowHeader ? 1 : 0), (item) => {
|
|
1335
|
+
if (item.renderItem.kind !== "row") return details.render(item.renderItem.row, item.renderItem.rowIndex);
|
|
1336
|
+
const { row, rowIndex } = item.renderItem;
|
|
1337
|
+
const columns = renderColumns(table.columns, binding, (column, columnIndex) => h(DataGridCell, {
|
|
1338
|
+
key: column.id,
|
|
1339
|
+
row,
|
|
1340
|
+
column,
|
|
1341
|
+
rowIndex,
|
|
1342
|
+
columnIndex,
|
|
1343
|
+
tree: props.treeCell
|
|
1344
|
+
}, slots.cell ? { default: (cellProps) => slots.cell?.(cellProps) } : void 0), "td");
|
|
1345
|
+
return h("tr", {
|
|
1346
|
+
key: item.key,
|
|
1347
|
+
role: "row",
|
|
1348
|
+
"aria-rowindex": table.pageStart + rowIndex + 1,
|
|
1349
|
+
"data-key": String(row.key),
|
|
1350
|
+
...hierarchyRowAttrs(table, row, hierarchy),
|
|
1351
|
+
"data-virtual-row": "",
|
|
1352
|
+
ref: (target) => binding.rows.measureElement(target, item.key)
|
|
1353
|
+
}, [slots.rowHeader?.({
|
|
1354
|
+
row,
|
|
1355
|
+
index: rowIndex
|
|
1356
|
+
}), ...columns]);
|
|
1357
|
+
}),
|
|
1358
|
+
...details.retained(new Set(binding.rowItems.filter((item) => item.renderItem.kind === "detail").map((item) => item.renderItem.row.key))),
|
|
1359
|
+
...loadSentinel(table, props.colspan ?? table.columns.length + (slots.rowHeader ? 1 : 0)) ? [loadSentinel(table, props.colspan ?? table.columns.length + (slots.rowHeader ? 1 : 0))] : []
|
|
1360
|
+
]);
|
|
1361
|
+
const content = slots.default?.({ rows: table.rows }) ?? table.renderItems.map((item) => item.kind === "detail" ? details.render(item.row, item.rowIndex) : (() => {
|
|
1362
|
+
const { row, rowIndex } = item;
|
|
1049
1363
|
return h("tr", {
|
|
1050
1364
|
key: item.key,
|
|
1051
1365
|
role: "row",
|
|
1052
|
-
"aria-rowindex":
|
|
1366
|
+
"aria-rowindex": rowIndex + 2,
|
|
1053
1367
|
"data-key": String(row.key),
|
|
1054
|
-
|
|
1055
|
-
ref: (target) => binding.rows.measureElement(target, item.key)
|
|
1368
|
+
...hierarchyRowAttrs(table, row, hierarchy)
|
|
1056
1369
|
}, [slots.rowHeader?.({
|
|
1057
1370
|
row,
|
|
1058
1371
|
index: rowIndex
|
|
1059
|
-
}), ...columns
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
index: rowIndex
|
|
1069
|
-
}), ...table.columns.map((column, columnIndex) => h(DataGridCell, {
|
|
1070
|
-
key: column.id,
|
|
1071
|
-
row,
|
|
1072
|
-
column,
|
|
1073
|
-
rowIndex,
|
|
1074
|
-
columnIndex
|
|
1075
|
-
}, slots.cell ? { default: (cellProps) => slots.cell?.(cellProps) } : void 0))]));
|
|
1372
|
+
}), ...table.columns.map((column, columnIndex) => h(DataGridCell, {
|
|
1373
|
+
key: column.id,
|
|
1374
|
+
row,
|
|
1375
|
+
column,
|
|
1376
|
+
rowIndex,
|
|
1377
|
+
columnIndex,
|
|
1378
|
+
tree: props.treeCell
|
|
1379
|
+
}, slots.cell ? { default: (cellProps) => slots.cell?.(cellProps) } : void 0))]);
|
|
1380
|
+
})());
|
|
1076
1381
|
const sentinel = loadSentinel(table, props.colspan ?? table.columns.length + (slots.rowHeader ? 1 : 0));
|
|
1077
|
-
return h(props.as,
|
|
1382
|
+
return h(props.as, [
|
|
1383
|
+
...content,
|
|
1384
|
+
...slots.default ? [] : details.retained(new Set(table.renderItems.filter((item) => item.kind === "detail").map((item) => item.row.key))),
|
|
1385
|
+
sentinel
|
|
1386
|
+
]);
|
|
1078
1387
|
};
|
|
1079
1388
|
return () => props.virtual && !virtual ? h(VirtualContent, {
|
|
1080
1389
|
table,
|
|
@@ -1142,6 +1451,10 @@ const DataGridCell = defineComponent({
|
|
|
1142
1451
|
row: rowProp,
|
|
1143
1452
|
column: columnProp,
|
|
1144
1453
|
as: asProp("td"),
|
|
1454
|
+
tree: {
|
|
1455
|
+
type: Boolean,
|
|
1456
|
+
default: true
|
|
1457
|
+
},
|
|
1145
1458
|
/** The row's position on the page. Found by searching the rows when left out. */
|
|
1146
1459
|
rowIndex: {
|
|
1147
1460
|
type: Number,
|
|
@@ -1157,6 +1470,7 @@ const DataGridCell = defineComponent({
|
|
|
1157
1470
|
const table = injectDataTable("<DataGridCell>");
|
|
1158
1471
|
const { grid, context } = useGrid("<DataGridCell>");
|
|
1159
1472
|
const virtual = injectVirtual();
|
|
1473
|
+
const hierarchy = injectHierarchy();
|
|
1160
1474
|
const element = ref();
|
|
1161
1475
|
const position = () => ({
|
|
1162
1476
|
row: props.rowIndex ?? table.rows.indexOf(props.row),
|
|
@@ -1182,13 +1496,16 @@ const DataGridCell = defineComponent({
|
|
|
1182
1496
|
commit: (then) => grid.commitEdit(then),
|
|
1183
1497
|
cancel: () => grid.cancelEdit()
|
|
1184
1498
|
}) ?? h(DataGridEditor, { label: `Edit ${column.header}` });
|
|
1185
|
-
else
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1499
|
+
else {
|
|
1500
|
+
const children = () => slots.default?.({
|
|
1501
|
+
row,
|
|
1502
|
+
column,
|
|
1503
|
+
value,
|
|
1504
|
+
display,
|
|
1505
|
+
editable
|
|
1506
|
+
}) ?? display;
|
|
1507
|
+
content = props.tree && table.tree && column.id === resolveTreeColumn(table, hierarchy?.treeColumn) ? h(DataTableTreeCell, { row }, { default: children }) : children();
|
|
1508
|
+
}
|
|
1192
1509
|
return h(props.as, {
|
|
1193
1510
|
ref: element,
|
|
1194
1511
|
id: cellId(context.id, at.row, at.column),
|
|
@@ -1221,5 +1538,5 @@ const DataGridCell = defineComponent({
|
|
|
1221
1538
|
});
|
|
1222
1539
|
|
|
1223
1540
|
//#endregion
|
|
1224
|
-
export { DataGridBody, DataGridCell, DataGridRoot, DataTableBody, DataTableCaption, DataTableCell, DataTableColumnVisibility, DataTableEmpty, DataTableHeader, DataTableHeaderCell, DataTableHeaderRow, DataTableLoadMore, DataTablePageSize, DataTablePagination, DataTableRoot, DataTableRow, DataTableSearch, DataTableSelectAll, DataTableSelectRow, DataTableSortButton, DataTableStatus, DataTableViewport, DataTableVirtualColumns, cellId, columnStyle, injectVirtual as injectVirtualRenderer, virtualProps };
|
|
1541
|
+
export { DataGridBody, DataGridCell, DataGridRoot, DataTableBody, DataTableCaption, DataTableCell, DataTableColumnVisibility, DataTableDetailRow, DataTableEmpty, DataTableExpandToggle, DataTableHeader, DataTableHeaderCell, DataTableHeaderRow, DataTableLoadMore, DataTablePageSize, DataTablePagination, DataTableRoot, DataTableRow, DataTableSearch, DataTableSelectAll, DataTableSelectRow, DataTableSortButton, DataTableStatus, DataTableTreeCell, DataTableViewport, DataTableVirtualColumns, cellId, columnStyle, expandToggleProps, hierarchyProps, injectVirtual as injectVirtualRenderer, resolveTreeColumn, treeCellProps, virtualProps };
|
|
1225
1542
|
//# sourceMappingURL=index.js.map
|