@lobehub/ui 5.6.4 → 5.7.0
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/es/DraggablePanel/DraggablePanel.mjs +309 -150
- package/es/DraggablePanel/DraggablePanel.mjs.map +1 -1
- package/es/DraggablePanel/type.d.mts +5 -0
- package/es/Menu/sharedStyle.mjs +1 -2
- package/es/Menu/sharedStyle.mjs.map +1 -1
- package/es/Modal/Modal.mjs +1 -1
- package/es/Modal/Modal.mjs.map +1 -1
- package/es/Modal/ModalStackItem.mjs +1 -1
- package/es/Modal/ModalStackItem.mjs.map +1 -1
- package/es/Modal/RawModalStackItem.mjs +1 -1
- package/es/Modal/RawModalStackItem.mjs.map +1 -1
- package/es/Modal/imperative.mjs +2 -2
- package/es/Modal/imperative.mjs.map +1 -1
- package/es/base-ui/Popover/style.mjs +1 -2
- package/es/base-ui/Popover/style.mjs.map +1 -1
- package/es/hooks/useMermaid.mjs +6 -5
- package/es/hooks/useMermaid.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import Center from "../Flex/Center.mjs";
|
|
|
3
3
|
import Icon from "../Icon/Icon.mjs";
|
|
4
4
|
import { handleVariants, panelVariants, styles, toggleVariants } from "./style.mjs";
|
|
5
5
|
import { reversePlacement } from "./utils.mjs";
|
|
6
|
-
import { memo, use, useCallback, useEffect, useMemo,
|
|
6
|
+
import { memo, startTransition, use, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { ConfigProvider } from "antd";
|
|
9
9
|
import { cx } from "antd-style";
|
|
@@ -13,66 +13,65 @@ import { useHover } from "ahooks";
|
|
|
13
13
|
import isEqual from "fast-deep-equal";
|
|
14
14
|
import { Resizable } from "re-resizable";
|
|
15
15
|
//#region src/DraggablePanel/DraggablePanel.tsx
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
const DraggablePanel = memo(({ headerHeight =
|
|
16
|
+
const ARROW_MAP = {
|
|
17
|
+
bottom: ChevronUp,
|
|
18
|
+
left: ChevronRight,
|
|
19
|
+
right: ChevronLeft,
|
|
20
|
+
top: ChevronDown
|
|
21
|
+
};
|
|
22
|
+
const MARGIN_MAP = {
|
|
23
|
+
bottom: { marginTop: 4 },
|
|
24
|
+
left: { marginRight: 4 },
|
|
25
|
+
right: { marginLeft: 4 },
|
|
26
|
+
top: { marginBottom: 4 }
|
|
27
|
+
};
|
|
28
|
+
const DISABLED_RESIZING = {
|
|
29
|
+
bottom: false,
|
|
30
|
+
bottomLeft: false,
|
|
31
|
+
bottomRight: false,
|
|
32
|
+
left: false,
|
|
33
|
+
right: false,
|
|
34
|
+
top: false,
|
|
35
|
+
topLeft: false,
|
|
36
|
+
topRight: false
|
|
37
|
+
};
|
|
38
|
+
const toCssSize = (value, fallback) => {
|
|
39
|
+
if (typeof value === "number") return `${Math.max(value, 0)}px`;
|
|
40
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
41
|
+
return fallback;
|
|
42
|
+
};
|
|
43
|
+
const DraggablePanel = memo(({ headerHeight = 0, fullscreen, maxHeight, pin = true, mode = "fixed", children, placement = "right", resize, style, showBorder = true, showHandleHighlight = false, showHandleWideArea = true, backgroundColor, size, stableLayout = false, defaultSize: customizeDefaultSize, minWidth, minHeight, maxWidth, onSizeChange, onSizeDragging, expandable = true, expand, defaultExpand = true, onExpandChange, className, showHandleWhenCollapsed, destroyOnClose, styles: customStyles, classNames, dir }) => {
|
|
44
44
|
const ref = useRef(null);
|
|
45
45
|
const isHovering = useHover(ref);
|
|
46
46
|
const isVertical = placement === "top" || placement === "bottom";
|
|
47
|
-
const [isPending, startTransition] = useTransition();
|
|
48
47
|
const hoverTimeoutRef = useRef(void 0);
|
|
48
|
+
const resetTransitionTimeoutRef = useRef(void 0);
|
|
49
|
+
const resizableRef = useRef(null);
|
|
50
|
+
const initialExpandedSizeRef = useRef(void 0);
|
|
49
51
|
const { direction: antdDirection } = use(ConfigProvider.ConfigContext);
|
|
50
52
|
const direction = dir ?? antdDirection;
|
|
51
53
|
const internalPlacement = useMemo(() => {
|
|
52
|
-
|
|
54
|
+
if (direction !== "rtl") return placement;
|
|
55
|
+
if (placement === "left") return "right";
|
|
56
|
+
if (placement === "right") return "left";
|
|
57
|
+
return placement;
|
|
53
58
|
}, [direction, placement]);
|
|
54
|
-
const cssVariables =
|
|
59
|
+
const cssVariables = {
|
|
55
60
|
"--draggable-panel-bg": backgroundColor || "",
|
|
56
61
|
"--draggable-panel-header-height": `${headerHeight}px`
|
|
57
|
-
}
|
|
62
|
+
};
|
|
58
63
|
const [isExpand, setIsExpand] = useMergeState(defaultExpand, {
|
|
59
64
|
onChange: onExpandChange,
|
|
60
65
|
value: expand
|
|
61
66
|
});
|
|
62
|
-
const [
|
|
63
|
-
|
|
64
|
-
showExpand: true
|
|
65
|
-
});
|
|
67
|
+
const [shouldTransition, setShouldTransition] = useState(true);
|
|
68
|
+
const [showExpand, setShowExpand] = useState(true);
|
|
66
69
|
useEffect(() => {
|
|
67
70
|
if (pin) return;
|
|
68
71
|
if (hoverTimeoutRef.current) clearTimeout(hoverTimeoutRef.current);
|
|
69
|
-
if (isHovering && !isExpand) startTransition(() =>
|
|
70
|
-
setIsExpand(true);
|
|
71
|
-
});
|
|
72
|
+
if (isHovering && !isExpand) startTransition(() => setIsExpand(true));
|
|
72
73
|
else if (!isHovering && isExpand) hoverTimeoutRef.current = setTimeout(() => {
|
|
73
|
-
startTransition(() =>
|
|
74
|
-
setIsExpand(false);
|
|
75
|
-
});
|
|
74
|
+
startTransition(() => setIsExpand(false));
|
|
76
75
|
}, 150);
|
|
77
76
|
}, [
|
|
78
77
|
pin,
|
|
@@ -83,8 +82,13 @@ const DraggablePanel = memo(({ headerHeight = DEFAULT_HEADER_HEIGHT, fullscreen,
|
|
|
83
82
|
useEffect(() => {
|
|
84
83
|
return () => {
|
|
85
84
|
if (hoverTimeoutRef.current) clearTimeout(hoverTimeoutRef.current);
|
|
85
|
+
if (resetTransitionTimeoutRef.current) clearTimeout(resetTransitionTimeoutRef.current);
|
|
86
86
|
};
|
|
87
87
|
}, []);
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
initialExpandedSizeRef.current = void 0;
|
|
90
|
+
}, [internalPlacement]);
|
|
91
|
+
const reversed = reversePlacement(internalPlacement);
|
|
88
92
|
const canResizing = resize !== false && isExpand;
|
|
89
93
|
const resizing = useMemo(() => ({
|
|
90
94
|
bottom: false,
|
|
@@ -95,23 +99,27 @@ const DraggablePanel = memo(({ headerHeight = DEFAULT_HEADER_HEIGHT, fullscreen,
|
|
|
95
99
|
top: false,
|
|
96
100
|
topLeft: false,
|
|
97
101
|
topRight: false,
|
|
98
|
-
[
|
|
102
|
+
[reversed]: true,
|
|
99
103
|
...resize
|
|
100
|
-
}), [
|
|
104
|
+
}), [reversed, resize]);
|
|
101
105
|
const defaultSize = useMemo(() => {
|
|
102
106
|
if (isVertical) return {
|
|
103
|
-
height:
|
|
107
|
+
height: 180,
|
|
104
108
|
width: "100%",
|
|
105
109
|
...customizeDefaultSize
|
|
106
110
|
};
|
|
107
111
|
return {
|
|
108
112
|
height: "100%",
|
|
109
|
-
width:
|
|
113
|
+
width: 280,
|
|
110
114
|
...customizeDefaultSize
|
|
111
115
|
};
|
|
112
116
|
}, [isVertical, customizeDefaultSize]);
|
|
117
|
+
const normalizedMaxHeight = typeof maxHeight === "number" ? Math.max(maxHeight, 0) : void 0;
|
|
118
|
+
const normalizedMaxWidth = typeof maxWidth === "number" ? Math.max(maxWidth, 0) : void 0;
|
|
119
|
+
const normalizedMinHeight = typeof minHeight === "number" ? Math.max(minHeight, 0) : void 0;
|
|
120
|
+
const normalizedMinWidth = typeof minWidth === "number" ? Math.max(minWidth, 0) : void 0;
|
|
113
121
|
const sizeProps = useMemo(() => {
|
|
114
|
-
if (!isExpand) return isVertical ? {
|
|
122
|
+
if (!stableLayout && !isExpand) return isVertical ? {
|
|
115
123
|
minHeight: 0,
|
|
116
124
|
size: { height: 0 }
|
|
117
125
|
} : {
|
|
@@ -120,143 +128,294 @@ const DraggablePanel = memo(({ headerHeight = DEFAULT_HEADER_HEIGHT, fullscreen,
|
|
|
120
128
|
};
|
|
121
129
|
return {
|
|
122
130
|
defaultSize,
|
|
123
|
-
maxHeight:
|
|
124
|
-
maxWidth:
|
|
125
|
-
minHeight:
|
|
126
|
-
minWidth:
|
|
131
|
+
maxHeight: normalizedMaxHeight,
|
|
132
|
+
maxWidth: normalizedMaxWidth,
|
|
133
|
+
minHeight: normalizedMinHeight,
|
|
134
|
+
minWidth: normalizedMinWidth,
|
|
127
135
|
size
|
|
128
136
|
};
|
|
129
137
|
}, [
|
|
138
|
+
stableLayout,
|
|
130
139
|
isExpand,
|
|
131
140
|
isVertical,
|
|
132
141
|
defaultSize,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
142
|
+
normalizedMaxHeight,
|
|
143
|
+
normalizedMaxWidth,
|
|
144
|
+
normalizedMinHeight,
|
|
145
|
+
normalizedMinWidth,
|
|
137
146
|
size
|
|
138
147
|
]);
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
148
|
+
const fallbackExpandedSize = isVertical ? "180px" : "280px";
|
|
149
|
+
const controlledExpandedSize = useMemo(() => {
|
|
150
|
+
const controlledSize = isVertical ? size?.height : size?.width;
|
|
151
|
+
if (controlledSize === void 0) return void 0;
|
|
152
|
+
return toCssSize(controlledSize, fallbackExpandedSize);
|
|
153
|
+
}, [
|
|
154
|
+
isVertical,
|
|
155
|
+
size?.height,
|
|
156
|
+
size?.width,
|
|
157
|
+
fallbackExpandedSize
|
|
158
|
+
]);
|
|
159
|
+
const defaultExpandedSize = useMemo(() => {
|
|
160
|
+
return toCssSize(isVertical ? defaultSize.height : defaultSize.width, fallbackExpandedSize);
|
|
161
|
+
}, [
|
|
162
|
+
isVertical,
|
|
163
|
+
defaultSize.height,
|
|
164
|
+
defaultSize.width,
|
|
165
|
+
fallbackExpandedSize
|
|
166
|
+
]);
|
|
167
|
+
const [resizedExpandedSize, setResizedExpandedSize] = useState({});
|
|
168
|
+
const expandedOuterSize = controlledExpandedSize ?? (isVertical ? resizedExpandedSize.vertical : resizedExpandedSize.horizontal) ?? defaultExpandedSize;
|
|
169
|
+
const setExpandedMainSize = useCallback((nextSize) => {
|
|
170
|
+
if (!stableLayout) return;
|
|
171
|
+
const currentSize = isVertical ? nextSize.height : nextSize.width;
|
|
172
|
+
if (!currentSize) return;
|
|
173
|
+
const normalizedSize = toCssSize(currentSize, fallbackExpandedSize);
|
|
174
|
+
setResizedExpandedSize((state) => isVertical ? {
|
|
175
|
+
...state,
|
|
176
|
+
vertical: normalizedSize
|
|
177
|
+
} : {
|
|
178
|
+
...state,
|
|
179
|
+
horizontal: normalizedSize
|
|
152
180
|
});
|
|
181
|
+
}, [
|
|
182
|
+
fallbackExpandedSize,
|
|
183
|
+
isVertical,
|
|
184
|
+
stableLayout
|
|
185
|
+
]);
|
|
186
|
+
const captureInitialExpandedSize = useCallback(() => {
|
|
187
|
+
if (initialExpandedSizeRef.current) return initialExpandedSizeRef.current;
|
|
188
|
+
const rect = resizableRef.current?.resizable?.getBoundingClientRect();
|
|
189
|
+
if (!rect) return void 0;
|
|
190
|
+
const nextInitialSize = isVertical ? {
|
|
191
|
+
height: rect.height,
|
|
192
|
+
width: "100%"
|
|
193
|
+
} : {
|
|
194
|
+
height: "100%",
|
|
195
|
+
width: rect.width
|
|
196
|
+
};
|
|
197
|
+
initialExpandedSizeRef.current = nextInitialSize;
|
|
198
|
+
return nextInitialSize;
|
|
199
|
+
}, [isVertical]);
|
|
200
|
+
useEffect(() => {
|
|
201
|
+
if (!isExpand) return;
|
|
202
|
+
captureInitialExpandedSize();
|
|
203
|
+
}, [captureInitialExpandedSize, isExpand]);
|
|
204
|
+
const toggleExpand = useCallback(() => {
|
|
205
|
+
if (expandable) setIsExpand(!isExpand);
|
|
153
206
|
}, [
|
|
154
207
|
expandable,
|
|
155
208
|
isExpand,
|
|
156
209
|
setIsExpand
|
|
157
210
|
]);
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
marginRight: internalPlacement === "left" ? 4 : 0,
|
|
176
|
-
marginTop: internalPlacement === "bottom" ? 4 : 0,
|
|
177
|
-
transform: `rotate(${isExpand ? 180 : 0}deg)`,
|
|
178
|
-
transition: "transform 0.3s ease"
|
|
179
|
-
}
|
|
180
|
-
})
|
|
181
|
-
})
|
|
182
|
-
}), [
|
|
183
|
-
toggleVariants,
|
|
184
|
-
internalPlacement,
|
|
185
|
-
isExpand,
|
|
186
|
-
pin,
|
|
187
|
-
showHandleWhenCollapsed,
|
|
188
|
-
classNames?.handle,
|
|
189
|
-
toggleExpand,
|
|
190
|
-
customStyles?.handle,
|
|
191
|
-
styles.handlerIcon,
|
|
192
|
-
Arrow
|
|
193
|
-
]);
|
|
194
|
-
const handleResize = useCallback((_, _direction, reference_, delta) => {
|
|
195
|
-
onSizeDragging?.(delta, {
|
|
196
|
-
height: reference_.style.height,
|
|
197
|
-
width: reference_.style.width
|
|
211
|
+
const clampResizeSize = useCallback((el) => {
|
|
212
|
+
const rect = el.getBoundingClientRect();
|
|
213
|
+
const currentMainSize = isVertical ? rect.height : rect.width;
|
|
214
|
+
const minMainSize = isVertical ? normalizedMinHeight : normalizedMinWidth;
|
|
215
|
+
const maxMainSize = isVertical ? normalizedMaxHeight : normalizedMaxWidth;
|
|
216
|
+
let clampedMainSize = currentMainSize;
|
|
217
|
+
if (typeof minMainSize === "number") clampedMainSize = Math.max(clampedMainSize, minMainSize);
|
|
218
|
+
if (typeof maxMainSize === "number") clampedMainSize = Math.min(clampedMainSize, maxMainSize);
|
|
219
|
+
if (!Number.isFinite(clampedMainSize) || Math.abs(clampedMainSize - currentMainSize) < .5) return {
|
|
220
|
+
height: el.style.height,
|
|
221
|
+
width: el.style.width
|
|
222
|
+
};
|
|
223
|
+
const width = isVertical ? el.style.width || "100%" : `${clampedMainSize}px`;
|
|
224
|
+
const height = isVertical ? `${clampedMainSize}px` : el.style.height || "100%";
|
|
225
|
+
resizableRef.current?.updateSize({
|
|
226
|
+
height,
|
|
227
|
+
width
|
|
198
228
|
});
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
229
|
+
return {
|
|
230
|
+
height,
|
|
231
|
+
width
|
|
232
|
+
};
|
|
233
|
+
}, [
|
|
234
|
+
isVertical,
|
|
235
|
+
normalizedMaxHeight,
|
|
236
|
+
normalizedMaxWidth,
|
|
237
|
+
normalizedMinHeight,
|
|
238
|
+
normalizedMinWidth
|
|
239
|
+
]);
|
|
240
|
+
const handleResize = useCallback((_event, _direction, el, delta) => {
|
|
241
|
+
const nextSize = clampResizeSize(el);
|
|
242
|
+
setExpandedMainSize(nextSize);
|
|
243
|
+
onSizeDragging?.(delta, nextSize);
|
|
244
|
+
}, [
|
|
245
|
+
clampResizeSize,
|
|
246
|
+
onSizeDragging,
|
|
247
|
+
setExpandedMainSize
|
|
248
|
+
]);
|
|
249
|
+
const triggerResetWithoutTransition = useCallback(() => {
|
|
250
|
+
if (resetTransitionTimeoutRef.current) clearTimeout(resetTransitionTimeoutRef.current);
|
|
251
|
+
setShouldTransition(false);
|
|
252
|
+
resetTransitionTimeoutRef.current = setTimeout(() => {
|
|
253
|
+
setShouldTransition(true);
|
|
254
|
+
}, 0);
|
|
202
255
|
}, []);
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
256
|
+
const handleResetSize = useCallback(() => {
|
|
257
|
+
if (!canResizing) return;
|
|
258
|
+
const resetSize = captureInitialExpandedSize();
|
|
259
|
+
if (!resetSize) return;
|
|
260
|
+
triggerResetWithoutTransition();
|
|
261
|
+
const rect = resizableRef.current?.resizable?.getBoundingClientRect();
|
|
262
|
+
const prevMainSize = rect ? isVertical ? rect.height : rect.width : 0;
|
|
263
|
+
const resetMainSize = isVertical ? resetSize.height : resetSize.width;
|
|
264
|
+
const nextMainSize = typeof resetMainSize === "number" ? resetMainSize : prevMainSize;
|
|
265
|
+
resizableRef.current?.updateSize(resetSize);
|
|
266
|
+
setExpandedMainSize(resetSize);
|
|
267
|
+
onSizeChange?.(isVertical ? {
|
|
268
|
+
height: nextMainSize - prevMainSize,
|
|
269
|
+
width: 0
|
|
270
|
+
} : {
|
|
271
|
+
height: 0,
|
|
272
|
+
width: nextMainSize - prevMainSize
|
|
273
|
+
}, resetSize);
|
|
274
|
+
}, [
|
|
275
|
+
canResizing,
|
|
276
|
+
captureInitialExpandedSize,
|
|
277
|
+
isVertical,
|
|
278
|
+
onSizeChange,
|
|
279
|
+
setExpandedMainSize,
|
|
280
|
+
triggerResetWithoutTransition
|
|
281
|
+
]);
|
|
282
|
+
const handleResizeStart = useCallback((event) => {
|
|
283
|
+
if (event.detail === 2) {
|
|
284
|
+
handleResetSize();
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
if (resetTransitionTimeoutRef.current) {
|
|
288
|
+
clearTimeout(resetTransitionTimeoutRef.current);
|
|
289
|
+
resetTransitionTimeoutRef.current = void 0;
|
|
290
|
+
}
|
|
291
|
+
setShouldTransition(false);
|
|
292
|
+
setShowExpand(false);
|
|
293
|
+
}, [handleResetSize]);
|
|
294
|
+
const handleResizeStop = useCallback((_event, _direction, el, delta) => {
|
|
295
|
+
const nextSize = clampResizeSize(el);
|
|
296
|
+
setExpandedMainSize(nextSize);
|
|
297
|
+
setShouldTransition(true);
|
|
298
|
+
setShowExpand(true);
|
|
299
|
+
onSizeChange?.(delta, nextSize);
|
|
300
|
+
}, [
|
|
301
|
+
clampResizeSize,
|
|
302
|
+
onSizeChange,
|
|
303
|
+
setExpandedMainSize
|
|
304
|
+
]);
|
|
305
|
+
const resizeHandleClassName = useMemo(() => cx(handleVariants({ placement: reversed }), showHandleHighlight && styles.handleHighlight), [reversed, showHandleHighlight]);
|
|
306
|
+
if (fullscreen) return /* @__PURE__ */ jsx("div", {
|
|
307
|
+
className: cx(styles.fullscreen, className),
|
|
308
|
+
style: cssVariables,
|
|
309
|
+
children
|
|
310
|
+
});
|
|
311
|
+
const Arrow = ARROW_MAP[internalPlacement] ?? ChevronLeft;
|
|
312
|
+
const stableOuterFlex = stableLayout ? {
|
|
313
|
+
display: "flex",
|
|
314
|
+
flexDirection: "column",
|
|
315
|
+
minHeight: 0
|
|
316
|
+
} : {};
|
|
317
|
+
const sidebarOuterStyle = isVertical ? {
|
|
318
|
+
height: isExpand ? expandedOuterSize : 0,
|
|
319
|
+
overflow: "hidden",
|
|
320
|
+
transition: shouldTransition ? "height 0.2s var(--ant-motion-ease-out, ease)" : "none",
|
|
321
|
+
width: "100%",
|
|
322
|
+
...stableOuterFlex
|
|
323
|
+
} : {
|
|
324
|
+
overflow: "hidden",
|
|
325
|
+
transition: shouldTransition ? "width 0.2s var(--ant-motion-ease-out, ease)" : "none",
|
|
326
|
+
width: isExpand ? expandedOuterSize : 0,
|
|
327
|
+
...stableLayout ? {
|
|
328
|
+
...stableOuterFlex,
|
|
329
|
+
flex: 1,
|
|
330
|
+
minWidth: 0,
|
|
331
|
+
height: "100%"
|
|
332
|
+
} : {}
|
|
333
|
+
};
|
|
334
|
+
const sidebarInnerStyle = stableLayout ? {
|
|
335
|
+
display: "flex",
|
|
336
|
+
flex: 1,
|
|
337
|
+
flexDirection: "column",
|
|
338
|
+
height: "100%",
|
|
339
|
+
minHeight: 0,
|
|
340
|
+
minWidth: 0,
|
|
341
|
+
width: "100%"
|
|
342
|
+
} : isVertical ? {
|
|
343
|
+
height: "100%",
|
|
344
|
+
width: "100%"
|
|
345
|
+
} : { width: "100%" };
|
|
346
|
+
const stableAsideStyle = stableLayout ? {
|
|
347
|
+
display: "flex",
|
|
348
|
+
flexDirection: "column",
|
|
349
|
+
minHeight: 0,
|
|
350
|
+
...mode === "fixed" ? { height: "100%" } : {}
|
|
351
|
+
} : {};
|
|
352
|
+
const stableResizableStyle = {
|
|
353
|
+
display: "flex",
|
|
354
|
+
flex: 1,
|
|
355
|
+
flexDirection: "column",
|
|
356
|
+
height: "100%",
|
|
357
|
+
minHeight: 0,
|
|
358
|
+
minWidth: 0,
|
|
359
|
+
width: "100%"
|
|
360
|
+
};
|
|
361
|
+
const panelNode = (!destroyOnClose || isExpand) && /* @__PURE__ */ jsx(Resizable, {
|
|
362
|
+
ref: resizableRef,
|
|
211
363
|
...sizeProps,
|
|
212
364
|
className: cx(styles.panel, classNames?.content),
|
|
213
|
-
enable: canResizing ? resizing :
|
|
214
|
-
handleClasses: canResizing ? { [
|
|
365
|
+
enable: canResizing ? resizing : DISABLED_RESIZING,
|
|
366
|
+
handleClasses: canResizing ? { [reversed]: resizeHandleClassName } : {},
|
|
215
367
|
style: {
|
|
216
368
|
...cssVariables,
|
|
217
|
-
|
|
218
|
-
|
|
369
|
+
transition: shouldTransition ? void 0 : "none",
|
|
370
|
+
...stableLayout ? stableResizableStyle : {},
|
|
219
371
|
...style
|
|
220
372
|
},
|
|
221
373
|
onResize: handleResize,
|
|
222
374
|
onResizeStart: handleResizeStart,
|
|
223
375
|
onResizeStop: handleResizeStop,
|
|
224
|
-
children
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
classNames?.content,
|
|
229
|
-
canResizing,
|
|
230
|
-
resizing,
|
|
231
|
-
internalPlacement,
|
|
232
|
-
handleVariants,
|
|
233
|
-
showHandleHighlight,
|
|
234
|
-
styles.handleHighlight,
|
|
235
|
-
handleResize,
|
|
236
|
-
handleResizeStart,
|
|
237
|
-
handleResizeStop,
|
|
238
|
-
state.isResizing,
|
|
239
|
-
isPending,
|
|
240
|
-
style,
|
|
241
|
-
children,
|
|
242
|
-
cx
|
|
243
|
-
]);
|
|
244
|
-
if (fullscreen) return /* @__PURE__ */ jsx("div", {
|
|
245
|
-
className: cx(styles.fullscreen, className),
|
|
246
|
-
style: cssVariables,
|
|
247
|
-
children
|
|
376
|
+
children: stableLayout ? /* @__PURE__ */ jsx("div", {
|
|
377
|
+
style: sidebarInnerStyle,
|
|
378
|
+
children
|
|
379
|
+
}) : children
|
|
248
380
|
});
|
|
249
381
|
return /* @__PURE__ */ jsxs("aside", {
|
|
250
382
|
dir,
|
|
251
383
|
ref,
|
|
252
|
-
style:
|
|
384
|
+
style: {
|
|
385
|
+
...cssVariables,
|
|
386
|
+
...stableAsideStyle
|
|
387
|
+
},
|
|
253
388
|
className: cx(panelVariants({
|
|
254
389
|
isExpand,
|
|
255
390
|
mode,
|
|
256
391
|
placement: internalPlacement,
|
|
257
392
|
showBorder
|
|
258
393
|
}), className),
|
|
259
|
-
children: [expandable &&
|
|
394
|
+
children: [expandable && showExpand && /* @__PURE__ */ jsx(Center, {
|
|
395
|
+
className: toggleVariants({
|
|
396
|
+
placement: internalPlacement,
|
|
397
|
+
showHandleWideArea
|
|
398
|
+
}),
|
|
399
|
+
style: { opacity: isExpand ? pin ? void 0 : 0 : showHandleWhenCollapsed ? 1 : 0 },
|
|
400
|
+
children: /* @__PURE__ */ jsx(Center, {
|
|
401
|
+
className: classNames?.handle,
|
|
402
|
+
style: customStyles?.handle,
|
|
403
|
+
onClick: toggleExpand,
|
|
404
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
405
|
+
className: styles.handlerIcon,
|
|
406
|
+
icon: Arrow,
|
|
407
|
+
size: 16,
|
|
408
|
+
style: {
|
|
409
|
+
...MARGIN_MAP[internalPlacement],
|
|
410
|
+
transform: `rotate(${isExpand ? 180 : 0}deg)`,
|
|
411
|
+
transition: "transform 0.3s ease"
|
|
412
|
+
}
|
|
413
|
+
})
|
|
414
|
+
})
|
|
415
|
+
}), stableLayout ? /* @__PURE__ */ jsx("div", {
|
|
416
|
+
style: sidebarOuterStyle,
|
|
417
|
+
children: panelNode
|
|
418
|
+
}) : panelNode]
|
|
260
419
|
});
|
|
261
420
|
}, isEqual);
|
|
262
421
|
DraggablePanel.displayName = "DraggablePanel";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DraggablePanel.mjs","names":["useControlledState"],"sources":["../../src/DraggablePanel/DraggablePanel.tsx"],"sourcesContent":["'use client';\n\nimport { useHover } from 'ahooks';\nimport { ConfigProvider } from 'antd';\nimport { cx } from 'antd-style';\nimport isEqual from 'fast-deep-equal';\nimport { ChevronDown, ChevronLeft, ChevronRight, ChevronUp } from 'lucide-react';\nimport type { Enable, NumberSize, Size } from 're-resizable';\nimport { Resizable } from 're-resizable';\nimport {\n memo,\n use,\n useCallback,\n useEffect,\n useMemo,\n useReducer,\n useRef,\n useTransition,\n} from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport { Center } from '@/Flex';\nimport Icon from '@/Icon';\n\nimport { handleVariants, panelVariants, styles, toggleVariants } from './style';\nimport type { DraggablePanelProps } from './type';\nimport { reversePlacement } from './utils';\n\n// Constants\nconst DEFAULT_HEIGHT = 180;\nconst DEFAULT_WIDTH = 280;\nconst DEFAULT_HEADER_HEIGHT = 0;\nconst DEFAULT_PIN = true;\nconst DEFAULT_MODE = 'fixed';\nconst DEFAULT_EXPANDABLE = true;\nconst DEFAULT_EXPAND = true;\nconst DEFAULT_SHOW_HANDLE_WIDE_AREA = true;\n\n// State reducer for better state management\ninterface DraggablePanelState {\n isResizing: boolean;\n showExpand: boolean;\n}\n\ntype DraggablePanelAction =\n | { type: 'START_RESIZE' }\n | { type: 'STOP_RESIZE' }\n | { payload: boolean; type: 'SET_SHOW_EXPAND' };\n\nfunction draggablePanelReducer(\n state: DraggablePanelState,\n action: DraggablePanelAction,\n): DraggablePanelState {\n switch (action.type) {\n case 'START_RESIZE': {\n return { ...state, isResizing: true, showExpand: false };\n }\n case 'STOP_RESIZE': {\n return { ...state, isResizing: false, showExpand: true };\n }\n case 'SET_SHOW_EXPAND': {\n return { ...state, showExpand: action.payload };\n }\n default: {\n return state;\n }\n }\n}\n\nconst DraggablePanel = memo<DraggablePanelProps>(\n ({\n headerHeight = DEFAULT_HEADER_HEIGHT,\n fullscreen,\n maxHeight,\n pin = DEFAULT_PIN,\n mode = DEFAULT_MODE,\n children,\n placement = 'right',\n resize,\n style,\n showBorder = true,\n showHandleHighlight = false,\n showHandleWideArea = DEFAULT_SHOW_HANDLE_WIDE_AREA,\n backgroundColor,\n size,\n defaultSize: customizeDefaultSize,\n minWidth,\n minHeight,\n maxWidth,\n onSizeChange,\n onSizeDragging,\n expandable = DEFAULT_EXPANDABLE,\n expand,\n defaultExpand = DEFAULT_EXPAND,\n onExpandChange,\n className,\n showHandleWhenCollapsed,\n destroyOnClose,\n styles: customStyles,\n classNames,\n dir,\n }) => {\n const ref = useRef<HTMLDivElement>(null);\n const isHovering = useHover(ref);\n const isVertical = placement === 'top' || placement === 'bottom';\n const [isPending, startTransition] = useTransition();\n\n // Use ref for hover timeout to avoid memory leaks\n const hoverTimeoutRef = useRef<any>(undefined);\n\n // inherit direction from Ant Design ConfigProvider\n const { direction: antdDirection } = use(ConfigProvider.ConfigContext);\n const direction = dir ?? antdDirection;\n\n // Handle RTL direction\n const internalPlacement = useMemo(() => {\n return direction === 'rtl' && ['left', 'right'].includes(placement)\n ? placement === 'left'\n ? 'right'\n : 'left'\n : placement;\n }, [direction, placement]);\n\n const cssVariables = useMemo<Record<string, string>>(\n () => ({\n '--draggable-panel-bg': backgroundColor || '',\n '--draggable-panel-header-height': `${headerHeight}px`,\n }),\n [backgroundColor, headerHeight],\n );\n\n const [isExpand, setIsExpand] = useControlledState(defaultExpand, {\n onChange: onExpandChange,\n value: expand,\n });\n\n // Initialize state with useReducer for better performance\n const initialState: DraggablePanelState = {\n isResizing: false,\n showExpand: true,\n };\n\n const [state, dispatch] = useReducer(draggablePanelReducer, initialState);\n\n // Auto-expand on hover if not pinned with optimized transition\n useEffect(() => {\n if (pin) return;\n\n // Clear previous timeout\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current);\n }\n\n if (isHovering && !isExpand) {\n startTransition(() => {\n setIsExpand(true);\n });\n } else if (!isHovering && isExpand) {\n // Add a small delay before collapsing to prevent flickering\n hoverTimeoutRef.current = setTimeout(() => {\n startTransition(() => {\n setIsExpand(false);\n });\n }, 150);\n }\n }, [pin, isHovering, isExpand, setIsExpand]);\n\n // Cleanup timeout on unmount\n useEffect(() => {\n return () => {\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current);\n }\n };\n }, []);\n\n const canResizing = resize !== false && isExpand;\n\n // Configure resizing handles\n const resizing = useMemo(\n () => ({\n bottom: false,\n bottomLeft: false,\n bottomRight: false,\n left: false,\n right: false,\n top: false,\n topLeft: false,\n topRight: false,\n [reversePlacement(internalPlacement)]: true,\n ...(resize as Enable),\n }),\n [internalPlacement, resize],\n );\n\n // Calculate default size based on orientation\n const defaultSize: Size = useMemo(() => {\n if (isVertical)\n return {\n height: DEFAULT_HEIGHT,\n width: '100%',\n ...customizeDefaultSize,\n };\n\n return {\n height: '100%',\n width: DEFAULT_WIDTH,\n ...customizeDefaultSize,\n };\n }, [isVertical, customizeDefaultSize]);\n\n // Determine appropriate size props based on expand state\n const sizeProps = useMemo(() => {\n if (!isExpand) {\n return isVertical\n ? { minHeight: 0, size: { height: 0 } }\n : { minWidth: 0, size: { width: 0 } };\n }\n\n return {\n defaultSize,\n maxHeight: typeof maxHeight === 'number' ? Math.max(maxHeight, 0) : maxHeight,\n maxWidth: typeof maxWidth === 'number' ? Math.max(maxWidth, 0) : maxWidth,\n minHeight: typeof minHeight === 'number' ? Math.max(minHeight, 0) : minHeight,\n minWidth: typeof minWidth === 'number' ? Math.max(minWidth, 0) : minWidth,\n size: size as Size,\n };\n }, [isExpand, isVertical, defaultSize, maxHeight, maxWidth, minHeight, minWidth, size]);\n\n // Determine the appropriate arrow icon based on placement\n const Arrow = useMemo(() => {\n switch (internalPlacement) {\n case 'top': {\n return ChevronDown;\n }\n case 'bottom': {\n return ChevronUp;\n }\n case 'right': {\n return ChevronLeft;\n }\n case 'left': {\n return ChevronRight;\n }\n default: {\n return ChevronLeft;\n }\n }\n }, [internalPlacement]);\n\n // Toggle expand state with transition for better performance\n const toggleExpand = useCallback(() => {\n if (!expandable) return;\n\n startTransition(() => {\n setIsExpand(!isExpand);\n });\n }, [expandable, isExpand, setIsExpand]);\n\n // Toggle handle component\n const handle = useMemo(\n () => (\n <Center\n className={toggleVariants({ placement: internalPlacement, showHandleWideArea })}\n style={{ opacity: isExpand ? (pin ? undefined : 0) : showHandleWhenCollapsed ? 1 : 0 }}\n >\n <Center\n className={classNames?.handle}\n style={customStyles?.handle}\n onClick={toggleExpand}\n >\n <Icon\n className={styles.handlerIcon}\n icon={Arrow}\n size={16}\n style={{\n marginBottom: internalPlacement === 'top' ? 4 : 0,\n marginLeft: internalPlacement === 'right' ? 4 : 0,\n marginRight: internalPlacement === 'left' ? 4 : 0,\n marginTop: internalPlacement === 'bottom' ? 4 : 0,\n transform: `rotate(${isExpand ? 180 : 0}deg)`,\n transition: 'transform 0.3s ease',\n }}\n />\n </Center>\n </Center>\n ),\n [\n toggleVariants,\n internalPlacement,\n isExpand,\n pin,\n showHandleWhenCollapsed,\n classNames?.handle,\n toggleExpand,\n customStyles?.handle,\n styles.handlerIcon,\n Arrow,\n ],\n );\n\n // Handle resize events with memoization\n const handleResize = useCallback(\n (_: unknown, _direction: unknown, reference_: HTMLElement, delta: NumberSize) => {\n onSizeDragging?.(delta, {\n height: reference_.style.height,\n width: reference_.style.width,\n });\n },\n [onSizeDragging],\n );\n\n const handleResizeStart = useCallback(() => {\n dispatch({ type: 'START_RESIZE' });\n }, []);\n\n const handleResizeStop = useCallback(\n (e: unknown, direction: unknown, reference_: HTMLElement, delta: NumberSize) => {\n dispatch({ type: 'STOP_RESIZE' });\n onSizeChange?.(delta, {\n height: reference_.style.height,\n width: reference_.style.width,\n });\n },\n [onSizeChange],\n );\n\n // Main panel content\n const inner = useMemo(\n () => (\n <Resizable\n {...sizeProps}\n className={cx(styles.panel, classNames?.content)}\n enable={canResizing ? (resizing as Enable) : undefined}\n handleClasses={\n canResizing\n ? {\n [reversePlacement(internalPlacement)]: cx(\n handleVariants({\n placement: reversePlacement(internalPlacement),\n }),\n showHandleHighlight && styles.handleHighlight,\n ),\n }\n : {}\n }\n style={{\n ...cssVariables,\n opacity: isPending ? 0.95 : 1,\n transition: state.isResizing ? 'unset' : undefined,\n ...style,\n }}\n onResize={handleResize}\n onResizeStart={handleResizeStart}\n onResizeStop={handleResizeStop}\n >\n {children}\n </Resizable>\n ),\n [\n sizeProps,\n styles.panel,\n classNames?.content,\n canResizing,\n resizing,\n internalPlacement,\n handleVariants,\n showHandleHighlight,\n styles.handleHighlight,\n handleResize,\n handleResizeStart,\n handleResizeStop,\n state.isResizing,\n isPending,\n style,\n children,\n cx,\n ],\n );\n\n // For fullscreen mode, return a simpler layout\n if (fullscreen) {\n return (\n <div className={cx(styles.fullscreen, className)} style={cssVariables}>\n {children}\n </div>\n );\n }\n\n return (\n <aside\n dir={dir}\n ref={ref}\n style={cssVariables}\n className={cx(\n panelVariants({\n isExpand,\n mode,\n placement: internalPlacement,\n showBorder,\n }),\n className,\n )}\n >\n {expandable && state.showExpand && handle}\n {destroyOnClose ? isExpand && inner : inner}\n </aside>\n );\n },\n isEqual,\n);\n\nDraggablePanel.displayName = 'DraggablePanel';\n\nexport default DraggablePanel;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DraggablePanel.mjs","names":["useControlledState"],"sources":["../../src/DraggablePanel/DraggablePanel.tsx"],"sourcesContent":["'use client';\n\nimport { useHover } from 'ahooks';\nimport { ConfigProvider } from 'antd';\nimport { cx } from 'antd-style';\nimport isEqual from 'fast-deep-equal';\nimport { ChevronDown, ChevronLeft, ChevronRight, ChevronUp } from 'lucide-react';\nimport type { Enable, NumberSize, Size } from 're-resizable';\nimport { Resizable } from 're-resizable';\nimport {\n type CSSProperties,\n memo,\n startTransition,\n use,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport { Center } from '@/Flex';\nimport Icon from '@/Icon';\n\nimport { handleVariants, panelVariants, styles, toggleVariants } from './style';\nimport type { DraggablePanelProps } from './type';\nimport { reversePlacement } from './utils';\n\nconst ARROW_MAP = {\n bottom: ChevronUp,\n left: ChevronRight,\n right: ChevronLeft,\n top: ChevronDown,\n} as const;\n\nconst MARGIN_MAP = {\n bottom: { marginTop: 4 },\n left: { marginRight: 4 },\n right: { marginLeft: 4 },\n top: { marginBottom: 4 },\n} as const;\n\nconst DISABLED_RESIZING: Enable = {\n bottom: false,\n bottomLeft: false,\n bottomRight: false,\n left: false,\n right: false,\n top: false,\n topLeft: false,\n topRight: false,\n};\n\nconst toCssSize = (value: string | number | undefined, fallback: string) => {\n if (typeof value === 'number') return `${Math.max(value, 0)}px`;\n if (typeof value === 'string' && value.length > 0) return value;\n return fallback;\n};\n\nconst DraggablePanel = memo<DraggablePanelProps>(\n ({\n headerHeight = 0,\n fullscreen,\n maxHeight,\n pin = true,\n mode = 'fixed',\n children,\n placement = 'right',\n resize,\n style,\n showBorder = true,\n showHandleHighlight = false,\n showHandleWideArea = true,\n backgroundColor,\n size,\n stableLayout = false,\n defaultSize: customizeDefaultSize,\n minWidth,\n minHeight,\n maxWidth,\n onSizeChange,\n onSizeDragging,\n expandable = true,\n expand,\n defaultExpand = true,\n onExpandChange,\n className,\n showHandleWhenCollapsed,\n destroyOnClose,\n styles: customStyles,\n classNames,\n dir,\n }) => {\n const ref = useRef<HTMLDivElement>(null);\n const isHovering = useHover(ref);\n const isVertical = placement === 'top' || placement === 'bottom';\n const hoverTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n const resetTransitionTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);\n const resizableRef = useRef<Resizable>(null);\n const initialExpandedSizeRef = useRef<Size | undefined>(undefined);\n\n const { direction: antdDirection } = use(ConfigProvider.ConfigContext);\n const direction = dir ?? antdDirection;\n\n const internalPlacement = useMemo(() => {\n if (direction !== 'rtl') return placement;\n if (placement === 'left') return 'right';\n if (placement === 'right') return 'left';\n return placement;\n }, [direction, placement]);\n\n const cssVariables = {\n '--draggable-panel-bg': backgroundColor || '',\n '--draggable-panel-header-height': `${headerHeight}px`,\n } as Record<string, string>;\n\n const [isExpand, setIsExpand] = useControlledState(defaultExpand, {\n onChange: onExpandChange,\n value: expand,\n });\n\n const [shouldTransition, setShouldTransition] = useState(true);\n const [showExpand, setShowExpand] = useState(true);\n\n useEffect(() => {\n if (pin) return;\n\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current);\n }\n\n if (isHovering && !isExpand) {\n startTransition(() => setIsExpand(true));\n } else if (!isHovering && isExpand) {\n hoverTimeoutRef.current = setTimeout(() => {\n startTransition(() => setIsExpand(false));\n }, 150);\n }\n }, [pin, isHovering, isExpand, setIsExpand]);\n\n useEffect(() => {\n return () => {\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current);\n }\n if (resetTransitionTimeoutRef.current) {\n clearTimeout(resetTransitionTimeoutRef.current);\n }\n };\n }, []);\n\n useEffect(() => {\n initialExpandedSizeRef.current = undefined;\n }, [internalPlacement]);\n\n const reversed = reversePlacement(internalPlacement);\n const canResizing = resize !== false && isExpand;\n\n const resizing = useMemo(\n () => ({\n bottom: false,\n bottomLeft: false,\n bottomRight: false,\n left: false,\n right: false,\n top: false,\n topLeft: false,\n topRight: false,\n [reversed]: true,\n ...(resize as Enable),\n }),\n [reversed, resize],\n );\n\n const defaultSize: Size = useMemo(() => {\n if (isVertical) return { height: 180, width: '100%', ...customizeDefaultSize };\n return { height: '100%', width: 280, ...customizeDefaultSize };\n }, [isVertical, customizeDefaultSize]);\n const normalizedMaxHeight = typeof maxHeight === 'number' ? Math.max(maxHeight, 0) : undefined;\n const normalizedMaxWidth = typeof maxWidth === 'number' ? Math.max(maxWidth, 0) : undefined;\n const normalizedMinHeight = typeof minHeight === 'number' ? Math.max(minHeight, 0) : undefined;\n const normalizedMinWidth = typeof minWidth === 'number' ? Math.max(minWidth, 0) : undefined;\n\n const sizeProps = useMemo(() => {\n if (!stableLayout && !isExpand) {\n return isVertical\n ? { minHeight: 0, size: { height: 0 } }\n : { minWidth: 0, size: { width: 0 } };\n }\n\n return {\n defaultSize,\n maxHeight: normalizedMaxHeight,\n maxWidth: normalizedMaxWidth,\n minHeight: normalizedMinHeight,\n minWidth: normalizedMinWidth,\n size: size as Size,\n };\n }, [\n stableLayout,\n isExpand,\n isVertical,\n defaultSize,\n normalizedMaxHeight,\n normalizedMaxWidth,\n normalizedMinHeight,\n normalizedMinWidth,\n size,\n ]);\n\n const fallbackExpandedSize = isVertical ? '180px' : '280px';\n const controlledExpandedSize = useMemo(() => {\n const controlledSize = isVertical ? size?.height : size?.width;\n if (controlledSize === undefined) return undefined;\n return toCssSize(controlledSize, fallbackExpandedSize);\n }, [isVertical, size?.height, size?.width, fallbackExpandedSize]);\n const defaultExpandedSize = useMemo(() => {\n const initialSize = isVertical ? defaultSize.height : defaultSize.width;\n return toCssSize(initialSize, fallbackExpandedSize);\n }, [isVertical, defaultSize.height, defaultSize.width, fallbackExpandedSize]);\n const [resizedExpandedSize, setResizedExpandedSize] = useState<{\n horizontal?: string;\n vertical?: string;\n }>({});\n const expandedOuterSize =\n controlledExpandedSize ??\n (isVertical ? resizedExpandedSize.vertical : resizedExpandedSize.horizontal) ??\n defaultExpandedSize;\n\n const setExpandedMainSize = useCallback(\n (nextSize: Size) => {\n if (!stableLayout) return;\n\n const currentSize = isVertical ? nextSize.height : nextSize.width;\n if (!currentSize) return;\n\n const normalizedSize = toCssSize(currentSize, fallbackExpandedSize);\n setResizedExpandedSize((state) =>\n isVertical\n ? { ...state, vertical: normalizedSize }\n : { ...state, horizontal: normalizedSize },\n );\n },\n [fallbackExpandedSize, isVertical, stableLayout],\n );\n\n const captureInitialExpandedSize = useCallback(() => {\n if (initialExpandedSizeRef.current) return initialExpandedSizeRef.current;\n\n const rect = resizableRef.current?.resizable?.getBoundingClientRect();\n if (!rect) return undefined;\n\n const nextInitialSize = isVertical\n ? ({ height: rect.height, width: '100%' } as Size)\n : ({ height: '100%', width: rect.width } as Size);\n\n initialExpandedSizeRef.current = nextInitialSize;\n return nextInitialSize;\n }, [isVertical]);\n\n useEffect(() => {\n if (!isExpand) return;\n captureInitialExpandedSize();\n }, [captureInitialExpandedSize, isExpand]);\n\n const toggleExpand = useCallback(() => {\n if (expandable) setIsExpand(!isExpand);\n }, [expandable, isExpand, setIsExpand]);\n\n const clampResizeSize = useCallback(\n (el: HTMLElement) => {\n const rect = el.getBoundingClientRect();\n const currentMainSize = isVertical ? rect.height : rect.width;\n const minMainSize = isVertical ? normalizedMinHeight : normalizedMinWidth;\n const maxMainSize = isVertical ? normalizedMaxHeight : normalizedMaxWidth;\n\n let clampedMainSize = currentMainSize;\n if (typeof minMainSize === 'number')\n clampedMainSize = Math.max(clampedMainSize, minMainSize);\n if (typeof maxMainSize === 'number')\n clampedMainSize = Math.min(clampedMainSize, maxMainSize);\n\n if (\n !Number.isFinite(clampedMainSize) ||\n Math.abs(clampedMainSize - currentMainSize) < 0.5\n ) {\n return { height: el.style.height, width: el.style.width };\n }\n\n const width = isVertical ? el.style.width || '100%' : `${clampedMainSize}px`;\n const height = isVertical ? `${clampedMainSize}px` : el.style.height || '100%';\n resizableRef.current?.updateSize({ height, width });\n\n return { height, width };\n },\n [\n isVertical,\n normalizedMaxHeight,\n normalizedMaxWidth,\n normalizedMinHeight,\n normalizedMinWidth,\n ],\n );\n\n const handleResize = useCallback(\n (_event: unknown, _direction: unknown, el: HTMLElement, delta: NumberSize) => {\n const nextSize = clampResizeSize(el);\n setExpandedMainSize(nextSize);\n onSizeDragging?.(delta, nextSize);\n },\n [clampResizeSize, onSizeDragging, setExpandedMainSize],\n );\n\n const triggerResetWithoutTransition = useCallback(() => {\n if (resetTransitionTimeoutRef.current) {\n clearTimeout(resetTransitionTimeoutRef.current);\n }\n\n setShouldTransition(false);\n resetTransitionTimeoutRef.current = setTimeout(() => {\n setShouldTransition(true);\n }, 0);\n }, []);\n\n const handleResetSize = useCallback(() => {\n if (!canResizing) return;\n\n const resetSize = captureInitialExpandedSize();\n if (!resetSize) return;\n\n triggerResetWithoutTransition();\n\n const rect = resizableRef.current?.resizable?.getBoundingClientRect();\n const prevMainSize = rect ? (isVertical ? rect.height : rect.width) : 0;\n const resetMainSize = isVertical ? resetSize.height : resetSize.width;\n const nextMainSize = typeof resetMainSize === 'number' ? resetMainSize : prevMainSize;\n\n resizableRef.current?.updateSize(resetSize);\n setExpandedMainSize(resetSize);\n\n onSizeChange?.(\n isVertical\n ? { height: nextMainSize - prevMainSize, width: 0 }\n : { height: 0, width: nextMainSize - prevMainSize },\n resetSize,\n );\n }, [\n canResizing,\n captureInitialExpandedSize,\n isVertical,\n onSizeChange,\n setExpandedMainSize,\n triggerResetWithoutTransition,\n ]);\n\n const handleResizeStart = useCallback(\n (event: { detail?: number }) => {\n if (event.detail === 2) {\n handleResetSize();\n return false;\n }\n\n if (resetTransitionTimeoutRef.current) {\n clearTimeout(resetTransitionTimeoutRef.current);\n resetTransitionTimeoutRef.current = undefined;\n }\n\n setShouldTransition(false);\n setShowExpand(false);\n },\n [handleResetSize],\n );\n\n const handleResizeStop = useCallback(\n (_event: unknown, _direction: unknown, el: HTMLElement, delta: NumberSize) => {\n const nextSize = clampResizeSize(el);\n setExpandedMainSize(nextSize);\n setShouldTransition(true);\n setShowExpand(true);\n onSizeChange?.(delta, nextSize);\n },\n [clampResizeSize, onSizeChange, setExpandedMainSize],\n );\n\n const resizeHandleClassName = useMemo(\n () =>\n cx(handleVariants({ placement: reversed }), showHandleHighlight && styles.handleHighlight),\n [reversed, showHandleHighlight],\n );\n\n if (fullscreen) {\n return (\n <div className={cx(styles.fullscreen, className)} style={cssVariables}>\n {children}\n </div>\n );\n }\n\n const Arrow = ARROW_MAP[internalPlacement] ?? ChevronLeft;\n const stableOuterFlex = stableLayout\n ? ({\n display: 'flex',\n flexDirection: 'column',\n minHeight: 0,\n } as const)\n : {};\n\n const sidebarOuterStyle = isVertical\n ? {\n height: isExpand ? expandedOuterSize : 0,\n overflow: 'hidden',\n transition: shouldTransition ? 'height 0.2s var(--ant-motion-ease-out, ease)' : 'none',\n width: '100%',\n ...stableOuterFlex,\n }\n : {\n overflow: 'hidden',\n transition: shouldTransition ? 'width 0.2s var(--ant-motion-ease-out, ease)' : 'none',\n width: isExpand ? expandedOuterSize : 0,\n ...(stableLayout\n ? {\n ...stableOuterFlex,\n flex: 1,\n minWidth: 0,\n height: '100%',\n }\n : {}),\n };\n\n const stableInnerStyle: CSSProperties = {\n display: 'flex',\n flex: 1,\n flexDirection: 'column',\n height: '100%',\n minHeight: 0,\n minWidth: 0,\n width: '100%',\n };\n const sidebarInnerStyle: CSSProperties = stableLayout\n ? stableInnerStyle\n : isVertical\n ? { height: '100%', width: '100%' }\n : { width: '100%' };\n\n const stableAsideStyle: CSSProperties = stableLayout\n ? {\n display: 'flex',\n flexDirection: 'column',\n minHeight: 0,\n ...(mode === 'fixed' ? { height: '100%' } : {}),\n }\n : {};\n\n const stableResizableStyle: CSSProperties = {\n display: 'flex',\n flex: 1,\n flexDirection: 'column',\n height: '100%',\n minHeight: 0,\n minWidth: 0,\n width: '100%',\n };\n\n const panelNode = (!destroyOnClose || isExpand) && (\n <Resizable\n ref={resizableRef}\n {...sizeProps}\n className={cx(styles.panel, classNames?.content)}\n enable={canResizing ? (resizing as Enable) : DISABLED_RESIZING}\n handleClasses={\n canResizing\n ? {\n [reversed]: resizeHandleClassName,\n }\n : {}\n }\n style={{\n ...cssVariables,\n transition: shouldTransition ? undefined : 'none',\n ...(stableLayout ? stableResizableStyle : {}),\n ...style,\n }}\n onResize={handleResize}\n onResizeStart={handleResizeStart}\n onResizeStop={handleResizeStop}\n >\n {stableLayout ? <div style={sidebarInnerStyle}>{children}</div> : children}\n </Resizable>\n );\n\n return (\n <aside\n dir={dir}\n ref={ref}\n style={{ ...cssVariables, ...stableAsideStyle }}\n className={cx(\n panelVariants({ isExpand, mode, placement: internalPlacement, showBorder }),\n className,\n )}\n >\n {expandable && showExpand && (\n <Center\n className={toggleVariants({ placement: internalPlacement, showHandleWideArea })}\n style={{\n opacity: isExpand ? (pin ? undefined : 0) : showHandleWhenCollapsed ? 1 : 0,\n }}\n >\n <Center\n className={classNames?.handle}\n style={customStyles?.handle}\n onClick={toggleExpand}\n >\n <Icon\n className={styles.handlerIcon}\n icon={Arrow}\n size={16}\n style={{\n ...MARGIN_MAP[internalPlacement],\n transform: `rotate(${isExpand ? 180 : 0}deg)`,\n transition: 'transform 0.3s ease',\n }}\n />\n </Center>\n </Center>\n )}\n {stableLayout ? <div style={sidebarOuterStyle}>{panelNode}</div> : panelNode}\n </aside>\n );\n },\n isEqual,\n);\n\nDraggablePanel.displayName = 'DraggablePanel';\n\nexport default DraggablePanel;\n"],"mappings":"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"}
|
|
@@ -38,6 +38,11 @@ interface DraggablePanelProps extends DivProps {
|
|
|
38
38
|
showHandleWhenCollapsed?: boolean;
|
|
39
39
|
showHandleWideArea?: boolean;
|
|
40
40
|
size?: Partial<Size>;
|
|
41
|
+
/**
|
|
42
|
+
* Use two-layer container layout to keep content layout stable when collapsed/expanded.
|
|
43
|
+
* @default false
|
|
44
|
+
*/
|
|
45
|
+
stableLayout?: boolean;
|
|
41
46
|
styles?: {
|
|
42
47
|
content?: CSSProperties;
|
|
43
48
|
handle?: CSSProperties;
|
package/es/Menu/sharedStyle.mjs
CHANGED
|
@@ -145,8 +145,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
145
145
|
outline: none;
|
|
146
146
|
box-shadow:
|
|
147
147
|
0 0 15px 0 #00000008,
|
|
148
|
-
0 2px 30px 0 #00000014
|
|
149
|
-
0 0 0 1px ${cssVar.colorBorder} inset;
|
|
148
|
+
0 2px 30px 0 #00000014;
|
|
150
149
|
`,
|
|
151
150
|
positioner: css`
|
|
152
151
|
--lobe-dropdown-animation-duration: 140ms;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sharedStyle.mjs","names":[],"sources":["../../src/Menu/sharedStyle.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n danger: css`\n color: ${cssVar.colorError} !important;\n\n &:hover {\n background: ${cssVar.colorErrorBg} !important;\n }\n `,\n\n empty: css`\n cursor: default;\n font-style: italic;\n color: ${cssVar.colorTextTertiary};\n `,\n\n extra: css`\n margin-inline-start: auto;\n padding-inline-start: 16px;\n font-size: 12px;\n color: ${cssVar.colorTextTertiary};\n `,\n\n groupLabel: css`\n user-select: none;\n\n padding-block: 8px 4px;\n padding-inline: 12px;\n\n font-size: 12px;\n font-weight: 500;\n line-height: 16px;\n color: ${cssVar.colorTextTertiary};\n text-transform: capitalize;\n `,\n\n icon: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 16px;\n height: 16px;\n margin-inline-end: 8px;\n `,\n\n item: css`\n cursor: pointer;\n user-select: none;\n\n position: relative;\n\n overflow: hidden;\n display: flex;\n align-items: center;\n\n width: 100%;\n min-height: 36px;\n padding-block: 8px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadiusSM};\n\n font-size: 14px;\n line-height: 20px;\n color: ${cssVar.colorText};\n\n outline: none;\n\n transition: all 150ms ${cssVar.motionEaseOut};\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &:active {\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: ${cssVar.colorTextDisabled};\n opacity: 0.5;\n\n &:hover {\n background: transparent;\n }\n }\n\n &[data-highlighted]:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-state='open']:not([data-disabled]),\n &[data-open]:not([data-disabled]),\n &[aria-expanded='true']:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n `,\n\n itemContent: css`\n display: flex;\n flex: 1;\n gap: 0;\n align-items: center;\n `,\n\n itemContentAlignStart: css`\n align-items: flex-start;\n `,\n\n iconAlignStart: css`\n align-self: flex-start;\n margin-block-start: 2px;\n `,\n\n label: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n & a,\n & a:visited,\n & a:hover,\n & a:active {\n color: inherit;\n }\n `,\n\n labelGroup: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-width: 0;\n `,\n\n desc: css`\n overflow: hidden;\n\n font-size: 12px;\n line-height: 16px;\n color: ${cssVar.colorTextTertiary};\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n\n popup: css`\n min-width: 120px;\n padding: 4px;\n border-radius: ${cssVar.borderRadius};\n\n background: ${cssVar.colorBgElevated};\n outline: none;\n box-shadow:\n 0 0 15px 0 #00000008,\n 0 2px 30px 0 #00000014
|
|
1
|
+
{"version":3,"file":"sharedStyle.mjs","names":[],"sources":["../../src/Menu/sharedStyle.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n danger: css`\n color: ${cssVar.colorError} !important;\n\n &:hover {\n background: ${cssVar.colorErrorBg} !important;\n }\n `,\n\n empty: css`\n cursor: default;\n font-style: italic;\n color: ${cssVar.colorTextTertiary};\n `,\n\n extra: css`\n margin-inline-start: auto;\n padding-inline-start: 16px;\n font-size: 12px;\n color: ${cssVar.colorTextTertiary};\n `,\n\n groupLabel: css`\n user-select: none;\n\n padding-block: 8px 4px;\n padding-inline: 12px;\n\n font-size: 12px;\n font-weight: 500;\n line-height: 16px;\n color: ${cssVar.colorTextTertiary};\n text-transform: capitalize;\n `,\n\n icon: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 16px;\n height: 16px;\n margin-inline-end: 8px;\n `,\n\n item: css`\n cursor: pointer;\n user-select: none;\n\n position: relative;\n\n overflow: hidden;\n display: flex;\n align-items: center;\n\n width: 100%;\n min-height: 36px;\n padding-block: 8px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadiusSM};\n\n font-size: 14px;\n line-height: 20px;\n color: ${cssVar.colorText};\n\n outline: none;\n\n transition: all 150ms ${cssVar.motionEaseOut};\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &:active {\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: ${cssVar.colorTextDisabled};\n opacity: 0.5;\n\n &:hover {\n background: transparent;\n }\n }\n\n &[data-highlighted]:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-state='open']:not([data-disabled]),\n &[data-open]:not([data-disabled]),\n &[aria-expanded='true']:not([data-disabled]) {\n background: ${cssVar.colorFillTertiary};\n }\n `,\n\n itemContent: css`\n display: flex;\n flex: 1;\n gap: 0;\n align-items: center;\n `,\n\n itemContentAlignStart: css`\n align-items: flex-start;\n `,\n\n iconAlignStart: css`\n align-self: flex-start;\n margin-block-start: 2px;\n `,\n\n label: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n & a,\n & a:visited,\n & a:hover,\n & a:active {\n color: inherit;\n }\n `,\n\n labelGroup: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-width: 0;\n `,\n\n desc: css`\n overflow: hidden;\n\n font-size: 12px;\n line-height: 16px;\n color: ${cssVar.colorTextTertiary};\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n\n popup: css`\n min-width: 120px;\n padding: 4px;\n border-radius: ${cssVar.borderRadius};\n\n background: ${cssVar.colorBgElevated};\n outline: none;\n box-shadow:\n 0 0 15px 0 #00000008,\n 0 2px 30px 0 #00000014;\n `,\n positioner: css`\n --lobe-dropdown-animation-duration: 140ms;\n --lobe-dropdown-animation-scale-y: 0.92;\n --lobe-dropdown-animation-ease-in: ease-in;\n --lobe-dropdown-animation-ease-out: ${cssVar.motionEaseOut};\n\n z-index: 1100;\n\n & > * {\n will-change: opacity, transform;\n transform-origin: var(--transform-origin);\n animation: none;\n }\n\n &[data-open] > * {\n transform: scaleY(1);\n opacity: 1;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-out);\n }\n\n &[data-open] > *[data-starting-style] {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n }\n\n &[data-closed] > * {\n transform: scaleY(var(--lobe-dropdown-animation-scale-y));\n opacity: 0;\n transition:\n opacity var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in),\n transform var(--lobe-dropdown-animation-duration) var(--lobe-dropdown-animation-ease-in);\n }\n\n &[data-hover-trigger] {\n --lobe-dropdown-animation-duration: 140ms;\n }\n\n &[data-submenu],\n &[data-nested] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n }\n\n &[data-side='left'],\n &[data-side='right'] {\n --lobe-dropdown-animation-duration: 0ms;\n --lobe-dropdown-animation-scale-y: 1;\n }\n `,\n\n separator: css`\n height: 1px;\n margin-block: 4px;\n margin-inline: 0;\n background: ${cssVar.colorBorder};\n `,\n\n submenuArrow: css`\n display: flex;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n\n width: 20px;\n height: 20px;\n margin-inline-start: auto;\n padding-inline-start: 8px;\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,QAAQ,GAAG;aACA,OAAO,WAAW;;;oBAGX,OAAO,aAAa;;;CAItC,OAAO,GAAG;;;aAGC,OAAO,kBAAkB;;CAGpC,OAAO,GAAG;;;;aAIC,OAAO,kBAAkB;;CAGpC,YAAY,GAAG;;;;;;;;;aASJ,OAAO,kBAAkB;;;CAIpC,MAAM,GAAG;;;;;;;;;;CAWT,MAAM,GAAG;;;;;;;;;;;;;;qBAcU,OAAO,eAAe;;;;aAI9B,OAAO,UAAU;;;;4BAIF,OAAO,cAAc;;;oBAG7B,OAAO,kBAAkB;;;;oBAIzB,OAAO,mBAAmB;;;;;eAK/B,OAAO,kBAAkB;;;;;;;;;oBASpB,OAAO,kBAAkB;;;;;;oBAMzB,OAAO,kBAAkB;;;CAI3C,aAAa,GAAG;;;;;;CAOhB,uBAAuB,GAAG;;;CAI1B,gBAAgB,GAAG;;;;CAKnB,OAAO,GAAG;;;;;;;;;;;;;CAcV,YAAY,GAAG;;;;;;;;CASf,MAAM,GAAG;;;;;aAKE,OAAO,kBAAkB;;;;CAKpC,OAAO,GAAG;;;qBAGS,OAAO,aAAa;;kBAEvB,OAAO,gBAAgB;;;;;;CAMvC,YAAY,GAAG;;;;0CAIyB,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgD7D,WAAW,GAAG;;;;kBAIE,OAAO,YAAY;;CAGnC,cAAc,GAAG;;;;;;;;;;;CAWlB,EAAE"}
|
package/es/Modal/Modal.mjs
CHANGED
|
@@ -65,7 +65,6 @@ const Modal$1 = memo(({ panelRef, allowFullscreen, children, title = " ", classN
|
|
|
65
65
|
theme: { token: { colorBgElevated: cssVar.colorBgContainer } },
|
|
66
66
|
children: /* @__PURE__ */ jsx(Modal, {
|
|
67
67
|
closable: true,
|
|
68
|
-
maskClosable: true,
|
|
69
68
|
cancelText,
|
|
70
69
|
className: cx(styles.content, className),
|
|
71
70
|
closeIcon: /* @__PURE__ */ jsx(Icon, {
|
|
@@ -75,6 +74,7 @@ const Modal$1 = memo(({ panelRef, allowFullscreen, children, title = " ", classN
|
|
|
75
74
|
confirmLoading,
|
|
76
75
|
destroyOnHidden,
|
|
77
76
|
footer: hideFooter ? null : footer,
|
|
77
|
+
mask: { closable: true },
|
|
78
78
|
okButtonProps,
|
|
79
79
|
okText,
|
|
80
80
|
open,
|
package/es/Modal/Modal.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.mjs","names":["Modal","AntModal"],"sources":["../../src/Modal/Modal.tsx"],"sourcesContent":["'use client';\n\nimport { Button, ConfigProvider, Drawer, Modal as AntModal } from 'antd';\nimport { cssVar, cx, useResponsive } from 'antd-style';\nimport { Maximize2, Minimize2, X } from 'lucide-react';\nimport { memo, type ReactNode, useState } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport Icon from '@/Icon';\n\nimport { styles } from './style';\nimport { type ModalProps } from './type';\n\nconst Modal = memo<ModalProps>(\n ({\n panelRef,\n allowFullscreen,\n children,\n title = ' ',\n className,\n classNames,\n width = 700,\n onCancel,\n open,\n destroyOnHidden,\n paddings,\n height = '75dvh',\n enableResponsive = true,\n footer,\n styles: customStyles,\n okText,\n onOk,\n cancelText,\n okButtonProps,\n cancelButtonProps,\n confirmLoading,\n ...rest\n }) => {\n const [fullscreen, setFullscreen] = useState(false);\n const { mobile } = useResponsive();\n const hideFooter = footer === false || footer === null;\n if (enableResponsive && mobile)\n return (\n <ConfigProvider\n theme={{\n token: {\n colorBgElevated: cssVar.colorBgContainer,\n },\n }}\n >\n <Drawer\n className={cx(styles.drawerContent, className)}\n closeIcon={<ActionIcon icon={X} />}\n destroyOnHidden={destroyOnHidden}\n height={fullscreen ? 'calc(100% - env(safe-area-inset-top))' : height}\n open={open}\n panelRef={panelRef}\n placement={'bottom'}\n title={title}\n classNames={\n typeof classNames === 'function'\n ? classNames\n : {\n ...classNames,\n wrapper: cx(styles.wrap, classNames?.wrapper),\n }\n }\n extra={\n allowFullscreen && (\n <ActionIcon\n icon={fullscreen ? Minimize2 : Maximize2}\n onClick={() => setFullscreen(!fullscreen)}\n />\n )\n }\n footer={\n hideFooter\n ? null\n : (footer as ReactNode) || (\n <>\n <Button\n color={'default'}\n variant={'filled'}\n onClick={onCancel as any}\n {...cancelButtonProps}\n >\n {cancelText || 'Cancel'}\n </Button>\n <Button\n loading={confirmLoading}\n type=\"primary\"\n onClick={onOk as any}\n {...okButtonProps}\n style={{\n marginInlineStart: 8,\n ...okButtonProps?.style,\n }}\n >\n {okText || 'OK'}\n </Button>\n </>\n )\n }\n styles={\n typeof customStyles === 'function'\n ? customStyles\n : {\n ...customStyles,\n body: {\n paddingBlock: `16px ${footer ? 0 : '16px'}`,\n paddingInline: paddings?.desktop ?? 16,\n ...customStyles?.body,\n },\n }\n }\n onClose={onCancel as any}\n {...rest}\n >\n {children}\n </Drawer>\n </ConfigProvider>\n );\n\n return (\n <ConfigProvider\n theme={{\n token: {\n colorBgElevated: cssVar.colorBgContainer,\n },\n }}\n >\n <AntModal\n closable\n
|
|
1
|
+
{"version":3,"file":"Modal.mjs","names":["Modal","AntModal"],"sources":["../../src/Modal/Modal.tsx"],"sourcesContent":["'use client';\n\nimport { Button, ConfigProvider, Drawer, Modal as AntModal } from 'antd';\nimport { cssVar, cx, useResponsive } from 'antd-style';\nimport { Maximize2, Minimize2, X } from 'lucide-react';\nimport { memo, type ReactNode, useState } from 'react';\n\nimport ActionIcon from '@/ActionIcon';\nimport Icon from '@/Icon';\n\nimport { styles } from './style';\nimport { type ModalProps } from './type';\n\nconst Modal = memo<ModalProps>(\n ({\n panelRef,\n allowFullscreen,\n children,\n title = ' ',\n className,\n classNames,\n width = 700,\n onCancel,\n open,\n destroyOnHidden,\n paddings,\n height = '75dvh',\n enableResponsive = true,\n footer,\n styles: customStyles,\n okText,\n onOk,\n cancelText,\n okButtonProps,\n cancelButtonProps,\n confirmLoading,\n ...rest\n }) => {\n const [fullscreen, setFullscreen] = useState(false);\n const { mobile } = useResponsive();\n const hideFooter = footer === false || footer === null;\n if (enableResponsive && mobile)\n return (\n <ConfigProvider\n theme={{\n token: {\n colorBgElevated: cssVar.colorBgContainer,\n },\n }}\n >\n <Drawer\n className={cx(styles.drawerContent, className)}\n closeIcon={<ActionIcon icon={X} />}\n destroyOnHidden={destroyOnHidden}\n height={fullscreen ? 'calc(100% - env(safe-area-inset-top))' : height}\n open={open}\n panelRef={panelRef}\n placement={'bottom'}\n title={title}\n classNames={\n typeof classNames === 'function'\n ? classNames\n : {\n ...classNames,\n wrapper: cx(styles.wrap, classNames?.wrapper),\n }\n }\n extra={\n allowFullscreen && (\n <ActionIcon\n icon={fullscreen ? Minimize2 : Maximize2}\n onClick={() => setFullscreen(!fullscreen)}\n />\n )\n }\n footer={\n hideFooter\n ? null\n : (footer as ReactNode) || (\n <>\n <Button\n color={'default'}\n variant={'filled'}\n onClick={onCancel as any}\n {...cancelButtonProps}\n >\n {cancelText || 'Cancel'}\n </Button>\n <Button\n loading={confirmLoading}\n type=\"primary\"\n onClick={onOk as any}\n {...okButtonProps}\n style={{\n marginInlineStart: 8,\n ...okButtonProps?.style,\n }}\n >\n {okText || 'OK'}\n </Button>\n </>\n )\n }\n styles={\n typeof customStyles === 'function'\n ? customStyles\n : {\n ...customStyles,\n body: {\n paddingBlock: `16px ${footer ? 0 : '16px'}`,\n paddingInline: paddings?.desktop ?? 16,\n ...customStyles?.body,\n },\n }\n }\n onClose={onCancel as any}\n {...rest}\n >\n {children}\n </Drawer>\n </ConfigProvider>\n );\n\n return (\n <ConfigProvider\n theme={{\n token: {\n colorBgElevated: cssVar.colorBgContainer,\n },\n }}\n >\n <AntModal\n closable\n cancelText={cancelText}\n className={cx(styles.content, className)}\n closeIcon={<Icon icon={X} size={20} />}\n confirmLoading={confirmLoading}\n destroyOnHidden={destroyOnHidden}\n footer={hideFooter ? null : footer}\n mask={{ closable: true }}\n okButtonProps={okButtonProps}\n okText={okText}\n open={open}\n panelRef={panelRef}\n title={title}\n width={width}\n cancelButtonProps={{\n color: 'default',\n variant: 'filled',\n ...cancelButtonProps,\n }}\n classNames={\n typeof classNames === 'function'\n ? classNames\n : {\n ...classNames,\n wrapper: cx(styles.wrap, classNames?.wrapper),\n }\n }\n styles={\n typeof customStyles === 'function'\n ? customStyles\n : {\n ...customStyles,\n body: {\n maxHeight: height,\n overflow: 'hidden auto',\n paddingBlock: `0 ${footer === null ? '16px' : 0}`,\n paddingInline: paddings?.desktop ?? 16,\n ...customStyles?.body,\n },\n }\n }\n onCancel={onCancel}\n onOk={onOk}\n {...rest}\n >\n {children}\n </AntModal>\n </ConfigProvider>\n );\n },\n);\n\nModal.displayName = 'Modal';\n\nexport default Modal;\n"],"mappings":";;;;;;;;;;AAaA,MAAMA,UAAQ,MACX,EACC,UACA,iBACA,UACA,QAAQ,KACR,WACA,YACA,QAAQ,KACR,UACA,MACA,iBACA,UACA,SAAS,SACT,mBAAmB,MACnB,QACA,QAAQ,cACR,QACA,MACA,YACA,eACA,mBACA,gBACA,GAAG,WACC;CACJ,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM;CACnD,MAAM,EAAE,WAAW,eAAe;CAClC,MAAM,aAAa,WAAW,SAAS,WAAW;AAClD,KAAI,oBAAoB,OACtB,QACE,oBAAC,gBAAD;EACE,OAAO,EACL,OAAO,EACL,iBAAiB,OAAO,kBACzB,EACF;YAED,oBAAC,QAAD;GACE,WAAW,GAAG,OAAO,eAAe,UAAU;GAC9C,WAAW,oBAAC,YAAD,EAAY,MAAM,GAAK,CAAA;GACjB;GACjB,QAAQ,aAAa,0CAA0C;GACzD;GACI;GACV,WAAW;GACJ;GACP,YACE,OAAO,eAAe,aAClB,aACA;IACE,GAAG;IACH,SAAS,GAAG,OAAO,MAAM,YAAY,QAAQ;IAC9C;GAEP,OACE,mBACE,oBAAC,YAAD;IACE,MAAM,aAAa,YAAY;IAC/B,eAAe,cAAc,CAAC,WAAW;IACzC,CAAA;GAGN,QACE,aACI,OACC,UACC,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,QAAD;IACE,OAAO;IACP,SAAS;IACT,SAAS;IACT,GAAI;cAEH,cAAc;IACR,CAAA,EACT,oBAAC,QAAD;IACE,SAAS;IACT,MAAK;IACL,SAAS;IACT,GAAI;IACJ,OAAO;KACL,mBAAmB;KACnB,GAAG,eAAe;KACnB;cAEA,UAAU;IACJ,CAAA,CACR,EAAA,CAAA;GAGX,QACE,OAAO,iBAAiB,aACpB,eACA;IACE,GAAG;IACH,MAAM;KACJ,cAAc,QAAQ,SAAS,IAAI;KACnC,eAAe,UAAU,WAAW;KACpC,GAAG,cAAc;KAClB;IACF;GAEP,SAAS;GACT,GAAI;GAEH;GACM,CAAA;EACM,CAAA;AAGrB,QACE,oBAAC,gBAAD;EACE,OAAO,EACL,OAAO,EACL,iBAAiB,OAAO,kBACzB,EACF;YAED,oBAACC,OAAD;GACE,UAAA;GACY;GACZ,WAAW,GAAG,OAAO,SAAS,UAAU;GACxC,WAAW,oBAAC,MAAD;IAAM,MAAM;IAAG,MAAM;IAAM,CAAA;GACtB;GACC;GACjB,QAAQ,aAAa,OAAO;GAC5B,MAAM,EAAE,UAAU,MAAM;GACT;GACP;GACF;GACI;GACH;GACA;GACP,mBAAmB;IACjB,OAAO;IACP,SAAS;IACT,GAAG;IACJ;GACD,YACE,OAAO,eAAe,aAClB,aACA;IACE,GAAG;IACH,SAAS,GAAG,OAAO,MAAM,YAAY,QAAQ;IAC9C;GAEP,QACE,OAAO,iBAAiB,aACpB,eACA;IACE,GAAG;IACH,MAAM;KACJ,WAAW;KACX,UAAU;KACV,cAAc,KAAK,WAAW,OAAO,SAAS;KAC9C,eAAe,UAAU,WAAW;KACpC,GAAG,cAAc;KAClB;IACF;GAEG;GACJ;GACN,GAAI;GAEH;GACQ,CAAA;EACI,CAAA;EAGtB;AAED,QAAM,cAAc"}
|
|
@@ -12,7 +12,7 @@ const ModalStackItem = memo(({ id, props, onClose, onUpdate, onDestroy }) => {
|
|
|
12
12
|
const stableAfterOpenChange = useEventCallback(afterOpenChange ?? noop);
|
|
13
13
|
const stableOnCancel = useEventCallback(onCancel ?? noop);
|
|
14
14
|
const close = useEventCallback(() => onClose(id));
|
|
15
|
-
const setCanDismissByClickOutside = useEventCallback((value) => onUpdate(id, {
|
|
15
|
+
const setCanDismissByClickOutside = useEventCallback((value) => onUpdate(id, { mask: { closable: value } }));
|
|
16
16
|
const stableContextValue = useMemo(() => ({
|
|
17
17
|
close,
|
|
18
18
|
setCanDismissByClickOutside
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModalStackItem.mjs","names":[],"sources":["../../src/Modal/ModalStackItem.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useMemo } from 'react';\n\nimport { useEventCallback } from '@/hooks/useEventCallback';\n\nimport Modal from './Modal';\nimport { ModalProvider } from './ModalProvider';\nimport type { ImperativeModalProps } from './type';\n\nexport type ModalStackItemProps = {\n id: string;\n onClose: (id: string) => void;\n onDestroy: (id: string) => void;\n onUpdate: (id: string, nextProps: Partial<ImperativeModalProps>) => void;\n props: ImperativeModalProps;\n};\n\nconst noop = () => {};\nexport const ModalStackItem = memo(\n ({ id, props, onClose, onUpdate, onDestroy }: ModalStackItemProps) => {\n const { afterClose, afterOpenChange, children, onCancel, open, ...rest } = props;\n const stableAfterClose = useEventCallback(afterClose ?? noop);\n const stableAfterOpenChange = useEventCallback(afterOpenChange ?? noop);\n const stableOnCancel = useEventCallback(onCancel ?? noop);\n const close = useEventCallback(() => onClose(id));\n const setCanDismissByClickOutside = useEventCallback((value: boolean) =>\n onUpdate(id, {
|
|
1
|
+
{"version":3,"file":"ModalStackItem.mjs","names":[],"sources":["../../src/Modal/ModalStackItem.tsx"],"sourcesContent":["'use client';\n\nimport { memo, useCallback, useMemo } from 'react';\n\nimport { useEventCallback } from '@/hooks/useEventCallback';\n\nimport Modal from './Modal';\nimport { ModalProvider } from './ModalProvider';\nimport type { ImperativeModalProps } from './type';\n\nexport type ModalStackItemProps = {\n id: string;\n onClose: (id: string) => void;\n onDestroy: (id: string) => void;\n onUpdate: (id: string, nextProps: Partial<ImperativeModalProps>) => void;\n props: ImperativeModalProps;\n};\n\nconst noop = () => {};\nexport const ModalStackItem = memo(\n ({ id, props, onClose, onUpdate, onDestroy }: ModalStackItemProps) => {\n const { afterClose, afterOpenChange, children, onCancel, open, ...rest } = props;\n const stableAfterClose = useEventCallback(afterClose ?? noop);\n const stableAfterOpenChange = useEventCallback(afterOpenChange ?? noop);\n const stableOnCancel = useEventCallback(onCancel ?? noop);\n const close = useEventCallback(() => onClose(id));\n const setCanDismissByClickOutside = useEventCallback((value: boolean) =>\n onUpdate(id, { mask: { closable: value } }),\n );\n const stableContextValue = useMemo(\n () => ({ close, setCanDismissByClickOutside }),\n [close, setCanDismissByClickOutside],\n );\n\n return (\n <Modal\n {...rest}\n open={open ?? true}\n afterClose={useCallback(() => {\n stableAfterClose?.();\n onDestroy(id);\n }, [stableAfterClose, onDestroy, id])}\n afterOpenChange={useCallback(\n (nextOpen: boolean) => {\n stableAfterOpenChange?.(nextOpen);\n if (!nextOpen) onDestroy(id);\n },\n [stableAfterOpenChange, onDestroy, id],\n )}\n onCancel={useCallback(\n (e: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLElement>) => {\n stableOnCancel?.(e);\n close();\n },\n [stableOnCancel, close],\n )}\n >\n <ModalProvider value={stableContextValue}>{children}</ModalProvider>\n </Modal>\n );\n },\n);\n\nModalStackItem.displayName = 'ModalStackItem';\n"],"mappings":";;;;;;;AAkBA,MAAM,aAAa;AACnB,MAAa,iBAAiB,MAC3B,EAAE,IAAI,OAAO,SAAS,UAAU,gBAAqC;CACpE,MAAM,EAAE,YAAY,iBAAiB,UAAU,UAAU,MAAM,GAAG,SAAS;CAC3E,MAAM,mBAAmB,iBAAiB,cAAc,KAAK;CAC7D,MAAM,wBAAwB,iBAAiB,mBAAmB,KAAK;CACvE,MAAM,iBAAiB,iBAAiB,YAAY,KAAK;CACzD,MAAM,QAAQ,uBAAuB,QAAQ,GAAG,CAAC;CACjD,MAAM,8BAA8B,kBAAkB,UACpD,SAAS,IAAI,EAAE,MAAM,EAAE,UAAU,OAAO,EAAE,CAAC,CAC5C;CACD,MAAM,qBAAqB,eAClB;EAAE;EAAO;EAA6B,GAC7C,CAAC,OAAO,4BAA4B,CACrC;AAED,QACE,oBAAC,OAAD;EACE,GAAI;EACJ,MAAM,QAAQ;EACd,YAAY,kBAAkB;AAC5B,uBAAoB;AACpB,aAAU,GAAG;KACZ;GAAC;GAAkB;GAAW;GAAG,CAAC;EACrC,iBAAiB,aACd,aAAsB;AACrB,2BAAwB,SAAS;AACjC,OAAI,CAAC,SAAU,WAAU,GAAG;KAE9B;GAAC;GAAuB;GAAW;GAAG,CACvC;EACD,UAAU,aACP,MAA8E;AAC7E,oBAAiB,EAAE;AACnB,UAAO;KAET,CAAC,gBAAgB,MAAM,CACxB;YAED,oBAAC,eAAD;GAAe,OAAO;GAAqB;GAAyB,CAAA;EAC9D,CAAA;EAGb;AAED,eAAe,cAAc"}
|
|
@@ -8,7 +8,7 @@ const RawModalStackItem = memo(({ component: Component, id, onClose, onUpdate, o
|
|
|
8
8
|
const stableOnClose = useEventCallback(onClose);
|
|
9
9
|
const close = useEventCallback(() => stableOnClose(id));
|
|
10
10
|
const setCanDismissByClickOutside = useEventCallback((value) => {
|
|
11
|
-
onUpdate(id, {
|
|
11
|
+
onUpdate(id, { mask: { closable: value } });
|
|
12
12
|
});
|
|
13
13
|
const contextValue = useMemo(() => ({
|
|
14
14
|
close,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RawModalStackItem.mjs","names":[],"sources":["../../src/Modal/RawModalStackItem.tsx"],"sourcesContent":["'use client';\n\nimport type { ComponentType } from 'react';\nimport { memo, useMemo } from 'react';\n\nimport { useEventCallback } from '@/hooks/useEventCallback';\n\nimport { ModalProvider } from './ModalProvider';\nimport type { ModalContextValue, RawModalOptions } from './type';\n\nexport type RawModalStackItemProps = {\n component: ComponentType<any>;\n id: string;\n onClose: (id: string) => void;\n onUpdate: (id: string, nextProps: Record<string, unknown>) => void;\n open: boolean;\n options?: RawModalOptions<PropertyKey, PropertyKey>;\n props: Record<string, unknown>;\n};\n\nexport const RawModalStackItem = memo(\n ({\n component: Component,\n id,\n onClose,\n onUpdate,\n open,\n options,\n props,\n }: RawModalStackItemProps) => {\n const stableOnClose = useEventCallback(onClose);\n const close = useEventCallback(() => stableOnClose(id));\n\n const setCanDismissByClickOutside = useEventCallback((value: boolean) => {\n onUpdate(id, {
|
|
1
|
+
{"version":3,"file":"RawModalStackItem.mjs","names":[],"sources":["../../src/Modal/RawModalStackItem.tsx"],"sourcesContent":["'use client';\n\nimport type { ComponentType } from 'react';\nimport { memo, useMemo } from 'react';\n\nimport { useEventCallback } from '@/hooks/useEventCallback';\n\nimport { ModalProvider } from './ModalProvider';\nimport type { ModalContextValue, RawModalOptions } from './type';\n\nexport type RawModalStackItemProps = {\n component: ComponentType<any>;\n id: string;\n onClose: (id: string) => void;\n onUpdate: (id: string, nextProps: Record<string, unknown>) => void;\n open: boolean;\n options?: RawModalOptions<PropertyKey, PropertyKey>;\n props: Record<string, unknown>;\n};\n\nexport const RawModalStackItem = memo(\n ({\n component: Component,\n id,\n onClose,\n onUpdate,\n open,\n options,\n props,\n }: RawModalStackItemProps) => {\n const stableOnClose = useEventCallback(onClose);\n const close = useEventCallback(() => stableOnClose(id));\n\n const setCanDismissByClickOutside = useEventCallback((value: boolean) => {\n onUpdate(id, { mask: { closable: value } });\n });\n const contextValue: ModalContextValue = useMemo(\n () => ({ close, setCanDismissByClickOutside }),\n [close, setCanDismissByClickOutside],\n );\n const openKey = options?.openKey ?? 'open';\n const onCloseKey = options?.onCloseKey ?? 'onClose';\n const injectedProps = {\n ...props,\n [onCloseKey]: close,\n [openKey]: open,\n };\n\n return (\n <ModalProvider value={contextValue}>\n <Component {...injectedProps} />\n </ModalProvider>\n );\n },\n);\n\nRawModalStackItem.displayName = 'RawModalStackItem';\n"],"mappings":";;;;;;AAoBA,MAAa,oBAAoB,MAC9B,EACC,WAAW,WACX,IACA,SACA,UACA,MACA,SACA,YAC4B;CAC5B,MAAM,gBAAgB,iBAAiB,QAAQ;CAC/C,MAAM,QAAQ,uBAAuB,cAAc,GAAG,CAAC;CAEvD,MAAM,8BAA8B,kBAAkB,UAAmB;AACvE,WAAS,IAAI,EAAE,MAAM,EAAE,UAAU,OAAO,EAAE,CAAC;GAC3C;CACF,MAAM,eAAkC,eAC/B;EAAE;EAAO;EAA6B,GAC7C,CAAC,OAAO,4BAA4B,CACrC;CACD,MAAM,UAAU,SAAS,WAAW;CACpC,MAAM,aAAa,SAAS,cAAc;AAO1C,QACE,oBAAC,eAAD;EAAe,OAAO;YACpB,oBAAC,WAAD;GAPF,GAAG;IACF,aAAa;IACb,UAAU;GAKuB,CAAA;EAClB,CAAA;EAGrB;AAED,kBAAkB,cAAc"}
|
package/es/Modal/imperative.mjs
CHANGED
|
@@ -158,7 +158,7 @@ const createModal = (props) => {
|
|
|
158
158
|
return {
|
|
159
159
|
close: () => closeModal(id),
|
|
160
160
|
destroy: () => destroyModal(id),
|
|
161
|
-
setCanDismissByClickOutside: (value) => updateModal(id, {
|
|
161
|
+
setCanDismissByClickOutside: (value) => updateModal(id, { mask: { closable: value } }),
|
|
162
162
|
update: (nextProps) => updateModal(id, nextProps)
|
|
163
163
|
};
|
|
164
164
|
};
|
|
@@ -176,7 +176,7 @@ function createRawModal(component, props, options) {
|
|
|
176
176
|
return {
|
|
177
177
|
close: () => closeModal(id),
|
|
178
178
|
destroy: () => destroyModal(id),
|
|
179
|
-
setCanDismissByClickOutside: (value) => updateRawProps(id, {
|
|
179
|
+
setCanDismissByClickOutside: (value) => updateRawProps(id, { mask: { closable: value } }),
|
|
180
180
|
update: (nextProps) => updateRawProps(id, nextProps)
|
|
181
181
|
};
|
|
182
182
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imperative.mjs","names":[],"sources":["../../src/Modal/imperative.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { memo, useEffect, useSyncExternalStore } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useIsClient } from '@/hooks/useIsClient';\nimport { useAppElement } from '@/ThemeProvider';\nimport { registerDevSingleton } from '@/utils/devSingleton';\n\nimport { ModalStackItem } from './ModalStackItem';\nimport { RawModalStackItem } from './RawModalStackItem';\nimport type {\n ImperativeModalProps,\n ModalInstance,\n RawModalComponent,\n RawModalComponentProps,\n RawModalInstance,\n RawModalKeyOptions,\n RawModalOptions,\n} from './type';\n\ntype ModalStackItemBase = {\n id: string;\n};\n\ntype ModalStackItemModal = ModalStackItemBase & {\n kind: 'modal';\n props: ImperativeModalProps;\n};\n\ntype ModalStackItemRaw = ModalStackItemBase & {\n component: RawModalComponent;\n kind: 'raw';\n open: boolean;\n options?: RawModalOptions<PropertyKey, PropertyKey>;\n props: Record<string, unknown>;\n};\n\ntype TModalStackItem = ModalStackItemModal | ModalStackItemRaw;\n\ntype ModalStackProps = {\n stack: TModalStackItem[];\n};\n\nexport type ModalHostProps = {\n root?: HTMLElement | ShadowRoot | null;\n};\n\nlet modalStack: TModalStackItem[] = [];\nlet modalSeed = 0;\nconst listeners = new Set<() => void>();\nconst rawDestroyTimers = new Map<string, number>();\n\nconst notify = () => {\n listeners.forEach((listener) => listener());\n};\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n};\n\nconst EMPTY_STACK: TModalStackItem[] = [];\nconst getSnapshot = () => modalStack;\nconst getServerSnapshot = () => EMPTY_STACK;\n\nconst ModalPortal = ({\n children,\n root,\n}: {\n children: ReactNode;\n root?: HTMLElement | ShadowRoot | null;\n}) => {\n const appElement = useAppElement();\n const container = root ?? appElement ?? document.body;\n\n return createPortal(children, container);\n};\n\nconst updateModal = (id: string, nextProps: Partial<ImperativeModalProps>) => {\n let changed = false;\n modalStack = modalStack.map((item) => {\n if (item.id !== id) return item;\n if (item.kind !== 'modal') return item;\n changed = true;\n return {\n ...item,\n props: { ...item.props, ...nextProps },\n };\n });\n\n if (changed) notify();\n};\n\nconst updateRawProps = (id: string, nextProps: Record<string, unknown>) => {\n let changed = false;\n modalStack = modalStack.map((item) => {\n if (item.id !== id) return item;\n if (item.kind !== 'raw') return item;\n changed = true;\n return {\n ...item,\n props: { ...item.props, ...nextProps },\n };\n });\n\n if (changed) notify();\n};\n\nconst setRawOpen = (id: string, open: boolean) => {\n let changed = false;\n modalStack = modalStack.map((item) => {\n if (item.id !== id) return item;\n if (item.kind !== 'raw') return item;\n if (item.open === open) return item;\n changed = true;\n return { ...item, open };\n });\n\n if (open) {\n const timer = rawDestroyTimers.get(id);\n if (timer) {\n clearTimeout(timer);\n rawDestroyTimers.delete(id);\n }\n }\n\n if (changed) notify();\n};\n\nconst closeModal = (id: string) => {\n const target = modalStack.find((item) => item.id === id);\n if (!target) return;\n\n if (target.kind === 'modal') {\n updateModal(id, { open: false });\n return;\n }\n\n setRawOpen(id, false);\n\n const shouldDestroy = target.options?.destroyOnClose ?? true;\n if (!shouldDestroy) return;\n\n const delay = target.options?.destroyDelay ?? 200;\n const existing = rawDestroyTimers.get(id);\n if (existing) clearTimeout(existing);\n const timer = window.setTimeout(() => {\n rawDestroyTimers.delete(id);\n\n destroyModal(id);\n }, delay);\n rawDestroyTimers.set(id, timer);\n};\n\nconst destroyModal = (id: string) => {\n const timer = rawDestroyTimers.get(id);\n if (timer) {\n clearTimeout(timer);\n rawDestroyTimers.delete(id);\n }\n const nextStack = modalStack.filter((item) => item.id !== id);\n if (nextStack.length === modalStack.length) return;\n modalStack = nextStack;\n notify();\n};\n\nconst ModalStack = memo(({ stack }: ModalStackProps) => {\n const isClient = useIsClient();\n if (!isClient) return null;\n return stack.map((item) => {\n if (item.kind === 'modal') {\n return (\n <ModalStackItem\n id={item.id}\n key={item.id}\n props={item.props}\n onClose={closeModal}\n onDestroy={destroyModal}\n onUpdate={updateModal}\n />\n );\n }\n\n return (\n <RawModalStackItem\n component={item.component}\n id={item.id}\n key={item.id}\n open={item.open}\n options={item.options}\n props={item.props}\n onClose={closeModal}\n onUpdate={updateRawProps}\n />\n );\n });\n});\n\nModalStack.displayName = 'ModalStack';\n\nexport const ModalHost = ({ root }: ModalHostProps) => {\n const stack = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n const isClient = useIsClient();\n\n useEffect(() => {\n if (!isClient) return;\n // Enforce singleton per portal root (dev-only).\n const scope = root ?? document.body;\n return registerDevSingleton('ModalHost', scope);\n }, [isClient, root]);\n\n if (!isClient) return null;\n if (stack.length === 0) return null;\n\n return (\n <ModalPortal root={root}>\n <ModalStack stack={stack} />\n </ModalPortal>\n );\n};\n\nexport const createModal = (props: ImperativeModalProps): ModalInstance => {\n const id = `modal-${Date.now()}-${modalSeed++}`;\n modalStack = [\n ...modalStack,\n { id, kind: 'modal', props: { ...props, open: props.open ?? true } },\n ];\n notify();\n\n return {\n close: () => closeModal(id),\n destroy: () => destroyModal(id),\n setCanDismissByClickOutside: (value) => updateModal(id, { maskClosable: value }),\n update: (nextProps) => updateModal(id, nextProps),\n };\n};\n\nexport function createRawModal<P extends RawModalComponentProps>(\n component: RawModalComponent<P>,\n props: Omit<P, 'open' | 'onClose'>,\n options?: RawModalOptions,\n): RawModalInstance<P>;\n\nexport function createRawModal<P, OpenKey extends keyof P, CloseKey extends keyof P>(\n component: RawModalComponent<P>,\n props: Omit<P, OpenKey | CloseKey>,\n options: RawModalKeyOptions<OpenKey, CloseKey>,\n): RawModalInstance<P, OpenKey, CloseKey>;\n\nexport function createRawModal<P, OpenKey extends keyof P, CloseKey extends keyof P>(\n component: RawModalComponent<P>,\n props: Omit<P, OpenKey | CloseKey>,\n options?: RawModalOptions<OpenKey, CloseKey>,\n): RawModalInstance<P, OpenKey, CloseKey> {\n const id = `modal-${Date.now()}-${modalSeed++}`;\n modalStack = [\n ...modalStack,\n {\n component,\n id,\n kind: 'raw',\n open: true,\n options,\n props: props as Record<string, unknown>,\n },\n ];\n notify();\n\n return {\n close: () => closeModal(id),\n destroy: () => destroyModal(id),\n setCanDismissByClickOutside: (value) => updateRawProps(id, { maskClosable: value }),\n update: (nextProps) => updateRawProps(id, nextProps as Record<string, unknown>),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"imperative.mjs","names":[],"sources":["../../src/Modal/imperative.tsx"],"sourcesContent":["'use client';\n\nimport type { ReactNode } from 'react';\nimport { memo, useEffect, useSyncExternalStore } from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useIsClient } from '@/hooks/useIsClient';\nimport { useAppElement } from '@/ThemeProvider';\nimport { registerDevSingleton } from '@/utils/devSingleton';\n\nimport { ModalStackItem } from './ModalStackItem';\nimport { RawModalStackItem } from './RawModalStackItem';\nimport type {\n ImperativeModalProps,\n ModalInstance,\n RawModalComponent,\n RawModalComponentProps,\n RawModalInstance,\n RawModalKeyOptions,\n RawModalOptions,\n} from './type';\n\ntype ModalStackItemBase = {\n id: string;\n};\n\ntype ModalStackItemModal = ModalStackItemBase & {\n kind: 'modal';\n props: ImperativeModalProps;\n};\n\ntype ModalStackItemRaw = ModalStackItemBase & {\n component: RawModalComponent;\n kind: 'raw';\n open: boolean;\n options?: RawModalOptions<PropertyKey, PropertyKey>;\n props: Record<string, unknown>;\n};\n\ntype TModalStackItem = ModalStackItemModal | ModalStackItemRaw;\n\ntype ModalStackProps = {\n stack: TModalStackItem[];\n};\n\nexport type ModalHostProps = {\n root?: HTMLElement | ShadowRoot | null;\n};\n\nlet modalStack: TModalStackItem[] = [];\nlet modalSeed = 0;\nconst listeners = new Set<() => void>();\nconst rawDestroyTimers = new Map<string, number>();\n\nconst notify = () => {\n listeners.forEach((listener) => listener());\n};\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n};\n\nconst EMPTY_STACK: TModalStackItem[] = [];\nconst getSnapshot = () => modalStack;\nconst getServerSnapshot = () => EMPTY_STACK;\n\nconst ModalPortal = ({\n children,\n root,\n}: {\n children: ReactNode;\n root?: HTMLElement | ShadowRoot | null;\n}) => {\n const appElement = useAppElement();\n const container = root ?? appElement ?? document.body;\n\n return createPortal(children, container);\n};\n\nconst updateModal = (id: string, nextProps: Partial<ImperativeModalProps>) => {\n let changed = false;\n modalStack = modalStack.map((item) => {\n if (item.id !== id) return item;\n if (item.kind !== 'modal') return item;\n changed = true;\n return {\n ...item,\n props: { ...item.props, ...nextProps },\n };\n });\n\n if (changed) notify();\n};\n\nconst updateRawProps = (id: string, nextProps: Record<string, unknown>) => {\n let changed = false;\n modalStack = modalStack.map((item) => {\n if (item.id !== id) return item;\n if (item.kind !== 'raw') return item;\n changed = true;\n return {\n ...item,\n props: { ...item.props, ...nextProps },\n };\n });\n\n if (changed) notify();\n};\n\nconst setRawOpen = (id: string, open: boolean) => {\n let changed = false;\n modalStack = modalStack.map((item) => {\n if (item.id !== id) return item;\n if (item.kind !== 'raw') return item;\n if (item.open === open) return item;\n changed = true;\n return { ...item, open };\n });\n\n if (open) {\n const timer = rawDestroyTimers.get(id);\n if (timer) {\n clearTimeout(timer);\n rawDestroyTimers.delete(id);\n }\n }\n\n if (changed) notify();\n};\n\nconst closeModal = (id: string) => {\n const target = modalStack.find((item) => item.id === id);\n if (!target) return;\n\n if (target.kind === 'modal') {\n updateModal(id, { open: false });\n return;\n }\n\n setRawOpen(id, false);\n\n const shouldDestroy = target.options?.destroyOnClose ?? true;\n if (!shouldDestroy) return;\n\n const delay = target.options?.destroyDelay ?? 200;\n const existing = rawDestroyTimers.get(id);\n if (existing) clearTimeout(existing);\n const timer = window.setTimeout(() => {\n rawDestroyTimers.delete(id);\n\n destroyModal(id);\n }, delay);\n rawDestroyTimers.set(id, timer);\n};\n\nconst destroyModal = (id: string) => {\n const timer = rawDestroyTimers.get(id);\n if (timer) {\n clearTimeout(timer);\n rawDestroyTimers.delete(id);\n }\n const nextStack = modalStack.filter((item) => item.id !== id);\n if (nextStack.length === modalStack.length) return;\n modalStack = nextStack;\n notify();\n};\n\nconst ModalStack = memo(({ stack }: ModalStackProps) => {\n const isClient = useIsClient();\n if (!isClient) return null;\n return stack.map((item) => {\n if (item.kind === 'modal') {\n return (\n <ModalStackItem\n id={item.id}\n key={item.id}\n props={item.props}\n onClose={closeModal}\n onDestroy={destroyModal}\n onUpdate={updateModal}\n />\n );\n }\n\n return (\n <RawModalStackItem\n component={item.component}\n id={item.id}\n key={item.id}\n open={item.open}\n options={item.options}\n props={item.props}\n onClose={closeModal}\n onUpdate={updateRawProps}\n />\n );\n });\n});\n\nModalStack.displayName = 'ModalStack';\n\nexport const ModalHost = ({ root }: ModalHostProps) => {\n const stack = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n const isClient = useIsClient();\n\n useEffect(() => {\n if (!isClient) return;\n // Enforce singleton per portal root (dev-only).\n const scope = root ?? document.body;\n return registerDevSingleton('ModalHost', scope);\n }, [isClient, root]);\n\n if (!isClient) return null;\n if (stack.length === 0) return null;\n\n return (\n <ModalPortal root={root}>\n <ModalStack stack={stack} />\n </ModalPortal>\n );\n};\n\nexport const createModal = (props: ImperativeModalProps): ModalInstance => {\n const id = `modal-${Date.now()}-${modalSeed++}`;\n modalStack = [\n ...modalStack,\n { id, kind: 'modal', props: { ...props, open: props.open ?? true } },\n ];\n notify();\n\n return {\n close: () => closeModal(id),\n destroy: () => destroyModal(id),\n setCanDismissByClickOutside: (value) => updateModal(id, { mask: { closable: value } }),\n update: (nextProps) => updateModal(id, nextProps),\n };\n};\n\nexport function createRawModal<P extends RawModalComponentProps>(\n component: RawModalComponent<P>,\n props: Omit<P, 'open' | 'onClose'>,\n options?: RawModalOptions,\n): RawModalInstance<P>;\n\nexport function createRawModal<P, OpenKey extends keyof P, CloseKey extends keyof P>(\n component: RawModalComponent<P>,\n props: Omit<P, OpenKey | CloseKey>,\n options: RawModalKeyOptions<OpenKey, CloseKey>,\n): RawModalInstance<P, OpenKey, CloseKey>;\n\nexport function createRawModal<P, OpenKey extends keyof P, CloseKey extends keyof P>(\n component: RawModalComponent<P>,\n props: Omit<P, OpenKey | CloseKey>,\n options?: RawModalOptions<OpenKey, CloseKey>,\n): RawModalInstance<P, OpenKey, CloseKey> {\n const id = `modal-${Date.now()}-${modalSeed++}`;\n modalStack = [\n ...modalStack,\n {\n component,\n id,\n kind: 'raw',\n open: true,\n options,\n props: props as Record<string, unknown>,\n },\n ];\n notify();\n\n return {\n close: () => closeModal(id),\n destroy: () => destroyModal(id),\n setCanDismissByClickOutside: (value) => updateRawProps(id, { mask: { closable: value } }),\n update: (nextProps) => updateRawProps(id, nextProps as Record<string, unknown>),\n };\n}\n"],"mappings":"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"}
|
|
@@ -67,8 +67,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
67
67
|
outline: none;
|
|
68
68
|
box-shadow:
|
|
69
69
|
0 0 15px 0 #00000008,
|
|
70
|
-
0 2px 30px 0 #00000014
|
|
71
|
-
0 0 0 1px ${cssVar.colorBorder} inset;
|
|
70
|
+
0 2px 30px 0 #00000014;
|
|
72
71
|
|
|
73
72
|
transition-timing-function: var(--lobe-popover-animation-ease-out);
|
|
74
73
|
transition-duration: var(--lobe-popover-animation-duration);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/base-ui/Popover/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n arrow: css`\n --lobe-popover-arrow-offset-block: 5px;\n --lobe-popover-arrow-offset-inline: 8px;\n\n pointer-events: none;\n\n position: absolute;\n transform-origin: center;\n\n display: flex;\n\n width: 12px;\n height: 6px;\n\n transition: inset-inline-start var(--lobe-popover-animation-duration)\n var(--lobe-popover-animation-ease-out);\n\n & > svg {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n & [data-role='fill'] {\n fill: ${cssVar.colorBgElevated};\n }\n\n & [data-role='stroke'] {\n fill: none;\n stroke: ${cssVar.colorBorder};\n stroke-width: 1px;\n }\n\n &[data-side='top'] {\n inset-block-end: calc(var(--lobe-popover-arrow-offset-block) * -1);\n transform: rotate(180deg);\n }\n\n &[data-side='left'] {\n inset-inline-end: calc(var(--lobe-popover-arrow-offset-inline) * -1);\n transform: rotate(90deg);\n }\n\n &[data-side='right'] {\n inset-inline-start: calc(var(--lobe-popover-arrow-offset-inline) * -1);\n transform: rotate(-90deg);\n }\n\n &[data-side='bottom'] {\n inset-block-start: calc(var(--lobe-popover-arrow-offset-block) * -1);\n }\n `,\n\n popup: css`\n position: relative;\n transform-origin: var(--transform-origin);\n\n min-width: 120px;\n max-width: var(--available-width);\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorText};\n\n background: ${cssVar.colorBgElevated};\n outline: none;\n box-shadow:\n 0 0 15px 0 #00000008,\n 0 2px 30px 0 #00000014
|
|
1
|
+
{"version":3,"file":"style.mjs","names":[],"sources":["../../../src/base-ui/Popover/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n arrow: css`\n --lobe-popover-arrow-offset-block: 5px;\n --lobe-popover-arrow-offset-inline: 8px;\n\n pointer-events: none;\n\n position: absolute;\n transform-origin: center;\n\n display: flex;\n\n width: 12px;\n height: 6px;\n\n transition: inset-inline-start var(--lobe-popover-animation-duration)\n var(--lobe-popover-animation-ease-out);\n\n & > svg {\n display: block;\n width: 100%;\n height: 100%;\n }\n\n & [data-role='fill'] {\n fill: ${cssVar.colorBgElevated};\n }\n\n & [data-role='stroke'] {\n fill: none;\n stroke: ${cssVar.colorBorder};\n stroke-width: 1px;\n }\n\n &[data-side='top'] {\n inset-block-end: calc(var(--lobe-popover-arrow-offset-block) * -1);\n transform: rotate(180deg);\n }\n\n &[data-side='left'] {\n inset-inline-end: calc(var(--lobe-popover-arrow-offset-inline) * -1);\n transform: rotate(90deg);\n }\n\n &[data-side='right'] {\n inset-inline-start: calc(var(--lobe-popover-arrow-offset-inline) * -1);\n transform: rotate(-90deg);\n }\n\n &[data-side='bottom'] {\n inset-block-start: calc(var(--lobe-popover-arrow-offset-block) * -1);\n }\n `,\n\n popup: css`\n position: relative;\n transform-origin: var(--transform-origin);\n\n min-width: 120px;\n max-width: var(--available-width);\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorText};\n\n background: ${cssVar.colorBgElevated};\n outline: none;\n box-shadow:\n 0 0 15px 0 #00000008,\n 0 2px 30px 0 #00000014;\n\n transition-timing-function: var(--lobe-popover-animation-ease-out);\n transition-duration: var(--lobe-popover-animation-duration);\n transition-property: opacity, transform;\n\n &[data-layout-animation] {\n transition-property: opacity, transform, width, height;\n }\n\n &[data-starting-style],\n &[data-ending-style] {\n transform: translate3d(var(--lobe-popover-translate-x), var(--lobe-popover-translate-y), 0)\n scale(var(--lobe-popover-animation-scale));\n opacity: 0;\n }\n\n &[data-ending-style] {\n transition-timing-function: var(--lobe-popover-animation-ease-in);\n transition-duration: var(--lobe-popover-animation-duration-exit);\n }\n\n &[data-instant] {\n transition: none;\n }\n `,\n\n positioner: css`\n --lobe-popover-animation-duration: 150ms;\n --lobe-popover-animation-translate: 6px;\n --lobe-popover-animation-scale: 0.96;\n --lobe-popover-animation-ease-in: ease-in;\n --lobe-popover-animation-duration-exit: 75ms;\n --lobe-popover-animation-ease-out: ${cssVar.motionEaseOut};\n --lobe-popover-translate-x: 0;\n --lobe-popover-translate-y: calc(var(--lobe-popover-animation-translate) * -1);\n\n z-index: 1100;\n\n width: min(var(--positioner-width), var(--available-width));\n height: var(--positioner-height);\n\n transition-timing-function: var(--lobe-popover-animation-ease-out);\n transition-duration: var(--lobe-popover-animation-duration);\n transition-property: none;\n\n &[data-layout-animation] {\n transition-property:\n inset-block-start, inset-inline-start, inset-inline-end, inset-block-end, transform;\n }\n\n &[data-instant] {\n transition: none;\n }\n\n /* Fallback: never show a popover when the anchor is hidden or the positioner falls back to (0,0). */\n &[data-anchor-hidden],\n &[data-zero-origin='true'] {\n pointer-events: none;\n visibility: hidden;\n }\n\n &[data-placement='top'],\n &[data-placement='topLeft'],\n &[data-placement='topRight'] {\n --lobe-popover-translate-x: 0;\n --lobe-popover-translate-y: var(--lobe-popover-animation-translate);\n }\n\n &[data-placement='bottom'],\n &[data-placement='bottomLeft'],\n &[data-placement='bottomRight'] {\n --lobe-popover-translate-x: 0;\n --lobe-popover-translate-y: calc(var(--lobe-popover-animation-translate) * -1);\n }\n\n &[data-placement='left'],\n &[data-placement='leftTop'],\n &[data-placement='leftBottom'] {\n --lobe-popover-translate-x: var(--lobe-popover-animation-translate);\n --lobe-popover-translate-y: 0;\n }\n\n &[data-placement='right'],\n &[data-placement='rightTop'],\n &[data-placement='rightBottom'] {\n --lobe-popover-translate-x: calc(var(--lobe-popover-animation-translate) * -1);\n --lobe-popover-translate-y: 0;\n }\n `,\n\n root: css`\n user-select: none;\n position: relative;\n filter: drop-shadow(0 2px 8px rgb(0 0 0 / 12%));\n `,\n\n viewport: css`\n --lobe-popover-viewport-inline-padding: 12px;\n\n position: relative;\n\n overflow: clip;\n\n max-width: var(--available-width);\n padding-block: 12px;\n padding-inline: var(--lobe-popover-viewport-inline-padding);\n\n [data-previous],\n [data-current] {\n transform: translateX(0);\n opacity: 1;\n transition:\n transform var(--lobe-popover-animation-duration) var(--lobe-popover-animation-ease-out),\n opacity calc(var(--lobe-popover-animation-duration) / 2)\n var(--lobe-popover-animation-ease-out);\n }\n\n [data-previous] {\n position: absolute;\n inset-block-start: 12px;\n inset-inline-start: var(--lobe-popover-viewport-inline-padding);\n }\n\n &[data-activation-direction~='right'] [data-previous][data-ending-style] {\n transform: translateX(-50%);\n opacity: 0;\n }\n\n &[data-activation-direction~='right'] [data-current][data-starting-style] {\n transform: translateX(50%);\n opacity: 0;\n }\n\n &[data-activation-direction~='left'] [data-previous][data-ending-style] {\n transform: translateX(50%);\n opacity: 0;\n }\n\n &[data-activation-direction~='left'] [data-current][data-starting-style] {\n transform: translateX(-50%);\n opacity: 0;\n }\n\n &[data-activation-direction~='down'] [data-previous][data-ending-style] {\n transform: translateY(-50%);\n opacity: 0;\n }\n\n &[data-activation-direction~='down'] [data-current][data-starting-style] {\n transform: translateY(50%);\n opacity: 0;\n }\n\n &[data-activation-direction~='up'] [data-previous][data-ending-style] {\n transform: translateY(50%);\n opacity: 0;\n }\n\n &[data-activation-direction~='up'] [data-current][data-starting-style] {\n transform: translateY(-50%);\n opacity: 0;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;cAwBE,OAAO,gBAAgB;;;;;gBAKrB,OAAO,YAAY;;;;;;;;;;;;;;;;;;;;;;;CAwBjC,OAAO,GAAG;;;;;;qBAMS,OAAO,aAAa;;aAE5B,OAAO,UAAU;;kBAEZ,OAAO,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BvC,YAAY,GAAG;;;;;;yCAMwB,OAAO,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0D5D,MAAM,GAAG;;;;;CAMT,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmEd,EAAE"}
|
package/es/hooks/useMermaid.mjs
CHANGED
|
@@ -17,10 +17,10 @@ const loadMermaid = () => {
|
|
|
17
17
|
if (!mermaidPromise) mermaidPromise = import("mermaid").then((mod) => mod.default);
|
|
18
18
|
return mermaidPromise;
|
|
19
19
|
};
|
|
20
|
-
const createMermaidConfig = (theme, customTheme) => ({
|
|
20
|
+
const createMermaidConfig = (theme, customTheme, securityLevel = "strict") => ({
|
|
21
21
|
fontFamily: theme.fontFamilyCode,
|
|
22
22
|
gantt: { useWidth: 1920 },
|
|
23
|
-
securityLevel
|
|
23
|
+
securityLevel,
|
|
24
24
|
startOnLoad: false,
|
|
25
25
|
theme: customTheme || (theme.isDarkMode ? "dark" : "neutral"),
|
|
26
26
|
themeVariables: customTheme ? void 0 : {
|
|
@@ -50,10 +50,10 @@ const createMermaidConfig = (theme, customTheme) => ({
|
|
|
50
50
|
/**
|
|
51
51
|
* 验证并处理 Mermaid 图表内容 - 优化版本(移除 SWR)
|
|
52
52
|
*/
|
|
53
|
-
const useMermaid = (content, { id, theme: customTheme }) => {
|
|
53
|
+
const useMermaid = (content, { id, theme: customTheme, securityLevel }) => {
|
|
54
54
|
const theme = useTheme();
|
|
55
55
|
const [data, setData] = useState("");
|
|
56
|
-
const mermaidConfig = useMemo(() => createMermaidConfig(theme, customTheme), [
|
|
56
|
+
const mermaidConfig = useMemo(() => createMermaidConfig(theme, customTheme, securityLevel), [
|
|
57
57
|
theme.fontFamilyCode,
|
|
58
58
|
theme.isDarkMode,
|
|
59
59
|
theme.colorTextDescription,
|
|
@@ -72,7 +72,8 @@ const useMermaid = (content, { id, theme: customTheme }) => {
|
|
|
72
72
|
theme.colorSuccessBg,
|
|
73
73
|
theme.colorSuccessText,
|
|
74
74
|
theme.colorText,
|
|
75
|
-
customTheme
|
|
75
|
+
customTheme,
|
|
76
|
+
securityLevel
|
|
76
77
|
]);
|
|
77
78
|
const cacheKey = useMemo(() => {
|
|
78
79
|
const hash = content.length < 1e4 ? content : Md5.hashStr(content);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useMermaid.mjs","names":[],"sources":["../../src/hooks/useMermaid.ts"],"sourcesContent":["'use client';\n\nimport { useTheme } from 'antd-style';\nimport type { MermaidConfig } from 'mermaid';\nimport { useEffect, useMemo, useState } from 'react';\nimport { Md5 } from 'ts-md5';\n\n// 缓存已验证的图表内容\nexport const MD5_LENGTH_THRESHOLD = 10_000;\n\n// Application-level cache for rendered Mermaid SVG\n// Key: cacheKey string, Value: Promise<string>\nconst mermaidCache = new Map<string, Promise<string>>();\n\n// Maximum cache size to prevent memory leaks\nconst MAX_CACHE_SIZE = 500;\n\n// Clean up old cache entries when limit is reached\nconst cleanupCache = () => {\n if (mermaidCache.size > MAX_CACHE_SIZE) {\n // Remove oldest 20% of entries\n const entriesToRemove = Math.floor(MAX_CACHE_SIZE * 0.2);\n const keysToRemove = Array.from(mermaidCache.keys()).slice(0, entriesToRemove);\n for (const key of keysToRemove) {\n mermaidCache.delete(key);\n }\n }\n};\n\n// 懒加载 mermaid 实例\nlet mermaidPromise: Promise<typeof import('mermaid').default | null> | null = null;\n\nexport const loadMermaid = (): Promise<typeof import('mermaid').default | null> => {\n if (typeof window === 'undefined') return Promise.resolve(null);\n\n if (!mermaidPromise) {\n mermaidPromise = import('mermaid').then((mod) => mod.default);\n }\n\n return mermaidPromise;\n};\n\n// Helper to create mermaid config\nexport const createMermaidConfig = (\n theme: ReturnType<typeof useTheme>,\n customTheme?: MermaidConfig['theme'],\n): MermaidConfig => ({\n fontFamily: theme.fontFamilyCode,\n gantt: {\n useWidth: 1920,\n },\n securityLevel
|
|
1
|
+
{"version":3,"file":"useMermaid.mjs","names":[],"sources":["../../src/hooks/useMermaid.ts"],"sourcesContent":["'use client';\n\nimport { useTheme } from 'antd-style';\nimport type { MermaidConfig } from 'mermaid';\nimport { useEffect, useMemo, useState } from 'react';\nimport { Md5 } from 'ts-md5';\n\n// 缓存已验证的图表内容\nexport const MD5_LENGTH_THRESHOLD = 10_000;\n\n// Application-level cache for rendered Mermaid SVG\n// Key: cacheKey string, Value: Promise<string>\nconst mermaidCache = new Map<string, Promise<string>>();\n\n// Maximum cache size to prevent memory leaks\nconst MAX_CACHE_SIZE = 500;\n\n// Clean up old cache entries when limit is reached\nconst cleanupCache = () => {\n if (mermaidCache.size > MAX_CACHE_SIZE) {\n // Remove oldest 20% of entries\n const entriesToRemove = Math.floor(MAX_CACHE_SIZE * 0.2);\n const keysToRemove = Array.from(mermaidCache.keys()).slice(0, entriesToRemove);\n for (const key of keysToRemove) {\n mermaidCache.delete(key);\n }\n }\n};\n\n// 懒加载 mermaid 实例\nlet mermaidPromise: Promise<typeof import('mermaid').default | null> | null = null;\n\nexport const loadMermaid = (): Promise<typeof import('mermaid').default | null> => {\n if (typeof window === 'undefined') return Promise.resolve(null);\n\n if (!mermaidPromise) {\n mermaidPromise = import('mermaid').then((mod) => mod.default);\n }\n\n return mermaidPromise;\n};\n\n// Helper to create mermaid config\nexport const createMermaidConfig = (\n theme: ReturnType<typeof useTheme>,\n customTheme?: MermaidConfig['theme'],\n // SECURITY: Keep 'strict' as the default. Using 'loose' causes Mermaid to render\n // node labels via innerHTML, enabling XSS when diagram content is user-controlled.\n // Only pass 'loose' if your use case explicitly requires HTML labels and you control\n // the diagram source entirely.\n securityLevel: MermaidConfig['securityLevel'] = 'strict',\n): MermaidConfig => ({\n fontFamily: theme.fontFamilyCode,\n gantt: {\n useWidth: 1920,\n },\n securityLevel,\n startOnLoad: false,\n theme: customTheme || (theme.isDarkMode ? 'dark' : 'neutral'),\n themeVariables: customTheme\n ? undefined\n : {\n errorBkgColor: theme.colorTextDescription,\n errorTextColor: theme.colorTextDescription,\n fontFamily: theme.fontFamily,\n lineColor: theme.colorTextSecondary,\n mainBkg: theme.colorBgContainer,\n noteBkgColor: theme.colorInfoBg,\n noteTextColor: theme.colorInfoText,\n pie1: theme.geekblue,\n pie2: theme.colorWarning,\n pie3: theme.colorSuccess,\n pie4: theme.colorError,\n primaryBorderColor: theme.colorBorder,\n primaryColor: theme.colorBgContainer,\n primaryTextColor: theme.colorText,\n secondaryBorderColor: theme.colorInfoBorder,\n secondaryColor: theme.colorInfoBg,\n secondaryTextColor: theme.colorInfoText,\n tertiaryBorderColor: theme.colorSuccessBorder,\n tertiaryColor: theme.colorSuccessBg,\n tertiaryTextColor: theme.colorSuccessText,\n textColor: theme.colorText,\n },\n});\n\n/**\n * 验证并处理 Mermaid 图表内容 - 优化版本(移除 SWR)\n */\nexport const useMermaid = (\n content: string,\n {\n id,\n theme: customTheme,\n securityLevel,\n }: {\n id: string;\n // SECURITY: Defaults to 'strict'. Set to 'loose' only when you fully control\n // the diagram source and intentionally need HTML rendering in node labels.\n securityLevel?: MermaidConfig['securityLevel'];\n theme?: MermaidConfig['theme'];\n },\n): string => {\n const theme = useTheme();\n const [data, setData] = useState<string>('');\n\n // 提取主题相关配置到 useMemo 中 - 只依赖实际使用的 theme 属性\n const mermaidConfig = useMemo(\n () => createMermaidConfig(theme, customTheme, securityLevel),\n [\n theme.fontFamilyCode,\n theme.isDarkMode,\n theme.colorTextDescription,\n theme.fontFamily,\n theme.colorTextSecondary,\n theme.colorBgContainer,\n theme.colorInfoBg,\n theme.colorInfoText,\n theme.geekblue,\n theme.colorWarning,\n theme.colorSuccess,\n theme.colorError,\n theme.colorBorder,\n theme.colorInfoBorder,\n theme.colorSuccessBorder,\n theme.colorSuccessBg,\n theme.colorSuccessText,\n theme.colorText,\n customTheme,\n securityLevel,\n ],\n );\n\n // 为长内容生成哈希键\n const cacheKey = useMemo((): string => {\n const hash = content.length < MD5_LENGTH_THRESHOLD ? content : Md5.hashStr(content);\n return [id, customTheme || (theme.isDarkMode ? 'd' : 'l'), hash].filter(Boolean).join('-');\n }, [content, id, theme.isDarkMode, customTheme]);\n\n useEffect(() => {\n // Check cache first\n const cachedPromise = mermaidCache.get(cacheKey);\n if (cachedPromise) {\n cachedPromise\n .then((svg) => {\n setData(svg);\n })\n .catch(() => {\n // Silently handle errors, fallback will be handled in the promise\n });\n return;\n }\n\n // Create new promise for rendering\n const renderPromise = (async (): Promise<string> => {\n try {\n const mermaidInstance = await loadMermaid();\n if (!mermaidInstance) return '';\n\n // 验证语法\n const isValid = await mermaidInstance.parse(content);\n\n if (isValid) {\n // 初始化并渲染\n mermaidInstance.initialize(mermaidConfig);\n const { svg } = await mermaidInstance.render(id, content);\n return svg;\n } else {\n throw new Error('Mermaid 语法无效');\n }\n } catch (error_) {\n console.error('Mermaid 解析错误:', error_);\n return '';\n }\n })();\n\n // Cache the promise\n mermaidCache.set(cacheKey, renderPromise);\n cleanupCache();\n\n // Handle promise result\n renderPromise\n .then((svg) => {\n // Only update if this is still the current cache key\n if (mermaidCache.get(cacheKey) === renderPromise) {\n setData(svg);\n }\n })\n .catch(() => {\n // Remove failed promise from cache\n if (mermaidCache.get(cacheKey) === renderPromise) {\n mermaidCache.delete(cacheKey);\n }\n });\n }, [cacheKey, content, id, mermaidConfig]);\n\n return data;\n};\n"],"mappings":"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"}
|