@hyddenlabs/hydn-ui 0.0.1 → 0.3.0-alpha.2

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/index.cjs CHANGED
@@ -1,14 +1,14 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var React2 = require('react');
4
+ var React3 = require('react');
5
5
  var iconsReact = require('@tabler/icons-react');
6
6
  var reactRouterDom = require('react-router-dom');
7
7
  var reactDom = require('react-dom');
8
8
 
9
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
10
 
11
- var React2__default = /*#__PURE__*/_interopDefault(React2);
11
+ var React3__default = /*#__PURE__*/_interopDefault(React3);
12
12
 
13
13
  // src/components/forms/button/button.tsx
14
14
  function Button({
@@ -221,9 +221,9 @@ function Checkbox({
221
221
  }
222
222
  Checkbox.displayName = "Checkbox";
223
223
  var checkbox_default = Checkbox;
224
- var RadioGroupContext = React2.createContext(null);
224
+ var RadioGroupContext = React3.createContext(null);
225
225
  var useRadioGroup = () => {
226
- const context = React2.useContext(RadioGroupContext);
226
+ const context = React3.useContext(RadioGroupContext);
227
227
  return context;
228
228
  };
229
229
  function RadioGroup({
@@ -270,37 +270,43 @@ function Radio({
270
270
  warning: "border-warning focus:ring-warning"
271
271
  };
272
272
  const inputId = id || `radio-${value || Math.random().toString(36).slice(2)}`;
273
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex items-center justify-center relative ${disabled ? "opacity-60 cursor-not-allowed" : "cursor-pointer"}`, children: [
274
- /* @__PURE__ */ jsxRuntime.jsx(
275
- "input",
276
- {
277
- type: "radio",
278
- checked: isChecked,
279
- onChange: handleChange,
280
- disabled,
281
- "aria-label": ariaLabel,
282
- "aria-invalid": validationState === "error",
283
- id: inputId,
284
- name,
285
- value,
286
- className: "peer sr-only"
287
- }
288
- ),
289
- /* @__PURE__ */ jsxRuntime.jsx(
290
- "span",
291
- {
292
- "aria-hidden": "true",
293
- onClick: () => !disabled && document.getElementById(inputId)?.click(),
294
- className: `w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all duration-200 ease-out bg-background shadow-sm
273
+ return /* @__PURE__ */ jsxRuntime.jsxs(
274
+ "div",
275
+ {
276
+ className: `inline-flex items-center justify-center relative ${disabled ? "opacity-60 cursor-not-allowed" : "cursor-pointer"}`,
277
+ children: [
278
+ /* @__PURE__ */ jsxRuntime.jsx(
279
+ "input",
280
+ {
281
+ type: "radio",
282
+ checked: isChecked,
283
+ onChange: handleChange,
284
+ disabled,
285
+ "aria-label": ariaLabel,
286
+ "aria-invalid": validationState === "error",
287
+ id: inputId,
288
+ name,
289
+ value,
290
+ className: "peer sr-only"
291
+ }
292
+ ),
293
+ /* @__PURE__ */ jsxRuntime.jsx(
294
+ "span",
295
+ {
296
+ "aria-hidden": "true",
297
+ onClick: () => !disabled && document.getElementById(inputId)?.click(),
298
+ className: `w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all duration-200 ease-out bg-background shadow-sm
295
299
  before:content-[''] before:w-2.5 before:h-2.5 before:rounded-full before:scale-0 before:transition-transform before:duration-200 before:ease-out before:bg-primary
296
300
  peer-checked:before:scale-100 peer-checked:border-primary
297
301
  peer-focus-visible:ring-2 peer-focus-visible:ring-offset-2 peer-focus-visible:ring-ring
298
302
  peer-disabled:opacity-50 peer-disabled:cursor-not-allowed
299
303
  peer-hover:border-primary/60 peer-active:scale-95
300
304
  ${validationClasses[validationState]} ${className}`
301
- }
302
- )
303
- ] });
305
+ }
306
+ )
307
+ ]
308
+ }
309
+ );
304
310
  }
305
311
  Radio.displayName = "Radio";
306
312
  var radio_default = Radio;
