wenay-react2 1.0.40 → 1.0.42
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/doc/EXAMPLE_USAGE.md +971 -0
- package/doc/PROJECT_FUNCTIONALITY.md +405 -0
- package/doc/PROJECT_RULES.md +80 -0
- package/doc/WENAY_REACT2_RENAMES.md +177 -0
- package/doc/changes/v1.0.35.md +26 -0
- package/doc/changes/v1.0.37.md +13 -0
- package/doc/changes/v1.0.38.md +48 -0
- package/doc/changes/v1.0.39.md +35 -0
- package/doc/changes/v1.0.40.md +15 -0
- package/doc/changes/v1.0.41.md +36 -0
- package/doc/changes/v1.0.42.md +26 -0
- package/doc/progress/README.md +14 -0
- package/doc/progress/architecture-fix-queue.md +74 -0
- package/doc/progress/hook-controller-opportunities.md +367 -0
- package/doc/progress/hook-extraction-audit.md +195 -0
- package/doc/progress/public-surface-normalization.md +368 -0
- package/doc/progress/style-system-normalization.md +121 -0
- package/doc/target/README.md +33 -0
- package/doc/target/my.md +81 -0
- package/doc/wenay-react2-1.0.8.tgz +0 -0
- package/doc/wenay-react2-rare.md +807 -0
- package/doc/wenay-react2.md +539 -0
- package/lib/common/api.d.ts +1 -0
- package/lib/common/api.js +8 -4
- package/lib/common/src/components/Dnd/DragArea.d.ts +5 -0
- package/lib/common/src/components/Dnd/DragArea.js +5 -1
- package/lib/common/src/components/Dnd/FloatingWindow.d.ts +9 -5
- package/lib/common/src/components/Dnd/FloatingWindow.js +39 -97
- package/lib/common/src/components/Dnd/Resizable.d.ts +3 -7
- package/lib/common/src/components/Dnd/Resizable.js +4 -3
- package/lib/common/src/components/Menu/RightMenu.js +8 -4
- package/lib/common/src/components/Menu/RightMenuStore.d.ts +2 -2
- package/lib/common/src/components/Menu/RightMenuStore.js +5 -3
- package/lib/common/src/components/Modal/LeftModal.js +4 -2
- package/lib/common/src/components/Modal/ModalContextProvider.js +5 -16
- package/lib/common/src/components/MyResizeObserver.d.ts +24 -0
- package/lib/common/src/components/MyResizeObserver.js +49 -0
- package/lib/common/src/components/Overlay.d.ts +24 -0
- package/lib/common/src/components/Overlay.js +28 -0
- package/lib/common/src/components/Settings/SettingsDialog.js +21 -22
- package/lib/common/src/components/Toolbar/Toolbar.d.ts +1 -0
- package/lib/common/src/components/Toolbar/Toolbar.js +16 -23
- package/lib/common/src/grid/columnState/ColumnsMenu.js +4 -13
- package/lib/common/src/grid/columnState/columnGrid.d.ts +103 -0
- package/lib/common/src/grid/columnState/columnGrid.js +231 -0
- package/lib/common/src/grid/columnState/columnState.js +10 -9
- package/lib/common/src/grid/columnState/index.js +3 -0
- package/lib/common/src/hooks/useDraggable.d.ts +8 -0
- package/lib/common/src/hooks/useDraggable.js +13 -4
- package/lib/common/src/hooks/useOutside.d.ts +4 -1
- package/lib/common/src/hooks/useOutside.js +2 -1
- package/lib/common/src/logs/logs.d.ts +123 -5
- package/lib/common/src/logs/logs.js +218 -130
- package/lib/common/src/logs/logsController.d.ts +3 -0
- package/lib/common/src/styles/tokens.d.ts +7 -6
- package/lib/common/src/styles/tokens.js +8 -5
- package/lib/common/src/utils/cache.d.ts +12 -0
- package/lib/common/src/utils/cache.js +0 -0
- package/lib/common/src/utils/fixedOrder.d.ts +15 -0
- package/lib/common/src/utils/fixedOrder.js +30 -0
- package/lib/common/src/utils/index.d.ts +2 -0
- package/lib/common/src/utils/index.js +2 -0
- package/lib/common/src/utils/memoryStore.d.ts +3 -6
- package/lib/common/src/utils/memoryStore.js +1 -3
- package/lib/common/src/utils/persistedMaps.d.ts +16 -0
- package/lib/common/src/utils/persistedMaps.js +5 -0
- package/lib/common/src/utils/searchHistory.js +7 -6
- package/lib/common/src/utils/structEqual.d.ts +12 -0
- package/lib/common/src/utils/structEqual.js +40 -0
- package/lib/common/updateBy.d.ts +3 -0
- package/lib/common/updateBy.js +57 -22
- package/lib/style/menuRight.css +29 -23
- package/lib/style/style.css +73 -10
- package/lib/style/tokens.css +8 -4
- package/package.json +3 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { copyToClipboard, Params, timeLocalToStr_hhmmss } from "wenay-common2";
|
|
4
4
|
import { renderBy, updateBy } from "../../updateBy";
|
|
5
5
|
import { contextMenu } from "../menu/menuMouse";
|
|
@@ -19,32 +19,50 @@ const datumMiniConst = {
|
|
|
19
19
|
const settingLogs = { params: Params.GetSimpleParams(getSettingLogs()) };
|
|
20
20
|
const logGridDefaultColDef = { ...colDefCentered, wrapText: true };
|
|
21
21
|
// varMin - minimum importance
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
// Each call builds its OWN state (fresh map, fresh mini feed, own settings - persisted under
|
|
23
|
+
// setting.settingsKey when provided). The global logsApi below injects the legacy module-level
|
|
24
|
+
// state explicitly, so existing consumers of datumConst/datumMiniConst/"settingLogs" keep
|
|
25
|
+
// seeing the same objects as before.
|
|
26
|
+
export function getLogsApi(setting, sharedState) {
|
|
27
|
+
const state = sharedState ?? createLogsControllerState({
|
|
28
|
+
settings: setting.settingsKey
|
|
29
|
+
? memoryGetOrCreate(setting.settingsKey, { params: Params.GetSimpleParams(getSettingLogs()) })
|
|
30
|
+
: undefined,
|
|
31
|
+
});
|
|
24
32
|
const controller = createLogsController({
|
|
25
33
|
options: setting,
|
|
26
|
-
state
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}),
|
|
31
|
-
onFullChange: () => renderBy(datumConst),
|
|
32
|
-
onMiniChange: () => renderBy(datumMiniConst),
|
|
33
|
-
onSettingsChange: () => renderBy(datum),
|
|
34
|
+
state,
|
|
35
|
+
onFullChange: () => renderBy(state.full),
|
|
36
|
+
onMiniChange: () => renderBy(state.mini),
|
|
37
|
+
onSettingsChange: () => renderBy(state.settings),
|
|
34
38
|
});
|
|
39
|
+
// legacy module state -> keep the exact same component identities as before;
|
|
40
|
+
// custom instances get views bound to THEIR state via closures
|
|
41
|
+
const usesLegacyState = state.full === datumConst
|
|
42
|
+
&& state.mini === datumMiniConst;
|
|
43
|
+
const Setting = usesLegacyState ? InputSettingLogs
|
|
44
|
+
: (props) => _jsx(InputSettingLogs, { ...props, settings: state.settings });
|
|
45
|
+
const Message = usesLegacyState ? MessageEventLogs
|
|
46
|
+
: (props) => _jsx(MessageEventLogs, { ...props, settings: state.settings, mini: state.mini });
|
|
47
|
+
const Page = usesLegacyState ? PageLogs
|
|
48
|
+
: (props) => _jsx(PageLogs, { ...props, state: state });
|
|
35
49
|
return {
|
|
36
50
|
addLogs: controller.addLogs,
|
|
37
51
|
params: controller.params,
|
|
38
52
|
React: {
|
|
39
|
-
Setting:
|
|
40
|
-
Message:
|
|
41
|
-
PageLogs:
|
|
53
|
+
Setting: Setting,
|
|
54
|
+
Message: Message,
|
|
55
|
+
PageLogs: Page
|
|
42
56
|
}
|
|
43
57
|
};
|
|
44
58
|
}
|
|
45
|
-
export const logsApi = getLogsApi({ limitPer: 500 }
|
|
46
|
-
|
|
47
|
-
|
|
59
|
+
export const logsApi = getLogsApi({ limitPer: 500 }, {
|
|
60
|
+
full: datumConst,
|
|
61
|
+
mini: datumMiniConst,
|
|
62
|
+
settings: memoryGetOrCreate("settingLogs", settingLogs),
|
|
63
|
+
});
|
|
64
|
+
function InputSettingLogs({ settings }) {
|
|
65
|
+
const datum = settings ?? memoryGetOrCreate("settingLogs", settingLogs);
|
|
48
66
|
return _jsx(ParamsEditor
|
|
49
67
|
// @ts-ignore
|
|
50
68
|
, {
|
|
@@ -54,106 +72,124 @@ function InputSettingLogs({}) {
|
|
|
54
72
|
renderBy(datum);
|
|
55
73
|
} });
|
|
56
74
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
75
|
+
/** Controller for the full-page logs table: owns the ag-grid imperative surface that
|
|
76
|
+
* `PageLogs` used to drive inline. The importance filter lives in ONE method
|
|
77
|
+
* (`applyImportanceFilter`) - it used to be duplicated between the settings effect and
|
|
78
|
+
* `onGridReady`. Rows keep the original identity semantics: the grid receives the mount-time
|
|
79
|
+
* snapshot once, later entries arrive as `applyTransactionAsync` copies of the mini feed. */
|
|
80
|
+
export function useLogsPageTable(state) {
|
|
81
|
+
const setting = state?.settings ?? memoryGetOrCreate("settingLogs", settingLogs);
|
|
82
|
+
const full = state?.full ?? datumConst;
|
|
83
|
+
const mini = state?.mini ?? datumMiniConst;
|
|
62
84
|
const apiGrid = useRef(null);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
85
|
+
// mount-time snapshot: the live grid is fed by transactions, not re-renders
|
|
86
|
+
const [rowData] = useState(() => [...full.map.values()].flat());
|
|
87
|
+
const getApi = useCallback(() => apiGrid.current, []);
|
|
88
|
+
const fit = useCallback(() => { apiGrid.current?.api.sizeColumnsToFit(); }, []);
|
|
89
|
+
const applyImportanceFilter = useCallback((min) => {
|
|
90
|
+
const api = apiGrid.current?.api;
|
|
91
|
+
if (!api)
|
|
92
|
+
return;
|
|
93
|
+
if (min) {
|
|
94
|
+
api.setFilterModel({
|
|
69
95
|
var: {
|
|
70
96
|
filterType: 'number',
|
|
71
97
|
type: 'greaterThanOrEqual',
|
|
72
|
-
filter:
|
|
98
|
+
filter: min
|
|
73
99
|
}
|
|
74
100
|
});
|
|
75
101
|
}
|
|
76
102
|
else {
|
|
77
|
-
|
|
103
|
+
api.destroyFilter("var");
|
|
78
104
|
}
|
|
105
|
+
}, []);
|
|
106
|
+
const appendRow = useCallback((row) => {
|
|
107
|
+
apiGrid.current?.api.applyTransactionAsync({ add: [row] });
|
|
108
|
+
}, []);
|
|
109
|
+
// settings change -> single filter method (no re-render: updateBy with a callback)
|
|
110
|
+
updateBy(setting, () => {
|
|
111
|
+
applyImportanceFilter(setting.params.minVarLogs);
|
|
79
112
|
});
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
});
|
|
86
|
-
}
|
|
113
|
+
// new mini-feed entry -> async append, copy like before (row identity per event)
|
|
114
|
+
updateBy(mini, () => {
|
|
115
|
+
const data = mini.last[0];
|
|
116
|
+
if (data)
|
|
117
|
+
appendRow({ ...data });
|
|
87
118
|
});
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
{
|
|
148
|
-
name: "copy", actionKey: "logs.copyCell", onClick: () => { copyToClipboard(e.value); }
|
|
149
|
-
}
|
|
150
|
-
]);
|
|
119
|
+
const onGridReady = useCallback((a) => {
|
|
120
|
+
apiGrid.current = a;
|
|
121
|
+
fit();
|
|
122
|
+
// fresh grid has no filter - only apply when the setting asks for one
|
|
123
|
+
if (setting.params.minVarLogs)
|
|
124
|
+
applyImportanceFilter(setting.params.minVarLogs);
|
|
125
|
+
}, [applyImportanceFilter, fit, setting]);
|
|
126
|
+
const columnDefs = useMemo(() => [
|
|
127
|
+
{
|
|
128
|
+
field: "time",
|
|
129
|
+
sort: "desc",
|
|
130
|
+
width: 50,
|
|
131
|
+
valueFormatter: (e) => e.value ? timeLocalToStr_hhmmss(e.value) : e.value
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
field: "id",
|
|
135
|
+
width: 20,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
field: "var",
|
|
139
|
+
width: 50,
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
field: "type1",
|
|
143
|
+
width: 50,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
field: "type2",
|
|
147
|
+
width: 50,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
field: "type3",
|
|
151
|
+
width: 50,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
field: "txt",
|
|
155
|
+
wrapText: true,
|
|
156
|
+
autoHeight: true,
|
|
157
|
+
width: 350
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
field: "address",
|
|
161
|
+
width: 150,
|
|
162
|
+
},
|
|
163
|
+
], []);
|
|
164
|
+
const gridProps = useMemo(() => ({
|
|
165
|
+
suppressCellFocus: true,
|
|
166
|
+
onGridReady,
|
|
167
|
+
defaultColDef: logGridDefaultColDef,
|
|
168
|
+
headerHeight: 30,
|
|
169
|
+
rowHeight: 26,
|
|
170
|
+
autoSizePadding: 1,
|
|
171
|
+
rowData,
|
|
172
|
+
columnDefs,
|
|
173
|
+
onCellMouseDown: (e) => {
|
|
174
|
+
if (e.event instanceof MouseEvent && e.event.button == 2) {
|
|
175
|
+
contextMenu.openAt(e.event, [
|
|
176
|
+
{
|
|
177
|
+
name: "copy", actionKey: "logs.copyCell", onClick: () => { copyToClipboard(e.value); }
|
|
151
178
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
179
|
+
]);
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
}), [columnDefs, onGridReady, rowData]);
|
|
183
|
+
return { getApi, fit, applyImportanceFilter, appendRow, onGridReady, columnDefs, gridProps };
|
|
155
184
|
}
|
|
156
|
-
function
|
|
185
|
+
export function PageLogs({ update, state }) {
|
|
186
|
+
const table = useLogsPageTable(state);
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
table.fit();
|
|
189
|
+
}, [update]);
|
|
190
|
+
return _jsx("div", { className: "maxSize", children: _jsx(AgGridTable, { ...table.gridProps }) });
|
|
191
|
+
}
|
|
192
|
+
export function MessageEventLogCard({ logs }) {
|
|
157
193
|
return _jsxs("div", { className: "testAnime", style: { width: "200px", color: logStyleTokens.text, height: "auto", marginTop: "10px", borderRight: `5px solid ${logStyleTokens.accent}`, background: logSeverityBackground(logs.var) }, children: [_jsx("p", { style: { textAlign: "center", fontSize: "10px", marginBottom: "1px" }, children: "notification" }), _jsx("hr", { style: {
|
|
158
194
|
backgroundImage: logDividerGradient(),
|
|
159
195
|
border: 0,
|
|
@@ -161,35 +197,87 @@ function Message({ logs }) {
|
|
|
161
197
|
margin: "0 0 0 0",
|
|
162
198
|
boxSizing: "content-box",
|
|
163
199
|
display: "block"
|
|
164
|
-
} }), _jsx("div", { style: { textAlign: "right", marginRight: "10px", height: "auto", overflowWrap: "break-word", textOverflow: "ellipsis" }, children: typeof logs.txt == "object" ? JSON.stringify(logs.txt) : logs.txt }), _jsx("p", { style: { float: "inline-end", textAlign: "right", marginRight: "10px" }, children: (new Date()).toLocaleDateString() })] });
|
|
200
|
+
} }), _jsx("div", { style: { textAlign: "right", marginRight: "10px", height: "auto", overflowWrap: "break-word", textOverflow: "ellipsis" }, children: typeof logs.txt == "object" ? JSON.stringify(logs.txt) : logs.txt }), _jsx("p", { style: { float: "inline-end", textAlign: "right", marginRight: "10px" }, children: (new Date(logs.time)).toLocaleDateString() })] });
|
|
165
201
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
202
|
+
export function useMessageEventLogsController(options = {}) {
|
|
203
|
+
const setting = options.settings ?? memoryGetOrCreate("settingLogs", settingLogs);
|
|
204
|
+
const mini = options.mini ?? datumMiniConst;
|
|
205
|
+
const maxVisible = Math.max(1, options.maxVisible ?? 10);
|
|
206
|
+
const [notifications, setNotifications] = useState([]);
|
|
207
|
+
const counterRef = useRef(0);
|
|
208
|
+
const lastLogRef = useRef(null);
|
|
209
|
+
const timersRef = useRef(new Map());
|
|
210
|
+
updateBy(setting);
|
|
211
|
+
const addNotification = useCallback((last) => {
|
|
212
|
+
if ((last.var ?? 0) < (setting.params.minVarMessage ?? 0))
|
|
174
213
|
return;
|
|
175
|
-
|
|
214
|
+
const key = String(counterRef.current++);
|
|
215
|
+
const item = { key, logs: last };
|
|
216
|
+
const displayMs = (setting.params.timeShow ? setting.params.timeShow : 2) * 1000;
|
|
217
|
+
setNotifications(prev => [item, ...prev]);
|
|
218
|
+
const timer = setTimeout(() => {
|
|
219
|
+
timersRef.current.delete(key);
|
|
220
|
+
setNotifications(prev => prev.filter(e => e.key !== key));
|
|
221
|
+
}, displayMs);
|
|
222
|
+
timersRef.current.set(key, timer);
|
|
223
|
+
}, [setting]);
|
|
224
|
+
const onMiniChange = useCallback(() => {
|
|
225
|
+
const last = mini.last[0];
|
|
226
|
+
if (!last || last === lastLogRef.current)
|
|
176
227
|
return;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
228
|
+
lastLogRef.current = last;
|
|
229
|
+
addNotification(last);
|
|
230
|
+
}, [addNotification, mini]);
|
|
231
|
+
updateBy(mini, onMiniChange);
|
|
232
|
+
useEffect(() => () => {
|
|
233
|
+
timersRef.current.forEach(clearTimeout);
|
|
234
|
+
timersRef.current.clear();
|
|
235
|
+
}, []);
|
|
236
|
+
const setShow = useCallback((value) => {
|
|
237
|
+
// LogsSettingsState.params is readonly at the type level; keep the legacy in-place mutation
|
|
238
|
+
;
|
|
239
|
+
setting.params.show = value;
|
|
240
|
+
renderBy(setting);
|
|
241
|
+
}, [setting]);
|
|
242
|
+
const toggleShow = useCallback(() => {
|
|
243
|
+
setShow(!setting.params.show);
|
|
244
|
+
}, [setShow, setting]);
|
|
245
|
+
return useMemo(() => ({
|
|
246
|
+
show: Boolean(setting.params.show),
|
|
247
|
+
setShow,
|
|
248
|
+
toggleShow,
|
|
249
|
+
notifications,
|
|
250
|
+
visibleNotifications: notifications.slice(0, maxVisible),
|
|
251
|
+
maxVisible,
|
|
252
|
+
}), [maxVisible, notifications, setShow, setting.params.show, toggleShow]);
|
|
253
|
+
}
|
|
254
|
+
export function MessageEventLogsView({ controller, zIndex, className, style }) {
|
|
255
|
+
const toggleTitle = controller.show ? "Hide log notifications" : "Show log notifications";
|
|
256
|
+
const toggleStyle = {
|
|
257
|
+
position: "absolute",
|
|
258
|
+
right: 0,
|
|
259
|
+
top: 0,
|
|
260
|
+
zIndex: 120,
|
|
261
|
+
minWidth: controller.show ? 24 : 42,
|
|
262
|
+
height: 24,
|
|
263
|
+
padding: controller.show ? 0 : "0 8px",
|
|
264
|
+
border: `1px solid ${logStyleTokens.accent}`,
|
|
265
|
+
borderRadius: 999,
|
|
266
|
+
background: controller.show ? logStyleTokens.toggleBg : logStyleTokens.toggleOffBg,
|
|
267
|
+
color: logStyleTokens.text,
|
|
268
|
+
cursor: "pointer",
|
|
269
|
+
display: "inline-flex",
|
|
270
|
+
alignItems: "center",
|
|
271
|
+
justifyContent: "center",
|
|
272
|
+
fontSize: controller.show ? 18 : 12,
|
|
273
|
+
lineHeight: 1,
|
|
274
|
+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.35)",
|
|
275
|
+
};
|
|
276
|
+
return _jsxs("div", { className: className, style: { maxHeight: "50vh", position: "absolute", right: "1px", zIndex, ...style }, children: [_jsx("button", { type: "button", "aria-label": toggleTitle, title: toggleTitle, onClick: controller.toggleShow, style: toggleStyle, children: controller.show ? "\u00d7" : "log" }), _jsx("div", { children: controller.show ? controller.visibleNotifications.map(e => (_jsx("div", { className: "example-exit", children: _jsx(MessageEventLogCard, { logs: e.logs }) }, e.key))) : null })] });
|
|
277
|
+
}
|
|
278
|
+
export function MessageEventLogs({ zIndex, settings, mini }) {
|
|
279
|
+
const controller = useMessageEventLogsController({ settings, mini });
|
|
280
|
+
return _jsx(MessageEventLogsView, { controller: controller, zIndex: zIndex });
|
|
193
281
|
}
|
|
194
282
|
const defPageBase = {
|
|
195
283
|
keyPage: "PageLogs"
|
|
@@ -12,6 +12,9 @@ export type LogsApiOptions = {
|
|
|
12
12
|
limit?: number;
|
|
13
13
|
limitPer: number;
|
|
14
14
|
varMin?: number;
|
|
15
|
+
/** memoryGetOrCreate key for this instance's settings; without it a fresh
|
|
16
|
+
* (non-persisted) settings object is used. The global logsApi keeps "settingLogs". */
|
|
17
|
+
settingsKey?: string;
|
|
15
18
|
};
|
|
16
19
|
export declare const getSettingLogs: () => {
|
|
17
20
|
minVarLogs: {
|
|
@@ -10,19 +10,20 @@ export declare const tokens: {
|
|
|
10
10
|
readonly borderCommon: "rgb(50, 62, 71)";
|
|
11
11
|
};
|
|
12
12
|
readonly menu: {
|
|
13
|
-
readonly bgColor: "
|
|
14
|
-
readonly blur: "
|
|
13
|
+
readonly bgColor: "#0c0c0c";
|
|
14
|
+
readonly blur: "0px";
|
|
15
15
|
readonly border: "1px solid rgba(255, 255, 255, 0.41)";
|
|
16
|
-
readonly activeBackground: "
|
|
16
|
+
readonly activeBackground: "#262626";
|
|
17
17
|
readonly itemColor: "#fff";
|
|
18
|
+
readonly itemActiveBgColor: "#262626";
|
|
19
|
+
readonly itemActiveColor: "#fff";
|
|
18
20
|
readonly itemHoverColor: "#101010";
|
|
19
21
|
readonly itemHoverBgColor: "#fff";
|
|
22
|
+
readonly itemPressedColor: "#101010";
|
|
23
|
+
readonly itemPressedBgColor: "#f2c94c";
|
|
20
24
|
readonly outlineColor: "#007bff";
|
|
21
25
|
readonly shadow: "0 0 20px 14px rgba(34, 60, 80, 0.2)";
|
|
22
26
|
};
|
|
23
|
-
/** FloatingWindow window chrome (--wnd-*). Defaults = legacy look; apps re-skin via :root[data-theme].
|
|
24
|
-
* --wnd-header-height/color/font-size/letter-spacing/transform are intentionally undeclared
|
|
25
|
-
* (inherit/auto) until a theme sets them. */
|
|
26
27
|
readonly wnd: {
|
|
27
28
|
readonly bg: "transparent";
|
|
28
29
|
readonly border: "none";
|
|
@@ -12,17 +12,20 @@ export const tokens = {
|
|
|
12
12
|
borderCommon: 'rgb(50, 62, 71)',
|
|
13
13
|
},
|
|
14
14
|
menu: {
|
|
15
|
-
bgColor: '
|
|
16
|
-
blur: '
|
|
15
|
+
bgColor: '#0c0c0c',
|
|
16
|
+
blur: '0px',
|
|
17
17
|
border: '1px solid rgba(255, 255, 255, 0.41)',
|
|
18
|
-
activeBackground: '
|
|
18
|
+
activeBackground: '#262626',
|
|
19
19
|
itemColor: '#fff',
|
|
20
|
+
itemActiveBgColor: '#262626',
|
|
21
|
+
itemActiveColor: '#fff',
|
|
20
22
|
itemHoverColor: '#101010',
|
|
21
23
|
itemHoverBgColor: '#fff',
|
|
24
|
+
itemPressedColor: '#101010',
|
|
25
|
+
itemPressedBgColor: '#f2c94c',
|
|
22
26
|
outlineColor: '#007bff',
|
|
23
27
|
shadow: '0 0 20px 14px rgba(34, 60, 80, 0.2)',
|
|
24
|
-
},
|
|
25
|
-
/** FloatingWindow window chrome (--wnd-*). Defaults = legacy look; apps re-skin via :root[data-theme].
|
|
28
|
+
}, /** FloatingWindow window chrome (--wnd-*). Defaults = legacy look; apps re-skin via :root[data-theme].
|
|
26
29
|
* --wnd-header-height/color/font-size/letter-spacing/transform are intentionally undeclared
|
|
27
30
|
* (inherit/auto) until a theme sets them. */
|
|
28
31
|
wnd: {
|
|
@@ -46,3 +46,15 @@ export declare function createCacheMap(arr: [k: string, v: Map<string, unknown>]
|
|
|
46
46
|
isDirty(): boolean;
|
|
47
47
|
getArr: [k: string, v: Map<string, unknown>][];
|
|
48
48
|
};
|
|
49
|
+
export type CacheMap = ReturnType<typeof createCacheMapWithStorage>;
|
|
50
|
+
/** The app-side persistence contract as one hook: load() on mount, then subscribe the dirty
|
|
51
|
+
* channel to saveDebounced(delay). The app still owns the write policy - this only wires the
|
|
52
|
+
* documented default (`doc/EXAMPLE_USAGE.md`). Returns pass-through methods for the rare
|
|
53
|
+
* imperative needs; `reload` is an explicit alias of `load` (a second load() merges storage
|
|
54
|
+
* on top of current maps - it is not a reset). */
|
|
55
|
+
export declare function useCacheMapPersistence(cache: CacheMap, delay?: number): {
|
|
56
|
+
isDirty: () => boolean;
|
|
57
|
+
flush: () => Promise<void>;
|
|
58
|
+
save: () => Promise<void>;
|
|
59
|
+
reload: () => Promise<void>;
|
|
60
|
+
};
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Shared "fixed entries pin back to their descriptor index" invariant.
|
|
2
|
+
*
|
|
3
|
+
* columnState.normalize(), ColumnsMenu.movedOrder(), Toolbar.normalize() and
|
|
4
|
+
* Toolbar.Settings.movedOrder() used to inline byte-identical copies of this idiom, with
|
|
5
|
+
* comments demanding they stay in sync (the drag preview must land exactly where the commit
|
|
6
|
+
* does). One implementation makes that invariant structural instead of disciplinary. */
|
|
7
|
+
export type FixedOrderDescriptor = {
|
|
8
|
+
key: string;
|
|
9
|
+
fixed?: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** Drop fixed keys from `order`, then pin every fixed descriptor back at its descriptor index. */
|
|
12
|
+
export declare function pinFixedOrder(order: readonly string[], descriptors: readonly FixedOrderDescriptor[]): string[];
|
|
13
|
+
/** The shared drag preview: splice-move `key` to index `to`, then re-pin fixed entries.
|
|
14
|
+
* Same result as committing the move through normalize(). */
|
|
15
|
+
export declare function movedOrderWithFixed(order: readonly string[], key: string, to: number, descriptors: readonly FixedOrderDescriptor[]): string[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Shared "fixed entries pin back to their descriptor index" invariant.
|
|
2
|
+
*
|
|
3
|
+
* columnState.normalize(), ColumnsMenu.movedOrder(), Toolbar.normalize() and
|
|
4
|
+
* Toolbar.Settings.movedOrder() used to inline byte-identical copies of this idiom, with
|
|
5
|
+
* comments demanding they stay in sync (the drag preview must land exactly where the commit
|
|
6
|
+
* does). One implementation makes that invariant structural instead of disciplinary. */
|
|
7
|
+
/** Drop fixed keys from `order`, then pin every fixed descriptor back at its descriptor index. */
|
|
8
|
+
export function pinFixedOrder(order, descriptors) {
|
|
9
|
+
const fixed = new Set();
|
|
10
|
+
for (const d of descriptors)
|
|
11
|
+
if (d.fixed)
|
|
12
|
+
fixed.add(d.key);
|
|
13
|
+
const res = order.filter(k => !fixed.has(k));
|
|
14
|
+
descriptors.forEach(function pinFixed(d, i) {
|
|
15
|
+
if (d.fixed)
|
|
16
|
+
res.splice(Math.min(i, res.length), 0, d.key);
|
|
17
|
+
});
|
|
18
|
+
return res;
|
|
19
|
+
}
|
|
20
|
+
/** The shared drag preview: splice-move `key` to index `to`, then re-pin fixed entries.
|
|
21
|
+
* Same result as committing the move through normalize(). */
|
|
22
|
+
export function movedOrderWithFixed(order, key, to, descriptors) {
|
|
23
|
+
const next = order.slice();
|
|
24
|
+
const from = next.indexOf(key);
|
|
25
|
+
if (from == -1)
|
|
26
|
+
return next;
|
|
27
|
+
next.splice(from, 1);
|
|
28
|
+
next.splice(Math.max(0, Math.min(next.length, to)), 0, key);
|
|
29
|
+
return pinFixedOrder(next, descriptors);
|
|
30
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export * from './gridRows';
|
|
2
2
|
export * from './arrayPromise';
|
|
3
3
|
export * from './cache';
|
|
4
|
+
export * from './fixedOrder';
|
|
4
5
|
export * from './callbackHub';
|
|
5
6
|
export * from './inputAutoStep';
|
|
6
7
|
export * from './memoryStore';
|
|
7
8
|
export * from './observableMap';
|
|
8
9
|
export * from './pageVisibilityContext';
|
|
9
10
|
export * from './searchHistory';
|
|
11
|
+
export * from './structEqual';
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export * from './gridRows';
|
|
2
2
|
export * from './arrayPromise';
|
|
3
3
|
export * from './cache';
|
|
4
|
+
export * from './fixedOrder';
|
|
4
5
|
export * from './callbackHub';
|
|
5
6
|
export * from './inputAutoStep';
|
|
6
7
|
export * from './memoryStore';
|
|
7
8
|
export * from './observableMap';
|
|
8
9
|
export * from './pageVisibilityContext';
|
|
9
10
|
export * from './searchHistory';
|
|
11
|
+
export * from './structEqual';
|
|
@@ -27,11 +27,8 @@ 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, import("../components/Dnd
|
|
31
|
-
resize: ObservableMap<string,
|
|
32
|
-
|
|
33
|
-
width?: number | string;
|
|
34
|
-
}>;
|
|
35
|
-
rightMenu: ObservableMap<string, import("../components/Menu/RightMenuStore").MenuRightSavedState>;
|
|
30
|
+
rnd: ObservableMap<string, import("../components/Dnd").FloatingWindowSavedGeometry>;
|
|
31
|
+
resize: ObservableMap<string, import("./persistedMaps").ResizableSavedSize>;
|
|
32
|
+
rightMenu: ObservableMap<string, import("../components/Menu").MenuRightSavedState>;
|
|
36
33
|
other: ObservableMap<string, object>;
|
|
37
34
|
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { deepClone } from "wenay-common2";
|
|
2
2
|
import { renderBy } from "../../updateBy";
|
|
3
|
-
import { floatingWindowMap } from "
|
|
4
|
-
import { mapResiReact } from "../components/Dnd/Resizable";
|
|
5
|
-
import { mapRightMenu } from "../components/Menu/RightMenuStore";
|
|
3
|
+
import { floatingWindowMap, mapResiReact, mapRightMenu } from "./persistedMaps";
|
|
6
4
|
import { createCacheMap } from "./cache";
|
|
7
5
|
import { ObservableMap } from "./observableMap";
|
|
8
6
|
// observable - memoryCache marks itself dirty on its mutations
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ObservableMap } from "./observableMap";
|
|
2
|
+
import type { FloatingWindowSavedGeometry } from "../components/Dnd/FloatingWindow";
|
|
3
|
+
import type { MenuRightSavedState } from "../components/Menu/RightMenuStore";
|
|
4
|
+
/** Persisted-state maps live in a utils LEAF so the runtime dependency graph points one way:
|
|
5
|
+
* owning components import their map from here, and memoryStore assembles the memoryCache
|
|
6
|
+
* registry without reaching up into the component layer (it used to import FloatingWindow/
|
|
7
|
+
* Resizable/RightMenuStore, dragging react-rnd and the Menu tree into every utils consumer).
|
|
8
|
+
* The `import type` lines above are erased at build - shapes stay documented at their owners. */
|
|
9
|
+
/** Saved size of an FResizableReact column/box; the shape the resize layer persists. */
|
|
10
|
+
export type ResizableSavedSize = {
|
|
11
|
+
height?: number | string;
|
|
12
|
+
width?: number | string;
|
|
13
|
+
};
|
|
14
|
+
export declare const floatingWindowMap: ObservableMap<string, FloatingWindowSavedGeometry>;
|
|
15
|
+
export declare const mapResiReact: ObservableMap<string, ResizableSavedSize>;
|
|
16
|
+
export declare const mapRightMenu: ObservableMap<string, MenuRightSavedState>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ObservableMap } from "./observableMap";
|
|
2
|
+
// observable - memoryCache marks itself dirty on their mutations
|
|
3
|
+
export const floatingWindowMap = new ObservableMap();
|
|
4
|
+
export const mapResiReact = new ObservableMap();
|
|
5
|
+
export const mapRightMenu = new ObservableMap();
|