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
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
let nextStatusId = 0;
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Pointer interaction for the optional row-order column; persistence belongs to the host.
|
|
5
|
+
*/
|
|
4
6
|
export class RowReorderInput {
|
|
5
7
|
constructor(controller) {
|
|
6
8
|
this.controller = controller;
|
|
@@ -16,61 +18,97 @@ export class RowReorderInput {
|
|
|
16
18
|
this.view.addEventListener('pointerup', this.onUp);
|
|
17
19
|
this.view.addEventListener('pointercancel', this.onCancel);
|
|
18
20
|
this.view.addEventListener('blur', this.cancel);
|
|
19
|
-
this.stops = ['filterchange', 'sortchange', 'rowreorderchange'].map(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
21
|
+
this.stops = ['filterchange', 'sortchange', 'rowreorderchange'].map((type) =>
|
|
22
|
+
controller.on(type, () => {
|
|
23
|
+
this.cancel();
|
|
24
|
+
this.syncMode();
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
this.stops.push(
|
|
28
|
+
controller.on('datachange', () => {
|
|
29
|
+
if (this.gesture && !controller.model.index.getNode(this.gesture.id)) this.cancel();
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
this.stops.push(
|
|
33
|
+
controller.on('rowreorder', (event) => {
|
|
34
|
+
if (!this.status) return;
|
|
35
|
+
const { nodeId, toIndex, siblingOrder } = event.detail;
|
|
36
|
+
const label = controller.model.index.getNode(nodeId)?.label ?? nodeId;
|
|
37
|
+
this.status.textContent = `${label}: position ${toIndex + 1} of ${siblingOrder.length}`;
|
|
38
|
+
})
|
|
39
|
+
);
|
|
32
40
|
const doc = this.canvas.ownerDocument;
|
|
33
41
|
if (doc?.createElement && this.canvas.parentElement) {
|
|
34
42
|
this.status = doc.createElement('span');
|
|
35
43
|
this.status.id = `vtc-row-order-status-${nextStatusId++}`;
|
|
36
44
|
this.status.setAttribute('aria-live', 'polite');
|
|
37
|
-
Object.assign(this.status.style, {
|
|
45
|
+
Object.assign(this.status.style, {
|
|
46
|
+
position: 'absolute',
|
|
47
|
+
width: '1px',
|
|
48
|
+
height: '1px',
|
|
49
|
+
overflow: 'hidden',
|
|
50
|
+
clipPath: 'inset(50%)'
|
|
51
|
+
});
|
|
38
52
|
this.canvas.parentElement.appendChild(this.status);
|
|
39
53
|
}
|
|
40
54
|
this.syncMode();
|
|
41
55
|
}
|
|
42
56
|
|
|
43
57
|
syncMode() {
|
|
44
|
-
this.canvas.style.touchAction =
|
|
58
|
+
this.canvas.style.touchAction =
|
|
59
|
+
this.controller.canReorderRows() || this.controller.rowDrag
|
|
60
|
+
? 'none'
|
|
61
|
+
: this.previousTouchAction;
|
|
45
62
|
}
|
|
46
63
|
|
|
47
|
-
onDown = event => {
|
|
64
|
+
onDown = (event) => {
|
|
48
65
|
if (event.button !== 0 || event.isPrimary === false || this.gesture) return;
|
|
49
66
|
this.suppressClick = false;
|
|
50
67
|
const point = this.point(event);
|
|
51
68
|
const hit = this.controller.hitTest(point.x, point.y);
|
|
52
69
|
if (!hit?.row) return;
|
|
53
70
|
const node = this.controller.model.index.getNode(hit.row.nodeId);
|
|
54
|
-
const payload =
|
|
71
|
+
const payload =
|
|
72
|
+
this.controller.rowDrag?.(node, this.controller.model.dynamicState.get(node.id) ?? {}) ??
|
|
73
|
+
null;
|
|
55
74
|
const orderPart = ['rowDrag', 'rowUp', 'rowDown'].includes(hit.part);
|
|
56
75
|
if (orderPart && node.reorderable === false) return;
|
|
57
|
-
if (
|
|
58
|
-
|
|
76
|
+
if (
|
|
77
|
+
orderPart
|
|
78
|
+
? !this.controller.canReorderRows() && !(payload != null && hit.part === 'rowDrag')
|
|
79
|
+
: payload == null || !['label', 'row', 'icon', 'cell'].includes(hit.part)
|
|
80
|
+
)
|
|
81
|
+
return;
|
|
82
|
+
this.canvas.focus({
|
|
83
|
+
preventScroll: true
|
|
84
|
+
});
|
|
59
85
|
this.controller.cellEditor?.close?.();
|
|
60
86
|
this.controller.focusedId = hit.row.nodeId;
|
|
61
|
-
this.gesture = {
|
|
62
|
-
|
|
87
|
+
this.gesture = {
|
|
88
|
+
id: hit.row.nodeId,
|
|
89
|
+
part: orderPart ? hit.part : 'rowDrag',
|
|
90
|
+
payload,
|
|
91
|
+
pointerId: event.pointerId,
|
|
92
|
+
startX: point.x,
|
|
93
|
+
startY: point.y,
|
|
94
|
+
point,
|
|
95
|
+
dragging: false
|
|
96
|
+
};
|
|
63
97
|
this.canvas.setPointerCapture?.(event.pointerId);
|
|
64
98
|
event.stopPropagation();
|
|
65
99
|
if (orderPart) event.preventDefault();
|
|
66
100
|
};
|
|
67
101
|
|
|
68
|
-
onMove = event => {
|
|
102
|
+
onMove = (event) => {
|
|
69
103
|
const gesture = this.gesture;
|
|
70
104
|
if (!gesture || event.pointerId !== gesture.pointerId) return;
|
|
71
105
|
gesture.point = this.point(event);
|
|
72
106
|
if (gesture.part !== 'rowDrag') return;
|
|
73
|
-
if (
|
|
107
|
+
if (
|
|
108
|
+
!gesture.dragging &&
|
|
109
|
+
Math.hypot(gesture.point.x - gesture.startX, gesture.point.y - gesture.startY) < 5
|
|
110
|
+
)
|
|
111
|
+
return;
|
|
74
112
|
if (!gesture.dragging && gesture.payload != null) this.emitDrag('rowdragstart', event);
|
|
75
113
|
gesture.dragging = true;
|
|
76
114
|
if (gesture.payload != null) this.emitDrag('rowdragmove', event);
|
|
@@ -80,24 +118,37 @@ export class RowReorderInput {
|
|
|
80
118
|
event.preventDefault();
|
|
81
119
|
};
|
|
82
120
|
|
|
83
|
-
onUp = event => {
|
|
121
|
+
onUp = (event) => {
|
|
84
122
|
const gesture = this.gesture;
|
|
85
123
|
if (!gesture || event.pointerId !== gesture.pointerId) return;
|
|
86
124
|
gesture.point = this.point(event);
|
|
87
|
-
const target = gesture.dragging
|
|
125
|
+
const target = gesture.dragging
|
|
126
|
+
? this.controller.getRowDropTarget(gesture.id, gesture.point.x, gesture.point.y)
|
|
127
|
+
: null;
|
|
88
128
|
const hit = this.controller.hitTest(gesture.point.x, gesture.point.y);
|
|
89
129
|
if (gesture.dragging && gesture.payload != null) this.emitDrag('rowdragend', event);
|
|
90
130
|
this.suppressClick = gesture.dragging;
|
|
91
131
|
this.cancel(false);
|
|
92
|
-
if (target)
|
|
132
|
+
if (target)
|
|
133
|
+
this.controller.moveRow(gesture.id, target.index, {
|
|
134
|
+
source: 'pointer'
|
|
135
|
+
});
|
|
93
136
|
else if (!gesture.dragging && hit?.row?.nodeId === gesture.id && hit.part === gesture.part) {
|
|
94
|
-
if (gesture.part === 'rowUp')
|
|
95
|
-
|
|
137
|
+
if (gesture.part === 'rowUp')
|
|
138
|
+
this.controller.moveRowBy(gesture.id, -1, {
|
|
139
|
+
source: 'button'
|
|
140
|
+
});
|
|
141
|
+
if (gesture.part === 'rowDown')
|
|
142
|
+
this.controller.moveRowBy(gesture.id, 1, {
|
|
143
|
+
source: 'button'
|
|
144
|
+
});
|
|
96
145
|
}
|
|
97
146
|
};
|
|
98
147
|
|
|
99
|
-
onCancel = event => {
|
|
100
|
-
|
|
148
|
+
onCancel = (event) => {
|
|
149
|
+
if (this.gesture?.pointerId === event.pointerId) this.cancel();
|
|
150
|
+
};
|
|
151
|
+
onKey = (event) => {
|
|
101
152
|
if (event.key === 'Escape' && this.gesture) {
|
|
102
153
|
this.cancel();
|
|
103
154
|
event.preventDefault();
|
|
@@ -106,24 +157,38 @@ export class RowReorderInput {
|
|
|
106
157
|
|
|
107
158
|
point(event) {
|
|
108
159
|
const rect = this.canvas.getBoundingClientRect();
|
|
109
|
-
return {
|
|
160
|
+
return {
|
|
161
|
+
x: event.clientX - rect.left,
|
|
162
|
+
y: event.clientY - rect.top
|
|
163
|
+
};
|
|
110
164
|
}
|
|
111
165
|
|
|
112
166
|
updateTarget() {
|
|
113
167
|
const gesture = this.gesture;
|
|
114
|
-
this.controller.setRowDrop(
|
|
168
|
+
this.controller.setRowDrop(
|
|
169
|
+
gesture
|
|
170
|
+
? this.controller.getRowDropTarget(gesture.id, gesture.point.x, gesture.point.y)
|
|
171
|
+
: null
|
|
172
|
+
);
|
|
115
173
|
}
|
|
116
174
|
|
|
117
175
|
scheduleScroll() {
|
|
118
176
|
if (this.frame !== null || !this.gesture?.dragging) return;
|
|
119
177
|
const viewport = this.controller.viewport;
|
|
120
|
-
if (
|
|
178
|
+
if (
|
|
179
|
+
this.gesture.point.x < 0 ||
|
|
180
|
+
this.gesture.point.x > viewport.viewportWidth ||
|
|
181
|
+
this.gesture.point.y < 0 ||
|
|
182
|
+
this.gesture.point.y > viewport.viewportHeight
|
|
183
|
+
)
|
|
184
|
+
return;
|
|
121
185
|
const y = this.gesture.point.y - viewport.renderInsetY;
|
|
122
186
|
const top = viewport.headerHeight;
|
|
123
187
|
const bottom = top + viewport.rowViewportHeight;
|
|
124
188
|
const delta = y < top + 24 ? -10 : y > bottom - 24 ? 10 : 0;
|
|
125
189
|
if (!delta) return;
|
|
126
|
-
const schedule =
|
|
190
|
+
const schedule =
|
|
191
|
+
this.view.requestAnimationFrame?.bind(this.view) ?? ((callback) => setTimeout(callback, 16));
|
|
127
192
|
this.frame = schedule(() => {
|
|
128
193
|
this.frame = null;
|
|
129
194
|
if (!this.gesture?.dragging) return;
|
|
@@ -136,8 +201,13 @@ export class RowReorderInput {
|
|
|
136
201
|
|
|
137
202
|
emitDrag(type, originalEvent) {
|
|
138
203
|
const gesture = this.gesture;
|
|
139
|
-
if (gesture)
|
|
140
|
-
|
|
204
|
+
if (gesture)
|
|
205
|
+
this.controller.events.emit(type, {
|
|
206
|
+
nodeId: gesture.id,
|
|
207
|
+
payload: gesture.payload,
|
|
208
|
+
label: this.controller.model.index.getNode(gesture.id)?.label ?? gesture.id,
|
|
209
|
+
originalEvent
|
|
210
|
+
});
|
|
141
211
|
}
|
|
142
212
|
|
|
143
213
|
cancel = (notify = true) => {
|
|
@@ -145,9 +215,11 @@ export class RowReorderInput {
|
|
|
145
215
|
if (gesture?.dragging) this.suppressClick = true;
|
|
146
216
|
if (notify && gesture?.dragging && gesture.payload != null) this.emitDrag('rowdragcancel');
|
|
147
217
|
this.gesture = null;
|
|
148
|
-
if (this.frame !== null)
|
|
218
|
+
if (this.frame !== null)
|
|
219
|
+
(this.view.cancelAnimationFrame?.bind(this.view) ?? clearTimeout)(this.frame);
|
|
149
220
|
this.frame = null;
|
|
150
|
-
if (gesture && this.canvas.hasPointerCapture?.(gesture.pointerId))
|
|
221
|
+
if (gesture && this.canvas.hasPointerCapture?.(gesture.pointerId))
|
|
222
|
+
this.canvas.releasePointerCapture(gesture.pointerId);
|
|
151
223
|
this.canvas.style.cursor = '';
|
|
152
224
|
this.controller.setRowDrop(null);
|
|
153
225
|
};
|
|
@@ -165,4 +237,5 @@ export class RowReorderInput {
|
|
|
165
237
|
for (const stop of this.stops) stop();
|
|
166
238
|
this.status?.remove();
|
|
167
239
|
}
|
|
240
|
+
|
|
168
241
|
}
|
|
@@ -4,6 +4,8 @@ export class TreeTooltip {
|
|
|
4
4
|
this.controller = controller;
|
|
5
5
|
this.canvas = controller.canvas;
|
|
6
6
|
this.host = host;
|
|
7
|
+
this.pointer = null;
|
|
8
|
+
this.targetKey = null;
|
|
7
9
|
if (!this.canvas || !host?.ownerDocument) throw new Error('TreeTooltip requires a mounted canvas and host');
|
|
8
10
|
this.element = host.ownerDocument.createElement('div');
|
|
9
11
|
this.element.className = 'virtual-tree-canvas-tooltip';
|
|
@@ -17,13 +19,28 @@ export class TreeTooltip {
|
|
|
17
19
|
});
|
|
18
20
|
host.appendChild(this.element);
|
|
19
21
|
this.canvas.addEventListener('mousemove', this.onMove);
|
|
20
|
-
this.canvas.addEventListener('mouseleave', this.
|
|
22
|
+
this.canvas.addEventListener('mouseleave', this.onLeave);
|
|
21
23
|
this.canvas.addEventListener('wheel', this.hide);
|
|
22
24
|
this.canvas.addEventListener('pointerdown', this.hide);
|
|
23
|
-
this.stops = [
|
|
25
|
+
this.stops = [
|
|
26
|
+
...['viewportchange', 'filterchange', 'rowdrag'].map(type => controller.on(type, this.hide)),
|
|
27
|
+
controller.on('datachange', this.refresh)
|
|
28
|
+
];
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
onMove = event => {
|
|
32
|
+
this.pointer = { clientX: event.clientX, clientY: event.clientY };
|
|
33
|
+
this.#update(true, false);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Refresh a visible tooltip without requiring another mousemove event. */
|
|
37
|
+
refresh = () => {
|
|
38
|
+
if (this.element.style.display === 'none' || !this.pointer) return;
|
|
39
|
+
this.#update(false, true);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
#update(reposition, preserveTarget) {
|
|
43
|
+
const event = this.pointer;
|
|
27
44
|
const rect = this.canvas.getBoundingClientRect();
|
|
28
45
|
const hit = this.controller.hitTest(event.clientX - rect.left, event.clientY - rect.top);
|
|
29
46
|
let text;
|
|
@@ -33,23 +50,40 @@ export class TreeTooltip {
|
|
|
33
50
|
: 'Clear sorting and filtering to reorder rows.';
|
|
34
51
|
} else text = this.controller.getTooltipForHit(hit)?.text;
|
|
35
52
|
if (!text || this.controller.rowReorderInput?.gesture) return this.hide();
|
|
53
|
+
const targetKey = tooltipTargetKey(hit);
|
|
54
|
+
if (preserveTarget && targetKey !== this.targetKey) return this.hide();
|
|
55
|
+
this.targetKey = targetKey;
|
|
56
|
+
if (this.element.textContent !== text) this.element.textContent = text;
|
|
57
|
+
if (!reposition) return;
|
|
36
58
|
const hostRect = this.host.getBoundingClientRect();
|
|
37
|
-
this.element.textContent = text;
|
|
38
59
|
this.element.style.display = 'block';
|
|
39
60
|
const x = event.clientX - hostRect.left + 12;
|
|
40
61
|
const y = event.clientY - hostRect.top + 14;
|
|
41
62
|
this.element.style.left = `${Math.max(8, Math.min(x, hostRect.width - this.element.offsetWidth - 8))}px`;
|
|
42
63
|
this.element.style.top = `${Math.max(8, Math.min(y, hostRect.height - this.element.offsetHeight - 8))}px`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
hide = () => {
|
|
67
|
+
this.element.style.display = 'none';
|
|
68
|
+
this.targetKey = null;
|
|
43
69
|
};
|
|
44
70
|
|
|
45
|
-
|
|
71
|
+
onLeave = () => {
|
|
72
|
+
this.pointer = null;
|
|
73
|
+
this.hide();
|
|
74
|
+
};
|
|
46
75
|
|
|
47
76
|
destroy() {
|
|
48
77
|
this.canvas.removeEventListener('mousemove', this.onMove);
|
|
49
|
-
this.canvas.removeEventListener('mouseleave', this.
|
|
78
|
+
this.canvas.removeEventListener('mouseleave', this.onLeave);
|
|
50
79
|
this.canvas.removeEventListener('wheel', this.hide);
|
|
51
80
|
this.canvas.removeEventListener('pointerdown', this.hide);
|
|
52
81
|
for (const stop of this.stops) stop();
|
|
53
82
|
this.element.remove();
|
|
54
83
|
}
|
|
55
84
|
}
|
|
85
|
+
|
|
86
|
+
function tooltipTargetKey(hit) {
|
|
87
|
+
if (!hit) return '';
|
|
88
|
+
return `${hit.area ?? ''}\0${hit.row?.nodeId ?? ''}\0${hit.column?.id ?? ''}\0${hit.part ?? ''}`;
|
|
89
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export class TreeViewInputController {
|
|
2
|
+
|
|
2
3
|
/**
|
|
3
4
|
* @param {{
|
|
4
5
|
* controller: import('../tree-view-controller.js').TreeViewController,
|
|
@@ -6,8 +7,10 @@ export class TreeViewInputController {
|
|
|
6
7
|
* }} options
|
|
7
8
|
*/
|
|
8
9
|
constructor(options) {
|
|
9
|
-
if (!options?.controller)
|
|
10
|
-
|
|
10
|
+
if (!options?.controller)
|
|
11
|
+
throw new TypeError('TreeViewInputController requires a TreeViewController');
|
|
12
|
+
if (!options.controller.canvas)
|
|
13
|
+
throw new Error('TreeViewInputController requires an initialized TreeViewController canvas');
|
|
11
14
|
this.controller = options.controller;
|
|
12
15
|
this.canvas = options.controller.canvas;
|
|
13
16
|
this.hoveredId = null;
|
|
@@ -15,7 +18,9 @@ export class TreeViewInputController {
|
|
|
15
18
|
this.cellEditor = options.cellEditor ?? null;
|
|
16
19
|
this.canvas.tabIndex = 0;
|
|
17
20
|
|
|
18
|
-
this.canvas.addEventListener('wheel', this.#onWheel, {
|
|
21
|
+
this.canvas.addEventListener('wheel', this.#onWheel, {
|
|
22
|
+
passive: false
|
|
23
|
+
});
|
|
19
24
|
this.canvas.addEventListener('mousedown', this.#onMouseDown);
|
|
20
25
|
this.canvas.addEventListener('mousemove', this.#onMouseMove);
|
|
21
26
|
(this.canvas.ownerDocument.defaultView ?? window).addEventListener('mouseup', this.#onMouseUp);
|
|
@@ -29,7 +34,10 @@ export class TreeViewInputController {
|
|
|
29
34
|
this.canvas.removeEventListener('wheel', this.#onWheel);
|
|
30
35
|
this.canvas.removeEventListener('mousedown', this.#onMouseDown);
|
|
31
36
|
this.canvas.removeEventListener('mousemove', this.#onMouseMove);
|
|
32
|
-
(this.canvas.ownerDocument.defaultView ?? window).removeEventListener(
|
|
37
|
+
(this.canvas.ownerDocument.defaultView ?? window).removeEventListener(
|
|
38
|
+
'mouseup',
|
|
39
|
+
this.#onMouseUp
|
|
40
|
+
);
|
|
33
41
|
this.canvas.removeEventListener('mouseleave', this.#onMouseLeave);
|
|
34
42
|
this.canvas.removeEventListener('click', this.#onClick);
|
|
35
43
|
this.canvas.removeEventListener('dblclick', this.#onDoubleClick);
|
|
@@ -71,13 +79,18 @@ export class TreeViewInputController {
|
|
|
71
79
|
};
|
|
72
80
|
|
|
73
81
|
#onClick = (event) => {
|
|
74
|
-
if (this.controller.rowReorderInput?.suppressClick) {
|
|
82
|
+
if (this.controller.rowReorderInput?.suppressClick) {
|
|
83
|
+
this.controller.rowReorderInput.suppressClick = false;
|
|
84
|
+
event.preventDefault();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
75
87
|
const hit = this.#hitTest(event);
|
|
76
88
|
if (!hit) return;
|
|
77
89
|
if (['rowDrag', 'rowUp', 'rowDown'].includes(hit.part)) return;
|
|
78
90
|
if (hit.area === 'header') {
|
|
79
91
|
if (hit.part === 'filter' && this.cellEditor?.handleHeaderClick(event, hit)) return;
|
|
80
|
-
if (!this.resizeDrag && hit.part === 'label' && hit.column)
|
|
92
|
+
if (!this.resizeDrag && hit.part === 'label' && hit.column)
|
|
93
|
+
this.controller.sortBy(hit.column.id);
|
|
81
94
|
return;
|
|
82
95
|
}
|
|
83
96
|
if (hit.part === 'chevron' && hit.row.hasChildren) {
|
|
@@ -85,12 +98,14 @@ export class TreeViewInputController {
|
|
|
85
98
|
return;
|
|
86
99
|
}
|
|
87
100
|
if (this.cellEditor?.handleClick(event, hit)) return;
|
|
88
|
-
this.canvas.focus({
|
|
101
|
+
this.canvas.focus({
|
|
102
|
+
preventScroll: true
|
|
103
|
+
});
|
|
89
104
|
this.controller.clickNode(hit.row.nodeId, {
|
|
90
105
|
shiftKey: event.shiftKey,
|
|
91
106
|
ctrlKey: event.ctrlKey,
|
|
92
107
|
metaKey: event.metaKey,
|
|
93
|
-
multi: this.canvas.dataset.multi === 'true'
|
|
108
|
+
multi: this.canvas.dataset.multi === 'true'
|
|
94
109
|
});
|
|
95
110
|
};
|
|
96
111
|
|
|
@@ -113,7 +128,7 @@ export class TreeViewInputController {
|
|
|
113
128
|
this.resizeDrag = {
|
|
114
129
|
columnId: hit.column.id,
|
|
115
130
|
startX: event.clientX - rect.left,
|
|
116
|
-
startWidth: hit.column.width
|
|
131
|
+
startWidth: hit.column.width
|
|
117
132
|
};
|
|
118
133
|
this.canvas.style.cursor = 'col-resize';
|
|
119
134
|
event.preventDefault();
|
|
@@ -137,6 +152,7 @@ export class TreeViewInputController {
|
|
|
137
152
|
const clientY = event.clientY - rect.top;
|
|
138
153
|
return this.controller.hitTest(clientX, clientY);
|
|
139
154
|
}
|
|
155
|
+
|
|
140
156
|
}
|
|
141
157
|
|
|
142
158
|
function cursorForHit(hit) {
|
|
@@ -145,7 +161,14 @@ function cursorForHit(hit) {
|
|
|
145
161
|
if (hit?.area === 'header' && hit.part === 'resize') return 'col-resize';
|
|
146
162
|
if (hit?.area === 'header' && hit.part === 'filter') return 'text';
|
|
147
163
|
if (hit?.area !== 'row') return '';
|
|
148
|
-
if (
|
|
164
|
+
if (
|
|
165
|
+
hit.part === 'button' ||
|
|
166
|
+
hit.part === 'checkbox' ||
|
|
167
|
+
hit.part === 'arrayAdd' ||
|
|
168
|
+
hit.part === 'arrayRemove' ||
|
|
169
|
+
hit.part === 'chevron'
|
|
170
|
+
)
|
|
171
|
+
return 'pointer';
|
|
149
172
|
if (hit.part === 'editor' || hit.part === 'number') return 'text';
|
|
150
173
|
if (hit.part === 'range') return 'ew-resize';
|
|
151
174
|
return '';
|