wenay-react2 1.0.38 → 1.0.40
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/lib/common/src/components/Dnd/FloatingWindow.d.ts +29 -12
- package/lib/common/src/components/Dnd/FloatingWindow.js +100 -91
- package/lib/common/src/components/Input.d.ts +25 -6
- package/lib/common/src/components/Input.js +27 -8
- package/lib/common/src/components/Menu/RightMenu.d.ts +28 -1
- package/lib/common/src/components/Menu/RightMenu.js +62 -35
- package/lib/common/src/components/Modal/LeftModal.js +5 -4
- package/lib/common/src/components/Modal/Modal.js +8 -7
- package/lib/common/src/components/ParamsEditor.d.ts +15 -0
- package/lib/common/src/components/ParamsEditor.js +45 -18
- package/lib/common/src/components/Settings/SettingsDialog.d.ts +68 -6
- package/lib/common/src/components/Settings/SettingsDialog.js +73 -13
- package/lib/common/src/components/Toolbar/Toolbar.js +64 -19
- package/lib/common/src/components/UiSlot/UiSlot.js +5 -4
- package/lib/common/src/grid/columnState/ColumnDots.d.ts +1 -1
- package/lib/common/src/grid/columnState/ColumnDots.js +1 -1
- package/lib/common/src/grid/columnState/ColumnsMenu.js +10 -18
- package/lib/common/src/grid/columnState/columnState.js +8 -6
- package/lib/common/src/hooks/useKeyboard.js +4 -3
- package/lib/common/src/logs/logs.d.ts +13 -133
- package/lib/common/src/logs/logs.js +20 -39
- package/lib/common/src/logs/logsContext.d.ts +26 -0
- package/lib/common/src/logs/logsContext.js +25 -20
- package/lib/common/src/logs/logsController.d.ts +88 -0
- package/lib/common/src/logs/logsController.js +54 -0
- package/lib/common/src/logs/miniLogs.d.ts +69 -3
- package/lib/common/src/logs/miniLogs.js +70 -15
- package/lib/common/src/menu/menu.d.ts +15 -3
- package/lib/common/src/menu/menu.js +81 -17
- package/lib/common/src/menu/menuMouse.d.ts +35 -0
- package/lib/common/src/menu/menuMouse.js +113 -4
- package/lib/common/src/styles/tokens.d.ts +79 -1
- package/lib/common/src/styles/tokens.js +79 -1
- package/lib/common/src/utils/memoryStore.d.ts +1 -10
- package/lib/common/src/utils/searchHistory.js +4 -3
- package/lib/style/style.css +122 -50
- package/lib/style/tokens.css +76 -2
- package/package.json +49 -49
|
@@ -29,7 +29,7 @@ function MenuProgress({ data }) {
|
|
|
29
29
|
/*******************************************************
|
|
30
30
|
* Main menu element with onClick and counters
|
|
31
31
|
*******************************************************/
|
|
32
|
-
function MenuElement({ data: item, toLeft, className, update, open, }) {
|
|
32
|
+
function MenuElement({ data: item, toLeft, className, update, open, onActionEvent, }) {
|
|
33
33
|
const unsubOk = useRef(null);
|
|
34
34
|
const unsubErr = useRef(null);
|
|
35
35
|
useEffect(() => {
|
|
@@ -47,8 +47,18 @@ function MenuElement({ data: item, toLeft, className, update, open, }) {
|
|
|
47
47
|
"MenuR " + (active ? "toButtonA" : "toButton"), style: { float: toLeft ? "left" : "right" }, onClick: () => {
|
|
48
48
|
if (!item.onClick)
|
|
49
49
|
return;
|
|
50
|
-
const
|
|
50
|
+
const actionKey = item.actionKey ?? undefined;
|
|
51
|
+
onActionEvent?.({ type: "click", item: item, actionKey });
|
|
52
|
+
let result;
|
|
53
|
+
try {
|
|
54
|
+
result = item.onClick(item);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
onActionEvent?.({ type: "error", item: item, actionKey, error });
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
51
60
|
if (!result) {
|
|
61
|
+
onActionEvent?.({ type: "ok", item: item, actionKey });
|
|
52
62
|
update();
|
|
53
63
|
return;
|
|
54
64
|
}
|
|
@@ -72,8 +82,14 @@ function MenuElement({ data: item, toLeft, className, update, open, }) {
|
|
|
72
82
|
setProgress(null);
|
|
73
83
|
}
|
|
74
84
|
};
|
|
75
|
-
unsubOk.current = pa.onOk((data, i, countOk, countError, count) =>
|
|
76
|
-
|
|
85
|
+
unsubOk.current = pa.onOk((data, i, countOk, countError, count) => {
|
|
86
|
+
onActionEvent?.({ type: "taskOk", item: item, actionKey });
|
|
87
|
+
return onTick(countOk, countError, count);
|
|
88
|
+
});
|
|
89
|
+
unsubErr.current = pa.onError((error, i, countOk, countError, count) => {
|
|
90
|
+
onActionEvent?.({ type: "taskError", item: item, actionKey, error });
|
|
91
|
+
return onTick(countOk, countError, count);
|
|
92
|
+
});
|
|
77
93
|
void pa.allSettled();
|
|
78
94
|
}
|
|
79
95
|
// If this is a single promise
|
|
@@ -81,6 +97,7 @@ function MenuElement({ data: item, toLeft, className, update, open, }) {
|
|
|
81
97
|
setProgress({});
|
|
82
98
|
result
|
|
83
99
|
.then(async (val) => {
|
|
100
|
+
onActionEvent?.({ type: "ok", item: item, actionKey });
|
|
84
101
|
if (Array.isArray(val) && val.length) {
|
|
85
102
|
// If an array from Promise.allSettled was returned
|
|
86
103
|
// Count ok/error results
|
|
@@ -99,6 +116,10 @@ function MenuElement({ data: item, toLeft, className, update, open, }) {
|
|
|
99
116
|
setProgress({ ok: 1 });
|
|
100
117
|
await sleepAsync(0);
|
|
101
118
|
}
|
|
119
|
+
})
|
|
120
|
+
.catch((error) => {
|
|
121
|
+
onActionEvent?.({ type: "error", item: item, actionKey, error });
|
|
122
|
+
throw error;
|
|
102
123
|
})
|
|
103
124
|
.finally(async () => {
|
|
104
125
|
await sleepAsync(500);
|
|
@@ -106,73 +127,116 @@ function MenuElement({ data: item, toLeft, className, update, open, }) {
|
|
|
106
127
|
});
|
|
107
128
|
}
|
|
108
129
|
else {
|
|
130
|
+
onActionEvent?.({ type: "ok", item: item, actionKey });
|
|
109
131
|
update();
|
|
110
132
|
}
|
|
111
133
|
}, children: _jsxs("div", { className: "toLine", children: [typeof item.name === "string"
|
|
112
134
|
? item.name
|
|
113
135
|
: item.name(item.getStatus?.()), progress && _jsx(MenuProgress, { data: progress })] }) }));
|
|
114
136
|
}
|
|
115
|
-
const MenuItemWrapper = ({ item, index, update, className, isLeftAligned, leftPos, menuElement, open, setOpenIndex, }) => {
|
|
137
|
+
const MenuItemWrapper = ({ item, index, update, className, isLeftAligned, leftPos, menuElement, open, setOpenIndex, onActionEvent, }) => {
|
|
116
138
|
const [childMenu, setChildMenu] = useState([]);
|
|
117
139
|
const [asyncFuncElement, setAsyncFuncElement] = useState(null);
|
|
118
140
|
const [onFocusMenu, setOnFocusMenu] = useState([]);
|
|
119
141
|
useEffect(() => {
|
|
120
142
|
if (open && item.next) {
|
|
143
|
+
const actionKey = item.actionKey ?? undefined;
|
|
144
|
+
onActionEvent?.({ type: "submenuOpen", item, actionKey });
|
|
121
145
|
let alive = true; // guard: do not set state after unmount or item change
|
|
122
|
-
|
|
146
|
+
let result;
|
|
147
|
+
try {
|
|
148
|
+
result = item.next();
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
onActionEvent?.({ type: "submenuError", item, actionKey, error });
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
123
154
|
if (result instanceof Promise) {
|
|
124
155
|
result.then((val) => {
|
|
125
156
|
if (alive)
|
|
126
157
|
setChildMenu(val.filter(Boolean));
|
|
158
|
+
onActionEvent?.({ type: "submenuOk", item, actionKey });
|
|
159
|
+
}).catch((error) => {
|
|
160
|
+
onActionEvent?.({ type: "submenuError", item, actionKey, error });
|
|
161
|
+
throw error;
|
|
127
162
|
});
|
|
128
163
|
}
|
|
129
164
|
else {
|
|
130
165
|
setChildMenu(result.filter(Boolean));
|
|
166
|
+
onActionEvent?.({ type: "submenuOk", item, actionKey });
|
|
131
167
|
}
|
|
132
168
|
return () => { alive = false; };
|
|
133
169
|
}
|
|
134
170
|
else {
|
|
135
171
|
setChildMenu([]);
|
|
136
172
|
}
|
|
137
|
-
}, [open, item.next]);
|
|
173
|
+
}, [open, item, item.next, onActionEvent]);
|
|
138
174
|
useEffect(() => {
|
|
139
175
|
if (open && item.func) {
|
|
176
|
+
const actionKey = item.actionKey ?? undefined;
|
|
177
|
+
onActionEvent?.({ type: "funcOpen", item, actionKey });
|
|
140
178
|
let alive = true;
|
|
141
|
-
|
|
179
|
+
let result;
|
|
180
|
+
try {
|
|
181
|
+
result = item.func();
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
onActionEvent?.({ type: "funcError", item, actionKey, error });
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
142
187
|
if (result instanceof Promise) {
|
|
143
188
|
result.then((val) => {
|
|
144
189
|
if (alive)
|
|
145
190
|
setAsyncFuncElement(val);
|
|
191
|
+
onActionEvent?.({ type: "funcOk", item, actionKey });
|
|
192
|
+
}).catch((error) => {
|
|
193
|
+
onActionEvent?.({ type: "funcError", item, actionKey, error });
|
|
194
|
+
throw error;
|
|
146
195
|
});
|
|
147
196
|
}
|
|
148
197
|
else {
|
|
149
198
|
setAsyncFuncElement(result);
|
|
199
|
+
onActionEvent?.({ type: "funcOk", item, actionKey });
|
|
150
200
|
}
|
|
151
201
|
return () => { alive = false; };
|
|
152
202
|
}
|
|
153
203
|
else {
|
|
154
204
|
setAsyncFuncElement(null);
|
|
155
205
|
}
|
|
156
|
-
}, [open, item.func]);
|
|
206
|
+
}, [open, item, item.func, onActionEvent]);
|
|
157
207
|
useEffect(() => {
|
|
158
208
|
if (open && item.onFocus) {
|
|
209
|
+
const actionKey = item.actionKey ?? undefined;
|
|
210
|
+
onActionEvent?.({ type: "focusOpen", item, actionKey });
|
|
159
211
|
let alive = true;
|
|
160
|
-
|
|
212
|
+
let result;
|
|
213
|
+
try {
|
|
214
|
+
result = item.onFocus();
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
onActionEvent?.({ type: "focusError", item, actionKey, error });
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
161
220
|
if (result instanceof Promise) {
|
|
162
221
|
result.then((val) => {
|
|
163
222
|
if (alive)
|
|
164
223
|
setOnFocusMenu(val.filter(Boolean));
|
|
224
|
+
onActionEvent?.({ type: "focusOk", item, actionKey });
|
|
225
|
+
}).catch((error) => {
|
|
226
|
+
onActionEvent?.({ type: "focusError", item, actionKey, error });
|
|
227
|
+
throw error;
|
|
165
228
|
});
|
|
166
229
|
}
|
|
167
230
|
else {
|
|
168
231
|
setOnFocusMenu(result.filter(Boolean));
|
|
232
|
+
onActionEvent?.({ type: "focusOk", item, actionKey });
|
|
169
233
|
}
|
|
170
234
|
return () => { alive = false; };
|
|
171
235
|
}
|
|
172
236
|
else {
|
|
173
237
|
setOnFocusMenu([]);
|
|
174
238
|
}
|
|
175
|
-
}, [open, item.onFocus]);
|
|
239
|
+
}, [open, item, item.onFocus, onActionEvent]);
|
|
176
240
|
const onMouseEnter = () => {
|
|
177
241
|
if (open)
|
|
178
242
|
return;
|
|
@@ -186,24 +250,24 @@ const MenuItemWrapper = ({ item, index, update, className, isLeftAligned, leftPo
|
|
|
186
250
|
data: viewItem,
|
|
187
251
|
className,
|
|
188
252
|
update,
|
|
189
|
-
}) ?? (_jsx(MenuElement, { toLeft: isLeftAligned, data: viewItem, className: className, update: update, open: open })), _jsxs("div", { children: [open && childMenu.length > 0 && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { data: childMenu, coordinate: {
|
|
253
|
+
}) ?? (_jsx(MenuElement, { toLeft: isLeftAligned, data: viewItem, className: className, update: update, open: open, onActionEvent: onActionEvent })), _jsxs("div", { children: [open && childMenu.length > 0 && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { data: childMenu, coordinate: {
|
|
190
254
|
x: 3,
|
|
191
255
|
y: 0,
|
|
192
256
|
toLeft: isLeftAligned,
|
|
193
257
|
left: leftPos,
|
|
194
|
-
} }) })), open && asyncFuncElement && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { menu: () => asyncFuncElement, data: [], coordinate: {
|
|
258
|
+
}, onActionEvent: onActionEvent }) })), open && asyncFuncElement && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { menu: () => asyncFuncElement, data: [], coordinate: {
|
|
195
259
|
x: 3,
|
|
196
260
|
y: 0,
|
|
197
261
|
toLeft: isLeftAligned,
|
|
198
262
|
left: leftPos,
|
|
199
|
-
} }) })), open && onFocusMenu.length > 0 && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { data: onFocusMenu, coordinate: {
|
|
263
|
+
}, onActionEvent: onActionEvent }) })), open && onFocusMenu.length > 0 && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { data: onFocusMenu, coordinate: {
|
|
200
264
|
x: 3,
|
|
201
265
|
y: 0,
|
|
202
266
|
toLeft: isLeftAligned,
|
|
203
267
|
left: leftPos,
|
|
204
|
-
} }) }))] })] }));
|
|
268
|
+
}, onActionEvent: onActionEvent }) }))] })] }));
|
|
205
269
|
};
|
|
206
|
-
export function Menu({ coordinate = { x: 0, y: 0, toLeft: false, left: 0 }, data, zIndex, menu, className, menuElement, }) {
|
|
270
|
+
export function Menu({ coordinate = { x: 0, y: 0, toLeft: false, left: 0 }, data, zIndex, menu, className, menuElement, onActionEvent, }) {
|
|
207
271
|
const [, forceUpdate] = useState(false);
|
|
208
272
|
const update = () => forceUpdate((p) => !p);
|
|
209
273
|
const refMenu = useRef(null);
|
|
@@ -257,6 +321,6 @@ export function Menu({ coordinate = { x: 0, y: 0, toLeft: false, left: 0 }, data
|
|
|
257
321
|
...alignStyle,
|
|
258
322
|
}, children: menu
|
|
259
323
|
? menu(dataMemo)
|
|
260
|
-
: dataMemo.map((item, i, arr) => (_jsx(MenuItemWrapper, { item: item, index: i, update: update, className: className, isLeftAligned: isLeftAligned, leftPos: leftPos, menuElement: menuElement, open: activeIndex === i, setOpenIndex: setActiveIndex }, typeof item.name === "string" ? item.name : i))) }));
|
|
324
|
+
: dataMemo.map((item, i, arr) => (_jsx(MenuItemWrapper, { item: item, index: i, update: update, className: className, isLeftAligned: isLeftAligned, leftPos: leftPos, menuElement: menuElement, open: activeIndex === i, setOpenIndex: setActiveIndex, onActionEvent: onActionEvent }, typeof item.name === "string" ? item.name : i))) }));
|
|
261
325
|
}
|
|
262
326
|
export { MenuProgress, MenuElement };
|
|
@@ -28,6 +28,39 @@ export type ContextMenuLayerProps = {
|
|
|
28
28
|
onConsume?: () => void;
|
|
29
29
|
className?: (active?: boolean) => string;
|
|
30
30
|
};
|
|
31
|
+
export type ContextMenuActionCounters = {
|
|
32
|
+
click: number;
|
|
33
|
+
ok: number;
|
|
34
|
+
error: number;
|
|
35
|
+
taskOk: number;
|
|
36
|
+
taskError: number;
|
|
37
|
+
submenuOpen: number;
|
|
38
|
+
submenuOk: number;
|
|
39
|
+
submenuError: number;
|
|
40
|
+
funcOpen: number;
|
|
41
|
+
funcOk: number;
|
|
42
|
+
funcError: number;
|
|
43
|
+
focusOpen: number;
|
|
44
|
+
focusOk: number;
|
|
45
|
+
focusError: number;
|
|
46
|
+
};
|
|
47
|
+
export type ContextMenuStatsSnapshot = {
|
|
48
|
+
openAt: number;
|
|
49
|
+
openAtPoint: number;
|
|
50
|
+
legacyLayer: number;
|
|
51
|
+
close: number;
|
|
52
|
+
replace: number;
|
|
53
|
+
empty: number;
|
|
54
|
+
sources: Record<string, number>;
|
|
55
|
+
layers: Record<string, number>;
|
|
56
|
+
actionTotals: ContextMenuActionCounters;
|
|
57
|
+
actions: Record<string, ContextMenuActionCounters>;
|
|
58
|
+
};
|
|
59
|
+
export type ContextMenuStats = {
|
|
60
|
+
getSnapshot(): ContextMenuStatsSnapshot;
|
|
61
|
+
reset(): void;
|
|
62
|
+
onChange(cb: (snapshot: ContextMenuStatsSnapshot) => void): () => void;
|
|
63
|
+
};
|
|
31
64
|
export declare function createContextMenu(data?: {
|
|
32
65
|
name?: string;
|
|
33
66
|
}): {
|
|
@@ -51,6 +84,7 @@ export declare function createContextMenu(data?: {
|
|
|
51
84
|
layerId?: string;
|
|
52
85
|
}) => boolean;
|
|
53
86
|
close: () => void;
|
|
87
|
+
stats: ContextMenuStats;
|
|
54
88
|
Layer: ({ children, other, statusOn, onUnClick, onConsume, zIndex, className }: ContextMenuLayerProps) => import("react/jsx-runtime").JSX.Element;
|
|
55
89
|
MenuView: typeof Menu;
|
|
56
90
|
};
|
|
@@ -75,6 +109,7 @@ export declare const contextMenu: {
|
|
|
75
109
|
layerId?: string;
|
|
76
110
|
}) => boolean;
|
|
77
111
|
close: () => void;
|
|
112
|
+
stats: ContextMenuStats;
|
|
78
113
|
Layer: ({ children, other, statusOn, onUnClick, onConsume, zIndex, className }: ContextMenuLayerProps) => import("react/jsx-runtime").JSX.Element;
|
|
79
114
|
MenuView: typeof Menu;
|
|
80
115
|
};
|
|
@@ -2,6 +2,33 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import { Menu } from "./menu";
|
|
4
4
|
import { OutsideClickArea } from "../hooks/useOutside";
|
|
5
|
+
function createActionCounters() {
|
|
6
|
+
return {
|
|
7
|
+
click: 0,
|
|
8
|
+
ok: 0,
|
|
9
|
+
error: 0,
|
|
10
|
+
taskOk: 0,
|
|
11
|
+
taskError: 0,
|
|
12
|
+
submenuOpen: 0,
|
|
13
|
+
submenuOk: 0,
|
|
14
|
+
submenuError: 0,
|
|
15
|
+
funcOpen: 0,
|
|
16
|
+
funcOk: 0,
|
|
17
|
+
funcError: 0,
|
|
18
|
+
focusOpen: 0,
|
|
19
|
+
focusOk: 0,
|
|
20
|
+
focusError: 0,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function cloneActionCounters(counters) {
|
|
24
|
+
return { ...counters };
|
|
25
|
+
}
|
|
26
|
+
function cloneActions(actions) {
|
|
27
|
+
const result = {};
|
|
28
|
+
for (const [key, counters] of Object.entries(actions))
|
|
29
|
+
result[key] = cloneActionCounters(counters);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
5
32
|
function normalizeItems(items) {
|
|
6
33
|
return (items ?? []).filter(Boolean);
|
|
7
34
|
}
|
|
@@ -32,6 +59,19 @@ export function createContextMenu(data) {
|
|
|
32
59
|
const map = new Map();
|
|
33
60
|
const state = { open: false, items: [], point: { x: 0, y: 0 }, seq: 0 };
|
|
34
61
|
const listeners = new Set();
|
|
62
|
+
const statsListeners = new Set();
|
|
63
|
+
const statsState = {
|
|
64
|
+
openAt: 0,
|
|
65
|
+
openAtPoint: 0,
|
|
66
|
+
legacyLayer: 0,
|
|
67
|
+
close: 0,
|
|
68
|
+
replace: 0,
|
|
69
|
+
empty: 0,
|
|
70
|
+
sources: {},
|
|
71
|
+
layers: {},
|
|
72
|
+
actionTotals: createActionCounters(),
|
|
73
|
+
actions: {},
|
|
74
|
+
};
|
|
35
75
|
const layers = new Set();
|
|
36
76
|
let layerSeq = 0;
|
|
37
77
|
function emit() {
|
|
@@ -43,6 +83,63 @@ export function createContextMenu(data) {
|
|
|
43
83
|
listeners.add(cb);
|
|
44
84
|
return () => { listeners.delete(cb); };
|
|
45
85
|
}
|
|
86
|
+
function statsSnapshot() {
|
|
87
|
+
return {
|
|
88
|
+
openAt: statsState.openAt,
|
|
89
|
+
openAtPoint: statsState.openAtPoint,
|
|
90
|
+
legacyLayer: statsState.legacyLayer,
|
|
91
|
+
close: statsState.close,
|
|
92
|
+
replace: statsState.replace,
|
|
93
|
+
empty: statsState.empty,
|
|
94
|
+
sources: { ...statsState.sources },
|
|
95
|
+
layers: { ...statsState.layers },
|
|
96
|
+
actionTotals: cloneActionCounters(statsState.actionTotals),
|
|
97
|
+
actions: cloneActions(statsState.actions),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function emitStats() {
|
|
101
|
+
const snapshot = statsSnapshot();
|
|
102
|
+
for (const cb of [...statsListeners])
|
|
103
|
+
cb(snapshot);
|
|
104
|
+
}
|
|
105
|
+
function bumpStat(key) {
|
|
106
|
+
statsState[key] += 1;
|
|
107
|
+
emitStats();
|
|
108
|
+
}
|
|
109
|
+
function bumpMapStat(map, key) {
|
|
110
|
+
if (!key)
|
|
111
|
+
return;
|
|
112
|
+
map[key] = (map[key] ?? 0) + 1;
|
|
113
|
+
}
|
|
114
|
+
function recordMenuAction(event) {
|
|
115
|
+
const stat = event.type;
|
|
116
|
+
statsState.actionTotals[stat] += 1;
|
|
117
|
+
if (event.actionKey) {
|
|
118
|
+
const counters = statsState.actions[event.actionKey] ??= createActionCounters();
|
|
119
|
+
counters[stat] += 1;
|
|
120
|
+
}
|
|
121
|
+
emitStats();
|
|
122
|
+
}
|
|
123
|
+
const stats = {
|
|
124
|
+
getSnapshot: statsSnapshot,
|
|
125
|
+
reset() {
|
|
126
|
+
statsState.openAt = 0;
|
|
127
|
+
statsState.openAtPoint = 0;
|
|
128
|
+
statsState.legacyLayer = 0;
|
|
129
|
+
statsState.close = 0;
|
|
130
|
+
statsState.replace = 0;
|
|
131
|
+
statsState.empty = 0;
|
|
132
|
+
statsState.sources = {};
|
|
133
|
+
statsState.layers = {};
|
|
134
|
+
statsState.actionTotals = createActionCounters();
|
|
135
|
+
statsState.actions = {};
|
|
136
|
+
emitStats();
|
|
137
|
+
},
|
|
138
|
+
onChange(cb) {
|
|
139
|
+
statsListeners.add(cb);
|
|
140
|
+
return () => { statsListeners.delete(cb); };
|
|
141
|
+
},
|
|
142
|
+
};
|
|
46
143
|
function legacyItems() {
|
|
47
144
|
if (map.has("only"))
|
|
48
145
|
return normalizeItems(map.get("only"));
|
|
@@ -56,28 +153,39 @@ export function createContextMenu(data) {
|
|
|
56
153
|
function close() {
|
|
57
154
|
if (!state.open && state.items.length == 0)
|
|
58
155
|
return;
|
|
156
|
+
bumpStat("close");
|
|
59
157
|
state.open = false;
|
|
60
158
|
state.items = [];
|
|
61
159
|
state.layerId = undefined;
|
|
62
160
|
emit();
|
|
63
161
|
}
|
|
64
|
-
function
|
|
162
|
+
function openMenu(anchor, items, opts = {}, kind) {
|
|
65
163
|
preventNative(anchor);
|
|
66
164
|
const nextItems = normalizeItems(items);
|
|
67
165
|
if (nextItems.length == 0) {
|
|
166
|
+
bumpStat("empty");
|
|
68
167
|
close();
|
|
69
168
|
return false;
|
|
70
169
|
}
|
|
170
|
+
if (state.open)
|
|
171
|
+
bumpStat("replace");
|
|
172
|
+
bumpStat(kind);
|
|
71
173
|
state.open = true;
|
|
72
174
|
state.items = nextItems;
|
|
73
175
|
state.point = anchorPoint(anchor);
|
|
74
176
|
state.source = opts.source;
|
|
75
177
|
state.layerId = opts.layerId ?? anchorLayerId(anchor) ?? [...layers][0];
|
|
178
|
+
bumpMapStat(statsState.sources, state.source);
|
|
179
|
+
bumpMapStat(statsState.layers, state.layerId);
|
|
180
|
+
emitStats();
|
|
76
181
|
emit();
|
|
77
182
|
return true;
|
|
78
183
|
}
|
|
184
|
+
function openAt(anchor, items, opts = {}) {
|
|
185
|
+
return openMenu(anchor, items, opts, "openAt");
|
|
186
|
+
}
|
|
79
187
|
function openAtPoint(point, items, opts = {}) {
|
|
80
|
-
return
|
|
188
|
+
return openMenu(point, items, opts, "openAtPoint");
|
|
81
189
|
}
|
|
82
190
|
function getState() {
|
|
83
191
|
return {
|
|
@@ -123,7 +231,7 @@ export function createContextMenu(data) {
|
|
|
123
231
|
return other ? normalizeItems(other()) : legacyItems();
|
|
124
232
|
}
|
|
125
233
|
function openQueued(anchor) {
|
|
126
|
-
const opened =
|
|
234
|
+
const opened = openMenu(anchor, queuedItems(), { source: "layer", layerId }, "legacyLayer");
|
|
127
235
|
if (opened) {
|
|
128
236
|
map.clear();
|
|
129
237
|
onConsume?.();
|
|
@@ -183,7 +291,7 @@ export function createContextMenu(data) {
|
|
|
183
291
|
if (!state.open || hasQueuedItems(other))
|
|
184
292
|
openQueued(event);
|
|
185
293
|
}
|
|
186
|
-
}, children: [children, state.open && enabled && state.layerId == layerId && _jsx(OutsideClickArea, { outsideClick: handleClose, children: _jsx(Menu, { className: className, data: state.items, coordinate: relativePoint(), zIndex: zIndex }) })] });
|
|
294
|
+
}, children: [children, state.open && enabled && state.layerId == layerId && _jsx(OutsideClickArea, { outsideClick: handleClose, children: _jsx(Menu, { className: className, data: state.items, coordinate: relativePoint(), zIndex: zIndex, onActionEvent: recordMenuAction }) })] });
|
|
187
295
|
}
|
|
188
296
|
return {
|
|
189
297
|
bb,
|
|
@@ -194,6 +302,7 @@ export function createContextMenu(data) {
|
|
|
194
302
|
openAt,
|
|
195
303
|
openAtPoint,
|
|
196
304
|
close,
|
|
305
|
+
stats,
|
|
197
306
|
Layer,
|
|
198
307
|
MenuView: Menu,
|
|
199
308
|
};
|
|
@@ -75,7 +75,85 @@ export declare const tokens: {
|
|
|
75
75
|
readonly popRadius: "8px";
|
|
76
76
|
readonly popShadow: "0 8px 28px rgba(0, 0, 0, 0.5)";
|
|
77
77
|
};
|
|
78
|
-
/**
|
|
78
|
+
/** Column-state compact menu (ColumnsMenu/MenuStrip) chrome (--cols-menu-*). */
|
|
79
|
+
readonly colsMenu: {
|
|
80
|
+
readonly gap: "6px";
|
|
81
|
+
readonly btnGap: "4px";
|
|
82
|
+
readonly btnPadding: "3px 9px";
|
|
83
|
+
readonly btnRadius: "6px";
|
|
84
|
+
readonly btnFontSize: "12px";
|
|
85
|
+
readonly btnLineHeight: "16px";
|
|
86
|
+
readonly onBorder: "1px solid #24292f";
|
|
87
|
+
readonly onBg: "#24292f";
|
|
88
|
+
readonly onColor: "#fff";
|
|
89
|
+
readonly offBorder: "1px solid #d0d7de";
|
|
90
|
+
readonly offBg: "#fff";
|
|
91
|
+
readonly offColor: "#8c959f";
|
|
92
|
+
readonly disabledBorder: "1px dashed #d0d7de";
|
|
93
|
+
readonly disabledBg: "#f6f8fa";
|
|
94
|
+
readonly disabledColor: "#c4ccd4";
|
|
95
|
+
readonly fixedShadow: "0 0 0 2px #eaeef2";
|
|
96
|
+
readonly dragShadow: "0 3px 10px rgba(0, 0, 0, 0.35)";
|
|
97
|
+
readonly divider: "#d0d7de";
|
|
98
|
+
readonly abbrFontSize: "10px";
|
|
99
|
+
readonly abbrFontWeight: 700;
|
|
100
|
+
readonly abbrLetterSpacing: "0.5px";
|
|
101
|
+
readonly marksFontSize: "9px";
|
|
102
|
+
readonly marksOpacity: 0.9;
|
|
103
|
+
};
|
|
104
|
+
/** ColumnDots chrome (--cols-dots-*). Defaults preserve restored card-29 look. */
|
|
105
|
+
readonly colsDots: {
|
|
106
|
+
readonly text: "#24292f";
|
|
107
|
+
readonly headGap: "10px";
|
|
108
|
+
readonly headMarginBottom: "6px";
|
|
109
|
+
readonly headFontSize: "12px";
|
|
110
|
+
readonly metaColor: "#57606a";
|
|
111
|
+
readonly sortBorder: "1px solid #6e7781";
|
|
112
|
+
readonly sortRadius: "6px";
|
|
113
|
+
readonly sortPadding: "2px 8px";
|
|
114
|
+
readonly sortFontSize: "12px";
|
|
115
|
+
readonly sortBg: "#fff";
|
|
116
|
+
readonly trackHeight: "56px";
|
|
117
|
+
readonly trackMargin: "0 14px";
|
|
118
|
+
readonly rail: "#d0d7de";
|
|
119
|
+
readonly markWidth: "44px";
|
|
120
|
+
readonly markHeight: "56px";
|
|
121
|
+
readonly markMarginLeft: "-22px";
|
|
122
|
+
readonly sortMarkColor: "#0969da";
|
|
123
|
+
readonly sortMarkFontSize: "11px";
|
|
124
|
+
readonly pin: "#afb8c1";
|
|
125
|
+
readonly labelColor: "#8c959f";
|
|
126
|
+
readonly labelActiveColor: "#24292f";
|
|
127
|
+
readonly labelFontSize: "10px";
|
|
128
|
+
readonly dotSize: "18px";
|
|
129
|
+
readonly dotRadius: "9px";
|
|
130
|
+
readonly dotBg: "#24292f";
|
|
131
|
+
readonly dotShadow: "0 3px 10px rgba(0, 0, 0, 0.35)";
|
|
132
|
+
readonly selectedBg: "#0969da";
|
|
133
|
+
readonly selectedBorder: "#b6d4fe";
|
|
134
|
+
readonly fixedBorder: "#afb8c1";
|
|
135
|
+
};
|
|
136
|
+
/** CardList chrome (--cols-card-*). Defaults preserve restored card-29 look. */
|
|
137
|
+
readonly colsCard: {
|
|
138
|
+
readonly gap: "8px";
|
|
139
|
+
readonly border: "1px solid #d0d7de";
|
|
140
|
+
readonly radius: "8px";
|
|
141
|
+
readonly padding: "8px 10px";
|
|
142
|
+
readonly bg: "#fff";
|
|
143
|
+
readonly headerGap: "8px";
|
|
144
|
+
readonly headerMarginBottom: "6px";
|
|
145
|
+
readonly titleFontSize: "14px";
|
|
146
|
+
readonly accentFontSize: "11px";
|
|
147
|
+
readonly accentPadding: "1px 8px";
|
|
148
|
+
readonly accentRadius: "10px";
|
|
149
|
+
readonly accentBg: "#ddf4ff";
|
|
150
|
+
readonly accentColor: "#0969da";
|
|
151
|
+
readonly fieldGap: "10px";
|
|
152
|
+
readonly fieldFontSize: "12px";
|
|
153
|
+
readonly fieldLineHeight: 1.7;
|
|
154
|
+
readonly labelColor: "#57606a";
|
|
155
|
+
readonly labelMinWidth: "72px";
|
|
156
|
+
};
|
|
79
157
|
readonly logs: {
|
|
80
158
|
readonly notificationText: "#fff";
|
|
81
159
|
readonly notificationAccent: "#5D9FFA";
|
|
@@ -77,7 +77,85 @@ export const tokens = {
|
|
|
77
77
|
popRadius: '8px',
|
|
78
78
|
popShadow: '0 8px 28px rgba(0, 0, 0, 0.5)',
|
|
79
79
|
},
|
|
80
|
-
/**
|
|
80
|
+
/** Column-state compact menu (ColumnsMenu/MenuStrip) chrome (--cols-menu-*). */
|
|
81
|
+
colsMenu: {
|
|
82
|
+
gap: '6px',
|
|
83
|
+
btnGap: '4px',
|
|
84
|
+
btnPadding: '3px 9px',
|
|
85
|
+
btnRadius: '6px',
|
|
86
|
+
btnFontSize: '12px',
|
|
87
|
+
btnLineHeight: '16px',
|
|
88
|
+
onBorder: '1px solid #24292f',
|
|
89
|
+
onBg: '#24292f',
|
|
90
|
+
onColor: '#fff',
|
|
91
|
+
offBorder: '1px solid #d0d7de',
|
|
92
|
+
offBg: '#fff',
|
|
93
|
+
offColor: '#8c959f',
|
|
94
|
+
disabledBorder: '1px dashed #d0d7de',
|
|
95
|
+
disabledBg: '#f6f8fa',
|
|
96
|
+
disabledColor: '#c4ccd4',
|
|
97
|
+
fixedShadow: '0 0 0 2px #eaeef2',
|
|
98
|
+
dragShadow: '0 3px 10px rgba(0, 0, 0, 0.35)',
|
|
99
|
+
divider: '#d0d7de',
|
|
100
|
+
abbrFontSize: '10px',
|
|
101
|
+
abbrFontWeight: 700,
|
|
102
|
+
abbrLetterSpacing: '0.5px',
|
|
103
|
+
marksFontSize: '9px',
|
|
104
|
+
marksOpacity: 0.9,
|
|
105
|
+
},
|
|
106
|
+
/** ColumnDots chrome (--cols-dots-*). Defaults preserve restored card-29 look. */
|
|
107
|
+
colsDots: {
|
|
108
|
+
text: '#24292f',
|
|
109
|
+
headGap: '10px',
|
|
110
|
+
headMarginBottom: '6px',
|
|
111
|
+
headFontSize: '12px',
|
|
112
|
+
metaColor: '#57606a',
|
|
113
|
+
sortBorder: '1px solid #6e7781',
|
|
114
|
+
sortRadius: '6px',
|
|
115
|
+
sortPadding: '2px 8px',
|
|
116
|
+
sortFontSize: '12px',
|
|
117
|
+
sortBg: '#fff',
|
|
118
|
+
trackHeight: '56px',
|
|
119
|
+
trackMargin: '0 14px',
|
|
120
|
+
rail: '#d0d7de',
|
|
121
|
+
markWidth: '44px',
|
|
122
|
+
markHeight: '56px',
|
|
123
|
+
markMarginLeft: '-22px',
|
|
124
|
+
sortMarkColor: '#0969da',
|
|
125
|
+
sortMarkFontSize: '11px',
|
|
126
|
+
pin: '#afb8c1',
|
|
127
|
+
labelColor: '#8c959f',
|
|
128
|
+
labelActiveColor: '#24292f',
|
|
129
|
+
labelFontSize: '10px',
|
|
130
|
+
dotSize: '18px',
|
|
131
|
+
dotRadius: '9px',
|
|
132
|
+
dotBg: '#24292f',
|
|
133
|
+
dotShadow: '0 3px 10px rgba(0, 0, 0, 0.35)',
|
|
134
|
+
selectedBg: '#0969da',
|
|
135
|
+
selectedBorder: '#b6d4fe',
|
|
136
|
+
fixedBorder: '#afb8c1',
|
|
137
|
+
},
|
|
138
|
+
/** CardList chrome (--cols-card-*). Defaults preserve restored card-29 look. */
|
|
139
|
+
colsCard: {
|
|
140
|
+
gap: '8px',
|
|
141
|
+
border: '1px solid #d0d7de',
|
|
142
|
+
radius: '8px',
|
|
143
|
+
padding: '8px 10px',
|
|
144
|
+
bg: '#fff',
|
|
145
|
+
headerGap: '8px',
|
|
146
|
+
headerMarginBottom: '6px',
|
|
147
|
+
titleFontSize: '14px',
|
|
148
|
+
accentFontSize: '11px',
|
|
149
|
+
accentPadding: '1px 8px',
|
|
150
|
+
accentRadius: '10px',
|
|
151
|
+
accentBg: '#ddf4ff',
|
|
152
|
+
accentColor: '#0969da',
|
|
153
|
+
fieldGap: '10px',
|
|
154
|
+
fieldFontSize: '12px',
|
|
155
|
+
fieldLineHeight: 1.7,
|
|
156
|
+
labelColor: '#57606a',
|
|
157
|
+
labelMinWidth: '72px',
|
|
158
|
+
}, /** Logs chrome (--logs-*). Defaults preserve the old logger look; apps re-skin via CSS vars. */
|
|
81
159
|
logs: {
|
|
82
160
|
notificationText: '#fff',
|
|
83
161
|
notificationAccent: '#5D9FFA',
|
|
@@ -27,16 +27,7 @@ export declare const memoryCache: {
|
|
|
27
27
|
getArr: [k: string, v: Map<string, unknown>][];
|
|
28
28
|
};
|
|
29
29
|
export declare const memoryMaps: {
|
|
30
|
-
rnd: ObservableMap<string,
|
|
31
|
-
position: {
|
|
32
|
-
x: number;
|
|
33
|
-
y: number;
|
|
34
|
-
};
|
|
35
|
-
size: {
|
|
36
|
-
height: number | string;
|
|
37
|
-
width: number | string;
|
|
38
|
-
};
|
|
39
|
-
}>;
|
|
30
|
+
rnd: ObservableMap<string, import("../components/Dnd/FloatingWindow").FloatingWindowSavedGeometry>;
|
|
40
31
|
resize: ObservableMap<string, {
|
|
41
32
|
height?: number | string;
|
|
42
33
|
width?: number | string;
|