virtual-tree-canvas 0.7.0 → 0.7.2
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/CHANGELOG.md +15 -0
- package/README.md +12 -1
- package/docs/icon-catalog.html +68 -66
- package/docs/icon-catalog.md +111 -111
- package/docs/performance/dynamic-updates-0.7.1.md +38 -0
- package/package.json +3 -2
- package/src/assets/icons.js +10 -4
- package/src/core/dynamic-state.js +19 -29
- package/src/core/patch-batcher.js +4 -0
- package/src/core/theme-manager.js +238 -64
- package/src/core/tree-cell-layout.js +4 -2
- package/src/core/tree-column-model.js +72 -24
- package/src/core/tree-model.js +4 -2
- package/src/core/view-options.js +98 -25
- package/src/core/visible-row-model.js +50 -20
- package/src/index.d.ts +22 -0
- package/src/input/row-actions.js +224 -83
- package/src/input/row-reorder-input.js +112 -39
- package/src/input/tree-tooltip.js +39 -5
- package/src/input/tree-view-input-controller.js +33 -10
- package/src/inspector/cell-editor-manager.js +110 -31
- package/src/inspector/pane-layout.js +11 -3
- package/src/renderers/checkbox.js +12 -13
- package/src/renderers/tree-row-renderer.js +325 -68
- package/src/tree-view-controller.js +919 -213
- package/src/tree-view.js +215 -53
- package/src/view/styles.js +83 -12
|
@@ -3,7 +3,8 @@ export const darkTheme = {
|
|
|
3
3
|
indentWidth: 18,
|
|
4
4
|
font: '12px Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif',
|
|
5
5
|
unitFont: '11px ui-monospace, SFMono-Regular, Consolas, monospace',
|
|
6
|
-
monoFont:
|
|
6
|
+
monoFont:
|
|
7
|
+
'12px "JetBrains Mono", "Cascadia Mono", "Fira Code", ui-monospace, SFMono-Regular, Consolas, monospace',
|
|
7
8
|
colors: {
|
|
8
9
|
background: '#0a0f1c',
|
|
9
10
|
row: '#0a0f1c',
|
|
@@ -30,46 +31,146 @@ export const darkTheme = {
|
|
|
30
31
|
badgeText: '#ffffff',
|
|
31
32
|
border: '#1b2637',
|
|
32
33
|
borderStrong: '#2b3b52',
|
|
33
|
-
shadow: 'rgba(0,0,0,.24)'
|
|
34
|
+
shadow: 'rgba(0,0,0,.24)'
|
|
35
|
+
},
|
|
36
|
+
valueColors: {
|
|
37
|
+
number: '#8bd5ee',
|
|
38
|
+
bigint: '#8bd5ee',
|
|
39
|
+
string: '#dde5ef',
|
|
40
|
+
boolean: '#86d6b5',
|
|
41
|
+
enum: '#c4b5fd',
|
|
42
|
+
null: '#9aa9bc',
|
|
43
|
+
undefined: '#9aa9bc'
|
|
34
44
|
},
|
|
35
|
-
valueColors: { number: '#8bd5ee', bigint: '#8bd5ee', string: '#dde5ef', boolean: '#86d6b5', enum: '#c4b5fd', null: '#9aa9bc', undefined: '#9aa9bc' },
|
|
36
45
|
types: {
|
|
37
|
-
root: {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
46
|
+
root: {
|
|
47
|
+
icon: 'folder',
|
|
48
|
+
color: '#38bdf8'
|
|
49
|
+
},
|
|
50
|
+
system: {
|
|
51
|
+
icon: 'folder',
|
|
52
|
+
color: '#818cf8'
|
|
53
|
+
},
|
|
54
|
+
platform: {
|
|
55
|
+
icon: 'aircraft',
|
|
56
|
+
color: '#60a5fa'
|
|
57
|
+
},
|
|
58
|
+
air: {
|
|
59
|
+
icon: 'aircraft',
|
|
60
|
+
color: '#60a5fa'
|
|
61
|
+
},
|
|
62
|
+
ground: {
|
|
63
|
+
icon: 'ground',
|
|
64
|
+
color: '#a3e635'
|
|
65
|
+
},
|
|
66
|
+
surface: {
|
|
67
|
+
icon: 'surface',
|
|
68
|
+
color: '#22d3ee'
|
|
69
|
+
},
|
|
70
|
+
subsurface: {
|
|
71
|
+
icon: 'subsurface',
|
|
72
|
+
color: '#38bdf8'
|
|
73
|
+
},
|
|
74
|
+
space: {
|
|
75
|
+
icon: 'space',
|
|
76
|
+
color: '#c084fc'
|
|
77
|
+
},
|
|
78
|
+
munition: {
|
|
79
|
+
icon: 'munition',
|
|
80
|
+
color: '#fb7185'
|
|
81
|
+
},
|
|
82
|
+
sensor: {
|
|
83
|
+
icon: 'radar',
|
|
84
|
+
color: '#34d399'
|
|
85
|
+
},
|
|
86
|
+
track: {
|
|
87
|
+
icon: 'track',
|
|
88
|
+
color: '#a78bfa'
|
|
89
|
+
},
|
|
90
|
+
geometry: {
|
|
91
|
+
icon: 'point',
|
|
92
|
+
color: '#38bdf8'
|
|
93
|
+
},
|
|
94
|
+
control: {
|
|
95
|
+
icon: 'control',
|
|
96
|
+
color: '#f59e0b'
|
|
97
|
+
},
|
|
98
|
+
situation: {
|
|
99
|
+
icon: 'situation',
|
|
100
|
+
color: '#2dd4bf'
|
|
101
|
+
},
|
|
102
|
+
damage: {
|
|
103
|
+
icon: 'damage',
|
|
104
|
+
color: '#fb7185'
|
|
105
|
+
},
|
|
106
|
+
warning: {
|
|
107
|
+
icon: 'warning',
|
|
108
|
+
color: '#facc15'
|
|
109
|
+
},
|
|
110
|
+
error: {
|
|
111
|
+
icon: 'error',
|
|
112
|
+
color: '#ef4444'
|
|
113
|
+
},
|
|
114
|
+
task: {
|
|
115
|
+
icon: 'task',
|
|
116
|
+
color: '#f97316'
|
|
117
|
+
},
|
|
118
|
+
bus: {
|
|
119
|
+
icon: 'data-bus',
|
|
120
|
+
color: '#22d3ee'
|
|
121
|
+
},
|
|
122
|
+
object: {
|
|
123
|
+
icon: 'inspector-object',
|
|
124
|
+
color: '#7dd3fc'
|
|
125
|
+
},
|
|
126
|
+
array: {
|
|
127
|
+
icon: 'inspector-array',
|
|
128
|
+
color: '#a78bfa'
|
|
129
|
+
},
|
|
130
|
+
string: {
|
|
131
|
+
icon: 'inspector-value',
|
|
132
|
+
color: '#94a3b8'
|
|
133
|
+
},
|
|
134
|
+
number: {
|
|
135
|
+
icon: 'inspector-value',
|
|
136
|
+
color: '#34d399'
|
|
137
|
+
},
|
|
138
|
+
boolean: {
|
|
139
|
+
icon: 'inspector-value',
|
|
140
|
+
color: '#22c55e'
|
|
141
|
+
},
|
|
142
|
+
null: {
|
|
143
|
+
icon: 'inspector-value',
|
|
144
|
+
color: '#64748b'
|
|
145
|
+
}
|
|
62
146
|
},
|
|
63
147
|
statuses: {
|
|
64
|
-
0: {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
148
|
+
0: {
|
|
149
|
+
label: 'OK',
|
|
150
|
+
color: '#22c55e'
|
|
151
|
+
},
|
|
152
|
+
1: {
|
|
153
|
+
label: 'WARN',
|
|
154
|
+
color: '#facc15'
|
|
155
|
+
},
|
|
156
|
+
2: {
|
|
157
|
+
label: 'ERR',
|
|
158
|
+
color: '#ef4444'
|
|
159
|
+
}
|
|
160
|
+
}
|
|
68
161
|
};
|
|
69
162
|
|
|
70
163
|
export const lightTheme = {
|
|
71
164
|
...darkTheme,
|
|
72
|
-
valueColors: {
|
|
165
|
+
valueColors: {
|
|
166
|
+
number: '#075985',
|
|
167
|
+
bigint: '#075985',
|
|
168
|
+
string: '#182438',
|
|
169
|
+
boolean: '#176249',
|
|
170
|
+
enum: '#6b3fa0',
|
|
171
|
+
null: '#576579',
|
|
172
|
+
undefined: '#576579'
|
|
173
|
+
},
|
|
73
174
|
colors: {
|
|
74
175
|
background: '#f8fafc',
|
|
75
176
|
row: '#ffffff',
|
|
@@ -96,8 +197,8 @@ export const lightTheme = {
|
|
|
96
197
|
badgeFill: '#e2e8f0',
|
|
97
198
|
border: '#e2e8f0',
|
|
98
199
|
borderStrong: '#cbd5e1',
|
|
99
|
-
shadow: 'rgba(15,23,42,.1)'
|
|
100
|
-
}
|
|
200
|
+
shadow: 'rgba(15,23,42,.1)'
|
|
201
|
+
}
|
|
101
202
|
};
|
|
102
203
|
|
|
103
204
|
export const tacticalTheme = {
|
|
@@ -125,34 +226,85 @@ export const tacticalTheme = {
|
|
|
125
226
|
badgeFill: '#102217',
|
|
126
227
|
border: '#183321',
|
|
127
228
|
borderStrong: '#295337',
|
|
128
|
-
shadow: 'rgba(0,0,0,.3)'
|
|
229
|
+
shadow: 'rgba(0,0,0,.3)'
|
|
129
230
|
},
|
|
130
231
|
types: {
|
|
131
232
|
...darkTheme.types,
|
|
132
|
-
root: {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
233
|
+
root: {
|
|
234
|
+
icon: 'folder',
|
|
235
|
+
color: '#7ddc92'
|
|
236
|
+
},
|
|
237
|
+
platform: {
|
|
238
|
+
icon: 'aircraft',
|
|
239
|
+
color: '#93c572'
|
|
240
|
+
},
|
|
241
|
+
air: {
|
|
242
|
+
icon: 'aircraft',
|
|
243
|
+
color: '#93c572'
|
|
244
|
+
},
|
|
245
|
+
ground: {
|
|
246
|
+
icon: 'ground',
|
|
247
|
+
color: '#c7f36f'
|
|
248
|
+
},
|
|
249
|
+
surface: {
|
|
250
|
+
icon: 'surface',
|
|
251
|
+
color: '#67e8f9'
|
|
252
|
+
},
|
|
253
|
+
subsurface: {
|
|
254
|
+
icon: 'subsurface',
|
|
255
|
+
color: '#7dd3fc'
|
|
256
|
+
},
|
|
257
|
+
space: {
|
|
258
|
+
icon: 'space',
|
|
259
|
+
color: '#d8b4fe'
|
|
260
|
+
},
|
|
261
|
+
munition: {
|
|
262
|
+
icon: 'munition',
|
|
263
|
+
color: '#ff8fab'
|
|
264
|
+
},
|
|
265
|
+
sensor: {
|
|
266
|
+
icon: 'radar',
|
|
267
|
+
color: '#45d483'
|
|
268
|
+
},
|
|
269
|
+
track: {
|
|
270
|
+
icon: 'track',
|
|
271
|
+
color: '#d6f264'
|
|
272
|
+
},
|
|
273
|
+
geometry: {
|
|
274
|
+
icon: 'point',
|
|
275
|
+
color: '#7ddc92'
|
|
276
|
+
},
|
|
277
|
+
control: {
|
|
278
|
+
icon: 'control',
|
|
279
|
+
color: '#ffd166'
|
|
280
|
+
},
|
|
281
|
+
situation: {
|
|
282
|
+
icon: 'situation',
|
|
283
|
+
color: '#8be9d9'
|
|
284
|
+
},
|
|
285
|
+
damage: {
|
|
286
|
+
icon: 'damage',
|
|
287
|
+
color: '#ff8fab'
|
|
288
|
+
},
|
|
289
|
+
warning: {
|
|
290
|
+
icon: 'warning',
|
|
291
|
+
color: '#ffd166'
|
|
292
|
+
},
|
|
293
|
+
error: {
|
|
294
|
+
icon: 'error',
|
|
295
|
+
color: '#ff5c5c'
|
|
296
|
+
},
|
|
297
|
+
bus: {
|
|
298
|
+
icon: 'data-bus',
|
|
299
|
+
color: '#67e8f9'
|
|
300
|
+
}
|
|
301
|
+
}
|
|
150
302
|
};
|
|
151
303
|
|
|
152
304
|
export const themes = {
|
|
153
305
|
dark: darkTheme,
|
|
154
306
|
light: lightTheme,
|
|
155
|
-
tactical: tacticalTheme
|
|
307
|
+
tactical: tacticalTheme
|
|
156
308
|
};
|
|
157
309
|
|
|
158
310
|
export class ThemeManager extends EventTarget {
|
|
@@ -170,7 +322,10 @@ export class ThemeManager extends EventTarget {
|
|
|
170
322
|
return this.theme;
|
|
171
323
|
}
|
|
172
324
|
|
|
173
|
-
/**
|
|
325
|
+
/**
|
|
326
|
+
* @param {import('./types.js').TreeNode} node
|
|
327
|
+
* @param {import('./types.js').NodeDynamicState} state
|
|
328
|
+
*/
|
|
174
329
|
resolveNodeStyle(node, state = {}) {
|
|
175
330
|
const typeRule = this.theme.types[node?.type ?? ''] ?? {};
|
|
176
331
|
const statusRule = this.resolveStatus(state.status);
|
|
@@ -180,14 +335,20 @@ export class ThemeManager extends EventTarget {
|
|
|
180
335
|
typeColor: typeRule.color ?? this.theme.colors.progressFill,
|
|
181
336
|
status: statusRule,
|
|
182
337
|
font: this.theme.font,
|
|
183
|
-
colors: this.theme.colors
|
|
338
|
+
colors: this.theme.colors
|
|
184
339
|
};
|
|
185
340
|
}
|
|
186
341
|
|
|
187
342
|
resolveStatus(status) {
|
|
188
343
|
const key = status ?? 0;
|
|
189
|
-
return
|
|
344
|
+
return (
|
|
345
|
+
this.theme.statuses[key] ?? {
|
|
346
|
+
label: String(key),
|
|
347
|
+
color: this.theme.colors.textMuted
|
|
348
|
+
}
|
|
349
|
+
);
|
|
190
350
|
}
|
|
351
|
+
|
|
191
352
|
}
|
|
192
353
|
|
|
193
354
|
export function resolveTheme(theme = {}) {
|
|
@@ -195,7 +356,8 @@ export function resolveTheme(theme = {}) {
|
|
|
195
356
|
if (!Object.hasOwn(themes, theme)) throw new TypeError(`Unknown virtual tree theme: ${theme}`);
|
|
196
357
|
return themes[theme];
|
|
197
358
|
}
|
|
198
|
-
if (!theme || typeof theme !== 'object' || Array.isArray(theme))
|
|
359
|
+
if (!theme || typeof theme !== 'object' || Array.isArray(theme))
|
|
360
|
+
throw new TypeError('theme must be a theme name or object');
|
|
199
361
|
return theme;
|
|
200
362
|
}
|
|
201
363
|
|
|
@@ -221,7 +383,7 @@ function normalizeTheme(theme = {}) {
|
|
|
221
383
|
indentGuide: base.colors.guide,
|
|
222
384
|
chevron: base.colors.chevron,
|
|
223
385
|
chevronMuted: base.colors.textMuted,
|
|
224
|
-
progress: base.colors.progressFill
|
|
386
|
+
progress: base.colors.progressFill
|
|
225
387
|
};
|
|
226
388
|
}
|
|
227
389
|
|
|
@@ -229,9 +391,21 @@ function mergeTheme(base, override) {
|
|
|
229
391
|
return {
|
|
230
392
|
...base,
|
|
231
393
|
...override,
|
|
232
|
-
colors: {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
394
|
+
colors: {
|
|
395
|
+
...base.colors,
|
|
396
|
+
...(override.colors ?? {})
|
|
397
|
+
},
|
|
398
|
+
valueColors: {
|
|
399
|
+
...base.valueColors,
|
|
400
|
+
...(override.valueColors ?? {})
|
|
401
|
+
},
|
|
402
|
+
types: {
|
|
403
|
+
...base.types,
|
|
404
|
+
...(override.types ?? {})
|
|
405
|
+
},
|
|
406
|
+
statuses: {
|
|
407
|
+
...base.statuses,
|
|
408
|
+
...(override.statuses ?? {})
|
|
409
|
+
}
|
|
236
410
|
};
|
|
237
411
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Share tree-cell positions between painting, hit testing and tooltips.
|
|
3
|
+
*/
|
|
2
4
|
export function treeCellLayout(depth, indentWidth, hasHierarchy) {
|
|
3
5
|
const indent = depth * indentWidth;
|
|
4
6
|
return {
|
|
5
7
|
chevronX: hasHierarchy ? indent + 10 : null,
|
|
6
8
|
iconX: indent + (hasHierarchy ? 27 : 8),
|
|
7
|
-
labelX: indent + (hasHierarchy ? 50 : 31)
|
|
9
|
+
labelX: indent + (hasHierarchy ? 50 : 31)
|
|
8
10
|
};
|
|
9
11
|
}
|
|
@@ -6,7 +6,7 @@ export const builtInColumns = {
|
|
|
6
6
|
minWidth: 160,
|
|
7
7
|
align: 'left',
|
|
8
8
|
kind: 'tree',
|
|
9
|
-
value: (node) => node.label ?? node.id
|
|
9
|
+
value: (node) => node.label ?? node.id
|
|
10
10
|
},
|
|
11
11
|
status: {
|
|
12
12
|
id: 'status',
|
|
@@ -15,7 +15,7 @@ export const builtInColumns = {
|
|
|
15
15
|
minWidth: 64,
|
|
16
16
|
align: 'center',
|
|
17
17
|
kind: 'status',
|
|
18
|
-
value: (_node, state) => state.status ?? 0
|
|
18
|
+
value: (_node, state) => state.status ?? 0
|
|
19
19
|
},
|
|
20
20
|
value: {
|
|
21
21
|
id: 'value',
|
|
@@ -24,7 +24,7 @@ export const builtInColumns = {
|
|
|
24
24
|
minWidth: 56,
|
|
25
25
|
align: 'right',
|
|
26
26
|
kind: 'value',
|
|
27
|
-
value: (_node, state) => state.value ?? ''
|
|
27
|
+
value: (_node, state) => state.value ?? ''
|
|
28
28
|
},
|
|
29
29
|
progress: {
|
|
30
30
|
id: 'progress',
|
|
@@ -33,7 +33,7 @@ export const builtInColumns = {
|
|
|
33
33
|
minWidth: 80,
|
|
34
34
|
align: 'left',
|
|
35
35
|
kind: 'progress',
|
|
36
|
-
value: (_node, state) => state.progress ?? ''
|
|
36
|
+
value: (_node, state) => state.progress ?? ''
|
|
37
37
|
},
|
|
38
38
|
type: {
|
|
39
39
|
id: 'type',
|
|
@@ -42,7 +42,7 @@ export const builtInColumns = {
|
|
|
42
42
|
minWidth: 70,
|
|
43
43
|
align: 'left',
|
|
44
44
|
kind: 'type',
|
|
45
|
-
value: (node) => node.type ?? ''
|
|
45
|
+
value: (node) => node.type ?? ''
|
|
46
46
|
},
|
|
47
47
|
updated: {
|
|
48
48
|
id: 'updated',
|
|
@@ -51,15 +51,18 @@ export const builtInColumns = {
|
|
|
51
51
|
minWidth: 84,
|
|
52
52
|
align: 'right',
|
|
53
53
|
kind: 'updated',
|
|
54
|
-
value: (_node, state) => state.updatedAt ?? ''
|
|
55
|
-
}
|
|
54
|
+
value: (_node, state) => state.updatedAt ?? ''
|
|
55
|
+
}
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
export class TreeColumnModel {
|
|
59
59
|
constructor(columns = [builtInColumns.tree]) {
|
|
60
60
|
this.columns = [];
|
|
61
61
|
this.contentWidth = 0;
|
|
62
|
-
this.sort = {
|
|
62
|
+
this.sort = {
|
|
63
|
+
columnId: null,
|
|
64
|
+
direction: null
|
|
65
|
+
};
|
|
63
66
|
this.setColumns(columns);
|
|
64
67
|
}
|
|
65
68
|
|
|
@@ -76,23 +79,50 @@ export class TreeColumnModel {
|
|
|
76
79
|
|
|
77
80
|
setRowReorder(enabled) {
|
|
78
81
|
this.rowReorder = Boolean(enabled);
|
|
79
|
-
this.columns = this.columns.filter(column => column.id !== '__vtc_row_order');
|
|
80
|
-
if (this.rowReorder)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
this.columns = this.columns.filter((column) => column.id !== '__vtc_row_order');
|
|
83
|
+
if (this.rowReorder)
|
|
84
|
+
this.columns.unshift(
|
|
85
|
+
normalizeColumn(
|
|
86
|
+
{
|
|
87
|
+
id: '__vtc_row_order',
|
|
88
|
+
label: '',
|
|
89
|
+
kind: 'rowOrder',
|
|
90
|
+
width: 72,
|
|
91
|
+
minWidth: 72,
|
|
92
|
+
sortable: false,
|
|
93
|
+
resizable: false
|
|
94
|
+
},
|
|
95
|
+
0
|
|
96
|
+
)
|
|
97
|
+
);
|
|
84
98
|
this.#layout();
|
|
85
99
|
}
|
|
86
100
|
|
|
87
101
|
setRowActions(count) {
|
|
88
102
|
this.rowActionCount = count;
|
|
89
|
-
this.columns = this.columns.filter(column => column.id !== '__vtc_actions');
|
|
90
|
-
if (count)
|
|
91
|
-
|
|
103
|
+
this.columns = this.columns.filter((column) => column.id !== '__vtc_actions');
|
|
104
|
+
if (count)
|
|
105
|
+
this.columns.push(
|
|
106
|
+
normalizeColumn(
|
|
107
|
+
{
|
|
108
|
+
id: '__vtc_actions',
|
|
109
|
+
label: '',
|
|
110
|
+
kind: 'text',
|
|
111
|
+
width: count * 28,
|
|
112
|
+
minWidth: count * 28,
|
|
113
|
+
sortable: false,
|
|
114
|
+
resizable: false,
|
|
115
|
+
value: () => ''
|
|
116
|
+
},
|
|
117
|
+
0
|
|
118
|
+
)
|
|
119
|
+
);
|
|
92
120
|
this.#layout();
|
|
93
121
|
}
|
|
94
122
|
|
|
95
|
-
/**
|
|
123
|
+
/**
|
|
124
|
+
* @param {number} x
|
|
125
|
+
*/
|
|
96
126
|
getColumnAt(x) {
|
|
97
127
|
return this.columns.find((column) => x >= column.x && x < column.x + column.width) ?? null;
|
|
98
128
|
}
|
|
@@ -114,21 +144,33 @@ export class TreeColumnModel {
|
|
|
114
144
|
const currentIndex = this.columns.findIndex((column) => column.id === id);
|
|
115
145
|
if (currentIndex === -1) return false;
|
|
116
146
|
const [column] = this.columns.splice(currentIndex, 1);
|
|
117
|
-
const nextIndex = Math.max(
|
|
147
|
+
const nextIndex = Math.max(
|
|
148
|
+
this.rowReorder ? 1 : 0,
|
|
149
|
+
Math.min(this.columns.length - (this.rowActionCount ? 1 : 0), targetIndex)
|
|
150
|
+
);
|
|
118
151
|
this.columns.splice(nextIndex, 0, column);
|
|
119
|
-
if (!this.columns.some((item) => item.kind === 'tree'))
|
|
152
|
+
if (!this.columns.some((item) => item.kind === 'tree'))
|
|
153
|
+
this.columns.unshift(normalizeColumn(builtInColumns.tree, 0));
|
|
120
154
|
this.#layout();
|
|
121
155
|
return true;
|
|
122
156
|
}
|
|
123
157
|
|
|
124
158
|
setSort(columnId, direction) {
|
|
125
159
|
if (columnId !== null && !this.getColumn(columnId)) return false;
|
|
126
|
-
this.sort = {
|
|
160
|
+
this.sort = {
|
|
161
|
+
columnId,
|
|
162
|
+
direction
|
|
163
|
+
};
|
|
127
164
|
return true;
|
|
128
165
|
}
|
|
129
166
|
|
|
130
167
|
getResizeHandleAt(x, tolerance = 5) {
|
|
131
|
-
return
|
|
168
|
+
return (
|
|
169
|
+
this.columns.find(
|
|
170
|
+
(column) =>
|
|
171
|
+
column.resizable !== false && Math.abs(x - (column.x + column.width)) <= tolerance
|
|
172
|
+
) ?? null
|
|
173
|
+
);
|
|
132
174
|
}
|
|
133
175
|
|
|
134
176
|
#layout() {
|
|
@@ -139,16 +181,22 @@ export class TreeColumnModel {
|
|
|
139
181
|
}
|
|
140
182
|
this.contentWidth = x;
|
|
141
183
|
}
|
|
184
|
+
|
|
142
185
|
}
|
|
143
186
|
|
|
144
187
|
export function defaultTreeTableColumns() {
|
|
145
188
|
return [
|
|
146
|
-
{
|
|
189
|
+
{
|
|
190
|
+
...builtInColumns.tree,
|
|
191
|
+
id: 'name',
|
|
192
|
+
label: 'Name',
|
|
193
|
+
width: 340
|
|
194
|
+
},
|
|
147
195
|
builtInColumns.type,
|
|
148
196
|
builtInColumns.status,
|
|
149
197
|
builtInColumns.value,
|
|
150
198
|
builtInColumns.progress,
|
|
151
|
-
builtInColumns.updated
|
|
199
|
+
builtInColumns.updated
|
|
152
200
|
];
|
|
153
201
|
}
|
|
154
202
|
|
|
@@ -170,6 +218,6 @@ function normalizeColumn(column, index) {
|
|
|
170
218
|
format: source.format,
|
|
171
219
|
valueType: source.valueType,
|
|
172
220
|
render: source.render,
|
|
173
|
-
x: 0
|
|
221
|
+
x: 0
|
|
174
222
|
};
|
|
175
223
|
}
|
package/src/core/tree-model.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TreeIndex } from './tree-index.js';
|
|
2
|
-
import {
|
|
2
|
+
import { mergeDynamicStateChanged } from './dynamic-state.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Owns structural nodes, expanded state, and per-node dynamic state.
|
|
@@ -86,11 +86,13 @@ export class TreeModel extends EventTarget {
|
|
|
86
86
|
* @param {Array<import('./types.js').DynamicPatch>} patches
|
|
87
87
|
*/
|
|
88
88
|
applyDynamicPatches(patches) {
|
|
89
|
+
const changedIds = new Set();
|
|
89
90
|
for (const patch of patches) {
|
|
90
91
|
const current = this.dynamicState.get(patch.id);
|
|
91
92
|
if (!current) continue;
|
|
92
|
-
|
|
93
|
+
if (mergeDynamicStateChanged(current, patch.state)) changedIds.add(patch.id);
|
|
93
94
|
}
|
|
95
|
+
return changedIds;
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
/** @param {string} id */
|