@@ -361,13 +367,13 @@ function MultiSelect({
361
367
  size = "md",
362
368
  className = ""
363
369
  }) {
364
- const [isOpen, setIsOpen] = React2.useState(false);
365
- const [searchQuery, setSearchQuery] = React2.useState("");
366
- const [focusedIndex, setFocusedIndex] = React2.useState(-1);
367
- const containerRef = React2.useRef(null);
368
- const searchInputRef = React2.useRef(null);
370
+ const [isOpen, setIsOpen] = React3.useState(false);
371
+ const [searchQuery, setSearchQuery] = React3.useState("");
372
+ const [focusedIndex, setFocusedIndex] = React3.useState(-1);
373
+ const containerRef = React3.useRef(null);
374
+ const searchInputRef = React3.useRef(null);
369
375
  const selectedValues = value || [];
370
- React2.useEffect(() => {
376
+ React3.useEffect(() => {
371
377
  const handleClickOutside = (event) => {
372
378
  if (containerRef.current && !containerRef.current.contains(event.target)) {
373
379
  setIsOpen(false);
@@ -380,14 +386,12 @@ function MultiSelect({
380
386
  }
381
387
  return void 0;
382
388
  }, [isOpen]);
383
- React2.useEffect(() => {
389
+ React3.useEffect(() => {
384
390
  if (isOpen && searchInputRef.current) {
385
391
  searchInputRef.current.focus();
386
392
  }
387
393
  }, [isOpen]);
388
- const filteredOptions = options.filter(
389
- (option) => option.label.toLowerCase().includes(searchQuery.toLowerCase())
390
- );
394
+ const filteredOptions = options.filter((option) => option.label.toLowerCase().includes(searchQuery.toLowerCase()));
391
395
  const handleToggleOption = (optionValue) => {
392
396
  const isSelected = selectedValues.includes(optionValue);
393
397
  let newValues;
@@ -866,7 +870,7 @@ function FormField({
866
870
  validationState = "default"
867
871
  }) {
868
872
  const effectiveValidationState = error ? "error" : validationState;
869
- const childWithValidation = React2.isValidElement(children) ? React2.cloneElement(children, {
873
+ const childWithValidation = React3.isValidElement(children) ? React3.cloneElement(children, {
870
874
  validationState: effectiveValidationState
871
875
  }) : children;
872
876
  return /* @__PURE__ */ jsxRuntime.jsxs(stack_default, { direction: "vertical", spacing: "sm", className, children: [
@@ -891,8 +895,8 @@ function InputGroup({ children, prefix, suffix, className = "" }) {
891
895
  InputGroup.displayName = "InputGroup";
892
896
  var input_group_default = InputGroup;
893
897
  function Calendar({ value, onChange, minDate, maxDate, disabled = false, className = "" }) {
894
- const [currentMonth, setCurrentMonth] = React2.useState(value || /* @__PURE__ */ new Date());
895
- const [selectedDate, setSelectedDate] = React2.useState(value);
898
+ const [currentMonth, setCurrentMonth] = React3.useState(value || /* @__PURE__ */ new Date());
899
+ const [selectedDate, setSelectedDate] = React3.useState(value);
896
900
  const getDaysInMonth = (date) => {
897
901
  return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
898
902
  };
@@ -1028,14 +1032,14 @@ function DatePicker({
1028
1032
  className = "",
1029
1033
  size = "md"
1030
1034
  }) {
1031
- const [isOpen, setIsOpen] = React2.useState(false);
1032
- const [selectedDate, setSelectedDate] = React2.useState(value);
1033
- const containerRef = React2.useRef(null);
1034
- const inputRef = React2.useRef(null);
1035
- React2.useEffect(() => {
1035
+ const [isOpen, setIsOpen] = React3.useState(false);
1036
+ const [selectedDate, setSelectedDate] = React3.useState(value);
1037
+ const containerRef = React3.useRef(null);
1038
+ const inputRef = React3.useRef(null);
1039
+ React3.useEffect(() => {
1036
1040
  setSelectedDate(value);
1037
1041
  }, [value]);
1038
- React2.useEffect(() => {
1042
+ React3.useEffect(() => {
1039
1043
  const handleClickOutside = (event) => {
1040
1044
  if (containerRef.current && !containerRef.current.contains(event.target)) {
1041
1045
  setIsOpen(false);
@@ -1047,7 +1051,7 @@ function DatePicker({
1047
1051
  }
1048
1052
  return void 0;
1049
1053
  }, [isOpen]);
1050
- React2.useEffect(() => {
1054
+ React3.useEffect(() => {
1051
1055
  const handleEscape = (event) => {
1052
1056
  if (event.key === "Escape" && isOpen) {
1053
1057
  setIsOpen(false);
@@ -1171,15 +1175,7 @@ function DatePicker({
1171
1175
  className: "absolute left-0 top-full mt-2 z-50 animate-scaleIn origin-top",
1172
1176
  role: "dialog",
1173
1177
  "aria-label": "Calendar",
1174
- children: /* @__PURE__ */ jsxRuntime.jsx(
1175
- calendar_default,
1176
- {
1177
- value: selectedDate,
1178
- onChange: handleDateSelect,
1179
- minDate,
1180
- maxDate
1181
- }
1182
- )
1178
+ children: /* @__PURE__ */ jsxRuntime.jsx(calendar_default, { value: selectedDate, onChange: handleDateSelect, minDate, maxDate })
1183
1179
  }
1184
1180
  )
1185
1181
  ] });
@@ -1232,7 +1228,7 @@ function Navbar({
1232
1228
  border = "none",
1233
1229
  disableMobileMenu = false
1234
1230
  }) {
1235
- const [mobileMenuOpen, setMobileMenuOpen] = React2.useState(false);
1231
+ const [mobileMenuOpen, setMobileMenuOpen] = React3.useState(false);
1236
1232
  const appearanceClasses = {
1237
1233
  solid: "bg-background shadow-sm",
1238
1234
  blur: "bg-background/70 backdrop-blur-md supports-[backdrop-filter]:bg-background/60 border border-border/60",
@@ -1321,18 +1317,45 @@ function NavbarLink({ href, children, external = false, className = "", end = fa
1321
1317
  }
1322
1318
  NavbarLink.displayName = "NavbarLink";
1323
1319
  var navbar_link_default = NavbarLink;
1324
- function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1325
- const [activeTab, setActiveTab] = React2.useState(defaultTab || tabs[0]?.id);
1326
- const [isAnimating, setIsAnimating] = React2.useState(false);
1327
- const handleTabChange = (tabId) => {
1328
- if (tabId !== activeTab) {
1329
- setIsAnimating(true);
1330
- setTimeout(() => {
1331
- setActiveTab(tabId);
1332
- setIsAnimating(false);
1333
- }, 150);
1320
+ var PageTransition = ({
1321
+ children,
1322
+ duration = 300,
1323
+ type = "fade",
1324
+ className = ""
1325
+ }) => {
1326
+ const [isVisible, setIsVisible] = React3__default.default.useState(false);
1327
+ React3__default.default.useEffect(() => {
1328
+ requestAnimationFrame(() => {
1329
+ requestAnimationFrame(() => {
1330
+ setIsVisible(true);
1331
+ });
1332
+ });
1333
+ }, []);
1334
+ const getAnimationStyles = () => {
1335
+ if (type === "none") return "";
1336
+ const baseClasses = "transition-all ease-out";
1337
+ const durationClass = `duration-[${duration}ms]`;
1338
+ if (!isVisible) {
1339
+ switch (type) {
1340
+ case "fade":
1341
+ return `${baseClasses} ${durationClass} opacity-0 translate-y-1`;
1342
+ case "slide":
1343
+ return `${baseClasses} ${durationClass} opacity-0 translate-y-3`;
1344
+ case "scale":
1345
+ return `${baseClasses} ${durationClass} opacity-0 scale-[0.99]`;
1346
+ default:
1347
+ return `${baseClasses} ${durationClass} opacity-0 translate-y-1`;
1348
+ }
1349
+ } else {
1350
+ return `${baseClasses} ${durationClass} opacity-100 translate-y-0 scale-100`;
1334
1351
  }
1335
1352
  };
1353
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${getAnimationStyles()} ${className}`.trim(), children });
1354
+ };
1355
+ PageTransition.displayName = "PageTransition";
1356
+ var page_transition_default = PageTransition;
1357
+ function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1358
+ const [activeTab, setActiveTab] = React3.useState(defaultTab || tabs[0]?.id);
1336
1359
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
1337
1360
  /* @__PURE__ */ jsxRuntime.jsx("div", { role: "tablist", "aria-label": ariaLabel, className: "flex border-b-2 border-border/50", children: tabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
1338
1361
  "button",
@@ -1341,7 +1364,7 @@ function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1341
1364
  "aria-selected": activeTab === tab.id,
1342
1365
  "aria-controls": `panel-${tab.id}`,
1343
1366
  id: `tab-${tab.id}`,
1344
- onClick: () => handleTabChange(tab.id),
1367
+ onClick: () => setActiveTab(tab.id),
1345
1368
  className: `px-4 py-3 font-medium cursor-pointer transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 relative ${activeTab === tab.id ? "text-primary after:absolute after:bottom-0 after:left-0 after:right-0 after:h-0.5 after:bg-primary after:rounded-t after:transition-all after:duration-200" : "text-muted-foreground hover:text-foreground hover:bg-muted/50"}`,
1346
1369
  children: tab.label
1347
1370
  },
@@ -1354,8 +1377,7 @@ function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1354
1377
  id: `panel-${tab.id}`,
1355
1378
  "aria-labelledby": `tab-${tab.id}`,
1356
1379
  hidden: activeTab !== tab.id,
1357
- className: `pt-6 transition-all duration-200 ${activeTab === tab.id && !isAnimating ? "animate-fadeIn opacity-100" : "opacity-0"}`,
1358
- children: tab.content
1380
+ children: activeTab === tab.id && /* @__PURE__ */ jsxRuntime.jsx(page_transition_default, { type: "fade", duration: 150, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-6", children: tab.content }) })
1359
1381
  },
1360
1382
  tab.id
1361
1383
  ))
@@ -1363,16 +1385,23 @@ function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1363
1385
  }
1364
1386
  Tabs.displayName = "Tabs";
1365
1387
  var tabs_default = Tabs;
1366
- var DropdownContext = React2.createContext(null);
1367
- function Dropdown({ trigger, children, className = "", align = "start", autoClose = true, size = "md" }) {
1368
- const [isOpen, setIsOpen] = React2.useState(false);
1369
- const dropdownRef = React2.useRef(null);
1370
- const menuRef = React2.useRef(null);
1371
- const itemsRef = React2.useRef([]);
1372
- const [activeIndex, setActiveIndex] = React2.useState(-1);
1373
- const close = React2.useCallback(() => setIsOpen(false), []);
1374
- const open = React2.useCallback(() => setIsOpen(true), []);
1375
- React2.useEffect(() => {
1388
+ var DropdownContext = React3.createContext(null);
1389
+ function Dropdown({
1390
+ trigger,
1391
+ children,
1392
+ className = "",
1393
+ align = "start",
1394
+ autoClose = true,
1395
+ size = "md"
1396
+ }) {
1397
+ const [isOpen, setIsOpen] = React3.useState(false);
1398
+ const dropdownRef = React3.useRef(null);
1399
+ const menuRef = React3.useRef(null);
1400
+ const itemsRef = React3.useRef([]);
1401
+ const [activeIndex, setActiveIndex] = React3.useState(-1);
1402
+ const close = React3.useCallback(() => setIsOpen(false), []);
1403
+ const open = React3.useCallback(() => setIsOpen(true), []);
1404
+ React3.useEffect(() => {
1376
1405
  if (!isOpen) return;
1377
1406
  const handleKey = (e) => {
1378
1407
  if (!menuRef.current) return;
@@ -1407,7 +1436,7 @@ function Dropdown({ trigger, children, className = "", align = "start", autoClos
1407
1436
  document.addEventListener("keydown", handleKey);
1408
1437
  return () => document.removeEventListener("keydown", handleKey);
1409
1438
  }, [isOpen, activeIndex, close]);
1410
- React2.useEffect(() => {
1439
+ React3.useEffect(() => {
1411
1440
  if (!isOpen) return;
1412
1441
  const handleClickOutside = (event) => {
1413
1442
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
@@ -1417,7 +1446,7 @@ function Dropdown({ trigger, children, className = "", align = "start", autoClos
1417
1446
  document.addEventListener("mousedown", handleClickOutside);
1418
1447
  return () => document.removeEventListener("mousedown", handleClickOutside);
1419
1448
  }, [isOpen, close]);
1420
- React2.useEffect(() => {
1449
+ React3.useEffect(() => {
1421
1450
  if (isOpen) {
1422
1451
  const itemEls = itemsRef.current.filter(Boolean);
1423
1452
  if (itemEls.length) {
@@ -1454,9 +1483,9 @@ function Dropdown({ trigger, children, className = "", align = "start", autoClos
1454
1483
  role: "menu",
1455
1484
  "aria-orientation": "vertical",
1456
1485
  tabIndex: -1,
1457
- children: React2__default.default.Children.map(children, (child, i) => {
1458
- if (!React2__default.default.isValidElement(child)) return child;
1459
- return React2__default.default.cloneElement(child, { __dropdownIndex: i, __registerItem: registerItem, size });
1486
+ children: React3__default.default.Children.map(children, (child, i) => {
1487
+ if (!React3__default.default.isValidElement(child)) return child;
1488
+ return React3__default.default.cloneElement(child, { __dropdownIndex: i, __registerItem: registerItem, size });
1460
1489
  })
1461
1490
  }
1462
1491
  ) })
@@ -1726,14 +1755,14 @@ function Stepper({
1726
1755
  Stepper.displayName = "Stepper";
1727
1756
  var stepper_default = Stepper;
1728
1757
  function Toast({ message, children, type = "info", onClose, className = "", duration = 5e3 }) {
1729
- const [isClosing, setIsClosing] = React2.useState(false);
1758
+ const [isClosing, setIsClosing] = React3.useState(false);
1730
1759
  const typeClasses = {
1731
1760
  info: "bg-info text-info-foreground",
1732
1761
  success: "bg-success text-success-foreground",
1733
1762
  warning: "bg-warning text-warning-foreground",
1734
1763
  error: "bg-destructive text-destructive-foreground"
1735
1764
  };
1736
- React2.useEffect(() => {
1765
+ React3.useEffect(() => {
1737
1766
  if (duration > 0) {
1738
1767
  const timer = setTimeout(() => {
1739
1768
  handleClose();
@@ -1772,11 +1801,11 @@ function Tooltip({
1772
1801
  usePortal = false,
1773
1802
  className = ""
1774
1803
  }) {
1775
- const [showTooltip, setShowTooltip] = React2.useState(false);
1776
- const [tooltipPosition, setTooltipPosition] = React2.useState({ top: 0, left: 0 });
1777
- const triggerRef = React2.useRef(null);
1804
+ const [showTooltip, setShowTooltip] = React3.useState(false);
1805
+ const [tooltipPosition, setTooltipPosition] = React3.useState({ top: 0, left: 0 });
1806
+ const triggerRef = React3.useRef(null);
1778
1807
  const isVisible = open || showTooltip;
1779
- React2.useEffect(() => {
1808
+ React3.useEffect(() => {
1780
1809
  if (usePortal && isVisible && triggerRef.current) {
1781
1810
  const rect = triggerRef.current.getBoundingClientRect();
1782
1811
  const positions = {
@@ -1895,29 +1924,32 @@ function useOverlay(options) {
1895
1924
  exitDuration = 300,
1896
1925
  unmountOnExit = true
1897
1926
  } = options;
1898
- const previouslyFocusedRef = React2.useRef(null);
1899
- const containerRef = React2.useRef(null);
1900
- const [shouldRender, setShouldRender] = React2.useState(isOpen);
1901
- const [phase, setPhase] = React2.useState("mount");
1902
- React2.useLayoutEffect(() => {
1927
+ const previouslyFocusedRef = React3.useRef(null);
1928
+ const containerRef = React3.useRef(null);
1929
+ const [shouldRender, setShouldRender] = React3.useState(isOpen);
1930
+ const [phase, setPhase] = React3.useState("mount");
1931
+ React3.useLayoutEffect(() => {
1903
1932
  if (isOpen) {
1904
1933
  setShouldRender(true);
1905
- setPhase("animating-in");
1906
- let frame = 0;
1907
- const step = () => {
1908
- frame += 1;
1909
- if (frame >= animationFrames) {
1910
- setPhase("visible");
1911
- } else {
1912
- requestAnimationFrame(step);
1913
- }
1914
- };
1915
- requestAnimationFrame(step);
1934
+ setPhase("mount");
1935
+ requestAnimationFrame(() => {
1936
+ setPhase("animating-in");
1937
+ let frame = 0;
1938
+ const step = () => {
1939
+ frame += 1;
1940
+ if (frame >= animationFrames) {
1941
+ setPhase("visible");
1942
+ } else {
1943
+ requestAnimationFrame(step);
1944
+ }
1945
+ };
1946
+ requestAnimationFrame(step);
1947
+ });
1916
1948
  } else if (!isOpen && shouldRender) {
1917
1949
  setPhase("animating-out");
1918
1950
  }
1919
1951
  }, [isOpen, shouldRender, animationFrames]);
1920
- React2.useEffect(() => {
1952
+ React3.useEffect(() => {
1921
1953
  if (phase === "animating-out" && unmountOnExit) {
1922
1954
  const timeout = setTimeout(() => {
1923
1955
  setShouldRender(false);
@@ -1927,7 +1959,7 @@ function useOverlay(options) {
1927
1959
  }
1928
1960
  return void 0;
1929
1961
  }, [phase, exitDuration, unmountOnExit]);
1930
- React2.useEffect(() => {
1962
+ React3.useEffect(() => {
1931
1963
  if (isOpen) {
1932
1964
  if (typeof document !== "undefined") {
1933
1965
  if (restoreFocus) previouslyFocusedRef.current = document.activeElement;
@@ -1943,50 +1975,79 @@ function useOverlay(options) {
1943
1975
  }
1944
1976
  };
1945
1977
  }, [isOpen, lockScroll, restoreFocus]);
1946
- React2.useEffect(() => {
1978
+ React3.useEffect(() => {
1947
1979
  if (phase === "visible" && containerRef.current) {
1948
- containerRef.current.focus?.();
1980
+ const el = containerRef.current;
1981
+ try {
1982
+ el.focus?.({ preventScroll: true });
1983
+ } catch {
1984
+ el.focus?.();
1985
+ }
1949
1986
  }
1950
1987
  }, [phase]);
1951
- const handleKeyDown = React2.useCallback((e) => {
1952
- if (!focusTrap || phase !== "visible" || e.key !== "Tab" || !containerRef.current) return;
1953
- const node = containerRef.current;
1954
- const focusable = node.querySelectorAll(
1955
- 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'
1956
- );
1957
- if (!focusable.length) return;
1958
- const first = focusable[0];
1959
- const last = focusable[focusable.length - 1];
1960
- if (e.shiftKey) {
1961
- if (document.activeElement === first || document.activeElement === node) {
1988
+ const handleKeyDown = React3.useCallback(
1989
+ (e) => {
1990
+ if (!focusTrap || phase !== "visible" || e.key !== "Tab" || !containerRef.current) return;
1991
+ const node = containerRef.current;
1992
+ const focusable = node.querySelectorAll(
1993
+ 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'
1994
+ );
1995
+ if (!focusable.length) return;
1996
+ const first = focusable[0];
1997
+ const last = focusable[focusable.length - 1];
1998
+ if (e.shiftKey) {
1999
+ if (document.activeElement === first || document.activeElement === node) {
2000
+ e.preventDefault();
2001
+ last.focus();
2002
+ }
2003
+ } else if (document.activeElement === last) {
1962
2004
  e.preventDefault();
1963
- last.focus();
2005
+ first.focus();
1964
2006
  }
1965
- } else if (document.activeElement === last) {
1966
- e.preventDefault();
1967
- first.focus();
1968
- }
1969
- }, [focusTrap, phase]);
1970
- React2.useEffect(() => {
2007
+ },
2008
+ [focusTrap, phase]
2009
+ );
2010
+ React3.useEffect(() => {
1971
2011
  if (focusTrap && phase === "visible") {
1972
2012
  document.addEventListener("keydown", handleKeyDown);
1973
2013
  return () => document.removeEventListener("keydown", handleKeyDown);
1974
2014
  }
1975
2015
  return void 0;
1976
2016
  }, [phase, focusTrap, handleKeyDown]);
1977
- const getPhaseClass = React2.useCallback((openClass, closedClass) => phase === "visible" ? openClass : closedClass, [phase]);
2017
+ const getPhaseClass = React3.useCallback(
2018
+ (openClass, closedClass) => {
2019
+ return phase === "animating-in" || phase === "visible" ? openClass : closedClass;
2020
+ },
2021
+ [phase]
2022
+ );
1978
2023
  return { phase, shouldRender, ref: containerRef, getPhaseClass };
1979
2024
  }
1980
2025
  var useOverlay_default = useOverlay;
1981
- function Modal({ isOpen, onClose, children, title, description, content, actions, className = "", ariaLabel, align = "center" }) {
1982
- const { phase, shouldRender, ref: dialogRef, getPhaseClass } = useOverlay_default({
2026
+ function Modal({
2027
+ isOpen,
2028
+ onClose,
2029
+ children,
2030
+ title,
2031
+ description,
2032
+ content,
2033
+ actions,
2034
+ className = "",
2035
+ ariaLabel,
2036
+ align = "center"
2037
+ }) {
2038
+ const {
2039
+ phase,
2040
+ shouldRender,
2041
+ ref: dialogRef,
2042
+ getPhaseClass
2043
+ } = useOverlay_default({
1983
2044
  isOpen,
1984
2045
  focusTrap: true,
1985
2046
  lockScroll: true,
1986
2047
  animationFrames: 2,
1987
2048
  restoreFocus: true
1988
2049
  });
1989
- React2__default.default.useEffect(() => {
2050
+ React3__default.default.useEffect(() => {
1990
2051
  if (!isOpen) return;
1991
2052
  const handleEscape = (e) => {
1992
2053
  if (e.key === "Escape") {
@@ -2100,10 +2161,10 @@ function DeleteDialog({
2100
2161
  DeleteDialog.displayName = "DeleteDialog";
2101
2162
  var delete_dialog_default = DeleteDialog;
2102
2163
  function Popover({ trigger, children, content, position = "bottom", className = "" }) {
2103
- const [isOpen, setIsOpen] = React2.useState(false);
2104
- const popoverRef = React2.useRef(null);
2164
+ const [isOpen, setIsOpen] = React3.useState(false);
2165
+ const popoverRef = React3.useRef(null);
2105
2166
  const triggerContent = children || trigger;
2106
- React2.useEffect(() => {
2167
+ React3.useEffect(() => {
2107
2168
  const handleClickOutside = (event) => {
2108
2169
  if (popoverRef.current && !popoverRef.current.contains(event.target)) {
2109
2170
  setIsOpen(false);
@@ -2519,12 +2580,12 @@ function TableCell({ children, className = "", align = "left", ...props }) {
2519
2580
  return /* @__PURE__ */ jsxRuntime.jsx("td", { className: `px-6 py-4 whitespace-nowrap ${alignClasses[align]} ${className}`, ...props, children });
2520
2581
  }
2521
2582
  function useTable({ data, initialSort, pageSize = 10 }) {
2522
- const [sortConfig, setSortConfig] = React2.useState(
2583
+ const [sortConfig, setSortConfig] = React3.useState(
2523
2584
  initialSort ? { key: initialSort.key, direction: initialSort.direction } : null
2524
2585
  );
2525
- const [currentPage, setCurrentPage] = React2.useState(1);
2526
- const [selectedRows, setSelectedRows] = React2.useState(/* @__PURE__ */ new Set());
2527
- const sortedData = React2.useMemo(() => {
2586
+ const [currentPage, setCurrentPage] = React3.useState(1);
2587
+ const [selectedRows, setSelectedRows] = React3.useState(/* @__PURE__ */ new Set());
2588
+ const sortedData = React3.useMemo(() => {
2528
2589
  if (!sortConfig) return data;
2529
2590
  const sorted = [...data].sort((a, b) => {
2530
2591
  const aValue = a[sortConfig.key];
@@ -3000,7 +3061,7 @@ function Heading({ children, level = 1, className = "", noMargin = false }) {
3000
3061
  6: "mb-2"
3001
3062
  };
3002
3063
  const margin = noMargin ? "" : marginClasses[level];
3003
- return React2.createElement(
3064
+ return React3.createElement(
3004
3065
  `h${level}`,
3005
3066
  {
3006
3067
  className: `text-foreground ${levelClasses[level]} ${margin} ${className}`
@@ -3026,23 +3087,13 @@ function Card({
3026
3087
  className = "",
3027
3088
  variant = "default",
3028
3089
  size = "md",
3090
+ width = "auto",
3029
3091
  hoverable = false,
3030
3092
  imagePosition = "top",
3031
3093
  centered = false,
3032
3094
  compact = false,
3033
- interactive,
3034
- highlighted,
3035
- maxWidth,
3036
- padding,
3037
3095
  ...props
3038
3096
  }) {
3039
- if (interactive && !hoverable) hoverable = true;
3040
- if (highlighted) variant = "filled";
3041
- if (maxWidth) {
3042
- if (!size || size === "md") {
3043
- size = maxWidth === "2xl" ? "xl" : maxWidth;
3044
- }
3045
- }
3046
3097
  const variantClasses = {
3047
3098
  default: "bg-card text-card-foreground border border-border shadow-md",
3048
3099
  bordered: "bg-card text-card-foreground border-2 border-border",
@@ -3056,6 +3107,11 @@ function Card({
3056
3107
  lg: "w-[28rem]",
3057
3108
  xl: "w-[32rem]"
3058
3109
  };
3110
+ const widthClasses = {
3111
+ auto: size !== "md" ? sizeClasses[size] : "max-w-full",
3112
+ full: "w-full",
3113
+ fit: "w-fit"
3114
+ };
3059
3115
  const hoverClasses = hoverable ? "transition-all duration-300 hover:shadow-xl hover:-translate-y-1 cursor-pointer" : "transition-shadow duration-200";
3060
3116
  const imagePositionClasses = {
3061
3117
  top: "flex-col",
@@ -3071,12 +3127,11 @@ function Card({
3071
3127
  rounded-2xl
3072
3128
  overflow-hidden
3073
3129
  ${variantClasses[variant]}
3074
- ${size !== "md" ? sizeClasses[size] : "max-w-full"}
3130
+ ${widthClasses[width]}
3075
3131
  ${hoverClasses}
3076
3132
  ${imagePositionClasses[imagePosition]}
3077
3133
  ${centerClasses}
3078
3134
  ${compact ? "p-4" : ""}
3079
- ${padding === "none" ? "" : ""}
3080
3135
  ${imagePosition === "side" ? "flex" : "flex"}
3081
3136
  ${className}
3082
3137
  `.trim().replace(/\s+/g, " "),
@@ -3199,7 +3254,7 @@ function PricingTier({
3199
3254
  PricingTier.displayName = "PricingTier";
3200
3255
  var pricing_tier_default = PricingTier;
3201
3256
  function CodeBlock({ code, className = "", showCopy = true }) {
3202
- const [copied, setCopied] = React2.useState(false);
3257
+ const [copied, setCopied] = React3.useState(false);
3203
3258
  const handleCopy = async () => {
3204
3259
  try {
3205
3260
  await navigator.clipboard.writeText(code);
@@ -3226,88 +3281,216 @@ function CodeBlock({ code, className = "", showCopy = true }) {
3226
3281
  }
3227
3282
  CodeBlock.displayName = "CodeBlock";
3228
3283
  var code_block_default = CodeBlock;
3284
+ function CardBody({ children, padding = "md", className = "" }) {
3285
+ const paddingClasses = {
3286
+ none: "p-0",
3287
+ sm: "p-4",
3288
+ md: "p-6",
3289
+ lg: "p-8",
3290
+ xl: "p-10"
3291
+ };
3292
+ return /* @__PURE__ */ jsxRuntime.jsx(
3293
+ "div",
3294
+ {
3295
+ className: `
3296
+ card-body
3297
+ flex flex-col gap-2
3298
+ ${paddingClasses[padding]}
3299
+ ${className}
3300
+ `.trim().replace(/\s+/g, " "),
3301
+ children
3302
+ }
3303
+ );
3304
+ }
3305
+ CardBody.displayName = "CardBody";
3306
+ var card_body_default = CardBody;
3307
+ function CardTitle({ children, className = "", as: Component = "h2", size = "md" }) {
3308
+ const sizeClasses = {
3309
+ sm: "text-base font-semibold",
3310
+ md: "text-lg font-bold",
3311
+ lg: "text-xl font-bold",
3312
+ xl: "text-2xl font-bold"
3313
+ };
3314
+ return /* @__PURE__ */ jsxRuntime.jsx(
3315
+ Component,
3316
+ {
3317
+ className: `
3318
+ card-title
3319
+ ${sizeClasses[size]}
3320
+ ${className}
3321
+ `.trim().replace(/\s+/g, " "),
3322
+ children
3323
+ }
3324
+ );
3325
+ }
3326
+ CardTitle.displayName = "CardTitle";
3327
+ var card_title_default = CardTitle;
3328
+ function CardActions({ children, className = "", align = "end", direction = "row" }) {
3329
+ const alignClasses = {
3330
+ start: "justify-start",
3331
+ center: "justify-center",
3332
+ end: "justify-end",
3333
+ stretch: "justify-stretch"
3334
+ };
3335
+ const directionClasses = {
3336
+ row: "flex-row",
3337
+ column: "flex-col"
3338
+ };
3339
+ return /* @__PURE__ */ jsxRuntime.jsx(
3340
+ "div",
3341
+ {
3342
+ className: `
3343
+ flex gap-2 px-6 pb-6 pt-2
3344
+ ${directionClasses[direction]}
3345
+ ${alignClasses[align]}
3346
+ ${className}
3347
+ `.trim().replace(/\s+/g, " "),
3348
+ children
3349
+ }
3350
+ );
3351
+ }
3352
+ CardActions.displayName = "CardActions";
3353
+ var card_actions_default = CardActions;
3354
+ function CardFigure({ children, className = "", aspectRatio = "auto" }) {
3355
+ const aspectRatioClasses = {
3356
+ square: "aspect-square",
3357
+ video: "aspect-video",
3358
+ wide: "aspect-[21/9]",
3359
+ portrait: "aspect-[3/4]",
3360
+ auto: ""
3361
+ };
3362
+ return /* @__PURE__ */ jsxRuntime.jsx(
3363
+ "figure",
3364
+ {
3365
+ className: `
3366
+ card-figure
3367
+ relative overflow-hidden
3368
+ ${aspectRatioClasses[aspectRatio]}
3369
+ ${className}
3370
+ `.trim().replace(/\s+/g, " "),
3371
+ children
3372
+ }
3373
+ );
3374
+ }
3375
+ CardFigure.displayName = "CardFigure";
3376
+ var card_figure_default = CardFigure;
3229
3377
  function Divider({ orientation = "horizontal", className = "", ...props }) {
3230
3378
  const orientationClasses = orientation === "horizontal" ? "w-full h-px" : "h-full w-px";
3231
3379
  return /* @__PURE__ */ jsxRuntime.jsx("hr", { className: `border-0 bg-border ${orientationClasses} ${className}`, "aria-orientation": orientation, ...props });
3232
3380
  }
3233
3381
  Divider.displayName = "Divider";
3234
3382
  var divider_default = Divider;
3235
- function Drawer({ isOpen, onClose, children, position = "right", className = "", contentAlign = "start", centerVertical = false }) {
3236
- const { phase, shouldRender, ref: panelRef, getPhaseClass } = useOverlay_default({
3383
+ function Drawer({
3384
+ isOpen,
3385
+ onClose,
3386
+ children,
3387
+ position = "right",
3388
+ className = "",
3389
+ title,
3390
+ size = "md",
3391
+ closeOnEscape = true,
3392
+ closeOnOutside = true,
3393
+ unmountOnExit = true,
3394
+ portalRoot = typeof document !== "undefined" ? document.body : null,
3395
+ noAnimation = false
3396
+ }) {
3397
+ const { phase, shouldRender, ref, getPhaseClass } = useOverlay_default({
3237
3398
  isOpen,
3238
- focusTrap: true,
3239
3399
  lockScroll: true,
3240
3400
  restoreFocus: true,
3241
- animationFrames: 2
3401
+ focusTrap: true,
3402
+ unmountOnExit,
3403
+ exitDuration: noAnimation ? 0 : 300,
3404
+ animationFrames: noAnimation ? 0 : 2
3242
3405
  });
3243
- React2.useEffect(() => {
3244
- if (!isOpen) return;
3245
- const handleEscape = (e) => {
3246
- if (e.key === "Escape") onClose();
3247
- };
3248
- document.addEventListener("keydown", handleEscape);
3249
- return () => document.removeEventListener("keydown", handleEscape);
3250
- }, [isOpen, onClose]);
3251
3406
  if (!shouldRender) return null;
3252
- const positionClasses = {
3253
- left: "left-0 top-0 h-full w-80",
3254
- right: "right-0 top-0 h-full w-80",
3255
- top: "top-0 left-0 w-full h-80",
3256
- bottom: "bottom-0 left-0 w-full h-80"
3407
+ const sizeClasses = {
3408
+ sm: "w-72",
3409
+ md: "w-96",
3410
+ lg: "w-[32rem]",
3411
+ xl: "w-[40rem]",
3412
+ full: "w-full max-w-2xl"
3257
3413
  };
3258
- const offscreenTransform = {
3414
+ const edgeClasses = {
3415
+ left: "left-0 top-0 bottom-0",
3416
+ right: "right-0 top-0 bottom-0",
3417
+ top: "top-0 left-0 right-0 h-96",
3418
+ bottom: "bottom-0 left-0 right-0 h-96"
3419
+ };
3420
+ const closedTransform = {
3259
3421
  left: "-translate-x-full",
3260
3422
  right: "translate-x-full",
3261
3423
  top: "-translate-y-full",
3262
3424
  bottom: "translate-y-full"
3263
- }[position];
3264
- const transformClass = getPhaseClass("translate-x-0 translate-y-0", offscreenTransform);
3265
- const overlayOpacity = getPhaseClass("opacity-100", "opacity-0");
3266
- const panelOpacity = getPhaseClass("opacity-100", "opacity-0");
3267
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3425
+ };
3426
+ const openTransform = "translate-x-0 translate-y-0";
3427
+ const panelTransform = noAnimation ? "" : getPhaseClass(openTransform, closedTransform[position]);
3428
+ const overlayOpacity = noAnimation ? "" : getPhaseClass("opacity-100", "opacity-0");
3429
+ const handleKeyDown = (e) => {
3430
+ if (e.key === "Escape" && closeOnEscape) {
3431
+ e.stopPropagation();
3432
+ onClose();
3433
+ }
3434
+ };
3435
+ const panel = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3268
3436
  /* @__PURE__ */ jsxRuntime.jsx(
3269
3437
  "div",
3270
3438
  {
3271
- className: `fixed inset-0 bg-black/50 backdrop-blur-sm z-40 transition-opacity duration-300 ease-out will-change-opacity ${overlayOpacity}`,
3272
- onClick: onClose,
3439
+ className: `fixed inset-0 z-40 bg-black/50 backdrop-blur-sm transition-opacity duration-300 ${overlayOpacity}`,
3273
3440
  "aria-hidden": "true",
3441
+ onClick: () => closeOnOutside && onClose(),
3274
3442
  "data-phase": phase
3275
3443
  }
3276
3444
  ),
3277
3445
  /* @__PURE__ */ jsxRuntime.jsxs(
3278
3446
  "div",
3279
3447
  {
3280
- ref: panelRef,
3281
- className: `fixed bg-card text-card-foreground border border-border shadow-2xl z-50 flex flex-col ${positionClasses[position]} transform ${transformClass} ${panelOpacity} will-change-transform will-change-opacity transition-[transform,opacity] duration-300 ease-[cubic-bezier(.25,.8,.25,1)] focus:outline-none ${className}`,
3448
+ ref,
3282
3449
  role: "dialog",
3283
3450
  "aria-modal": "true",
3284
- "data-position": position,
3285
- "data-phase": phase,
3451
+ "aria-label": title || "Drawer",
3286
3452
  tabIndex: -1,
3287
- onTransitionEnd: () => {
3288
- },
3453
+ "data-phase": phase,
3454
+ "data-position": position,
3455
+ className: `fixed ${edgeClasses[position]} ${position === "left" || position === "right" ? sizeClasses[size] : ""} bg-card text-card-foreground shadow-2xl z-50 flex flex-col outline-none ${panelTransform} ${noAnimation ? "" : "transition-[transform] duration-300 ease-out"} ${className}`,
3456
+ onKeyDown: handleKeyDown,
3289
3457
  children: [
3290
- /* @__PURE__ */ jsxRuntime.jsx("header", { className: "flex items-center justify-end p-3 border-b border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
3291
- "button",
3292
- {
3293
- onClick: onClose,
3294
- "aria-label": "Close drawer",
3295
- className: "w-8 h-8 inline-flex items-center justify-center rounded hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring",
3296
- type: "button",
3297
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "\u2715" })
3298
- }
3299
- ) }),
3300
- /* @__PURE__ */ jsxRuntime.jsx(
3301
- "section",
3302
- {
3303
- className: `flex-1 overflow-y-auto px-3 py-3 transition-opacity duration-200 ${panelOpacity} flex flex-col ${contentAlign === "center" ? "items-center" : contentAlign === "end" ? "items-end" : "items-start"} space-y-4 ${centerVertical ? "justify-center" : ""}`,
3304
- children
3305
- }
3306
- )
3458
+ title && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/60 bg-card/95 backdrop-blur-sm", children: [
3459
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold tracking-tight", children: title }),
3460
+ /* @__PURE__ */ jsxRuntime.jsx(
3461
+ "button",
3462
+ {
3463
+ type: "button",
3464
+ "aria-label": "Close drawer",
3465
+ onClick: onClose,
3466
+ className: "w-8 h-8 inline-flex items-center justify-center rounded-md hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring",
3467
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
3468
+ "svg",
3469
+ {
3470
+ xmlns: "http://www.w3.org/2000/svg",
3471
+ width: "18",
3472
+ height: "18",
3473
+ viewBox: "0 0 24 24",
3474
+ fill: "none",
3475
+ stroke: "currentColor",
3476
+ strokeWidth: "2",
3477
+ strokeLinecap: "round",
3478
+ strokeLinejoin: "round",
3479
+ children: [
3480
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
3481
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
3482
+ ]
3483
+ }
3484
+ )
3485
+ }
3486
+ )
3487
+ ] }),
3488
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto p-5 flex flex-col gap-4", children })
3307
3489
  ]
3308
3490
  }
3309
3491
  )
3310
3492
  ] });
3493
+ return portalRoot ? reactDom.createPortal(panel, portalRoot) : panel;
3311
3494
  }
3312
3495
  Drawer.displayName = "Drawer";
3313
3496
  var drawer_default = Drawer;
@@ -3317,7 +3500,7 @@ function Page({ children, className = "" }) {
3317
3500
  Page.displayName = "Page";
3318
3501
  var page_default = Page;
3319
3502
  function AccordionItem({ title, children, defaultOpen = false }) {
3320
- const [isOpen, setIsOpen] = React2.useState(defaultOpen);
3503
+ const [isOpen, setIsOpen] = React3.useState(defaultOpen);
3321
3504
  return /* @__PURE__ */ jsxRuntime.jsxs("article", { className: "border-b border-border", children: [
3322
3505
  /* @__PURE__ */ jsxRuntime.jsxs(
3323
3506
  "button",
@@ -3350,65 +3533,69 @@ Accordion.displayName = "Accordion";
3350
3533
  var accordion_default = Accordion;
3351
3534
  function Hero({
3352
3535
  title,
3536
+ subtitle,
3353
3537
  description,
3354
3538
  primaryAction,
3355
3539
  secondaryAction,
3356
3540
  children,
3357
3541
  className = "",
3358
- backgroundGradient = true,
3542
+ variant = "gradient",
3359
3543
  centered = true,
3360
3544
  size = "lg"
3361
3545
  }) {
3362
3546
  const sizeClasses = {
3363
- sm: "py-12",
3364
- md: "py-16",
3365
- lg: "py-20 md:py-24"
3547
+ sm: "py-12 md:py-16",
3548
+ md: "py-16 md:py-20",
3549
+ lg: "py-20 md:py-28"
3366
3550
  };
3367
3551
  const titleSizes = {
3368
3552
  sm: "text-3xl md:text-4xl",
3369
3553
  md: "text-4xl md:text-5xl",
3370
- lg: "text-4xl md:text-5xl lg:text-6xl"
3554
+ lg: "text-5xl md:text-6xl lg:text-7xl"
3371
3555
  };
3372
- const descriptionSizes = {
3373
- sm: "text-base md:text-lg",
3374
- md: "text-lg md:text-xl",
3375
- lg: "text-xl md:text-2xl"
3556
+ const variantClasses = {
3557
+ gradient: "bg-gradient-to-b from-primary/10 via-primary/5 to-background",
3558
+ solid: "bg-muted/30",
3559
+ minimal: "bg-background"
3376
3560
  };
3377
- return /* @__PURE__ */ jsxRuntime.jsx(
3378
- "section",
3379
- {
3380
- className: `${sizeClasses[size]} ${backgroundGradient ? "bg-gradient-to-b from-primary/10 via-primary/5 to-background" : "bg-background"} ${className}`,
3381
- children: /* @__PURE__ */ jsxRuntime.jsx(container_default, { size: "lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: centered ? "text-center" : "", children: [
3382
- /* @__PURE__ */ jsxRuntime.jsx(heading_default, { level: 1, className: `${titleSizes[size]} font-bold mb-4 md:mb-6`, children: title }),
3383
- description && /* @__PURE__ */ jsxRuntime.jsx(text_default, { className: `${descriptionSizes[size]} mb-6 md:mb-8 ${centered ? "max-w-3xl mx-auto" : "max-w-3xl"}`, children: description }),
3384
- (primaryAction || secondaryAction) && /* @__PURE__ */ jsxRuntime.jsxs(stack_default, { direction: "horizontal", spacing: "md", className: `flex-wrap ${centered ? "justify-center" : ""}`, children: [
3385
- primaryAction && /* @__PURE__ */ jsxRuntime.jsx(
3386
- button_default,
3387
- {
3388
- size: "lg",
3389
- variant: primaryAction.variant || "primary",
3390
- style: primaryAction.style,
3391
- onClick: primaryAction.onClick,
3392
- loading: primaryAction.loading,
3393
- children: primaryAction.label
3394
- }
3395
- ),
3396
- secondaryAction && /* @__PURE__ */ jsxRuntime.jsx(
3397
- button_default,
3398
- {
3399
- size: "lg",
3400
- variant: secondaryAction.variant || "neutral",
3401
- style: secondaryAction.style || "outline",
3402
- onClick: secondaryAction.onClick,
3403
- loading: secondaryAction.loading,
3404
- children: secondaryAction.label
3405
- }
3406
- )
3407
- ] }),
3408
- children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-8", children })
3409
- ] }) })
3410
- }
3411
- );
3561
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: `relative ${sizeClasses[size]} ${variantClasses[variant]} ${className}`, children: [
3562
+ variant === "gradient" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-primary/20 to-transparent" }),
3563
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-background to-transparent pointer-events-none" }),
3564
+ /* @__PURE__ */ jsxRuntime.jsx(container_default, { size: "lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: centered ? "text-center mx-auto max-w-4xl" : "max-w-4xl", children: [
3565
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(text_default, { className: "text-lg md:text-xl font-semibold text-primary mb-4", weight: "semibold", children: subtitle }),
3566
+ /* @__PURE__ */ jsxRuntime.jsx(heading_default, { level: 1, className: `${titleSizes[size]} font-extrabold mb-6 tracking-tight`, children: title }),
3567
+ description && /* @__PURE__ */ jsxRuntime.jsx(text_default, { className: "text-lg md:text-xl mb-8 text-muted-foreground max-w-2xl mx-auto", children: description }),
3568
+ (primaryAction || secondaryAction) && /* @__PURE__ */ jsxRuntime.jsxs(stack_default, { direction: "horizontal", spacing: "md", className: `flex-wrap ${centered ? "justify-center" : ""}`, children: [
3569
+ primaryAction && /* @__PURE__ */ jsxRuntime.jsx(
3570
+ button_default,
3571
+ {
3572
+ size: "lg",
3573
+ variant: primaryAction.variant || "primary",
3574
+ style: primaryAction.style,
3575
+ onClick: primaryAction.onClick,
3576
+ loading: primaryAction.loading,
3577
+ icon: primaryAction.icon,
3578
+ className: "shadow-lg shadow-primary/20 hover:shadow-xl hover:shadow-primary/30 transition-all",
3579
+ children: primaryAction.label
3580
+ }
3581
+ ),
3582
+ secondaryAction && /* @__PURE__ */ jsxRuntime.jsx(
3583
+ button_default,
3584
+ {
3585
+ size: "lg",
3586
+ variant: secondaryAction.variant || "neutral",
3587
+ style: secondaryAction.style || "outline",
3588
+ onClick: secondaryAction.onClick,
3589
+ loading: secondaryAction.loading,
3590
+ icon: secondaryAction.icon,
3591
+ className: "hover:shadow-md transition-all",
3592
+ children: secondaryAction.label
3593
+ }
3594
+ )
3595
+ ] }),
3596
+ children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-10", children })
3597
+ ] }) })
3598
+ ] });
3412
3599
  }
3413
3600
  Hero.displayName = "Hero";
3414
3601
  var hero_default = Hero;
@@ -3541,7 +3728,7 @@ function Footer({ sections, copyright, social, className = "" }) {
3541
3728
  Footer.displayName = "Footer";
3542
3729
  var footer_default = Footer;
3543
3730
  function useScrollReset(deps, container) {
3544
- React2.useEffect(() => {
3731
+ React3.useEffect(() => {
3545
3732
  let cancelled = false;
3546
3733
  const maxRaf = 6;
3547
3734
  let rafCount = 0;
@@ -3586,11 +3773,11 @@ function LeftNavLayout({
3586
3773
  embedded = false,
3587
3774
  mainContentRef
3588
3775
  }) {
3589
- const [internalCollapsed, setInternalCollapsed] = React2.useState(false);
3590
- const [internalMobileMenuOpen, setInternalMobileMenuOpen] = React2.useState(false);
3591
- const navRef = React2.useRef(null);
3592
- const scrollPosRef = React2.useRef(0);
3593
- const internalContentRef = React2.useRef(null);
3776
+ const [internalCollapsed, setInternalCollapsed] = React3.useState(false);
3777
+ const [internalMobileMenuOpen, setInternalMobileMenuOpen] = React3.useState(false);
3778
+ const navRef = React3.useRef(null);
3779
+ const scrollPosRef = React3.useRef(0);
3780
+ const internalContentRef = React3.useRef(null);
3594
3781
  const contentRef = mainContentRef || internalContentRef;
3595
3782
  const collapsed = controlledCollapsed ?? internalCollapsed;
3596
3783
  const setCollapsed = (value) => {
@@ -3610,7 +3797,7 @@ function LeftNavLayout({
3610
3797
  };
3611
3798
  const toggleCollapsed = () => setCollapsed(!collapsed);
3612
3799
  const toggleMobileMenu = () => setMobileMenuOpen(!mobileMenuOpen);
3613
- React2.useEffect(() => {
3800
+ React3.useEffect(() => {
3614
3801
  if (navRef.current) {
3615
3802
  navRef.current.scrollTop = scrollPosRef.current;
3616
3803
  }
@@ -3618,7 +3805,14 @@ function LeftNavLayout({
3618
3805
  useScrollReset_default([children], contentRef.current);
3619
3806
  const containerClasses = embedded ? "flex bg-background border border-border rounded-lg overflow-hidden" : "flex h-[calc(100vh-4rem)] bg-background";
3620
3807
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${containerClasses} ${className}`, children: [
3621
- mobileCollapsible && mobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-40 lg:hidden bg-background/80 backdrop-blur-sm", onClick: toggleMobileMenu, "aria-hidden": "true" }),
3808
+ mobileCollapsible && mobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
3809
+ "div",
3810
+ {
3811
+ className: "fixed inset-0 z-40 lg:hidden bg-background/80 backdrop-blur-sm",
3812
+ onClick: toggleMobileMenu,
3813
+ "aria-hidden": "true"
3814
+ }
3815
+ ),
3622
3816
  /* @__PURE__ */ jsxRuntime.jsxs(
3623
3817
  "aside",
3624
3818
  {
@@ -3696,15 +3890,15 @@ function LeftNavItem({
3696
3890
  title,
3697
3891
  preventNavigation = false
3698
3892
  }) {
3699
- const navRef = React2.useRef(null);
3700
- const [isCollapsed, setIsCollapsed] = React2.useState(() => {
3893
+ const navRef = React3.useRef(null);
3894
+ const [isCollapsed, setIsCollapsed] = React3.useState(() => {
3701
3895
  if (typeof window !== "undefined") {
3702
3896
  const navElement = document.querySelector("nav[data-collapsed]");
3703
3897
  return navElement?.getAttribute("data-collapsed") === "true";
3704
3898
  }
3705
3899
  return false;
3706
3900
  });
3707
- React2.useEffect(() => {
3901
+ React3.useEffect(() => {
3708
3902
  const checkCollapsed = () => {
3709
3903
  const navElement2 = navRef.current?.closest("nav");
3710
3904
  if (navElement2) {
@@ -3807,26 +4001,26 @@ function Code({ children, block = false, variant = "default", className = "" })
3807
4001
  }
3808
4002
  Code.displayName = "Code";
3809
4003
  var code_default = Code;
3810
- var ThemeContext = React2.createContext(void 0);
4004
+ var ThemeContext = React3.createContext(void 0);
3811
4005
  function ThemeProvider({
3812
4006
  children,
3813
4007
  defaultTheme = "light",
3814
4008
  storageKey = "hydn-theme",
3815
4009
  themes = ["light", "dark"]
3816
4010
  }) {
3817
- const [theme, setThemeState] = React2.useState(() => {
4011
+ const [theme, setThemeState] = React3.useState(() => {
3818
4012
  if (typeof window !== "undefined") {
3819
4013
  const stored = localStorage.getItem(storageKey);
3820
4014
  return stored && themes.includes(stored) ? stored : defaultTheme;
3821
4015
  }
3822
4016
  return defaultTheme;
3823
4017
  });
3824
- React2.useEffect(() => {
4018
+ React3.useEffect(() => {
3825
4019
  const root = window.document.documentElement;
3826
4020
  root.classList.remove(...themes);
3827
4021
  root.classList.add(theme);
3828
4022
  }, [theme, themes]);
3829
- const setTheme = React2.useCallback(
4023
+ const setTheme = React3.useCallback(
3830
4024
  (newTheme) => {
3831
4025
  if (themes.includes(newTheme)) {
3832
4026
  localStorage.setItem(storageKey, newTheme);
@@ -3837,7 +4031,7 @@ function ThemeProvider({
3837
4031
  },
3838
4032
  [themes, storageKey]
3839
4033
  );
3840
- const value = React2.useMemo(
4034
+ const value = React3.useMemo(
3841
4035
  () => ({
3842
4036
  theme,
3843
4037
  setTheme,
@@ -3848,7 +4042,7 @@ function ThemeProvider({
3848
4042
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value, children });
3849
4043
  }
3850
4044
  function useTheme() {
3851
- const context = React2.useContext(ThemeContext);
4045
+ const context = React3.useContext(ThemeContext);
3852
4046
  if (!context) {
3853
4047
  throw new Error("useTheme must be used within a ThemeProvider");
3854
4048
  }
@@ -3859,39 +4053,53 @@ function ColorModeToggle({ className = "" }) {
3859
4053
  const toggleTheme = () => {
3860
4054
  setTheme(theme === "light" ? "dark" : "light");
3861
4055
  };
3862
- const getIcon = () => {
3863
- if (theme === "dark") {
3864
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx(
3865
- "path",
3866
- {
3867
- strokeLinecap: "round",
3868
- strokeLinejoin: "round",
3869
- strokeWidth: 2,
3870
- d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
3871
- }
3872
- ) });
3873
- }
3874
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx(
3875
- "path",
3876
- {
3877
- strokeLinecap: "round",
3878
- strokeLinejoin: "round",
3879
- strokeWidth: 2,
3880
- d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
3881
- }
3882
- ) });
3883
- };
3884
- const getLabel = () => {
3885
- return `Switch to ${theme === "light" ? "dark" : "light"} theme`;
3886
- };
3887
- return /* @__PURE__ */ jsxRuntime.jsx(
4056
+ const isDark = theme === "dark";
4057
+ const label = `Switch to ${theme === "light" ? "dark" : "light"} theme`;
4058
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3888
4059
  "button",
3889
4060
  {
3890
4061
  onClick: toggleTheme,
3891
- className: `p-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors cursor-pointer ${className}`,
3892
- "aria-label": getLabel(),
3893
- title: getLabel(),
3894
- children: getIcon()
4062
+ className: `relative p-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors cursor-pointer ${className}`,
4063
+ "aria-label": label,
4064
+ title: label,
4065
+ children: [
4066
+ /* @__PURE__ */ jsxRuntime.jsx(
4067
+ "svg",
4068
+ {
4069
+ className: `w-5 h-5 absolute inset-0 m-auto transition-all duration-300 ${isDark ? "rotate-90 scale-0 opacity-0" : "rotate-0 scale-100 opacity-100"}`,
4070
+ fill: "none",
4071
+ stroke: "currentColor",
4072
+ viewBox: "0 0 24 24",
4073
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4074
+ "path",
4075
+ {
4076
+ strokeLinecap: "round",
4077
+ strokeLinejoin: "round",
4078
+ strokeWidth: 2,
4079
+ d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
4080
+ }
4081
+ )
4082
+ }
4083
+ ),
4084
+ /* @__PURE__ */ jsxRuntime.jsx(
4085
+ "svg",
4086
+ {
4087
+ className: `w-5 h-5 transition-all duration-300 ${isDark ? "rotate-0 scale-100 opacity-100" : "-rotate-90 scale-0 opacity-0"}`,
4088
+ fill: "none",
4089
+ stroke: "currentColor",
4090
+ viewBox: "0 0 24 24",
4091
+ children: /* @__PURE__ */ jsxRuntime.jsx(
4092
+ "path",
4093
+ {
4094
+ strokeLinecap: "round",
4095
+ strokeLinejoin: "round",
4096
+ strokeWidth: 2,
4097
+ d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
4098
+ }
4099
+ )
4100
+ }
4101
+ )
4102
+ ]
3895
4103
  }
3896
4104
  );
3897
4105
  }
@@ -3908,8 +4116,12 @@ exports.Button = button_default;
3908
4116
  exports.ButtonGroup = button_group_default;
3909
4117
  exports.Calendar = calendar_default;
3910
4118
  exports.Card = card_default;
4119
+ exports.CardActions = card_actions_default;
4120
+ exports.CardBody = card_body_default;
4121
+ exports.CardFigure = card_figure_default;
3911
4122
  exports.CardFooter = card_footer_default;
3912
4123
  exports.CardHeader = card_header_default;
4124
+ exports.CardTitle = card_title_default;
3913
4125
  exports.Checkbox = checkbox_default;
3914
4126
  exports.Chip = chip_default;
3915
4127
  exports.Code = code_default;