@seedgrid/fe-components 0.2.10 → 2026.3.1
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/dist/buttons/SgFloatActionButton.d.ts.map +1 -1
- package/dist/buttons/SgFloatActionButton.js +168 -38
- package/dist/commons/SgAvatar.d.ts +66 -0
- package/dist/commons/SgAvatar.d.ts.map +1 -0
- package/dist/commons/SgAvatar.js +136 -0
- package/dist/commons/SgSkeleton.d.ts +16 -0
- package/dist/commons/SgSkeleton.d.ts.map +1 -0
- package/dist/commons/SgSkeleton.js +58 -0
- package/dist/digits/discard-digit/SgDiscardDigit.d.ts +39 -0
- package/dist/digits/discard-digit/SgDiscardDigit.d.ts.map +1 -0
- package/dist/digits/discard-digit/SgDiscardDigit.js +303 -0
- package/dist/digits/discard-digit/index.d.ts +3 -0
- package/dist/digits/discard-digit/index.d.ts.map +1 -0
- package/dist/digits/discard-digit/index.js +1 -0
- package/dist/digits/fade-digit/SgFadeDigit.d.ts +27 -0
- package/dist/digits/fade-digit/SgFadeDigit.d.ts.map +1 -0
- package/dist/digits/fade-digit/SgFadeDigit.js +85 -0
- package/dist/digits/fade-digit/index.d.ts +3 -0
- package/dist/digits/fade-digit/index.d.ts.map +1 -0
- package/dist/digits/fade-digit/index.js +1 -0
- package/dist/digits/flip-digit/SgFlipDigit.d.ts +27 -0
- package/dist/digits/flip-digit/SgFlipDigit.d.ts.map +1 -0
- package/dist/digits/flip-digit/SgFlipDigit.js +70 -0
- package/dist/digits/flip-digit/index.d.ts.map +1 -0
- package/dist/digits/matrix-digit/SgMatrixDigit.d.ts +32 -0
- package/dist/digits/matrix-digit/SgMatrixDigit.d.ts.map +1 -0
- package/dist/digits/matrix-digit/SgMatrixDigit.js +86 -0
- package/dist/digits/matrix-digit/index.d.ts +3 -0
- package/dist/digits/matrix-digit/index.d.ts.map +1 -0
- package/dist/digits/matrix-digit/index.js +1 -0
- package/dist/digits/neon-digit/SgNeonDigit.d.ts +37 -0
- package/dist/digits/neon-digit/SgNeonDigit.d.ts.map +1 -0
- package/dist/digits/neon-digit/SgNeonDigit.js +59 -0
- package/dist/digits/neon-digit/index.d.ts +3 -0
- package/dist/digits/neon-digit/index.d.ts.map +1 -0
- package/dist/digits/neon-digit/index.js +1 -0
- package/dist/digits/roller3d-digit/SgRoller3DDigit.d.ts +37 -0
- package/dist/digits/roller3d-digit/SgRoller3DDigit.d.ts.map +1 -0
- package/dist/digits/roller3d-digit/SgRoller3DDigit.js +47 -0
- package/dist/digits/roller3d-digit/index.d.ts +3 -0
- package/dist/digits/roller3d-digit/index.d.ts.map +1 -0
- package/dist/digits/roller3d-digit/index.js +1 -0
- package/dist/environment/SgEnvironmentProvider.d.ts +1 -0
- package/dist/environment/SgEnvironmentProvider.d.ts.map +1 -1
- package/dist/environment/SgEnvironmentProvider.js +51 -12
- package/dist/gadgets/clock/SgClock.d.ts +3 -1
- package/dist/gadgets/clock/SgClock.d.ts.map +1 -1
- package/dist/gadgets/clock/SgClock.js +111 -180
- package/dist/gadgets/clock/SgTimeProvider.d.ts +1 -0
- package/dist/gadgets/clock/SgTimeProvider.d.ts.map +1 -1
- package/dist/gadgets/clock/SgTimeProvider.js +11 -4
- package/dist/gadgets/gauge/SgLinearGauge.d.ts +59 -0
- package/dist/gadgets/gauge/SgLinearGauge.d.ts.map +1 -0
- package/dist/gadgets/gauge/SgLinearGauge.js +258 -0
- package/dist/gadgets/gauge/SgRadialGauge.d.ts +73 -0
- package/dist/gadgets/gauge/SgRadialGauge.d.ts.map +1 -0
- package/dist/gadgets/gauge/SgRadialGauge.js +311 -0
- package/dist/gadgets/gauge/index.d.ts +5 -0
- package/dist/gadgets/gauge/index.d.ts.map +1 -0
- package/dist/gadgets/gauge/index.js +2 -0
- package/dist/gadgets/string-animator/SgStringAnimator.d.ts +91 -0
- package/dist/gadgets/string-animator/SgStringAnimator.d.ts.map +1 -0
- package/dist/gadgets/string-animator/SgStringAnimator.js +145 -0
- package/dist/gadgets/string-animator/index.d.ts +3 -0
- package/dist/gadgets/string-animator/index.d.ts.map +1 -0
- package/dist/gadgets/string-animator/index.js +1 -0
- package/dist/i18n/en-US.json +9 -1
- package/dist/i18n/es.json +55 -47
- package/dist/i18n/index.d.ts +32 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/pt-BR.json +9 -1
- package/dist/i18n/pt-PT.json +9 -1
- package/dist/index.d.ts +46 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -1
- package/dist/inputs/SgAutocomplete.js +21 -5
- package/dist/inputs/SgCombobox.d.ts.map +1 -1
- package/dist/inputs/SgCombobox.js +8 -3
- package/dist/inputs/SgRadioGroup.d.ts +37 -0
- package/dist/inputs/SgRadioGroup.d.ts.map +1 -0
- package/dist/inputs/SgRadioGroup.js +139 -0
- package/dist/inputs/SgRating.d.ts +55 -0
- package/dist/inputs/SgRating.d.ts.map +1 -0
- package/dist/inputs/SgRating.js +135 -0
- package/dist/inputs/SgSlider.d.ts +20 -0
- package/dist/inputs/SgSlider.d.ts.map +1 -0
- package/dist/inputs/SgSlider.js +40 -0
- package/dist/inputs/SgStepperInput.d.ts +22 -0
- package/dist/inputs/SgStepperInput.d.ts.map +1 -0
- package/dist/inputs/SgStepperInput.js +51 -0
- package/dist/inputs/SgTextEditor.d.ts +1 -0
- package/dist/inputs/SgTextEditor.d.ts.map +1 -1
- package/dist/inputs/SgTextEditor.js +19 -3
- package/dist/layout/SgAccordion.d.ts +39 -0
- package/dist/layout/SgAccordion.d.ts.map +1 -0
- package/dist/layout/SgAccordion.js +116 -0
- package/dist/layout/SgBreadcrumb.d.ts +33 -0
- package/dist/layout/SgBreadcrumb.d.ts.map +1 -0
- package/dist/layout/SgBreadcrumb.js +121 -0
- package/dist/layout/SgCarousel.d.ts +43 -0
- package/dist/layout/SgCarousel.d.ts.map +1 -0
- package/dist/layout/SgCarousel.js +166 -0
- package/dist/layout/SgDockLayout.d.ts +14 -0
- package/dist/layout/SgDockLayout.d.ts.map +1 -1
- package/dist/layout/SgDockLayout.js +145 -13
- package/dist/layout/SgDockScreen.d.ts +15 -0
- package/dist/layout/SgDockScreen.d.ts.map +1 -0
- package/dist/layout/SgDockScreen.js +13 -0
- package/dist/layout/SgDockZone.d.ts.map +1 -1
- package/dist/layout/SgDockZone.js +36 -2
- package/dist/layout/SgExpandablePanel.d.ts +50 -0
- package/dist/layout/SgExpandablePanel.d.ts.map +1 -0
- package/dist/layout/SgExpandablePanel.js +302 -0
- package/dist/layout/SgMainPanel.d.ts.map +1 -1
- package/dist/layout/SgMainPanel.js +36 -14
- package/dist/layout/SgMenu.d.ts +91 -0
- package/dist/layout/SgMenu.d.ts.map +1 -0
- package/dist/layout/SgMenu.js +939 -0
- package/dist/layout/SgPageControl.d.ts +49 -0
- package/dist/layout/SgPageControl.d.ts.map +1 -0
- package/dist/layout/SgPageControl.js +152 -0
- package/dist/layout/SgPanel.d.ts.map +1 -1
- package/dist/layout/SgPanel.js +10 -1
- package/dist/layout/SgScreen.d.ts +2 -0
- package/dist/layout/SgScreen.d.ts.map +1 -1
- package/dist/layout/SgScreen.js +4 -2
- package/dist/layout/SgToolBar.d.ts +9 -3
- package/dist/layout/SgToolBar.d.ts.map +1 -1
- package/dist/layout/SgToolBar.js +461 -55
- package/dist/menus/SgDockMenu.d.ts +62 -0
- package/dist/menus/SgDockMenu.d.ts.map +1 -0
- package/dist/menus/SgDockMenu.js +480 -0
- package/dist/others/SgPlayground.js +72 -72
- package/package.json +72 -63
- package/dist/gadgets/flip-digit/SgFlipDigit.d.ts +0 -23
- package/dist/gadgets/flip-digit/SgFlipDigit.d.ts.map +0 -1
- package/dist/gadgets/flip-digit/SgFlipDigit.js +0 -118
- package/dist/gadgets/flip-digit/index.d.ts.map +0 -1
- /package/dist/{gadgets → digits}/flip-digit/index.d.ts +0 -0
- /package/dist/{gadgets → digits}/flip-digit/index.js +0 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
5
|
+
function cn(...parts) {
|
|
6
|
+
return parts.filter(Boolean).join(" ");
|
|
7
|
+
}
|
|
8
|
+
function clamp(value, min, max) {
|
|
9
|
+
return Math.max(min, Math.min(value, max));
|
|
10
|
+
}
|
|
11
|
+
function toCssSize(value, fallback) {
|
|
12
|
+
if (value === undefined || value === null)
|
|
13
|
+
return `${fallback}px`;
|
|
14
|
+
if (typeof value === "number")
|
|
15
|
+
return `${value}px`;
|
|
16
|
+
const trimmed = value.trim();
|
|
17
|
+
return trimmed.length > 0 ? trimmed : `${fallback}px`;
|
|
18
|
+
}
|
|
19
|
+
function parsePx(value) {
|
|
20
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
21
|
+
return value;
|
|
22
|
+
if (typeof value !== "string")
|
|
23
|
+
return undefined;
|
|
24
|
+
const trimmed = value.trim().toLowerCase();
|
|
25
|
+
if (!trimmed)
|
|
26
|
+
return undefined;
|
|
27
|
+
const match = /^(-?\d+(?:\.\d+)?)(px)?$/.exec(trimmed);
|
|
28
|
+
if (!match)
|
|
29
|
+
return undefined;
|
|
30
|
+
const parsed = Number(match[1]);
|
|
31
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
32
|
+
}
|
|
33
|
+
function axisForDirection(direction) {
|
|
34
|
+
return direction === "left" || direction === "right" ? "x" : "y";
|
|
35
|
+
}
|
|
36
|
+
function closedTransform(direction) {
|
|
37
|
+
if (direction === "right")
|
|
38
|
+
return "-translate-x-full";
|
|
39
|
+
if (direction === "left")
|
|
40
|
+
return "translate-x-full";
|
|
41
|
+
if (direction === "bottom")
|
|
42
|
+
return "-translate-y-full";
|
|
43
|
+
return "translate-y-full";
|
|
44
|
+
}
|
|
45
|
+
function elevationClass(elevation) {
|
|
46
|
+
if (elevation === "sm")
|
|
47
|
+
return "shadow-sm";
|
|
48
|
+
if (elevation === "md")
|
|
49
|
+
return "shadow-md";
|
|
50
|
+
if (elevation === "lg")
|
|
51
|
+
return "shadow-lg";
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
54
|
+
function roundedClass(rounded) {
|
|
55
|
+
if (rounded === "none")
|
|
56
|
+
return "rounded-none";
|
|
57
|
+
if (rounded === "md")
|
|
58
|
+
return "rounded-md";
|
|
59
|
+
if (rounded === "lg")
|
|
60
|
+
return "rounded-lg";
|
|
61
|
+
return "rounded-xl";
|
|
62
|
+
}
|
|
63
|
+
function getFocusableElements(root) {
|
|
64
|
+
return Array.from(root.querySelectorAll(`button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])`)).filter((el) => !el.hasAttribute("disabled") && el.getAttribute("aria-hidden") !== "true");
|
|
65
|
+
}
|
|
66
|
+
export const SgExpandablePanel = React.forwardRef(function SgExpandablePanel(props, ref) {
|
|
67
|
+
const { header, children, footer, handle, open, defaultOpen = false, onOpenChange, expandTo, placement = "start", mode = "inline", size, resizable = false, onSizeChange, closeOnOutsideClick, closeOnEsc = true, trapFocus, showBackdrop = true, animation, elevation = "md", border = true, rounded = "lg", ariaLabel, role, className, contentClassName, headerClassName, bodyClassName, footerClassName, overlayClassName, style } = props;
|
|
68
|
+
const isControlled = open !== undefined;
|
|
69
|
+
const [openUncontrolled, setOpenUncontrolled] = React.useState(defaultOpen);
|
|
70
|
+
const isOpen = isControlled ? !!open : openUncontrolled;
|
|
71
|
+
const setOpen = React.useCallback((next) => {
|
|
72
|
+
if (!isControlled)
|
|
73
|
+
setOpenUncontrolled(next);
|
|
74
|
+
onOpenChange?.(next);
|
|
75
|
+
}, [isControlled, onOpenChange]);
|
|
76
|
+
const axis = axisForDirection(expandTo);
|
|
77
|
+
const fallbackMainSize = axis === "x" ? 320 : 280;
|
|
78
|
+
const [mainSize, setMainSize] = React.useState(size?.default ?? fallbackMainSize);
|
|
79
|
+
React.useEffect(() => {
|
|
80
|
+
if (size?.default !== undefined) {
|
|
81
|
+
setMainSize(size.default);
|
|
82
|
+
}
|
|
83
|
+
}, [size?.default]);
|
|
84
|
+
const minPx = parsePx(size?.min) ?? (axis === "x" ? 180 : 140);
|
|
85
|
+
const maxPx = parsePx(size?.max) ?? Number.POSITIVE_INFINITY;
|
|
86
|
+
const mainSizeCss = toCssSize(mainSize, fallbackMainSize);
|
|
87
|
+
const minSizeCss = size?.min !== undefined ? toCssSize(size.min, minPx) : undefined;
|
|
88
|
+
const maxSizeCss = size?.max !== undefined && Number.isFinite(maxPx)
|
|
89
|
+
? toCssSize(size.max, maxPx)
|
|
90
|
+
: size?.max !== undefined
|
|
91
|
+
? toCssSize(size.max, fallbackMainSize)
|
|
92
|
+
: undefined;
|
|
93
|
+
const resolvedTrapFocus = trapFocus ?? mode === "overlay";
|
|
94
|
+
const resolvedCloseOnOutsideClick = closeOnOutsideClick ?? mode === "overlay";
|
|
95
|
+
const shouldRenderBackdrop = showBackdrop || resolvedCloseOnOutsideClick;
|
|
96
|
+
const animationType = animation?.type ?? "slide";
|
|
97
|
+
const durationMs = animation?.durationMs ?? 180;
|
|
98
|
+
const [mounted, setMounted] = React.useState(false);
|
|
99
|
+
const [present, setPresent] = React.useState(isOpen);
|
|
100
|
+
const [entered, setEntered] = React.useState(isOpen);
|
|
101
|
+
React.useEffect(() => {
|
|
102
|
+
setMounted(true);
|
|
103
|
+
}, []);
|
|
104
|
+
React.useEffect(() => {
|
|
105
|
+
if (mode !== "overlay") {
|
|
106
|
+
setEntered(isOpen);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (isOpen) {
|
|
110
|
+
setPresent(true);
|
|
111
|
+
const id = window.requestAnimationFrame(() => setEntered(true));
|
|
112
|
+
return () => window.cancelAnimationFrame(id);
|
|
113
|
+
}
|
|
114
|
+
setEntered(false);
|
|
115
|
+
const delay = animationType === "none" ? 0 : durationMs;
|
|
116
|
+
const id = window.setTimeout(() => setPresent(false), delay);
|
|
117
|
+
return () => window.clearTimeout(id);
|
|
118
|
+
}, [mode, isOpen, animationType, durationMs]);
|
|
119
|
+
React.useEffect(() => {
|
|
120
|
+
if (mode !== "overlay" || !present || !isOpen)
|
|
121
|
+
return;
|
|
122
|
+
const original = document.body.style.overflow;
|
|
123
|
+
document.body.style.overflow = "hidden";
|
|
124
|
+
return () => {
|
|
125
|
+
document.body.style.overflow = original;
|
|
126
|
+
};
|
|
127
|
+
}, [mode, present, isOpen]);
|
|
128
|
+
const panelRef = React.useRef(null);
|
|
129
|
+
const overlayRef = React.useRef(null);
|
|
130
|
+
const mergedRef = React.useMemo(() => (node) => {
|
|
131
|
+
panelRef.current = node;
|
|
132
|
+
if (typeof ref === "function")
|
|
133
|
+
ref(node);
|
|
134
|
+
else if (ref)
|
|
135
|
+
ref.current = node;
|
|
136
|
+
}, [ref]);
|
|
137
|
+
const lastActiveRef = React.useRef(null);
|
|
138
|
+
React.useEffect(() => {
|
|
139
|
+
if (mode !== "overlay" || !isOpen)
|
|
140
|
+
return;
|
|
141
|
+
lastActiveRef.current = document.activeElement;
|
|
142
|
+
const id = window.setTimeout(() => {
|
|
143
|
+
const root = panelRef.current;
|
|
144
|
+
if (!root)
|
|
145
|
+
return;
|
|
146
|
+
const focusables = getFocusableElements(root);
|
|
147
|
+
(focusables[0] ?? root).focus?.();
|
|
148
|
+
}, 0);
|
|
149
|
+
return () => window.clearTimeout(id);
|
|
150
|
+
}, [mode, isOpen]);
|
|
151
|
+
React.useEffect(() => {
|
|
152
|
+
if (mode !== "overlay")
|
|
153
|
+
return;
|
|
154
|
+
if (isOpen || present)
|
|
155
|
+
return;
|
|
156
|
+
lastActiveRef.current?.focus?.();
|
|
157
|
+
}, [mode, isOpen, present]);
|
|
158
|
+
React.useEffect(() => {
|
|
159
|
+
if (mode !== "overlay" || !isOpen)
|
|
160
|
+
return;
|
|
161
|
+
const onKeyDown = (event) => {
|
|
162
|
+
if (closeOnEsc && event.key === "Escape") {
|
|
163
|
+
event.preventDefault();
|
|
164
|
+
setOpen(false);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (!resolvedTrapFocus || event.key !== "Tab")
|
|
168
|
+
return;
|
|
169
|
+
const root = panelRef.current;
|
|
170
|
+
if (!root)
|
|
171
|
+
return;
|
|
172
|
+
const focusables = getFocusableElements(root);
|
|
173
|
+
if (focusables.length === 0)
|
|
174
|
+
return;
|
|
175
|
+
const first = focusables[0];
|
|
176
|
+
const last = focusables[focusables.length - 1];
|
|
177
|
+
if (!first || !last)
|
|
178
|
+
return;
|
|
179
|
+
const active = document.activeElement;
|
|
180
|
+
if (!event.shiftKey && active === last) {
|
|
181
|
+
event.preventDefault();
|
|
182
|
+
first.focus();
|
|
183
|
+
}
|
|
184
|
+
else if (event.shiftKey && active === first) {
|
|
185
|
+
event.preventDefault();
|
|
186
|
+
last.focus();
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
document.addEventListener("keydown", onKeyDown);
|
|
190
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
191
|
+
}, [mode, isOpen, closeOnEsc, resolvedTrapFocus, setOpen]);
|
|
192
|
+
const resizeState = React.useRef(null);
|
|
193
|
+
const onResizeStart = React.useCallback((event) => {
|
|
194
|
+
if (!resizable)
|
|
195
|
+
return;
|
|
196
|
+
const panel = panelRef.current;
|
|
197
|
+
if (!panel)
|
|
198
|
+
return;
|
|
199
|
+
event.preventDefault();
|
|
200
|
+
event.stopPropagation();
|
|
201
|
+
const rect = panel.getBoundingClientRect();
|
|
202
|
+
resizeState.current = {
|
|
203
|
+
startX: event.clientX,
|
|
204
|
+
startY: event.clientY,
|
|
205
|
+
startSize: axis === "x" ? rect.width : rect.height
|
|
206
|
+
};
|
|
207
|
+
const onMove = (moveEvent) => {
|
|
208
|
+
if (!resizeState.current)
|
|
209
|
+
return;
|
|
210
|
+
const dx = moveEvent.clientX - resizeState.current.startX;
|
|
211
|
+
const dy = moveEvent.clientY - resizeState.current.startY;
|
|
212
|
+
const delta = axis === "x"
|
|
213
|
+
? expandTo === "right"
|
|
214
|
+
? dx
|
|
215
|
+
: -dx
|
|
216
|
+
: expandTo === "bottom"
|
|
217
|
+
? dy
|
|
218
|
+
: -dy;
|
|
219
|
+
const next = clamp(resizeState.current.startSize + delta, minPx, maxPx);
|
|
220
|
+
setMainSize(next);
|
|
221
|
+
onSizeChange?.(next);
|
|
222
|
+
};
|
|
223
|
+
const onUp = () => {
|
|
224
|
+
resizeState.current = null;
|
|
225
|
+
window.removeEventListener("pointermove", onMove);
|
|
226
|
+
window.removeEventListener("pointerup", onUp);
|
|
227
|
+
window.removeEventListener("pointercancel", onUp);
|
|
228
|
+
};
|
|
229
|
+
window.addEventListener("pointermove", onMove);
|
|
230
|
+
window.addEventListener("pointerup", onUp);
|
|
231
|
+
window.addEventListener("pointercancel", onUp);
|
|
232
|
+
}, [axis, expandTo, maxPx, minPx, onSizeChange, resizable]);
|
|
233
|
+
const panelBaseClass = cn("relative min-h-0 min-w-0 overflow-hidden bg-background text-foreground", "flex flex-col", border ? "border border-border" : "", roundedClass(rounded), elevationClass(elevation), animationType === "none"
|
|
234
|
+
? ""
|
|
235
|
+
: "transition-[transform,opacity,width,height] ease-out", contentClassName);
|
|
236
|
+
const panelRole = role ?? (mode === "overlay" ? "dialog" : "region");
|
|
237
|
+
const panelAriaLabel = ariaLabel ?? "Expandable panel";
|
|
238
|
+
const transitionStyle = animationType === "none" ? { transitionDuration: "0ms" } : { transitionDuration: `${durationMs}ms` };
|
|
239
|
+
const resizeHandleClass = expandTo === "right"
|
|
240
|
+
? "absolute inset-y-0 right-0 w-1 cursor-ew-resize"
|
|
241
|
+
: expandTo === "left"
|
|
242
|
+
? "absolute inset-y-0 left-0 w-1 cursor-ew-resize"
|
|
243
|
+
: expandTo === "bottom"
|
|
244
|
+
? "absolute inset-x-0 bottom-0 h-1 cursor-ns-resize"
|
|
245
|
+
: "absolute inset-x-0 top-0 h-1 cursor-ns-resize";
|
|
246
|
+
const renderPanelContent = (extraStyle, stateClass) => (_jsxs("div", { ref: mergedRef, role: panelRole, "aria-modal": mode === "overlay" ? true : undefined, "aria-label": panelAriaLabel, tabIndex: -1, className: cn(panelBaseClass, stateClass, className), style: { ...extraStyle, ...style, ...transitionStyle }, children: [handle ? _jsx("div", { className: "px-3 pt-2", children: handle }) : null, header ? (_jsx("div", { className: cn("shrink-0 border-b border-border px-4 py-3", headerClassName), children: header })) : null, _jsx("div", { className: cn("min-h-0 flex-1 overflow-auto px-4 py-3", bodyClassName), children: children }), footer ? (_jsx("div", { className: cn("shrink-0 border-t border-border px-4 py-3", footerClassName), children: footer })) : null, resizable ? (_jsx("div", { className: cn(resizeHandleClass, "z-20 bg-transparent transition-colors hover:bg-primary/20 active:bg-primary/30"), onPointerDown: onResizeStart, "aria-hidden": "true" })) : null] }));
|
|
247
|
+
if (mode === "inline") {
|
|
248
|
+
const wrapperStyle = axis === "x"
|
|
249
|
+
? {
|
|
250
|
+
width: isOpen ? mainSizeCss : "0px",
|
|
251
|
+
minWidth: isOpen ? minSizeCss : undefined,
|
|
252
|
+
maxWidth: maxSizeCss
|
|
253
|
+
}
|
|
254
|
+
: {
|
|
255
|
+
height: isOpen ? mainSizeCss : "0px",
|
|
256
|
+
minHeight: isOpen ? minSizeCss : undefined,
|
|
257
|
+
maxHeight: maxSizeCss
|
|
258
|
+
};
|
|
259
|
+
const inlineStateClass = animationType === "fade"
|
|
260
|
+
? isOpen
|
|
261
|
+
? "opacity-100"
|
|
262
|
+
: "opacity-0"
|
|
263
|
+
: animationType === "slide"
|
|
264
|
+
? cn(isOpen ? "opacity-100 translate-x-0 translate-y-0" : "opacity-0", !isOpen ? closedTransform(expandTo) : "")
|
|
265
|
+
: "";
|
|
266
|
+
return (_jsx("div", { className: cn("relative min-h-0 min-w-0 overflow-hidden", animationType === "none" ? "" : "transition-[width,height,opacity] ease-out"), style: { ...wrapperStyle, ...transitionStyle }, children: renderPanelContent(axis === "x"
|
|
267
|
+
? { width: "100%", minWidth: 0, height: "100%" }
|
|
268
|
+
: { height: "100%", minHeight: 0, width: "100%" }, inlineStateClass) }));
|
|
269
|
+
}
|
|
270
|
+
if (!mounted || !present)
|
|
271
|
+
return null;
|
|
272
|
+
const overlayContainerClass = axis === "x"
|
|
273
|
+
? cn("fixed inset-0 z-[1000] flex pointer-events-none", expandTo === "right" ? "justify-start" : "justify-end", placement === "start" ? "items-start" : placement === "center" ? "items-center" : "items-end")
|
|
274
|
+
: cn("fixed inset-0 z-[1000] flex flex-col pointer-events-none", expandTo === "bottom" ? "justify-start" : "justify-end", placement === "start" ? "items-start" : placement === "center" ? "items-center" : "items-end");
|
|
275
|
+
const overlayPanelStyle = axis === "x"
|
|
276
|
+
? {
|
|
277
|
+
width: mainSizeCss,
|
|
278
|
+
minWidth: minSizeCss,
|
|
279
|
+
maxWidth: maxSizeCss,
|
|
280
|
+
height: placement === "center" ? "calc(100% - 2rem)" : "100%"
|
|
281
|
+
}
|
|
282
|
+
: {
|
|
283
|
+
height: mainSizeCss,
|
|
284
|
+
minHeight: minSizeCss,
|
|
285
|
+
maxHeight: maxSizeCss,
|
|
286
|
+
width: placement === "center" ? "calc(100% - 2rem)" : "100%"
|
|
287
|
+
};
|
|
288
|
+
const overlayStateClass = animationType === "fade"
|
|
289
|
+
? entered
|
|
290
|
+
? "opacity-100"
|
|
291
|
+
: "opacity-0"
|
|
292
|
+
: animationType === "slide"
|
|
293
|
+
? cn(entered ? "opacity-100 translate-x-0 translate-y-0" : "opacity-0", !entered ? closedTransform(expandTo) : "")
|
|
294
|
+
: "";
|
|
295
|
+
return createPortal(_jsxs("div", { className: "fixed inset-0 z-[1000] pointer-events-none", children: [shouldRenderBackdrop ? (_jsx("div", { ref: overlayRef, className: cn("absolute inset-0 pointer-events-auto", showBackdrop ? "bg-black/40 backdrop-blur-[1px]" : "bg-transparent", animationType === "none" ? "" : "transition-opacity ease-out", entered ? "opacity-100" : "opacity-0", overlayClassName), style: transitionStyle, onMouseDown: (event) => {
|
|
296
|
+
if (!resolvedCloseOnOutsideClick)
|
|
297
|
+
return;
|
|
298
|
+
if (event.target === overlayRef.current)
|
|
299
|
+
setOpen(false);
|
|
300
|
+
} })) : null, _jsx("div", { className: overlayContainerClass, children: _jsx("div", { className: "pointer-events-auto", children: renderPanelContent(overlayPanelStyle, overlayStateClass) }) })] }), document.body);
|
|
301
|
+
});
|
|
302
|
+
SgExpandablePanel.displayName = "SgExpandablePanel";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SgMainPanel.d.ts","sourceRoot":"","sources":["../../src/layout/SgMainPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAiD/B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACtF,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"SgMainPanel.d.ts","sourceRoot":"","sources":["../../src/layout/SgMainPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAiD/B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACtF,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,2CA4H5D;yBA5He,WAAW"}
|
|
@@ -46,25 +46,47 @@ export function SgMainPanel(props) {
|
|
|
46
46
|
const left = allItems.filter((item) => item.align === "left");
|
|
47
47
|
const right = allItems.filter((item) => item.align === "right");
|
|
48
48
|
const client = allItems.filter((item) => item.align === "client");
|
|
49
|
-
const
|
|
49
|
+
const gapCss = toCssSpace(gap);
|
|
50
|
+
const dockGapStyle = gapCss !== undefined ? { gap: gapCss } : undefined;
|
|
50
51
|
return (_jsxs("div", { className: cn("flex h-full w-full min-h-0 min-w-0 flex-col", className), style: {
|
|
51
52
|
...style,
|
|
52
|
-
padding: toCssSpace(padding)
|
|
53
|
-
|
|
53
|
+
padding: toCssSpace(padding),
|
|
54
|
+
...(dockGapStyle ?? null)
|
|
55
|
+
}, ...rest, children: [top.map((item, index) => {
|
|
56
|
+
const heightCss = toCssPercent(item.height);
|
|
57
|
+
return cloneWithLayout(item.node, item.key ?? `top-${index}`, {
|
|
54
58
|
width: "100%",
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
...(heightCss !== undefined
|
|
60
|
+
? { height: heightCss, flex: `0 0 ${heightCss}` }
|
|
61
|
+
: { flex: "0 0 auto" })
|
|
62
|
+
}, "w-full");
|
|
63
|
+
}), _jsxs("div", { className: "flex flex-1 min-h-0 min-w-0", style: dockGapStyle, children: [left.map((item, index) => {
|
|
64
|
+
const widthCss = toCssPercent(item.width);
|
|
65
|
+
return cloneWithLayout(item.node, item.key ?? `left-${index}`, {
|
|
66
|
+
height: "100%",
|
|
67
|
+
...(widthCss !== undefined
|
|
68
|
+
? { width: widthCss, flex: `0 0 ${widthCss}` }
|
|
69
|
+
: { flex: "0 0 auto" })
|
|
70
|
+
}, "h-full min-h-0");
|
|
71
|
+
}), _jsx("div", { className: "flex flex-1 min-h-0 min-w-0", style: dockGapStyle, children: client.map((item, index) => (_jsx("div", { className: "flex-1 min-h-0 min-w-0", children: cloneWithLayout(item.node, item.key ?? `client-inner-${index}`, {
|
|
60
72
|
width: "100%",
|
|
61
73
|
height: "100%"
|
|
62
|
-
}, "h-full w-full") }, item.key ?? `client-${index}`))) }), right.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
}, "h-full w-full") }, item.key ?? `client-${index}`))) }), right.map((item, index) => {
|
|
75
|
+
const widthCss = toCssPercent(item.width);
|
|
76
|
+
return cloneWithLayout(item.node, item.key ?? `right-${index}`, {
|
|
77
|
+
height: "100%",
|
|
78
|
+
...(widthCss !== undefined
|
|
79
|
+
? { width: widthCss, flex: `0 0 ${widthCss}` }
|
|
80
|
+
: { flex: "0 0 auto" })
|
|
81
|
+
}, "h-full min-h-0");
|
|
82
|
+
})] }), bottom.map((item, index) => {
|
|
83
|
+
const heightCss = toCssPercent(item.height);
|
|
84
|
+
return cloneWithLayout(item.node, item.key ?? `bottom-${index}`, {
|
|
66
85
|
width: "100%",
|
|
67
|
-
|
|
68
|
-
|
|
86
|
+
...(heightCss !== undefined
|
|
87
|
+
? { height: heightCss, flex: `0 0 ${heightCss}` }
|
|
88
|
+
: { flex: "0 0 auto" })
|
|
89
|
+
}, "w-full");
|
|
90
|
+
})] }));
|
|
69
91
|
}
|
|
70
92
|
SgMainPanel.displayName = "SgMainPanel";
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type SgExpandablePanelSize } from "./SgExpandablePanel";
|
|
3
|
+
import { type SgDockZoneId } from "./SgDockLayout";
|
|
4
|
+
export type SgMenuNode = {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
url?: string;
|
|
8
|
+
children?: SgMenuNode[];
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
icon?: React.ReactNode;
|
|
11
|
+
badge?: string | number;
|
|
12
|
+
onClick?: () => void;
|
|
13
|
+
};
|
|
14
|
+
export type SgMenuSelection = {
|
|
15
|
+
activeId?: string;
|
|
16
|
+
activeUrl?: string;
|
|
17
|
+
};
|
|
18
|
+
export type SgMenuBrand = {
|
|
19
|
+
title?: string;
|
|
20
|
+
imageSrc?: string;
|
|
21
|
+
image?: React.ReactNode;
|
|
22
|
+
onClick?: () => void;
|
|
23
|
+
};
|
|
24
|
+
export type SgMenuUser = {
|
|
25
|
+
name: string;
|
|
26
|
+
subtitle?: string;
|
|
27
|
+
avatarSrc?: string;
|
|
28
|
+
avatar?: React.ReactNode;
|
|
29
|
+
onClick?: () => void;
|
|
30
|
+
};
|
|
31
|
+
export type SgMenuStyle = "panel" | "tiered" | "mega-horizontal" | "mega-vertical" | "PanelMenu" | "Tiered" | "MegaMenuHorizontal" | "MegaMenuVertical";
|
|
32
|
+
export type SgMenuOrientationDirection = "horizontal-left" | "horizontal-right" | "vertical-up" | "vertical-top" | "vertical-down";
|
|
33
|
+
export type SgMenuProps = {
|
|
34
|
+
id?: string;
|
|
35
|
+
menu: SgMenuNode[];
|
|
36
|
+
selection?: SgMenuSelection;
|
|
37
|
+
brand?: SgMenuBrand;
|
|
38
|
+
user?: SgMenuUser;
|
|
39
|
+
userMenu?: SgMenuNode[];
|
|
40
|
+
variant?: "sidebar" | "drawer" | "inline" | "hybrid";
|
|
41
|
+
menuStyle?: SgMenuStyle;
|
|
42
|
+
position?: "left" | "right";
|
|
43
|
+
density?: "compact" | "comfortable";
|
|
44
|
+
indent?: number;
|
|
45
|
+
collapsedWidth?: number | string;
|
|
46
|
+
expandedWidth?: number | string;
|
|
47
|
+
overlaySize?: SgExpandablePanelSize;
|
|
48
|
+
overlayBackdrop?: boolean;
|
|
49
|
+
dockable?: boolean;
|
|
50
|
+
dockZone?: SgDockZoneId;
|
|
51
|
+
draggable?: boolean;
|
|
52
|
+
orientationDirection?: SgMenuOrientationDirection;
|
|
53
|
+
mode?: "accordion" | "multiple";
|
|
54
|
+
expandedIds?: string[];
|
|
55
|
+
defaultExpandedIds?: string[];
|
|
56
|
+
onExpandedIdsChange?: (ids: string[]) => void;
|
|
57
|
+
collapsed?: boolean;
|
|
58
|
+
defaultCollapsed?: boolean;
|
|
59
|
+
onCollapsedChange?: (value: boolean) => void;
|
|
60
|
+
showCollapseButton?: boolean;
|
|
61
|
+
open?: boolean;
|
|
62
|
+
defaultOpen?: boolean;
|
|
63
|
+
onOpenChange?: (value: boolean) => void;
|
|
64
|
+
closeOnNavigate?: boolean;
|
|
65
|
+
pinned?: boolean;
|
|
66
|
+
defaultPinned?: boolean;
|
|
67
|
+
onPinnedChange?: (value: boolean) => void;
|
|
68
|
+
showPinButton?: boolean;
|
|
69
|
+
onNavigate?: (node: SgMenuNode) => void;
|
|
70
|
+
onAction?: (node: SgMenuNode) => void;
|
|
71
|
+
onItemClick?: (node: SgMenuNode) => void;
|
|
72
|
+
ariaLabel?: string;
|
|
73
|
+
keyboardNavigation?: boolean;
|
|
74
|
+
openSubmenuOnHover?: boolean;
|
|
75
|
+
search?: {
|
|
76
|
+
enabled: boolean;
|
|
77
|
+
placeholder?: string;
|
|
78
|
+
};
|
|
79
|
+
elevation?: "none" | "sm" | "md";
|
|
80
|
+
border?: boolean;
|
|
81
|
+
className?: string;
|
|
82
|
+
style?: React.CSSProperties;
|
|
83
|
+
userSectionClassName?: string;
|
|
84
|
+
userSectionStyle?: React.CSSProperties;
|
|
85
|
+
footer?: React.ReactNode;
|
|
86
|
+
};
|
|
87
|
+
export declare function SgMenu(props: Readonly<SgMenuProps>): import("react/jsx-runtime").JSX.Element;
|
|
88
|
+
export declare namespace SgMenu {
|
|
89
|
+
var displayName: string;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=SgMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SgMenu.d.ts","sourceRoot":"","sources":["../../src/layout/SgMenu.tsx"],"names":[],"mappings":"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"}
|