@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.
Files changed (140) 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/digits/discard-digit/SgDiscardDigit.d.ts +39 -0
  10. package/dist/digits/discard-digit/SgDiscardDigit.d.ts.map +1 -0
  11. package/dist/digits/discard-digit/SgDiscardDigit.js +303 -0
  12. package/dist/digits/discard-digit/index.d.ts +3 -0
  13. package/dist/digits/discard-digit/index.d.ts.map +1 -0
  14. package/dist/digits/discard-digit/index.js +1 -0
  15. package/dist/digits/fade-digit/SgFadeDigit.d.ts +27 -0
  16. package/dist/digits/fade-digit/SgFadeDigit.d.ts.map +1 -0
  17. package/dist/digits/fade-digit/SgFadeDigit.js +85 -0
  18. package/dist/digits/fade-digit/index.d.ts +3 -0
  19. package/dist/digits/fade-digit/index.d.ts.map +1 -0
  20. package/dist/digits/fade-digit/index.js +1 -0
  21. package/dist/digits/flip-digit/SgFlipDigit.d.ts +27 -0
  22. package/dist/digits/flip-digit/SgFlipDigit.d.ts.map +1 -0
  23. package/dist/digits/flip-digit/SgFlipDigit.js +70 -0
  24. package/dist/digits/flip-digit/index.d.ts.map +1 -0
  25. package/dist/digits/matrix-digit/SgMatrixDigit.d.ts +32 -0
  26. package/dist/digits/matrix-digit/SgMatrixDigit.d.ts.map +1 -0
  27. package/dist/digits/matrix-digit/SgMatrixDigit.js +86 -0
  28. package/dist/digits/matrix-digit/index.d.ts +3 -0
  29. package/dist/digits/matrix-digit/index.d.ts.map +1 -0
  30. package/dist/digits/matrix-digit/index.js +1 -0
  31. package/dist/digits/neon-digit/SgNeonDigit.d.ts +37 -0
  32. package/dist/digits/neon-digit/SgNeonDigit.d.ts.map +1 -0
  33. package/dist/digits/neon-digit/SgNeonDigit.js +59 -0
  34. package/dist/digits/neon-digit/index.d.ts +3 -0
  35. package/dist/digits/neon-digit/index.d.ts.map +1 -0
  36. package/dist/digits/neon-digit/index.js +1 -0
  37. package/dist/digits/roller3d-digit/SgRoller3DDigit.d.ts +37 -0
  38. package/dist/digits/roller3d-digit/SgRoller3DDigit.d.ts.map +1 -0
  39. package/dist/digits/roller3d-digit/SgRoller3DDigit.js +47 -0
  40. package/dist/digits/roller3d-digit/index.d.ts +3 -0
  41. package/dist/digits/roller3d-digit/index.d.ts.map +1 -0
  42. package/dist/digits/roller3d-digit/index.js +1 -0
  43. package/dist/environment/SgEnvironmentProvider.d.ts +1 -0
  44. package/dist/environment/SgEnvironmentProvider.d.ts.map +1 -1
  45. package/dist/environment/SgEnvironmentProvider.js +51 -12
  46. package/dist/gadgets/clock/SgClock.d.ts +3 -1
  47. package/dist/gadgets/clock/SgClock.d.ts.map +1 -1
  48. package/dist/gadgets/clock/SgClock.js +111 -180
  49. package/dist/gadgets/clock/SgTimeProvider.d.ts +1 -0
  50. package/dist/gadgets/clock/SgTimeProvider.d.ts.map +1 -1
  51. package/dist/gadgets/clock/SgTimeProvider.js +11 -4
  52. package/dist/gadgets/gauge/SgLinearGauge.d.ts +59 -0
  53. package/dist/gadgets/gauge/SgLinearGauge.d.ts.map +1 -0
  54. package/dist/gadgets/gauge/SgLinearGauge.js +258 -0
  55. package/dist/gadgets/gauge/SgRadialGauge.d.ts +73 -0
  56. package/dist/gadgets/gauge/SgRadialGauge.d.ts.map +1 -0
  57. package/dist/gadgets/gauge/SgRadialGauge.js +311 -0
  58. package/dist/gadgets/gauge/index.d.ts +5 -0
  59. package/dist/gadgets/gauge/index.d.ts.map +1 -0
  60. package/dist/gadgets/gauge/index.js +2 -0
  61. package/dist/gadgets/string-animator/SgStringAnimator.d.ts +91 -0
  62. package/dist/gadgets/string-animator/SgStringAnimator.d.ts.map +1 -0
  63. package/dist/gadgets/string-animator/SgStringAnimator.js +145 -0
  64. package/dist/gadgets/string-animator/index.d.ts +3 -0
  65. package/dist/gadgets/string-animator/index.d.ts.map +1 -0
  66. package/dist/gadgets/string-animator/index.js +1 -0
  67. package/dist/i18n/en-US.json +9 -1
  68. package/dist/i18n/es.json +55 -47
  69. package/dist/i18n/index.d.ts +32 -0
  70. package/dist/i18n/index.d.ts.map +1 -1
  71. package/dist/i18n/pt-BR.json +9 -1
  72. package/dist/i18n/pt-PT.json +9 -1
  73. package/dist/index.d.ts +46 -4
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +22 -1
  76. package/dist/inputs/SgAutocomplete.js +21 -5
  77. package/dist/inputs/SgCombobox.d.ts.map +1 -1
  78. package/dist/inputs/SgCombobox.js +8 -3
  79. package/dist/inputs/SgRadioGroup.d.ts +37 -0
  80. package/dist/inputs/SgRadioGroup.d.ts.map +1 -0
  81. package/dist/inputs/SgRadioGroup.js +139 -0
  82. package/dist/inputs/SgRating.d.ts +55 -0
  83. package/dist/inputs/SgRating.d.ts.map +1 -0
  84. package/dist/inputs/SgRating.js +135 -0
  85. package/dist/inputs/SgSlider.d.ts +20 -0
  86. package/dist/inputs/SgSlider.d.ts.map +1 -0
  87. package/dist/inputs/SgSlider.js +40 -0
  88. package/dist/inputs/SgStepperInput.d.ts +22 -0
  89. package/dist/inputs/SgStepperInput.d.ts.map +1 -0
  90. package/dist/inputs/SgStepperInput.js +51 -0
  91. package/dist/inputs/SgTextEditor.d.ts +1 -0
  92. package/dist/inputs/SgTextEditor.d.ts.map +1 -1
  93. package/dist/inputs/SgTextEditor.js +19 -3
  94. package/dist/layout/SgAccordion.d.ts +39 -0
  95. package/dist/layout/SgAccordion.d.ts.map +1 -0
  96. package/dist/layout/SgAccordion.js +116 -0
  97. package/dist/layout/SgBreadcrumb.d.ts +33 -0
  98. package/dist/layout/SgBreadcrumb.d.ts.map +1 -0
  99. package/dist/layout/SgBreadcrumb.js +121 -0
  100. package/dist/layout/SgCarousel.d.ts +43 -0
  101. package/dist/layout/SgCarousel.d.ts.map +1 -0
  102. package/dist/layout/SgCarousel.js +166 -0
  103. package/dist/layout/SgDockLayout.d.ts +14 -0
  104. package/dist/layout/SgDockLayout.d.ts.map +1 -1
  105. package/dist/layout/SgDockLayout.js +145 -13
  106. package/dist/layout/SgDockScreen.d.ts +15 -0
  107. package/dist/layout/SgDockScreen.d.ts.map +1 -0
  108. package/dist/layout/SgDockScreen.js +13 -0
  109. package/dist/layout/SgDockZone.d.ts.map +1 -1
  110. package/dist/layout/SgDockZone.js +36 -2
  111. package/dist/layout/SgExpandablePanel.d.ts +50 -0
  112. package/dist/layout/SgExpandablePanel.d.ts.map +1 -0
  113. package/dist/layout/SgExpandablePanel.js +302 -0
  114. package/dist/layout/SgMainPanel.d.ts.map +1 -1
  115. package/dist/layout/SgMainPanel.js +36 -14
  116. package/dist/layout/SgMenu.d.ts +91 -0
  117. package/dist/layout/SgMenu.d.ts.map +1 -0
  118. package/dist/layout/SgMenu.js +939 -0
  119. package/dist/layout/SgPageControl.d.ts +49 -0
  120. package/dist/layout/SgPageControl.d.ts.map +1 -0
  121. package/dist/layout/SgPageControl.js +152 -0
  122. package/dist/layout/SgPanel.d.ts.map +1 -1
  123. package/dist/layout/SgPanel.js +10 -1
  124. package/dist/layout/SgScreen.d.ts +2 -0
  125. package/dist/layout/SgScreen.d.ts.map +1 -1
  126. package/dist/layout/SgScreen.js +4 -2
  127. package/dist/layout/SgToolBar.d.ts +9 -3
  128. package/dist/layout/SgToolBar.d.ts.map +1 -1
  129. package/dist/layout/SgToolBar.js +461 -55
  130. package/dist/menus/SgDockMenu.d.ts +62 -0
  131. package/dist/menus/SgDockMenu.d.ts.map +1 -0
  132. package/dist/menus/SgDockMenu.js +480 -0
  133. package/dist/others/SgPlayground.js +72 -72
  134. package/package.json +72 -63
  135. package/dist/gadgets/flip-digit/SgFlipDigit.d.ts +0 -23
  136. package/dist/gadgets/flip-digit/SgFlipDigit.d.ts.map +0 -1
  137. package/dist/gadgets/flip-digit/SgFlipDigit.js +0 -118
  138. package/dist/gadgets/flip-digit/index.d.ts.map +0 -1
  139. /package/dist/{gadgets → digits}/flip-digit/index.d.ts +0 -0
  140. /package/dist/{gadgets → digits}/flip-digit/index.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"SgFloatActionButton.d.ts","sourceRoot":"","sources":["../../src/buttons/SgFloatActionButton.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SgFloatActionButton.d.ts","sourceRoot":"","sources":["../../src/buttons/SgFloatActionButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAuC/B,MAAM,MAAM,WAAW,GACnB,UAAU,GAAG,aAAa,GAAG,aAAa,GAC1C,YAAY,GAAG,eAAe,GAC9B,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;AAElD,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,WAAW,GACX,SAAS,GACT,MAAM,GACN,SAAS,GACT,MAAM,GACN,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC;AACrC,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACzC,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AACvD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACvD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AACpF,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAC9D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,GAAG,gBAAgB,CAAC;AAEnF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,CAAC;IAEvB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,MAAM,CAAC,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,WAAW,CAAC;IAEvB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC7C,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA6NF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,wBAAwB,CAAC,2CAwhB5E;yBAxhBe,mBAAmB"}
@@ -3,10 +3,33 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { t, useComponentsI18n } from "../i18n";
5
5
  import { SgPopup } from "../overlay/SgPopup";
6
+ import { useHasSgEnvironmentProvider, useSgPersistence } from "../environment/SgEnvironmentProvider";
6
7
  /* ── helpers ── */
7
8
  function cn(...parts) {
8
9
  return parts.filter(Boolean).join(" ");
9
10
  }
11
+ function parseStoredDragPosition(raw) {
12
+ const value = typeof raw === "string" ? (() => {
13
+ try {
14
+ return JSON.parse(raw);
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ })() : raw;
20
+ if (!value ||
21
+ typeof value !== "object" ||
22
+ typeof value.x !== "number" ||
23
+ typeof value.y !== "number" ||
24
+ !Number.isFinite(value.x) ||
25
+ !Number.isFinite(value.y)) {
26
+ return null;
27
+ }
28
+ return {
29
+ x: value.x,
30
+ y: value.y
31
+ };
32
+ }
10
33
  /* ── constants ── */
11
34
  const EDGE = 24;
12
35
  const POS_CSS = {
@@ -177,9 +200,20 @@ function slideInit(pos) {
177
200
  return "translateX(-24px)";
178
201
  return "translateX(24px)";
179
202
  }
203
+ function slideNudge(pos, dist = 10) {
204
+ if (pos.endsWith("bottom"))
205
+ return `translateY(${dist}px)`;
206
+ if (pos.endsWith("top"))
207
+ return `translateY(-${dist}px)`;
208
+ if (pos.startsWith("left"))
209
+ return `translateX(-${dist}px)`;
210
+ return `translateX(${dist}px)`;
211
+ }
180
212
  /* ── component ── */
181
213
  export function SgFloatActionButton(props) {
182
214
  const i18n = useComponentsI18n();
215
+ const hasEnvironmentProvider = useHasSgEnvironmentProvider();
216
+ const { load: loadPersistedState, save: savePersistedState, clear: clearPersistedState } = useSgPersistence();
183
217
  const { hint, hintDelay = 300, icon, activeIcon, position = "right-bottom", offset, enableDragDrop = false, dragId, severity = "primary", variant, color, size = "md", shape = "circle", elevation = "md", disabled = false, loading = false, autoHideOnScroll = false, hideDirection = "down", animation = "scale", animationOn = "mount", animationDuration = 200, type = "linear", radius, transitionDelay = 30, actions, onClick, className, style, zIndex = 50, absolute = false, } = props;
184
218
  const hintPos = props.hintPosition ?? DEFAULT_HINT[position];
185
219
  const dir = props.direction ?? DEFAULT_DIR[position];
@@ -199,7 +233,81 @@ export function SgFloatActionButton(props) {
199
233
  const containerRef = React.useRef(null);
200
234
  const fabBtnRef = React.useRef(null);
201
235
  const hintTimer = React.useRef(null);
236
+ const dragCleanupRef = React.useRef(null);
202
237
  const isAbsolute = absolute === true;
238
+ const storageKey = dragId ? `sg-fab-pos:${dragId}` : null;
239
+ const loadStoredPosition = React.useCallback(async () => {
240
+ if (!storageKey)
241
+ return null;
242
+ if (hasEnvironmentProvider) {
243
+ try {
244
+ const loaded = await loadPersistedState(storageKey);
245
+ if (loaded === null || loaded === undefined)
246
+ return null;
247
+ const parsed = parseStoredDragPosition(loaded);
248
+ if (!parsed) {
249
+ await clearPersistedState(storageKey);
250
+ return null;
251
+ }
252
+ return parsed;
253
+ }
254
+ catch {
255
+ return null;
256
+ }
257
+ }
258
+ try {
259
+ const raw = localStorage.getItem(storageKey);
260
+ if (!raw)
261
+ return null;
262
+ const parsed = parseStoredDragPosition(raw);
263
+ if (!parsed) {
264
+ localStorage.removeItem(storageKey);
265
+ return null;
266
+ }
267
+ return parsed;
268
+ }
269
+ catch {
270
+ return null;
271
+ }
272
+ }, [clearPersistedState, hasEnvironmentProvider, loadPersistedState, storageKey]);
273
+ const saveStoredPosition = React.useCallback(async (nextPos) => {
274
+ if (!storageKey)
275
+ return;
276
+ if (hasEnvironmentProvider) {
277
+ try {
278
+ await savePersistedState(storageKey, nextPos);
279
+ }
280
+ catch {
281
+ // ignore
282
+ }
283
+ return;
284
+ }
285
+ try {
286
+ localStorage.setItem(storageKey, JSON.stringify(nextPos));
287
+ }
288
+ catch {
289
+ // ignore
290
+ }
291
+ }, [hasEnvironmentProvider, savePersistedState, storageKey]);
292
+ const clearStoredPosition = React.useCallback(async () => {
293
+ if (!storageKey)
294
+ return;
295
+ if (hasEnvironmentProvider) {
296
+ try {
297
+ await clearPersistedState(storageKey);
298
+ }
299
+ catch {
300
+ // ignore
301
+ }
302
+ return;
303
+ }
304
+ try {
305
+ localStorage.removeItem(storageKey);
306
+ }
307
+ catch {
308
+ // ignore
309
+ }
310
+ }, [clearPersistedState, hasEnvironmentProvider, storageKey]);
203
311
  React.useEffect(() => { const t = setTimeout(() => setMounted(true), 20); return () => clearTimeout(t); }, []);
204
312
  React.useEffect(() => {
205
313
  if (!clicked)
@@ -228,19 +336,11 @@ export function SgFloatActionButton(props) {
228
336
  React.useEffect(() => {
229
337
  if (!enableDragDrop || !dragId)
230
338
  return;
231
- try {
232
- const stored = localStorage.getItem(`sg-fab-pos:${dragId}`);
233
- if (!stored)
234
- return;
235
- const parsed = JSON.parse(stored);
236
- if (!parsed ||
237
- typeof parsed.x !== "number" ||
238
- typeof parsed.y !== "number" ||
239
- !Number.isFinite(parsed.x) ||
240
- !Number.isFinite(parsed.y)) {
241
- localStorage.removeItem(`sg-fab-pos:${dragId}`);
339
+ let alive = true;
340
+ (async () => {
341
+ const parsed = await loadStoredPosition();
342
+ if (!alive || !parsed)
242
343
  return;
243
- }
244
344
  const px = parsed.x;
245
345
  const py = parsed.y;
246
346
  const wh = BTN_WH[size];
@@ -261,11 +361,11 @@ export function SgFloatActionButton(props) {
261
361
  dragPosRef.current = clamped;
262
362
  setDragPos(clamped);
263
363
  hasStoredPosRef.current = true;
264
- }
265
- catch {
266
- // ignore
267
- }
268
- }, [enableDragDrop, dragId, size, isAbsolute]);
364
+ })();
365
+ return () => {
366
+ alive = false;
367
+ };
368
+ }, [enableDragDrop, dragId, loadStoredPosition, size, isAbsolute]);
269
369
  React.useEffect(() => {
270
370
  if (!open)
271
371
  return;
@@ -279,6 +379,12 @@ export function SgFloatActionButton(props) {
279
379
  document.addEventListener("keydown", onKey);
280
380
  return () => { document.removeEventListener("mousedown", onMd); document.removeEventListener("keydown", onKey); };
281
381
  }, [open]);
382
+ React.useEffect(() => {
383
+ return () => {
384
+ dragCleanupRef.current?.();
385
+ dragCleanupRef.current = null;
386
+ };
387
+ }, []);
282
388
  const onEnter = React.useCallback(() => {
283
389
  setHovered(true);
284
390
  if (hint)
@@ -314,7 +420,11 @@ export function SgFloatActionButton(props) {
314
420
  return;
315
421
  if (!containerRef.current)
316
422
  return;
423
+ dragCleanupRef.current?.();
424
+ dragCleanupRef.current = null;
317
425
  event.preventDefault();
426
+ const doc = event.currentTarget.ownerDocument ?? document;
427
+ const view = doc.defaultView ?? window;
318
428
  const rect = containerRef.current.getBoundingClientRect();
319
429
  const parent = isAbsolute
320
430
  ? (containerRef.current.offsetParent?.getBoundingClientRect() ?? {
@@ -348,25 +458,38 @@ export function SgFloatActionButton(props) {
348
458
  setDragPos(nextPos);
349
459
  hasStoredPosRef.current = true;
350
460
  };
351
- const handleUp = () => {
461
+ let finalized = false;
462
+ const finalizeDrag = () => {
463
+ if (finalized)
464
+ return;
465
+ finalized = true;
352
466
  setIsDragging(false);
353
467
  dragStart.current = null;
354
468
  if (enableDragDrop && dragId && dragPosRef.current) {
355
- try {
356
- localStorage.setItem(`sg-fab-pos:${dragId}`, JSON.stringify(dragPosRef.current));
357
- }
358
- catch {
359
- // ignore
360
- }
469
+ void saveStoredPosition(dragPosRef.current);
470
+ }
471
+ view.removeEventListener("pointermove", handleMove);
472
+ view.removeEventListener("pointerup", handleUp);
473
+ view.removeEventListener("pointercancel", handleUp);
474
+ view.removeEventListener("blur", handleUp);
475
+ doc.removeEventListener("visibilitychange", handleVisibilityChange);
476
+ if (dragCleanupRef.current === finalizeDrag) {
477
+ dragCleanupRef.current = null;
478
+ }
479
+ };
480
+ const handleUp = () => finalizeDrag();
481
+ const handleVisibilityChange = () => {
482
+ if (doc.visibilityState === "hidden") {
483
+ finalizeDrag();
361
484
  }
362
- window.removeEventListener("pointermove", handleMove);
363
- window.removeEventListener("pointerup", handleUp);
364
- window.removeEventListener("pointercancel", handleUp);
365
485
  };
366
- window.addEventListener("pointermove", handleMove);
367
- window.addEventListener("pointerup", handleUp);
368
- window.addEventListener("pointercancel", handleUp);
369
- }, [enableDragDrop, disabled, loading, actions, dragId, isAbsolute]);
486
+ dragCleanupRef.current = finalizeDrag;
487
+ view.addEventListener("pointermove", handleMove);
488
+ view.addEventListener("pointerup", handleUp);
489
+ view.addEventListener("pointercancel", handleUp);
490
+ view.addEventListener("blur", handleUp);
491
+ doc.addEventListener("visibilitychange", handleVisibilityChange);
492
+ }, [enableDragDrop, disabled, loading, actions, dragId, isAbsolute, saveStoredPosition]);
370
493
  const handleContextMenu = React.useCallback((event) => {
371
494
  if (!enableDragDrop || !dragId)
372
495
  return;
@@ -380,19 +503,14 @@ export function SgFloatActionButton(props) {
380
503
  setMenuOpen(false);
381
504
  return;
382
505
  }
383
- try {
384
- localStorage.removeItem(`sg-fab-pos:${dragId}`);
385
- }
386
- catch (error) {
387
- // ignore
388
- }
506
+ void clearStoredPosition();
389
507
  dragPosRef.current = null;
390
508
  setDragPos(null);
391
509
  setOpen(false);
392
510
  setMenuOpen(false);
393
511
  hasStoredPosRef.current = false;
394
512
  dragMoved.current = false;
395
- }, [dragId]);
513
+ }, [clearStoredPosition, dragId]);
396
514
  /* colors */
397
515
  const resolvedSeverity = severity ?? variant ?? "primary";
398
516
  const c = COLORS[resolvedSeverity];
@@ -465,6 +583,12 @@ export function SgFloatActionButton(props) {
465
583
  case "scale":
466
584
  anim.transform = hovered ? "scale(1.1)" : "scale(1)";
467
585
  break;
586
+ case "fade":
587
+ anim.opacity = hovered ? 0.62 : 1;
588
+ break;
589
+ case "slide":
590
+ anim.transform = hovered ? slideNudge(position, 10) : "translate(0,0)";
591
+ break;
468
592
  case "rotate":
469
593
  anim.transform = hovered ? "rotate(15deg)" : "rotate(0deg)";
470
594
  break;
@@ -479,6 +603,12 @@ export function SgFloatActionButton(props) {
479
603
  case "scale":
480
604
  anim.transform = clicked ? "scale(0.9)" : "scale(1)";
481
605
  break;
606
+ case "fade":
607
+ anim.opacity = clicked ? 0.52 : 1;
608
+ break;
609
+ case "slide":
610
+ anim.transform = clicked ? slideNudge(position, 14) : "translate(0,0)";
611
+ break;
482
612
  case "rotate":
483
613
  anim.transform = clicked ? "rotate(90deg)" : "rotate(0deg)";
484
614
  break;
@@ -0,0 +1,66 @@
1
+ import * as React from "react";
2
+ export type SgAvatarSeverity = "primary" | "secondary" | "success" | "warning" | "danger" | "info" | "neutral" | "custom";
3
+ export type SgAvatarShape = "circle" | "square";
4
+ export type SgAvatarSize = "xs" | "sm" | "md" | "lg" | "xl";
5
+ export type SgAvatarCustomColors = {
6
+ bg?: string;
7
+ fg?: string;
8
+ border?: string;
9
+ ring?: string;
10
+ };
11
+ export type SgAvatarProps = Omit<React.HTMLAttributes<HTMLSpanElement>, "children" | "color"> & {
12
+ src?: string;
13
+ alt?: string;
14
+ label?: React.ReactNode;
15
+ icon?: React.ReactNode;
16
+ fallback?: React.ReactNode;
17
+ size?: SgAvatarSize;
18
+ shape?: SgAvatarShape;
19
+ severity?: SgAvatarSeverity;
20
+ bordered?: boolean;
21
+ disabled?: boolean;
22
+ customColors?: SgAvatarCustomColors;
23
+ imageClassName?: string;
24
+ children?: React.ReactNode;
25
+ onImageError?: (event: React.SyntheticEvent<HTMLImageElement, Event>) => void;
26
+ };
27
+ export type SgAvatarGroupOverlap = "none" | "sm" | "md" | "lg";
28
+ export type SgAvatarGroupProps = Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
29
+ children: React.ReactNode;
30
+ max?: number;
31
+ total?: number;
32
+ overlap?: SgAvatarGroupOverlap;
33
+ moreSeverity?: SgAvatarSeverity;
34
+ moreLabel?: (remaining: number) => React.ReactNode;
35
+ size?: SgAvatarSize;
36
+ shape?: SgAvatarShape;
37
+ bordered?: boolean;
38
+ };
39
+ export declare const SgAvatar: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLSpanElement>, "color" | "children"> & {
40
+ src?: string;
41
+ alt?: string;
42
+ label?: React.ReactNode;
43
+ icon?: React.ReactNode;
44
+ fallback?: React.ReactNode;
45
+ size?: SgAvatarSize;
46
+ shape?: SgAvatarShape;
47
+ severity?: SgAvatarSeverity;
48
+ bordered?: boolean;
49
+ disabled?: boolean;
50
+ customColors?: SgAvatarCustomColors;
51
+ imageClassName?: string;
52
+ children?: React.ReactNode;
53
+ onImageError?: (event: React.SyntheticEvent<HTMLImageElement, Event>) => void;
54
+ } & React.RefAttributes<HTMLSpanElement>>;
55
+ export declare const SgAvatarGroup: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
56
+ children: React.ReactNode;
57
+ max?: number;
58
+ total?: number;
59
+ overlap?: SgAvatarGroupOverlap;
60
+ moreSeverity?: SgAvatarSeverity;
61
+ moreLabel?: (remaining: number) => React.ReactNode;
62
+ size?: SgAvatarSize;
63
+ shape?: SgAvatarShape;
64
+ bordered?: boolean;
65
+ } & React.RefAttributes<HTMLDivElement>>;
66
+ //# sourceMappingURL=SgAvatar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SgAvatar.d.ts","sourceRoot":"","sources":["../../src/commons/SgAvatar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ function cn(...parts) {
5
+ return parts.filter(Boolean).join(" ");
6
+ }
7
+ const SIZE = {
8
+ xs: { box: "size-6", text: "text-[11px]", icon: "size-3.5" },
9
+ sm: { box: "size-8", text: "text-xs", icon: "size-4" },
10
+ md: { box: "size-10", text: "text-sm", icon: "size-5" },
11
+ lg: { box: "size-14", text: "text-lg", icon: "size-7" },
12
+ xl: { box: "size-20", text: "text-2xl", icon: "size-9" }
13
+ };
14
+ const GROUP_OVERLAP = {
15
+ none: "",
16
+ sm: "-ml-1",
17
+ md: "-ml-2",
18
+ lg: "-ml-3"
19
+ };
20
+ const PRESET = {
21
+ primary: {
22
+ bg: "hsl(var(--primary))",
23
+ fg: "hsl(var(--primary-foreground))",
24
+ border: "hsl(var(--primary))",
25
+ ring: "hsl(var(--ring, var(--primary)))"
26
+ },
27
+ secondary: {
28
+ bg: "hsl(var(--secondary))",
29
+ fg: "hsl(var(--secondary-foreground))",
30
+ border: "hsl(var(--secondary))",
31
+ ring: "hsl(var(--ring, var(--secondary)))"
32
+ },
33
+ success: {
34
+ bg: "hsl(var(--tertiary, var(--accent, var(--primary))))",
35
+ fg: "hsl(var(--tertiary-foreground, var(--accent-foreground, var(--primary-foreground))))",
36
+ border: "hsl(var(--tertiary, var(--accent, var(--primary))))",
37
+ ring: "hsl(var(--ring, var(--tertiary, var(--accent, var(--primary)))))"
38
+ },
39
+ warning: {
40
+ bg: "hsl(var(--accent, var(--secondary, var(--primary))))",
41
+ fg: "hsl(var(--accent-foreground, var(--secondary-foreground, var(--primary-foreground))))",
42
+ border: "hsl(var(--accent, var(--secondary, var(--primary))))",
43
+ ring: "hsl(var(--ring, var(--accent, var(--secondary, var(--primary)))))"
44
+ },
45
+ danger: {
46
+ bg: "hsl(var(--destructive))",
47
+ fg: "hsl(var(--destructive-foreground))",
48
+ border: "hsl(var(--destructive))",
49
+ ring: "hsl(var(--ring, var(--destructive)))"
50
+ },
51
+ info: {
52
+ bg: "hsl(var(--secondary, var(--primary)))",
53
+ fg: "hsl(var(--secondary-foreground, var(--primary-foreground)))",
54
+ border: "hsl(var(--secondary, var(--primary)))",
55
+ ring: "hsl(var(--ring, var(--secondary, var(--primary))))"
56
+ },
57
+ neutral: {
58
+ bg: "hsl(var(--muted))",
59
+ fg: "hsl(var(--muted-foreground))",
60
+ border: "hsl(var(--border))",
61
+ ring: "hsl(var(--ring, var(--muted)))"
62
+ }
63
+ };
64
+ function resolveAvatarColors(severity, custom) {
65
+ const base = severity === "custom" ? PRESET.primary : PRESET[severity];
66
+ return {
67
+ bg: custom?.bg ?? base.bg,
68
+ fg: custom?.fg ?? base.fg,
69
+ border: custom?.border ?? base.border,
70
+ ring: custom?.ring ?? base.ring
71
+ };
72
+ }
73
+ function buildVars(severity, custom) {
74
+ const merged = resolveAvatarColors(severity, custom);
75
+ return {
76
+ ["--sg-avatar-bg"]: merged.bg,
77
+ ["--sg-avatar-fg"]: merged.fg,
78
+ ["--sg-avatar-border"]: merged.border,
79
+ ["--sg-avatar-ring"]: merged.ring
80
+ };
81
+ }
82
+ function hasRenderable(value) {
83
+ if (value === null || value === undefined || value === false)
84
+ return false;
85
+ if (typeof value === "string")
86
+ return value.trim().length > 0;
87
+ return true;
88
+ }
89
+ function normalizeLabel(label) {
90
+ if (typeof label !== "string")
91
+ return label;
92
+ const trimmed = label.trim();
93
+ if (!trimmed)
94
+ return "";
95
+ if (trimmed.length <= 2)
96
+ return trimmed.toUpperCase();
97
+ const words = trimmed.split(/\s+/).filter(Boolean);
98
+ if (words.length >= 2) {
99
+ return `${words[0]?.[0] ?? ""}${words[1]?.[0] ?? ""}`.toUpperCase();
100
+ }
101
+ return trimmed.slice(0, 2).toUpperCase();
102
+ }
103
+ export const SgAvatar = React.forwardRef(({ src, alt = "Avatar", label, icon, fallback, size = "md", shape = "circle", severity = "primary", bordered = true, disabled = false, customColors, className, imageClassName, children, onImageError, onClick, role, tabIndex, style, title, ["aria-label"]: ariaLabel, ...rest }, ref) => {
104
+ const [imageFailed, setImageFailed] = React.useState(false);
105
+ const s = SIZE[size];
106
+ React.useEffect(() => {
107
+ setImageFailed(false);
108
+ }, [src]);
109
+ const hasChildren = hasRenderable(children);
110
+ const showImage = !hasChildren && !!src && !imageFailed;
111
+ const showIcon = !hasChildren && !showImage && hasRenderable(icon);
112
+ const showLabel = !hasChildren && !showImage && !showIcon && hasRenderable(label);
113
+ const interactive = typeof onClick === "function" || role === "button" || typeof tabIndex === "number";
114
+ const resolvedAriaLabel = ariaLabel ?? (typeof label === "string" ? label : alt);
115
+ const squareRadius = size === "xs" || size === "sm" ? "rounded-md" : "rounded-xl";
116
+ return (_jsx("span", { ref: ref, title: title, role: role, tabIndex: tabIndex, onClick: disabled ? undefined : onClick, "aria-label": resolvedAriaLabel, style: { ...buildVars(severity, customColors), ...style }, className: cn("relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden", "font-medium leading-none", s.box, s.text, shape === "circle" ? "rounded-full" : squareRadius, bordered ? "border border-[var(--sg-avatar-border)]" : "border border-transparent", showImage ? "bg-muted text-transparent" : "bg-[var(--sg-avatar-bg)] text-[var(--sg-avatar-fg)]", interactive
117
+ ? "cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--sg-avatar-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background"
118
+ : "", disabled ? "pointer-events-none opacity-55" : "", className), ...rest, children: hasChildren ? (children) : showImage ? (_jsx("img", { src: src, alt: alt, loading: "lazy", draggable: false, className: cn("size-full object-cover", imageClassName), onError: (event) => {
119
+ setImageFailed(true);
120
+ onImageError?.(event);
121
+ } })) : showIcon ? (_jsx("span", { className: cn("inline-flex items-center justify-center", s.icon), children: icon })) : showLabel ? (_jsx("span", { className: "uppercase", children: normalizeLabel(label) })) : (_jsx("span", { className: cn("inline-flex items-center justify-center", s.icon), children: hasRenderable(fallback) ? fallback : "?" })) }));
122
+ });
123
+ SgAvatar.displayName = "SgAvatar";
124
+ export const SgAvatarGroup = React.forwardRef(({ children, max, total, overlap = "md", moreSeverity = "neutral", moreLabel, size = "md", shape = "circle", bordered = true, className, ...rest }, ref) => {
125
+ const avatars = React.Children.toArray(children).filter((item) => item !== null && item !== undefined);
126
+ const normalizedMax = typeof max === "number" && Number.isFinite(max) && max > 0 ? Math.floor(max) : undefined;
127
+ const visibleCount = normalizedMax ? Math.min(normalizedMax, avatars.length) : avatars.length;
128
+ const visible = avatars.slice(0, visibleCount);
129
+ const calculatedTotal = Math.max(total ?? avatars.length, avatars.length);
130
+ const hiddenCount = Math.max(calculatedTotal - visibleCount, 0);
131
+ return (_jsxs("div", { ref: ref, className: cn("inline-flex items-center", className), ...rest, children: [visible.map((child, index) => {
132
+ const key = React.isValidElement(child) && child.key != null ? String(child.key) : `sg-avatar-${index}`;
133
+ return (_jsx("span", { className: cn("inline-flex", index === 0 ? "" : GROUP_OVERLAP[overlap]), children: child }, key));
134
+ }), hiddenCount > 0 ? (_jsx("span", { className: cn("inline-flex", visibleCount === 0 ? "" : GROUP_OVERLAP[overlap]), children: _jsx(SgAvatar, { label: moreLabel ? moreLabel(hiddenCount) : `+${hiddenCount}`, size: size, shape: shape, severity: moreSeverity, bordered: bordered }) })) : null] }));
135
+ });
136
+ SgAvatarGroup.displayName = "SgAvatarGroup";
@@ -0,0 +1,16 @@
1
+ import * as React from "react";
2
+ export type SgSkeletonShape = "text" | "rectangle" | "rounded" | "square" | "circle";
3
+ export type SgSkeletonAnimation = "wave" | "pulse" | "none";
4
+ export type SgSkeletonProps = Omit<React.HTMLAttributes<HTMLDivElement>, "children"> & {
5
+ width?: number | string;
6
+ height?: number | string;
7
+ size?: number | string;
8
+ borderRadius?: number | string;
9
+ shape?: SgSkeletonShape;
10
+ animation?: SgSkeletonAnimation;
11
+ };
12
+ export declare function SgSkeleton(props: Readonly<SgSkeletonProps>): import("react/jsx-runtime").JSX.Element;
13
+ export declare namespace SgSkeleton {
14
+ var displayName: string;
15
+ }
16
+ //# sourceMappingURL=SgSkeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SgSkeleton.d.ts","sourceRoot":"","sources":["../../src/commons/SgSkeleton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrF,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,GAAG;IACrF,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,2CAsF1D;yBAtFe,UAAU"}
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ function cn(...parts) {
5
+ return parts.filter(Boolean).join(" ");
6
+ }
7
+ function toCssSize(value) {
8
+ if (value === undefined || value === null)
9
+ return undefined;
10
+ return typeof value === "number" ? `${value}px` : value;
11
+ }
12
+ export function SgSkeleton(props) {
13
+ const { width, height, size, borderRadius, shape = "text", animation = "wave", className, style, ...rest } = props;
14
+ const waveOverlayRef = React.useRef(null);
15
+ React.useEffect(() => {
16
+ if (animation !== "wave")
17
+ return;
18
+ const node = waveOverlayRef.current;
19
+ if (!node || typeof node.animate !== "function")
20
+ return;
21
+ const wave = node.animate([{ transform: "translateX(-100%)" }, { transform: "translateX(100%)" }], {
22
+ duration: 1300,
23
+ iterations: Infinity,
24
+ easing: "ease-in-out"
25
+ });
26
+ return () => {
27
+ wave.cancel();
28
+ };
29
+ }, [animation]);
30
+ const cssSize = toCssSize(size);
31
+ const cssWidth = cssSize ??
32
+ toCssSize(width) ??
33
+ (shape === "square" || shape === "circle" ? "2.5rem" : "100%");
34
+ const cssHeight = cssSize ??
35
+ toCssSize(height) ??
36
+ (shape === "text" ? "1rem" : shape === "square" || shape === "circle" ? "2.5rem" : "2rem");
37
+ const cssBorderRadius = toCssSize(borderRadius) ??
38
+ (shape === "circle"
39
+ ? "9999px"
40
+ : shape === "square"
41
+ ? "0"
42
+ : shape === "rounded"
43
+ ? "0.75rem"
44
+ : shape === "text"
45
+ ? "9999px"
46
+ : "0.375rem");
47
+ return (_jsx("div", { className: cn("relative block overflow-hidden bg-muted/80", animation === "pulse" ? "animate-pulse" : "", className), style: {
48
+ width: cssWidth,
49
+ height: cssHeight,
50
+ borderRadius: cssBorderRadius,
51
+ ...style
52
+ }, ...rest, children: animation === "wave" ? (_jsx("span", { ref: waveOverlayRef, "aria-hidden": "true", className: "pointer-events-none absolute inset-0", style: {
53
+ backgroundImage: "linear-gradient(90deg, transparent 0%, hsl(var(--background) / 0.55) 50%, transparent 100%)",
54
+ transform: "translateX(-100%)",
55
+ willChange: "transform"
56
+ } })) : null }));
57
+ }
58
+ SgSkeleton.displayName = "SgSkeleton";
@@ -0,0 +1,39 @@
1
+ import * as React from "react";
2
+ export type SgDiscardDigitProps = {
3
+ /** Texto/valor exibido na folha do topo. */
4
+ value: string;
5
+ /** Cor do texto principal. */
6
+ color?: string;
7
+ /** Fonte (font-family) usada no texto. */
8
+ font?: string;
9
+ /** Cor de fundo das folhas. */
10
+ backgroundColor?: string;
11
+ /** Tamanho da fonte em px (escala geral do bloco). */
12
+ fontSize?: number;
13
+ /** Peso da fonte. */
14
+ fontWeight?: number | string;
15
+ /** Ativa animacao de descarte quando o valor muda. */
16
+ animateOnChange?: boolean;
17
+ /** Duracao total da animacao em ms. */
18
+ transitionMs?: number;
19
+ /** Quantidade de folhas visiveis na pilha (min 2, max 30). Ignorado se totalNumberPages for definido. */
20
+ stackDepth?: number;
21
+ /** Total de paginas do monte. Quando definido, a pilha visual encolhe a cada increasePage(). */
22
+ totalNumberPages?: number;
23
+ /** Estrategia de animacao para mudancas por prop `value`. */
24
+ changeAnimationMode?: "discard" | "incoming";
25
+ /** Classes CSS adicionais. */
26
+ className?: string;
27
+ /** Estilo inline adicional. */
28
+ style?: React.CSSProperties;
29
+ };
30
+ export type SgDiscardDigitHandle = {
31
+ /** Decrementa a pagina atual (minimo 1). */
32
+ decreasePage(): void;
33
+ /** Incrementa a pagina atual (maximo totalNumberPages). */
34
+ increasePage(): void;
35
+ /** Retorna a pagina atual (1-indexed). */
36
+ page(): number;
37
+ };
38
+ export declare const SgDiscardDigit: React.ForwardRefExoticComponent<SgDiscardDigitProps & React.RefAttributes<SgDiscardDigitHandle>>;
39
+ //# sourceMappingURL=SgDiscardDigit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SgDiscardDigit.d.ts","sourceRoot":"","sources":["../../../src/digits/discard-digit/SgDiscardDigit.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA4B/B,MAAM,MAAM,mBAAmB,GAAG;IAChC,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,sDAAsD;IACtD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yGAAyG;IACzG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,mBAAmB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAC7C,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,4CAA4C;IAC5C,YAAY,IAAI,IAAI,CAAC;IACrB,2DAA2D;IAC3D,YAAY,IAAI,IAAI,CAAC;IACrB,0CAA0C;IAC1C,IAAI,IAAI,MAAM,CAAC;CAChB,CAAC;AAmBF,eAAO,MAAM,cAAc,kGAkYzB,CAAC"}