@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.
Files changed (155) hide show
  1. package/dist/buttons/SgFloatActionButton.d.ts.map +1 -1
  2. package/dist/buttons/SgFloatActionButton.js +168 -38
  3. package/dist/commons/SgAvatar.d.ts +66 -0
  4. package/dist/commons/SgAvatar.d.ts.map +1 -0
  5. package/dist/commons/SgAvatar.js +136 -0
  6. package/dist/commons/SgSkeleton.d.ts +16 -0
  7. package/dist/commons/SgSkeleton.d.ts.map +1 -0
  8. package/dist/commons/SgSkeleton.js +58 -0
  9. package/dist/commons/SgToaster.d.ts +9 -0
  10. package/dist/commons/SgToaster.d.ts.map +1 -1
  11. package/dist/commons/SgToaster.js +86 -17
  12. package/dist/digits/discard-digit/SgDiscardDigit.d.ts +39 -0
  13. package/dist/digits/discard-digit/SgDiscardDigit.d.ts.map +1 -0
  14. package/dist/digits/discard-digit/SgDiscardDigit.js +303 -0
  15. package/dist/digits/discard-digit/index.d.ts +3 -0
  16. package/dist/digits/discard-digit/index.d.ts.map +1 -0
  17. package/dist/digits/discard-digit/index.js +1 -0
  18. package/dist/digits/fade-digit/SgFadeDigit.d.ts +27 -0
  19. package/dist/digits/fade-digit/SgFadeDigit.d.ts.map +1 -0
  20. package/dist/digits/fade-digit/SgFadeDigit.js +85 -0
  21. package/dist/digits/fade-digit/index.d.ts +3 -0
  22. package/dist/digits/fade-digit/index.d.ts.map +1 -0
  23. package/dist/digits/fade-digit/index.js +1 -0
  24. package/dist/digits/flip-digit/SgFlipDigit.d.ts +27 -0
  25. package/dist/digits/flip-digit/SgFlipDigit.d.ts.map +1 -0
  26. package/dist/digits/flip-digit/SgFlipDigit.js +70 -0
  27. package/dist/digits/flip-digit/index.d.ts.map +1 -0
  28. package/dist/digits/matrix-digit/SgMatrixDigit.d.ts +32 -0
  29. package/dist/digits/matrix-digit/SgMatrixDigit.d.ts.map +1 -0
  30. package/dist/digits/matrix-digit/SgMatrixDigit.js +86 -0
  31. package/dist/digits/matrix-digit/index.d.ts +3 -0
  32. package/dist/digits/matrix-digit/index.d.ts.map +1 -0
  33. package/dist/digits/matrix-digit/index.js +1 -0
  34. package/dist/digits/neon-digit/SgNeonDigit.d.ts +37 -0
  35. package/dist/digits/neon-digit/SgNeonDigit.d.ts.map +1 -0
  36. package/dist/digits/neon-digit/SgNeonDigit.js +59 -0
  37. package/dist/digits/neon-digit/index.d.ts +3 -0
  38. package/dist/digits/neon-digit/index.d.ts.map +1 -0
  39. package/dist/digits/neon-digit/index.js +1 -0
  40. package/dist/digits/roller3d-digit/SgRoller3DDigit.d.ts +37 -0
  41. package/dist/digits/roller3d-digit/SgRoller3DDigit.d.ts.map +1 -0
  42. package/dist/digits/roller3d-digit/SgRoller3DDigit.js +47 -0
  43. package/dist/digits/roller3d-digit/index.d.ts +3 -0
  44. package/dist/digits/roller3d-digit/index.d.ts.map +1 -0
  45. package/dist/digits/roller3d-digit/index.js +1 -0
  46. package/dist/environment/SgEnvironmentProvider.d.ts +1 -0
  47. package/dist/environment/SgEnvironmentProvider.d.ts.map +1 -1
  48. package/dist/environment/SgEnvironmentProvider.js +51 -12
  49. package/dist/gadgets/clock/SgClock.d.ts +3 -1
  50. package/dist/gadgets/clock/SgClock.d.ts.map +1 -1
  51. package/dist/gadgets/clock/SgClock.js +111 -180
  52. package/dist/gadgets/clock/SgTimeProvider.d.ts +1 -0
  53. package/dist/gadgets/clock/SgTimeProvider.d.ts.map +1 -1
  54. package/dist/gadgets/clock/SgTimeProvider.js +11 -4
  55. package/dist/gadgets/gauge/SgLinearGauge.d.ts +59 -0
  56. package/dist/gadgets/gauge/SgLinearGauge.d.ts.map +1 -0
  57. package/dist/gadgets/gauge/SgLinearGauge.js +258 -0
  58. package/dist/gadgets/gauge/SgRadialGauge.d.ts +73 -0
  59. package/dist/gadgets/gauge/SgRadialGauge.d.ts.map +1 -0
  60. package/dist/gadgets/gauge/SgRadialGauge.js +311 -0
  61. package/dist/gadgets/gauge/index.d.ts +5 -0
  62. package/dist/gadgets/gauge/index.d.ts.map +1 -0
  63. package/dist/gadgets/gauge/index.js +2 -0
  64. package/dist/gadgets/qr-code/SgQRCode.d.ts +25 -0
  65. package/dist/gadgets/qr-code/SgQRCode.d.ts.map +1 -0
  66. package/dist/gadgets/qr-code/SgQRCode.js +75 -0
  67. package/dist/gadgets/qr-code/index.d.ts +3 -0
  68. package/dist/gadgets/qr-code/index.d.ts.map +1 -0
  69. package/dist/gadgets/qr-code/index.js +1 -0
  70. package/dist/gadgets/string-animator/SgStringAnimator.d.ts +91 -0
  71. package/dist/gadgets/string-animator/SgStringAnimator.d.ts.map +1 -0
  72. package/dist/gadgets/string-animator/SgStringAnimator.js +145 -0
  73. package/dist/gadgets/string-animator/index.d.ts +3 -0
  74. package/dist/gadgets/string-animator/index.d.ts.map +1 -0
  75. package/dist/gadgets/string-animator/index.js +1 -0
  76. package/dist/i18n/en-US.json +9 -1
  77. package/dist/i18n/es.json +55 -47
  78. package/dist/i18n/index.d.ts +32 -0
  79. package/dist/i18n/index.d.ts.map +1 -1
  80. package/dist/i18n/pt-BR.json +9 -1
  81. package/dist/i18n/pt-PT.json +9 -1
  82. package/dist/index.d.ts +53 -5
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +25 -1
  85. package/dist/inputs/SgAutocomplete.js +21 -5
  86. package/dist/inputs/SgCombobox.d.ts +26 -0
  87. package/dist/inputs/SgCombobox.d.ts.map +1 -0
  88. package/dist/inputs/SgCombobox.js +354 -0
  89. package/dist/inputs/SgInputOTP.d.ts.map +1 -1
  90. package/dist/inputs/SgInputOTP.js +9 -2
  91. package/dist/inputs/SgRadioGroup.d.ts +37 -0
  92. package/dist/inputs/SgRadioGroup.d.ts.map +1 -0
  93. package/dist/inputs/SgRadioGroup.js +139 -0
  94. package/dist/inputs/SgRating.d.ts +55 -0
  95. package/dist/inputs/SgRating.d.ts.map +1 -0
  96. package/dist/inputs/SgRating.js +135 -0
  97. package/dist/inputs/SgSlider.d.ts +20 -0
  98. package/dist/inputs/SgSlider.d.ts.map +1 -0
  99. package/dist/inputs/SgSlider.js +40 -0
  100. package/dist/inputs/SgStepperInput.d.ts +22 -0
  101. package/dist/inputs/SgStepperInput.d.ts.map +1 -0
  102. package/dist/inputs/SgStepperInput.js +51 -0
  103. package/dist/inputs/SgTextEditor.d.ts +1 -0
  104. package/dist/inputs/SgTextEditor.d.ts.map +1 -1
  105. package/dist/inputs/SgTextEditor.js +19 -3
  106. package/dist/inputs/SgToggleSwitch.d.ts +36 -0
  107. package/dist/inputs/SgToggleSwitch.d.ts.map +1 -0
  108. package/dist/inputs/SgToggleSwitch.js +174 -0
  109. package/dist/layout/SgAccordion.d.ts +39 -0
  110. package/dist/layout/SgAccordion.d.ts.map +1 -0
  111. package/dist/layout/SgAccordion.js +116 -0
  112. package/dist/layout/SgBreadcrumb.d.ts +33 -0
  113. package/dist/layout/SgBreadcrumb.d.ts.map +1 -0
  114. package/dist/layout/SgBreadcrumb.js +121 -0
  115. package/dist/layout/SgCarousel.d.ts +43 -0
  116. package/dist/layout/SgCarousel.d.ts.map +1 -0
  117. package/dist/layout/SgCarousel.js +166 -0
  118. package/dist/layout/SgDockLayout.d.ts +14 -0
  119. package/dist/layout/SgDockLayout.d.ts.map +1 -1
  120. package/dist/layout/SgDockLayout.js +145 -13
  121. package/dist/layout/SgDockScreen.d.ts +15 -0
  122. package/dist/layout/SgDockScreen.d.ts.map +1 -0
  123. package/dist/layout/SgDockScreen.js +13 -0
  124. package/dist/layout/SgDockZone.d.ts.map +1 -1
  125. package/dist/layout/SgDockZone.js +36 -2
  126. package/dist/layout/SgExpandablePanel.d.ts +50 -0
  127. package/dist/layout/SgExpandablePanel.d.ts.map +1 -0
  128. package/dist/layout/SgExpandablePanel.js +302 -0
  129. package/dist/layout/SgMainPanel.d.ts.map +1 -1
  130. package/dist/layout/SgMainPanel.js +36 -14
  131. package/dist/layout/SgMenu.d.ts +91 -0
  132. package/dist/layout/SgMenu.d.ts.map +1 -0
  133. package/dist/layout/SgMenu.js +939 -0
  134. package/dist/layout/SgPageControl.d.ts +49 -0
  135. package/dist/layout/SgPageControl.d.ts.map +1 -0
  136. package/dist/layout/SgPageControl.js +152 -0
  137. package/dist/layout/SgPanel.d.ts.map +1 -1
  138. package/dist/layout/SgPanel.js +10 -1
  139. package/dist/layout/SgScreen.d.ts +2 -0
  140. package/dist/layout/SgScreen.d.ts.map +1 -1
  141. package/dist/layout/SgScreen.js +4 -2
  142. package/dist/layout/SgToolBar.d.ts +9 -3
  143. package/dist/layout/SgToolBar.d.ts.map +1 -1
  144. package/dist/layout/SgToolBar.js +461 -55
  145. package/dist/menus/SgDockMenu.d.ts +62 -0
  146. package/dist/menus/SgDockMenu.d.ts.map +1 -0
  147. package/dist/menus/SgDockMenu.js +480 -0
  148. package/dist/others/SgPlayground.js +73 -73
  149. package/package.json +72 -57
  150. package/dist/gadgets/flip-digit/SgFlipDigit.d.ts +0 -23
  151. package/dist/gadgets/flip-digit/SgFlipDigit.d.ts.map +0 -1
  152. package/dist/gadgets/flip-digit/SgFlipDigit.js +0 -118
  153. package/dist/gadgets/flip-digit/index.d.ts.map +0 -1
  154. /package/dist/{gadgets → digits}/flip-digit/index.d.ts +0 -0
  155. /package/dist/{gadgets → digits}/flip-digit/index.js +0 -0
