wenay-react2 1.0.20 → 1.0.21
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 +383 -382
- package/lib/common/api.d.ts +28 -0
- package/lib/common/api.js +41 -16
- package/lib/common/src/components/Buttons/MiniButton.d.ts +1 -0
- package/lib/common/src/components/Buttons/MiniButton.js +2 -2
- package/lib/common/src/components/Dnd/DraggableOutlineDiv.d.ts +1 -0
- package/lib/common/src/components/Dnd/DraggableOutlineDiv.js +7 -6
- package/lib/common/src/components/Dnd/RNDFunc.js +28 -17
- package/lib/common/src/components/Dnd/RNDFunc3.d.ts +27 -17
- package/lib/common/src/components/Dnd/RNDFunc3.js +107 -105
- package/lib/common/src/components/Dnd/Resizable.js +3 -3
- package/lib/common/src/components/Menu/RightMenu.js +11 -17
- package/lib/common/src/components/Menu/StickerMenu.js +42 -28
- package/lib/common/src/components/Menu/index.d.ts +1 -1
- package/lib/common/src/components/Menu/index.js +1 -1
- package/lib/common/src/components/Modal/LeftModal.d.ts +14 -12
- package/lib/common/src/components/Modal/LeftModal.js +30 -16
- package/lib/common/src/components/Modal/Modal.d.ts +26 -12
- package/lib/common/src/components/Modal/Modal.js +66 -89
- package/lib/common/src/components/Modal/ModalContextProvider.d.ts +20 -3
- package/lib/common/src/components/Modal/ModalContextProvider.js +35 -8
- package/lib/common/src/components/MyResizeObserver.js +15 -18
- package/lib/common/src/components/Other.js +3 -2
- package/lib/common/src/components/Parameters.js +7 -6
- package/lib/common/src/components/ParametersEngine.js +25 -54
- package/lib/common/src/grid/agGrid4/agGrid4.d.ts +53 -0
- package/lib/common/src/grid/agGrid4/agGrid4.js +132 -0
- package/lib/common/src/grid/agGrid4/core.d.ts +56 -0
- package/lib/common/src/grid/agGrid4/core.js +127 -0
- package/lib/common/src/grid/agGrid4/index.d.ts +6 -0
- package/lib/common/src/grid/agGrid4/index.js +3 -0
- package/lib/common/src/grid/agGrid4/theme.d.ts +7 -0
- package/lib/common/src/grid/agGrid4/theme.js +18 -0
- package/lib/common/src/hooks/useAddDownAnyKey.d.ts +21 -2
- package/lib/common/src/hooks/useAddDownAnyKey.js +46 -8
- package/lib/common/src/hooks/useDraggable.d.ts +20 -2
- package/lib/common/src/hooks/useDraggable.js +146 -115
- package/lib/common/src/hooks/useOutside.d.ts +24 -4
- package/lib/common/src/hooks/useOutside.js +76 -27
- package/lib/common/src/logs/logs.d.ts +5 -2
- package/lib/common/src/logs/logs.js +15 -31
- package/lib/common/src/logs/logs3.d.ts +9 -9
- package/lib/common/src/logs/logs3.js +47 -38
- package/lib/common/src/logs/miniLogs.d.ts +3 -3
- package/lib/common/src/logs/miniLogs.js +28 -36
- package/lib/common/src/menu/menu.d.ts +18 -18
- package/lib/common/src/menu/menu.js +48 -24
- package/lib/common/src/menu/menuMouse.js +4 -1
- package/lib/common/src/menu/menuR.d.ts +2 -2
- package/lib/common/src/menu/menuR.js +34 -34
- package/lib/common/src/myChart/1/myChart.d.ts +5 -5
- package/lib/common/src/myChart/1/myChart.js +58 -47
- package/lib/common/src/myChart/1/myChartTest.js +8 -4
- package/lib/common/src/myChart/chartEngine/chartEngineReact.d.ts +24 -27
- package/lib/common/src/myChart/chartEngine/chartEngineReact.js +166 -117
- package/lib/common/src/styles/styleGrid.d.ts +2 -1
- package/lib/common/src/styles/styleGrid.js +10 -12
- package/lib/common/src/styles/tokens.d.ts +39 -0
- package/lib/common/src/styles/tokens.js +40 -0
- package/lib/common/src/utils/applyTransactionAsyncUpdate.d.ts +7 -0
- package/lib/common/src/utils/applyTransactionAsyncUpdate.js +19 -12
- package/lib/common/src/utils/arrayPromise.d.ts +6 -0
- package/lib/common/src/utils/arrayPromise.js +7 -1
- package/lib/common/src/utils/cache.js +24 -21
- package/lib/common/src/utils/inputAutoStep.d.ts +1 -1
- package/lib/common/src/utils/inputAutoStep.js +30 -19
- package/lib/common/src/utils/mapMemory.js +9 -10
- package/lib/common/updateBy.d.ts +21 -2
- package/lib/common/updateBy.js +66 -31
- package/lib/index.js +0 -2
- package/lib/style/menuRight.css +13 -26
- package/lib/style/style.css +51 -39
- package/lib/style/tokens.css +34 -0
- package/package.json +2 -2
|
@@ -1,42 +1,35 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { timeLocalToStr_hhmmss } from "wenay-common2";
|
|
3
3
|
import { AgGridReact } from "ag-grid-react";
|
|
4
|
-
|
|
4
|
+
const columns = [
|
|
5
|
+
{
|
|
6
|
+
field: "time",
|
|
7
|
+
sort: "desc",
|
|
8
|
+
width: 50,
|
|
9
|
+
valueFormatter: (e) => e.value ? timeLocalToStr_hhmmss(e.value) : e.value
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
field: "id",
|
|
13
|
+
width: 20,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
field: "var",
|
|
17
|
+
width: 50,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
field: "txt",
|
|
21
|
+
wrapText: true,
|
|
22
|
+
autoHeight: true,
|
|
23
|
+
width: 350
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
field: "address",
|
|
27
|
+
width: 150,
|
|
28
|
+
},
|
|
29
|
+
];
|
|
5
30
|
export function MiniLogs({ data, onClick }) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
{
|
|
9
|
-
field: "time",
|
|
10
|
-
sort: "desc",
|
|
11
|
-
width: 50,
|
|
12
|
-
valueFormatter: (e) => e.value ? timeLocalToStr_hhmmss(e.value) : e.value
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
field: "id",
|
|
16
|
-
width: 20,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
field: "var",
|
|
20
|
-
width: 50,
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
field: "txt",
|
|
24
|
-
wrapText: true,
|
|
25
|
-
autoHeight: true,
|
|
26
|
-
width: 350
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
field: "address",
|
|
30
|
-
width: 150,
|
|
31
|
-
},
|
|
32
|
-
];
|
|
33
|
-
return _jsx("div", { className: "maxSize", children: _jsx(AgGridReact
|
|
34
|
-
// className = "ag-theme-alpine-dark ag-theme-alpine2" // ag-theme-alpine-dark3
|
|
35
|
-
, {
|
|
36
|
-
// className = "ag-theme-alpine-dark ag-theme-alpine2" // ag-theme-alpine-dark3
|
|
37
|
-
suppressCellFocus: true, onGridReady: (a) => {
|
|
38
|
-
apiGrid.current = a; //as GridReadyEvent<tColum>
|
|
39
|
-
apiGrid.current.api.sizeColumnsToFit();
|
|
31
|
+
return _jsx("div", { className: "maxSize", children: _jsx(AgGridReact, { suppressCellFocus: true, onGridReady: (a) => {
|
|
32
|
+
a.api.sizeColumnsToFit();
|
|
40
33
|
}, defaultColDef: {
|
|
41
34
|
headerClass: () => ("gridTable-header"),
|
|
42
35
|
resizable: true,
|
|
@@ -45,7 +38,6 @@ export function MiniLogs({ data, onClick }) {
|
|
|
45
38
|
filter: true,
|
|
46
39
|
wrapText: true,
|
|
47
40
|
}, headerHeight: 30, rowHeight: 26, autoSizePadding: 1, rowData: data, columnDefs: columns, onCellMouseDown: (e) => {
|
|
48
|
-
// @ts-ignore
|
|
49
41
|
onClick?.(e);
|
|
50
42
|
} }) });
|
|
51
43
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { ReactElement } from 'react';
|
|
2
2
|
/*******************************************************
|
|
3
|
-
*
|
|
3
|
+
* Menu data types
|
|
4
4
|
*******************************************************/
|
|
5
5
|
export type tMenuReactStrictly<T = any> = {
|
|
6
6
|
name: string | ((status?: T) => string);
|
|
@@ -15,7 +15,7 @@ export type tMenuReactStrictly<T = any> = {
|
|
|
15
15
|
};
|
|
16
16
|
export type tMenuReact<T = any> = tMenuReactStrictly<T> | false | null | undefined;
|
|
17
17
|
/*******************************************************
|
|
18
|
-
*
|
|
18
|
+
* Helper type
|
|
19
19
|
*******************************************************/
|
|
20
20
|
type tCounters = {
|
|
21
21
|
ok?: number;
|
|
@@ -23,13 +23,13 @@ type tCounters = {
|
|
|
23
23
|
count?: number;
|
|
24
24
|
};
|
|
25
25
|
/*******************************************************
|
|
26
|
-
*
|
|
26
|
+
* Displays counter/progress with animation and ok/error counts
|
|
27
27
|
*******************************************************/
|
|
28
28
|
declare function TimeNum({ data }: {
|
|
29
29
|
data: tCounters;
|
|
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
35
|
data: Pick<tMenuReactStrictly, "onClick" | "active" | "name" | "getStatus">;
|
|
@@ -38,22 +38,22 @@ declare function MenuElement({ data: item, toLeft, className, update, }: {
|
|
|
38
38
|
update: () => void;
|
|
39
39
|
}): ReactElement;
|
|
40
40
|
/*******************************************************
|
|
41
|
-
*
|
|
42
|
-
*
|
|
41
|
+
* MenuBase renders the popup menu with support for
|
|
42
|
+
* nested submenus and their state management.
|
|
43
43
|
*
|
|
44
|
-
* @param {Object} props -
|
|
45
|
-
* @param {Object} [props.coordinate] -
|
|
46
|
-
* @param {number} props.coordinate.x -
|
|
47
|
-
* @param {number} props.coordinate.y -
|
|
48
|
-
* @param {boolean} [props.coordinate.toLeft=false] -
|
|
49
|
-
* @param {number} [props.coordinate.left=0] -
|
|
50
|
-
* @param {tMenuReactStrictly[]} props.data -
|
|
51
|
-
* @param {number} [props.zIndex] -
|
|
52
|
-
* @param {Function} [props.menu] -
|
|
53
|
-
* @param {Function} [props.menuElement] -
|
|
54
|
-
* @param {Function} [props.className] -
|
|
44
|
+
* @param {Object} props - Component props.
|
|
45
|
+
* @param {Object} [props.coordinate] - Menu coordinates and display parameters.
|
|
46
|
+
* @param {number} props.coordinate.x - X coordinate for menu placement.
|
|
47
|
+
* @param {number} props.coordinate.y - Y coordinate for menu placement.
|
|
48
|
+
* @param {boolean} [props.coordinate.toLeft=false] - Whether the menu should be shifted left.
|
|
49
|
+
* @param {number} [props.coordinate.left=0] - Additional left offset when the menu has nested items.
|
|
50
|
+
* @param {tMenuReactStrictly[]} props.data - Array of objects describing menu items.
|
|
51
|
+
* @param {number} [props.zIndex] - Menu z-index for overlap visibility.
|
|
52
|
+
* @param {Function} [props.menu] - Function that generates a custom React element for the whole menu.
|
|
53
|
+
* @param {Function} [props.menuElement] - Function that generates a custom React element for one menu item.
|
|
54
|
+
* @param {Function} [props.className] - Function for assigning CSS classes to menu items.
|
|
55
55
|
*
|
|
56
|
-
* @returns {ReactElement}
|
|
56
|
+
* @returns {ReactElement} Visual menu element.
|
|
57
57
|
*/
|
|
58
58
|
type MenuBaseProps = {
|
|
59
59
|
menu?: (arr: tMenuReact[]) => ReactElement;
|
|
@@ -2,12 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
3
3
|
import { PromiseArrayListen, sleepAsync } from "wenay-common2";
|
|
4
4
|
/*******************************************************
|
|
5
|
-
*
|
|
5
|
+
* Displays counter/progress with animation and ok/error counts
|
|
6
6
|
*******************************************************/
|
|
7
7
|
function TimeNum({ data }) {
|
|
8
|
-
const
|
|
9
|
-
const [count, setCount] = useState(refCounter.current);
|
|
10
|
-
refCounter.current = count;
|
|
8
|
+
const [count, setCount] = useState(0);
|
|
11
9
|
const formatLabel = () => {
|
|
12
10
|
if (!data.ok && !data.error)
|
|
13
11
|
return count;
|
|
@@ -29,13 +27,13 @@ function TimeNum({ data }) {
|
|
|
29
27
|
}, children: formatLabel() }));
|
|
30
28
|
}
|
|
31
29
|
/*******************************************************
|
|
32
|
-
*
|
|
30
|
+
* Main menu element with onClick and counters
|
|
33
31
|
*******************************************************/
|
|
34
32
|
function MenuElement({ data: item, toLeft, className, update, }) {
|
|
35
33
|
const unsubOk = useRef(null);
|
|
36
34
|
const unsubErr = useRef(null);
|
|
37
35
|
useEffect(() => {
|
|
38
|
-
//
|
|
36
|
+
// Unsubscribe on unmount
|
|
39
37
|
return () => {
|
|
40
38
|
unsubOk.current?.();
|
|
41
39
|
unsubErr.current?.();
|
|
@@ -53,24 +51,37 @@ function MenuElement({ data: item, toLeft, className, update, }) {
|
|
|
53
51
|
update();
|
|
54
52
|
return;
|
|
55
53
|
}
|
|
56
|
-
//
|
|
54
|
+
// If this is an array of tasks, promises, or functions
|
|
57
55
|
if (Array.isArray(result)) {
|
|
58
56
|
const tasks = result.filter(Boolean);
|
|
59
|
-
const pa = PromiseArrayListen(tasks); //
|
|
57
|
+
const pa = PromiseArrayListen(tasks); // External helper function
|
|
60
58
|
setProgress({});
|
|
61
59
|
unsubOk.current?.();
|
|
62
60
|
unsubErr.current?.();
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
// clear progress when all tasks settle, same as the single-promise path;
|
|
62
|
+
// previously the counter (and its 30ms interval) lived until unmount
|
|
63
|
+
const onTick = async (countOk, countError, count) => {
|
|
64
|
+
setProgress({ ok: countOk, error: countError, count });
|
|
65
|
+
if (countOk + countError >= count) {
|
|
66
|
+
unsubOk.current?.();
|
|
67
|
+
unsubErr.current?.();
|
|
68
|
+
unsubOk.current = null;
|
|
69
|
+
unsubErr.current = null;
|
|
70
|
+
await sleepAsync(500);
|
|
71
|
+
setProgress(null);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
unsubOk.current = pa.listenOk((data, i, countOk, countError, count) => onTick(countOk, countError, count));
|
|
75
|
+
unsubErr.current = pa.listenError((error, i, countOk, countError, count) => onTick(countOk, countError, count));
|
|
65
76
|
}
|
|
66
|
-
//
|
|
77
|
+
// If this is a single promise
|
|
67
78
|
else if (result instanceof Promise) {
|
|
68
79
|
setProgress({});
|
|
69
80
|
result
|
|
70
81
|
.then(async (val) => {
|
|
71
82
|
if (Array.isArray(val) && val.length) {
|
|
72
|
-
//
|
|
73
|
-
//
|
|
83
|
+
// If an array from Promise.allSettled was returned
|
|
84
|
+
// Count ok/error results
|
|
74
85
|
if (val[0]?.status === "fulfilled" || val[0]?.status === "rejected") {
|
|
75
86
|
const t = { ok: 0, error: 0 };
|
|
76
87
|
val.forEach((res) => {
|
|
@@ -105,15 +116,18 @@ const MenuItemWrapper = ({ item, index, update, className, isLeftAligned, leftPo
|
|
|
105
116
|
const [onFocusMenu, setOnFocusMenu] = useState([]);
|
|
106
117
|
useEffect(() => {
|
|
107
118
|
if (item.status && item.next) {
|
|
119
|
+
let alive = true; // guard: do not set state after unmount or item change
|
|
108
120
|
const result = item.next();
|
|
109
121
|
if (result instanceof Promise) {
|
|
110
122
|
result.then((val) => {
|
|
111
|
-
|
|
123
|
+
if (alive)
|
|
124
|
+
setChildMenu(val.filter(Boolean));
|
|
112
125
|
});
|
|
113
126
|
}
|
|
114
127
|
else {
|
|
115
128
|
setChildMenu(result.filter(Boolean));
|
|
116
129
|
}
|
|
130
|
+
return () => { alive = false; };
|
|
117
131
|
}
|
|
118
132
|
else {
|
|
119
133
|
setChildMenu([]);
|
|
@@ -121,15 +135,18 @@ const MenuItemWrapper = ({ item, index, update, className, isLeftAligned, leftPo
|
|
|
121
135
|
}, [item.status, item.next]);
|
|
122
136
|
useEffect(() => {
|
|
123
137
|
if (item.status && item.func) {
|
|
138
|
+
let alive = true;
|
|
124
139
|
const result = item.func();
|
|
125
140
|
if (result instanceof Promise) {
|
|
126
141
|
result.then((val) => {
|
|
127
|
-
|
|
142
|
+
if (alive)
|
|
143
|
+
setAsyncFuncElement(val);
|
|
128
144
|
});
|
|
129
145
|
}
|
|
130
146
|
else {
|
|
131
147
|
setAsyncFuncElement(result);
|
|
132
148
|
}
|
|
149
|
+
return () => { alive = false; };
|
|
133
150
|
}
|
|
134
151
|
else {
|
|
135
152
|
setAsyncFuncElement(null);
|
|
@@ -137,15 +154,18 @@ const MenuItemWrapper = ({ item, index, update, className, isLeftAligned, leftPo
|
|
|
137
154
|
}, [item.status, item.func]);
|
|
138
155
|
useEffect(() => {
|
|
139
156
|
if (item.status && item.onFocus) {
|
|
157
|
+
let alive = true;
|
|
140
158
|
const result = item.onFocus();
|
|
141
159
|
if (result instanceof Promise) {
|
|
142
160
|
result.then((val) => {
|
|
143
|
-
|
|
161
|
+
if (alive)
|
|
162
|
+
setOnFocusMenu(val.filter(Boolean));
|
|
144
163
|
});
|
|
145
164
|
}
|
|
146
165
|
else {
|
|
147
166
|
setOnFocusMenu(result.filter(Boolean));
|
|
148
167
|
}
|
|
168
|
+
return () => { alive = false; };
|
|
149
169
|
}
|
|
150
170
|
else {
|
|
151
171
|
setOnFocusMenu([]);
|
|
@@ -187,21 +207,28 @@ export function MenuBase({ coordinate = { x: 0, y: 0, toLeft: false, left: 0 },
|
|
|
187
207
|
const [, forceUpdate] = useState(false);
|
|
188
208
|
const update = () => forceUpdate((p) => !p);
|
|
189
209
|
const refMenu = useRef(null);
|
|
190
|
-
const dataMemo = useMemo(() => data.filter(
|
|
210
|
+
const dataMemo = useMemo(() => data.filter(Boolean), [data, data.length]);
|
|
191
211
|
const [top, setTop] = useState(coordinate.y);
|
|
192
212
|
const [leftPos, setLeftPos] = useState(coordinate.x);
|
|
193
213
|
const [menuWidth, setMenuWidth] = useState(0);
|
|
194
214
|
const [isLeftAligned, setIsLeftAligned] = useState(!!coordinate.toLeft);
|
|
195
215
|
const [xOffset, setXOffset] = useState(0);
|
|
216
|
+
// Mirror of applied top: vertical snap is recalculated from the base coordinate.y,
|
|
217
|
+
// not from prev; the setTop(prev + ...) delta formula accumulated between runs and drifted.
|
|
218
|
+
const appliedTop = useRef(top);
|
|
219
|
+
appliedTop.current = top;
|
|
196
220
|
useLayoutEffect(() => {
|
|
197
221
|
if (!refMenu.current)
|
|
198
222
|
return;
|
|
199
223
|
const rect = refMenu.current.getBoundingClientRect();
|
|
200
224
|
const w = window.innerWidth, h = window.innerHeight;
|
|
201
|
-
|
|
202
|
-
|
|
225
|
+
// Vertical: same bottom snap to viewport edge, but idempotently from the base.
|
|
226
|
+
const baseBottom = rect.bottom - (appliedTop.current - coordinate.y);
|
|
227
|
+
setTop(h - baseBottom < 8 ? coordinate.y + (h - baseBottom) : coordinate.y);
|
|
203
228
|
setLeftPos(rect.x);
|
|
204
229
|
setMenuWidth(rect.width);
|
|
230
|
+
// Horizontal: original sticky logic; reflect once without rollback,
|
|
231
|
+
// it is self-stabilizing and does not accumulate.
|
|
205
232
|
if (!coordinate.toLeft && w - rect.right < 8 && rect.width < (coordinate.left ?? 0)) {
|
|
206
233
|
setXOffset(rect.x - (coordinate.left ?? 0));
|
|
207
234
|
setIsLeftAligned(true);
|
|
@@ -213,10 +240,7 @@ export function MenuBase({ coordinate = { x: 0, y: 0, toLeft: false, left: 0 },
|
|
|
213
240
|
const alignStyle = isLeftAligned
|
|
214
241
|
? { display: "flex", flexDirection: "column-reverse", alignItems: "flex-end" }
|
|
215
242
|
: {};
|
|
216
|
-
return (_jsx("div", { ref:
|
|
217
|
-
if (el)
|
|
218
|
-
refMenu.current = el;
|
|
219
|
-
}, style: {
|
|
243
|
+
return (_jsx("div", { ref: refMenu, style: {
|
|
220
244
|
position: "absolute",
|
|
221
245
|
zIndex,
|
|
222
246
|
paddingLeft: 3,
|
|
@@ -225,6 +249,6 @@ export function MenuBase({ coordinate = { x: 0, y: 0, toLeft: false, left: 0 },
|
|
|
225
249
|
...alignStyle,
|
|
226
250
|
}, children: menu
|
|
227
251
|
? menu(dataMemo)
|
|
228
|
-
: dataMemo.map((item, i, arr) => (_jsx(MenuItemWrapper, { item: item, index: i, update: update, className: className, isLeftAligned: isLeftAligned, leftPos: leftPos, menuElement: menuElement, fullArray: dataMemo }, i))) }));
|
|
252
|
+
: 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))) }));
|
|
229
253
|
}
|
|
230
254
|
export { TimeNum, MenuElement };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
2
|
import { GetMenuR } from "./menuR";
|
|
2
3
|
import { MenuBase } from "./menu";
|
|
3
4
|
function GetMouseMenuApi(data) {
|
|
@@ -21,7 +22,9 @@ function GetMouseMenuApi(data) {
|
|
|
21
22
|
}
|
|
22
23
|
function ReactMouse(agr) {
|
|
23
24
|
const datum = menuMouse.value; //staticGetAdd(menuMouse.name, menuMouse.value
|
|
24
|
-
|
|
25
|
+
// JSX instead of a direct call: MenuR's hooks must live in its own fiber,
|
|
26
|
+
// a direct call ties them to whichever component renders ReactMouse
|
|
27
|
+
return _jsx(MenuR, { ...agr, other: agr.other ?? other, statusOn: datum.status, onConsume: () => { map.clear(); } });
|
|
25
28
|
}
|
|
26
29
|
return {
|
|
27
30
|
bb, get map() { return map; }, get menuMouse() { return menuMouse; }, ReactMouse, ReactMenu: MenuBase
|
|
@@ -2,8 +2,8 @@ import React from "react";
|
|
|
2
2
|
import { tMenuReact } from "./menu";
|
|
3
3
|
export declare function GetMenuR(): {
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* Manage the global `bb` variable that prevents opening multiple
|
|
6
|
+
* menus.
|
|
7
7
|
*/
|
|
8
8
|
bb(b?: boolean): boolean | undefined;
|
|
9
9
|
MenuR: ({ children, other, statusOn, onUnClick, onConsume, zIndex, className }: {
|
|
@@ -2,30 +2,30 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import React, { useEffect, useRef } from "react";
|
|
3
3
|
import { MenuBase } from "./menu";
|
|
4
4
|
import { DivOutsideClick } from "../hooks/useOutside";
|
|
5
|
-
//
|
|
5
|
+
// Wrapper function for creating MenuR and managing the global `bb` variable.
|
|
6
6
|
export function GetMenuR() {
|
|
7
|
-
let bb = false; //
|
|
8
|
-
//
|
|
7
|
+
let bb = false; // Global activity flag that prevents opening multiple menus.
|
|
8
|
+
// Main MenuR component
|
|
9
9
|
function MenuR({ children, other = () => [], statusOn = true, onUnClick, onConsume, zIndex, className }) {
|
|
10
|
-
const data = { x: 0, y: 0 }; //
|
|
10
|
+
const data = { x: 0, y: 0 }; // Current position of the interaction element
|
|
11
11
|
const [show, setShow] = React.useState({ status: false });
|
|
12
12
|
useEffect(() => {
|
|
13
13
|
return () => {
|
|
14
|
-
bb = false; //
|
|
14
|
+
bb = false; // Reset activity flag when the component unmounts
|
|
15
15
|
};
|
|
16
16
|
}, []);
|
|
17
|
-
const timeEvent = useRef(Date.now()); //
|
|
18
|
-
|
|
19
|
-
const touchTime = useRef(null); //
|
|
17
|
+
const timeEvent = useRef(Date.now()); // Timestamp for tracking double clicks
|
|
18
|
+
const touchXY = useRef({ x: 0, y: 0 }); // Current touch coordinates (ref: survives rerenders mid-gesture)
|
|
19
|
+
const touchTime = useRef(null); // Touch start time
|
|
20
20
|
return (_jsxs("div", { className: "maxSize", style: { position: "relative" },
|
|
21
|
-
//
|
|
21
|
+
// Disable the native context menu
|
|
22
22
|
onContextMenu: e => {
|
|
23
23
|
if (statusOn) {
|
|
24
24
|
e.preventDefault();
|
|
25
25
|
e.stopPropagation();
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
-
//
|
|
28
|
+
// Determine the interaction position for the current element
|
|
29
29
|
ref: (e) => {
|
|
30
30
|
if (e) {
|
|
31
31
|
const r = e.getBoundingClientRect();
|
|
@@ -33,33 +33,33 @@ export function GetMenuR() {
|
|
|
33
33
|
data.y = r.y;
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
-
//
|
|
36
|
+
// Store initial touch coordinates
|
|
37
37
|
onTouchStart: (e) => {
|
|
38
|
-
if (x == 0)
|
|
39
|
-
x = e.touches[0].screenX;
|
|
40
|
-
if (y == 0)
|
|
41
|
-
y = e.touches[0].screenY;
|
|
38
|
+
if (touchXY.current.x == 0)
|
|
39
|
+
touchXY.current.x = e.touches[0].screenX;
|
|
40
|
+
if (touchXY.current.y == 0)
|
|
41
|
+
touchXY.current.y = e.touches[0].screenY;
|
|
42
42
|
touchTime.current = Date.now();
|
|
43
43
|
},
|
|
44
|
-
//
|
|
44
|
+
// Check for significant movement to avoid showing the menu while scrolling
|
|
45
45
|
onTouchMove: (e) => {
|
|
46
46
|
let x2 = e.touches[0].screenX;
|
|
47
47
|
let y2 = e.touches[0].screenY;
|
|
48
48
|
let pX = e.touches[0].pageX;
|
|
49
49
|
let pY = e.touches[0].pageY;
|
|
50
|
-
if ((Math.abs(x2 - x) / pX > 0.05) || (Math.abs(y2 - y) / pY > 0.05)) {
|
|
51
|
-
touchTime.current = null; //
|
|
50
|
+
if ((Math.abs(x2 - touchXY.current.x) / pX > 0.05) || (Math.abs(y2 - touchXY.current.y) / pY > 0.05)) {
|
|
51
|
+
touchTime.current = null; // If movement is too large, disable menu display
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
|
-
//
|
|
54
|
+
// Detect long touch for opening the context menu
|
|
55
55
|
onTouchEnd: (e) => {
|
|
56
56
|
if (statusOn) {
|
|
57
57
|
if (touchTime.current && Date.now() - touchTime.current > 300) {
|
|
58
|
-
//
|
|
58
|
+
// More than 300 ms counts as a long press
|
|
59
59
|
touchTime.current = null;
|
|
60
|
-
x = y = 0;
|
|
60
|
+
touchXY.current.x = touchXY.current.y = 0;
|
|
61
61
|
if (bb)
|
|
62
|
-
return; //
|
|
62
|
+
return; // Menu is already active
|
|
63
63
|
bb = true;
|
|
64
64
|
const menu = other().filter(el => el);
|
|
65
65
|
onConsume?.();
|
|
@@ -74,30 +74,30 @@ export function GetMenuR() {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
},
|
|
77
|
-
//
|
|
77
|
+
// Track double click
|
|
78
78
|
onDoubleClick: (event) => {
|
|
79
79
|
timeEvent.current = Date.now();
|
|
80
80
|
},
|
|
81
|
-
//
|
|
81
|
+
// Handle right mouse click or double click
|
|
82
82
|
onMouseUp: (event) => {
|
|
83
83
|
if (statusOn) {
|
|
84
84
|
if (event.button == 2 || Date.now() - timeEvent.current < 300) {
|
|
85
85
|
if (bb)
|
|
86
|
-
return; //
|
|
86
|
+
return; // Menu is already active
|
|
87
87
|
bb = true;
|
|
88
88
|
const menu = other().filter(el => el);
|
|
89
89
|
onConsume?.();
|
|
90
90
|
setShow({ status: true, menu, coordinate: { x: event.clientX - data.x, y: event.clientY - data.y } });
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
-
}, children: [children /*
|
|
94
|
-
//
|
|
93
|
+
}, children: [children /* Child element whose events are tracked */, show.status && statusOn && (
|
|
94
|
+
// Show the context menu
|
|
95
95
|
_jsx(DivOutsideClick, { outsideClick: () => {
|
|
96
|
-
onUnClick?.(false); // Вызов обработчика при закрытии меню
|
|
97
96
|
if (!bb)
|
|
98
|
-
return;
|
|
99
|
-
bb = false; //
|
|
100
|
-
|
|
97
|
+
return; // Menu is already inactive; do not call close handler
|
|
98
|
+
bb = false; // Menu is no longer active
|
|
99
|
+
onUnClick?.(false); // Call close handler
|
|
100
|
+
setShow({ status: false }); // Hide the menu
|
|
101
101
|
}, children: _jsx(MenuBase, { className: className, data: [
|
|
102
102
|
...(show.plusMenu ?? []),
|
|
103
103
|
...(show.menu ?? [])
|
|
@@ -105,8 +105,8 @@ export function GetMenuR() {
|
|
|
105
105
|
}
|
|
106
106
|
return {
|
|
107
107
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
108
|
+
* Manage the global `bb` variable that prevents opening multiple
|
|
109
|
+
* menus.
|
|
110
110
|
*/
|
|
111
111
|
bb(b) {
|
|
112
112
|
if (b != undefined) {
|
|
@@ -115,6 +115,6 @@ export function GetMenuR() {
|
|
|
115
115
|
else
|
|
116
116
|
return bb;
|
|
117
117
|
},
|
|
118
|
-
MenuR //
|
|
118
|
+
MenuR // Return the created component
|
|
119
119
|
};
|
|
120
120
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Chart point: time and price.
|
|
3
3
|
*/
|
|
4
4
|
export interface IChartPoint {
|
|
5
5
|
time: number;
|
|
6
6
|
price: number;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Canvas settings.
|
|
10
10
|
*/
|
|
11
11
|
export interface IChartConfig {
|
|
12
12
|
container: HTMLElement;
|
|
@@ -17,8 +17,8 @@ export interface IChartConfig {
|
|
|
17
17
|
showPriceAxis?: boolean;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
20
|
+
* Interface returned by createChartCanvas:
|
|
21
|
+
* methods for zoom, scrolling, etc.
|
|
22
22
|
*/
|
|
23
23
|
export interface IChartCanvas {
|
|
24
24
|
appendData(points: IChartPoint | IChartPoint[]): void;
|
|
@@ -35,6 +35,6 @@ export interface IChartCanvas {
|
|
|
35
35
|
destroy(): void;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
38
|
+
* Creates a functional canvas with wheel zoom support.
|
|
39
39
|
*/
|
|
40
40
|
export declare function createChartCanvas(config: IChartConfig): IChartCanvas;
|