nuxt-ui-tools 1.16.10 → 1.17.0

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 (39) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/i18n/locales/en.js +8 -0
  3. package/dist/runtime/i18n/locales/fr.js +8 -0
  4. package/dist/runtime/i18n/types.d.ts +8 -0
  5. package/dist/runtime/table/components/table/table-layout.d.ts +2 -0
  6. package/dist/runtime/table/components/table/table-layout.js +1 -0
  7. package/dist/runtime/table/components/table/table-renderer.d.vue.ts +6 -6
  8. package/dist/runtime/table/components/table/table-renderer.vue +75 -11
  9. package/dist/runtime/table/components/table/table-renderer.vue.d.ts +6 -6
  10. package/dist/runtime/table/components/table/table-row.d.vue.ts +15 -2
  11. package/dist/runtime/table/components/table/table-row.vue +23 -2
  12. package/dist/runtime/table/components/table/table-row.vue.d.ts +15 -2
  13. package/dist/runtime/table/components/table/table-tree-control.d.vue.ts +19 -0
  14. package/dist/runtime/table/components/table/table-tree-control.vue +112 -0
  15. package/dist/runtime/table/components/table/table-tree-control.vue.d.ts +19 -0
  16. package/dist/runtime/table/components/table/table-tree-header.d.vue.ts +3 -0
  17. package/dist/runtime/table/components/table/table-tree-header.vue +66 -0
  18. package/dist/runtime/table/components/table/table-tree-header.vue.d.ts +3 -0
  19. package/dist/runtime/table/composables/use-table-api.d.ts +2 -0
  20. package/dist/runtime/table/composables/use-table-api.js +2 -0
  21. package/dist/runtime/table/composables/use-table-internals.d.ts +48 -0
  22. package/dist/runtime/table/composables/use-table-internals.js +13 -4
  23. package/dist/runtime/table/composables/use-table-selection.d.ts +2 -0
  24. package/dist/runtime/table/composables/use-table-selection.js +15 -6
  25. package/dist/runtime/table/composables/use-table-tree.d.ts +36 -0
  26. package/dist/runtime/table/composables/use-table-tree.js +199 -0
  27. package/dist/runtime/table/types/index.d.ts +1 -0
  28. package/dist/runtime/table/types/layout.d.ts +3 -2
  29. package/dist/runtime/table/types/table-api.d.ts +6 -0
  30. package/dist/runtime/table/types/tree.d.ts +100 -0
  31. package/dist/runtime/table/types/tree.js +0 -0
  32. package/dist/runtime/table/utils/columns/defs.js +19 -2
  33. package/dist/runtime/table/utils/columns/types.d.ts +6 -1
  34. package/dist/runtime/table/utils/columns/types.js +7 -0
  35. package/dist/runtime/table/utils/index.d.ts +1 -0
  36. package/dist/runtime/table/utils/index.js +1 -0
  37. package/dist/runtime/table/utils/tree.d.ts +64 -0
  38. package/dist/runtime/table/utils/tree.js +112 -0
  39. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "configKey": "nuxtUiTools",
6
6
  "docs": "https://ui.nuxt.com/docs/getting-started/installation/nuxt",
7
7
  "name": "nuxt-ui-tools",
8
- "version": "1.16.10",
8
+ "version": "1.17.0",
9
9
  "builder": {
10
10
  "@nuxt/module-builder": "1.0.3",
11
11
  "unbuild": "unknown"
@@ -727,6 +727,14 @@ export default defineUiToolsLocale({
727
727
  rowOther: "rows",
728
728
  selection: "Selection",
729
729
  total: "Total"
730
+ },
731
+ tree: {
732
+ collapse: "Collapse row",
733
+ collapseAll: "Collapse all rows",
734
+ expand: "Expand row",
735
+ expandAll: "Expand all rows",
736
+ selectAll: "Select all rows",
737
+ selectRow: "Select row"
730
738
  }
731
739
  }
732
740
  },
@@ -727,6 +727,14 @@ export default defineUiToolsLocale({
727
727
  rowOther: "lignes",
728
728
  selection: "S\xE9lection",
729
729
  total: "Total"
730
+ },
731
+ tree: {
732
+ collapse: "Replier la ligne",
733
+ collapseAll: "Replier toutes les lignes",
734
+ expand: "D\xE9plier la ligne",
735
+ expandAll: "D\xE9plier toutes les lignes",
736
+ selectAll: "S\xE9lectionner toutes les lignes",
737
+ selectRow: "S\xE9lectionner la ligne"
730
738
  }
731
739
  }
732
740
  },
@@ -50,6 +50,14 @@ export interface UiToolsTableMessages {
50
50
  rowOne: string;
51
51
  rowOther: string;
52
52
  };
