@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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import React2, { createContext, useState, useRef, useEffect, isValidElement, cloneElement, useCallback, useMemo, createElement, useContext, useLayoutEffect } from 'react';
2
+ import React3, { createContext, useState, useRef, useEffect, isValidElement, cloneElement, useCallback, useMemo, createElement, useContext, useLayoutEffect } from 'react';
3
3
  import { IconX, IconChevronDown, IconCheck, IconCalendar, IconMenu2, IconTrash, IconChevronRight, IconChevronLeft, IconSelector, IconChevronUp } from '@tabler/icons-react';
4
4
  import { Link, NavLink } from 'react-router-dom';
5
5
  import { createPortal } from 'react-dom';
@@ -264,37 +264,43 @@ function Radio({
264
264
  warning: "border-warning focus:ring-warning"
265
265
  };
266
266
  const inputId = id || `radio-${value || Math.random().toString(36).slice(2)}`;
267
- return /* @__PURE__ */ jsxs("div", { className: `inline-flex items-center justify-center relative ${disabled ? "opacity-60 cursor-not-allowed" : "cursor-pointer"}`, children: [
268
- /* @__PURE__ */ jsx(
269
- "input",
270
- {
271
- type: "radio",
272
- checked: isChecked,
273
- onChange: handleChange,
274
- disabled,
275
- "aria-label": ariaLabel,
276
- "aria-invalid": validationState === "error",
277
- id: inputId,
278
- name,
279
- value,
280
- className: "peer sr-only"
281
- }
282
- ),
283
- /* @__PURE__ */ jsx(
284
- "span",
285
- {
286
- "aria-hidden": "true",
287
- onClick: () => !disabled && document.getElementById(inputId)?.click(),
288
- className: `w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all duration-200 ease-out bg-background shadow-sm
267
+ return /* @__PURE__ */ jsxs(
268
+ "div",
269
+ {
270
+ className: `inline-flex items-center justify-center relative ${disabled ? "opacity-60 cursor-not-allowed" : "cursor-pointer"}`,
271
+ children: [
272
+ /* @__PURE__ */ jsx(
273
+ "input",
274
+ {
275
+ type: "radio",
276
+ checked: isChecked,
277
+ onChange: handleChange,
278
+ disabled,
279
+ "aria-label": ariaLabel,
280
+ "aria-invalid": validationState === "error",
281
+ id: inputId,
282
+ name,
283
+ value,
284
+ className: "peer sr-only"
285
+ }
286
+ ),
287
+ /* @__PURE__ */ jsx(
288
+ "span",
289
+ {
290
+ "aria-hidden": "true",
291
+ onClick: () => !disabled && document.getElementById(inputId)?.click(),
292
+ className: `w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all duration-200 ease-out bg-background shadow-sm
289
293
  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
290
294
  peer-checked:before:scale-100 peer-checked:border-primary
291
295
  peer-focus-visible:ring-2 peer-focus-visible:ring-offset-2 peer-focus-visible:ring-ring
292
296
  peer-disabled:opacity-50 peer-disabled:cursor-not-allowed
293
297
  peer-hover:border-primary/60 peer-active:scale-95
294
298
  ${validationClasses[validationState]} ${className}`
295
- }
296
- )
297
- ] });
299
+ }
300
+ )
301
+ ]
302
+ }
303
+ );
298
304
  }
299
305
  Radio.displayName = "Radio";
300
306
  var radio_default = Radio;
@@ -379,9 +385,7 @@ function MultiSelect({
379
385
  searchInputRef.current.focus();
380
386
  }
381
387
  }, [isOpen]);
382
- const filteredOptions = options.filter(
383
- (option) => option.label.toLowerCase().includes(searchQuery.toLowerCase())
384
- );
388
+ const filteredOptions = options.filter((option) => option.label.toLowerCase().includes(searchQuery.toLowerCase()));
385
389
  const handleToggleOption = (optionValue) => {
386
390
  const isSelected = selectedValues.includes(optionValue);
387
391
  let newValues;
@@ -1165,15 +1169,7 @@ function DatePicker({
1165
1169
  className: "absolute left-0 top-full mt-2 z-50 animate-scaleIn origin-top",
1166
1170
  role: "dialog",
1167
1171
  "aria-label": "Calendar",
1168
- children: /* @__PURE__ */ jsx(
1169
- calendar_default,
1170
- {
1171
- value: selectedDate,
1172
- onChange: handleDateSelect,
1173
- minDate,
1174
- maxDate
1175
- }
1176
- )
1172
+ children: /* @__PURE__ */ jsx(calendar_default, { value: selectedDate, onChange: handleDateSelect, minDate, maxDate })
1177
1173
  }
1178
1174
  )
1179
1175
  ] });
@@ -1315,18 +1311,45 @@ function NavbarLink({ href, children, external = false, className = "", end = fa
1315
1311
  }
1316
1312
  NavbarLink.displayName = "NavbarLink";
1317
1313
  var navbar_link_default = NavbarLink;
1318
- function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1319
- const [activeTab, setActiveTab] = useState(defaultTab || tabs[0]?.id);
1320
- const [isAnimating, setIsAnimating] = useState(false);
1321
- const handleTabChange = (tabId) => {
1322
- if (tabId !== activeTab) {
1323
- setIsAnimating(true);
1324
- setTimeout(() => {
1325
- setActiveTab(tabId);
1326
- setIsAnimating(false);
1327
- }, 150);
1314
+ var PageTransition = ({
1315
+ children,
1316
+ duration = 300,
1317
+ type = "fade",
1318
+ className = ""
1319
+ }) => {
1320
+ const [isVisible, setIsVisible] = React3.useState(false);
1321
+ React3.useEffect(() => {
1322
+ requestAnimationFrame(() => {
1323
+ requestAnimationFrame(() => {
1324
+ setIsVisible(true);
1325
+ });
1326
+ });
1327
+ }, []);
1328
+ const getAnimationStyles = () => {
1329
+ if (type === "none") return "";
1330
+ const baseClasses = "transition-all ease-out";
1331
+ const durationClass = `duration-[${duration}ms]`;
1332
+ if (!isVisible) {
1333
+ switch (type) {
1334
+ case "fade":
1335
+ return `${baseClasses} ${durationClass} opacity-0 translate-y-1`;
1336
+ case "slide":
1337
+ return `${baseClasses} ${durationClass} opacity-0 translate-y-3`;
1338
+ case "scale":
1339
+ return `${baseClasses} ${durationClass} opacity-0 scale-[0.99]`;
1340
+ default:
1341
+ return `${baseClasses} ${durationClass} opacity-0 translate-y-1`;
1342
+ }
1343
+ } else {
1344
+ return `${baseClasses} ${durationClass} opacity-100 translate-y-0 scale-100`;
1328
1345
  }
1329
1346
  };
1347
+ return /* @__PURE__ */ jsx("div", { className: `${getAnimationStyles()} ${className}`.trim(), children });
1348
+ };
1349
+ PageTransition.displayName = "PageTransition";
1350
+ var page_transition_default = PageTransition;
1351
+ function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1352
+ const [activeTab, setActiveTab] = useState(defaultTab || tabs[0]?.id);
1330
1353
  return /* @__PURE__ */ jsxs("div", { className, children: [
1331
1354
  /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": ariaLabel, className: "flex border-b-2 border-border/50", children: tabs.map((tab) => /* @__PURE__ */ jsx(
1332
1355
  "button",
@@ -1335,7 +1358,7 @@ function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1335
1358
  "aria-selected": activeTab === tab.id,
1336
1359
  "aria-controls": `panel-${tab.id}`,
1337
1360
  id: `tab-${tab.id}`,
1338
- onClick: () => handleTabChange(tab.id),
1361
+ onClick: () => setActiveTab(tab.id),
1339
1362
  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"}`,
1340
1363
  children: tab.label
1341
1364
  },
@@ -1348,8 +1371,7 @@ function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1348
1371
  id: `panel-${tab.id}`,
1349
1372
  "aria-labelledby": `tab-${tab.id}`,
1350
1373
  hidden: activeTab !== tab.id,
1351
- className: `pt-6 transition-all duration-200 ${activeTab === tab.id && !isAnimating ? "animate-fadeIn opacity-100" : "opacity-0"}`,
1352
- children: tab.content
1374
+ children: activeTab === tab.id && /* @__PURE__ */ jsx(page_transition_default, { type: "fade", duration: 150, children: /* @__PURE__ */ jsx("div", { className: "pt-6", children: tab.content }) })
1353
1375
  },
1354
1376
  tab.id
1355
1377
  ))
@@ -1358,7 +1380,14 @@ function Tabs({ tabs, defaultTab, className = "", ariaLabel = "Tabs" }) {
1358
1380
  Tabs.displayName = "Tabs";
1359
1381
  var tabs_default = Tabs;
1360
1382
  var DropdownContext = createContext(null);
1361
- function Dropdown({ trigger, children, className = "", align = "start", autoClose = true, size = "md" }) {
1383
+ function Dropdown({
1384
+ trigger,
1385
+ children,
1386
+ className = "",
1387
+ align = "start",
1388
+ autoClose = true,
1389
+ size = "md"
1390
+ }) {
1362
1391
  const [isOpen, setIsOpen] = useState(false);
1363
1392
  const dropdownRef = useRef(null);
1364
1393
  const menuRef = useRef(null);
@@ -1448,9 +1477,9 @@ function Dropdown({ trigger, children, className = "", align = "start", autoClos
1448
1477
  role: "menu",
1449
1478
  "aria-orientation": "vertical",
1450
1479
  tabIndex: -1,
1451
- children: React2.Children.map(children, (child, i) => {
1452
- if (!React2.isValidElement(child)) return child;
1453
- return React2.cloneElement(child, { __dropdownIndex: i, __registerItem: registerItem, size });
1480
+ children: React3.Children.map(children, (child, i) => {
1481
+ if (!React3.isValidElement(child)) return child;
1482
+ return React3.cloneElement(child, { __dropdownIndex: i, __registerItem: registerItem, size });
1454
1483
  })
1455
1484
  }
1456
1485
  ) })
@@ -1896,17 +1925,20 @@ function useOverlay(options) {
1896
1925
  useLayoutEffect(() => {
1897
1926
  if (isOpen) {
1898
1927
  setShouldRender(true);
1899
- setPhase("animating-in");
1900
- let frame = 0;
1901
- const step = () => {
1902
- frame += 1;
1903
- if (frame >= animationFrames) {
1904
- setPhase("visible");
1905
- } else {
1906
- requestAnimationFrame(step);
1907
- }
1908
- };
1909
- requestAnimationFrame(step);
1928
+ setPhase("mount");
1929
+ requestAnimationFrame(() => {
1930
+ setPhase("animating-in");
1931
+ let frame = 0;
1932
+ const step = () => {
1933
+ frame += 1;
1934
+ if (frame >= animationFrames) {
1935
+ setPhase("visible");
1936
+ } else {
1937
+ requestAnimationFrame(step);
1938
+ }
1939
+ };
1940
+ requestAnimationFrame(step);
1941
+ });
1910
1942
  } else if (!isOpen && shouldRender) {
1911
1943
  setPhase("animating-out");
1912
1944
  }
@@ -1939,28 +1971,36 @@ function useOverlay(options) {
1939
1971
  }, [isOpen, lockScroll, restoreFocus]);
1940
1972
  useEffect(() => {
1941
1973
  if (phase === "visible" && containerRef.current) {
1942
- containerRef.current.focus?.();
1974
+ const el = containerRef.current;
1975
+ try {
1976
+ el.focus?.({ preventScroll: true });
1977
+ } catch {
1978
+ el.focus?.();
1979
+ }
1943
1980
  }
1944
1981
  }, [phase]);
1945
- const handleKeyDown = useCallback((e) => {
1946
- if (!focusTrap || phase !== "visible" || e.key !== "Tab" || !containerRef.current) return;
1947
- const node = containerRef.current;
1948
- const focusable = node.querySelectorAll(
1949
- 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'
1950
- );
1951
- if (!focusable.length) return;
1952
- const first = focusable[0];
1953
- const last = focusable[focusable.length - 1];
1954
- if (e.shiftKey) {
1955
- if (document.activeElement === first || document.activeElement === node) {
1982
+ const handleKeyDown = useCallback(
1983
+ (e) => {
1984
+ if (!focusTrap || phase !== "visible" || e.key !== "Tab" || !containerRef.current) return;
1985
+ const node = containerRef.current;
1986
+ const focusable = node.querySelectorAll(
1987
+ 'a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])'
1988
+ );
1989
+ if (!focusable.length) return;
1990
+ const first = focusable[0];
1991
+ const last = focusable[focusable.length - 1];
1992
+ if (e.shiftKey) {
1993
+ if (document.activeElement === first || document.activeElement === node) {
1994
+ e.preventDefault();
1995
+ last.focus();
1996
+ }
1997
+ } else if (document.activeElement === last) {
1956
1998
  e.preventDefault();
1957
- last.focus();
1999
+ first.focus();
1958
2000
  }
1959
- } else if (document.activeElement === last) {
1960
- e.preventDefault();
1961
- first.focus();
1962
- }
1963
- }, [focusTrap, phase]);
2001
+ },
2002
+ [focusTrap, phase]
2003
+ );
1964
2004
  useEffect(() => {
1965
2005
  if (focusTrap && phase === "visible") {
1966
2006
  document.addEventListener("keydown", handleKeyDown);
@@ -1968,19 +2008,40 @@ function useOverlay(options) {
1968
2008
  }
1969
2009
  return void 0;
1970
2010
  }, [phase, focusTrap, handleKeyDown]);
1971
- const getPhaseClass = useCallback((openClass, closedClass) => phase === "visible" ? openClass : closedClass, [phase]);
2011
+ const getPhaseClass = useCallback(
2012
+ (openClass, closedClass) => {
2013
+ return phase === "animating-in" || phase === "visible" ? openClass : closedClass;
2014
+ },
2015
+ [phase]
2016
+ );
1972
2017
  return { phase, shouldRender, ref: containerRef, getPhaseClass };
1973
2018
  }
1974
2019
  var useOverlay_default = useOverlay;
1975
- function Modal({ isOpen, onClose, children, title, description, content, actions, className = "", ariaLabel, align = "center" }) {
1976
- const { phase, shouldRender, ref: dialogRef, getPhaseClass } = useOverlay_default({
2020
+ function Modal({
2021
+ isOpen,
2022
+ onClose,
2023
+ children,
2024
+ title,
2025
+ description,
2026
+ content,
2027
+ actions,
2028
+ className = "",
2029
+ ariaLabel,
2030
+ align = "center"
2031
+ }) {
2032
+ const {
2033
+ phase,
2034
+ shouldRender,
2035
+ ref: dialogRef,
2036
+ getPhaseClass
2037
+ } = useOverlay_default({
1977
2038
  isOpen,
1978
2039
  focusTrap: true,
1979
2040
  lockScroll: true,
1980
2041
  animationFrames: 2,
1981
2042
  restoreFocus: true
1982
2043
  });
1983
- React2.useEffect(() => {
2044
+ React3.useEffect(() => {
1984
2045
  if (!isOpen) return;
1985
2046
  const handleEscape = (e) => {
1986
2047
  if (e.key === "Escape") {
@@ -3020,23 +3081,13 @@ function Card({
3020
3081
  className = "",
3021
3082
  variant = "default",
3022
3083
  size = "md",
3084
+ width = "auto",
3023
3085
  hoverable = false,
3024
3086
  imagePosition = "top",
3025
3087
  centered = false,
3026
3088
  compact = false,
3027
- interactive,
3028
- highlighted,
3029
- maxWidth,
3030
- padding,
3031
3089
  ...props
3032
3090
  }) {
3033
- if (interactive && !hoverable) hoverable = true;
3034
- if (highlighted) variant = "filled";
3035
- if (maxWidth) {
3036
- if (!size || size === "md") {
3037
- size = maxWidth === "2xl" ? "xl" : maxWidth;
3038
- }
3039
- }
3040
3091
  const variantClasses = {
3041
3092
  default: "bg-card text-card-foreground border border-border shadow-md",
3042
3093
  bordered: "bg-card text-card-foreground border-2 border-border",
@@ -3050,6 +3101,11 @@ function Card({
3050
3101
  lg: "w-[28rem]",
3051
3102
  xl: "w-[32rem]"
3052
3103
  };
3104
+ const widthClasses = {
3105
+ auto: size !== "md" ? sizeClasses[size] : "max-w-full",
3106
+ full: "w-full",
3107
+ fit: "w-fit"
3108
+ };
3053
3109
  const hoverClasses = hoverable ? "transition-all duration-300 hover:shadow-xl hover:-translate-y-1 cursor-pointer" : "transition-shadow duration-200";
3054
3110
  const imagePositionClasses = {
3055
3111
  top: "flex-col",
@@ -3065,12 +3121,11 @@ function Card({
3065
3121
  rounded-2xl
3066
3122
  overflow-hidden
3067
3123
  ${variantClasses[variant]}
3068
- ${size !== "md" ? sizeClasses[size] : "max-w-full"}
3124
+ ${widthClasses[width]}
3069
3125
  ${hoverClasses}
3070
3126
  ${imagePositionClasses[imagePosition]}
3071
3127
  ${centerClasses}
3072
3128
  ${compact ? "p-4" : ""}
3073
- ${padding === "none" ? "" : ""}
3074
3129
  ${imagePosition === "side" ? "flex" : "flex"}
3075
3130
  ${className}
3076
3131
  `.trim().replace(/\s+/g, " "),
@@ -3220,88 +3275,216 @@ function CodeBlock({ code, className = "", showCopy = true }) {
3220
3275
  }
3221
3276
  CodeBlock.displayName = "CodeBlock";
3222
3277
  var code_block_default = CodeBlock;
3278
+ function CardBody({ children, padding = "md", className = "" }) {
3279
+ const paddingClasses = {
3280
+ none: "p-0",
3281
+ sm: "p-4",
3282
+ md: "p-6",
3283
+ lg: "p-8",
3284
+ xl: "p-10"
3285
+ };
3286
+ return /* @__PURE__ */ jsx(
3287
+ "div",
3288
+ {
3289
+ className: `
3290
+ card-body
3291
+ flex flex-col gap-2
3292
+ ${paddingClasses[padding]}
3293
+ ${className}
3294
+ `.trim().replace(/\s+/g, " "),
3295
+ children
3296
+ }
3297
+ );
3298
+ }
3299
+ CardBody.displayName = "CardBody";
3300
+ var card_body_default = CardBody;
3301
+ function CardTitle({ children, className = "", as: Component = "h2", size = "md" }) {
3302
+ const sizeClasses = {
3303
+ sm: "text-base font-semibold",
3304
+ md: "text-lg font-bold",
3305
+ lg: "text-xl font-bold",
3306
+ xl: "text-2xl font-bold"
3307
+ };
3308
+ return /* @__PURE__ */ jsx(
3309
+ Component,
3310
+ {
3311
+ className: `
3312
+ card-title
3313
+ ${sizeClasses[size]}
3314
+ ${className}
3315
+ `.trim().replace(/\s+/g, " "),
3316
+ children
3317
+ }
3318
+ );
3319
+ }
3320
+ CardTitle.displayName = "CardTitle";
3321
+ var card_title_default = CardTitle;
3322
+ function CardActions({ children, className = "", align = "end", direction = "row" }) {
3323
+ const alignClasses = {
3324
+ start: "justify-start",
3325
+ center: "justify-center",
3326
+ end: "justify-end",
3327
+ stretch: "justify-stretch"
3328
+ };
3329
+ const directionClasses = {
3330
+ row: "flex-row",
3331
+ column: "flex-col"
3332
+ };
3333
+ return /* @__PURE__ */ jsx(
3334
+ "div",
3335
+ {
3336
+ className: `
3337
+ flex gap-2 px-6 pb-6 pt-2
3338
+ ${directionClasses[direction]}
3339
+ ${alignClasses[align]}
3340
+ ${className}
3341
+ `.trim().replace(/\s+/g, " "),
3342
+ children
3343
+ }
3344
+ );
3345
+ }
3346
+ CardActions.displayName = "CardActions";
3347
+ var card_actions_default = CardActions;
3348
+ function CardFigure({ children, className = "", aspectRatio = "auto" }) {
3349
+ const aspectRatioClasses = {
3350
+ square: "aspect-square",
3351
+ video: "aspect-video",
3352
+ wide: "aspect-[21/9]",
3353
+ portrait: "aspect-[3/4]",
3354
+ auto: ""
3355
+ };
3356
+ return /* @__PURE__ */ jsx(
3357
+ "figure",
3358
+ {
3359
+ className: `
3360
+ card-figure
3361
+ relative overflow-hidden
3362
+ ${aspectRatioClasses[aspectRatio]}
3363
+ ${className}
3364
+ `.trim().replace(/\s+/g, " "),
3365
+ children
3366
+ }
3367
+ );
3368
+ }
3369
+ CardFigure.displayName = "CardFigure";
3370
+ var card_figure_default = CardFigure;
3223
3371
  function Divider({ orientation = "horizontal", className = "", ...props }) {
3224
3372
  const orientationClasses = orientation === "horizontal" ? "w-full h-px" : "h-full w-px";
3225
3373
  return /* @__PURE__ */ jsx("hr", { className: `border-0 bg-border ${orientationClasses} ${className}`, "aria-orientation": orientation, ...props });
3226
3374
  }
3227
3375
  Divider.displayName = "Divider";
3228
3376
  var divider_default = Divider;
3229
- function Drawer({ isOpen, onClose, children, position = "right", className = "", contentAlign = "start", centerVertical = false }) {
3230
- const { phase, shouldRender, ref: panelRef, getPhaseClass } = useOverlay_default({
3377
+ function Drawer({
3378
+ isOpen,
3379
+ onClose,
3380
+ children,
3381
+ position = "right",
3382
+ className = "",
3383
+ title,
3384
+ size = "md",
3385
+ closeOnEscape = true,
3386
+ closeOnOutside = true,
3387
+ unmountOnExit = true,
3388
+ portalRoot = typeof document !== "undefined" ? document.body : null,
3389
+ noAnimation = false
3390
+ }) {
3391
+ const { phase, shouldRender, ref, getPhaseClass } = useOverlay_default({
3231
3392
  isOpen,
3232
- focusTrap: true,
3233
3393
  lockScroll: true,
3234
3394
  restoreFocus: true,
3235
- animationFrames: 2
3395
+ focusTrap: true,
3396
+ unmountOnExit,
3397
+ exitDuration: noAnimation ? 0 : 300,
3398
+ animationFrames: noAnimation ? 0 : 2
3236
3399
  });
3237
- useEffect(() => {
3238
- if (!isOpen) return;
3239
- const handleEscape = (e) => {
3240
- if (e.key === "Escape") onClose();
3241
- };
3242
- document.addEventListener("keydown", handleEscape);
3243
- return () => document.removeEventListener("keydown", handleEscape);
3244
- }, [isOpen, onClose]);
3245
3400
  if (!shouldRender) return null;
3246
- const positionClasses = {
3247
- left: "left-0 top-0 h-full w-80",
3248
- right: "right-0 top-0 h-full w-80",
3249
- top: "top-0 left-0 w-full h-80",
3250
- bottom: "bottom-0 left-0 w-full h-80"
3401
+ const sizeClasses = {
3402
+ sm: "w-72",
3403
+ md: "w-96",
3404
+ lg: "w-[32rem]",
3405
+ xl: "w-[40rem]",
3406
+ full: "w-full max-w-2xl"
3251
3407
  };
3252
- const offscreenTransform = {
3408
+ const edgeClasses = {
3409
+ left: "left-0 top-0 bottom-0",
3410
+ right: "right-0 top-0 bottom-0",
3411
+ top: "top-0 left-0 right-0 h-96",
3412
+ bottom: "bottom-0 left-0 right-0 h-96"
3413
+ };
3414
+ const closedTransform = {
3253
3415
  left: "-translate-x-full",
3254
3416
  right: "translate-x-full",
3255
3417
  top: "-translate-y-full",
3256
3418
  bottom: "translate-y-full"
3257
- }[position];
3258
- const transformClass = getPhaseClass("translate-x-0 translate-y-0", offscreenTransform);
3259
- const overlayOpacity = getPhaseClass("opacity-100", "opacity-0");
3260
- const panelOpacity = getPhaseClass("opacity-100", "opacity-0");
3261
- return /* @__PURE__ */ jsxs(Fragment, { children: [
3419
+ };
3420
+ const openTransform = "translate-x-0 translate-y-0";
3421
+ const panelTransform = noAnimation ? "" : getPhaseClass(openTransform, closedTransform[position]);
3422
+ const overlayOpacity = noAnimation ? "" : getPhaseClass("opacity-100", "opacity-0");
3423
+ const handleKeyDown = (e) => {
3424
+ if (e.key === "Escape" && closeOnEscape) {
3425
+ e.stopPropagation();
3426
+ onClose();
3427
+ }
3428
+ };
3429
+ const panel = /* @__PURE__ */ jsxs(Fragment, { children: [
3262
3430
  /* @__PURE__ */ jsx(
3263
3431
  "div",
3264
3432
  {
3265
- className: `fixed inset-0 bg-black/50 backdrop-blur-sm z-40 transition-opacity duration-300 ease-out will-change-opacity ${overlayOpacity}`,
3266
- onClick: onClose,
3433
+ className: `fixed inset-0 z-40 bg-black/50 backdrop-blur-sm transition-opacity duration-300 ${overlayOpacity}`,
3267
3434
  "aria-hidden": "true",
3435
+ onClick: () => closeOnOutside && onClose(),
3268
3436
  "data-phase": phase
3269
3437
  }
3270
3438
  ),
3271
3439
  /* @__PURE__ */ jsxs(
3272
3440
  "div",
3273
3441
  {
3274
- ref: panelRef,
3275
- 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}`,
3442
+ ref,
3276
3443
  role: "dialog",
3277
3444
  "aria-modal": "true",
3278
- "data-position": position,
3279
- "data-phase": phase,
3445
+ "aria-label": title || "Drawer",
3280
3446
  tabIndex: -1,
3281
- onTransitionEnd: () => {
3282
- },
3447
+ "data-phase": phase,
3448
+ "data-position": position,
3449
+ 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}`,
3450
+ onKeyDown: handleKeyDown,
3283
3451
  children: [
3284
- /* @__PURE__ */ jsx("header", { className: "flex items-center justify-end p-3 border-b border-border", children: /* @__PURE__ */ jsx(
3285
- "button",
3286
- {
3287
- onClick: onClose,
3288
- "aria-label": "Close drawer",
3289
- className: "w-8 h-8 inline-flex items-center justify-center rounded hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring",
3290
- type: "button",
3291
- children: /* @__PURE__ */ jsx("span", { className: "text-sm", children: "\u2715" })
3292
- }
3293
- ) }),
3294
- /* @__PURE__ */ jsx(
3295
- "section",
3296
- {
3297
- 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" : ""}`,
3298
- children
3299
- }
3300
- )
3452
+ title && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/60 bg-card/95 backdrop-blur-sm", children: [
3453
+ /* @__PURE__ */ jsx("h2", { className: "text-base font-semibold tracking-tight", children: title }),
3454
+ /* @__PURE__ */ jsx(
3455
+ "button",
3456
+ {
3457
+ type: "button",
3458
+ "aria-label": "Close drawer",
3459
+ onClick: onClose,
3460
+ 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",
3461
+ children: /* @__PURE__ */ jsxs(
3462
+ "svg",
3463
+ {
3464
+ xmlns: "http://www.w3.org/2000/svg",
3465
+ width: "18",
3466
+ height: "18",
3467
+ viewBox: "0 0 24 24",
3468
+ fill: "none",
3469
+ stroke: "currentColor",
3470
+ strokeWidth: "2",
3471
+ strokeLinecap: "round",
3472
+ strokeLinejoin: "round",
3473
+ children: [
3474
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
3475
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
3476
+ ]
3477
+ }
3478
+ )
3479
+ }
3480
+ )
3481
+ ] }),
3482
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-5 flex flex-col gap-4", children })
3301
3483
  ]
3302
3484
  }
3303
3485
  )
3304
3486
  ] });
3487
+ return portalRoot ? createPortal(panel, portalRoot) : panel;
3305
3488
  }
3306
3489
  Drawer.displayName = "Drawer";
3307
3490
  var drawer_default = Drawer;
@@ -3344,65 +3527,69 @@ Accordion.displayName = "Accordion";
3344
3527
  var accordion_default = Accordion;
3345
3528
  function Hero({
3346
3529
  title,
3530
+ subtitle,
3347
3531
  description,
3348
3532
  primaryAction,
3349
3533
  secondaryAction,
3350
3534
  children,
3351
3535
  className = "",
3352
- backgroundGradient = true,
3536
+ variant = "gradient",
3353
3537
  centered = true,
3354
3538
  size = "lg"
3355
3539
  }) {
3356
3540
  const sizeClasses = {
3357
- sm: "py-12",
3358
- md: "py-16",
3359
- lg: "py-20 md:py-24"
3541
+ sm: "py-12 md:py-16",
3542
+ md: "py-16 md:py-20",
3543
+ lg: "py-20 md:py-28"
3360
3544
  };
3361
3545
  const titleSizes = {
3362
3546
  sm: "text-3xl md:text-4xl",
3363
3547
  md: "text-4xl md:text-5xl",
3364
- lg: "text-4xl md:text-5xl lg:text-6xl"
3548
+ lg: "text-5xl md:text-6xl lg:text-7xl"
3365
3549
  };
3366
- const descriptionSizes = {
3367
- sm: "text-base md:text-lg",
3368
- md: "text-lg md:text-xl",
3369
- lg: "text-xl md:text-2xl"
3550
+ const variantClasses = {
3551
+ gradient: "bg-gradient-to-b from-primary/10 via-primary/5 to-background",
3552
+ solid: "bg-muted/30",
3553
+ minimal: "bg-background"
3370
3554
  };
3371
- return /* @__PURE__ */ jsx(
3372
- "section",
3373
- {
3374
- className: `${sizeClasses[size]} ${backgroundGradient ? "bg-gradient-to-b from-primary/10 via-primary/5 to-background" : "bg-background"} ${className}`,
3375
- children: /* @__PURE__ */ jsx(container_default, { size: "lg", children: /* @__PURE__ */ jsxs("div", { className: centered ? "text-center" : "", children: [
3376
- /* @__PURE__ */ jsx(heading_default, { level: 1, className: `${titleSizes[size]} font-bold mb-4 md:mb-6`, children: title }),
3377
- description && /* @__PURE__ */ jsx(text_default, { className: `${descriptionSizes[size]} mb-6 md:mb-8 ${centered ? "max-w-3xl mx-auto" : "max-w-3xl"}`, children: description }),
3378
- (primaryAction || secondaryAction) && /* @__PURE__ */ jsxs(stack_default, { direction: "horizontal", spacing: "md", className: `flex-wrap ${centered ? "justify-center" : ""}`, children: [
3379
- primaryAction && /* @__PURE__ */ jsx(
3380
- button_default,
3381
- {
3382
- size: "lg",
3383
- variant: primaryAction.variant || "primary",
3384
- style: primaryAction.style,
3385
- onClick: primaryAction.onClick,
3386
- loading: primaryAction.loading,
3387
- children: primaryAction.label
3388
- }
3389
- ),
3390
- secondaryAction && /* @__PURE__ */ jsx(
3391
- button_default,
3392
- {
3393
- size: "lg",
3394
- variant: secondaryAction.variant || "neutral",
3395
- style: secondaryAction.style || "outline",
3396
- onClick: secondaryAction.onClick,
3397
- loading: secondaryAction.loading,
3398
- children: secondaryAction.label
3399
- }
3400
- )
3401
- ] }),
3402
- children && /* @__PURE__ */ jsx("div", { className: "mt-8", children })
3403
- ] }) })
3404
- }
3405
- );
3555
+ return /* @__PURE__ */ jsxs("section", { className: `relative ${sizeClasses[size]} ${variantClasses[variant]} ${className}`, children: [
3556
+ variant === "gradient" && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-primary/20 to-transparent" }),
3557
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-background to-transparent pointer-events-none" }),
3558
+ /* @__PURE__ */ jsx(container_default, { size: "lg", children: /* @__PURE__ */ jsxs("div", { className: centered ? "text-center mx-auto max-w-4xl" : "max-w-4xl", children: [
3559
+ subtitle && /* @__PURE__ */ jsx(text_default, { className: "text-lg md:text-xl font-semibold text-primary mb-4", weight: "semibold", children: subtitle }),
3560
+ /* @__PURE__ */ jsx(heading_default, { level: 1, className: `${titleSizes[size]} font-extrabold mb-6 tracking-tight`, children: title }),
3561
+ description && /* @__PURE__ */ jsx(text_default, { className: "text-lg md:text-xl mb-8 text-muted-foreground max-w-2xl mx-auto", children: description }),
3562
+ (primaryAction || secondaryAction) && /* @__PURE__ */ jsxs(stack_default, { direction: "horizontal", spacing: "md", className: `flex-wrap ${centered ? "justify-center" : ""}`, children: [
3563
+ primaryAction && /* @__PURE__ */ jsx(
3564
+ button_default,
3565
+ {
3566
+ size: "lg",
3567
+ variant: primaryAction.variant || "primary",
3568
+ style: primaryAction.style,
3569
+ onClick: primaryAction.onClick,
3570
+ loading: primaryAction.loading,
3571
+ icon: primaryAction.icon,
3572
+ className: "shadow-lg shadow-primary/20 hover:shadow-xl hover:shadow-primary/30 transition-all",
3573
+ children: primaryAction.label
3574
+ }
3575
+ ),
3576
+ secondaryAction && /* @__PURE__ */ jsx(
3577
+ button_default,
3578
+ {
3579
+ size: "lg",
3580
+ variant: secondaryAction.variant || "neutral",
3581
+ style: secondaryAction.style || "outline",
3582
+ onClick: secondaryAction.onClick,
3583
+ loading: secondaryAction.loading,
3584
+ icon: secondaryAction.icon,
3585
+ className: "hover:shadow-md transition-all",
3586
+ children: secondaryAction.label
3587
+ }
3588
+ )
3589
+ ] }),
3590
+ children && /* @__PURE__ */ jsx("div", { className: "mt-10", children })
3591
+ ] }) })
3592
+ ] });
3406
3593
  }
3407
3594
  Hero.displayName = "Hero";
3408
3595
  var hero_default = Hero;
@@ -3612,7 +3799,14 @@ function LeftNavLayout({
3612
3799
  useScrollReset_default([children], contentRef.current);
3613
3800
  const containerClasses = embedded ? "flex bg-background border border-border rounded-lg overflow-hidden" : "flex h-[calc(100vh-4rem)] bg-background";
3614
3801
  return /* @__PURE__ */ jsxs("div", { className: `${containerClasses} ${className}`, children: [
3615
- mobileCollapsible && mobileMenuOpen && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-40 lg:hidden bg-background/80 backdrop-blur-sm", onClick: toggleMobileMenu, "aria-hidden": "true" }),
3802
+ mobileCollapsible && mobileMenuOpen && /* @__PURE__ */ jsx(
3803
+ "div",
3804
+ {
3805
+ className: "fixed inset-0 z-40 lg:hidden bg-background/80 backdrop-blur-sm",
3806
+ onClick: toggleMobileMenu,
3807
+ "aria-hidden": "true"
3808
+ }
3809
+ ),
3616
3810
  /* @__PURE__ */ jsxs(
3617
3811
  "aside",
3618
3812
  {
@@ -3853,45 +4047,59 @@ function ColorModeToggle({ className = "" }) {
3853
4047
  const toggleTheme = () => {
3854
4048
  setTheme(theme === "light" ? "dark" : "light");
3855
4049
  };
3856
- const getIcon = () => {
3857
- if (theme === "dark") {
3858
- return /* @__PURE__ */ jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
3859
- "path",
3860
- {
3861
- strokeLinecap: "round",
3862
- strokeLinejoin: "round",
3863
- strokeWidth: 2,
3864
- 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"
3865
- }
3866
- ) });
3867
- }
3868
- return /* @__PURE__ */ jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
3869
- "path",
3870
- {
3871
- strokeLinecap: "round",
3872
- strokeLinejoin: "round",
3873
- strokeWidth: 2,
3874
- 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"
3875
- }
3876
- ) });
3877
- };
3878
- const getLabel = () => {
3879
- return `Switch to ${theme === "light" ? "dark" : "light"} theme`;
3880
- };
3881
- return /* @__PURE__ */ jsx(
4050
+ const isDark = theme === "dark";
4051
+ const label = `Switch to ${theme === "light" ? "dark" : "light"} theme`;
4052
+ return /* @__PURE__ */ jsxs(
3882
4053
  "button",
3883
4054
  {
3884
4055
  onClick: toggleTheme,
3885
- className: `p-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors cursor-pointer ${className}`,
3886
- "aria-label": getLabel(),
3887
- title: getLabel(),
3888
- children: getIcon()
4056
+ className: `relative p-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors cursor-pointer ${className}`,
4057
+ "aria-label": label,
4058
+ title: label,
4059
+ children: [
4060
+ /* @__PURE__ */ jsx(
4061
+ "svg",
4062
+ {
4063
+ 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"}`,
4064
+ fill: "none",
4065
+ stroke: "currentColor",
4066
+ viewBox: "0 0 24 24",
4067
+ children: /* @__PURE__ */ jsx(
4068
+ "path",
4069
+ {
4070
+ strokeLinecap: "round",
4071
+ strokeLinejoin: "round",
4072
+ strokeWidth: 2,
4073
+ 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"
4074
+ }
4075
+ )
4076
+ }
4077
+ ),
4078
+ /* @__PURE__ */ jsx(
4079
+ "svg",
4080
+ {
4081
+ className: `w-5 h-5 transition-all duration-300 ${isDark ? "rotate-0 scale-100 opacity-100" : "-rotate-90 scale-0 opacity-0"}`,
4082
+ fill: "none",
4083
+ stroke: "currentColor",
4084
+ viewBox: "0 0 24 24",
4085
+ children: /* @__PURE__ */ jsx(
4086
+ "path",
4087
+ {
4088
+ strokeLinecap: "round",
4089
+ strokeLinejoin: "round",
4090
+ strokeWidth: 2,
4091
+ 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"
4092
+ }
4093
+ )
4094
+ }
4095
+ )
4096
+ ]
3889
4097
  }
3890
4098
  );
3891
4099
  }
3892
4100
  ColorModeToggle.displayName = "ColorModeToggle";
3893
4101
  var color_mode_toggle_default = ColorModeToggle;
3894
4102
 
3895
- export { accordion_default as Accordion, AccordionItem, alert_default as Alert, avatar_default as Avatar, badge_default as Badge, breadcrumbs_default as Breadcrumbs, button_default as Button, button_group_default as ButtonGroup, calendar_default as Calendar, card_default as Card, card_footer_default as CardFooter, card_header_default as CardHeader, checkbox_default as Checkbox, chip_default as Chip, code_default as Code, code_block_default as CodeBlock, color_mode_toggle_default as ColorModeToggle, container_default as Container, data_table_default as DataTable, date_picker_default as DatePicker, delete_dialog_default as DeleteDialog, dialog_default as Dialog, divider_default as Divider, drawer_default as Drawer, dropdown_default as Dropdown, empty_state_default as EmptyState, feature_section_default as FeatureSection, footer_default as Footer, form_field_default as FormField, grid_default as Grid, heading_default as Heading, hero_default as Hero, input_default as Input, input_group_default as InputGroup, left_nav_item_default as LeftNavItem, left_nav_layout_default as LeftNavLayout, left_nav_section_default as LeftNavSection, link_default as Link, List, ListItem, modal_default as Modal, multi_select_default as MultiSelect, nav_default as Nav, navbar_default as Navbar, navbar_brand_default as NavbarBrand, navbar_link_default as NavbarLink, page_default as Page, pagination_default as Pagination, popover_default as Popover, pricing_table_default as PricingTable, pricing_tier_default as PricingTier, progress_bar_default as ProgressBar, radio_default as Radio, radio_group_default as RadioGroup, select_default as Select, select_item_default as SelectItem, sidebar_default as Sidebar, skeleton_default as Skeleton, slider_default as Slider, spinner_default as Spinner, stack_default as Stack, status_label_default as StatusLabel, stepper_default as Stepper, switch_default as Switch, Table, TableBody, TableCell, TableFooter, TableHeadCell, TableHeader, TableRow, tabs_default as Tabs, text_default as Text, textarea_default as Textarea, ThemeProvider, timeline_default as Timeline, TimelineItem, toast_default as Toast, tooltip_default as Tooltip, useTable, useTheme };
4103
+ export { accordion_default as Accordion, AccordionItem, alert_default as Alert, avatar_default as Avatar, badge_default as Badge, breadcrumbs_default as Breadcrumbs, button_default as Button, button_group_default as ButtonGroup, calendar_default as Calendar, card_default as Card, card_actions_default as CardActions, card_body_default as CardBody, card_figure_default as CardFigure, card_footer_default as CardFooter, card_header_default as CardHeader, card_title_default as CardTitle, checkbox_default as Checkbox, chip_default as Chip, code_default as Code, code_block_default as CodeBlock, color_mode_toggle_default as ColorModeToggle, container_default as Container, data_table_default as DataTable, date_picker_default as DatePicker, delete_dialog_default as DeleteDialog, dialog_default as Dialog, divider_default as Divider, drawer_default as Drawer, dropdown_default as Dropdown, empty_state_default as EmptyState, feature_section_default as FeatureSection, footer_default as Footer, form_field_default as FormField, grid_default as Grid, heading_default as Heading, hero_default as Hero, input_default as Input, input_group_default as InputGroup, left_nav_item_default as LeftNavItem, left_nav_layout_default as LeftNavLayout, left_nav_section_default as LeftNavSection, link_default as Link, List, ListItem, modal_default as Modal, multi_select_default as MultiSelect, nav_default as Nav, navbar_default as Navbar, navbar_brand_default as NavbarBrand, navbar_link_default as NavbarLink, page_default as Page, pagination_default as Pagination, popover_default as Popover, pricing_table_default as PricingTable, pricing_tier_default as PricingTier, progress_bar_default as ProgressBar, radio_default as Radio, radio_group_default as RadioGroup, select_default as Select, select_item_default as SelectItem, sidebar_default as Sidebar, skeleton_default as Skeleton, slider_default as Slider, spinner_default as Spinner, stack_default as Stack, status_label_default as StatusLabel, stepper_default as Stepper, switch_default as Switch, Table, TableBody, TableCell, TableFooter, TableHeadCell, TableHeader, TableRow, tabs_default as Tabs, text_default as Text, textarea_default as Textarea, ThemeProvider, timeline_default as Timeline, TimelineItem, toast_default as Toast, tooltip_default as Tooltip, useTable, useTheme };
3896
4104
  //# sourceMappingURL=index.js.map
3897
4105
  //# sourceMappingURL=index.js.map