@seedgrid/fe-components 0.2.9 → 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/commons/SgToaster.d.ts +9 -0
- package/dist/commons/SgToaster.d.ts.map +1 -1
- package/dist/commons/SgToaster.js +86 -17
- 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/qr-code/SgQRCode.d.ts +25 -0
- package/dist/gadgets/qr-code/SgQRCode.d.ts.map +1 -0
- package/dist/gadgets/qr-code/SgQRCode.js +75 -0
- package/dist/gadgets/qr-code/index.d.ts +3 -0
- package/dist/gadgets/qr-code/index.d.ts.map +1 -0
- package/dist/gadgets/qr-code/index.js +1 -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 +53 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -1
- package/dist/inputs/SgAutocomplete.js +21 -5
- package/dist/inputs/SgCombobox.d.ts +26 -0
- package/dist/inputs/SgCombobox.d.ts.map +1 -0
- package/dist/inputs/SgCombobox.js +354 -0
- package/dist/inputs/SgInputOTP.d.ts.map +1 -1
- package/dist/inputs/SgInputOTP.js +9 -2
- 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/inputs/SgToggleSwitch.d.ts +36 -0
- package/dist/inputs/SgToggleSwitch.d.ts.map +1 -0
- package/dist/inputs/SgToggleSwitch.js +174 -0
- 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 +73 -73
- package/package.json +72 -57
- 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
package/dist/layout/SgToolBar.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
5
|
import { useSgDockLayout } from "./SgDockLayout";
|
|
6
|
+
import { useHasSgEnvironmentProvider, useSgPersistence } from "../environment/SgEnvironmentProvider";
|
|
6
7
|
function cn(...parts) {
|
|
7
8
|
return parts.filter(Boolean).join(" ");
|
|
8
9
|
}
|
|
@@ -51,6 +52,50 @@ const BTN_COLORS = {
|
|
|
51
52
|
function clamp(n, min, max) {
|
|
52
53
|
return Math.max(min, Math.min(max, n));
|
|
53
54
|
}
|
|
55
|
+
function parseStoredDragPosition(raw) {
|
|
56
|
+
const value = typeof raw === "string" ? (() => {
|
|
57
|
+
try {
|
|
58
|
+
return JSON.parse(raw);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
})() : raw;
|
|
64
|
+
if (!value ||
|
|
65
|
+
typeof value !== "object" ||
|
|
66
|
+
typeof value.x !== "number" ||
|
|
67
|
+
typeof value.y !== "number" ||
|
|
68
|
+
!Number.isFinite(value.x) ||
|
|
69
|
+
!Number.isFinite(value.y)) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
x: value.x,
|
|
74
|
+
y: value.y
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function resolveOrientationDirection(orientationDirection) {
|
|
78
|
+
switch (orientationDirection) {
|
|
79
|
+
case "horizontal-right":
|
|
80
|
+
return { orientation: "horizontal", direction: "left" };
|
|
81
|
+
case "horizontal-left":
|
|
82
|
+
return { orientation: "horizontal", direction: "right" };
|
|
83
|
+
case "vertical-up":
|
|
84
|
+
return { orientation: "vertical", direction: "up" };
|
|
85
|
+
case "vertical-down":
|
|
86
|
+
default:
|
|
87
|
+
return { orientation: "vertical", direction: "down" };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function resolveDockOrientationDirection(orientationDirection, inDock, zone) {
|
|
91
|
+
if (!inDock || zone === "free")
|
|
92
|
+
return orientationDirection;
|
|
93
|
+
if (zone === "top" || zone === "bottom") {
|
|
94
|
+
return orientationDirection.startsWith("horizontal") ? orientationDirection : "horizontal-left";
|
|
95
|
+
}
|
|
96
|
+
return orientationDirection.startsWith("vertical") ? orientationDirection : "vertical-down";
|
|
97
|
+
}
|
|
98
|
+
const SgToolbarOrientationContext = React.createContext("vertical");
|
|
54
99
|
function useControlledState(args) {
|
|
55
100
|
const { value, defaultValue, onChange } = args;
|
|
56
101
|
const [internal, setInternal] = React.useState(defaultValue);
|
|
@@ -64,11 +109,21 @@ function useControlledState(args) {
|
|
|
64
109
|
return [current, set];
|
|
65
110
|
}
|
|
66
111
|
export function SgToolBar(props) {
|
|
67
|
-
const
|
|
112
|
+
const hasEnvironmentProvider = useHasSgEnvironmentProvider();
|
|
113
|
+
const { load: loadPersistedState, save: savePersistedState, clear: clearPersistedState } = useSgPersistence();
|
|
114
|
+
const { id, title, orientationDirection, buttonsPerDirection, bgColorTitle, bgColor, size, className, style, dockZone, draggable = false, freeDrag = false, defaultPosition, collapsible = true, collapsed, defaultCollapsed = false, onCollapsedChange, children } = props;
|
|
68
115
|
const dock = useSgDockLayout();
|
|
69
116
|
const inDock = !!dock;
|
|
70
117
|
const assignedZone = inDock ? dock.getToolbarZone(id) : null;
|
|
71
118
|
const effectiveZone = assignedZone ?? dockZone ?? "free";
|
|
119
|
+
const toolbarOrder = inDock ? dock.getToolbarOrder(id) : undefined;
|
|
120
|
+
const toolbarRenderOrder = toolbarOrder !== undefined ? toolbarOrder * 2 : undefined;
|
|
121
|
+
const [dragHoverZone, setDragHoverZone] = React.useState(null);
|
|
122
|
+
const dragHoverZoneRef = React.useRef(null);
|
|
123
|
+
const dragPlacementRef = React.useRef(null);
|
|
124
|
+
const zoneForOrientation = inDock && !freeDrag && dragHoverZone ? dragHoverZone : effectiveZone;
|
|
125
|
+
const resolvedOrientationDirection = resolveDockOrientationDirection(orientationDirection ?? "vertical-down", inDock, zoneForOrientation);
|
|
126
|
+
const { orientation, direction } = resolveOrientationDirection(resolvedOrientationDirection);
|
|
72
127
|
const portalTarget = inDock ? dock.getZoneElement(effectiveZone) : null;
|
|
73
128
|
const [isCollapsed, setIsCollapsed] = useControlledState({
|
|
74
129
|
value: collapsed ?? (inDock ? dock.getToolbarCollapsed(id) : undefined),
|
|
@@ -79,10 +134,106 @@ export function SgToolBar(props) {
|
|
|
79
134
|
dock.setToolbarCollapsed(id, next);
|
|
80
135
|
}
|
|
81
136
|
});
|
|
82
|
-
const [dragPos, setDragPos] = React.useState(
|
|
137
|
+
const [dragPos, setDragPos] = React.useState(null);
|
|
138
|
+
const dragPosRef = React.useRef(null);
|
|
139
|
+
const [dragActive, setDragActive] = React.useState(false);
|
|
83
140
|
const dragStart = React.useRef(null);
|
|
84
141
|
const dragMoved = React.useRef(false);
|
|
85
142
|
const containerRef = React.useRef(null);
|
|
143
|
+
const storageKey = React.useMemo(() => `sg-toolbar-pos:${id}`, [id]);
|
|
144
|
+
const setDragHoverZoneSafe = React.useCallback((next) => {
|
|
145
|
+
if (dragHoverZoneRef.current === next)
|
|
146
|
+
return;
|
|
147
|
+
dragHoverZoneRef.current = next;
|
|
148
|
+
setDragHoverZone(next);
|
|
149
|
+
}, []);
|
|
150
|
+
const loadStoredPosition = React.useCallback(async () => {
|
|
151
|
+
if (!storageKey)
|
|
152
|
+
return null;
|
|
153
|
+
if (hasEnvironmentProvider) {
|
|
154
|
+
try {
|
|
155
|
+
const loaded = await loadPersistedState(storageKey);
|
|
156
|
+
if (loaded === null || loaded === undefined)
|
|
157
|
+
return null;
|
|
158
|
+
const parsed = parseStoredDragPosition(loaded);
|
|
159
|
+
if (!parsed) {
|
|
160
|
+
await clearPersistedState(storageKey);
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
return parsed;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const raw = localStorage.getItem(storageKey);
|
|
171
|
+
if (!raw)
|
|
172
|
+
return null;
|
|
173
|
+
const parsed = parseStoredDragPosition(raw);
|
|
174
|
+
if (!parsed) {
|
|
175
|
+
localStorage.removeItem(storageKey);
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
return parsed;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}, [clearPersistedState, hasEnvironmentProvider, loadPersistedState, storageKey]);
|
|
184
|
+
const saveStoredPosition = React.useCallback(async (nextPos) => {
|
|
185
|
+
if (!storageKey)
|
|
186
|
+
return;
|
|
187
|
+
if (hasEnvironmentProvider) {
|
|
188
|
+
try {
|
|
189
|
+
await savePersistedState(storageKey, nextPos);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// ignore
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
localStorage.setItem(storageKey, JSON.stringify(nextPos));
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// ignore
|
|
201
|
+
}
|
|
202
|
+
}, [hasEnvironmentProvider, savePersistedState, storageKey]);
|
|
203
|
+
const resolveFreeDragMode = React.useCallback(() => {
|
|
204
|
+
const container = containerRef.current;
|
|
205
|
+
if (!container)
|
|
206
|
+
return "fixed";
|
|
207
|
+
const offsetParent = container.offsetParent;
|
|
208
|
+
if (offsetParent instanceof HTMLElement &&
|
|
209
|
+
offsetParent !== document.body &&
|
|
210
|
+
offsetParent !== document.documentElement) {
|
|
211
|
+
return "absolute";
|
|
212
|
+
}
|
|
213
|
+
return "fixed";
|
|
214
|
+
}, []);
|
|
215
|
+
const getDragBounds = React.useCallback((mode) => {
|
|
216
|
+
if (!containerRef.current)
|
|
217
|
+
return null;
|
|
218
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
219
|
+
if (mode === "absolute") {
|
|
220
|
+
const offsetParent = containerRef.current.offsetParent;
|
|
221
|
+
if (offsetParent instanceof HTMLElement) {
|
|
222
|
+
return {
|
|
223
|
+
minX: 0,
|
|
224
|
+
minY: 0,
|
|
225
|
+
maxX: Math.max(0, offsetParent.clientWidth - rect.width),
|
|
226
|
+
maxY: Math.max(0, offsetParent.clientHeight - rect.height)
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
minX: 0,
|
|
232
|
+
minY: 0,
|
|
233
|
+
maxX: Math.max(0, window.innerWidth - rect.width),
|
|
234
|
+
maxY: Math.max(0, window.innerHeight - rect.height)
|
|
235
|
+
};
|
|
236
|
+
}, []);
|
|
86
237
|
React.useEffect(() => {
|
|
87
238
|
if (!inDock)
|
|
88
239
|
return;
|
|
@@ -92,6 +243,57 @@ export function SgToolBar(props) {
|
|
|
92
243
|
orientation
|
|
93
244
|
});
|
|
94
245
|
}, [dock, id, effectiveZone, defaultCollapsed, inDock, orientation]);
|
|
246
|
+
React.useEffect(() => {
|
|
247
|
+
dragPosRef.current = dragPos;
|
|
248
|
+
}, [dragPos]);
|
|
249
|
+
React.useEffect(() => {
|
|
250
|
+
if (!freeDrag)
|
|
251
|
+
return;
|
|
252
|
+
let alive = true;
|
|
253
|
+
(async () => {
|
|
254
|
+
const parsed = await loadStoredPosition();
|
|
255
|
+
if (!alive || !parsed)
|
|
256
|
+
return;
|
|
257
|
+
const mode = resolveFreeDragMode();
|
|
258
|
+
const bounds = getDragBounds(mode);
|
|
259
|
+
if (!bounds)
|
|
260
|
+
return;
|
|
261
|
+
const next = {
|
|
262
|
+
x: clamp(parsed.x, bounds.minX, bounds.maxX),
|
|
263
|
+
y: clamp(parsed.y, bounds.minY, bounds.maxY),
|
|
264
|
+
mode
|
|
265
|
+
};
|
|
266
|
+
dragPosRef.current = next;
|
|
267
|
+
setDragPos(next);
|
|
268
|
+
})();
|
|
269
|
+
return () => {
|
|
270
|
+
alive = false;
|
|
271
|
+
};
|
|
272
|
+
}, [freeDrag, getDragBounds, loadStoredPosition, resolveFreeDragMode]);
|
|
273
|
+
React.useEffect(() => {
|
|
274
|
+
const defaultX = defaultPosition?.x;
|
|
275
|
+
const defaultY = defaultPosition?.y;
|
|
276
|
+
if (defaultX === undefined || defaultY === undefined || !freeDrag)
|
|
277
|
+
return;
|
|
278
|
+
const nextMode = resolveFreeDragMode();
|
|
279
|
+
setDragPos((prev) => {
|
|
280
|
+
if (prev)
|
|
281
|
+
return prev;
|
|
282
|
+
return { x: defaultX, y: defaultY, mode: nextMode };
|
|
283
|
+
});
|
|
284
|
+
}, [defaultPosition?.x, defaultPosition?.y, freeDrag, resolveFreeDragMode]);
|
|
285
|
+
React.useEffect(() => {
|
|
286
|
+
if (!dragActive)
|
|
287
|
+
return;
|
|
288
|
+
const previousBodyCursor = document.body.style.cursor;
|
|
289
|
+
const previousHtmlCursor = document.documentElement.style.cursor;
|
|
290
|
+
document.body.style.cursor = "grabbing";
|
|
291
|
+
document.documentElement.style.cursor = "grabbing";
|
|
292
|
+
return () => {
|
|
293
|
+
document.body.style.cursor = previousBodyCursor;
|
|
294
|
+
document.documentElement.style.cursor = previousHtmlCursor;
|
|
295
|
+
};
|
|
296
|
+
}, [dragActive]);
|
|
95
297
|
const handlePointerDown = React.useCallback((event) => {
|
|
96
298
|
if (event.button !== 0)
|
|
97
299
|
return;
|
|
@@ -103,12 +305,66 @@ export function SgToolBar(props) {
|
|
|
103
305
|
return;
|
|
104
306
|
event.preventDefault();
|
|
105
307
|
const rect = containerRef.current.getBoundingClientRect();
|
|
308
|
+
const dockInstance = dock;
|
|
309
|
+
const resolveDockPlacement = (clientX, clientY, toolbarLeft, toolbarTop, toolbarWidth, toolbarHeight) => {
|
|
310
|
+
if (!dockInstance)
|
|
311
|
+
return { zone: null, placement: null };
|
|
312
|
+
const zone = dockInstance.getZoneAtPoint(clientX, clientY);
|
|
313
|
+
if (!zone)
|
|
314
|
+
return { zone: null, placement: null };
|
|
315
|
+
const zoneEl = dockInstance.getZoneElement(zone);
|
|
316
|
+
const zoneRect = zoneEl?.getBoundingClientRect();
|
|
317
|
+
const isHorizontalZone = zone === "top" || zone === "bottom";
|
|
318
|
+
const isVerticalZone = zone === "left" || zone === "right";
|
|
319
|
+
const rawX = isHorizontalZone
|
|
320
|
+
? toolbarLeft
|
|
321
|
+
: isVerticalZone
|
|
322
|
+
? toolbarLeft + toolbarWidth / 2
|
|
323
|
+
: clientX;
|
|
324
|
+
const rawY = isVerticalZone
|
|
325
|
+
? toolbarTop
|
|
326
|
+
: isHorizontalZone
|
|
327
|
+
? toolbarTop + toolbarHeight / 2
|
|
328
|
+
: clientY;
|
|
329
|
+
const sampleX = zoneRect ? clamp(rawX, zoneRect.left + 1, zoneRect.right - 1) : rawX;
|
|
330
|
+
const sampleY = zoneRect ? clamp(rawY, zoneRect.top + 1, zoneRect.bottom - 1) : rawY;
|
|
331
|
+
return {
|
|
332
|
+
zone,
|
|
333
|
+
placement: dockInstance.getDropPlacementAtPoint(sampleX, sampleY, id)
|
|
334
|
+
};
|
|
335
|
+
};
|
|
336
|
+
if (inDock && !freeDrag && dockInstance) {
|
|
337
|
+
dockInstance.setDraggingToolbarId(id);
|
|
338
|
+
dockInstance.setDropPreviewActive(true);
|
|
339
|
+
const initial = resolveDockPlacement(event.clientX, event.clientY, rect.left, rect.top, rect.width, rect.height);
|
|
340
|
+
dragPlacementRef.current = initial.placement;
|
|
341
|
+
dockInstance.setDropIndicator(initial.placement);
|
|
342
|
+
const initialZone = initial.zone ?? effectiveZone;
|
|
343
|
+
setDragHoverZoneSafe(initialZone);
|
|
344
|
+
}
|
|
345
|
+
const dragMode = freeDrag
|
|
346
|
+
? (inDock ? "fixed" : resolveFreeDragMode())
|
|
347
|
+
: "fixed";
|
|
348
|
+
let initialLeft = rect.left;
|
|
349
|
+
let initialTop = rect.top;
|
|
350
|
+
if (dragMode === "absolute") {
|
|
351
|
+
const offsetParent = containerRef.current.offsetParent;
|
|
352
|
+
if (offsetParent instanceof HTMLElement) {
|
|
353
|
+
const parentRect = offsetParent.getBoundingClientRect();
|
|
354
|
+
initialLeft = rect.left - parentRect.left;
|
|
355
|
+
initialTop = rect.top - parentRect.top;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
106
358
|
dragStart.current = {
|
|
107
359
|
x: event.clientX,
|
|
108
360
|
y: event.clientY,
|
|
109
|
-
left:
|
|
110
|
-
top:
|
|
361
|
+
left: initialLeft,
|
|
362
|
+
top: initialTop,
|
|
363
|
+
mode: dragMode,
|
|
364
|
+
width: rect.width,
|
|
365
|
+
height: rect.height
|
|
111
366
|
};
|
|
367
|
+
setDragActive(true);
|
|
112
368
|
dragMoved.current = false;
|
|
113
369
|
const handleMove = (moveEvent) => {
|
|
114
370
|
if (!dragStart.current)
|
|
@@ -117,83 +373,233 @@ export function SgToolBar(props) {
|
|
|
117
373
|
const dy = moveEvent.clientY - dragStart.current.y;
|
|
118
374
|
if (Math.abs(dx) > 3 || Math.abs(dy) > 3)
|
|
119
375
|
dragMoved.current = true;
|
|
120
|
-
const
|
|
376
|
+
const bounds = getDragBounds(dragStart.current.mode);
|
|
377
|
+
const next = {
|
|
378
|
+
x: bounds ? clamp(dragStart.current.left + dx, bounds.minX, bounds.maxX) : dragStart.current.left + dx,
|
|
379
|
+
y: bounds ? clamp(dragStart.current.top + dy, bounds.minY, bounds.maxY) : dragStart.current.top + dy,
|
|
380
|
+
mode: dragStart.current.mode
|
|
381
|
+
};
|
|
382
|
+
dragPosRef.current = next;
|
|
121
383
|
setDragPos(next);
|
|
384
|
+
if (inDock && !freeDrag && dockInstance) {
|
|
385
|
+
const placementSourceLeft = dragStart.current.mode === "fixed" ? next.x : moveEvent.clientX;
|
|
386
|
+
const placementSourceTop = dragStart.current.mode === "fixed" ? next.y : moveEvent.clientY;
|
|
387
|
+
const resolved = resolveDockPlacement(moveEvent.clientX, moveEvent.clientY, placementSourceLeft, placementSourceTop, dragStart.current.width, dragStart.current.height);
|
|
388
|
+
dragPlacementRef.current = resolved.placement;
|
|
389
|
+
dockInstance.setDropIndicator(resolved.placement);
|
|
390
|
+
setDragHoverZoneSafe(resolved.zone);
|
|
391
|
+
}
|
|
122
392
|
};
|
|
123
393
|
const handleUp = (upEvent) => {
|
|
124
394
|
window.removeEventListener("pointermove", handleMove);
|
|
125
395
|
window.removeEventListener("pointerup", handleUp);
|
|
126
396
|
window.removeEventListener("pointercancel", handleUp);
|
|
397
|
+
const activeDrag = dragStart.current;
|
|
398
|
+
const currentDragPos = dragPosRef.current;
|
|
399
|
+
const placementSourceLeft = inDock && !freeDrag && activeDrag && currentDragPos?.mode === "fixed"
|
|
400
|
+
? currentDragPos.x
|
|
401
|
+
: upEvent.clientX;
|
|
402
|
+
const placementSourceTop = inDock && !freeDrag && activeDrag && currentDragPos?.mode === "fixed"
|
|
403
|
+
? currentDragPos.y
|
|
404
|
+
: upEvent.clientY;
|
|
405
|
+
const resolvedFinal = inDock && !freeDrag && dockInstance
|
|
406
|
+
? resolveDockPlacement(upEvent.clientX, upEvent.clientY, placementSourceLeft, placementSourceTop, activeDrag?.width ?? rect.width, activeDrag?.height ?? rect.height)
|
|
407
|
+
: { zone: null, placement: null };
|
|
408
|
+
const finalPlacement = inDock && !freeDrag && dockInstance
|
|
409
|
+
? resolvedFinal.placement ?? dragPlacementRef.current
|
|
410
|
+
: null;
|
|
411
|
+
const finalZone = finalPlacement?.zone ??
|
|
412
|
+
(inDock && !freeDrag && dockInstance ? resolvedFinal.zone : null);
|
|
413
|
+
dragPlacementRef.current = null;
|
|
414
|
+
setDragActive(false);
|
|
415
|
+
setDragHoverZoneSafe(null);
|
|
416
|
+
if (inDock && !freeDrag && dockInstance) {
|
|
417
|
+
dockInstance.setDropIndicator(null);
|
|
418
|
+
dockInstance.setDraggingToolbarId(null);
|
|
419
|
+
dockInstance.setDropPreviewActive(false);
|
|
420
|
+
}
|
|
127
421
|
if (!dragStart.current)
|
|
128
422
|
return;
|
|
423
|
+
const start = dragStart.current;
|
|
129
424
|
dragStart.current = null;
|
|
130
425
|
if (!dragMoved.current)
|
|
131
426
|
return;
|
|
132
|
-
if (
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
427
|
+
if (freeDrag) {
|
|
428
|
+
const current = dragPosRef.current ?? {
|
|
429
|
+
x: start.left,
|
|
430
|
+
y: start.top,
|
|
431
|
+
mode: start.mode
|
|
432
|
+
};
|
|
433
|
+
const bounds = getDragBounds(current.mode);
|
|
434
|
+
const clamped = bounds
|
|
435
|
+
? {
|
|
436
|
+
x: clamp(current.x, bounds.minX, bounds.maxX),
|
|
437
|
+
y: clamp(current.y, bounds.minY, bounds.maxY),
|
|
438
|
+
mode: current.mode
|
|
439
|
+
}
|
|
440
|
+
: current;
|
|
441
|
+
dragPosRef.current = clamped;
|
|
442
|
+
setDragPos(clamped);
|
|
443
|
+
void saveStoredPosition({ x: clamped.x, y: clamped.y });
|
|
137
444
|
}
|
|
138
|
-
else if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const maxX = Math.max(0, window.innerWidth - wh.width);
|
|
142
|
-
const maxY = Math.max(0, window.innerHeight - wh.height);
|
|
143
|
-
setDragPos({
|
|
144
|
-
x: clamp(dragPos?.x ?? wh.left, 0, maxX),
|
|
145
|
-
y: clamp(dragPos?.y ?? wh.top, 0, maxY)
|
|
146
|
-
});
|
|
445
|
+
else if (inDock && dockInstance) {
|
|
446
|
+
if (finalPlacement) {
|
|
447
|
+
dockInstance.placeToolbar(id, finalPlacement.zone, finalPlacement.index);
|
|
147
448
|
}
|
|
449
|
+
else if (finalZone) {
|
|
450
|
+
dockInstance.moveToolbar(id, finalZone);
|
|
451
|
+
}
|
|
452
|
+
dragPosRef.current = null;
|
|
453
|
+
setDragPos(null);
|
|
148
454
|
}
|
|
149
455
|
};
|
|
150
456
|
window.addEventListener("pointermove", handleMove);
|
|
151
457
|
window.addEventListener("pointerup", handleUp);
|
|
152
458
|
window.addEventListener("pointercancel", handleUp);
|
|
153
|
-
}, [
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
459
|
+
}, [
|
|
460
|
+
draggable,
|
|
461
|
+
freeDrag,
|
|
462
|
+
inDock,
|
|
463
|
+
dock,
|
|
464
|
+
id,
|
|
465
|
+
effectiveZone,
|
|
466
|
+
resolveFreeDragMode,
|
|
467
|
+
getDragBounds,
|
|
468
|
+
saveStoredPosition,
|
|
469
|
+
setDragHoverZoneSafe
|
|
470
|
+
]);
|
|
471
|
+
const showContent = !isCollapsed;
|
|
472
|
+
const openUp = orientation === "vertical" && direction === "up";
|
|
473
|
+
const openLeft = orientation === "horizontal" && direction === "left";
|
|
474
|
+
const detachFromDockFlow = dragActive && inDock && !freeDrag;
|
|
475
|
+
const normalizedButtonsPerDirection = Number.isFinite(buttonsPerDirection) && typeof buttonsPerDirection === "number" && buttonsPerDirection > 0
|
|
476
|
+
? Math.floor(buttonsPerDirection)
|
|
477
|
+
: undefined;
|
|
478
|
+
const showLeadingCollapseButton = orientation === "horizontal" && openLeft && showContent;
|
|
479
|
+
const collapseIconDirection = resolvedOrientationDirection === "horizontal-right" ? "right" : direction;
|
|
480
|
+
const content = showContent ? (_jsx("div", { className: cn("gap-2 p-2", normalizedButtonsPerDirection
|
|
481
|
+
? "grid"
|
|
482
|
+
: orientation === "horizontal"
|
|
483
|
+
? "flex flex-row"
|
|
484
|
+
: "flex flex-col"), style: normalizedButtonsPerDirection
|
|
485
|
+
? orientation === "horizontal"
|
|
486
|
+
? { gridTemplateColumns: `repeat(${normalizedButtonsPerDirection}, max-content)` }
|
|
487
|
+
: {
|
|
488
|
+
gridTemplateRows: `repeat(${normalizedButtonsPerDirection}, max-content)`,
|
|
489
|
+
gridAutoFlow: "column"
|
|
490
|
+
}
|
|
491
|
+
: undefined, children: children })) : null;
|
|
492
|
+
const toolbar = (_jsx(SgToolbarOrientationContext.Provider, { value: orientation, children: _jsxs("div", { ref: containerRef, "data-sg-toolbar-root": "true", "data-sg-toolbar-id": id, className: cn("select-none rounded-xl border border-border bg-background shadow-sm", orientation === "horizontal" ? "inline-flex flex-row items-center" : "inline-flex flex-col items-center", className), style: {
|
|
493
|
+
width: size?.w,
|
|
494
|
+
height: size?.h,
|
|
495
|
+
backgroundColor: bgColor,
|
|
496
|
+
cursor: draggable ? (dragActive ? "grabbing" : "grab") : undefined,
|
|
497
|
+
position: dragPos?.mode,
|
|
498
|
+
left: dragPos?.x,
|
|
499
|
+
top: dragPos?.y,
|
|
500
|
+
order: detachFromDockFlow ? undefined : toolbarRenderOrder,
|
|
501
|
+
zIndex: dragPos ? 1000 : undefined,
|
|
502
|
+
...style
|
|
503
|
+
}, onPointerDown: handlePointerDown, children: [openUp || openLeft ? content : null, (title || collapsible) && (_jsxs("div", { className: cn("flex items-center gap-2 px-2 py-1", orientation === "horizontal" ? "w-auto" : "w-full", orientation === "horizontal"
|
|
504
|
+
? showContent
|
|
505
|
+
? (openLeft ? "border-l border-border" : "border-r border-border")
|
|
506
|
+
: ""
|
|
507
|
+
: showContent
|
|
508
|
+
? (openUp ? "border-t border-border" : "border-b border-border")
|
|
509
|
+
: ""), style: { backgroundColor: bgColorTitle }, children: [collapsible && showLeadingCollapseButton ? (_jsx("button", { type: "button", className: "inline-flex size-6 items-center justify-center rounded-md hover:bg-muted", onClick: () => setIsCollapsed(!isCollapsed), onPointerDown: (e) => e.stopPropagation(), "aria-label": "Toggle toolbar", children: _jsx(CollapseIcon, { direction: collapseIconDirection, collapsed: isCollapsed }) })) : null, title ? (_jsx("span", { className: "text-xs font-semibold text-foreground truncate", children: title })) : null, collapsible && !showLeadingCollapseButton ? (_jsx("button", { type: "button", className: "ml-auto inline-flex size-6 items-center justify-center rounded-md hover:bg-muted", onClick: () => setIsCollapsed(!isCollapsed), onPointerDown: (e) => e.stopPropagation(), "aria-label": "Toggle toolbar", children: _jsx(CollapseIcon, { direction: collapseIconDirection, collapsed: isCollapsed }) })) : null] })), openUp || openLeft ? null : content] }) }));
|
|
510
|
+
const needsCenterWrapper = inDock && (effectiveZone === "right" || effectiveZone === "left");
|
|
511
|
+
const toolbarForRender = needsCenterWrapper && !detachFromDockFlow ? (_jsx("div", { style: { width: "100%", display: "flex", justifyContent: "center", order: toolbarRenderOrder }, children: toolbar })) : toolbar;
|
|
173
512
|
if (portalTarget) {
|
|
174
|
-
return createPortal(
|
|
513
|
+
return createPortal(toolbarForRender, portalTarget);
|
|
175
514
|
}
|
|
176
|
-
return
|
|
515
|
+
return toolbarForRender;
|
|
177
516
|
}
|
|
178
517
|
export function SgToolbarIconButton(props) {
|
|
179
|
-
const { icon, hint, severity = "plain", disabled, onClick, hideLabel } = props;
|
|
518
|
+
const { icon, label, showLabel = true, hint, loading = false, severity = "plain", disabled, onClick, hideLabel } = props;
|
|
519
|
+
const toolbarOrientation = React.useContext(SgToolbarOrientationContext);
|
|
520
|
+
const isHorizontalToolbar = toolbarOrientation === "horizontal";
|
|
180
521
|
const c = BTN_COLORS[severity];
|
|
181
522
|
const text = typeof icon === "string" ? icon : null;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
523
|
+
const hasVisibleLabel = Boolean(label) && showLabel && !hideLabel;
|
|
524
|
+
const [isPending, setIsPending] = React.useState(false);
|
|
525
|
+
const isLoading = loading || isPending;
|
|
526
|
+
const showHintTooltip = Boolean(hint) && !hideLabel;
|
|
527
|
+
const [hintPosition, setHintPosition] = React.useState({ x: 0, y: 0 });
|
|
528
|
+
const [isHintHovered, setIsHintHovered] = React.useState(false);
|
|
529
|
+
const buttonRef = React.useRef(null);
|
|
530
|
+
const handleClick = React.useCallback(() => {
|
|
531
|
+
if (!onClick || disabled || isLoading)
|
|
532
|
+
return;
|
|
533
|
+
const result = onClick();
|
|
534
|
+
if (!result || typeof result.then !== "function")
|
|
535
|
+
return;
|
|
536
|
+
setIsPending(true);
|
|
537
|
+
void result.finally(() => {
|
|
538
|
+
setIsPending(false);
|
|
539
|
+
});
|
|
540
|
+
}, [disabled, isLoading, onClick]);
|
|
541
|
+
const updateHintPosition = React.useCallback(() => {
|
|
542
|
+
if (!buttonRef.current)
|
|
543
|
+
return;
|
|
544
|
+
const buttonRect = buttonRef.current.getBoundingClientRect();
|
|
545
|
+
const toolbarRoot = buttonRef.current.closest("[data-sg-toolbar-root='true']");
|
|
546
|
+
const toolbarRect = toolbarRoot instanceof HTMLElement ? toolbarRoot.getBoundingClientRect() : null;
|
|
547
|
+
if (isHorizontalToolbar) {
|
|
548
|
+
const baseY = toolbarRect ? toolbarRect.top : buttonRect.top;
|
|
549
|
+
setHintPosition({
|
|
550
|
+
x: buttonRect.left + (buttonRect.width / 2),
|
|
551
|
+
y: baseY - 8
|
|
552
|
+
});
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const baseX = toolbarRect ? toolbarRect.right : buttonRect.right;
|
|
556
|
+
setHintPosition({
|
|
557
|
+
x: baseX + 8,
|
|
558
|
+
y: buttonRect.top + (buttonRect.height / 2)
|
|
559
|
+
});
|
|
560
|
+
}, [isHorizontalToolbar]);
|
|
561
|
+
React.useEffect(() => {
|
|
562
|
+
if (!showHintTooltip || !isHintHovered)
|
|
563
|
+
return;
|
|
564
|
+
updateHintPosition();
|
|
565
|
+
const handleReposition = () => updateHintPosition();
|
|
566
|
+
window.addEventListener("scroll", handleReposition, true);
|
|
567
|
+
window.addEventListener("resize", handleReposition);
|
|
568
|
+
return () => {
|
|
569
|
+
window.removeEventListener("scroll", handleReposition, true);
|
|
570
|
+
window.removeEventListener("resize", handleReposition);
|
|
571
|
+
};
|
|
572
|
+
}, [isHintHovered, showHintTooltip, updateHintPosition]);
|
|
573
|
+
const hintNode = showHintTooltip && isHintHovered && typeof document !== "undefined"
|
|
574
|
+
? createPortal(_jsx("span", { className: "pointer-events-none fixed z-[1200] whitespace-nowrap rounded bg-foreground/90 px-2 py-1 text-[11px] text-background", style: {
|
|
575
|
+
left: hintPosition.x,
|
|
576
|
+
top: hintPosition.y,
|
|
577
|
+
transform: isHorizontalToolbar ? "translate(-50%, -100%)" : "translateY(-50%)"
|
|
578
|
+
}, children: hint }), document.body)
|
|
579
|
+
: null;
|
|
580
|
+
return (_jsxs(_Fragment, { children: [_jsxs("button", { ref: buttonRef, type: "button", disabled: disabled || isLoading, onClick: handleClick, "aria-busy": isLoading || undefined, onMouseEnter: showHintTooltip ? () => {
|
|
581
|
+
updateHintPosition();
|
|
582
|
+
setIsHintHovered(true);
|
|
583
|
+
} : undefined, onMouseLeave: showHintTooltip ? () => setIsHintHovered(false) : undefined, "aria-label": hint ?? label ?? text ?? undefined, className: cn("group", "relative inline-flex items-center justify-center rounded-lg", "transition-[transform,filter] duration-150", "hover:brightness-95 active:brightness-90", "focus-visible:outline-none focus-visible:ring-4", "disabled:opacity-50 disabled:cursor-not-allowed", hasVisibleLabel ? "gap-2 px-2 pr-3" : ""), style: {
|
|
584
|
+
width: hasVisibleLabel ? undefined : 40,
|
|
585
|
+
minWidth: 40,
|
|
586
|
+
height: 40,
|
|
587
|
+
backgroundColor: c.bg,
|
|
588
|
+
color: c.fg,
|
|
589
|
+
["--tw-ring-color"]: c.ring
|
|
590
|
+
}, children: [isLoading ? (_jsx("span", { className: "inline-flex size-4 shrink-0 animate-spin rounded-full border-2 border-current border-r-transparent" })) : icon && typeof icon !== "string" ? (_jsx("span", { className: "inline-flex shrink-0", children: icon })) : (_jsx("span", { className: "shrink-0 text-[10px] font-semibold", children: text?.slice(0, 2) })), hasVisibleLabel ? (_jsx("span", { className: "text-xs font-medium leading-none", children: label })) : null] }), hintNode] }));
|
|
189
591
|
}
|
|
190
592
|
function CollapseIcon(props) {
|
|
191
593
|
const { direction, collapsed } = props;
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
594
|
+
const arrowUp = "M6 15l6-6 6 6";
|
|
595
|
+
const arrowDown = "M6 9l6 6 6-6";
|
|
596
|
+
const arrowLeft = "M15 6l-6 6 6 6";
|
|
597
|
+
const arrowRight = "M9 6l6 6-6 6";
|
|
598
|
+
const path = direction === "down" ? (collapsed ? arrowDown : arrowUp)
|
|
599
|
+
: direction === "up" ? (collapsed ? arrowUp : arrowDown)
|
|
600
|
+
: direction === "left" ? (collapsed ? arrowLeft : arrowRight)
|
|
601
|
+
: (collapsed ? arrowRight : arrowLeft);
|
|
602
|
+
return (_jsx("svg", { viewBox: "0 0 24 24", className: "size-4", "aria-hidden": "true", children: _jsx("path", { d: path, fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
197
603
|
}
|
|
198
604
|
SgToolBar.displayName = "SgToolBar";
|
|
199
605
|
SgToolbarIconButton.displayName = "SgToolbarIconButton";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type SgDockMenuPosition = "left-top" | "left-center" | "left-bottom" | "center-top" | "center-bottom" | "right-top" | "right-center" | "right-bottom";
|
|
3
|
+
export type SgDockMenuOrientation = "horizontal" | "vertical";
|
|
4
|
+
export type SgDockMenuItem = {
|
|
5
|
+
/** Unique identifier */
|
|
6
|
+
id: string;
|
|
7
|
+
/** Icon to display */
|
|
8
|
+
icon: React.ReactNode;
|
|
9
|
+
/** Label/tooltip text */
|
|
10
|
+
label: string;
|
|
11
|
+
/** Click handler */
|
|
12
|
+
onClick?: () => void;
|
|
13
|
+
/** Disabled state */
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
/** Badge content */
|
|
16
|
+
badge?: string | number;
|
|
17
|
+
/** Custom class name */
|
|
18
|
+
className?: string;
|
|
19
|
+
};
|
|
20
|
+
export interface SgDockMenuProps {
|
|
21
|
+
/** Unique identifier for the dock */
|
|
22
|
+
id?: string;
|
|
23
|
+
/** Items to display in the dock */
|
|
24
|
+
items: SgDockMenuItem[];
|
|
25
|
+
/** Position of the dock */
|
|
26
|
+
position?: SgDockMenuPosition;
|
|
27
|
+
/** Enable drag and drop repositioning */
|
|
28
|
+
enableDragDrop?: boolean;
|
|
29
|
+
/** ID for persisting drag position */
|
|
30
|
+
dragId?: string;
|
|
31
|
+
/** Offset from the edge */
|
|
32
|
+
offset?: {
|
|
33
|
+
x?: number;
|
|
34
|
+
y?: number;
|
|
35
|
+
};
|
|
36
|
+
/** Custom class name for container */
|
|
37
|
+
className?: string;
|
|
38
|
+
/** Custom class name for items */
|
|
39
|
+
itemClassName?: string;
|
|
40
|
+
/** Z-index */
|
|
41
|
+
zIndex?: number;
|
|
42
|
+
/** Item size in pixels */
|
|
43
|
+
itemSize?: number;
|
|
44
|
+
/** Gap between items in pixels */
|
|
45
|
+
gap?: number;
|
|
46
|
+
/** Background color */
|
|
47
|
+
backgroundColor?: string;
|
|
48
|
+
/** Show labels on hover */
|
|
49
|
+
showLabels?: boolean;
|
|
50
|
+
/** Magnification effect on hover */
|
|
51
|
+
magnify?: boolean;
|
|
52
|
+
/** Magnification scale */
|
|
53
|
+
magnifyScale?: number;
|
|
54
|
+
/** Border radius */
|
|
55
|
+
borderRadius?: number;
|
|
56
|
+
/** Shadow elevation */
|
|
57
|
+
elevation?: "none" | "sm" | "md" | "lg";
|
|
58
|
+
/** Custom style */
|
|
59
|
+
style?: React.CSSProperties;
|
|
60
|
+
}
|
|
61
|
+
export declare function SgDockMenu(props: Readonly<SgDockMenuProps>): import("react/jsx-runtime").JSX.Element;
|
|
62
|
+
//# sourceMappingURL=SgDockMenu.d.ts.map
|