wenay-react2 1.0.27 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/api.d.ts +2 -1
- package/lib/common/api.js +1 -1
- package/lib/common/src/components/Dnd/RNDFunc3.js +9 -17
- package/lib/common/src/components/Menu/RightMenu.d.ts +9 -9
- package/lib/common/src/components/Menu/RightMenu.js +68 -38
- package/lib/common/src/components/Menu/RightMenuStore.d.ts +11 -0
- package/lib/common/src/components/Menu/RightMenuStore.js +1 -0
- package/lib/common/src/components/Menu/index.d.ts +1 -0
- package/lib/common/src/components/Menu/index.js +1 -0
- package/lib/common/src/styles/tokens.d.ts +26 -0
- package/lib/common/src/styles/tokens.js +26 -0
- package/lib/common/src/utils/mapMemory.d.ts +1 -0
- package/lib/common/src/utils/mapMemory.js +3 -0
- package/lib/style/style.css +52 -11
- package/lib/style/tokens.css +33 -0
- package/package.json +1 -1
package/lib/common/api.d.ts
CHANGED
|
@@ -25,7 +25,8 @@ export * from "./src/components/ParametersEngine";
|
|
|
25
25
|
export * from "./src/components/Input";
|
|
26
26
|
export * from "./src/components/Modal";
|
|
27
27
|
export * from "./src/components/Menu";
|
|
28
|
-
export
|
|
28
|
+
export { MenuBase, TimeNum, MenuElement as LegacyMenuElement } from "./src/menu/menu";
|
|
29
|
+
export type { tMenuReact, tMenuReactStrictly } from "./src/menu/menu";
|
|
29
30
|
export * from "./src/menu/menuMouse";
|
|
30
31
|
export * from "./src/menu/menuR";
|
|
31
32
|
export * from "./src/logs/logs";
|
package/lib/common/api.js
CHANGED
|
@@ -38,7 +38,7 @@ export * from "./src/components/Modal";
|
|
|
38
38
|
// 11. Menu - depends on hooks, Dnd, and Modal
|
|
39
39
|
export * from "./src/components/Menu";
|
|
40
40
|
// 12. MENU - depends on components
|
|
41
|
-
export
|
|
41
|
+
export { MenuBase, TimeNum, MenuElement as LegacyMenuElement } from "./src/menu/menu";
|
|
42
42
|
export * from "./src/menu/menuMouse";
|
|
43
43
|
export * from "./src/menu/menuR";
|
|
44
44
|
// 13. LOGS - depend on utils/mapMemory, menu, and components/ParametersEngine
|
|
@@ -21,9 +21,11 @@ export const DivRnd3 = (a) => {
|
|
|
21
21
|
* Provides dragging and resizing, an optional header, and a close button.
|
|
22
22
|
*/
|
|
23
23
|
export function DivRndBase3({ children, keyForSave: ks, position, size, overflow = true, zIndex = 9, onUpdate, disableDragging, className, header, moveOnlyHeader, limit, onCLickClose, sizeByWindow = true }) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
// NOTE: no implicit limit for onCLickClose windows. `limit` is parent-relative,
|
|
25
|
+
// so {y:{min:0}} pinned windows to their DOM parent's top: a window opened from a
|
|
26
|
+
// centered wrapper (ModalProvider / ModalWrapper at top:50%) could not be dragged
|
|
27
|
+
// above mid-screen. Keeping the window on screen is already handled by the
|
|
28
|
+
// viewport clamp below (header rect vs viewport in useLayoutEffect).
|
|
27
29
|
const positionDef = { x: 0, y: 0, ...(position ?? {}) };
|
|
28
30
|
const sizeDef = { height: 0, width: 0, ...(size ?? {}) };
|
|
29
31
|
// If there is a key, store position and size data in the map
|
|
@@ -199,7 +201,7 @@ export function DivRndBase3({ children, keyForSave: ks, position, size, overflow
|
|
|
199
201
|
setHeight(window.innerHeight);
|
|
200
202
|
}
|
|
201
203
|
}, [x, y, width, height, sizeByWindow]);
|
|
202
|
-
const headerD = (_jsx("div", { ref: headerRef, onTouchStart: (e) => {
|
|
204
|
+
const headerD = (_jsx("div", { ref: headerRef, className: "wenayWndHeader", onTouchStart: (e) => {
|
|
203
205
|
const t = e.changedTouches[0];
|
|
204
206
|
if (t) {
|
|
205
207
|
lastT.current = {
|
|
@@ -215,14 +217,7 @@ export function DivRndBase3({ children, keyForSave: ks, position, size, overflow
|
|
|
215
217
|
y: y - e.clientY
|
|
216
218
|
};
|
|
217
219
|
setA(true);
|
|
218
|
-
},
|
|
219
|
-
userSelect: "none",
|
|
220
|
-
cursor: "grabbing"
|
|
221
|
-
}, children: header ?? (_jsx("div", { style: {
|
|
222
|
-
height: 20,
|
|
223
|
-
width: "100%",
|
|
224
|
-
backgroundImage: "repeating-linear-gradient(139deg, hsla(0,0%,100%,.1), hsla(0,0%,100%,.1) 15px, transparent 0, transparent 30px)"
|
|
225
|
-
} })) }));
|
|
220
|
+
}, children: header ?? _jsx("div", { className: "wenayWndHeaderDef" }) }));
|
|
226
221
|
return (_jsx(Rnd, { disableDragging: true, style: {
|
|
227
222
|
zIndex: zIndexX * 2 + zIndex
|
|
228
223
|
}, className: className, onResizeStop: (e, dir, elementRef, delta, { x: nx, y: ny }) => {
|
|
@@ -237,7 +232,7 @@ export function DivRndBase3({ children, keyForSave: ks, position, size, overflow
|
|
|
237
232
|
}, position: { x, y }, size: { width, height }, default: {
|
|
238
233
|
...position,
|
|
239
234
|
...size
|
|
240
|
-
}, children: _jsxs("div", { style: {
|
|
235
|
+
}, children: _jsxs("div", { className: "wenayWnd", style: {
|
|
241
236
|
width: "100%",
|
|
242
237
|
height: "100%",
|
|
243
238
|
display: "flex",
|
|
@@ -256,10 +251,7 @@ export function DivRndBase3({ children, keyForSave: ks, position, size, overflow
|
|
|
256
251
|
}, children: [moveOnlyHeader || header ? headerD : null, _jsxs("div", { className: "maxSize", style: { overflow: overflow ? "auto" : undefined }, children: [(a || b) && (_jsx("div", { className: "maxSize", style: {
|
|
257
252
|
position: "absolute",
|
|
258
253
|
zIndex: zIndexX * 2 + zIndex + 1
|
|
259
|
-
} })), typeof children === "function" ? children(update) : children] }), onCLickClose && (_jsx("div", { className: "wenayCloseBtn", title: "Close", style: {
|
|
260
|
-
position: "absolute",
|
|
261
|
-
right: -12,
|
|
262
|
-
top: -12,
|
|
254
|
+
} })), typeof children === "function" ? children(update) : children] }), onCLickClose && (_jsx("div", { className: "wenayCloseBtn wenayWndClose", title: "Close", style: {
|
|
263
255
|
zIndex: zIndexX * 2 + zIndex + 1
|
|
264
256
|
}, onClick: onCLickClose, children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", "aria-hidden": "true", children: _jsx("path", { d: "M2 2 L10 10 M10 2 L2 10", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" }) }) }, "323"))] }) }));
|
|
265
257
|
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import React, { JSX } from 'react';
|
|
2
|
-
type
|
|
2
|
+
import { type MenuRightPosition, type MenuRightPosition2 } from "./RightMenuStore";
|
|
3
|
+
export type MenuElement = {
|
|
3
4
|
label: string;
|
|
4
5
|
subMenuContent: () => JSX.Element;
|
|
5
6
|
};
|
|
6
|
-
type DropdownMenuProps = {
|
|
7
|
+
export type DropdownMenuProps = {
|
|
7
8
|
elements: MenuElement[];
|
|
8
9
|
style?: React.CSSProperties;
|
|
9
|
-
position?:
|
|
10
|
-
position2?:
|
|
10
|
+
position?: MenuRightPosition;
|
|
11
|
+
position2?: MenuRightPosition2;
|
|
12
|
+
keyForSave?: string;
|
|
11
13
|
};
|
|
12
|
-
export
|
|
14
|
+
export type MenuRightRenderProps = Omit<DropdownMenuProps, 'elements'>;
|
|
15
|
+
export declare function DropdownMenu({ elements, style, position: initialPosition, position2: initialPos2, keyForSave }: DropdownMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
13
16
|
export declare function MenuRightApi(): {
|
|
14
17
|
set(array: MenuElement[]): void;
|
|
15
18
|
delete(array: MenuElement[]): void;
|
|
16
19
|
get(): MenuElement[];
|
|
17
|
-
Render(
|
|
18
|
-
style?: React.CSSProperties;
|
|
19
|
-
}): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
Render(props?: MenuRightRenderProps): import("react/jsx-runtime").JSX.Element;
|
|
20
21
|
};
|
|
21
22
|
export declare function DropdownMenuTest(): import("react/jsx-runtime").JSX.Element;
|
|
22
|
-
export {};
|
|
@@ -5,7 +5,22 @@ import { useDraggable } from "../../hooks/useDraggable";
|
|
|
5
5
|
import { DivOutsideClick } from "../../hooks/useOutside";
|
|
6
6
|
import { DraggableOutlineDiv } from "../Dnd/DraggableOutlineDiv";
|
|
7
7
|
import { GetModalFuncJSX } from "../Modal/Modal";
|
|
8
|
-
|
|
8
|
+
import { mapRightMenu } from "./RightMenuStore";
|
|
9
|
+
export function DropdownMenu({ elements, style, position: initialPosition = 'right', position2: initialPos2 = 'top', keyForSave }) {
|
|
10
|
+
const [initialState] = useState(() => {
|
|
11
|
+
const fallback = {
|
|
12
|
+
position: initialPosition,
|
|
13
|
+
position2: initialPos2,
|
|
14
|
+
offset: { x: 0, y: 0 }
|
|
15
|
+
};
|
|
16
|
+
if (!keyForSave)
|
|
17
|
+
return fallback;
|
|
18
|
+
const saved = mapRightMenu.get(keyForSave);
|
|
19
|
+
if (saved)
|
|
20
|
+
return saved;
|
|
21
|
+
mapRightMenu.set(keyForSave, fallback);
|
|
22
|
+
return fallback;
|
|
23
|
+
});
|
|
9
24
|
const [isOpen, setIsOpen] = useState(false);
|
|
10
25
|
const [isFixed, setIsFixed] = useState(false);
|
|
11
26
|
const [select, setSelect] = useState(null);
|
|
@@ -13,41 +28,52 @@ export function DropdownMenu({ elements, style, position: initialPosition = 'rig
|
|
|
13
28
|
// Get modal JSX functions
|
|
14
29
|
const jsx = useMemo(GetModalFuncJSX, []);
|
|
15
30
|
const jsxRender = useMemo(() => _jsx(jsx.Render, {}), [jsx]);
|
|
16
|
-
const [position, setPosition] = useState(
|
|
17
|
-
const [isTop, setIsTop] = useState(
|
|
18
|
-
const positionLast = useRef({
|
|
31
|
+
const [position, setPosition] = useState(initialState.position);
|
|
32
|
+
const [isTop, setIsTop] = useState(initialState.position2 === 'top');
|
|
33
|
+
const positionLast = useRef({ ...initialState.offset });
|
|
34
|
+
const containerRef = useRef(null);
|
|
19
35
|
const handleDragEnd = useCallback((finalPosition) => {
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
positionLast.current.y
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
// Re-anchor from the computed dropped rect. useDraggable resets its delta
|
|
37
|
+
// before React necessarily paints, so measuring the element position here
|
|
38
|
+
// can read the pre-drop corner and cause a sudden relocation.
|
|
39
|
+
const el = containerRef.current;
|
|
40
|
+
if (!el)
|
|
41
|
+
return;
|
|
42
|
+
const parent = el.offsetParent;
|
|
43
|
+
// fixed positioning -> offsetParent is null -> viewport is the box
|
|
44
|
+
const bounds = parent?.getBoundingClientRect()
|
|
45
|
+
?? new DOMRect(0, 0, window.innerWidth, document.documentElement.clientHeight);
|
|
46
|
+
const measured = el.getBoundingClientRect();
|
|
47
|
+
const width = measured.width;
|
|
48
|
+
const height = measured.height;
|
|
49
|
+
const baseLeft = position === 'left'
|
|
50
|
+
? bounds.left + positionLast.current.x
|
|
51
|
+
: bounds.right - positionLast.current.x - width;
|
|
52
|
+
const baseTop = isTop
|
|
53
|
+
? bounds.top + positionLast.current.y
|
|
54
|
+
: bounds.bottom - positionLast.current.y - height;
|
|
55
|
+
const left = baseLeft + finalPosition.x;
|
|
56
|
+
const top = baseTop + finalPosition.y;
|
|
57
|
+
const right = left + width;
|
|
58
|
+
const bottom = top + height;
|
|
59
|
+
const toLeft = left + width / 2 < bounds.left + bounds.width / 2;
|
|
60
|
+
const toTop = top + height / 2 < bounds.top + bounds.height / 2;
|
|
61
|
+
const nextPosition = toLeft ? 'left' : 'right';
|
|
62
|
+
const nextOffset = {
|
|
63
|
+
x: Math.max(0, toLeft ? left - bounds.left : bounds.right - right),
|
|
64
|
+
y: Math.max(0, toTop ? top - bounds.top : bounds.bottom - bottom)
|
|
65
|
+
};
|
|
66
|
+
positionLast.current = nextOffset;
|
|
67
|
+
setPosition(nextPosition);
|
|
68
|
+
setIsTop(toTop);
|
|
69
|
+
if (keyForSave) {
|
|
70
|
+
mapRightMenu.set(keyForSave, {
|
|
71
|
+
position: nextPosition,
|
|
72
|
+
position2: toTop ? 'top' : 'bottom',
|
|
73
|
+
offset: { ...nextOffset }
|
|
74
|
+
});
|
|
49
75
|
}
|
|
50
|
-
}, [
|
|
76
|
+
}, [isTop, keyForSave, position]);
|
|
51
77
|
const { position: pos, dragProps } = useDraggable(0, 0, 50, handleDragEnd, () => { });
|
|
52
78
|
// Click and hover handlers
|
|
53
79
|
const handleClickOutside = useCallback(() => {
|
|
@@ -89,7 +115,11 @@ export function DropdownMenu({ elements, style, position: initialPosition = 'rig
|
|
|
89
115
|
[position]: 0,
|
|
90
116
|
right: position === 'left' ? 'auto' : 0,
|
|
91
117
|
flexDirection: position === 'left' ? 'row' : 'row-reverse'
|
|
92
|
-
}, children: [_jsx("div", { className: "dropdown-content", onMouseEnter: handleContentMouseEnter, onMouseLeave: handleContentMouseLeave, children: elements.map((item, index) => (_jsx("div", { className: `menu-item ${select === index ? 'force-hover' : ''}`, onMouseEnter: () => handleSelect(item, index), onClick: () => handleSelect(item, index), children: item.label }, item.label))) }), _jsx("div", { onMouseEnter: handleSubmenuMouseEnter, onMouseLeave: handleSubmenuMouseLeave, children: jsx.JSX ? (
|
|
118
|
+
}, children: [_jsx("div", { className: "dropdown-content", onMouseEnter: handleContentMouseEnter, onMouseLeave: handleContentMouseLeave, children: elements.map((item, index) => (_jsx("div", { className: `menu-item ${select === index ? 'force-hover' : ''}`, onMouseEnter: () => handleSelect(item, index), onClick: () => handleSelect(item, index), children: item.label }, item.label))) }), _jsx("div", { onMouseEnter: handleSubmenuMouseEnter, onMouseLeave: handleSubmenuMouseLeave, children: jsx.JSX ? (
|
|
119
|
+
// clamp to the viewport: with hard 40vw/70vh the submenu ran
|
|
120
|
+
// off screen when the menu sat near a bottom/side edge
|
|
121
|
+
_jsx("div", { className: "submenu", style: { width: '40vw', minHeight: '70vh',
|
|
122
|
+
maxWidth: '90vw', maxHeight: '85vh', overflowY: 'auto' }, children: jsxRender })) : null })] }));
|
|
93
123
|
// Calculate offsets
|
|
94
124
|
const computedX = position === 'left'
|
|
95
125
|
? positionLast.current.x + pos.x
|
|
@@ -123,7 +153,7 @@ export function DropdownMenu({ elements, style, position: initialPosition = 'rig
|
|
|
123
153
|
}
|
|
124
154
|
return computedStyle;
|
|
125
155
|
}, [style, position, isTop, computedX, computedY]);
|
|
126
|
-
return (_jsxs(DivOutsideClick, { outsideClick: handleClickOutside, className: `menu-container ${isFixed ? 'activeM' : ''}`, style: containerStyle, onMouseEnter: () => !isFixed && setIsOpen(true), onMouseLeave: () => !isFixed && setIsOpen(false), children: [_jsx("div", { ...dragProps, className: "menu-button", onClick: handleToggle, children: "\u2630" }), dop] }));
|
|
156
|
+
return (_jsxs(DivOutsideClick, { ref: containerRef, outsideClick: handleClickOutside, className: `menu-container ${isFixed ? 'activeM' : ''}`, style: containerStyle, onMouseEnter: () => !isFixed && setIsOpen(true), onMouseLeave: () => !isFixed && setIsOpen(false), children: [_jsx("div", { ...dragProps, className: "menu-button", onClick: handleToggle, children: "\u2630" }), dop] }));
|
|
127
157
|
}
|
|
128
158
|
export function MenuRightApi() {
|
|
129
159
|
const elements = [];
|
|
@@ -147,7 +177,7 @@ export function MenuRightApi() {
|
|
|
147
177
|
get() {
|
|
148
178
|
return elements;
|
|
149
179
|
},
|
|
150
|
-
Render(
|
|
180
|
+
Render(props = {}) {
|
|
151
181
|
const [el, setEl] = useState([...elements]);
|
|
152
182
|
useEffect(() => {
|
|
153
183
|
render = setEl;
|
|
@@ -155,7 +185,7 @@ export function MenuRightApi() {
|
|
|
155
185
|
render = null;
|
|
156
186
|
};
|
|
157
187
|
}, []);
|
|
158
|
-
return _jsx(DropdownMenu, { elements: el
|
|
188
|
+
return _jsx(DropdownMenu, { ...props, elements: el });
|
|
159
189
|
}
|
|
160
190
|
};
|
|
161
191
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type MenuRightPosition = 'left' | 'right';
|
|
2
|
+
export type MenuRightPosition2 = 'top' | 'bottom';
|
|
3
|
+
export type MenuRightSavedState = {
|
|
4
|
+
position: MenuRightPosition;
|
|
5
|
+
position2: MenuRightPosition2;
|
|
6
|
+
offset: {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export declare const mapRightMenu: Map<string, MenuRightSavedState>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const mapRightMenu = new Map();
|
|
@@ -17,6 +17,32 @@ export declare const tokens: {
|
|
|
17
17
|
readonly itemColor: "#fff";
|
|
18
18
|
readonly itemHoverColor: "#101010";
|
|
19
19
|
readonly itemHoverBgColor: "#fff";
|
|
20
|
+
readonly shadow: "0 0 20px 14px rgba(34, 60, 80, 0.2)";
|
|
21
|
+
};
|
|
22
|
+
/** DivRnd3 window chrome (--wnd-*). Defaults = legacy look; apps re-skin via :root[data-theme].
|
|
23
|
+
* --wnd-header-height/color/font-size/letter-spacing/transform are intentionally undeclared
|
|
24
|
+
* (inherit/auto) until a theme sets them. */
|
|
25
|
+
readonly wnd: {
|
|
26
|
+
readonly bg: "transparent";
|
|
27
|
+
readonly border: "none";
|
|
28
|
+
readonly radius: "0";
|
|
29
|
+
readonly shadow: "none";
|
|
30
|
+
readonly headerBg: "transparent";
|
|
31
|
+
readonly headerStripes: "repeating-linear-gradient(139deg, hsla(0, 0%, 100%, 0.1), hsla(0, 0%, 100%, 0.1) 15px, transparent 0, transparent 30px)";
|
|
32
|
+
readonly headerBorder: "none";
|
|
33
|
+
readonly headerPadding: "0";
|
|
34
|
+
readonly closeSize: "28px";
|
|
35
|
+
readonly closeTop: "-12px";
|
|
36
|
+
readonly closeRight: "-12px";
|
|
37
|
+
/** var(--color-bg-light) in CSS */
|
|
38
|
+
readonly closeBg: "#17202e";
|
|
39
|
+
/** var(--color-border-common) in CSS */
|
|
40
|
+
readonly closeBorder: "1px solid rgb(50, 62, 71)";
|
|
41
|
+
readonly closeShadow: "0 2px 6px rgba(0, 0, 0, 0.35)";
|
|
42
|
+
/** var(--color-text-base) in CSS */
|
|
43
|
+
readonly closeColor: "#c4c4c4";
|
|
44
|
+
readonly closeHover: "#fff";
|
|
45
|
+
readonly closeHoverBg: "#e5484d";
|
|
20
46
|
};
|
|
21
47
|
readonly font: {
|
|
22
48
|
readonly family: "Roboto";
|
|
@@ -19,6 +19,32 @@ export const tokens = {
|
|
|
19
19
|
itemColor: '#fff',
|
|
20
20
|
itemHoverColor: '#101010',
|
|
21
21
|
itemHoverBgColor: '#fff',
|
|
22
|
+
shadow: '0 0 20px 14px rgba(34, 60, 80, 0.2)',
|
|
23
|
+
},
|
|
24
|
+
/** DivRnd3 window chrome (--wnd-*). Defaults = legacy look; apps re-skin via :root[data-theme].
|
|
25
|
+
* --wnd-header-height/color/font-size/letter-spacing/transform are intentionally undeclared
|
|
26
|
+
* (inherit/auto) until a theme sets them. */
|
|
27
|
+
wnd: {
|
|
28
|
+
bg: 'transparent',
|
|
29
|
+
border: 'none',
|
|
30
|
+
radius: '0',
|
|
31
|
+
shadow: 'none',
|
|
32
|
+
headerBg: 'transparent',
|
|
33
|
+
headerStripes: 'repeating-linear-gradient(139deg, hsla(0, 0%, 100%, 0.1), hsla(0, 0%, 100%, 0.1) 15px, transparent 0, transparent 30px)',
|
|
34
|
+
headerBorder: 'none',
|
|
35
|
+
headerPadding: '0',
|
|
36
|
+
closeSize: '28px',
|
|
37
|
+
closeTop: '-12px',
|
|
38
|
+
closeRight: '-12px',
|
|
39
|
+
/** var(--color-bg-light) in CSS */
|
|
40
|
+
closeBg: '#17202e',
|
|
41
|
+
/** var(--color-border-common) in CSS */
|
|
42
|
+
closeBorder: '1px solid rgb(50, 62, 71)',
|
|
43
|
+
closeShadow: '0 2px 6px rgba(0, 0, 0, 0.35)',
|
|
44
|
+
/** var(--color-text-base) in CSS */
|
|
45
|
+
closeColor: '#c4c4c4',
|
|
46
|
+
closeHover: '#fff',
|
|
47
|
+
closeHoverBg: '#e5484d',
|
|
22
48
|
},
|
|
23
49
|
font: {
|
|
24
50
|
family: 'Roboto',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { deepClone } from "wenay-common2";
|
|
2
2
|
import { ExRNDMap3 } from "../components/Dnd/RNDFunc3";
|
|
3
3
|
import { mapResiReact } from "../components/Dnd/Resizable";
|
|
4
|
+
import { mapRightMenu } from "../components/Menu/RightMenuStore";
|
|
4
5
|
import { CacheFuncMap } from "./cache";
|
|
5
6
|
const staticProps = new Map();
|
|
6
7
|
export function staticSet(key, data) {
|
|
@@ -63,10 +64,12 @@ export function staticGetById(key, def, id) {
|
|
|
63
64
|
export const Cash = CacheFuncMap([
|
|
64
65
|
["mapResiReact", mapResiReact],
|
|
65
66
|
["ExRNDMap3", ExRNDMap3],
|
|
67
|
+
["mapRightMenu", mapRightMenu],
|
|
66
68
|
["staticProps", staticProps]
|
|
67
69
|
]);
|
|
68
70
|
export const MemoryMap = {
|
|
69
71
|
rnd: ExRNDMap3,
|
|
70
72
|
resize: mapResiReact,
|
|
73
|
+
rightMenu: mapRightMenu,
|
|
71
74
|
other: staticProps
|
|
72
75
|
};
|
package/lib/style/style.css
CHANGED
|
@@ -136,11 +136,11 @@ input:invalid {
|
|
|
136
136
|
|
|
137
137
|
/* Menu */
|
|
138
138
|
.MenuR {
|
|
139
|
-
box-shadow:
|
|
139
|
+
box-shadow: var(--menu-shadow);
|
|
140
140
|
margin-top: 4px;
|
|
141
141
|
min-width: 80px;
|
|
142
142
|
width: max-content;
|
|
143
|
-
background:
|
|
143
|
+
background: var(--menu-bg-color);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
.maxSize {
|
|
@@ -319,28 +319,69 @@ body {
|
|
|
319
319
|
margin-left: -1px;
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
/* DivRnd3 window chrome. All visuals go through --wnd-* tokens (tokens.css);
|
|
323
|
+
defaults reproduce the legacy look, apps re-skin via :root[data-theme] token overrides. */
|
|
324
|
+
.wenayWnd {
|
|
325
|
+
background: var(--wnd-bg);
|
|
326
|
+
border: var(--wnd-border);
|
|
327
|
+
border-radius: var(--wnd-radius);
|
|
328
|
+
box-shadow: var(--wnd-shadow);
|
|
329
|
+
}
|
|
330
|
+
/* Header drag zone. Color/font tokens are undeclared by default: an unresolved var()
|
|
331
|
+
makes the property fall back to its inherited value, i.e. exactly the legacy look. */
|
|
332
|
+
.wenayWndHeader {
|
|
333
|
+
user-select: none;
|
|
334
|
+
cursor: grabbing;
|
|
335
|
+
height: var(--wnd-header-height, auto);
|
|
336
|
+
padding: var(--wnd-header-padding);
|
|
337
|
+
background: var(--wnd-header-bg);
|
|
338
|
+
border-bottom: var(--wnd-header-border);
|
|
339
|
+
border-top-left-radius: var(--wnd-radius);
|
|
340
|
+
border-top-right-radius: var(--wnd-radius);
|
|
341
|
+
color: var(--wnd-header-color, inherit);
|
|
342
|
+
font-size: var(--wnd-header-font-size, inherit);
|
|
343
|
+
letter-spacing: var(--wnd-header-letter-spacing, inherit);
|
|
344
|
+
text-transform: var(--wnd-header-transform, inherit);
|
|
345
|
+
}
|
|
346
|
+
/* Default header content when no header element is passed (striped drag strip) */
|
|
347
|
+
.wenayWndHeaderDef {
|
|
348
|
+
height: var(--wnd-header-height, 20px);
|
|
349
|
+
width: 100%;
|
|
350
|
+
background: var(--wnd-header-stripes);
|
|
351
|
+
}
|
|
352
|
+
|
|
322
353
|
/* Window close button (DivRnd3 and others) */
|
|
323
354
|
.wenayCloseBtn {
|
|
324
|
-
width: 28px;
|
|
325
|
-
height: 28px;
|
|
355
|
+
width: var(--wnd-close-size, 28px);
|
|
356
|
+
height: var(--wnd-close-size, 28px);
|
|
357
|
+
/* keep the clickable zone >= 24x24 whatever the theme sets */
|
|
358
|
+
min-width: 24px;
|
|
359
|
+
min-height: 24px;
|
|
326
360
|
display: flex;
|
|
327
361
|
align-items: center;
|
|
328
362
|
justify-content: center;
|
|
329
363
|
border-radius: 50%;
|
|
330
|
-
background: var(--color-bg-light);
|
|
331
|
-
border: 1px solid var(--color-border-common);
|
|
332
|
-
color: var(--color-text-base);
|
|
364
|
+
background: var(--wnd-close-bg, var(--color-bg-light));
|
|
365
|
+
border: var(--wnd-close-border, 1px solid var(--color-border-common));
|
|
366
|
+
color: var(--wnd-close-color, var(--color-text-base));
|
|
333
367
|
cursor: pointer;
|
|
334
368
|
user-select: none;
|
|
335
|
-
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
|
|
369
|
+
box-shadow: var(--wnd-close-shadow, 0 2px 6px rgba(0, 0, 0, 0.35));
|
|
336
370
|
transition: background 0.15s, color 0.15s, transform 0.15s;
|
|
337
371
|
}
|
|
338
372
|
.wenayCloseBtn:hover {
|
|
339
|
-
background: #e5484d;
|
|
340
|
-
border-color: #e5484d;
|
|
341
|
-
color: #fff;
|
|
373
|
+
background: var(--wnd-close-hover-bg, #e5484d);
|
|
374
|
+
border-color: var(--wnd-close-hover-bg, #e5484d);
|
|
375
|
+
color: var(--wnd-close-hover, #fff);
|
|
342
376
|
transform: scale(1.08);
|
|
343
377
|
}
|
|
344
378
|
.wenayCloseBtn:active {
|
|
345
379
|
transform: scale(0.95);
|
|
346
380
|
}
|
|
381
|
+
/* Positioning of the close button inside DivRnd3. Kept separate from .wenayCloseBtn,
|
|
382
|
+
which may be used outside windows and must not become position:absolute there. */
|
|
383
|
+
.wenayWndClose {
|
|
384
|
+
position: absolute;
|
|
385
|
+
top: var(--wnd-close-top, -12px);
|
|
386
|
+
right: var(--wnd-close-right, -12px);
|
|
387
|
+
}
|
package/lib/style/tokens.css
CHANGED
|
@@ -29,6 +29,39 @@
|
|
|
29
29
|
--menu-item-hover-color: #101010;
|
|
30
30
|
--menu-item-hover-bg-color: var(--base-color-hover);
|
|
31
31
|
|
|
32
|
+
/* Menu shadow (was a literal in .MenuR) */
|
|
33
|
+
--menu-shadow: 0 0 20px 14px rgba(34, 60, 80, 0.2);
|
|
34
|
+
|
|
35
|
+
/* Window (DivRnd3) chrome. Defaults = legacy look, so apps without themes do not change.
|
|
36
|
+
Apps re-skin via :root[data-theme='...'] overrides, same contract as --color-* / --menu-*.
|
|
37
|
+
Intentionally NOT declared here (fall back to inherit/auto until a theme declares them):
|
|
38
|
+
--wnd-header-height, --wnd-header-color, --wnd-header-font-size,
|
|
39
|
+
--wnd-header-letter-spacing, --wnd-header-transform */
|
|
40
|
+
--wnd-bg: transparent;
|
|
41
|
+
--wnd-border: none;
|
|
42
|
+
--wnd-radius: 0;
|
|
43
|
+
--wnd-shadow: none;
|
|
44
|
+
|
|
45
|
+
/* Header drag zone: wrapper background (solid in themes) vs default striped strip.
|
|
46
|
+
Themes typically set --wnd-header-bg to a panel color and --wnd-header-stripes to none. */
|
|
47
|
+
--wnd-header-bg: transparent;
|
|
48
|
+
--wnd-header-stripes: repeating-linear-gradient(139deg, hsla(0, 0%, 100%, 0.1), hsla(0, 0%, 100%, 0.1) 15px, transparent 0, transparent 30px);
|
|
49
|
+
--wnd-header-border: none;
|
|
50
|
+
--wnd-header-padding: 0;
|
|
51
|
+
|
|
52
|
+
/* Close button. Legacy: floating circle at the window's top-right corner.
|
|
53
|
+
Themes move it into the header (top/right offsets) and strip the circle chrome.
|
|
54
|
+
Clickable zone is clamped to >= 24x24 in CSS regardless of --wnd-close-size. */
|
|
55
|
+
--wnd-close-size: 28px;
|
|
56
|
+
--wnd-close-top: -12px;
|
|
57
|
+
--wnd-close-right: -12px;
|
|
58
|
+
--wnd-close-bg: var(--color-bg-light);
|
|
59
|
+
--wnd-close-border: 1px solid var(--color-border-common);
|
|
60
|
+
--wnd-close-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
|
|
61
|
+
--wnd-close-color: var(--color-text-base);
|
|
62
|
+
--wnd-close-hover: #fff;
|
|
63
|
+
--wnd-close-hover-bg: #e5484d;
|
|
64
|
+
|
|
32
65
|
/* Layers */
|
|
33
66
|
--wenay-z-modal: 9999;
|
|
34
67
|
}
|