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,65 +1,75 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useRef, useEffect } from 'react';
|
|
3
3
|
const StickerMenu = () => {
|
|
4
|
-
//
|
|
4
|
+
// State flag: menu is open or closed
|
|
5
5
|
const [isOpen, setIsOpen] = useState(false);
|
|
6
|
-
//
|
|
6
|
+
// X offset during dragging; duplicated in a ref so document listeners
|
|
7
|
+
// subscribe once instead of on every drag tick
|
|
7
8
|
const [dragX, setDragX] = useState(0);
|
|
8
|
-
|
|
9
|
+
const dragXRef = useRef(0);
|
|
10
|
+
const setDrag = (v) => {
|
|
11
|
+
dragXRef.current = v;
|
|
12
|
+
setDragX(v);
|
|
13
|
+
};
|
|
14
|
+
// Refs for tracking drag start and dragging itself
|
|
9
15
|
const startXRef = useRef(null);
|
|
10
16
|
const draggingRef = useRef(false);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
//
|
|
17
|
+
const movedRef = useRef(false);
|
|
18
|
+
// Size settings: total menu width and visible sticker width when closed
|
|
19
|
+
const menuWidth = 250; // total width of the open menu
|
|
20
|
+
const stickerWidth = 50; // width of the visible part when the menu is closed
|
|
21
|
+
// Start dragging with mouse
|
|
15
22
|
const handleMouseDown = (e) => {
|
|
16
23
|
draggingRef.current = true;
|
|
17
24
|
startXRef.current = e.clientX;
|
|
18
25
|
};
|
|
19
|
-
//
|
|
26
|
+
// Start dragging with touch
|
|
20
27
|
const handleTouchStart = (e) => {
|
|
21
28
|
draggingRef.current = true;
|
|
22
29
|
startXRef.current = e.touches[0].clientX;
|
|
23
30
|
};
|
|
24
|
-
//
|
|
31
|
+
// Handle mouse movement
|
|
25
32
|
const handleMouseMove = (e) => {
|
|
26
33
|
if (!draggingRef.current || startXRef.current === null)
|
|
27
34
|
return;
|
|
28
35
|
const deltaX = e.clientX - startXRef.current;
|
|
29
|
-
|
|
36
|
+
setDrag(deltaX);
|
|
30
37
|
};
|
|
31
|
-
//
|
|
38
|
+
// Handle touch movement
|
|
32
39
|
const handleTouchMove = (e) => {
|
|
33
40
|
if (!draggingRef.current || startXRef.current === null)
|
|
34
41
|
return;
|
|
35
42
|
const deltaX = e.touches[0].clientX - startXRef.current;
|
|
36
|
-
|
|
43
|
+
setDrag(deltaX);
|
|
37
44
|
};
|
|
38
|
-
//
|
|
45
|
+
// Finish dragging with mouse
|
|
39
46
|
const handleMouseUp = () => {
|
|
40
47
|
if (!draggingRef.current)
|
|
41
48
|
return;
|
|
42
49
|
finishDrag();
|
|
43
50
|
};
|
|
44
|
-
//
|
|
51
|
+
// Finish dragging with touch
|
|
45
52
|
const handleTouchEnd = () => {
|
|
46
53
|
if (!draggingRef.current)
|
|
47
54
|
return;
|
|
48
55
|
finishDrag();
|
|
49
56
|
};
|
|
50
|
-
//
|
|
57
|
+
// Finish dragging: switch state if offset is greater than half of the menu width
|
|
51
58
|
const finishDrag = () => {
|
|
52
59
|
draggingRef.current = false;
|
|
53
|
-
|
|
60
|
+
const delta = dragXRef.current;
|
|
61
|
+
if (delta < -menuWidth / 2) {
|
|
54
62
|
setIsOpen(true);
|
|
63
|
+
movedRef.current = true; // suppress the click that follows mouseup, it would toggle back
|
|
55
64
|
}
|
|
56
|
-
else if (
|
|
65
|
+
else if (delta > menuWidth / 2) {
|
|
57
66
|
setIsOpen(false);
|
|
67
|
+
movedRef.current = true;
|
|
58
68
|
}
|
|
59
|
-
|
|
69
|
+
setDrag(0);
|
|
60
70
|
startXRef.current = null;
|
|
61
71
|
};
|
|
62
|
-
//
|
|
72
|
+
// Subscribe to global movement and drag-finish events
|
|
63
73
|
useEffect(() => {
|
|
64
74
|
document.addEventListener('mousemove', handleMouseMove);
|
|
65
75
|
document.addEventListener('touchmove', handleTouchMove);
|
|
@@ -71,25 +81,29 @@ const StickerMenu = () => {
|
|
|
71
81
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
72
82
|
document.removeEventListener('touchend', handleTouchEnd);
|
|
73
83
|
};
|
|
74
|
-
}, [
|
|
75
|
-
//
|
|
84
|
+
}, []);
|
|
85
|
+
// Toggle menu state on click
|
|
76
86
|
const handleClick = () => {
|
|
87
|
+
if (movedRef.current) {
|
|
88
|
+
movedRef.current = false;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
77
91
|
setIsOpen(!isOpen);
|
|
78
92
|
};
|
|
79
93
|
/*
|
|
80
|
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
94
|
+
Calculate the final X offset:
|
|
95
|
+
- When the menu is closed, shift it left so only the sticker is visible.
|
|
96
|
+
- During dragging, adjust the position relative to the current offset.
|
|
83
97
|
*/
|
|
84
98
|
let translateX = 0;
|
|
85
99
|
if (dragX !== 0) {
|
|
86
|
-
//
|
|
87
|
-
//
|
|
100
|
+
// If the menu is open, drag right only in the negative direction
|
|
101
|
+
// If closed, drag left only in the positive direction
|
|
88
102
|
translateX = isOpen ? Math.min(0, dragX) : Math.max(0, dragX);
|
|
89
103
|
}
|
|
90
104
|
const baseTranslate = isOpen ? 0 : -(menuWidth - stickerWidth);
|
|
91
105
|
const finalTranslate = baseTranslate + translateX;
|
|
92
|
-
//
|
|
106
|
+
// Menu container styles
|
|
93
107
|
const containerStyle = {
|
|
94
108
|
position: 'fixed',
|
|
95
109
|
top: '50%',
|
|
@@ -105,6 +119,6 @@ const StickerMenu = () => {
|
|
|
105
119
|
userSelect: 'none',
|
|
106
120
|
overflow: 'hidden'
|
|
107
121
|
};
|
|
108
|
-
return (_jsx("div", { style: containerStyle, onMouseDown: handleMouseDown, onTouchStart: handleTouchStart, onClick: handleClick, children: _jsxs("div", { style: { padding: '10px' }, children: [_jsx("h3", { children: "
|
|
122
|
+
return (_jsx("div", { style: containerStyle, onMouseDown: handleMouseDown, onTouchStart: handleTouchStart, onClick: handleClick, children: _jsxs("div", { style: { padding: '10px' }, children: [_jsx("h3", { children: "Menu" }), isOpen && (_jsxs("ul", { style: { listStyle: 'none', padding: 0 }, children: [_jsx("li", { children: "Item 1" }), _jsx("li", { children: "Item 2" }), _jsx("li", { children: "Item 3" })] }))] }) }));
|
|
109
123
|
};
|
|
110
124
|
export default StickerMenu;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { default as StickerMenu } from './StickerMenu';
|
|
2
2
|
export * from './RightMenu';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export { default as StickerMenu } from './StickerMenu';
|
|
2
2
|
export * from './RightMenu';
|
|
@@ -19,18 +19,19 @@ export declare function getApiLeftMenu(): {
|
|
|
19
19
|
set(jsx: React.JSX.Element | null): void;
|
|
20
20
|
JSX: React.JSX.Element | null;
|
|
21
21
|
Render(): React.JSX.Element | null;
|
|
22
|
-
addJSX
|
|
23
|
-
dellBy(jsx: React.JSX.Element): void;
|
|
24
|
-
readonly arrJSX: import("react/jsx-runtime").JSX.Element[];
|
|
25
|
-
RenderArr(): import("react/jsx-runtime").JSX.Element[];
|
|
22
|
+
addJSX<A extends React.JSX.Element | null>(jsx: A): A;
|
|
23
|
+
dellBy(jsx: React.JSX.Element | null): void;
|
|
24
|
+
readonly arrJSX: (import("react/jsx-runtime").JSX.Element | null)[];
|
|
25
|
+
RenderArr(): (import("react/jsx-runtime").JSX.Element | null)[];
|
|
26
26
|
};
|
|
27
27
|
renderBy(): void;
|
|
28
28
|
getMenu: () => Map<string, MenuItem[]>;
|
|
29
29
|
setMenu: (items: (MenuItemPartial | MenuItem)[], key?: string) => void;
|
|
30
|
-
Modal2: ({ menu, zIndex, zIndex0,
|
|
30
|
+
Modal2: ({ menu, zIndex, zIndex0, menuKey }: {
|
|
31
31
|
zIndex: number;
|
|
32
32
|
zIndex0?: number;
|
|
33
|
-
key
|
|
33
|
+
/** Store key for this menu; the former `key` prop never worked (React strips it from props). */
|
|
34
|
+
menuKey?: string;
|
|
34
35
|
menu?: (MenuItemPartial | MenuItem)[];
|
|
35
36
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
36
37
|
};
|
|
@@ -39,18 +40,19 @@ export declare const ApiLeftMenu: {
|
|
|
39
40
|
set(jsx: React.JSX.Element | null): void;
|
|
40
41
|
JSX: React.JSX.Element | null;
|
|
41
42
|
Render(): React.JSX.Element | null;
|
|
42
|
-
addJSX
|
|
43
|
-
dellBy(jsx: React.JSX.Element): void;
|
|
44
|
-
readonly arrJSX: import("react/jsx-runtime").JSX.Element[];
|
|
45
|
-
RenderArr(): import("react/jsx-runtime").JSX.Element[];
|
|
43
|
+
addJSX<A extends React.JSX.Element | null>(jsx: A): A;
|
|
44
|
+
dellBy(jsx: React.JSX.Element | null): void;
|
|
45
|
+
readonly arrJSX: (import("react/jsx-runtime").JSX.Element | null)[];
|
|
46
|
+
RenderArr(): (import("react/jsx-runtime").JSX.Element | null)[];
|
|
46
47
|
};
|
|
47
48
|
renderBy(): void;
|
|
48
49
|
getMenu: () => Map<string, MenuItem[]>;
|
|
49
50
|
setMenu: (items: (MenuItemPartial | MenuItem)[], key?: string) => void;
|
|
50
|
-
Modal2: ({ menu, zIndex, zIndex0,
|
|
51
|
+
Modal2: ({ menu, zIndex, zIndex0, menuKey }: {
|
|
51
52
|
zIndex: number;
|
|
52
53
|
zIndex0?: number;
|
|
53
|
-
key
|
|
54
|
+
/** Store key for this menu; the former `key` prop never worked (React strips it from props). */
|
|
55
|
+
menuKey?: string;
|
|
54
56
|
menu?: (MenuItemPartial | MenuItem)[];
|
|
55
57
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
56
58
|
};
|
|
@@ -42,17 +42,21 @@ function SidebarMenuComponent({ y_, x_, api, arr, zIndex }) {
|
|
|
42
42
|
textDecoration: "inherit",
|
|
43
43
|
cursor: "default",
|
|
44
44
|
}, children: e[0] }) }, i)));
|
|
45
|
-
|
|
45
|
+
const mountedRef = useRef(true);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
mountedRef.current = true;
|
|
48
|
+
return () => { mountedRef.current = false; };
|
|
49
|
+
}, []);
|
|
50
|
+
// Smooth animation function to target position; cancels on unmount,
|
|
51
|
+
// and the returned promise now resolves at the end (recursion was not awaited)
|
|
46
52
|
const animateToPosition = async (target) => {
|
|
47
53
|
lastPosition.current.auto = true;
|
|
48
54
|
const step = 40;
|
|
49
|
-
|
|
50
|
-
return;
|
|
51
|
-
const animate = async () => {
|
|
52
|
-
if (!lastPosition.current.auto || currentPosition.current.x === target)
|
|
53
|
-
return;
|
|
55
|
+
while (lastPosition.current.auto && currentPosition.current.x !== target) {
|
|
54
56
|
const direction = target > currentPosition.current.x ? 1 : -1;
|
|
55
57
|
await sleepAsync(10);
|
|
58
|
+
if (!mountedRef.current || !lastPosition.current.auto)
|
|
59
|
+
return;
|
|
56
60
|
const nextPos = currentPosition.current.x + direction * step;
|
|
57
61
|
if (Math.abs(target - nextPos) < step) {
|
|
58
62
|
lastPosition.current.auto = false;
|
|
@@ -64,9 +68,7 @@ function SidebarMenuComponent({ y_, x_, api, arr, zIndex }) {
|
|
|
64
68
|
}
|
|
65
69
|
currentPosition.current.x = nextPos;
|
|
66
70
|
setX(nextPos);
|
|
67
|
-
|
|
68
|
-
};
|
|
69
|
-
await animate();
|
|
71
|
+
}
|
|
70
72
|
};
|
|
71
73
|
useEffect(() => {
|
|
72
74
|
const menuApi = {
|
|
@@ -203,11 +205,11 @@ export function getApiLeftMenu() {
|
|
|
203
205
|
color: "rgba(255,255,255,0.1)"
|
|
204
206
|
}, children: textB })), children()] }));
|
|
205
207
|
};
|
|
206
|
-
let menuApi = null;
|
|
207
208
|
const menuStore = new Map();
|
|
208
209
|
const setMenu = (items, key = "base") => {
|
|
209
210
|
const colorGen = colorGenerator2({ min: 0, max: 90 });
|
|
210
|
-
|
|
211
|
+
// exclude this key's old items, otherwise a repeated setMenu shifts default colors
|
|
212
|
+
const currentMenuLength = getAllMenuItems().length - (menuStore.get(key)?.length ?? 0);
|
|
211
213
|
const baseColors = [];
|
|
212
214
|
for (let i = 0; i < currentMenuLength + items.length; i++) {
|
|
213
215
|
const colorResult = colorGen.next();
|
|
@@ -227,11 +229,23 @@ export function getApiLeftMenu() {
|
|
|
227
229
|
function getAllMenuItems() {
|
|
228
230
|
return [...menuStore.values()].flat();
|
|
229
231
|
}
|
|
230
|
-
function Modal2({ menu, zIndex, zIndex0,
|
|
231
|
-
|
|
232
|
-
|
|
232
|
+
function Modal2({ menu, zIndex, zIndex0, menuKey }) {
|
|
233
|
+
const lastSet = useRef(null);
|
|
234
|
+
// Set in an effect, not during render: otherwise StrictMode sets twice and every render has a side effect.
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
if (!menu)
|
|
237
|
+
return;
|
|
238
|
+
const prev = lastSet.current;
|
|
239
|
+
// shallow compare: skip the store rewrite when an inline array has the same items
|
|
240
|
+
if (prev && prev.menuKey === menuKey && prev.menu.length === menu.length
|
|
241
|
+
&& prev.menu.every((el, i) => el === menu[i]))
|
|
242
|
+
return;
|
|
243
|
+
lastSet.current = { menu, menuKey };
|
|
244
|
+
setMenu(menu, menuKey);
|
|
245
|
+
renderBy(menuStore);
|
|
246
|
+
}, [menu, menuKey]);
|
|
233
247
|
updateBy(menuStore);
|
|
234
|
-
return (_jsxs("div", { className: "maxSize", style: { position: "absolute", zIndex: zIndex0 }, children: [_jsx(modal.Render, {}), _jsx(LeftMenuComponent, { zIndex: zIndex, api:
|
|
248
|
+
return (_jsxs("div", { className: "maxSize", style: { position: "absolute", zIndex: zIndex0 }, children: [_jsx(modal.Render, {}), _jsx(LeftMenuComponent, { zIndex: zIndex, api: () => { }, menu: getAllMenuItems() })] }));
|
|
235
249
|
}
|
|
236
250
|
const modal = GetModalJSX();
|
|
237
251
|
return {
|
|
@@ -244,7 +258,7 @@ export function getApiLeftMenu() {
|
|
|
244
258
|
}
|
|
245
259
|
export const ApiLeftMenu = getApiLeftMenu();
|
|
246
260
|
export function TestLeft333() {
|
|
247
|
-
//
|
|
261
|
+
// Test menu moved here from module scope; previously ApiLeftMenu.setMenu(...) ran on import and leaked to all consumers.
|
|
248
262
|
return _jsx(ApiLeftMenu.Modal2, { zIndex: 20, menu: [
|
|
249
263
|
{ button: _jsx("div", { style: { width: 200, height: 50, background: "rgb(92,50,213)" }, children: "1" }), el: () => _jsx("div", { children: "1" }), color: "rgb(92,50,213)" },
|
|
250
264
|
{ button: _jsx("div", { style: { width: 200, height: 50, background: "rgb(98,149,58)" }, children: "2" }), el: () => _jsx("div", { children: "2" }) },
|
|
@@ -1,30 +1,44 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import type { ModalApi } from "./ModalContextProvider";
|
|
3
|
+
type LegacyModalSetter = (jsx: React.ReactNode | null) => void;
|
|
4
|
+
type ModalTarget = LegacyModalSetter | ModalApi;
|
|
2
5
|
export declare function inputModal({ setModalJSX, func, name, txt }: {
|
|
3
6
|
txt?: string;
|
|
4
7
|
name?: string;
|
|
5
|
-
|
|
8
|
+
/** Any modal setter: setState/useModal or ModalApi from useModal */
|
|
9
|
+
setModalJSX: ModalTarget;
|
|
6
10
|
func: (txt: string) => void;
|
|
7
11
|
}): void;
|
|
8
|
-
export declare function confirmModal({ setModalJSX, func }: {
|
|
9
|
-
|
|
12
|
+
export declare function confirmModal({ setModalJSX, func, password }: {
|
|
13
|
+
/** Any modal setter: setState/useModal or ModalApi from useModal */
|
|
14
|
+
setModalJSX: ModalTarget;
|
|
10
15
|
func: () => any;
|
|
16
|
+
/** Confirmation code word. Default "111" is kept for compatibility; pass your own. */
|
|
17
|
+
password?: string;
|
|
11
18
|
}): void;
|
|
19
|
+
/**
|
|
20
|
+
* @deprecated Imperative JSX storage based on updateBy/renderBy.
|
|
21
|
+
* Use `ModalProvider`/`useModal` (ModalContextProvider): context plus portal.
|
|
22
|
+
*/
|
|
12
23
|
export declare function GetModalJSX(): {
|
|
13
24
|
set(jsx: React.JSX.Element | null): void;
|
|
14
25
|
JSX: React.JSX.Element | null;
|
|
15
26
|
Render(): React.JSX.Element | null;
|
|
16
|
-
addJSX
|
|
17
|
-
dellBy(jsx: React.JSX.Element): void;
|
|
18
|
-
readonly arrJSX: import("react/jsx-runtime").JSX.Element[];
|
|
19
|
-
RenderArr(): import("react/jsx-runtime").JSX.Element[];
|
|
27
|
+
addJSX<A extends React.JSX.Element | null>(jsx: A): A;
|
|
28
|
+
dellBy(jsx: React.JSX.Element | null): void;
|
|
29
|
+
readonly arrJSX: (import("react/jsx-runtime").JSX.Element | null)[];
|
|
30
|
+
RenderArr(): (import("react/jsx-runtime").JSX.Element | null)[];
|
|
20
31
|
};
|
|
21
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Imperative JSX storage based on updateBy/renderBy.
|
|
34
|
+
* Use `ModalProvider`/`useModal` (ModalContextProvider): context plus portal.
|
|
35
|
+
*/
|
|
22
36
|
export declare function GetModalFuncJSX(): {
|
|
23
|
-
set(jsx:
|
|
24
|
-
JSX:
|
|
37
|
+
set(jsx: (() => React.JSX.Element | null) | null): void;
|
|
38
|
+
JSX: (() => React.JSX.Element | null) | null;
|
|
25
39
|
Render(): React.JSX.Element | null;
|
|
26
|
-
addJSX(jsx:
|
|
27
|
-
dellBy(jsx:
|
|
40
|
+
addJSX<A extends (() => React.JSX.Element | null) | null>(jsx: A): A;
|
|
41
|
+
dellBy(jsx: (() => React.JSX.Element | null) | null): void;
|
|
28
42
|
readonly arrJSX: (import("react/jsx-runtime").JSX.Element | null)[];
|
|
29
43
|
RenderArr(): (import("react/jsx-runtime").JSX.Element | null)[];
|
|
30
44
|
};
|
|
@@ -1,104 +1,81 @@
|
|
|
1
1
|
import { jsx as _jsx_1 } from "react/jsx-runtime";
|
|
2
2
|
import { renderBy, updateBy } from "../../../updateBy";
|
|
3
3
|
import { InputPageModal } from "../Input";
|
|
4
|
+
function setModalTarget(target, jsx) {
|
|
5
|
+
if (typeof target == "function")
|
|
6
|
+
target(jsx);
|
|
7
|
+
else
|
|
8
|
+
target.replace(jsx);
|
|
9
|
+
}
|
|
4
10
|
export function inputModal({ setModalJSX, func, name, txt }) {
|
|
5
|
-
setModalJSX
|
|
11
|
+
setModalTarget(setModalJSX, _jsx_1(InputPageModal, { callback: txt => {
|
|
6
12
|
func(txt);
|
|
7
|
-
setModalJSX
|
|
8
|
-
}, outClick: () => setModalJSX
|
|
13
|
+
setModalTarget(setModalJSX, null);
|
|
14
|
+
}, outClick: () => setModalTarget(setModalJSX, null), name: name ?? "name", txt: txt }));
|
|
9
15
|
}
|
|
10
|
-
export function confirmModal({ setModalJSX, func }) {
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
export function confirmModal({ setModalJSX, func, password = "111" }) {
|
|
17
|
+
// Do not expose custom passwords in the hint; show the legacy default as before.
|
|
18
|
+
const hint = password == "111" ? "password 111" : "password";
|
|
19
|
+
setModalTarget(setModalJSX, _jsx_1(InputPageModal, { callback: txt => {
|
|
20
|
+
if (txt == password)
|
|
13
21
|
func();
|
|
14
|
-
setModalJSX
|
|
15
|
-
}, outClick: () => setModalJSX
|
|
22
|
+
setModalTarget(setModalJSX, null);
|
|
23
|
+
}, outClick: () => setModalTarget(setModalJSX, null), name: hint }));
|
|
16
24
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
// Shared store for GetModalJSX/GetModalFuncJSX: identical logic, the only
|
|
26
|
+
// difference is how a stored value turns into an element (renderItem)
|
|
27
|
+
function createJsxStore(renderItem) {
|
|
28
|
+
let _jsx = null;
|
|
29
|
+
let _jsxArr = [];
|
|
30
|
+
let key = 0;
|
|
31
|
+
const check = (jsx) => _jsxArr.findIndex(e => e.jsx == jsx);
|
|
32
|
+
const data = {
|
|
33
|
+
set(jsx) {
|
|
34
|
+
_jsx = jsx;
|
|
35
|
+
renderBy(data);
|
|
36
|
+
},
|
|
37
|
+
set JSX(jsx) {
|
|
38
|
+
_jsx = jsx;
|
|
39
|
+
renderBy(data);
|
|
40
|
+
},
|
|
41
|
+
get JSX() { return _jsx; },
|
|
42
|
+
Render() {
|
|
43
|
+
updateBy(data);
|
|
44
|
+
return _jsx && renderItem(_jsx);
|
|
45
|
+
},
|
|
46
|
+
addJSX(jsx) {
|
|
47
|
+
if (check(jsx) == -1) {
|
|
48
|
+
_jsxArr.push({ jsx, key: key++ });
|
|
26
49
|
renderBy(data);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
50
|
+
}
|
|
51
|
+
return jsx;
|
|
52
|
+
},
|
|
53
|
+
dellBy(jsx) {
|
|
54
|
+
const c = check(jsx);
|
|
55
|
+
if (c != -1) {
|
|
56
|
+
_jsxArr.splice(c, 1);
|
|
30
57
|
renderBy(data);
|
|
31
|
-
},
|
|
32
|
-
get JSX() { return _jsx; },
|
|
33
|
-
Render() {
|
|
34
|
-
updateBy(data);
|
|
35
|
-
return _jsx;
|
|
36
|
-
},
|
|
37
|
-
addJSX(jsx) {
|
|
38
|
-
const c = check(jsx);
|
|
39
|
-
if (c == -1) {
|
|
40
|
-
_jsxArr.push({ jsx, key: key++ });
|
|
41
|
-
renderBy(data);
|
|
42
|
-
}
|
|
43
|
-
return jsx;
|
|
44
|
-
},
|
|
45
|
-
dellBy(jsx) {
|
|
46
|
-
const c = check(jsx);
|
|
47
|
-
if (c != -1) {
|
|
48
|
-
_jsxArr.splice(c, 1);
|
|
49
|
-
renderBy(data);
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
get arrJSX() { return _jsxArr.map(e => _jsx_1("div", { children: e.jsx }, e.key)); },
|
|
53
|
-
RenderArr() {
|
|
54
|
-
updateBy(data);
|
|
55
|
-
return _jsxArr.map(e => _jsx_1("div", { children: e.jsx }, e.key));
|
|
56
58
|
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
+
},
|
|
60
|
+
get arrJSX() { return _jsxArr.map(e => e.jsx && _jsx_1("div", { children: renderItem(e.jsx) }, e.key)); },
|
|
61
|
+
RenderArr() {
|
|
62
|
+
updateBy(data);
|
|
63
|
+
return data.arrJSX;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
59
66
|
return data;
|
|
60
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated Imperative JSX storage based on updateBy/renderBy.
|
|
70
|
+
* Use `ModalProvider`/`useModal` (ModalContextProvider): context plus portal.
|
|
71
|
+
*/
|
|
72
|
+
export function GetModalJSX() {
|
|
73
|
+
return createJsxStore(jsx => jsx);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* @deprecated Imperative JSX storage based on updateBy/renderBy.
|
|
77
|
+
* Use `ModalProvider`/`useModal` (ModalContextProvider): context plus portal.
|
|
78
|
+
*/
|
|
61
79
|
export function GetModalFuncJSX() {
|
|
62
|
-
|
|
63
|
-
let _jsx = null;
|
|
64
|
-
let _jsxArr = [];
|
|
65
|
-
let key = 0;
|
|
66
|
-
const check = (jsx) => _jsxArr.findIndex(e => e.jsx == jsx);
|
|
67
|
-
return {
|
|
68
|
-
set(jsx) {
|
|
69
|
-
_jsx = jsx;
|
|
70
|
-
renderBy(data);
|
|
71
|
-
},
|
|
72
|
-
set JSX(jsx) {
|
|
73
|
-
_jsx = jsx;
|
|
74
|
-
renderBy(data);
|
|
75
|
-
},
|
|
76
|
-
get JSX() { return _jsx; },
|
|
77
|
-
Render() {
|
|
78
|
-
updateBy(data);
|
|
79
|
-
return _jsx ? _jsx() : null;
|
|
80
|
-
},
|
|
81
|
-
addJSX(jsx) {
|
|
82
|
-
const c = check(jsx);
|
|
83
|
-
if (c == -1) {
|
|
84
|
-
_jsxArr.push({ jsx, key: key++ });
|
|
85
|
-
renderBy(data);
|
|
86
|
-
}
|
|
87
|
-
return jsx;
|
|
88
|
-
},
|
|
89
|
-
dellBy(jsx) {
|
|
90
|
-
const c = check(jsx);
|
|
91
|
-
if (c != -1) {
|
|
92
|
-
_jsxArr.splice(c, 1);
|
|
93
|
-
renderBy(data);
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
get arrJSX() { return _jsxArr.map(e => e.jsx && _jsx_1("div", { children: e.jsx() }, e.key)); },
|
|
97
|
-
RenderArr() {
|
|
98
|
-
updateBy(data);
|
|
99
|
-
return _jsxArr.map(e => e.jsx && _jsx_1("div", { children: e.jsx() }, e.key));
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
})();
|
|
103
|
-
return data;
|
|
80
|
+
return createJsxStore(f => f());
|
|
104
81
|
}
|
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
export
|
|
2
|
+
export type ModalApi = {
|
|
3
|
+
show(node: ReactNode): void;
|
|
4
|
+
open(node: ReactNode): void;
|
|
5
|
+
close(): void;
|
|
6
|
+
replace(node: ReactNode | null): void;
|
|
7
|
+
set(node: ReactNode | null): void;
|
|
8
|
+
};
|
|
9
|
+
export type ModalController = ((jsx: ReactNode | null) => void) & ModalApi;
|
|
10
|
+
export type ModalProviderProps = {
|
|
3
11
|
children: ReactNode;
|
|
4
|
-
|
|
5
|
-
|
|
12
|
+
/** Close on click outside the modal. Defaults to true for legacy behavior. */
|
|
13
|
+
closeOnOutsideClick?: boolean;
|
|
14
|
+
/** Close on Escape. Defaults to true. */
|
|
15
|
+
closeOnEscape?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare const ModalProvider: ({ children, closeOnOutsideClick, closeOnEscape }: ModalProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
export declare const useModal: () => ModalController;
|
|
19
|
+
/** @deprecated Use `useModal()`; it is callable and also has show/open/close/set methods. */
|
|
20
|
+
export declare const useModalOld: () => ModalController;
|
|
21
|
+
/** @deprecated Use `useModal()` directly. */
|
|
22
|
+
export declare function useModalApi(): ModalApi;
|
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext, useState } from 'react';
|
|
2
|
+
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import { DivOutsideClick } from "../../hooks/useOutside";
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
5
|
+
import { tokens } from "../../styles/tokens";
|
|
6
|
+
const noopModal = Object.assign(() => { }, { show() { }, open() { }, close() { }, replace() { }, set() { } });
|
|
7
|
+
const ModalContext = createContext(noopModal);
|
|
8
|
+
export const ModalProvider = ({ children, closeOnOutsideClick = true, closeOnEscape = true }) => {
|
|
8
9
|
const [modal, setModal] = useState(null);
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const modalApi = useMemo(() => {
|
|
11
|
+
const api = ((node) => setModal(node));
|
|
12
|
+
api.show = (node) => setModal(node);
|
|
13
|
+
api.open = api.show;
|
|
14
|
+
api.close = () => setModal(null);
|
|
15
|
+
api.replace = (node) => setModal(node);
|
|
16
|
+
api.set = api.replace;
|
|
17
|
+
return api;
|
|
18
|
+
}, []);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (!modal || !closeOnEscape)
|
|
21
|
+
return;
|
|
22
|
+
const onKeyDown = (e) => {
|
|
23
|
+
if (e.key == 'Escape')
|
|
24
|
+
setModal(null);
|
|
25
|
+
};
|
|
26
|
+
document.addEventListener('keydown', onKeyDown);
|
|
27
|
+
return () => document.removeEventListener('keydown', onKeyDown);
|
|
28
|
+
}, [modal, closeOnEscape]);
|
|
29
|
+
return (_jsxs(ModalContext.Provider, { value: modalApi, children: [children, modal && createPortal(_jsx("div", { style: {
|
|
30
|
+
position: 'fixed', inset: 0, zIndex: tokens.zIndex.modal,
|
|
11
31
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
12
32
|
backgroundColor: 'rgba(0,0,0,0.5)'
|
|
13
|
-
}, children: _jsx(DivOutsideClick, { outsideClick: () =>
|
|
33
|
+
}, children: _jsx(DivOutsideClick, { outsideClick: () => { if (closeOnOutsideClick)
|
|
34
|
+
setModal(null); }, status: true, children: modal }) }), document.body)] }));
|
|
14
35
|
};
|
|
15
|
-
//
|
|
36
|
+
// Callable for legacy code, controller-style for new code.
|
|
16
37
|
export const useModal = () => useContext(ModalContext);
|
|
38
|
+
/** @deprecated Use `useModal()`; it is callable and also has show/open/close/set methods. */
|
|
39
|
+
export const useModalOld = () => useContext(ModalContext);
|
|
40
|
+
/** @deprecated Use `useModal()` directly. */
|
|
41
|
+
export function useModalApi() {
|
|
42
|
+
return useContext(ModalContext);
|
|
43
|
+
}
|