@@ -9,11 +9,26 @@ export function useSgDockLayout() {
9
9
  const EMPTY_STATE = { version: 1, toolbars: {} };
10
10
  export function SgDockLayout(props) {
11
11
  const { id, className, children, defaultState } = props;
12
- const { value: persisted, setValue } = useSgPersistentState({
12
+ const { value: persisted, setValue, hydrated } = useSgPersistentState({
13
13
  baseKey: `dock-layout:${id}`,
14
14
  defaultValue: defaultState ?? EMPTY_STATE
15
15
  });
16
+ const [isDropPreviewActive, setIsDropPreviewActive] = React.useState(false);
17
+ const [draggingToolbarId, setDraggingToolbarIdState] = React.useState(null);
18
+ const [dropIndicator, setDropIndicator] = React.useState(null);
16
19
  const zonesRef = React.useRef(new Map());
20
+ const getSortedZoneToolbarIds = React.useCallback((state, zone, excludingId) => {
21
+ return Object.values(state)
22
+ .filter((tb) => tb.zone === zone && tb.id !== excludingId)
23
+ .sort((a, b) => {
24
+ const orderA = a.order ?? 0;
25
+ const orderB = b.order ?? 0;
26
+ if (orderA !== orderB)
27
+ return orderA - orderB;
28
+ return a.id.localeCompare(b.id);
29
+ })
30
+ .map((tb) => tb.id);
31
+ }, []);
17
32
  const registerZone = React.useCallback((zone, el) => {
18
33
  if (!el) {
19
34
  zonesRef.current.delete(zone);
@@ -33,43 +48,150 @@ export function SgDockLayout(props) {
33
48
  }
34
49
  return null;
35
50
  }, []);
51
+ const getDropPlacementAtPoint = React.useCallback((x, y, draggingToolbarId) => {
52
+ const zone = getZoneAtPoint(x, y);
53
+ if (!zone)
54
+ return null;
55
+ const zoneEl = zonesRef.current.get(zone);
56
+ if (!zoneEl)
57
+ return null;
58
+ const axisHorizontal = zone === "top" || zone === "bottom";
59
+ const toolbarEls = Array.from(zoneEl.querySelectorAll("[data-sg-toolbar-root='true'][data-sg-toolbar-id]"))
60
+ .filter((el) => el.dataset.sgToolbarId !== draggingToolbarId)
61
+ .sort((a, b) => {
62
+ const rectA = a.getBoundingClientRect();
63
+ const rectB = b.getBoundingClientRect();
64
+ if (axisHorizontal) {
65
+ if (rectA.top !== rectB.top)
66
+ return rectA.top - rectB.top;
67
+ return rectA.left - rectB.left;
68
+ }
69
+ if (rectA.left !== rectB.left)
70
+ return rectA.left - rectB.left;
71
+ return rectA.top - rectB.top;
72
+ });
73
+ const cursorMajor = axisHorizontal ? x : y;
74
+ let index = toolbarEls.length;
75
+ for (let i = 0; i < toolbarEls.length; i += 1) {
76
+ const toolbarEl = toolbarEls[i];
77
+ if (!toolbarEl)
78
+ continue;
79
+ const rect = toolbarEl.getBoundingClientRect();
80
+ const majorCenter = axisHorizontal ? rect.left + rect.width / 2 : rect.top + rect.height / 2;
81
+ if (cursorMajor < majorCenter) {
82
+ index = i;
83
+ break;
84
+ }
85
+ }
86
+ return { zone, index };
87
+ }, [getZoneAtPoint]);
88
+ const setDropPreviewActive = React.useCallback((next) => {
89
+ setIsDropPreviewActive((prev) => (prev === next ? prev : next));
90
+ if (!next) {
91
+ setDropIndicator(null);
92
+ setDraggingToolbarIdState(null);
93
+ }
94
+ }, []);
95
+ const setDraggingToolbarId = React.useCallback((toolbarId) => {
96
+ setDraggingToolbarIdState((prev) => (prev === toolbarId ? prev : toolbarId));
97
+ }, []);
98
+ React.useEffect(() => {
99
+ if (!isDropPreviewActive)
100
+ return;
101
+ const clearPreview = () => setDropPreviewActive(false);
102
+ const handleVisibilityChange = () => {
103
+ if (document.hidden)
104
+ clearPreview();
105
+ };
106
+ window.addEventListener("pointerup", clearPreview);
107
+ window.addEventListener("pointercancel", clearPreview);
108
+ window.addEventListener("blur", clearPreview);
109
+ document.addEventListener("visibilitychange", handleVisibilityChange);
110
+ return () => {
111
+ window.removeEventListener("pointerup", clearPreview);
112
+ window.removeEventListener("pointercancel", clearPreview);
113
+ window.removeEventListener("blur", clearPreview);
114
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
115
+ };
116
+ }, [isDropPreviewActive, setDropPreviewActive]);
36
117
  const getToolbarZone = React.useCallback((toolbarId) => persisted.toolbars[toolbarId]?.zone ?? null, [persisted]);
118
+ const getToolbarOrder = React.useCallback((toolbarId) => {
119
+ const toolbar = persisted.toolbars[toolbarId];
120
+ if (!toolbar)
121
+ return undefined;
122
+ if (draggingToolbarId && toolbarId === draggingToolbarId)
123
+ return undefined;
124
+ const ids = getSortedZoneToolbarIds(persisted.toolbars, toolbar.zone, draggingToolbarId ?? undefined);
125
+ const index = ids.indexOf(toolbarId);
126
+ return index === -1 ? undefined : index;
127
+ }, [draggingToolbarId, getSortedZoneToolbarIds, persisted]);
128
+ const getZoneToolbarCount = React.useCallback((zone) => {
129
+ const zoneEl = zonesRef.current.get(zone);
130
+ if (!zoneEl)
131
+ return 0;
132
+ return Array.from(zoneEl.querySelectorAll("[data-sg-toolbar-root='true'][data-sg-toolbar-id]")).filter((el) => el.dataset.sgToolbarId !== draggingToolbarId).length;
133
+ }, [draggingToolbarId]);
37
134
  const ensureToolbar = React.useCallback((toolbarId, state) => {
135
+ if (!hydrated)
136
+ return;
38
137
  setValue((prev) => {
39
138
  if (prev.toolbars[toolbarId])
40
139
  return prev;
140
+ const targetZone = state.zone ?? "free";
141
+ const zoneIds = getSortedZoneToolbarIds(prev.toolbars, targetZone);
41
142
  return {
42
143
  ...prev,
43
144
  toolbars: {
44
145
  ...prev.toolbars,
45
146
  [toolbarId]: {
46
147
  id: toolbarId,
47
- zone: state.zone ?? "free",
148
+ zone: targetZone,
48
149
  collapsed: state.collapsed ?? false,
49
150
  orientation: state.orientation,
50
- order: state.order ?? Object.keys(prev.toolbars).length
151
+ order: state.order ?? zoneIds.length
51
152
  }
52
153
  }
53
154
  };
54
155
  });
55
- }, [setValue]);
56
- const moveToolbar = React.useCallback((toolbarId, zone) => {
156
+ }, [getSortedZoneToolbarIds, hydrated, setValue]);
157
+ const placeToolbar = React.useCallback((toolbarId, zone, index) => {
57
158
  setValue((prev) => {
58
159
  const current = prev.toolbars[toolbarId];
59
160
  if (!current)
60
161
  return prev;
162
+ const sourceZone = current.zone;
163
+ const targetZone = zone;
164
+ const nextToolbars = {
165
+ ...prev.toolbars
166
+ };
167
+ const targetIds = getSortedZoneToolbarIds(prev.toolbars, targetZone, toolbarId);
168
+ const safeIndex = Math.max(0, Math.min(index, targetIds.length));
169
+ targetIds.splice(safeIndex, 0, toolbarId);
170
+ targetIds.forEach((tbId, i) => {
171
+ const base = nextToolbars[tbId];
172
+ if (!base)
173
+ return;
174
+ nextToolbars[tbId] = { ...base, zone: targetZone, order: i };
175
+ });
176
+ if (sourceZone !== targetZone) {
177
+ const sourceIds = getSortedZoneToolbarIds(prev.toolbars, sourceZone, toolbarId);
178
+ sourceIds.forEach((tbId, i) => {
179
+ const base = nextToolbars[tbId];
180
+ if (!base)
181
+ return;
182
+ nextToolbars[tbId] = { ...base, order: i };
183
+ });
184
+ }
61
185
  return {
62
186
  ...prev,
63
- toolbars: {
64
- ...prev.toolbars,
65
- [toolbarId]: {
66
- ...current,
67
- zone
68
- }
69
- }
187
+ toolbars: nextToolbars
70
188
  };
71
189
  });
72
- }, [setValue]);
190
+ }, [getSortedZoneToolbarIds, setValue]);
191
+ const moveToolbar = React.useCallback((toolbarId, zone) => {
192
+ const currentZoneIds = getSortedZoneToolbarIds(persisted.toolbars, zone, toolbarId);
193
+ placeToolbar(toolbarId, zone, currentZoneIds.length);
194
+ }, [getSortedZoneToolbarIds, persisted.toolbars, placeToolbar]);
73
195
  const getToolbarCollapsed = React.useCallback((toolbarId) => persisted.toolbars[toolbarId]?.collapsed, [persisted]);
74
196
  const setToolbarCollapsed = React.useCallback((toolbarId, next) => {
75
197
  setValue((prev) => {
@@ -90,8 +212,18 @@ export function SgDockLayout(props) {
90
212
  getZoneElement,
91
213
  registerZone,
92
214
  getZoneAtPoint,
215
+ getDropPlacementAtPoint,
216
+ getZoneToolbarCount,
217
+ isDropPreviewActive,
218
+ setDropPreviewActive,
219
+ draggingToolbarId,
220
+ setDraggingToolbarId,
221
+ dropIndicator,
222
+ setDropIndicator,
93
223
  getToolbarZone,
224
+ getToolbarOrder,
94
225
  moveToolbar,
226
+ placeToolbar,
95
227
  ensureToolbar,
96
228
  getToolbarCollapsed,
97
229
  setToolbarCollapsed
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ import { type SgDockLayoutState } from "./SgDockLayout";
3
+ import { type SgScreenProps } from "./SgScreen";
4
+ export type SgDockScreenProps = Omit<SgScreenProps, "children" | "id"> & {
5
+ id: string;
6
+ screenId?: string;
7
+ defaultState?: SgDockLayoutState;
8
+ layoutClassName?: string;
9
+ children?: React.ReactNode;
10
+ };
11
+ export declare function SgDockScreen(props: Readonly<SgDockScreenProps>): import("react/jsx-runtime").JSX.Element;
12
+ export declare namespace SgDockScreen {
13
+ var displayName: string;
14
+ }
15
+ //# sourceMappingURL=SgDockScreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SgDockScreen.d.ts","sourceRoot":"","sources":["../../src/layout/SgDockScreen.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAM1D,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,IAAI,CAAC,GAAG;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAIF,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,iBAAiB,CAAC,2CAqB9D;yBArBe,YAAY"}
@@ -0,0 +1,13 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { SgDockLayout } from "./SgDockLayout";
4
+ import { SgScreen } from "./SgScreen";
5
+ function cn(...parts) {
6
+ return parts.filter(Boolean).join(" ");
7
+ }
8
+ const AUTO_LAYOUT_ROOT_CLASS = "relative grid h-full w-full min-h-0 min-w-0 grid-cols-[12rem_1fr_12rem] grid-rows-[auto_1fr_auto]";
9
+ export function SgDockScreen(props) {
10
+ const { id, screenId, defaultState, layoutClassName, children, ...screenProps } = props;
11
+ return (_jsx(SgScreen, { ...screenProps, id: screenId, children: _jsx(SgDockLayout, { id: id, defaultState: defaultState, className: cn(AUTO_LAYOUT_ROOT_CLASS, layoutClassName), children: children }) }));
12
+ }
13
+ SgDockScreen.displayName = "SgDockScreen";
@@ -1 +1 @@
1
- {"version":3,"file":"SgDockZone.d.ts","sourceRoot":"","sources":["../../src/layout/SgDockZone.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEpE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAMF,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,2CAwB1D;yBAxBe,UAAU"}
1
+ {"version":3,"file":"SgDockZone.d.ts","sourceRoot":"","sources":["../../src/layout/SgDockZone.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGpE,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAeF,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,2CA0E1D;yBA1Ee,UAAU"}
@@ -1,20 +1,54 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { useSgDockLayout } from "./SgDockLayout";
5
+ import { t, useComponentsI18n } from "../i18n";
5
6
  function cn(...parts) {
6
7
  return parts.filter(Boolean).join(" ");
7
8
  }
9
+ const POSITION_CLASS_PATTERN = /(?:^|\s)!?(?:(?:[a-z0-9-]+:)+)?(?:static|fixed|absolute|relative|sticky)(?=\s|$)/i;
10
+ const DEFAULT_ZONE_LAYOUT_CLASS = {
11
+ top: "col-span-3 row-start-1 items-start",
12
+ bottom: "col-span-3 row-start-3 items-end",
13
+ left: "col-start-1 row-start-2 items-start",
14
+ right: "col-start-3 row-start-2 items-start",
15
+ free: "col-start-2 row-start-2 items-center justify-center"
16
+ };
8
17
  export function SgDockZone(props) {
9
18
  const { zone, className, children } = props;
10
19
  const dock = useSgDockLayout();
20
+ const i18n = useComponentsI18n();
11
21
  const ref = React.useRef(null);
22
+ const showDropPreview = Boolean(dock?.isDropPreviewActive);
23
+ const dropIndicator = dock?.dropIndicator ?? null;
24
+ const zoneToolbarCount = dock?.getZoneToolbarCount(zone) ?? 0;
25
+ const showSlotPreview = showDropPreview && zone !== "free" && Boolean(dock?.draggingToolbarId);
26
+ const dropSlotIndexes = React.useMemo(() => {
27
+ if (!showSlotPreview)
28
+ return [];
29
+ const slotCount = Math.max(1, zoneToolbarCount + 1);
30
+ return Array.from({ length: slotCount }, (_, i) => i);
31
+ }, [showSlotPreview, zoneToolbarCount]);
32
+ const isHorizontalZone = zone === "top" || zone === "bottom";
33
+ const isVerticalZone = zone === "left" || zone === "right";
34
+ const hasExplicitPositionClass = POSITION_CLASS_PATTERN.test(className ?? "");
35
+ const hasCustomClass = Boolean(className?.trim());
36
+ const zoneDefaultLayoutClass = hasCustomClass ? null : DEFAULT_ZONE_LAYOUT_CLASS[zone];
12
37
  React.useEffect(() => {
13
38
  if (!dock)
14
39
  return;
15
40
  dock.registerZone(zone, ref.current);
16
41
  return () => dock.registerZone(zone, null);
17
42
  }, [dock, zone]);
18
- return (_jsx("div", { ref: ref, "data-sg-dock-zone": zone, className: cn("relative flex gap-3 p-3", zone === "top" || zone === "bottom" ? "flex-row items-center" : "flex-col items-center", className), children: children }));
43
+ return (_jsxs("div", { ref: ref, "data-sg-dock-zone": zone, className: cn(hasExplicitPositionClass ? "flex min-h-0 min-w-0 gap-3 p-2" : "relative flex min-h-0 min-w-0 gap-3 p-2", isHorizontalZone
44
+ ? "flex-row flex-wrap items-start content-start"
45
+ : isVerticalZone
46
+ ? "flex-col flex-wrap items-start content-start"
47
+ : "flex-col items-center", showDropPreview ? "rounded-xl border-2 border-dashed border-border/70 bg-background/40 p-3 transition-colors duration-150" : null, showDropPreview && isHorizontalZone ? "min-h-16" : null, showDropPreview && isVerticalZone ? "min-w-24" : null, zoneDefaultLayoutClass, className), children: [children, dropSlotIndexes.map((slotIndex) => {
48
+ const isActiveSlot = dropIndicator?.zone === zone && dropIndicator.index === slotIndex;
49
+ return (_jsx("span", { className: cn("pointer-events-none relative z-[2] inline-flex shrink-0 items-center justify-center rounded border border-dashed text-[11px] font-semibold uppercase tracking-wide transition-colors duration-100", isHorizontalZone ? "h-10 w-16" : "h-8 w-20 self-center", isActiveSlot
50
+ ? "border-primary/70 bg-background/95 text-primary"
51
+ : "border-border/60 bg-background/70 text-foreground/50"), style: { order: slotIndex * 2 - 1 }, "aria-hidden": "true", children: "><" }, `drop-slot-${zone}-${slotIndex}`));
52
+ }), showDropPreview && !showSlotPreview ? (_jsx("span", { className: "pointer-events-none absolute inset-0 z-[1] flex items-center justify-center text-xs font-semibold uppercase tracking-wide text-foreground/70", "aria-hidden": "true", children: t(i18n, "components.dock.dropHere") })) : null] }));
19
53
  }
20
54
  SgDockZone.displayName = "SgDockZone";
@@ -0,0 +1,50 @@
1
+ import * as React from "react";
2
+ export type SgExpandablePanelDirection = "left" | "right" | "top" | "bottom";
3
+ export type SgExpandablePanelPlacement = "start" | "center" | "end";
4
+ export type SgExpandablePanelMode = "inline" | "overlay";
5
+ export type SgExpandablePanelElevation = "none" | "sm" | "md" | "lg";
6
+ export type SgExpandablePanelRounded = "none" | "md" | "lg" | "xl";
7
+ export type SgExpandablePanelRole = "dialog" | "region";
8
+ export type SgExpandablePanelSize = {
9
+ min?: number | string;
10
+ max?: number | string;
11
+ default?: number | string;
12
+ };
13
+ export type SgExpandablePanelAnimation = {
14
+ type?: "slide" | "fade" | "none";
15
+ durationMs?: number;
16
+ };
17
+ export type SgExpandablePanelProps = {
18
+ header?: React.ReactNode;
19
+ children: React.ReactNode;
20
+ footer?: React.ReactNode;
21
+ handle?: React.ReactNode;
22
+ open?: boolean;
23
+ defaultOpen?: boolean;
24
+ onOpenChange?: (open: boolean) => void;
25
+ expandTo: SgExpandablePanelDirection;
26
+ placement?: SgExpandablePanelPlacement;
27
+ mode?: SgExpandablePanelMode;
28
+ size?: SgExpandablePanelSize;
29
+ resizable?: boolean;
30
+ onSizeChange?: (size: number | string) => void;
31
+ closeOnOutsideClick?: boolean;
32
+ closeOnEsc?: boolean;
33
+ trapFocus?: boolean;
34
+ showBackdrop?: boolean;
35
+ animation?: SgExpandablePanelAnimation;
36
+ elevation?: SgExpandablePanelElevation;
37
+ border?: boolean;
38
+ rounded?: SgExpandablePanelRounded;
39
+ ariaLabel?: string;
40
+ role?: SgExpandablePanelRole;
41
+ className?: string;
42
+ contentClassName?: string;
43
+ headerClassName?: string;
44
+ bodyClassName?: string;
45
+ footerClassName?: string;
46
+ overlayClassName?: string;
47
+ style?: React.CSSProperties;
48
+ };
49
+ export declare const SgExpandablePanel: React.ForwardRefExoticComponent<SgExpandablePanelProps & React.RefAttributes<HTMLDivElement>>;
50
+ //# sourceMappingURL=SgExpandablePanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SgExpandablePanel.d.ts","sourceRoot":"","sources":["../../src/layout/SgExpandablePanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,MAAM,0BAA0B,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAC7E,MAAM,MAAM,0BAA0B,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AACpE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,SAAS,CAAC;AACzD,MAAM,MAAM,0BAA0B,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACrE,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACnE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAExD,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAEvC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,SAAS,CAAC,EAAE,0BAA0B,CAAC;IACvC,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAE7B,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IAE/C,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,SAAS,CAAC,EAAE,0BAA0B,CAAC;IAEvC,SAAS,CAAC,EAAE,0BAA0B,CAAC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,wBAAwB,CAAC;IAEnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAE7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AA6DF,eAAO,MAAM,iBAAiB,+FA4Y7B,CAAC"}
@@ -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";