53
+ tree: {
54
+ expand: string;
55
+ collapse: string;
56
+ expandAll: string;
57
+ collapseAll: string;
58
+ selectRow: string;
59
+ selectAll: string;
60
+ };
53
61
  columnsMenu: {
54
62
  sortAsc: string;
55
63
  sortDesc: string;
@@ -24,6 +24,7 @@ export declare function columnCellLayout(params: {
24
24
  }): {
25
25
  class: import("vue").ClassValue[];
26
26
  innerClass: string;
27
+ internal: import("../../utils/index.js").DataListColumnInternalKind | undefined;
27
28
  render: ((params: {
28
29
  row: import("../../types/index.js").GenericObject;
29
30
  index: number;
@@ -45,6 +46,7 @@ export declare function tableRowCells(params: {
45
46
  layout: {
46
47
  class: import("vue").ClassValue[];
47
48
  innerClass: string;
49
+ internal: import("../../utils/index.js").DataListColumnInternalKind | undefined;
48
50
  render: ((params: {
49
51
  row: import("../../types/index.js").GenericObject;
50
52
  index: number;
@@ -12,6 +12,7 @@ export function columnCellLayout(params) {
12
12
  params.tdClass
13
13
  ],
14
14
  innerClass: meta?.align === "right" ? "justify-end" : meta?.align === "center" ? "justify-center" : "",
15
+ internal: meta?.internal,
15
16
  render: meta?.render,
16
17
  style: [params.offset, meta?.lines ? { "--nut-dl-lines": meta.lines } : void 0]
17
18
  };
@@ -8,7 +8,7 @@ type __VLS_Props = {
8
8
  ui?: DataListTableUi;
9
9
  };
10
10
  declare function refresh(): void;
11
- declare var __VLS_33: {
11
+ declare var __VLS_41: {
12
12
  columnSlots: TableColumnSlot[];
13
13
  leafColumns: import("@tanstack/table-core").Column<{
14
14
  columnPinningFeature: import("@tanstack/table-core").TableFeature;
@@ -18,16 +18,16 @@ declare var __VLS_33: {
18
18
  coreRowModel: (table: import("@tanstack/table-core").Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
19
19
  columnMeta: import("../../utils/index.js").DataListColumnMeta;
20
20
  }, object, unknown>[];
21
- }, __VLS_35: {
21
+ }, __VLS_43: {
22
22
  error: {};
23
23
  retry: typeof refresh;
24
- }, __VLS_44: {};
24
+ }, __VLS_52: {};
25
25
  type __VLS_Slots = {} & {
26
- footer?: (props: typeof __VLS_33) => any;
26
+ footer?: (props: typeof __VLS_41) => any;
27
27
  } & {
28
- error?: (props: typeof __VLS_35) => any;
28
+ error?: (props: typeof __VLS_43) => any;
29
29
  } & {
30
- empty?: (props: typeof __VLS_44) => any;
30
+ empty?: (props: typeof __VLS_52) => any;
31
31
  };
32
32
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
33
33
  resetColumnSizing: () => void;
@@ -10,8 +10,17 @@ import { mergeDataListUiClass } from "../../utils";
10
10
  import {
11
11
  ROW_ACTIONS_COLUMN_ID,
12
12
  SELECT_COLUMN_ID,
13
- SELECT_COLUMN_WIDTH
13
+ SELECT_COLUMN_WIDTH,
14
+ TREE_COLUMN_ID
14
15
  } from "../../utils/columns/types";
16
+ import {
17
+ TREE_CHECK_WIDTH,
18
+ TREE_GAP,
19
+ TREE_GUTTER_WIDTH,
20
+ TREE_LEAD,
21
+ TREE_TOGGLE_WIDTH,
22
+ getTreeColumnWidth
23
+ } from "../../utils/tree";
15
24
  import DataListErrorState from "../data-list/data-list-error-state.vue";
16
25
  import ProgressLine from "../layout/progress-line.vue";
17
26
  import TableCell from "./table-cell";
@@ -21,6 +30,7 @@ import { columnCellLayout, tableRowCells } from "./table-layout";
21
30
  import TableOverlayScrollbars from "./table-overlay-scrollbars.vue";
22
31
  import TableRow from "./table-row.vue";
23
32
  import TableSkeletonCell from "./table-skeleton-cell";
33
+ import TableTreeHeader from "./table-tree-header.vue";
24
34
  const LOAD_MORE_THRESHOLD = 6;
25
35
  const PREFETCH_VIEWPORTS = 3;
26
36
  const VIRTUALIZE_ROW_THRESHOLD = 40;
@@ -43,6 +53,7 @@ const props = defineProps({
43
53
  ui: { type: Object, required: false }
44
54
  });
45
55
  const internals = useTableInternals();
56
+ const { tree } = internals;
46
57
  const dataListUi = useDataListUi();
47
58
  const { locale, t } = useUiToolsLocale();
48
59
  const rows = computed(
@@ -76,21 +87,35 @@ const tokenStyle = computed(() => ({
76
87
  "--nut-dl-foot-h": `${tokens.value.head - 2}px`,
77
88
  "--nut-dl-gutter": `${gutter.value}px`,
78
89
  "--nut-dl-head-h": `${tokens.value.head}px`,
79
- "--nut-dl-row-h": `${tokens.value.row}px`
90
+ "--nut-dl-row-h": `${tokens.value.row}px`,
91
+ "--nut-dl-tree-gutter": `${TREE_GUTTER_WIDTH}px`,
92
+ "--nut-dl-tree-toggle": `${TREE_TOGGLE_WIDTH}px`,
93
+ "--nut-dl-tree-gap": `${TREE_GAP}px`,
94
+ "--nut-dl-tree-check": `${treeCheckWidth.value}px`,
95
+ "--nut-dl-tree-lead": `${treeLead.value}px`
80
96
  }));
81
97
  const { columnDefs } = internals.tableColumns;
82
98
  const columnState = internals.tableColumns.tableState;
99
+ const treeLead = computed(() => Math.max(TREE_LEAD, gutter.value - 2));
100
+ const treeCheckWidth = computed(() => TREE_CHECK_WIDTH[dataListUi.controlSize.value]);
83
101
  const columnSizing = computed({
84
102
  get: () => {
85
103
  const sizing = columnState.value.columnSizing ?? {};
86
- if (!gutterExtra.value) {
104
+ const ids = new Set(columnDefs.value.map((def) => def.id));
105
+ const hasTree = ids.has(TREE_COLUMN_ID);
106
+ if (!gutterExtra.value && !hasTree) {
87
107
  return sizing;
88
108
  }
89
- const ids = new Set(columnDefs.value.map((def) => def.id));
90
109
  const next = { ...sizing };
91
- if (ids.has(SELECT_COLUMN_ID) && !(SELECT_COLUMN_ID in sizing)) {
110
+ if (ids.has(SELECT_COLUMN_ID) && !(SELECT_COLUMN_ID in sizing) && gutterExtra.value) {
92
111
  next[SELECT_COLUMN_ID] = SELECT_COLUMN_WIDTH + gutterExtra.value;
93
112
  }
113
+ if (hasTree)
114
+ next[TREE_COLUMN_ID] = getTreeColumnWidth({
115
+ check: treeCheckWidth.value,
116
+ lead: treeLead.value,
117
+ maxDepth: tree.index.value.maxDepth
118
+ });
94
119
  return next;
95
120
  },
96
121
  set: (columnSizing2) => {
@@ -100,20 +125,27 @@ const columnSizing = computed({
100
125
  const pinned = computed(() => {
101
126
  const ids = new Set(columnDefs.value.map((def) => def.id));
102
127
  const left = (columnState.value.columnPinning?.left ?? []).filter(
103
- (id) => ids.has(id) && id !== SELECT_COLUMN_ID
128
+ (id) => ids.has(id) && id !== SELECT_COLUMN_ID && id !== TREE_COLUMN_ID
104
129
  );
105
130
  const right = (columnState.value.columnPinning?.right ?? []).filter(
106
131
  (id) => ids.has(id) && id !== ROW_ACTIONS_COLUMN_ID
107
132
  );
108
133
  return {
109
134
  end: ids.has(ROW_ACTIONS_COLUMN_ID) ? [...right, ROW_ACTIONS_COLUMN_ID] : right,
110
- start: ids.has(SELECT_COLUMN_ID) ? [SELECT_COLUMN_ID, ...left] : left
135
+ start: [
136
+ ...ids.has(SELECT_COLUMN_ID) ? [SELECT_COLUMN_ID] : [],
137
+ ...ids.has(TREE_COLUMN_ID) ? [TREE_COLUMN_ID] : [],
138
+ ...left
139
+ ]
111
140
  };
112
141
  });
113
142
  function getRowId(row, index) {
114
143
  return internals.selection.getRowId({ index, row });
115
144
  }
116
- const renderRows = computed(() => rowsMounted.value ? rows.value : []);
145
+ const sourceRows = computed(
146
+ () => tree.enabled.value && rows.value.length > 0 ? tree.visibleRows.value : rows.value
147
+ );
148
+ const renderRows = computed(() => rowsMounted.value ? sourceRows.value : []);
117
149
  const virtualized = computed(
118
150
  () => renderRows.value.length >= VIRTUALIZE_ROW_THRESHOLD || renderRows.value.length * columnDefs.value.length >= VIRTUALIZE_CELL_THRESHOLD
119
151
  );
@@ -358,7 +390,7 @@ onBeforeUnmount(() => {
358
390
  resizeObserver?.disconnect();
359
391
  });
360
392
  watch(
361
- [totalWidth, () => rows.value.length],
393
+ [totalWidth, () => sourceRows.value.length],
362
394
  () => nextTick().then(() => {
363
395
  columnVirtualizer.value.measure();
364
396
  scrollbarsRef.value?.measure();
@@ -512,6 +544,25 @@ watch(
512
544
  }, APPEND_WINDOW);
513
545
  }
514
546
  );
547
+ function isAppended(rowId, flatIndex) {
548
+ return (tree.nodeOf(rowId)?.rootIndex ?? flatIndex) >= appendedFrom.value;
549
+ }
550
+ function hasCheckbox(rowId) {
551
+ const node = tree.nodeOf(rowId);
552
+ return internals.selection.selectionEnabled.value && node !== void 0 && tree.isSelectable(node);
553
+ }
554
+ function onSelectRow(rowId, event) {
555
+ internals.selection.toggleRowSelection({
556
+ rowId,
557
+ selected: !internals.selection.isRowSelected({ rowId }),
558
+ shiftKey: event.shiftKey
559
+ });
560
+ }
561
+ function onBodyPointerOver(event) {
562
+ if (!tree.enabled.value || event.pointerType === "touch") return;
563
+ const row = event.target instanceof Element ? event.target.closest("tr") : null;
564
+ tree.lightLineage(row?.dataset.rowId);
565
+ }
515
566
  function skeletonColumn(columnId) {
516
567
  const meta = headerByColumnId.value.get(columnId)?.column.columnDef.meta;
517
568
  if (meta?.internal === "selection") return { align: meta.align, skeleton: "check" };
@@ -646,6 +697,11 @@ defineExpose({ resetColumnSizing });
646
697
  :row="HEADER_ROW"
647
698
  :index="-1"
648
699
  />
700
+ <TableTreeHeader
701
+ v-else-if="
702
+ headerByColumnId.get(slot.columnId).column.columnDef.meta?.internal === 'tree'
703
+ "
704
+ />
649
705
  </div>
650
706
  </template>
651
707
  <TableColumnHeader
@@ -662,6 +718,8 @@ defineExpose({ resetColumnSizing });
662
718
  <tbody
663
719
  :class="mergeDataListUiClass('nut-dl-table__body', void 0, ui?.tbody)"
664
720
  :data-replacing="replacing"
721
+ @pointerover="onBodyPointerOver"
722
+ @pointerleave="tree.lightLineage()"
665
723
  >
666
724
  <tr
667
725
  v-if="virtualPaddingTop"
@@ -681,8 +739,14 @@ defineExpose({ resetColumnSizing });
681
739
  :index="virtual.index"
682
740
  :cells="rowCells"
683
741
  :selected="internals.selection.isRowSelected({ rowId: String(row.id) })"
684
- :appended="virtual.index >= appendedFrom"
742
+ :appended="isAppended(row.id, virtual.index)"
685
743
  :row-class="rowClass"
744
+ :node="tree.nodeOf(row.id)"
745
+ :expanded="tree.isExpanded(row.id)"
746
+ :checkbox="hasCheckbox(row.id)"
747
+ :motion="tree.motionOf(row.id)"
748
+ @toggle="tree.toggleRow(row.id)"
749
+ @select="onSelectRow(row.id, $event)"
686
750
  />
687
751
 
688
752
  <tr
@@ -870,5 +934,5 @@ defineExpose({ resetColumnSizing });
870
934
  <style>
871
935
  .nut-dl-table{--nut-dl-surface:var(--nut-dl-table-surface,var(--ui-bg-elevated));--nut-dl-line:var(--nut-dl-table-line,var(--ui-border));--nut-dl-line-soft:var(--nut-dl-table-line-soft,var(--ui-border-muted));--nut-dl-head-bg:var(--nut-dl-table-head-bg,var(--ui-bg-muted));--nut-dl-head-fg:var(--nut-dl-table-head-fg,var(--ui-text-muted));--nut-dl-head-font:var(--nut-dl-table-head-font,11px);--nut-dl-head-weight:var(--nut-dl-table-head-weight,600);--nut-dl-head-tracking:var(--nut-dl-table-head-tracking,0.04em);--nut-dl-head-transform:var(--nut-dl-table-head-transform,none);--nut-dl-row-hover:var(--nut-dl-table-row-hover,var(--ui-bg-muted));--nut-dl-row-selected:var(
872
936
  --nut-dl-table-row-selected,color-mix(in srgb,var(--ui-primary) 10%,var(--nut-dl-surface))
873
- );--nut-dl-accent:var(--ui-primary);--nut-dl-cell-fg:var(--nut-dl-table-cell-fg,var(--ui-text-toned));--nut-dl-pin-line:var(--nut-dl-table-pin-line,var(--nut-dl-line))}.nut-dl-table__scroll{overflow-anchor:none;scrollbar-width:none}.nut-dl-table__scroll::-webkit-scrollbar{display:none}.nut-dl-th{color:var(--nut-dl-head-fg);font-size:var(--nut-dl-head-font);font-weight:var(--nut-dl-head-weight);letter-spacing:var(--nut-dl-head-tracking);text-transform:var(--nut-dl-head-transform);-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap}.nut-dl-table__fill,.nut-dl-table__spacer,.nut-dl-th{background:var(--nut-dl-head-bg);border-bottom:1px solid var(--nut-dl-line)}.nut-dl-tf{background:var(--nut-dl-head-bg);border-top:1px solid var(--nut-dl-line);color:var(--ui-text-highlighted);font-weight:var(--nut-dl-table-foot-weight,500);white-space:nowrap}tfoot .nut-dl-table__fill,tfoot .nut-dl-table__spacer{border-bottom:0;border-top:1px solid var(--nut-dl-line)}.nut-dl-spinner{animation:nut-dl-spin .8s linear infinite}@keyframes nut-dl-spin{to{transform:rotate(1turn)}}tbody .nut-dl-table__spacer{background:var(--nut-dl-surface);border-bottom:1px solid var(--nut-dl-line-soft)}tbody .nut-dl-table__fill{background:inherit;border-bottom:1px solid var(--nut-dl-line-soft)}.nut-dl-th__btn--open{background:color-mix(in srgb,var(--nut-dl-head-fg) 8%,transparent)}.nut-dl-rz:after{background:var(--ui-border-accented);bottom:10px;content:"";opacity:0;position:absolute;right:0;top:10px;transition:opacity .12s;width:1px}.nut-dl-rz:hover:after,.nut-dl-th:hover .nut-dl-rz:after{opacity:1}.nut-dl-rz--active:after,.nut-dl-rz:hover:after{background:var(--nut-dl-accent);bottom:6px;left:2.5px;opacity:1;top:6px;width:2px}.nut-dl-row{background:var(--nut-dl-surface);transition:background-color .1s}.nut-dl-row:hover{background:var(--nut-dl-row-hover)}.nut-dl-row--selected,.nut-dl-row--selected:hover{background:var(--nut-dl-row-selected)}.nut-dl-td,.nut-dl-tf[data-col],.nut-dl-th__btn,.nut-dl-th__static{padding-left:var(--nut-dl-cell-l,var(--nut-dl-cell-x));padding-right:var(--nut-dl-cell-r,var(--nut-dl-cell-x))}.nut-dl-row>.nut-dl-td:first-child,.nut-dl-table__foot-row>.nut-dl-tf:first-child,.nut-dl-table__head-row>.nut-dl-th:first-child{--nut-dl-cell-l:var(--nut-dl-gutter)}.nut-dl-row>.nut-dl-td:last-child,.nut-dl-table__foot-row>.nut-dl-tf:last-child,.nut-dl-table__head-row>.nut-dl-th:last-child{--nut-dl-cell-r:var(--nut-dl-gutter)}.nut-dl-row>.nut-dl-td--actions:last-child,.nut-dl-table__foot-row>.nut-dl-tf--actions:last-child,.nut-dl-table__head-row>.nut-dl-th--actions:last-child,.nut-dl-td--actions,.nut-dl-tf--actions{--nut-dl-cell-l:var(--nut-dl-cell-x);--nut-dl-cell-r:var(--nut-dl-cell-x)}.nut-dl-td--actions .nut-dl-td__inner{justify-content:flex-end}.nut-dl-td{background:inherit;border-bottom:1px solid var(--nut-dl-line-soft);box-sizing:border-box;color:var(--nut-dl-cell-fg);overflow:hidden;overflow-wrap:anywhere;padding-block:var(--nut-dl-cell-y,6px);white-space:normal}.nut-dl-table__table tbody:has(+tfoot)>.nut-dl-row:last-child>.nut-dl-td{border-bottom:0}.nut-dl-td{contain:paint}.nut-dl-td__inner{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--nut-dl-lines,3);line-clamp:var(--nut-dl-lines,3);max-height:calc(var(--nut-dl-lines, 3)*1.5em);overflow:hidden}.nut-dl-td--ellipsis{--nut-dl-lines:1;white-space:nowrap}.nut-dl-td--ellipsis .nut-dl-td__inner{display:block;text-overflow:ellipsis}.nut-dl-td--actions .nut-dl-td__inner,.nut-dl-td--selection .nut-dl-td__inner{align-items:center;display:flex}.nut-dl-td--actions,.nut-dl-td--selection{white-space:nowrap}.nut-dl-td--actions .nut-dl-td__inner>*{opacity:.55;transition:opacity .12s}.nut-dl-row:hover .nut-dl-td--actions .nut-dl-td__inner>*{opacity:1}.nut-dl-pin{position:sticky}.nut-dl-pin--first-end:before,.nut-dl-pin--last-start:after{background:var(--nut-dl-line);bottom:0;content:"";pointer-events:none;position:absolute;top:0;width:1px}.nut-dl-pin--last-start:after{right:0}.nut-dl-pin--first-end:before{left:0}.nut-dl-pin--first-end:before,.nut-dl-pin--last-start:after{background:var(--nut-dl-pin-line)}.nut-dl-td--actions.nut-dl-pin--first-end:before,.nut-dl-th--actions.nut-dl-pin--first-end:before{display:none}.nut-dl-skeleton{animation:nut-dl-shimmer 1.6s ease-in-out infinite;animation-delay:calc(var(--nut-dl-i, 0)*-90ms);background:linear-gradient(90deg,var(--ui-bg-accented) 0,var(--ui-bg-muted) 45%,var(--ui-bg-accented) 100%);background-size:200% 100%}.nut-dl-row--skeleton{animation:nut-dl-fade-in .18s ease .12s both}.nut-dl-row--appended{animation:nut-dl-fade-in .2s ease both}.nut-dl-table__body{transition:opacity .16s ease-out}.nut-dl-table__body[data-replacing=true]{opacity:.55;transition:opacity .2s ease-in .18s}@keyframes nut-dl-fade-in{0%{opacity:0}to{opacity:1}}@keyframes nut-dl-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}@media (prefers-reduced-motion:reduce){.nut-dl-row,.nut-dl-table__body{transition:none}.nut-dl-row--appended,.nut-dl-row--skeleton,.nut-dl-skeleton{animation:none}}
937
+ );--nut-dl-accent:var(--ui-primary);--nut-dl-cell-fg:var(--nut-dl-table-cell-fg,var(--ui-text-toned));--nut-dl-pin-line:var(--nut-dl-table-pin-line,var(--nut-dl-line));--nut-dl-rail:var(--nut-dl-table-rail,var(--ui-border-accented));--nut-dl-rail-lit:var(--nut-dl-table-rail-lit,var(--ui-primary));--nut-dl-rail-radius:var(--nut-dl-table-rail-radius,calc(var(--ui-radius)*1.5));--nut-dl-toggle-hover:var(--nut-dl-table-toggle-hover,var(--ui-bg-accented));--nut-dl-tree-shift:var(--nut-dl-table-tree-shift,6px)}.nut-dl-table__scroll{overflow-anchor:none;scrollbar-width:none}.nut-dl-table__scroll::-webkit-scrollbar{display:none}.nut-dl-th{color:var(--nut-dl-head-fg);font-size:var(--nut-dl-head-font);font-weight:var(--nut-dl-head-weight);letter-spacing:var(--nut-dl-head-tracking);text-transform:var(--nut-dl-head-transform);-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap}.nut-dl-table__fill,.nut-dl-table__spacer,.nut-dl-th{background:var(--nut-dl-head-bg);border-bottom:1px solid var(--nut-dl-line)}.nut-dl-tf{background:var(--nut-dl-head-bg);border-top:1px solid var(--nut-dl-line);color:var(--ui-text-highlighted);font-weight:var(--nut-dl-table-foot-weight,500);white-space:nowrap}tfoot .nut-dl-table__fill,tfoot .nut-dl-table__spacer{border-bottom:0;border-top:1px solid var(--nut-dl-line)}.nut-dl-spinner{animation:nut-dl-spin .8s linear infinite}@keyframes nut-dl-spin{to{transform:rotate(1turn)}}tbody .nut-dl-table__spacer{background:var(--nut-dl-surface);border-bottom:1px solid var(--nut-dl-line-soft)}tbody .nut-dl-table__fill{background:inherit;border-bottom:1px solid var(--nut-dl-line-soft)}.nut-dl-th__btn--open{background:color-mix(in srgb,var(--nut-dl-head-fg) 8%,transparent)}.nut-dl-rz:after{background:var(--ui-border-accented);bottom:10px;content:"";opacity:0;position:absolute;right:0;top:10px;transition:opacity .12s;width:1px}.nut-dl-rz:hover:after,.nut-dl-th:hover .nut-dl-rz:after{opacity:1}.nut-dl-rz--active:after,.nut-dl-rz:hover:after{background:var(--nut-dl-accent);bottom:6px;left:2.5px;opacity:1;top:6px;width:2px}.nut-dl-row{background:var(--nut-dl-surface);transition:background-color .1s}.nut-dl-row:hover{background:var(--nut-dl-row-hover)}.nut-dl-row--selected,.nut-dl-row--selected:hover{background:var(--nut-dl-row-selected)}.nut-dl-td,.nut-dl-tf[data-col],.nut-dl-th__btn,.nut-dl-th__static{padding-left:var(--nut-dl-cell-l,var(--nut-dl-cell-x));padding-right:var(--nut-dl-cell-r,var(--nut-dl-cell-x))}.nut-dl-row>.nut-dl-td:first-child,.nut-dl-table__foot-row>.nut-dl-tf:first-child,.nut-dl-table__head-row>.nut-dl-th:first-child{--nut-dl-cell-l:var(--nut-dl-gutter)}.nut-dl-row>.nut-dl-td:last-child,.nut-dl-table__foot-row>.nut-dl-tf:last-child,.nut-dl-table__head-row>.nut-dl-th:last-child{--nut-dl-cell-r:var(--nut-dl-gutter)}.nut-dl-row>.nut-dl-td--actions:last-child,.nut-dl-table__foot-row>.nut-dl-tf--actions:last-child,.nut-dl-table__head-row>.nut-dl-th--actions:last-child,.nut-dl-td--actions,.nut-dl-tf--actions{--nut-dl-cell-l:var(--nut-dl-cell-x);--nut-dl-cell-r:var(--nut-dl-cell-x)}.nut-dl-td--actions .nut-dl-td__inner{justify-content:flex-end}.nut-dl-td{background:inherit;border-bottom:1px solid var(--nut-dl-line-soft);box-sizing:border-box;color:var(--nut-dl-cell-fg);overflow:hidden;overflow-wrap:anywhere;padding-block:var(--nut-dl-cell-y,6px);white-space:normal}.nut-dl-table__table tbody:has(+tfoot)>.nut-dl-row:last-child>.nut-dl-td{border-bottom:0}.nut-dl-td{contain:paint}.nut-dl-td__inner{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--nut-dl-lines,3);line-clamp:var(--nut-dl-lines,3);max-height:calc(var(--nut-dl-lines, 3)*1.5em);overflow:hidden}.nut-dl-td--ellipsis{--nut-dl-lines:1;white-space:nowrap}.nut-dl-td--ellipsis .nut-dl-td__inner{display:block;text-overflow:ellipsis}.nut-dl-td--actions .nut-dl-td__inner,.nut-dl-td--selection .nut-dl-td__inner{align-items:center;display:flex}.nut-dl-td--actions,.nut-dl-td--selection{white-space:nowrap}.nut-dl-td--actions .nut-dl-td__inner>*{opacity:.55;transition:opacity .12s}.nut-dl-row:hover .nut-dl-td--actions .nut-dl-td__inner>*{opacity:1}.nut-dl-pin{position:sticky}.nut-dl-pin--first-end:before,.nut-dl-pin--last-start:after{background:var(--nut-dl-line);bottom:0;content:"";pointer-events:none;position:absolute;top:0;width:1px}.nut-dl-pin--last-start:after{right:0}.nut-dl-pin--first-end:before{left:0}.nut-dl-pin--first-end:before,.nut-dl-pin--last-start:after{background:var(--nut-dl-pin-line)}.nut-dl-td--actions.nut-dl-pin--first-end:before,.nut-dl-th--actions.nut-dl-pin--first-end:before{display:none}.nut-dl-skeleton{animation:nut-dl-shimmer 1.6s ease-in-out infinite;animation-delay:calc(var(--nut-dl-i, 0)*-90ms);background:linear-gradient(90deg,var(--ui-bg-accented) 0,var(--ui-bg-muted) 45%,var(--ui-bg-accented) 100%);background-size:200% 100%}.nut-dl-row--skeleton{animation:nut-dl-fade-in .18s ease .12s both}.nut-dl-row--appended{animation:nut-dl-fade-in .2s ease both}.nut-dl-table__body{transition:opacity .16s ease-out}.nut-dl-table__body[data-replacing=true]{opacity:.55;transition:opacity .2s ease-in .18s}@keyframes nut-dl-fade-in{0%{opacity:0}to{opacity:1}}@keyframes nut-dl-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}@media (prefers-reduced-motion:reduce){.nut-dl-row,.nut-dl-table__body{transition:none}.nut-dl-row--appended,.nut-dl-row--skeleton,.nut-dl-skeleton{animation:none}}
874
938
  </style>
@@ -8,7 +8,7 @@ type __VLS_Props = {
8
8
  ui?: DataListTableUi;
9
9
  };
10
10
  declare function refresh(): void;
11
- declare var __VLS_33: {
11
+ declare var __VLS_41: {
12
12
  columnSlots: TableColumnSlot[];
13
13
  leafColumns: import("@tanstack/table-core").Column<{
14
14
  columnPinningFeature: import("@tanstack/table-core").TableFeature;
@@ -18,16 +18,16 @@ declare var __VLS_33: {
18
18
  coreRowModel: (table: import("@tanstack/table-core").Table<any, any>) => () => import("@tanstack/table-core").RowModel<any, any>;
19
19
  columnMeta: import("../../utils/index.js").DataListColumnMeta;
20
20
  }, object, unknown>[];
21
- }, __VLS_35: {
21
+ }, __VLS_43: {
22
22
  error: {};
23
23
  retry: typeof refresh;
24
- }, __VLS_44: {};
24
+ }, __VLS_52: {};
25
25
  type __VLS_Slots = {} & {
26
- footer?: (props: typeof __VLS_33) => any;
26
+ footer?: (props: typeof __VLS_41) => any;
27
27
  } & {
28
- error?: (props: typeof __VLS_35) => any;
28
+ error?: (props: typeof __VLS_43) => any;
29
29
  } & {
30
- empty?: (props: typeof __VLS_44) => any;
30
+ empty?: (props: typeof __VLS_52) => any;
31
31
  };
32
32
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
33
33
  resetColumnSizing: () => void;
@@ -3,7 +3,7 @@
3
3
  * so rows that stay on screen while the virtual window slides keep their cells untouched.
4
4
  */
5
5
  import type { HTMLAttributes } from 'vue';
6
- import type { GenericObject } from '../../types/index.js';
6
+ import type { GenericObject, TableTreeMotion, TableTreeNode } from '../../types/index.js';
7
7
  import type { tableRowCells } from './table-layout.js';
8
8
  type __VLS_Props = {
9
9
  rowId: string;
@@ -13,7 +13,20 @@ type __VLS_Props = {
13
13
  selected: boolean;
14
14
  appended: boolean;
15
15
  rowClass?: HTMLAttributes['class'];
16
+ /** Where the row sits in the tree; absent unless the schema configures `table.tree`. */
17
+ node?: TableTreeNode;
18
+ expanded?: boolean;
19
+ /** Whether the tree cell carries a checkbox for this row. */
20
+ checkbox?: boolean;
21
+ /** The row is being revealed or concealed by a branch opening or closing. */
22
+ motion?: TableTreeMotion;
16
23
  };
17
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
25
+ select: (event: MouseEvent) => any;
26
+ toggle: () => any;
27
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
28
+ onSelect?: ((event: MouseEvent) => any) | undefined;
29
+ onToggle?: (() => any) | undefined;
30
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
31
  declare const _default: typeof __VLS_export;
19
32
  export default _default;
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import TableCell from "./table-cell";
3
+ import TableTreeControl from "./table-tree-control.vue";
3
4
  defineProps({
4
5
  rowId: { type: String, required: true },
5
6
  original: { type: Object, required: true },
@@ -7,8 +8,13 @@ defineProps({
7
8
  cells: { type: null, required: true },
8
9
  selected: { type: Boolean, required: true },
9
10
  appended: { type: Boolean, required: true },
10
- rowClass: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true }
11
+ rowClass: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
12
+ node: { type: Object, required: false },
13
+ expanded: { type: Boolean, required: false },
14
+ checkbox: { type: Boolean, required: false },
15
+ motion: { type: Object, required: false }
11
16
  });
17
+ const emit = defineEmits(["toggle", "select"]);
12
18
  </script>
13
19
 
14
20
  <template>
@@ -17,10 +23,13 @@ defineProps({
17
23
  :class="[
18
24
  selected ? 'nut-dl-row--selected' : '',
19
25
  appended ? 'nut-dl-row--appended' : '',
26
+ motion ? `nut-dl-row--${motion.kind === 'enter' ? 'reveal' : 'conceal'}` : '',
20
27
  rowClass
21
28
  ]"
29
+ :style="motion ? { '--nut-dl-tree-i': motion.order } : void 0"
22
30
  :data-index="index"
23
31
  :data-row-id="rowId"
32
+ :data-tree-depth="node?.depth"
24
33
  >
25
34
  <template v-for="slot in cells" :key="slot.key">
26
35
  <td v-if="slot.kind === 'fill'" class="nut-dl-table__fill p-0" aria-hidden="true" />
@@ -37,7 +46,19 @@ defineProps({
37
46
  :data-col="slot.columnId"
38
47
  :style="slot.layout.style"
39
48
  >
40
- <div class="nut-dl-td__inner min-w-0" :class="slot.layout.innerClass">
49
+ <template v-if="slot.layout.internal === 'tree'">
50
+ <TableTreeControl
51
+ v-if="node"
52
+ :node="node"
53
+ :expanded="expanded === true"
54
+ :index="index"
55
+ :selected="selected"
56
+ :checkbox="checkbox === true"
57
+ @toggle="emit('toggle')"
58
+ @select="emit('select', $event)"
59
+ />
60
+ </template>
61
+ <div v-else class="nut-dl-td__inner min-w-0" :class="slot.layout.innerClass">
41
62
  <TableCell
42
63
  v-if="slot.layout.render"
43
64
  :index="index"
@@ -3,7 +3,7 @@
3
3
  * so rows that stay on screen while the virtual window slides keep their cells untouched.
4
4
  */
5
5
  import type { HTMLAttributes } from 'vue';
6
- import type { GenericObject } from '../../types/index.js';
6
+ import type { GenericObject, TableTreeMotion, TableTreeNode } from '../../types/index.js';
7
7
  import type { tableRowCells } from './table-layout.js';
8
8
  type __VLS_Props = {
9
9
  rowId: string;
@@ -13,7 +13,20 @@ type __VLS_Props = {
13
13
  selected: boolean;
14
14
  appended: boolean;
15
15
  rowClass?: HTMLAttributes['class'];
16
+ /** Where the row sits in the tree; absent unless the schema configures `table.tree`. */
17
+ node?: TableTreeNode;
18
+ expanded?: boolean;
19
+ /** Whether the tree cell carries a checkbox for this row. */
20
+ checkbox?: boolean;
21
+ /** The row is being revealed or concealed by a branch opening or closing. */
22
+ motion?: TableTreeMotion;
16
23
  };
17
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
25
+ select: (event: MouseEvent) => any;
26
+ toggle: () => any;
27
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
28
+ onSelect?: ((event: MouseEvent) => any) | undefined;
29
+ onToggle?: (() => any) | undefined;
30
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
31
  declare const _default: typeof __VLS_export;
19
32
  export default _default;
@@ -0,0 +1,19 @@
1
+ import type { TableTreeNode } from '../../types/index.js';
2
+ type __VLS_Props = {
3
+ node: TableTreeNode;
4
+ expanded: boolean;
5
+ /** The row's position in the rendered list: a lit rail stops at the row under the pointer. */
6
+ index: number;
7
+ selected: boolean;
8
+ /** Whether the row carries a checkbox; its width is reserved either way. */
9
+ checkbox: boolean;
10
+ };
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ select: (event: MouseEvent) => any;
13
+ toggle: () => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onSelect?: ((event: MouseEvent) => any) | undefined;
16
+ onToggle?: (() => any) | undefined;
17
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ declare const _default: typeof __VLS_export;
19
+ export default _default;
@@ -0,0 +1,112 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { useUiToolsLocale } from "#ui-tools/i18n";
4
+ import { useTableInternals } from "../../composables/use-table-internals";
5
+ import { getTreeLineage, getTreeRails } from "../../utils/tree";
6
+ import TableSelectionControl from "./table-selection-control.vue";
7
+ const props = defineProps({
8
+ node: { type: Object, required: true },
9
+ expanded: { type: Boolean, required: true },
10
+ index: { type: Number, required: true },
11
+ selected: { type: Boolean, required: true },
12
+ checkbox: { type: Boolean, required: true }
13
+ });
14
+ const emit = defineEmits(["toggle", "select"]);
15
+ const { t } = useUiToolsLocale();
16
+ const { tree } = useTableInternals();
17
+ const lineage = computed(() => getTreeLineage(props.node));
18
+ const rails = computed(() => getTreeRails(props.node));
19
+ const lit = computed(() => {
20
+ let states = "";
21
+ for (let position = 0; position < props.node.depth; position += 1) {
22
+ const group = lineage.value[position];
23
+ const until = group === void 0 ? -1 : tree.litUntil(group.id);
24
+ states += props.index === until ? "t" : props.index < until ? "v" : "-";
25
+ }
26
+ return states;
27
+ });
28
+ const onPath = computed(() => tree.isOnPath(props.node.id));
29
+ const gutters = computed(
30
+ () => Array.from({ length: props.node.depth }, (_, position) => {
31
+ const own = position === props.node.depth - 1;
32
+ return {
33
+ /* This row's own level: down from the top, then a rounded turn toward the chevron. */
34
+ elbow: own,
35
+ lit: lit.value[position],
36
+ position,
37
+ /* An ancestor with a sibling still to come keeps its rail running through this row. */
38
+ rail: !own && rails.value[position] === true,
39
+ /* Siblings follow, so this row's own rail carries on below the turn. */
40
+ tail: own && !props.node.isLast
41
+ };
42
+ })
43
+ );
44
+ function onKeydown(event) {
45
+ const opens = event.key === "ArrowRight" && !props.expanded;
46
+ const closes = event.key === "ArrowLeft" && props.expanded;
47
+ if (!opens && !closes) return;
48
+ event.preventDefault();
49
+ emit("toggle");
50
+ }
51
+ </script>
52
+
53
+ <template>
54
+ <div class="nut-dl-tree" :class="{ 'nut-dl-tree--leaf': !node.hasChildren }">
55
+ <span class="nut-dl-tree__rule" aria-hidden="true" />
56
+ <span
57
+ v-for="gutter in gutters"
58
+ :key="gutter.position"
59
+ class="nut-dl-tree__gutter"
60
+ :class="{
61
+ 'nut-dl-tree__gutter--elbow': gutter.elbow,
62
+ 'nut-dl-tree__gutter--rail': gutter.rail,
63
+ 'nut-dl-tree__gutter--tail': gutter.tail
64
+ }"
65
+ :data-lit="gutter.lit === '-' ? void 0 : gutter.lit"
66
+ aria-hidden="true"
67
+ />
68
+ <span
69
+ class="nut-dl-tree__node"
70
+ :data-open="expanded || void 0"
71
+ :data-path="onPath || void 0"
72
+ >
73
+ <button
74
+ v-if="node.hasChildren"
75
+ type="button"
76
+ class="nut-dl-tree__toggle"
77
+ :aria-expanded="expanded"
78
+ :aria-label="expanded ? t('table.tree.collapse') : t('table.tree.expand')"
79
+ @click.stop="emit('toggle')"
80
+ @keydown="onKeydown"
81
+ >
82
+ <svg viewBox="0 0 24 24" width="12" height="12" fill="none" aria-hidden="true">
83
+ <path
84
+ d="m9 18 6-6-6-6"
85
+ stroke="currentColor"
86
+ stroke-width="2.5"
87
+ stroke-linecap="round"
88
+ stroke-linejoin="round"
89
+ />
90
+ </svg>
91
+ </button>
92
+ <!--
93
+ A childless row keeps the chevron's footprint empty, so every elbow and rail lines up with
94
+ its siblings that do have one. This branch and the shared width in `.nut-dl-tree__slot`
95
+ are the whole decision: drop both to let childless rows pull left instead.
96
+ -->
97
+ <span v-else class="nut-dl-tree__slot" aria-hidden="true" />
98
+ </span>
99
+ <span class="nut-dl-tree__check">
100
+ <TableSelectionControl
101
+ v-if="checkbox"
102
+ :model-value="selected"
103
+ :ariaLabel="t('table.tree.selectRow')"
104
+ @toggle="emit('select', $event)"
105
+ />
106
+ </span>
107
+ </div>
108
+ </template>
109
+
110
+ <style>
111
+ .nut-dl-tree{align-items:stretch;display:flex;inset:0;padding-left:var(--nut-dl-tree-lead);position:absolute;--nut-dl-tree-axis:calc(var(--nut-dl-tree-toggle)/2);--nut-dl-tree-arm:calc(var(--nut-dl-tree-gutter) - var(--nut-dl-tree-axis) + 1px)}.nut-dl-tree--leaf{--nut-dl-tree-arm:var(--nut-dl-tree-gutter)}.nut-dl-tree__gutter{--nut-dl-tree-vertical:var(--nut-dl-rail);--nut-dl-tree-turn:var(--nut-dl-rail);--nut-dl-tree-tail:var(--nut-dl-rail);align-self:stretch;flex:none;position:relative;width:var(--nut-dl-tree-gutter)}.nut-dl-tree__gutter[data-lit=v]{--nut-dl-tree-vertical:var(--nut-dl-rail-lit);--nut-dl-tree-tail:var(--nut-dl-rail-lit)}.nut-dl-tree__gutter[data-lit=t]{--nut-dl-tree-vertical:var(--nut-dl-rail-lit);--nut-dl-tree-turn:var(--nut-dl-rail-lit)}.nut-dl-tree__gutter--rail:before,.nut-dl-tree__gutter--tail:after{content:"";left:var(--nut-dl-tree-axis);position:absolute;transition:background-color .14s ease;width:1px}.nut-dl-tree__gutter--rail:before{background:var(--nut-dl-tree-vertical)}.nut-dl-tree__gutter--tail:after{background:var(--nut-dl-tree-tail)}.nut-dl-tree__gutter--rail:before{bottom:0;top:0}.nut-dl-tree__gutter--tail:after{bottom:0;top:50%}.nut-dl-tree__gutter--elbow:before{border-bottom:1px solid var(--nut-dl-tree-turn);border-bottom-left-radius:var(--nut-dl-rail-radius);border-left:1px solid var(--nut-dl-tree-vertical);box-sizing:border-box;content:"";height:50%;left:var(--nut-dl-tree-axis);position:absolute;top:0;transition:border-color .14s ease;width:var(--nut-dl-tree-arm)}.nut-dl-tree__node{align-items:center;align-self:stretch;display:flex;flex:none;position:relative}.nut-dl-tree__node:after{background:var(--nut-dl-rail);bottom:0;content:"";left:var(--nut-dl-tree-axis);opacity:0;position:absolute;top:calc(50% + var(--nut-dl-tree-axis) + 1px);transition:opacity .16s ease,background-color .14s ease;width:1px}.nut-dl-tree__node[data-open]:after{opacity:1}.nut-dl-tree__node[data-path]:after{background:var(--nut-dl-rail-lit)}.nut-dl-tree__slot,.nut-dl-tree__toggle{flex:none;height:var(--nut-dl-tree-toggle);width:var(--nut-dl-tree-toggle)}.nut-dl-tree__toggle{background:transparent;border:0;border-radius:var(--nut-dl-rail-radius);color:var(--ui-text-dimmed);cursor:pointer;display:grid;outline:none;padding:0;place-items:center;position:relative;transition:background-color .12s ease,color .12s ease,transform .12s ease}.nut-dl-tree__toggle:before{content:"";inset:-8px -5px;position:absolute}.nut-dl-tree__toggle:hover{background:var(--nut-dl-toggle-hover);color:var(--ui-text-highlighted)}.nut-dl-tree__toggle:active{background:color-mix(in srgb,var(--ui-text) 10%,var(--nut-dl-toggle-hover));transform:scale(.9)}.nut-dl-tree__toggle:focus-visible{outline:2px solid var(--nut-dl-accent);outline-offset:1px}.nut-dl-tree__toggle[aria-expanded=true]{color:var(--ui-text-toned)}.nut-dl-tree__toggle svg{transition:transform .18s cubic-bezier(.2,.8,.2,1)}.nut-dl-tree__toggle[aria-expanded=true] svg{transform:rotate(90deg)}.nut-dl-tree__check{align-items:center;align-self:stretch;display:flex;flex:none;margin-left:var(--nut-dl-tree-gap);width:var(--nut-dl-tree-check)}.nut-dl-tree__rule{background:var(--nut-dl-line-soft);height:1px;inset:auto 0 0;position:absolute}.nut-dl-table__table tbody:has(+tfoot)>.nut-dl-row:last-child .nut-dl-tree__rule{display:none}.nut-dl-row>.nut-dl-td.nut-dl-td--tree,.nut-dl-row>.nut-dl-td.nut-dl-td--tree:first-child{border-bottom:0;padding:0}.nut-dl-td--tree:not(.nut-dl-pin){position:relative}.nut-dl-th--tree .nut-dl-th__static{padding-left:var(--nut-dl-tree-lead);padding-right:0}.nut-dl-row--reveal{animation:nut-dl-tree-reveal .19s cubic-bezier(.2,.8,.2,1) both;animation-delay:calc(var(--nut-dl-tree-i, 0)*24ms)}.nut-dl-row--conceal{animation:nut-dl-tree-conceal .12s ease-in both;pointer-events:none}@keyframes nut-dl-tree-reveal{0%{opacity:0;transform:translateY(calc(var(--nut-dl-tree-shift)*-1))}to{opacity:1;transform:none}}@keyframes nut-dl-tree-conceal{0%{opacity:1;transform:none}to{opacity:0;transform:translateY(calc(var(--nut-dl-tree-shift)*-1))}}@media (prefers-reduced-motion:reduce){.nut-dl-row--conceal,.nut-dl-row--reveal{animation:none}.nut-dl-tree__gutter--elbow:before,.nut-dl-tree__gutter--rail:before,.nut-dl-tree__gutter--tail:after,.nut-dl-tree__node:after,.nut-dl-tree__toggle,.nut-dl-tree__toggle svg{transition:none}}
112
+ </style>
@@ -0,0 +1,19 @@
1
+ import type { TableTreeNode } from '../../types/index.js';
2
+ type __VLS_Props = {
3
+ node: TableTreeNode;
4
+ expanded: boolean;
5
+ /** The row's position in the rendered list: a lit rail stops at the row under the pointer. */
6
+ index: number;
7
+ selected: boolean;
8
+ /** Whether the row carries a checkbox; its width is reserved either way. */
9
+ checkbox: boolean;
10
+ };
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ select: (event: MouseEvent) => any;
13
+ toggle: () => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ onSelect?: ((event: MouseEvent) => any) | undefined;
16
+ onToggle?: (() => any) | undefined;
17
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ declare const _default: typeof __VLS_export;
19
+ export default _default;
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;