@stonecrop/atable 0.4.24 → 0.4.26

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.
@@ -11,10 +11,6 @@ export declare const createTableStore: (initData: {
11
11
  rows: TableRow[];
12
12
  id?: string;
13
13
  config?: TableConfig;
14
- table?: {
15
- [key: string]: any;
16
- };
17
- display?: TableDisplay[];
18
14
  modal?: TableModal;
19
15
  }) => import("pinia").Store<`table-${string}`, Pick<{
20
16
  columns: import("vue").Ref<{
@@ -117,25 +113,7 @@ export declare const createTableStore: (initData: {
117
113
  } | undefined;
118
114
  label?: string | undefined;
119
115
  }[]>;
120
- display: import("vue").Ref<{
121
- expanded?: boolean | undefined;
122
- childrenOpen?: boolean | undefined;
123
- isParent?: boolean | undefined;
124
- isRoot?: boolean | undefined;
125
- open?: boolean | undefined;
126
- indent?: number | undefined;
127
- parent?: number | undefined;
128
- rowModified?: boolean | undefined;
129
- }[], TableDisplay[] | {
130
- expanded?: boolean | undefined;
131
- childrenOpen?: boolean | undefined;
132
- isParent?: boolean | undefined;
133
- isRoot?: boolean | undefined;
134
- open?: boolean | undefined;
135
- indent?: number | undefined;
136
- parent?: number | undefined;
137
- rowModified?: boolean | undefined;
138
- }[]>;
116
+ display: import("vue").WritableComputedRef<TableDisplay[], TableDisplay[]>;
139
117
  ganttBars: import("vue").Ref<{
140
118
  id: string;
141
119
  rowIndex: number;
@@ -207,7 +185,7 @@ export declare const createTableStore: (initData: {
207
185
  colspan?: number | undefined;
208
186
  } | undefined;
209
187
  }[]>;
210
- table: import("vue").Ref<{}, {}>;
188
+ table: import("vue").ComputedRef<{}>;
211
189
  updates: import("vue").Ref<Record<string, string>, Record<string, string>>;
212
190
  hasPinnedColumns: import("vue").ComputedRef<boolean>;
213
191
  isGanttView: import("vue").ComputedRef<boolean>;
@@ -265,7 +243,8 @@ export declare const createTableStore: (initData: {
265
243
  unregisterConnectionHandle: (handleId: string) => void;
266
244
  unregisterGanttBar: (barId: string) => void;
267
245
  updateGanttBar: (event: GanttDragEvent) => void;
268
- }, "columns" | "config" | "connectionHandles" | "connectionPaths" | "display" | "ganttBars" | "modal" | "rows" | "table" | "updates">, Pick<{
246
+ updateRows: (newRows: TableRow[]) => void;
247
+ }, "columns" | "config" | "connectionHandles" | "connectionPaths" | "ganttBars" | "modal" | "rows" | "updates">, Pick<{
269
248
  columns: import("vue").Ref<{
270
249
  name: string;
271
250
  align?: CanvasTextAlign | undefined;
@@ -366,25 +345,7 @@ export declare const createTableStore: (initData: {
366
345
  } | undefined;
367
346
  label?: string | undefined;
368
347
  }[]>;
369
- display: import("vue").Ref<{
370
- expanded?: boolean | undefined;
371
- childrenOpen?: boolean | undefined;
372
- isParent?: boolean | undefined;
373
- isRoot?: boolean | undefined;
374
- open?: boolean | undefined;
375
- indent?: number | undefined;
376
- parent?: number | undefined;
377
- rowModified?: boolean | undefined;
378
- }[], TableDisplay[] | {
379
- expanded?: boolean | undefined;
380
- childrenOpen?: boolean | undefined;
381
- isParent?: boolean | undefined;
382
- isRoot?: boolean | undefined;
383
- open?: boolean | undefined;
384
- indent?: number | undefined;
385
- parent?: number | undefined;
386
- rowModified?: boolean | undefined;
387
- }[]>;
348
+ display: import("vue").WritableComputedRef<TableDisplay[], TableDisplay[]>;
388
349
  ganttBars: import("vue").Ref<{
389
350
  id: string;
390
351
  rowIndex: number;
@@ -456,7 +417,7 @@ export declare const createTableStore: (initData: {
456
417
  colspan?: number | undefined;
457
418
  } | undefined;
458
419
  }[]>;
459
- table: import("vue").Ref<{}, {}>;
420
+ table: import("vue").ComputedRef<{}>;
460
421
  updates: import("vue").Ref<Record<string, string>, Record<string, string>>;
461
422
  hasPinnedColumns: import("vue").ComputedRef<boolean>;
462
423
  isGanttView: import("vue").ComputedRef<boolean>;
@@ -514,7 +475,8 @@ export declare const createTableStore: (initData: {
514
475
  unregisterConnectionHandle: (handleId: string) => void;
515
476
  unregisterGanttBar: (barId: string) => void;
516
477
  updateGanttBar: (event: GanttDragEvent) => void;
517
- }, "hasPinnedColumns" | "isGanttView" | "isTreeView" | "numberedRowWidth" | "zeroColumn">, Pick<{
478
+ updateRows: (newRows: TableRow[]) => void;
479
+ }, "display" | "table" | "hasPinnedColumns" | "isGanttView" | "isTreeView" | "numberedRowWidth" | "zeroColumn">, Pick<{
518
480
  columns: import("vue").Ref<{
519
481
  name: string;
520
482
  align?: CanvasTextAlign | undefined;
@@ -615,25 +577,7 @@ export declare const createTableStore: (initData: {
615
577
  } | undefined;
616
578
  label?: string | undefined;
617
579
  }[]>;
618
- display: import("vue").Ref<{
619
- expanded?: boolean | undefined;
620
- childrenOpen?: boolean | undefined;
621
- isParent?: boolean | undefined;
622
- isRoot?: boolean | undefined;
623
- open?: boolean | undefined;
624
- indent?: number | undefined;
625
- parent?: number | undefined;
626
- rowModified?: boolean | undefined;
627
- }[], TableDisplay[] | {
628
- expanded?: boolean | undefined;
629
- childrenOpen?: boolean | undefined;
630
- isParent?: boolean | undefined;
631
- isRoot?: boolean | undefined;
632
- open?: boolean | undefined;
633
- indent?: number | undefined;
634
- parent?: number | undefined;
635
- rowModified?: boolean | undefined;
636
- }[]>;
580
+ display: import("vue").WritableComputedRef<TableDisplay[], TableDisplay[]>;
637
581
  ganttBars: import("vue").Ref<{
638
582
  id: string;
639
583
  rowIndex: number;
@@ -705,7 +649,7 @@ export declare const createTableStore: (initData: {
705
649
  colspan?: number | undefined;
706
650
  } | undefined;
707
651
  }[]>;
708
- table: import("vue").Ref<{}, {}>;
652
+ table: import("vue").ComputedRef<{}>;
709
653
  updates: import("vue").Ref<Record<string, string>, Record<string, string>>;
710
654
  hasPinnedColumns: import("vue").ComputedRef<boolean>;
711
655
  isGanttView: import("vue").ComputedRef<boolean>;
@@ -763,5 +707,6 @@ export declare const createTableStore: (initData: {
763
707
  unregisterConnectionHandle: (handleId: string) => void;
764
708
  unregisterGanttBar: (barId: string) => void;
765
709
  updateGanttBar: (event: GanttDragEvent) => void;
766
- }, "closeModal" | "createConnection" | "deleteConnection" | "getCellData" | "getCellDisplayValue" | "getConnectionsForBar" | "getFormattedValue" | "getHandlesForBar" | "getHeaderCellStyle" | "getIndent" | "getRowExpandSymbol" | "isRowGantt" | "isRowVisible" | "registerConnectionHandle" | "registerGanttBar" | "resizeColumn" | "setCellData" | "setCellText" | "toggleRowExpand" | "unregisterConnectionHandle" | "unregisterGanttBar" | "updateGanttBar">>;
710
+ updateRows: (newRows: TableRow[]) => void;
711
+ }, "closeModal" | "createConnection" | "deleteConnection" | "getCellData" | "getCellDisplayValue" | "getConnectionsForBar" | "getFormattedValue" | "getHandlesForBar" | "getHeaderCellStyle" | "getIndent" | "getRowExpandSymbol" | "isRowGantt" | "isRowVisible" | "registerConnectionHandle" | "registerGanttBar" | "resizeColumn" | "setCellData" | "setCellText" | "toggleRowExpand" | "unregisterConnectionHandle" | "unregisterGanttBar" | "updateGanttBar" | "updateRows">>;
767
712
  //# sourceMappingURL=table.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/stores/table.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/stores/table.ts"],"names":[],"mappings":"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"}
@@ -10,28 +10,8 @@ import { generateHash } from '../utils';
10
10
  export const createTableStore = (initData) => {
11
11
  const id = initData.id || generateHash();
12
12
  const createStore = defineStore(`table-${id}`, () => {
13
- // util functions
14
- const createTableObject = () => {
15
- const table = {};
16
- for (const [colIndex, column] of columns.value.entries()) {
17
- for (const [rowIndex, row] of rows.value.entries()) {
18
- table[`${colIndex}:${rowIndex}`] = row[column.name];
19
- }
20
- }
21
- return table;
22
- };
23
- const createDisplayObject = (display) => {
13
+ const createDisplayObject = () => {
24
14
  const defaultDisplay = [Object.assign({}, { rowModified: false })];
25
- // TODO: (typing) what is the type of `display` here?
26
- if (display) {
27
- if ('0:0' in display) {
28
- return display;
29
- }
30
- // else if ('default' in display) {
31
- // // TODO: (typing) what is the possible input here for 'default'?
32
- // defaultDisplay = display.default
33
- // }
34
- }
35
15
  // TODO: (typing) is this type correct for the parent set?
36
16
  const parents = new Set();
37
17
  for (let rowIndex = 0; rowIndex < rows.value.length; rowIndex++) {
@@ -59,8 +39,70 @@ export const createTableStore = (initData) => {
59
39
  const columns = ref(initData.columns);
60
40
  const rows = ref(initData.rows);
61
41
  const config = ref(initData.config || {});
62
- const table = ref(initData.table || createTableObject());
63
- const display = ref(createDisplayObject(initData.display));
42
+ // Track row modifications and expand states separately from the computed display
43
+ const rowModifications = ref({});
44
+ const rowExpandStates = ref({});
45
+ const table = computed(() => {
46
+ const table = {};
47
+ for (const [colIndex, column] of columns.value.entries()) {
48
+ for (const [rowIndex, row] of rows.value.entries()) {
49
+ table[`${colIndex}:${rowIndex}`] = row[column.name];
50
+ }
51
+ }
52
+ return table;
53
+ });
54
+ const display = computed({
55
+ get: () => {
56
+ const baseDisplay = createDisplayObject();
57
+ // Apply persistent modifications and expand states
58
+ for (let i = 0; i < baseDisplay.length; i++) {
59
+ if (rowModifications.value[i]) {
60
+ baseDisplay[i].rowModified = rowModifications.value[i];
61
+ }
62
+ if (rowExpandStates.value[i]) {
63
+ if (rowExpandStates.value[i].childrenOpen !== undefined) {
64
+ baseDisplay[i].childrenOpen = rowExpandStates.value[i].childrenOpen;
65
+ }
66
+ if (rowExpandStates.value[i].expanded !== undefined) {
67
+ baseDisplay[i].expanded = rowExpandStates.value[i].expanded;
68
+ }
69
+ }
70
+ }
71
+ // Calculate 'open' property for tree view based on parent's childrenOpen state
72
+ if (isTreeView.value) {
73
+ // Helper function to check if all ancestors are open
74
+ const isNodeOpen = (rowIndex, display) => {
75
+ const row = display[rowIndex];
76
+ if (row.isRoot) {
77
+ return true; // Root nodes are always open
78
+ }
79
+ if (row.parent === null || row.parent === undefined) {
80
+ return true;
81
+ }
82
+ const parentIndex = row.parent;
83
+ if (parentIndex < 0 || parentIndex >= display.length) {
84
+ return false;
85
+ }
86
+ const parent = display[parentIndex];
87
+ // Node is open if parent's children are open AND parent itself is open
88
+ return (parent.childrenOpen || false) && isNodeOpen(parentIndex, display);
89
+ };
90
+ for (let i = 0; i < baseDisplay.length; i++) {
91
+ const row = baseDisplay[i];
92
+ if (!row.isRoot) {
93
+ baseDisplay[i].open = isNodeOpen(i, baseDisplay);
94
+ }
95
+ }
96
+ }
97
+ return baseDisplay;
98
+ },
99
+ set: (newDisplay) => {
100
+ // Only update if the new display is different from the current one; also avoids recursive updates
101
+ if (JSON.stringify(newDisplay) !== JSON.stringify(display.value)) {
102
+ display.value = newDisplay;
103
+ }
104
+ },
105
+ });
64
106
  const modal = ref(initData.modal || { visible: false });
65
107
  const updates = ref({});
66
108
  const ganttBars = ref([]);
@@ -81,7 +123,7 @@ export const createTableStore = (initData) => {
81
123
  const index = `${colIndex}:${rowIndex}`;
82
124
  const col = columns.value[colIndex];
83
125
  if (table.value[index] !== value) {
84
- display.value[rowIndex].rowModified = true;
126
+ rowModifications.value[rowIndex] = true;
85
127
  }
86
128
  table.value[index] = value;
87
129
  // Create a new row object to ensure reactivity
@@ -90,10 +132,13 @@ export const createTableStore = (initData) => {
90
132
  [col.name]: value,
91
133
  };
92
134
  };
135
+ const updateRows = (newRows) => {
136
+ rows.value = newRows;
137
+ };
93
138
  const setCellText = (colIndex, rowIndex, value) => {
94
139
  const index = `${colIndex}:${rowIndex}`;
95
140
  if (table.value[index] !== value) {
96
- display.value[rowIndex].rowModified = true;
141
+ rowModifications.value[rowIndex] = true;
97
142
  updates.value[index] = value;
98
143
  }
99
144
  };
@@ -143,21 +188,38 @@ export const createTableStore = (initData) => {
143
188
  };
144
189
  const toggleRowExpand = (rowIndex) => {
145
190
  if (isTreeView.value) {
146
- display.value[rowIndex].childrenOpen = !display.value[rowIndex].childrenOpen;
147
- const isOpen = display.value[rowIndex].childrenOpen;
148
- for (let index = 0; index < rows.value.length; index++) {
149
- if (display.value[index].parent === rowIndex) {
150
- display.value[index].open = isOpen;
151
- if (!isOpen) {
152
- // If we're closing, also close any children recursively
153
- display.value[index].childrenOpen = false;
154
- toggleRowExpand(index);
155
- }
156
- }
191
+ const currentState = rowExpandStates.value[rowIndex] || {};
192
+ const currentChildrenOpen = currentState.childrenOpen ?? display.value[rowIndex].childrenOpen;
193
+ const newChildrenOpen = !currentChildrenOpen;
194
+ rowExpandStates.value[rowIndex] = {
195
+ ...currentState,
196
+ childrenOpen: newChildrenOpen,
197
+ };
198
+ // If we're closing, recursively close all descendant nodes
199
+ if (!newChildrenOpen) {
200
+ closeDescendants(rowIndex);
157
201
  }
158
202
  }
159
203
  else if (config.value.view === 'list-expansion') {
160
- display.value[rowIndex].expanded = !display.value[rowIndex].expanded;
204
+ const currentState = rowExpandStates.value[rowIndex] || {};
205
+ const currentExpanded = currentState.expanded ?? display.value[rowIndex].expanded;
206
+ rowExpandStates.value[rowIndex] = {
207
+ ...currentState,
208
+ expanded: !currentExpanded,
209
+ };
210
+ }
211
+ };
212
+ const closeDescendants = (parentRowIndex) => {
213
+ for (let index = 0; index < rows.value.length; index++) {
214
+ if (display.value[index].parent === parentRowIndex) {
215
+ const childState = rowExpandStates.value[index] || {};
216
+ rowExpandStates.value[index] = {
217
+ ...childState,
218
+ childrenOpen: false,
219
+ };
220
+ // Recursively close this child's descendants
221
+ closeDescendants(index);
222
+ }
161
223
  }
162
224
  };
163
225
  const getCellDisplayValue = (colIndex, rowIndex) => {
@@ -263,6 +325,7 @@ export const createTableStore = (initData) => {
263
325
  const fromHandle = connectionHandles.value.find(h => h.id === fromHandleId);
264
326
  const toHandle = connectionHandles.value.find(h => h.id === toHandleId);
265
327
  if (!fromHandle || !toHandle) {
328
+ // eslint-disable-next-line no-console
266
329
  console.warn('Cannot create connection: handle not found');
267
330
  return null;
268
331
  }
@@ -337,6 +400,7 @@ export const createTableStore = (initData) => {
337
400
  unregisterConnectionHandle,
338
401
  unregisterGanttBar,
339
402
  updateGanttBar,
403
+ updateRows,
340
404
  };
341
405
  });
342
406
  return createStore();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/atable",
3
- "version": "0.4.24",
3
+ "version": "0.4.26",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": {
@@ -38,8 +38,8 @@
38
38
  "@vueuse/core": "^13.4.0",
39
39
  "pinia": "^3.0.3",
40
40
  "vue": "^3.5.17",
41
- "@stonecrop/themes": "0.4.24",
42
- "@stonecrop/utilities": "0.4.24"
41
+ "@stonecrop/themes": "0.4.26",
42
+ "@stonecrop/utilities": "0.4.26"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@microsoft/api-documenter": "^7.26.29",
@@ -86,15 +86,11 @@ import ATableModal from './ATableModal.vue'
86
86
  import { createTableStore } from '../stores/table'
87
87
  import type { ConnectionEvent, ConnectionPath, GanttDragEvent, TableColumn, TableConfig, TableRow } from '../types'
88
88
 
89
- const modelValue = defineModel<TableRow[]>({ required: true })
89
+ const rows = defineModel<TableRow[]>('rows', { required: true })
90
+ const columns = defineModel<TableColumn[]>('columns', { required: true })
90
91
 
91
- const {
92
- id,
93
- columns,
94
- config = new Object(),
95
- } = defineProps<{
92
+ const { id, config = new Object() } = defineProps<{
96
93
  id?: string
97
- columns: TableColumn[]
98
94
  config?: TableConfig
99
95
  }>()
100
96
 
@@ -102,18 +98,19 @@ const emit = defineEmits<{
102
98
  cellUpdate: [{ colIndex: number; rowIndex: number; newValue: any; oldValue: any }]
103
99
  'gantt:drag': [event: GanttDragEvent]
104
100
  'connection:event': [event: ConnectionEvent]
101
+ 'columns:update': [columns: TableColumn[]]
105
102
  }>()
106
103
 
107
104
  const tableRef = useTemplateRef<HTMLTableElement>('table')
108
- const store = createTableStore({ columns, rows: modelValue.value, id, config })
105
+ const store = createTableStore({ columns: columns.value, rows: rows.value, id, config })
109
106
 
110
107
  store.$onAction(({ name, store, args, after }) => {
111
108
  if (name === 'setCellData' || name === 'setCellText') {
112
109
  const [colIndex, rowIndex, newValue] = args
113
110
  const oldValue = store.getCellData(colIndex, rowIndex)
114
111
  after(() => {
115
- // Update modelValue to trigger update:modelValue event
116
- modelValue.value = [...store.rows]
112
+ // Update rows model to trigger update:rows event
113
+ rows.value = [...store.rows]
117
114
  emit('cellUpdate', { colIndex, rowIndex, newValue, oldValue })
118
115
  })
119
116
  } else if (name === 'updateGanttBar') {
@@ -130,12 +127,18 @@ store.$onAction(({ name, store, args, after }) => {
130
127
  emit('gantt:drag', event)
131
128
  })
132
129
  }
130
+ } else if (name === 'resizeColumn') {
131
+ after(() => {
132
+ // Update columns model
133
+ columns.value = [...store.columns]
134
+ emit('columns:update', [...store.columns])
135
+ })
133
136
  }
134
137
  })
135
138
 
136
- // Watch for external changes to modelValue and sync to store
139
+ // Watch for external changes to rows and sync to store
137
140
  watch(
138
- () => modelValue.value,
141
+ () => rows.value,
139
142
  newRows => {
140
143
  // Only update if the rows have actually changed (avoid infinite loops)
141
144
  if (JSON.stringify(newRows) !== JSON.stringify(store.rows)) {
@@ -145,8 +148,21 @@ watch(
145
148
  { deep: true }
146
149
  )
147
150
 
151
+ // Watch for changes to columns and sync to store
152
+ watch(
153
+ columns,
154
+ newColumns => {
155
+ // Only update if the columns have actually changed (avoid infinite loops)
156
+ if (JSON.stringify(newColumns) !== JSON.stringify(store.columns)) {
157
+ store.columns = [...newColumns]
158
+ emit('columns:update', [...newColumns] as TableColumn[])
159
+ }
160
+ },
161
+ { deep: true }
162
+ )
163
+
148
164
  onMounted(() => {
149
- if (columns.some(column => column.pinned)) {
165
+ if (columns.value.some(column => column.pinned)) {
150
166
  assignStickyCellWidths()
151
167
 
152
168
  // in tree views, also add a mutation observer to capture and adjust expanded rows
@@ -26,37 +26,13 @@ export const createTableStore = (initData: {
26
26
  rows: TableRow[]
27
27
  id?: string
28
28
  config?: TableConfig
29
- table?: { [key: string]: any }
30
- display?: TableDisplay[]
31
29
  modal?: TableModal
32
30
  }) => {
33
31
  const id = initData.id || generateHash()
34
32
  const createStore = defineStore(`table-${id}`, () => {
35
- // util functions
36
- const createTableObject = () => {
37
- const table = {}
38
- for (const [colIndex, column] of columns.value.entries()) {
39
- for (const [rowIndex, row] of rows.value.entries()) {
40
- table[`${colIndex}:${rowIndex}`] = row[column.name]
41
- }
42
- }
43
- return table
44
- }
45
-
46
- const createDisplayObject = (display?: TableDisplay[]) => {
33
+ const createDisplayObject = () => {
47
34
  const defaultDisplay: TableDisplay[] = [Object.assign({}, { rowModified: false })]
48
35
 
49
- // TODO: (typing) what is the type of `display` here?
50
- if (display) {
51
- if ('0:0' in display) {
52
- return display
53
- }
54
- // else if ('default' in display) {
55
- // // TODO: (typing) what is the possible input here for 'default'?
56
- // defaultDisplay = display.default
57
- // }
58
- }
59
-
60
36
  // TODO: (typing) is this type correct for the parent set?
61
37
  const parents = new Set<string | number>()
62
38
  for (let rowIndex = 0; rowIndex < rows.value.length; rowIndex++) {
@@ -87,8 +63,81 @@ export const createTableStore = (initData: {
87
63
  const columns = ref(initData.columns)
88
64
  const rows = ref(initData.rows)
89
65
  const config = ref(initData.config || {})
90
- const table = ref(initData.table || createTableObject())
91
- const display = ref(createDisplayObject(initData.display))
66
+
67
+ // Track row modifications and expand states separately from the computed display
68
+ const rowModifications = ref<Record<number, boolean>>({})
69
+ const rowExpandStates = ref<Record<number, { childrenOpen?: boolean; expanded?: boolean }>>({})
70
+
71
+ const table = computed(() => {
72
+ const table = {}
73
+ for (const [colIndex, column] of columns.value.entries()) {
74
+ for (const [rowIndex, row] of rows.value.entries()) {
75
+ table[`${colIndex}:${rowIndex}`] = row[column.name]
76
+ }
77
+ }
78
+ return table
79
+ })
80
+
81
+ const display = computed({
82
+ get: () => {
83
+ const baseDisplay = createDisplayObject()
84
+
85
+ // Apply persistent modifications and expand states
86
+ for (let i = 0; i < baseDisplay.length; i++) {
87
+ if (rowModifications.value[i]) {
88
+ baseDisplay[i].rowModified = rowModifications.value[i]
89
+ }
90
+ if (rowExpandStates.value[i]) {
91
+ if (rowExpandStates.value[i].childrenOpen !== undefined) {
92
+ baseDisplay[i].childrenOpen = rowExpandStates.value[i].childrenOpen!
93
+ }
94
+ if (rowExpandStates.value[i].expanded !== undefined) {
95
+ baseDisplay[i].expanded = rowExpandStates.value[i].expanded!
96
+ }
97
+ }
98
+ }
99
+
100
+ // Calculate 'open' property for tree view based on parent's childrenOpen state
101
+ if (isTreeView.value) {
102
+ // Helper function to check if all ancestors are open
103
+ const isNodeOpen = (rowIndex: number, display: TableDisplay[]): boolean => {
104
+ const row = display[rowIndex]
105
+ if (row.isRoot) {
106
+ return true // Root nodes are always open
107
+ }
108
+
109
+ if (row.parent === null || row.parent === undefined) {
110
+ return true
111
+ }
112
+
113
+ const parentIndex = row.parent
114
+ if (parentIndex < 0 || parentIndex >= display.length) {
115
+ return false
116
+ }
117
+
118
+ const parent = display[parentIndex]
119
+ // Node is open if parent's children are open AND parent itself is open
120
+ return (parent.childrenOpen || false) && isNodeOpen(parentIndex, display)
121
+ }
122
+
123
+ for (let i = 0; i < baseDisplay.length; i++) {
124
+ const row = baseDisplay[i]
125
+ if (!row.isRoot) {
126
+ baseDisplay[i].open = isNodeOpen(i, baseDisplay)
127
+ }
128
+ }
129
+ }
130
+
131
+ return baseDisplay
132
+ },
133
+ set: (newDisplay: TableDisplay[]) => {
134
+ // Only update if the new display is different from the current one; also avoids recursive updates
135
+ if (JSON.stringify(newDisplay) !== JSON.stringify(display.value)) {
136
+ display.value = newDisplay
137
+ }
138
+ },
139
+ })
140
+
92
141
  const modal = ref<TableModal>(initData.modal || { visible: false })
93
142
  const updates = ref<Record<string, string>>({})
94
143
  const ganttBars = ref<GanttBarInfo[]>([])
@@ -116,7 +165,7 @@ export const createTableStore = (initData: {
116
165
  const col = columns.value[colIndex]
117
166
 
118
167
  if (table.value[index] !== value) {
119
- display.value[rowIndex].rowModified = true
168
+ rowModifications.value[rowIndex] = true
120
169
  }
121
170
 
122
171
  table.value[index] = value
@@ -127,11 +176,15 @@ export const createTableStore = (initData: {
127
176
  }
128
177
  }
129
178
 
179
+ const updateRows = (newRows: TableRow[]) => {
180
+ rows.value = newRows
181
+ }
182
+
130
183
  const setCellText = (colIndex: number, rowIndex: number, value: string) => {
131
184
  const index = `${colIndex}:${rowIndex}`
132
185
 
133
186
  if (table.value[index] !== value) {
134
- display.value[rowIndex].rowModified = true
187
+ rowModifications.value[rowIndex] = true
135
188
  updates.value[index] = value
136
189
  }
137
190
  }
@@ -194,21 +247,40 @@ export const createTableStore = (initData: {
194
247
 
195
248
  const toggleRowExpand = (rowIndex: number) => {
196
249
  if (isTreeView.value) {
197
- display.value[rowIndex].childrenOpen = !display.value[rowIndex].childrenOpen
198
- const isOpen = display.value[rowIndex].childrenOpen
199
-
200
- for (let index = 0; index < rows.value.length; index++) {
201
- if (display.value[index].parent === rowIndex) {
202
- display.value[index].open = isOpen
203
- if (!isOpen) {
204
- // If we're closing, also close any children recursively
205
- display.value[index].childrenOpen = false
206
- toggleRowExpand(index)
207
- }
208
- }
250
+ const currentState = rowExpandStates.value[rowIndex] || {}
251
+ const currentChildrenOpen = currentState.childrenOpen ?? display.value[rowIndex].childrenOpen
252
+ const newChildrenOpen = !currentChildrenOpen
253
+
254
+ rowExpandStates.value[rowIndex] = {
255
+ ...currentState,
256
+ childrenOpen: newChildrenOpen,
257
+ }
258
+
259
+ // If we're closing, recursively close all descendant nodes
260
+ if (!newChildrenOpen) {
261
+ closeDescendants(rowIndex)
209
262
  }
210
263
  } else if (config.value.view === 'list-expansion') {
211
- display.value[rowIndex].expanded = !display.value[rowIndex].expanded
264
+ const currentState = rowExpandStates.value[rowIndex] || {}
265
+ const currentExpanded = currentState.expanded ?? display.value[rowIndex].expanded
266
+ rowExpandStates.value[rowIndex] = {
267
+ ...currentState,
268
+ expanded: !currentExpanded,
269
+ }
270
+ }
271
+ }
272
+
273
+ const closeDescendants = (parentRowIndex: number) => {
274
+ for (let index = 0; index < rows.value.length; index++) {
275
+ if (display.value[index].parent === parentRowIndex) {
276
+ const childState = rowExpandStates.value[index] || {}
277
+ rowExpandStates.value[index] = {
278
+ ...childState,
279
+ childrenOpen: false,
280
+ }
281
+ // Recursively close this child's descendants
282
+ closeDescendants(index)
283
+ }
212
284
  }
213
285
  }
214
286
 
@@ -323,6 +395,7 @@ export const createTableStore = (initData: {
323
395
  const toHandle = connectionHandles.value.find(h => h.id === toHandleId)
324
396
 
325
397
  if (!fromHandle || !toHandle) {
398
+ // eslint-disable-next-line no-console
326
399
  console.warn('Cannot create connection: handle not found')
327
400
  return null
328
401
  }
@@ -405,6 +478,7 @@ export const createTableStore = (initData: {
405
478
  unregisterConnectionHandle,
406
479
  unregisterGanttBar,
407
480
  updateGanttBar,
481
+ updateRows,
408
482
  }
409
483
  })
410
484