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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useLayoutEffect, useRef, useState } from 'react';
|
|
3
3
|
import { listen as createListen } from 'wenay-common2';
|
|
4
|
-
import {
|
|
4
|
+
import { createUpdateApi } from '../../../updateBy';
|
|
5
5
|
import { memoryGetOrCreate, memoryMarkDirty } from '../../utils/memoryStore';
|
|
6
6
|
import { OutsideClickArea } from '../../hooks/useOutside';
|
|
7
7
|
import { useReorder } from '../../hooks/useReorder';
|
|
@@ -12,6 +12,7 @@ const densities = { list: [
|
|
|
12
12
|
{ key: 'icon', name: 'Icons', renderItem: itemIconOnly },
|
|
13
13
|
{ key: 'label', name: 'Icons + labels' },
|
|
14
14
|
] };
|
|
15
|
+
const densitiesApi = createUpdateApi(densities);
|
|
15
16
|
/** Icon with a text fallback: no glyph = the first letters of short/title
|
|
16
17
|
* (an "PR"-style pseudo-icon), so icon densities work for icon-less items. */
|
|
17
18
|
export function toolbarItemIcon(item) {
|
|
@@ -30,12 +31,12 @@ export function registerToolbarDensity(d) {
|
|
|
30
31
|
densities.list.push(d);
|
|
31
32
|
else
|
|
32
33
|
densities.list.splice(i, 1, d);
|
|
33
|
-
|
|
34
|
+
densitiesApi.render();
|
|
34
35
|
return function offToolbarDensity() {
|
|
35
36
|
const j = densities.list.indexOf(d);
|
|
36
37
|
if (j != -1) {
|
|
37
38
|
densities.list.splice(j, 1);
|
|
38
|
-
|
|
39
|
+
densitiesApi.render();
|
|
39
40
|
}
|
|
40
41
|
};
|
|
41
42
|
}
|
|
@@ -55,6 +56,49 @@ function itemContent(item, densityKey) {
|
|
|
55
56
|
* order (the gear always sits at the bar edge), but toggleable like an item. */
|
|
56
57
|
const SETTINGS_KEY = '__settings';
|
|
57
58
|
const RESET_KEY = '__reset';
|
|
59
|
+
function useToolbarFlip(layoutKey) {
|
|
60
|
+
const itemRefs = useRef(new Map());
|
|
61
|
+
const prevRects = useRef(new Map());
|
|
62
|
+
const rafs = useRef([]);
|
|
63
|
+
useLayoutEffect(() => {
|
|
64
|
+
const prev = prevRects.current;
|
|
65
|
+
const next = new Map();
|
|
66
|
+
rafs.current.forEach(cancelAnimationFrame);
|
|
67
|
+
rafs.current = [];
|
|
68
|
+
itemRefs.current.forEach((node, key) => {
|
|
69
|
+
const rect = node.getBoundingClientRect();
|
|
70
|
+
next.set(key, { left: rect.left, top: rect.top });
|
|
71
|
+
const old = prev.get(key);
|
|
72
|
+
if (old == null)
|
|
73
|
+
return;
|
|
74
|
+
const dx = old.left - rect.left;
|
|
75
|
+
const dy = old.top - rect.top;
|
|
76
|
+
if (Math.abs(dx) < 0.5 && Math.abs(dy) < 0.5)
|
|
77
|
+
return;
|
|
78
|
+
node.style.transition = 'none';
|
|
79
|
+
node.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
80
|
+
node.getBoundingClientRect();
|
|
81
|
+
const raf = requestAnimationFrame(() => {
|
|
82
|
+
node.style.transition = 'transform 180ms ease';
|
|
83
|
+
node.style.transform = '';
|
|
84
|
+
});
|
|
85
|
+
rafs.current.push(raf);
|
|
86
|
+
});
|
|
87
|
+
prevRects.current = next;
|
|
88
|
+
return () => {
|
|
89
|
+
rafs.current.forEach(cancelAnimationFrame);
|
|
90
|
+
rafs.current = [];
|
|
91
|
+
};
|
|
92
|
+
}, [layoutKey]);
|
|
93
|
+
return function bind(key) {
|
|
94
|
+
return (node) => {
|
|
95
|
+
if (node)
|
|
96
|
+
itemRefs.current.set(key, node);
|
|
97
|
+
else
|
|
98
|
+
itemRefs.current.delete(key);
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
}
|
|
58
102
|
export function createToolbar(opts) {
|
|
59
103
|
const resetDefaultVisible = () => opts.resetItem !== false && opts.resetItem?.defaultVisible === true;
|
|
60
104
|
const defConfig = () => ({
|
|
@@ -63,6 +107,7 @@ export function createToolbar(opts) {
|
|
|
63
107
|
density: opts.def?.density ?? densities.list[0].key,
|
|
64
108
|
});
|
|
65
109
|
const st = memoryGetOrCreate(opts.key, defConfig());
|
|
110
|
+
const stApi = createUpdateApi(st);
|
|
66
111
|
const [emitChange, onChange] = createListen();
|
|
67
112
|
// ext is fixed for the controller's lifetime, so hook call order inside
|
|
68
113
|
// useConfig/Bar/Settings never changes for a given toolbar instance
|
|
@@ -137,7 +182,7 @@ export function createToolbar(opts) {
|
|
|
137
182
|
[RESET_KEY]: metaVisible(next, RESET_KEY, resetDefaultVisible()),
|
|
138
183
|
};
|
|
139
184
|
st.density = next.density;
|
|
140
|
-
|
|
185
|
+
stApi.render();
|
|
141
186
|
memoryMarkDirty(opts.key);
|
|
142
187
|
ext.setConfig({ order: next.order.slice(), visible });
|
|
143
188
|
// the source's own onChange already re-emitted; emit only when it can't
|
|
@@ -153,7 +198,7 @@ export function createToolbar(opts) {
|
|
|
153
198
|
st.order = next.order.slice();
|
|
154
199
|
st.visible = { ...next.visible };
|
|
155
200
|
st.density = next.density;
|
|
156
|
-
|
|
201
|
+
stApi.render();
|
|
157
202
|
memoryMarkDirty(opts.key);
|
|
158
203
|
const orderChanged = !sameOrder(curSourceOrder, nextSourceOrder);
|
|
159
204
|
if (orderChanged)
|
|
@@ -168,7 +213,7 @@ export function createToolbar(opts) {
|
|
|
168
213
|
st.order = next.order.slice();
|
|
169
214
|
st.visible = { ...next.visible };
|
|
170
215
|
st.density = next.density;
|
|
171
|
-
|
|
216
|
+
stApi.render();
|
|
172
217
|
memoryMarkDirty(opts.key);
|
|
173
218
|
emitChange(normalize());
|
|
174
219
|
}
|
|
@@ -176,7 +221,7 @@ export function createToolbar(opts) {
|
|
|
176
221
|
const getConfig = () => normalize();
|
|
177
222
|
/** subscription to everything the toolbar renders from (hook) */
|
|
178
223
|
function useSubscribe() {
|
|
179
|
-
|
|
224
|
+
stApi.use();
|
|
180
225
|
ext?.useConfig(); // ext is per-instance constant - hook order is stable
|
|
181
226
|
}
|
|
182
227
|
function useConfig() {
|
|
@@ -191,7 +236,7 @@ export function createToolbar(opts) {
|
|
|
191
236
|
* someone else's nodes.) */
|
|
192
237
|
function useItems() {
|
|
193
238
|
useSubscribe();
|
|
194
|
-
|
|
239
|
+
densitiesApi.use();
|
|
195
240
|
const cfg = normalize();
|
|
196
241
|
const byKey = new Map(opts.items.map(i => [i.key, i]));
|
|
197
242
|
return cfg.order
|
|
@@ -238,18 +283,18 @@ export function createToolbar(opts) {
|
|
|
238
283
|
* the popover sticks to - 'right' (default, for bars in a top-right corner)
|
|
239
284
|
* or 'left'. */
|
|
240
285
|
function Bar(p = {}) {
|
|
241
|
-
|
|
242
|
-
updateBy(densities);
|
|
286
|
+
const items = useItems();
|
|
243
287
|
const cfg = normalize();
|
|
244
288
|
const [open, setOpen] = useState(false);
|
|
245
|
-
const byKey = new Map(opts.items.map(i => [i.key, i]));
|
|
246
289
|
const resetOn = opts.resetItem !== false && (p.reset ?? p.settings ?? false) && cfg.visible[RESET_KEY] != false;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
290
|
+
const settingsOn = !!p.settings && cfg.visible[SETTINGS_KEY] != false;
|
|
291
|
+
const layoutKey = [
|
|
292
|
+
...items.map(x => `${x.item.key}:${x.density}`),
|
|
293
|
+
resetOn ? `${RESET_KEY}:on` : '',
|
|
294
|
+
settingsOn ? `${SETTINGS_KEY}:on` : '',
|
|
295
|
+
].join('|');
|
|
296
|
+
const bindFlip = useToolbarFlip(layoutKey);
|
|
297
|
+
return _jsxs("div", { className: p.className ?? 'wenayTb', children: [items.map(x => _jsx("div", { ref: bindFlip(x.item.key), className: 'wenayTbItem', title: x.density == 'icon' ? x.item.title : undefined, onClick: x.item.onClick, children: x.content }, x.item.key)), resetOn && _jsx("div", { ref: bindFlip(RESET_KEY), className: 'wenayTbItem', title: resetTitle(), onClick: () => reset(), children: resetIcon() }), settingsOn && _jsxs(OutsideClickArea, { className: 'wenayTbGear', status: open, outsideClick: () => setOpen(false), children: [_jsx("div", { ref: bindFlip(SETTINGS_KEY), className: 'wenayTbItem', title: settingsTitle(), onClick: () => setOpen(v => !v), children: settingsIcon() }), open && _jsx("div", { className: p.popAlign == 'left' ? 'wenayTbPop wenayTbPopLeft' : 'wenayTbPop', children: _jsx(Settings, {}) })] })] });
|
|
253
298
|
}
|
|
254
299
|
/** The pure editor over config: density segments + one row per item
|
|
255
300
|
* (visibility checkbox, icon preview, title, drag handle). Reorder rides the
|
|
@@ -260,7 +305,7 @@ export function createToolbar(opts) {
|
|
|
260
305
|
* Plus arrow keys on the focused handle; fixed rows have neither. */
|
|
261
306
|
function Settings(p = {}) {
|
|
262
307
|
useSubscribe();
|
|
263
|
-
|
|
308
|
+
densitiesApi.use();
|
|
264
309
|
const cfg = normalize();
|
|
265
310
|
const base = p.className ?? 'wenaySegBtn';
|
|
266
311
|
const activeCls = p.activeClassName ?? 'wenaySegBtnActive';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { createUpdateApi } from "../../../updateBy";
|
|
3
3
|
import { memoryGetOrCreate, memoryMarkDirty } from "../../utils/memoryStore";
|
|
4
4
|
/** One UI block shown in exactly one of several mount points; the point is a persisted setting.
|
|
5
5
|
* Persistence rides the existing memoryProps -> memoryCache mechanics: memoryProps is observable,
|
|
@@ -9,6 +9,7 @@ import { memoryGetOrCreate, memoryMarkDirty } from "../../utils/memoryStore";
|
|
|
9
9
|
* the persisted place with its own and renders children only on a match. */
|
|
10
10
|
export function createUiSlot(opts) {
|
|
11
11
|
const st = memoryGetOrCreate(opts.key, { place: opts.def });
|
|
12
|
+
const stApi = createUpdateApi(st);
|
|
12
13
|
// a stored place may no longer exist after an app update - fall back to def
|
|
13
14
|
const isPlace = (p) => typeof p == "string" && p in opts.places;
|
|
14
15
|
const getPlace = () => isPlace(st.place) ? st.place : opts.def;
|
|
@@ -16,16 +17,16 @@ export function createUiSlot(opts) {
|
|
|
16
17
|
if (st.place == p)
|
|
17
18
|
return;
|
|
18
19
|
st.place = p;
|
|
19
|
-
|
|
20
|
+
stApi.render();
|
|
20
21
|
memoryMarkDirty(opts.key);
|
|
21
22
|
};
|
|
22
23
|
function Slot(p) {
|
|
23
|
-
|
|
24
|
+
stApi.use();
|
|
24
25
|
return getPlace() == p.place ? _jsx(_Fragment, { children: p.children }) : null;
|
|
25
26
|
}
|
|
26
27
|
/** Segmented row over opts.places; apps pass their own .chip / .chipActive classes */
|
|
27
28
|
function PlacementSetting(p = {}) {
|
|
28
|
-
|
|
29
|
+
stApi.use();
|
|
29
30
|
const cur = getPlace();
|
|
30
31
|
const base = p.className ?? "wenaySegBtn";
|
|
31
32
|
const activeCls = p.activeClassName ?? "wenaySegBtnActive";
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import type { ColumnStateController } from './columnState';
|
|
3
3
|
export declare function ColumnDots(p: {
|
|
4
4
|
state: ColumnStateController;
|
|
5
|
-
/** max simultaneous dots (default
|
|
5
|
+
/** max simultaneous dots (default 8) */
|
|
6
6
|
max?: number;
|
|
7
7
|
className?: string;
|
|
8
8
|
style?: React.CSSProperties;
|
|
@@ -25,7 +25,7 @@ export function ColumnDots(p) {
|
|
|
25
25
|
const cfg = p.state.api.useConfig();
|
|
26
26
|
const cols = p.state.columns;
|
|
27
27
|
const byKey = new Map(cols.map(c => [c.key, c]));
|
|
28
|
-
const max = p.max ??
|
|
28
|
+
const max = p.max ?? 8;
|
|
29
29
|
const order = cfg.order;
|
|
30
30
|
const n = order.length;
|
|
31
31
|
const visibleKeys = order.filter(k => cfg.visible[k] != false);
|
|
@@ -22,22 +22,17 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
22
22
|
// comes back to life when the column returns. No ag-grid, no storage here.
|
|
23
23
|
import { useRef } from 'react';
|
|
24
24
|
import { useReorder } from '../../hooks/useReorder';
|
|
25
|
+
function colsMenuClass(parts) {
|
|
26
|
+
return parts.filter(Boolean).join(' ');
|
|
27
|
+
}
|
|
25
28
|
function MenuButton(p) {
|
|
26
29
|
const it = p.item;
|
|
27
30
|
const disabled = it.state == 'disabled';
|
|
28
31
|
const on = it.state == 'on';
|
|
32
|
+
const stateClass = disabled ? 'wenayColsMenuBtn_disabled' : on ? 'wenayColsMenuBtn_on' : 'wenayColsMenuBtn_off';
|
|
29
33
|
const abbr = p.compact && it.icon == null
|
|
30
|
-
? _jsx("span", {
|
|
31
|
-
return _jsxs("div", { title: it.title, onClick: disabled ? undefined : e => p.onItem?.(it.key, e), onMouseDown: p.drag?.onMouseDown, onTouchStart: p.drag?.onTouchStart, style: {
|
|
32
|
-
position: 'relative', display: 'flex', alignItems: 'center', gap: 4,
|
|
33
|
-
padding: '3px 9px', borderRadius: 6, fontSize: 12, lineHeight: '16px',
|
|
34
|
-
whiteSpace: 'nowrap', cursor: disabled ? 'default' : 'pointer',
|
|
35
|
-
...(disabled ? { border: '1px dashed #d0d7de', background: '#f6f8fa', color: '#c4ccd4' }
|
|
36
|
-
: on ? { border: '1px solid #24292f', background: '#24292f', color: '#fff' }
|
|
37
|
-
: { border: '1px solid #d0d7de', background: '#fff', color: '#8c959f', textDecoration: 'line-through' }),
|
|
38
|
-
...(it.fixed ? { boxShadow: '0 0 0 2px #eaeef2' } : null),
|
|
39
|
-
...p.style,
|
|
40
|
-
}, children: [it.icon != null && _jsx("span", { style: { display: 'inline-flex', alignItems: 'center' }, children: it.icon }), abbr, !p.compact && _jsx("span", { children: it.short ?? it.title }), it.marks != null && _jsx("span", { style: { fontSize: 9, opacity: 0.9 }, children: it.marks })] });
|
|
34
|
+
? _jsx("span", { className: 'wenayColsMenuAbbr', children: (it.short ?? it.title).slice(0, 3) }) : null;
|
|
35
|
+
return _jsxs("div", { title: it.title, onClick: disabled ? undefined : e => p.onItem?.(it.key, e), onMouseDown: p.drag?.onMouseDown, onTouchStart: p.drag?.onTouchStart, className: colsMenuClass(['wenayColsMenuBtn', stateClass, it.fixed && 'wenayColsMenuBtn_fixed', p.className]), style: p.style, children: [it.icon != null && _jsx("span", { className: 'wenayColsMenuIcon', children: it.icon }), abbr, !p.compact && _jsx("span", { className: 'wenayColsMenuLabel', children: it.short ?? it.title }), it.marks != null && _jsx("span", { className: 'wenayColsMenuMarks', children: it.marks })] });
|
|
41
36
|
}
|
|
42
37
|
/** The presentation layer: renders the buttons in the given order, reports
|
|
43
38
|
* clicks (onItem) and drag-reorders (onMove) - never interprets either.
|
|
@@ -61,7 +56,7 @@ export function MenuStrip(p) {
|
|
|
61
56
|
return;
|
|
62
57
|
p.onItem?.(key, e);
|
|
63
58
|
}
|
|
64
|
-
return _jsxs("div", { className: p.className, style:
|
|
59
|
+
return _jsxs("div", { className: colsMenuClass(['wenayColsMenu', p.className]), style: p.style, children: [_jsx("div", { ref: reorder.listRef, className: 'wenayColsMenuList', children: p.items.map(it => {
|
|
65
60
|
const r = reorder.item(it.key);
|
|
66
61
|
const drag = {
|
|
67
62
|
onMouseDown: (e) => {
|
|
@@ -70,12 +65,9 @@ export function MenuStrip(p) {
|
|
|
70
65
|
},
|
|
71
66
|
onTouchStart: r.props.onTouchStart,
|
|
72
67
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
: r.active ? { transition: 'transform 0.15s ease' } : null),
|
|
77
|
-
} }, it.key);
|
|
78
|
-
}) }), !!p.tail?.length && _jsxs(_Fragment, { children: [_jsx("div", { style: { width: 1, alignSelf: 'stretch', margin: '1px 2px', background: '#d0d7de' } }), p.tail.map(it => _jsx(MenuButton, { item: it, onItem: p.onItem, compact: p.compact }, it.key))] })] });
|
|
68
|
+
const dragClass = r.dragging ? 'wenayColsMenuBtn_dragging' : r.active ? 'wenayColsMenuBtn_shift' : undefined;
|
|
69
|
+
return _jsx(MenuButton, { item: it, onItem: onItem, drag: drag, compact: p.compact, className: dragClass, style: r.style }, it.key);
|
|
70
|
+
}) }), !!p.tail?.length && _jsxs(_Fragment, { children: [_jsx("div", { className: 'wenayColsMenuDivider' }), p.tail.map(it => _jsx(MenuButton, { item: it, onItem: p.onItem, compact: p.compact }, it.key))] })] });
|
|
79
71
|
}
|
|
80
72
|
/** The binding layer: MenuStrip fed by a ColumnStateController. Buttons follow
|
|
81
73
|
* config.order (the grid mirror is free: both sides subscribe to the same
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { listen as createListen } from 'wenay-common2';
|
|
2
|
-
import {
|
|
2
|
+
import { createUpdateApi } from '../../../updateBy';
|
|
3
3
|
import { memoryGetOrCreate, memoryMarkDirty } from '../../utils/memoryStore';
|
|
4
4
|
const SCHEMA_V = 1;
|
|
5
5
|
/** Grid events that mean "the user changed the column layout / sort / filter". */
|
|
@@ -17,6 +17,7 @@ export function createColumnState(opts) {
|
|
|
17
17
|
groups: opts.def?.groups ? { ...opts.def.groups } : Object.fromEntries(groupKeys.map(g => [g, groupMembers(g)])),
|
|
18
18
|
});
|
|
19
19
|
const st = memoryGetOrCreate(opts.key, defConfig());
|
|
20
|
+
const stApi = createUpdateApi(st);
|
|
20
21
|
const [emitChange, onChange] = createListen();
|
|
21
22
|
/** Runtime-only, never persisted: actual = which keys the attached grid has;
|
|
22
23
|
* gate = optional app-level availability over a stable grid schema (standards,
|
|
@@ -25,6 +26,7 @@ export function createColumnState(opts) {
|
|
|
25
26
|
present: null,
|
|
26
27
|
presentGate: null,
|
|
27
28
|
};
|
|
29
|
+
const rtApi = createUpdateApi(rt);
|
|
28
30
|
const keyMap = (keys) => keys ? Object.fromEntries(keys.map(k => [k, true])) : null;
|
|
29
31
|
const sameMap = (a, b) => JSON.stringify(a) == JSON.stringify(b);
|
|
30
32
|
function combinedPresent() {
|
|
@@ -42,14 +44,14 @@ export function createColumnState(opts) {
|
|
|
42
44
|
if (sameMap(next, rt.present))
|
|
43
45
|
return;
|
|
44
46
|
rt.present = next;
|
|
45
|
-
|
|
47
|
+
rtApi.render();
|
|
46
48
|
}
|
|
47
49
|
function setPresentGate(keys) {
|
|
48
50
|
const next = keyMap(keys);
|
|
49
51
|
if (sameMap(next, rt.presentGate))
|
|
50
52
|
return;
|
|
51
53
|
rt.presentGate = next;
|
|
52
|
-
|
|
54
|
+
rtApi.render();
|
|
53
55
|
applyToGrid();
|
|
54
56
|
}
|
|
55
57
|
const getPresent = combinedPresent;
|
|
@@ -60,7 +62,7 @@ export function createColumnState(opts) {
|
|
|
60
62
|
};
|
|
61
63
|
const passesPresentGate = (key) => !rt.presentGate || rt.presentGate[key] == true;
|
|
62
64
|
function usePresent() {
|
|
63
|
-
|
|
65
|
+
rtApi.use();
|
|
64
66
|
return combinedPresent();
|
|
65
67
|
}
|
|
66
68
|
/** The persisted state may be stale or partial (older app version, columns
|
|
@@ -116,7 +118,7 @@ export function createColumnState(opts) {
|
|
|
116
118
|
st.sort = next.sort ? { ...next.sort } : null;
|
|
117
119
|
st.filter = { ...next.filter };
|
|
118
120
|
st.groups = Object.fromEntries(Object.entries(next.groups).map(([g, keys]) => [g, keys.slice()]));
|
|
119
|
-
|
|
121
|
+
stApi.render();
|
|
120
122
|
memoryMarkDirty(opts.key);
|
|
121
123
|
if (!fromGrid)
|
|
122
124
|
applyToGrid();
|
|
@@ -126,7 +128,7 @@ export function createColumnState(opts) {
|
|
|
126
128
|
const setConfig = (next) => commit(next, false);
|
|
127
129
|
const reset = () => commit(defConfig(), false);
|
|
128
130
|
function useConfig() {
|
|
129
|
-
|
|
131
|
+
stApi.use();
|
|
130
132
|
return normalize();
|
|
131
133
|
}
|
|
132
134
|
function show(key, on) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useEffect, useRef } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { createUpdateApi } from "../../updateBy";
|
|
3
3
|
import { listen as createListen } from "wenay-common2";
|
|
4
4
|
export const keyboardState = {
|
|
5
5
|
key: ""
|
|
6
6
|
};
|
|
7
|
+
const keyboardStateApi = createUpdateApi(keyboardState);
|
|
7
8
|
const [emitKeyDown, keyboardListen] = createListen();
|
|
8
9
|
export const keyboard = {
|
|
9
10
|
get key() { return keyboardState.key; },
|
|
@@ -11,7 +12,7 @@ export const keyboard = {
|
|
|
11
12
|
get() { return keyboardState.key; },
|
|
12
13
|
clear() {
|
|
13
14
|
keyboardState.key = "";
|
|
14
|
-
|
|
15
|
+
keyboardStateApi.render();
|
|
15
16
|
emitKeyDown("", undefined);
|
|
16
17
|
},
|
|
17
18
|
reset() {
|
|
@@ -38,7 +39,7 @@ export function useKeyboard(options = {}) {
|
|
|
38
39
|
if (!(event instanceof KeyboardEvent))
|
|
39
40
|
return;
|
|
40
41
|
keyboardState.key = event.key;
|
|
41
|
-
|
|
42
|
+
keyboardStateApi.render();
|
|
42
43
|
emitKeyDown(event.key, event);
|
|
43
44
|
onKeyDownRef.current?.(event.key, event);
|
|
44
45
|
};
|
|
@@ -1,92 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
txt: string;
|
|
7
|
-
};
|
|
8
|
-
declare const getSettingLogs: () => {
|
|
9
|
-
minVarLogs: {
|
|
10
|
-
name: string;
|
|
11
|
-
range: {
|
|
12
|
-
min: number;
|
|
13
|
-
max: number;
|
|
14
|
-
step: number;
|
|
15
|
-
};
|
|
16
|
-
value: number;
|
|
17
|
-
};
|
|
18
|
-
minVarMessage: {
|
|
19
|
-
name: string;
|
|
20
|
-
range: {
|
|
21
|
-
min: number;
|
|
22
|
-
max: number;
|
|
23
|
-
step: number;
|
|
24
|
-
};
|
|
25
|
-
value: number;
|
|
26
|
-
};
|
|
27
|
-
timeShow: {
|
|
28
|
-
name: string;
|
|
29
|
-
range: {
|
|
30
|
-
min: number;
|
|
31
|
-
max: number;
|
|
32
|
-
step: number;
|
|
33
|
-
};
|
|
34
|
-
value: number;
|
|
35
|
-
};
|
|
36
|
-
show: {
|
|
37
|
-
name: string;
|
|
38
|
-
value: boolean;
|
|
39
|
-
};
|
|
40
|
-
};
|
|
41
|
-
export declare function getLogsApi<T extends object = {}>(setting: {
|
|
42
|
-
limit?: number;
|
|
43
|
-
limitPer: number;
|
|
44
|
-
varMin?: number;
|
|
45
|
-
}): {
|
|
46
|
-
addLogs(a: LogInput<T>): void;
|
|
1
|
+
import { getSettingLogs, type LogEntry, type LogsApiOptions } from "./logsController";
|
|
2
|
+
export { createLogsController, createLogsControllerState, getSettingLogs, } from "./logsController";
|
|
3
|
+
export type { CreateLogsControllerOptions, LogsApiOptions, LogsController, LogsControllerState, LogsFullState, LogsMiniState, } from "./logsController";
|
|
4
|
+
export declare function getLogsApi<T extends object = {}>(setting: LogsApiOptions): {
|
|
5
|
+
addLogs: (input: import("./logsController").LogInput<T>) => LogEntry<T>;
|
|
47
6
|
params: {
|
|
48
|
-
def:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
range: {
|
|
52
|
-
min: number;
|
|
53
|
-
max: number;
|
|
54
|
-
step: number;
|
|
55
|
-
};
|
|
56
|
-
value: number;
|
|
57
|
-
};
|
|
58
|
-
minVarMessage: {
|
|
59
|
-
name: string;
|
|
60
|
-
range: {
|
|
61
|
-
min: number;
|
|
62
|
-
max: number;
|
|
63
|
-
step: number;
|
|
64
|
-
};
|
|
65
|
-
value: number;
|
|
66
|
-
};
|
|
67
|
-
timeShow: {
|
|
68
|
-
name: string;
|
|
69
|
-
range: {
|
|
70
|
-
min: number;
|
|
71
|
-
max: number;
|
|
72
|
-
step: number;
|
|
73
|
-
};
|
|
74
|
-
value: number;
|
|
75
|
-
};
|
|
76
|
-
show: {
|
|
77
|
-
name: string;
|
|
78
|
-
value: boolean;
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
get(): {
|
|
82
|
-
minVarLogs: number;
|
|
83
|
-
minVarMessage: number;
|
|
84
|
-
timeShow: number;
|
|
85
|
-
show: boolean;
|
|
86
|
-
} & {
|
|
87
|
-
readonly [key: number]: void;
|
|
88
|
-
};
|
|
89
|
-
set(a: Params.SimpleParams<ReturnType<typeof getSettingLogs>>): void;
|
|
7
|
+
def: typeof getSettingLogs;
|
|
8
|
+
get(): import("./logsController").LogsSettings;
|
|
9
|
+
set(settings: import("./logsController").LogsSettings): void;
|
|
90
10
|
};
|
|
91
11
|
React: {
|
|
92
12
|
Setting: typeof InputSettingLogs;
|
|
@@ -95,55 +15,16 @@ export declare function getLogsApi<T extends object = {}>(setting: {
|
|
|
95
15
|
};
|
|
96
16
|
};
|
|
97
17
|
export declare const logsApi: {
|
|
98
|
-
addLogs(
|
|
18
|
+
addLogs: (input: {
|
|
99
19
|
id: string;
|
|
100
20
|
var?: number;
|
|
101
21
|
time: Date;
|
|
102
22
|
txt: string;
|
|
103
|
-
})
|
|
23
|
+
}) => LogEntry<{}>;
|
|
104
24
|
params: {
|
|
105
|
-
def:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
range: {
|
|
109
|
-
min: number;
|
|
110
|
-
max: number;
|
|
111
|
-
step: number;
|
|
112
|
-
};
|
|
113
|
-
value: number;
|
|
114
|
-
};
|
|
115
|
-
minVarMessage: {
|
|
116
|
-
name: string;
|
|
117
|
-
range: {
|
|
118
|
-
min: number;
|
|
119
|
-
max: number;
|
|
120
|
-
step: number;
|
|
121
|
-
};
|
|
122
|
-
value: number;
|
|
123
|
-
};
|
|
124
|
-
timeShow: {
|
|
125
|
-
name: string;
|
|
126
|
-
range: {
|
|
127
|
-
min: number;
|
|
128
|
-
max: number;
|
|
129
|
-
step: number;
|
|
130
|
-
};
|
|
131
|
-
value: number;
|
|
132
|
-
};
|
|
133
|
-
show: {
|
|
134
|
-
name: string;
|
|
135
|
-
value: boolean;
|
|
136
|
-
};
|
|
137
|
-
};
|
|
138
|
-
get(): {
|
|
139
|
-
minVarLogs: number;
|
|
140
|
-
minVarMessage: number;
|
|
141
|
-
timeShow: number;
|
|
142
|
-
show: boolean;
|
|
143
|
-
} & {
|
|
144
|
-
readonly [key: number]: void;
|
|
145
|
-
};
|
|
146
|
-
set(a: Params.SimpleParams<ReturnType<typeof getSettingLogs>>): void;
|
|
25
|
+
def: typeof getSettingLogs;
|
|
26
|
+
get(): import("./logsController").LogsSettings;
|
|
27
|
+
set(settings: import("./logsController").LogsSettings): void;
|
|
147
28
|
};
|
|
148
29
|
React: {
|
|
149
30
|
Setting: typeof InputSettingLogs;
|
|
@@ -163,4 +44,3 @@ export declare function MessageEventLogs({ zIndex }: {
|
|
|
163
44
|
export declare function LogsPage({ update }: {
|
|
164
45
|
update?: number;
|
|
165
46
|
}): import("react/jsx-runtime").JSX.Element;
|
|
166
|
-
export {};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { AgGridReact } from "ag-grid-react";
|
|
3
2
|
import { useCallback, useEffect, useRef } from "react";
|
|
4
3
|
import { copyToClipboard, Params, timeLocalToStr_hhmmss } from "wenay-common2";
|
|
5
4
|
import { renderBy, updateBy } from "../../updateBy";
|
|
@@ -7,6 +6,9 @@ import { contextMenu } from "../menu/menuMouse";
|
|
|
7
6
|
import { memoryGetOrCreate } from "../utils/memoryStore";
|
|
8
7
|
import { ParamsEditor } from "../components/ParamsEditor";
|
|
9
8
|
import { logDividerGradient, logSeverityBackground, logStyleTokens } from "./logStyles";
|
|
9
|
+
import { AgGridTable, colDefCentered } from "../grid/agGrid4";
|
|
10
|
+
import { createLogsController, createLogsControllerState, getSettingLogs, } from "./logsController";
|
|
11
|
+
export { createLogsController, createLogsControllerState, getSettingLogs, } from "./logsController";
|
|
10
12
|
const cashLogs = new Map();
|
|
11
13
|
const datumConst = {
|
|
12
14
|
map: cashLogs,
|
|
@@ -14,39 +16,25 @@ const datumConst = {
|
|
|
14
16
|
const datumMiniConst = {
|
|
15
17
|
last: []
|
|
16
18
|
};
|
|
17
|
-
const getSettingLogs = () => ({
|
|
18
|
-
minVarLogs: { name: "min. importance for notifications", range: { min: 0, max: 25, step: 1 }, value: 0 },
|
|
19
|
-
minVarMessage: { name: "min. importance for log table", range: { min: 0, max: 25, step: 1 }, value: 0 },
|
|
20
|
-
timeShow: { name: "screen display time", range: { min: 1, max: 20, step: 1 }, value: 2 },
|
|
21
|
-
show: { name: "show", value: true }
|
|
22
|
-
});
|
|
23
19
|
const settingLogs = { params: Params.GetSimpleParams(getSettingLogs()) };
|
|
20
|
+
const logGridDefaultColDef = { ...colDefCentered, wrapText: true };
|
|
24
21
|
// varMin - minimum importance
|
|
25
22
|
export function getLogsApi(setting) {
|
|
26
23
|
const datum = memoryGetOrCreate("settingLogs", settingLogs);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
const controller = createLogsController({
|
|
25
|
+
options: setting,
|
|
26
|
+
state: createLogsControllerState({
|
|
27
|
+
full: datumConst,
|
|
28
|
+
mini: datumMiniConst,
|
|
29
|
+
settings: datum,
|
|
30
|
+
}),
|
|
31
|
+
onFullChange: () => renderBy(datumConst),
|
|
32
|
+
onMiniChange: () => renderBy(datumMiniConst),
|
|
33
|
+
onSettingsChange: () => renderBy(datum),
|
|
34
|
+
});
|
|
33
35
|
return {
|
|
34
|
-
addLogs
|
|
35
|
-
|
|
36
|
-
addToArr(datumMiniConst.last, item, setting.limit ?? 50);
|
|
37
|
-
addToArr(datumConst.map.get(a.id) ?? datumConst.map.set(a.id, []).get(a.id), item, setting.limitPer);
|
|
38
|
-
renderBy(datumConst);
|
|
39
|
-
renderBy(datumMiniConst);
|
|
40
|
-
},
|
|
41
|
-
params: {
|
|
42
|
-
def: getSettingLogs,
|
|
43
|
-
get() { return datum.params; },
|
|
44
|
-
set(a) {
|
|
45
|
-
datum.params = a;
|
|
46
|
-
renderBy(datumMiniConst);
|
|
47
|
-
renderBy(datumConst);
|
|
48
|
-
},
|
|
49
|
-
},
|
|
36
|
+
addLogs: controller.addLogs,
|
|
37
|
+
params: controller.params,
|
|
50
38
|
React: {
|
|
51
39
|
Setting: InputSettingLogs,
|
|
52
40
|
Message: MessageEventLogs,
|
|
@@ -136,7 +124,7 @@ export function PageLogs({ update }) {
|
|
|
136
124
|
width: 150,
|
|
137
125
|
},
|
|
138
126
|
];
|
|
139
|
-
return _jsx("div", { className: "maxSize", children: _jsx(
|
|
127
|
+
return _jsx("div", { className: "maxSize", children: _jsx(AgGridTable
|
|
140
128
|
// className = "ag-theme-alpine-dark ag-theme-alpine2" // ag-theme-alpine-dark3
|
|
141
129
|
, {
|
|
142
130
|
// className = "ag-theme-alpine-dark ag-theme-alpine2" // ag-theme-alpine-dark3
|
|
@@ -153,18 +141,11 @@ export function PageLogs({ update }) {
|
|
|
153
141
|
});
|
|
154
142
|
}
|
|
155
143
|
}, onSortChanged: (e) => {
|
|
156
|
-
}, defaultColDef: {
|
|
157
|
-
headerClass: () => ("gridTable-header"),
|
|
158
|
-
resizable: true,
|
|
159
|
-
cellStyle: { textAlign: "center" },
|
|
160
|
-
sortable: true,
|
|
161
|
-
filter: true,
|
|
162
|
-
wrapText: true,
|
|
163
|
-
}, headerHeight: 30, rowHeight: 26, autoSizePadding: 1, rowData: rowData, columnDefs: columns, onCellMouseDown: (e) => {
|
|
144
|
+
}, defaultColDef: logGridDefaultColDef, headerHeight: 30, rowHeight: 26, autoSizePadding: 1, rowData: rowData, columnDefs: columns, onCellMouseDown: (e) => {
|
|
164
145
|
if (e.event instanceof MouseEvent && e.event.button == 2) {
|
|
165
146
|
contextMenu.openAt(e.event, [
|
|
166
147
|
{
|
|
167
|
-
name: "copy", onClick: () => { copyToClipboard(e.value); }
|
|
148
|
+
name: "copy", actionKey: "logs.copyCell", onClick: () => { copyToClipboard(e.value); }
|
|
168
149
|
}
|
|
169
150
|
]);
|
|
170
151
|
}
|