wenay-react2 1.0.34 → 1.0.36
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/README.md +12 -56
- package/lib/common/api.d.ts +28 -28
- package/lib/common/api.js +31 -31
- package/lib/common/src/components/Buttons/MiniButton.d.ts +1 -3
- package/lib/common/src/components/Buttons/MiniButton.js +1 -3
- package/lib/common/src/components/Dnd/{RNDFunc.d.ts → DragArea.d.ts} +1 -1
- package/lib/common/src/components/Dnd/{RNDFunc.js → DragArea.js} +1 -1
- package/lib/common/src/components/Dnd/{RNDFunc3.d.ts → FloatingWindow.d.ts} +7 -7
- package/lib/common/src/components/Dnd/{RNDFunc3.js → FloatingWindow.js} +10 -10
- package/lib/common/src/components/Dnd/OutlineDragDemo.d.ts +1 -0
- package/lib/common/src/components/Dnd/{DraggableOutlineDiv.js → OutlineDragDemo.js} +1 -2
- package/lib/common/src/components/Dnd/Resizable.js +1 -1
- package/lib/common/src/components/Dnd/index.d.ts +3 -3
- package/lib/common/src/components/Dnd/index.js +3 -3
- package/lib/common/src/components/Input.d.ts +5 -5
- package/lib/common/src/components/Input.js +10 -10
- package/lib/common/src/components/Menu/RightMenu.d.ts +25 -5
- package/lib/common/src/components/Menu/RightMenu.js +27 -19
- package/lib/common/src/components/Menu/RightMenuStore.d.ts +2 -2
- package/lib/common/src/components/Menu/RightMenuStore.js +1 -1
- package/lib/common/src/components/Modal/LeftModal.js +4 -4
- package/lib/common/src/components/Modal/Modal.d.ts +11 -17
- package/lib/common/src/components/Modal/Modal.js +15 -21
- package/lib/common/src/components/Modal/ModalContextProvider.d.ts +0 -6
- package/lib/common/src/components/Modal/ModalContextProvider.js +2 -9
- package/lib/common/src/components/Other.d.ts +2 -2
- package/lib/common/src/components/Other.js +5 -5
- package/lib/common/src/components/Parameters.d.ts +3 -3
- package/lib/common/src/components/Parameters.js +3 -3
- package/lib/common/src/components/{ParametersEngine.d.ts → ParamsEditor.d.ts} +1 -1
- package/lib/common/src/components/{ParametersEngine.js → ParamsEditor.js} +10 -10
- package/lib/common/src/components/Settings/SettingsDialog.d.ts +4 -4
- package/lib/common/src/components/Toolbar/Toolbar.d.ts +50 -37
- package/lib/common/src/components/Toolbar/Toolbar.js +60 -23
- package/lib/common/src/components/UiSlot/UiSlot.d.ts +3 -3
- package/lib/common/src/components/UiSlot/UiSlot.js +6 -6
- package/lib/common/src/grid/agGrid4/agGrid4.d.ts +4 -4
- package/lib/common/src/grid/agGrid4/agGrid4.js +6 -6
- package/lib/common/src/grid/agGrid4/index.d.ts +3 -3
- package/lib/common/src/grid/agGrid4/index.js +1 -1
- package/lib/common/src/grid/agGrid4/theme.d.ts +3 -3
- package/lib/common/src/grid/columnState/CardList.d.ts +11 -0
- package/lib/common/src/grid/columnState/CardList.js +28 -0
- package/lib/common/src/grid/columnState/ColumnDots.d.ts +9 -0
- package/lib/common/src/grid/columnState/ColumnDots.js +121 -0
- package/lib/common/src/grid/columnState/ColumnsMenu.d.ts +65 -0
- package/lib/common/src/grid/columnState/ColumnsMenu.js +123 -0
- package/lib/common/src/grid/columnState/columnState.d.ts +113 -0
- package/lib/common/src/grid/columnState/columnState.js +284 -0
- package/lib/common/src/grid/columnState/index.d.ts +4 -0
- package/lib/common/src/grid/columnState/index.js +4 -0
- package/lib/common/src/hooks/index.d.ts +1 -1
- package/lib/common/src/hooks/index.js +1 -1
- package/lib/common/src/hooks/useKeyboard.d.ts +18 -0
- package/lib/common/src/hooks/{useAddDownAnyKey.js → useKeyboard.js} +16 -24
- package/lib/common/src/hooks/useObserveStore.d.ts +26 -11
- package/lib/common/src/hooks/useObserveStore.js +21 -2
- package/lib/common/src/hooks/useOutside.d.ts +12 -19
- package/lib/common/src/hooks/useOutside.js +9 -16
- package/lib/common/src/hooks/useReorder.d.ts +4 -4
- package/lib/common/src/hooks/useReorderBoard.d.ts +15 -15
- package/lib/common/src/hooks/useReplay.d.ts +33 -6
- package/lib/common/src/hooks/useReplay.js +32 -5
- package/lib/common/src/logs/logs.d.ts +3 -3
- package/lib/common/src/logs/logs.js +11 -13
- package/lib/common/src/logs/{logs3.d.ts → logsContext.d.ts} +4 -4
- package/lib/common/src/logs/{logs3.js → logsContext.js} +4 -4
- package/lib/common/src/menu/menu.d.ts +16 -16
- package/lib/common/src/menu/menu.js +12 -11
- package/lib/common/src/menu/menuMouse.d.ts +71 -13
- package/lib/common/src/menu/menuMouse.js +189 -21
- package/lib/common/src/menu/menuR.d.ts +3 -3
- package/lib/common/src/menu/menuR.js +5 -5
- package/lib/common/src/styles/styleGrid.d.ts +1 -1
- package/lib/common/src/styles/tokens.d.ts +1 -1
- package/lib/common/src/styles/tokens.js +1 -1
- package/lib/common/src/utils/cache.d.ts +11 -11
- package/lib/common/src/utils/cache.js +0 -0
- package/lib/common/src/utils/gridRows.d.ts +37 -0
- package/lib/common/src/utils/{applyTransactionAsyncUpdate.js → gridRows.js} +6 -38
- package/lib/common/src/utils/index.d.ts +2 -2
- package/lib/common/src/utils/index.js +2 -2
- package/lib/common/src/utils/inputAutoStep.d.ts +2 -2
- package/lib/common/src/utils/inputAutoStep.js +26 -37
- package/lib/common/src/utils/{mapMemory.d.ts → memoryStore.d.ts} +13 -13
- package/lib/common/src/utils/{mapMemory.js → memoryStore.js} +32 -32
- package/lib/common/src/utils/observableMap.d.ts +5 -5
- package/lib/common/src/utils/observableMap.js +3 -3
- package/lib/common/updateBy.js +2 -2
- package/lib/style/style.css +3 -3
- package/lib/style/tokens.css +1 -1
- package/package.json +49 -49
- package/lib/common/src/components/Dnd/DraggableOutlineDiv.d.ts +0 -2
- package/lib/common/src/hooks/useAddDownAnyKey.d.ts +0 -24
- package/lib/common/src/utils/applyTransactionAsyncUpdate.d.ts +0 -53
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReorderItem } from './useReorder';
|
|
2
2
|
/** useReorderBoard - the columns extension of useReorder: keyed blocks live in
|
|
3
3
|
* VERTICAL columns (plain consumer divs), one block drags between/within them,
|
|
4
4
|
* ONE commit on drop. Column "gravity" is pure consumer CSS (justify-content:
|
|
@@ -8,19 +8,19 @@ import { tReorderItem } from './useReorder';
|
|
|
8
8
|
* drag. Children of a column div must be exactly its items, 1:1, in order.
|
|
9
9
|
* Same non-goals as useReorder: no nesting, no spans/collision packing, no
|
|
10
10
|
* autoscroll - that day is a ready-made dnd library. */
|
|
11
|
-
export type
|
|
11
|
+
export type BoardPosition = {
|
|
12
12
|
col: string;
|
|
13
13
|
index: number;
|
|
14
14
|
};
|
|
15
|
-
export type
|
|
15
|
+
export type BoardColumn = {
|
|
16
16
|
key: string;
|
|
17
17
|
items: string[];
|
|
18
18
|
};
|
|
19
|
-
export type
|
|
19
|
+
export type ReorderBoardOptions = {
|
|
20
20
|
/** columns in board order; each column's div children must render items 1:1 */
|
|
21
|
-
columns:
|
|
21
|
+
columns: BoardColumn[];
|
|
22
22
|
/** ONE commit on drop; skipped when nothing moved */
|
|
23
|
-
commit: (next:
|
|
23
|
+
commit: (next: BoardColumn[]) => void;
|
|
24
24
|
/** false = this key cannot start a drag (default: all can) */
|
|
25
25
|
canDrag?: (key: string) => boolean;
|
|
26
26
|
/** hold before the drag starts; default 0 */
|
|
@@ -28,12 +28,12 @@ export type tReorderBoardOptions = {
|
|
|
28
28
|
/** the block was grabbed */
|
|
29
29
|
onDragStart?: (e: {
|
|
30
30
|
key: string;
|
|
31
|
-
from:
|
|
31
|
+
from: BoardPosition;
|
|
32
32
|
}) => void;
|
|
33
33
|
/** every pointer move while dragging; position = pointer delta in local px */
|
|
34
34
|
onDragMove?: (e: {
|
|
35
35
|
key: string;
|
|
36
|
-
over:
|
|
36
|
+
over: BoardPosition;
|
|
37
37
|
position: {
|
|
38
38
|
x: number;
|
|
39
39
|
y: number;
|
|
@@ -42,20 +42,20 @@ export type tReorderBoardOptions = {
|
|
|
42
42
|
/** the target slot changed (compare prev.col != over.col for column crossings) */
|
|
43
43
|
onOverChange?: (e: {
|
|
44
44
|
key: string;
|
|
45
|
-
over:
|
|
46
|
-
prev:
|
|
45
|
+
over: BoardPosition;
|
|
46
|
+
prev: BoardPosition | null;
|
|
47
47
|
}) => void;
|
|
48
48
|
/** drop; committed=false when nothing moved (plain click) */
|
|
49
49
|
onDragEnd?: (e: {
|
|
50
50
|
key: string;
|
|
51
|
-
from:
|
|
52
|
-
over:
|
|
51
|
+
from: BoardPosition;
|
|
52
|
+
over: BoardPosition;
|
|
53
53
|
committed: boolean;
|
|
54
54
|
}) => void;
|
|
55
55
|
};
|
|
56
|
-
export declare function useReorderBoard(o:
|
|
56
|
+
export declare function useReorderBoard(o: ReorderBoardOptions): {
|
|
57
57
|
columnRef: (col: string) => (el: HTMLElement | null) => void;
|
|
58
|
-
item: (key: string) =>
|
|
58
|
+
item: (key: string) => ReorderItem;
|
|
59
59
|
dragKey: string | null;
|
|
60
|
-
over:
|
|
60
|
+
over: BoardPosition | null;
|
|
61
61
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type
|
|
1
|
+
import { Observe, Replay } from "wenay-common2";
|
|
2
|
+
type StoreDrain = Observe.StoreDrain;
|
|
3
|
+
type StoreEachCtx = Observe.StoreEachCtx;
|
|
4
|
+
type StorePatch = Observe.StorePatch;
|
|
3
5
|
type ReplayEvent<Z extends any[]> = Replay.ReplayEvent<Z>;
|
|
4
6
|
type ReplayRemote<Z extends any[]> = Replay.ReplayRemote<Z>;
|
|
5
7
|
type StaleInfo = Replay.StaleInfo;
|
|
@@ -63,14 +65,14 @@ export declare function useReplaySubscribe<Z extends any[]>(remote: ReplayRemote
|
|
|
63
65
|
export type UseStoreReplaySyncOptions = UseReplaySubscribeOptions;
|
|
64
66
|
export type StoreReplaySyncController = ReplaySubscribeController;
|
|
65
67
|
/**
|
|
66
|
-
* Sync an existing mirror store from a store replay line (`
|
|
67
|
-
* Thin lifecycle wrapper over `
|
|
68
|
+
* Sync an existing mirror store from a store replay line (`Observe.exposeStoreReplay(...).api.replay`).
|
|
69
|
+
* Thin lifecycle wrapper over `Observe.syncStoreReplay`: the keyframe (root patch) and the
|
|
68
70
|
* patch tail are applied to the store by the library; UI subscribes to the store as usual
|
|
69
71
|
* (useStoreNode/useStoreSelect).
|
|
70
72
|
*/
|
|
71
|
-
export declare function useStoreReplaySync<T extends object>(store:
|
|
73
|
+
export declare function useStoreReplaySync<T extends object>(store: Observe.Store<T> | null | undefined, remote: ReplayRemote<[StorePatch]> | null | undefined, options?: UseStoreReplaySyncOptions): StoreReplaySyncController;
|
|
72
74
|
export type StoreReplayMirrorController<T extends object> = StoreReplaySyncController & {
|
|
73
|
-
readonly store:
|
|
75
|
+
readonly store: Observe.Store<T>;
|
|
74
76
|
};
|
|
75
77
|
/**
|
|
76
78
|
* Convenience: create a local mirror store and keep it synced from a store replay line.
|
|
@@ -78,6 +80,31 @@ export type StoreReplayMirrorController<T extends object> = StoreReplaySyncContr
|
|
|
78
80
|
* so reconnect is a journal tail, not a keyframe. A new `remote` recreates the store.
|
|
79
81
|
*/
|
|
80
82
|
export declare function useStoreReplayMirror<T extends object>(remote: ReplayRemote<[StorePatch]> | null | undefined, initial: T, options?: UseStoreReplaySyncOptions): StoreReplayMirrorController<T>;
|
|
83
|
+
export type UseStoreReplayEachOptions<T extends object> = UseStoreReplaySyncOptions & {
|
|
84
|
+
/**
|
|
85
|
+
* Seed of the internal mirror store. Creation-time only (a later identity change does nothing).
|
|
86
|
+
* Reconnect after a FULL unmount: pass the saved snapshot together with `since`
|
|
87
|
+
* ({since: prev.seq(), initial: prev.store.snapshot()}) — the tail lands ON TOP of the previous
|
|
88
|
+
* state; a fresh empty mirror would not converge.
|
|
89
|
+
*/
|
|
90
|
+
initial?: T;
|
|
91
|
+
/** Drain of the internal mirror store — the coalescing window of the per-key feed. Creation-time only. */
|
|
92
|
+
drain?: StoreDrain;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Per-key fold over a store replay line — React counterpart of `Observe.syncStoreReplayEach`
|
|
96
|
+
* (internal mirror store + syncStoreReplay + store.each()). cb fires once per CHANGED top-level
|
|
97
|
+
* key per drain window with the current value; the first delivery is the keyframe EXPANDED per
|
|
98
|
+
* key; (key, undefined) = key deleted — cold start / reconnect are not special cases for per-key
|
|
99
|
+
* consumers (grid rows, canvas layers, ...). The fold target should live outside React state.
|
|
100
|
+
*
|
|
101
|
+
* Unlike the library one-call (a fresh store per call), the mirror here lives in a ref: within
|
|
102
|
+
* one mounted component every resubscribe (StrictMode double-effect, restart(), enabled toggling,
|
|
103
|
+
* staleMs/policy change) reconnects by tail ON TOP of the kept state — no snapshot/initial dance.
|
|
104
|
+
* A new `remote` identity recreates the store (fresh keyframe). Direct reads / extra
|
|
105
|
+
* subscriptions: controller.store (useStoreNode/useStoreKeys work on it as usual).
|
|
106
|
+
*/
|
|
107
|
+
export declare function useStoreReplayEach<T extends object>(remote: ReplayRemote<[StorePatch]> | null | undefined, cb: (key: string, value: T[keyof T] | undefined, ctx: StoreEachCtx) => void, options?: UseStoreReplayEachOptions<T>): StoreReplayMirrorController<T>;
|
|
81
108
|
export type UseReplayFrameOptions = {
|
|
82
109
|
/** Pull period, ms. Default 300. */
|
|
83
110
|
intervalMs?: number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { Observe, Replay } from "wenay-common2";
|
|
3
|
+
import { useStoreEach } from "./useObserveStore";
|
|
3
4
|
/**
|
|
4
5
|
* React bridge over the Replay stack (snapshot + sequenced delta line) of wenay-common2.
|
|
5
6
|
*
|
|
@@ -111,8 +112,8 @@ export function useReplaySubscribe(remote, cb, options = {}) {
|
|
|
111
112
|
return useMemo(() => ({ ready, error, stale, seq, lastTs, restart }), [ready, error, stale, seq, lastTs, restart]);
|
|
112
113
|
}
|
|
113
114
|
/**
|
|
114
|
-
* Sync an existing mirror store from a store replay line (`
|
|
115
|
-
* Thin lifecycle wrapper over `
|
|
115
|
+
* Sync an existing mirror store from a store replay line (`Observe.exposeStoreReplay(...).api.replay`).
|
|
116
|
+
* Thin lifecycle wrapper over `Observe.syncStoreReplay`: the keyframe (root patch) and the
|
|
116
117
|
* patch tail are applied to the store by the library; UI subscribes to the store as usual
|
|
117
118
|
* (useStoreNode/useStoreSelect).
|
|
118
119
|
*/
|
|
@@ -138,7 +139,7 @@ export function useStoreReplaySync(store, remote, options = {}) {
|
|
|
138
139
|
setError(null);
|
|
139
140
|
if (staleMs === undefined)
|
|
140
141
|
setStale(false); // see useReplaySubscribe: stale re-syncs from common2, no reset-to-false flicker
|
|
141
|
-
const off =
|
|
142
|
+
const off = Observe.syncStoreReplay(store, remote, {
|
|
142
143
|
since: seqRef.current,
|
|
143
144
|
policy,
|
|
144
145
|
hint: hintRef.current,
|
|
@@ -195,12 +196,38 @@ export function useStoreReplaySync(store, remote, options = {}) {
|
|
|
195
196
|
export function useStoreReplayMirror(remote, initial, options = {}) {
|
|
196
197
|
const storeRef = useRef(null);
|
|
197
198
|
if (!storeRef.current || storeRef.current.remote !== remote) {
|
|
198
|
-
storeRef.current = { remote, store:
|
|
199
|
+
storeRef.current = { remote, store: Observe.createStore(initial) };
|
|
199
200
|
}
|
|
200
201
|
const store = storeRef.current.store;
|
|
201
202
|
const sync = useStoreReplaySync(store, remote, options);
|
|
202
203
|
return useMemo(() => ({ ...sync, store }), [sync, store]);
|
|
203
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Per-key fold over a store replay line — React counterpart of `Observe.syncStoreReplayEach`
|
|
207
|
+
* (internal mirror store + syncStoreReplay + store.each()). cb fires once per CHANGED top-level
|
|
208
|
+
* key per drain window with the current value; the first delivery is the keyframe EXPANDED per
|
|
209
|
+
* key; (key, undefined) = key deleted — cold start / reconnect are not special cases for per-key
|
|
210
|
+
* consumers (grid rows, canvas layers, ...). The fold target should live outside React state.
|
|
211
|
+
*
|
|
212
|
+
* Unlike the library one-call (a fresh store per call), the mirror here lives in a ref: within
|
|
213
|
+
* one mounted component every resubscribe (StrictMode double-effect, restart(), enabled toggling,
|
|
214
|
+
* staleMs/policy change) reconnects by tail ON TOP of the kept state — no snapshot/initial dance.
|
|
215
|
+
* A new `remote` identity recreates the store (fresh keyframe). Direct reads / extra
|
|
216
|
+
* subscriptions: controller.store (useStoreNode/useStoreKeys work on it as usual).
|
|
217
|
+
*/
|
|
218
|
+
export function useStoreReplayEach(remote, cb, options = {}) {
|
|
219
|
+
const { initial, drain, ...syncOptions } = options;
|
|
220
|
+
const storeRef = useRef(null);
|
|
221
|
+
if (!storeRef.current || storeRef.current.remote !== remote) {
|
|
222
|
+
storeRef.current = { remote, store: Observe.createStore((initial ?? {}), drain !== undefined ? { drain } : undefined) };
|
|
223
|
+
}
|
|
224
|
+
const store = storeRef.current.store;
|
|
225
|
+
// each BEFORE sync: effects run in hook-call order, so the per-key subscriber already exists
|
|
226
|
+
// when the keyframe applies to the store (the expansion is not missed)
|
|
227
|
+
useStoreEach(store, cb, { enabled: syncOptions.enabled });
|
|
228
|
+
const sync = useStoreReplaySync(store, remote, syncOptions);
|
|
229
|
+
return useMemo(() => ({ ...sync, store }), [sync, store]);
|
|
230
|
+
}
|
|
204
231
|
/**
|
|
205
232
|
* Pull a replay line at YOUR pace (the frame model of common2): a timer around
|
|
206
233
|
* `remote.frame(seq, hint)` — the server condenses the tail via the line's `frame` lambda
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Params } from "wenay-common2";
|
|
2
|
-
type
|
|
2
|
+
type LogInput<T extends object> = T & {
|
|
3
3
|
id: string;
|
|
4
4
|
var?: number;
|
|
5
5
|
time: Date;
|
|
@@ -43,7 +43,7 @@ export declare function getLogsApi<T extends object = {}>(setting: {
|
|
|
43
43
|
limitPer: number;
|
|
44
44
|
varMin?: number;
|
|
45
45
|
}): {
|
|
46
|
-
addLogs(a:
|
|
46
|
+
addLogs(a: LogInput<T>): void;
|
|
47
47
|
params: {
|
|
48
48
|
def: () => {
|
|
49
49
|
minVarLogs: {
|
|
@@ -160,7 +160,7 @@ export declare function PageLogs({ update }: {
|
|
|
160
160
|
export declare function MessageEventLogs({ zIndex }: {
|
|
161
161
|
zIndex?: number;
|
|
162
162
|
}): import("react/jsx-runtime").JSX.Element;
|
|
163
|
-
export declare function
|
|
163
|
+
export declare function LogsPage({ update }: {
|
|
164
164
|
update?: number;
|
|
165
165
|
}): import("react/jsx-runtime").JSX.Element;
|
|
166
166
|
export {};
|
|
@@ -3,9 +3,9 @@ import { AgGridReact } from "ag-grid-react";
|
|
|
3
3
|
import { useCallback, useEffect, useRef } from "react";
|
|
4
4
|
import { copyToClipboard, Params, timeLocalToStr_hhmmss } from "wenay-common2";
|
|
5
5
|
import { renderBy, updateBy } from "../../updateBy";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { contextMenu } from "../menu/menuMouse";
|
|
7
|
+
import { memoryGetOrCreate } from "../utils/memoryStore";
|
|
8
|
+
import { ParamsEditor } from "../components/ParamsEditor";
|
|
9
9
|
const cashLogs = new Map();
|
|
10
10
|
const datumConst = {
|
|
11
11
|
map: cashLogs,
|
|
@@ -22,7 +22,7 @@ const getSettingLogs = () => ({
|
|
|
22
22
|
const settingLogs = { params: Params.GetSimpleParams(getSettingLogs()) };
|
|
23
23
|
// varMin - minimum importance
|
|
24
24
|
export function getLogsApi(setting) {
|
|
25
|
-
const datum =
|
|
25
|
+
const datum = memoryGetOrCreate("settingLogs", settingLogs);
|
|
26
26
|
function addToArr(arr, data, limit) {
|
|
27
27
|
arr.unshift(data);
|
|
28
28
|
if (arr.length > limit)
|
|
@@ -55,8 +55,8 @@ export function getLogsApi(setting) {
|
|
|
55
55
|
}
|
|
56
56
|
export const logsApi = getLogsApi({ limitPer: 500 });
|
|
57
57
|
function InputSettingLogs({}) {
|
|
58
|
-
const datum =
|
|
59
|
-
return _jsx(
|
|
58
|
+
const datum = memoryGetOrCreate("settingLogs", settingLogs);
|
|
59
|
+
return _jsx(ParamsEditor
|
|
60
60
|
// @ts-ignore
|
|
61
61
|
, {
|
|
62
62
|
// @ts-ignore
|
|
@@ -69,7 +69,7 @@ export function PageLogs({ update }) {
|
|
|
69
69
|
const datumFull = datumConst;
|
|
70
70
|
const rowData = [...datumFull.map.values()].flat();
|
|
71
71
|
const datum = datumMiniConst;
|
|
72
|
-
const setting =
|
|
72
|
+
const setting = memoryGetOrCreate("settingLogs", settingLogs);
|
|
73
73
|
const apiGrid = useRef(null);
|
|
74
74
|
useEffect(() => {
|
|
75
75
|
apiGrid.current?.api.sizeColumnsToFit();
|
|
@@ -160,10 +160,8 @@ export function PageLogs({ update }) {
|
|
|
160
160
|
filter: true,
|
|
161
161
|
wrapText: true,
|
|
162
162
|
}, headerHeight: 30, rowHeight: 26, autoSizePadding: 1, rowData: rowData, columnDefs: columns, onCellMouseDown: (e) => {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// copyToClipboard(e.value)
|
|
166
|
-
mouseMenuApi.map.set("sym", [
|
|
163
|
+
if (e.event instanceof MouseEvent && e.event.button == 2) {
|
|
164
|
+
contextMenu.openAt(e.event, [
|
|
167
165
|
{
|
|
168
166
|
name: "copy", onClick: () => { copyToClipboard(e.value); }
|
|
169
167
|
}
|
|
@@ -189,7 +187,7 @@ function Message({ logs }) {
|
|
|
189
187
|
const tt = {};
|
|
190
188
|
let r = 0;
|
|
191
189
|
export function MessageEventLogs({ zIndex }) {
|
|
192
|
-
const setting =
|
|
190
|
+
const setting = memoryGetOrCreate("settingLogs", settingLogs);
|
|
193
191
|
updateBy(tt);
|
|
194
192
|
updateBy(datumMiniConst, () => {
|
|
195
193
|
const last = datumMiniConst.last[0];
|
|
@@ -222,7 +220,7 @@ const pages = [
|
|
|
222
220
|
{ name: "setting", key: "InputSettingLogs", page: InputSettingLogs },
|
|
223
221
|
];
|
|
224
222
|
const map = Object.fromEntries(pages.map(e => [e.key, e.page]));
|
|
225
|
-
export function
|
|
223
|
+
export function LogsPage({ update }) {
|
|
226
224
|
const datum = defPageBase;
|
|
227
225
|
updateBy(datum);
|
|
228
226
|
const Page = map[datum.keyPage];
|
|
@@ -3,14 +3,14 @@ import React from 'react';
|
|
|
3
3
|
* 1. Log types
|
|
4
4
|
* -----------------------------
|
|
5
5
|
*/
|
|
6
|
-
export interface
|
|
6
|
+
export interface LogInput<T extends object = {}> {
|
|
7
7
|
id: string;
|
|
8
8
|
var?: number;
|
|
9
9
|
time: Date;
|
|
10
10
|
txt: string;
|
|
11
11
|
[key: string]: any;
|
|
12
12
|
}
|
|
13
|
-
export interface
|
|
13
|
+
export interface LogEntry<T extends object = {}> extends LogInput<T> {
|
|
14
14
|
num: number;
|
|
15
15
|
}
|
|
16
16
|
/** -----------------------------
|
|
@@ -18,8 +18,8 @@ export interface tLogs<T extends object = {}> extends tLogsInput<T> {
|
|
|
18
18
|
* -----------------------------
|
|
19
19
|
*/
|
|
20
20
|
interface LogsContextValue {
|
|
21
|
-
logs:
|
|
22
|
-
addLog: (input:
|
|
21
|
+
logs: LogEntry[];
|
|
22
|
+
addLog: (input: LogInput) => void;
|
|
23
23
|
minVarLogs: number;
|
|
24
24
|
setMinVarLogs: (value: number) => void;
|
|
25
25
|
minVarMessage: number;
|
|
@@ -2,11 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { createContext, useContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { AgGridReact } from 'ag-grid-react';
|
|
4
4
|
/** -----------------------------
|
|
5
|
-
* 2.
|
|
5
|
+
* 2. memoryGetOrCreate function -
|
|
6
6
|
* loads and saves data in localStorage.
|
|
7
7
|
* -----------------------------
|
|
8
8
|
*/
|
|
9
|
-
function
|
|
9
|
+
function memoryGetOrCreate(key, defaultValue) {
|
|
10
10
|
try {
|
|
11
11
|
const stored = localStorage.getItem(key);
|
|
12
12
|
// If localStorage has no value, write defaultValue
|
|
@@ -32,7 +32,7 @@ function staticGetAdd(key, defaultValue) {
|
|
|
32
32
|
const LogsContext = createContext(null);
|
|
33
33
|
export function LogsProvider({ children }) {
|
|
34
34
|
// 4.1. Load settings from localStorage once (lazy init: the provider rerenders on every addLog)
|
|
35
|
-
const [savedSettings] = useState(() =>
|
|
35
|
+
const [savedSettings] = useState(() => memoryGetOrCreate("logSettings", {
|
|
36
36
|
minVarLogs: 0,
|
|
37
37
|
minVarMessage: 0,
|
|
38
38
|
timeShow: 2,
|
|
@@ -42,7 +42,7 @@ export function LogsProvider({ children }) {
|
|
|
42
42
|
// only settings are, but logs can be saved too if needed)
|
|
43
43
|
const [logs, setLogs] = useState([]);
|
|
44
44
|
const counterRef = useRef(0);
|
|
45
|
-
// 4.3. Settings themselves, initialized from
|
|
45
|
+
// 4.3. Settings themselves, initialized from memoryGetOrCreate output
|
|
46
46
|
const [minVarLogs, setMinVarLogs] = useState(savedSettings.minVarLogs);
|
|
47
47
|
const [minVarMessage, setMinVarMessage] = useState(savedSettings.minVarMessage);
|
|
48
48
|
const [timeShow, setTimeShow] = useState(savedSettings.timeShow);
|
|
@@ -2,22 +2,22 @@ import React, { ReactElement } from 'react';
|
|
|
2
2
|
/*******************************************************
|
|
3
3
|
* Menu data types
|
|
4
4
|
*******************************************************/
|
|
5
|
-
export type
|
|
5
|
+
export type MenuItemStrict<T = any> = {
|
|
6
6
|
name: string | ((status?: T) => string);
|
|
7
7
|
getStatus?: (() => T) | null;
|
|
8
8
|
onClick?: ((e: any) => void | undefined | null | ((void | undefined | null | Promise<any> | (() => Promise<any>))[]) | Promise<any>) | null;
|
|
9
9
|
active?: (() => boolean) | null;
|
|
10
10
|
status?: boolean;
|
|
11
|
-
next?: (() => (
|
|
11
|
+
next?: (() => (MenuItem<any> | false)[] | Promise<(MenuItem<any> | false)[]>) | null;
|
|
12
12
|
func?: (() => React.ReactElement | Promise<React.ReactElement>) | null;
|
|
13
|
-
onFocus?: (() =>
|
|
13
|
+
onFocus?: (() => MenuItem<any>[] | Promise<MenuItem<any>[]>) | null;
|
|
14
14
|
menuElement?: typeof MenuElement;
|
|
15
15
|
};
|
|
16
|
-
export type
|
|
16
|
+
export type MenuItem<T = any> = MenuItemStrict<T> | false | null | undefined;
|
|
17
17
|
/*******************************************************
|
|
18
18
|
* Helper type
|
|
19
19
|
*******************************************************/
|
|
20
|
-
type
|
|
20
|
+
type MenuProgressCounters = {
|
|
21
21
|
ok?: number;
|
|
22
22
|
error?: number;
|
|
23
23
|
count?: number;
|
|
@@ -25,20 +25,20 @@ type tCounters = {
|
|
|
25
25
|
/*******************************************************
|
|
26
26
|
* Displays counter/progress with animation and ok/error counts
|
|
27
27
|
*******************************************************/
|
|
28
|
-
declare function
|
|
29
|
-
data:
|
|
28
|
+
declare function MenuProgress({ data }: {
|
|
29
|
+
data: MenuProgressCounters;
|
|
30
30
|
}): ReactElement;
|
|
31
31
|
/*******************************************************
|
|
32
32
|
* Main menu element with onClick and counters
|
|
33
33
|
*******************************************************/
|
|
34
34
|
declare function MenuElement({ data: item, toLeft, className, update, }: {
|
|
35
|
-
data: Pick<
|
|
35
|
+
data: Pick<MenuItemStrict, "onClick" | "active" | "name" | "getStatus">;
|
|
36
36
|
toLeft: boolean;
|
|
37
37
|
className?: (active?: boolean) => string;
|
|
38
38
|
update: () => void;
|
|
39
39
|
}): ReactElement;
|
|
40
40
|
/*******************************************************
|
|
41
|
-
*
|
|
41
|
+
* Menu renders the popup menu with support for
|
|
42
42
|
* nested submenus and their state management.
|
|
43
43
|
*
|
|
44
44
|
* @param {Object} props - Component props.
|
|
@@ -47,7 +47,7 @@ declare function MenuElement({ data: item, toLeft, className, update, }: {
|
|
|
47
47
|
* @param {number} props.coordinate.y - Y coordinate for menu placement.
|
|
48
48
|
* @param {boolean} [props.coordinate.toLeft=false] - Whether the menu should be shifted left.
|
|
49
49
|
* @param {number} [props.coordinate.left=0] - Additional left offset when the menu has nested items.
|
|
50
|
-
* @param {
|
|
50
|
+
* @param {MenuItemStrict[]} props.data - Array of objects describing menu items.
|
|
51
51
|
* @param {number} [props.zIndex] - Menu z-index for overlap visibility.
|
|
52
52
|
* @param {Function} [props.menu] - Function that generates a custom React element for the whole menu.
|
|
53
53
|
* @param {Function} [props.menuElement] - Function that generates a custom React element for one menu item.
|
|
@@ -55,10 +55,10 @@ declare function MenuElement({ data: item, toLeft, className, update, }: {
|
|
|
55
55
|
*
|
|
56
56
|
* @returns {ReactElement} Visual menu element.
|
|
57
57
|
*/
|
|
58
|
-
type
|
|
59
|
-
menu?: (arr:
|
|
60
|
-
menuElement?: (item:
|
|
61
|
-
data:
|
|
58
|
+
type MenuProps = {
|
|
59
|
+
menu?: (arr: MenuItem[]) => ReactElement;
|
|
60
|
+
menuElement?: (item: MenuItem) => ReactElement;
|
|
61
|
+
data: MenuItem[];
|
|
62
62
|
zIndex?: number;
|
|
63
63
|
className?: (active?: boolean) => string;
|
|
64
64
|
coordinate?: {
|
|
@@ -68,5 +68,5 @@ type MenuBaseProps = {
|
|
|
68
68
|
left?: number;
|
|
69
69
|
};
|
|
70
70
|
};
|
|
71
|
-
export declare function
|
|
72
|
-
export {
|
|
71
|
+
export declare function Menu({ coordinate, data, zIndex, menu, className, menuElement, }: MenuProps): ReactElement;
|
|
72
|
+
export { MenuProgress, MenuElement };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { promiseProgress, sleepAsync } from "wenay-common2";
|
|
4
4
|
/*******************************************************
|
|
5
5
|
* Displays counter/progress with animation and ok/error counts
|
|
6
6
|
*******************************************************/
|
|
7
|
-
function
|
|
7
|
+
function MenuProgress({ data }) {
|
|
8
8
|
const [count, setCount] = useState(0);
|
|
9
9
|
const formatLabel = () => {
|
|
10
10
|
if (!data.ok && !data.error)
|
|
@@ -54,7 +54,7 @@ function MenuElement({ data: item, toLeft, className, update, }) {
|
|
|
54
54
|
// If this is an array of tasks, promises, or functions
|
|
55
55
|
if (Array.isArray(result)) {
|
|
56
56
|
const tasks = result.filter(Boolean);
|
|
57
|
-
const pa =
|
|
57
|
+
const pa = promiseProgress(tasks);
|
|
58
58
|
setProgress({});
|
|
59
59
|
unsubOk.current?.();
|
|
60
60
|
unsubErr.current?.();
|
|
@@ -71,8 +71,9 @@ function MenuElement({ data: item, toLeft, className, update, }) {
|
|
|
71
71
|
setProgress(null);
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
|
-
unsubOk.current = pa.
|
|
75
|
-
unsubErr.current = pa.
|
|
74
|
+
unsubOk.current = pa.onOk((data, i, countOk, countError, count) => onTick(countOk, countError, count));
|
|
75
|
+
unsubErr.current = pa.onError((error, i, countOk, countError, count) => onTick(countOk, countError, count));
|
|
76
|
+
void pa.allSettled();
|
|
76
77
|
}
|
|
77
78
|
// If this is a single promise
|
|
78
79
|
else if (result instanceof Promise) {
|
|
@@ -108,7 +109,7 @@ function MenuElement({ data: item, toLeft, className, update, }) {
|
|
|
108
109
|
}
|
|
109
110
|
}, children: _jsxs("div", { className: "toLine", children: [typeof item.name === "string"
|
|
110
111
|
? item.name
|
|
111
|
-
: item.name(item.getStatus?.()), progress && _jsx(
|
|
112
|
+
: item.name(item.getStatus?.()), progress && _jsx(MenuProgress, { data: progress })] }) }));
|
|
112
113
|
}
|
|
113
114
|
const MenuItemWrapper = ({ item, index, update, className, isLeftAligned, leftPos, menuElement, fullArray, }) => {
|
|
114
115
|
const [childMenu, setChildMenu] = useState([]);
|
|
@@ -186,24 +187,24 @@ const MenuItemWrapper = ({ item, index, update, className, isLeftAligned, leftPo
|
|
|
186
187
|
data: item,
|
|
187
188
|
className,
|
|
188
189
|
update,
|
|
189
|
-
}) ?? (_jsx(MenuElement, { toLeft: isLeftAligned, data: item, className: className, update: update })), _jsxs("div", { children: [item.status && childMenu.length > 0 && (_jsx("div", { style: { position: "relative" }, children: _jsx(
|
|
190
|
+
}) ?? (_jsx(MenuElement, { toLeft: isLeftAligned, data: item, className: className, update: update })), _jsxs("div", { children: [item.status && childMenu.length > 0 && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { data: childMenu, coordinate: {
|
|
190
191
|
x: 3,
|
|
191
192
|
y: 0,
|
|
192
193
|
toLeft: isLeftAligned,
|
|
193
194
|
left: leftPos,
|
|
194
|
-
} }) })), item.status && asyncFuncElement && (_jsx("div", { style: { position: "relative" }, children: _jsx(
|
|
195
|
+
} }) })), item.status && asyncFuncElement && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { menu: () => asyncFuncElement, data: [], coordinate: {
|
|
195
196
|
x: 3,
|
|
196
197
|
y: 0,
|
|
197
198
|
toLeft: isLeftAligned,
|
|
198
199
|
left: leftPos,
|
|
199
|
-
} }) })), item.status && onFocusMenu.length > 0 && (_jsx("div", { style: { position: "relative" }, children: _jsx(
|
|
200
|
+
} }) })), item.status && onFocusMenu.length > 0 && (_jsx("div", { style: { position: "relative" }, children: _jsx(Menu, { data: onFocusMenu, coordinate: {
|
|
200
201
|
x: 3,
|
|
201
202
|
y: 0,
|
|
202
203
|
toLeft: isLeftAligned,
|
|
203
204
|
left: leftPos,
|
|
204
205
|
} }) }))] })] }));
|
|
205
206
|
};
|
|
206
|
-
export function
|
|
207
|
+
export function Menu({ coordinate = { x: 0, y: 0, toLeft: false, left: 0 }, data, zIndex, menu, className, menuElement, }) {
|
|
207
208
|
const [, forceUpdate] = useState(false);
|
|
208
209
|
const update = () => forceUpdate((p) => !p);
|
|
209
210
|
const refMenu = useRef(null);
|
|
@@ -251,4 +252,4 @@ export function MenuBase({ coordinate = { x: 0, y: 0, toLeft: false, left: 0 },
|
|
|
251
252
|
? menu(dataMemo)
|
|
252
253
|
: dataMemo.map((item, i, arr) => (_jsx(MenuItemWrapper, { item: item, index: i, update: update, className: className, isLeftAligned: isLeftAligned, leftPos: leftPos, menuElement: menuElement, fullArray: dataMemo }, typeof item.name === "string" ? item.name : i))) }));
|
|
253
254
|
}
|
|
254
|
-
export {
|
|
255
|
+
export { MenuProgress, MenuElement };
|
|
@@ -1,7 +1,62 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Menu, MenuItem, MenuItemStrict } from "./menu";
|
|
3
|
+
export type ContextMenuPoint = {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
};
|
|
7
|
+
export type ContextMenuAnchor = ContextMenuPoint | {
|
|
8
|
+
clientX: number;
|
|
9
|
+
clientY: number;
|
|
10
|
+
target?: EventTarget | null;
|
|
11
|
+
preventDefault?: () => void;
|
|
12
|
+
stopPropagation?: () => void;
|
|
13
|
+
};
|
|
14
|
+
export type ContextMenuState = {
|
|
15
|
+
open: boolean;
|
|
16
|
+
items: MenuItemStrict[];
|
|
17
|
+
point: ContextMenuPoint;
|
|
18
|
+
source?: string;
|
|
19
|
+
layerId?: string;
|
|
20
|
+
seq: number;
|
|
21
|
+
};
|
|
22
|
+
export type ContextMenuLayerProps = {
|
|
23
|
+
children: React.ReactElement;
|
|
24
|
+
zIndex?: number;
|
|
25
|
+
other?: () => MenuItem[];
|
|
26
|
+
statusOn?: boolean;
|
|
27
|
+
onUnClick?: (e: boolean) => void;
|
|
28
|
+
onConsume?: () => void;
|
|
29
|
+
className?: (active?: boolean) => string;
|
|
30
|
+
};
|
|
31
|
+
export declare function createContextMenu(data?: {
|
|
32
|
+
name?: string;
|
|
33
|
+
}): {
|
|
34
|
+
bb: (b?: boolean) => boolean | undefined;
|
|
35
|
+
readonly map: Map<string, MenuItem[]>;
|
|
36
|
+
readonly menuMouse: {
|
|
37
|
+
name: string;
|
|
38
|
+
readonly value: {
|
|
39
|
+
status: boolean;
|
|
40
|
+
clicks: number;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
getState: () => ContextMenuState;
|
|
44
|
+
subscribe: (cb: () => void) => () => void;
|
|
45
|
+
openAt: (anchor: ContextMenuAnchor, items: readonly MenuItem[] | null | undefined, opts?: {
|
|
46
|
+
source?: string;
|
|
47
|
+
layerId?: string;
|
|
48
|
+
}) => boolean;
|
|
49
|
+
openAtPoint: (point: ContextMenuPoint, items: readonly MenuItem[] | null | undefined, opts?: {
|
|
50
|
+
source?: string;
|
|
51
|
+
layerId?: string;
|
|
52
|
+
}) => boolean;
|
|
53
|
+
close: () => void;
|
|
54
|
+
Layer: ({ children, other, statusOn, onUnClick, onConsume, zIndex, className }: ContextMenuLayerProps) => import("react/jsx-runtime").JSX.Element;
|
|
55
|
+
MenuView: typeof Menu;
|
|
56
|
+
};
|
|
57
|
+
export declare const contextMenu: {
|
|
3
58
|
bb: (b?: boolean) => boolean | undefined;
|
|
4
|
-
readonly map: Map<string,
|
|
59
|
+
readonly map: Map<string, MenuItem[]>;
|
|
5
60
|
readonly menuMouse: {
|
|
6
61
|
name: string;
|
|
7
62
|
readonly value: {
|
|
@@ -9,14 +64,17 @@ export declare const mouseMenuApi: {
|
|
|
9
64
|
clicks: number;
|
|
10
65
|
};
|
|
11
66
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
67
|
+
getState: () => ContextMenuState;
|
|
68
|
+
subscribe: (cb: () => void) => () => void;
|
|
69
|
+
openAt: (anchor: ContextMenuAnchor, items: readonly MenuItem[] | null | undefined, opts?: {
|
|
70
|
+
source?: string;
|
|
71
|
+
layerId?: string;
|
|
72
|
+
}) => boolean;
|
|
73
|
+
openAtPoint: (point: ContextMenuPoint, items: readonly MenuItem[] | null | undefined, opts?: {
|
|
74
|
+
source?: string;
|
|
75
|
+
layerId?: string;
|
|
76
|
+
}) => boolean;
|
|
77
|
+
close: () => void;
|
|
78
|
+
Layer: ({ children, other, statusOn, onUnClick, onConsume, zIndex, className }: ContextMenuLayerProps) => import("react/jsx-runtime").JSX.Element;
|
|
79
|
+
MenuView: typeof Menu;
|
|
22
80
|
};
|