@hexclave/dashboard-ui-components 1.0.5 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/components/alert.js +4 -4
  2. package/dist/components/alert.js.map +1 -1
  3. package/dist/components/analytics-chart/analytics-chart.js +2 -2
  4. package/dist/components/analytics-chart/index.js +2 -2
  5. package/dist/components/badge.js +1 -1
  6. package/dist/components/badge.js.map +1 -1
  7. package/dist/components/button.js +3 -3
  8. package/dist/components/button.js.map +1 -1
  9. package/dist/components/data-grid/data-grid-toolbar.js +5 -5
  10. package/dist/components/data-grid/data-grid-toolbar.js.map +1 -1
  11. package/dist/components/data-grid/data-grid.d.ts.map +1 -1
  12. package/dist/components/data-grid/data-grid.js +13 -7
  13. package/dist/components/data-grid/data-grid.js.map +1 -1
  14. package/dist/components/data-grid/data-grid.test.js +34 -1
  15. package/dist/components/data-grid/data-grid.test.js.map +1 -1
  16. package/dist/components/data-grid/index.js +2 -2
  17. package/dist/components/data-grid/use-url-state.js +1 -1
  18. package/dist/components/dialog.d.ts +6 -2
  19. package/dist/components/dialog.d.ts.map +1 -1
  20. package/dist/components/dialog.js +14 -10
  21. package/dist/components/dialog.js.map +1 -1
  22. package/dist/components/input.js +12 -9
  23. package/dist/components/input.js.map +1 -1
  24. package/dist/components/pill-toggle.js +1 -1
  25. package/dist/components/pill-toggle.js.map +1 -1
  26. package/dist/components/tabs.js +2 -2
  27. package/dist/components/tabs.js.map +1 -1
  28. package/dist/dashboard-ui-components.global.js +85 -51
  29. package/dist/dashboard-ui-components.global.js.map +4 -4
  30. package/dist/esm/components/alert.js +4 -4
  31. package/dist/esm/components/alert.js.map +1 -1
  32. package/dist/esm/components/analytics-chart/analytics-chart.js +2 -2
  33. package/dist/esm/components/analytics-chart/index.js +2 -2
  34. package/dist/esm/components/badge.js +1 -1
  35. package/dist/esm/components/badge.js.map +1 -1
  36. package/dist/esm/components/button.js +3 -3
  37. package/dist/esm/components/button.js.map +1 -1
  38. package/dist/esm/components/data-grid/data-grid-toolbar.js +5 -5
  39. package/dist/esm/components/data-grid/data-grid-toolbar.js.map +1 -1
  40. package/dist/esm/components/data-grid/data-grid.d.ts.map +1 -1
  41. package/dist/esm/components/data-grid/data-grid.js +13 -7
  42. package/dist/esm/components/data-grid/data-grid.js.map +1 -1
  43. package/dist/esm/components/data-grid/data-grid.test.js +34 -1
  44. package/dist/esm/components/data-grid/data-grid.test.js.map +1 -1
  45. package/dist/esm/components/data-grid/index.js +2 -2
  46. package/dist/esm/components/data-grid/use-url-state.js +1 -1
  47. package/dist/esm/components/dialog.d.ts +6 -2
  48. package/dist/esm/components/dialog.d.ts.map +1 -1
  49. package/dist/esm/components/dialog.js +13 -11
  50. package/dist/esm/components/dialog.js.map +1 -1
  51. package/dist/esm/components/input.js +12 -9
  52. package/dist/esm/components/input.js.map +1 -1
  53. package/dist/esm/components/pill-toggle.js +1 -1
  54. package/dist/esm/components/pill-toggle.js.map +1 -1
  55. package/dist/esm/components/tabs.js +2 -2
  56. package/dist/esm/components/tabs.js.map +1 -1
  57. package/dist/esm/index.d.ts +2 -2
  58. package/dist/esm/index.js +2 -2
  59. package/dist/index.d.ts +2 -2
  60. package/dist/index.js +12 -0
  61. package/package.json +3 -3
  62. package/src/components/alert.tsx +4 -4
  63. package/src/components/badge.tsx +1 -1
  64. package/src/components/button.tsx +3 -3
  65. package/src/components/data-grid/data-grid-toolbar.tsx +12 -12
  66. package/src/components/data-grid/data-grid.test.tsx +42 -1
  67. package/src/components/data-grid/data-grid.tsx +17 -6
  68. package/src/components/dialog.tsx +24 -13
  69. package/src/components/input.tsx +24 -12
  70. package/src/components/pill-toggle.tsx +1 -1
  71. package/src/components/tabs.tsx +6 -3
  72. package/src/index.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.js","names":[],"sources":["../../../src/components/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n cn,\n} from \"@hexclave/ui\";\nimport React from \"react\";\n\nexport type DesignDialogSize =\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"xl\"\n | \"2xl\"\n | \"3xl\"\n | \"4xl\"\n | \"5xl\"\n | \"6xl\"\n | \"7xl\"\n | \"full\";\n\nexport type DesignDialogVariant = \"glassmorphic\" | \"plain\";\n\nconst dialogSizeClasses = new Map<DesignDialogSize, string>([\n [\"sm\", \"max-w-sm\"],\n [\"md\", \"max-w-md\"],\n [\"lg\", \"max-w-lg\"],\n [\"xl\", \"max-w-xl\"],\n [\"2xl\", \"max-w-2xl\"],\n [\"3xl\", \"max-w-3xl\"],\n [\"4xl\", \"max-w-4xl\"],\n [\"5xl\", \"max-w-5xl\"],\n [\"6xl\", \"max-w-6xl\"],\n [\"7xl\", \"max-w-7xl\"],\n [\"full\", \"max-w-[calc(100vw-2rem)]\"],\n]);\n\nconst dialogSurfaceClasses = new Map<DesignDialogVariant, string>([\n [\"glassmorphic\", \"border-0 sm:rounded-2xl bg-background/85 backdrop-blur-2xl ring-1 ring-foreground/[0.06] shadow-[0_24px_48px_-12px_rgba(0,0,0,0.25),0_4px_24px_-8px_rgba(0,0,0,0.12)] dark:bg-background/80 dark:ring-white/[0.06]\"],\n [\"plain\", \"border bg-background shadow-lg sm:rounded-lg\"],\n]);\n\nconst dialogOverlayClasses = new Map<DesignDialogVariant, string | undefined>([\n [\"glassmorphic\", \"bg-black/50 backdrop-blur-sm\"],\n [\"plain\", undefined],\n]);\n\ntype DesignDialogIcon = React.ElementType<{ className?: string }>;\n\ntype DesignDialogRootProps = Omit<React.ComponentProps<typeof Dialog>, \"children\">;\n\nexport type DesignDialogProps = {\n trigger?: React.ReactElement,\n size?: DesignDialogSize,\n variant?: DesignDialogVariant,\n icon?: DesignDialogIcon | null,\n title?: React.ReactNode,\n description?: React.ReactNode,\n headerContent?: React.ReactNode,\n customHeader?: React.ReactNode,\n footer?: React.ReactNode,\n noBodyPadding?: boolean,\n hideTopCloseButton?: boolean,\n className?: string,\n overlayClassName?: string,\n headerClassName?: string,\n bodyClassName?: string,\n footerClassName?: string,\n children?: React.ReactNode,\n} & DesignDialogRootProps;\n\n/**\n * Canonical dashboard modal surface. This wraps the base dialog primitives with\n * a reusable glassmorphic shell and consistent header/body/footer regions.\n */\nexport function DesignDialog({\n trigger,\n size = \"lg\",\n variant = \"glassmorphic\",\n icon: Icon = null,\n title,\n description,\n headerContent,\n customHeader,\n footer,\n noBodyPadding = false,\n hideTopCloseButton = false,\n className,\n overlayClassName,\n headerClassName,\n bodyClassName,\n footerClassName,\n children,\n ...dialogRootProps\n}: DesignDialogProps) {\n const resolvedSizeClass = dialogSizeClasses.get(size) ?? \"max-w-lg\";\n const resolvedSurfaceClass = dialogSurfaceClasses.get(variant) ?? dialogSurfaceClasses.get(\"glassmorphic\");\n const resolvedOverlayClass = cn(dialogOverlayClasses.get(variant), overlayClassName);\n const shouldRenderTopHeaderRow = Icon != null || title != null || description != null;\n const shouldRenderHeader = customHeader != null || shouldRenderTopHeaderRow || headerContent != null;\n // Use toArray + filter(Boolean) instead of Children.count so that\n // expressions like `{condition && <Foo/>}` resolving to `false` don't\n // produce an empty DialogBody (which would still render padding/borders).\n const shouldRenderBody = React.Children.toArray(children).filter(Boolean).length > 0;\n const hasStandardTitle = title != null;\n const needsAccessibleTitleFallback = !hasStandardTitle && customHeader == null;\n\n if (process.env.NODE_ENV !== \"production\" && needsAccessibleTitleFallback) {\n console.warn(\n \"[DesignDialog] Rendered without a `title` or `customHeader`. Every dialog needs an accessible name — pass `title`, or render a `DialogTitle` inside `customHeader`.\",\n );\n }\n\n return (\n <Dialog {...dialogRootProps}>\n {trigger != null && (\n <DialogTrigger asChild>\n {trigger}\n </DialogTrigger>\n )}\n\n <DialogContent\n className={cn(\n \"gap-0 p-0 overflow-hidden\",\n resolvedSizeClass,\n resolvedSurfaceClass,\n className\n )}\n overlayProps={resolvedOverlayClass ? { className: resolvedOverlayClass } : undefined}\n noCloseButton={hideTopCloseButton}\n >\n {needsAccessibleTitleFallback && (\n <DialogTitle className=\"sr-only\">Dialog</DialogTitle>\n )}\n {shouldRenderHeader && (\n <DialogHeader className={cn(\"px-6 pt-6 pb-4 border-b border-foreground/[0.06]\", headerClassName)}>\n {customHeader ?? (\n <>\n {shouldRenderTopHeaderRow && (\n <div className={cn(\"flex items-start gap-3\", Icon == null && \"gap-0\")}>\n {Icon != null && (\n <div className=\"h-9 w-9 rounded-xl bg-primary/10 ring-1 ring-primary/15 flex items-center justify-center shrink-0\">\n <Icon className=\"h-4 w-4 text-primary\" />\n </div>\n )}\n {(title != null || description != null) && (\n <div className=\"flex-1 min-w-0 space-y-1\">\n {title != null ? (\n <DialogTitle className=\"text-base\">\n {title}\n </DialogTitle>\n ) : null}\n {description != null ? (\n <DialogDescription className=\"text-xs\">\n {description}\n </DialogDescription>\n ) : null}\n </div>\n )}\n </div>\n )}\n\n {headerContent != null ? (\n <div className={cn(shouldRenderTopHeaderRow && \"mt-4\")}>\n {headerContent}\n </div>\n ) : null}\n </>\n )}\n </DialogHeader>\n )}\n\n {shouldRenderBody && (\n <DialogBody\n className={cn(\n \"mx-0 my-0 w-auto\",\n noBodyPadding ? \"px-0 py-0\" : \"px-6 py-4\",\n bodyClassName\n )}\n >\n {children}\n </DialogBody>\n )}\n\n {footer != null ? (\n <DialogFooter className={cn(\"px-6 py-3 border-t border-foreground/[0.06] bg-foreground/[0.02]\", footerClassName)}>\n {footer}\n </DialogFooter>\n ) : null}\n </DialogContent>\n </Dialog>\n );\n}\n\nexport const DesignDialogRoot = Dialog;\nexport const DesignDialogTrigger = DialogTrigger;\nexport const DesignDialogClose = DialogClose;\nexport const DesignDialogTitle = DialogTitle;\nexport const DesignDialogDescription = DialogDescription;\n"],"mappings":";;;;;;;AA+BA,MAAM,oBAAoB,IAAI,IAA8B;CAC1D,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,QAAQ,2BAA2B;CACrC,CAAC;AAEF,MAAM,uBAAuB,IAAI,IAAiC,CAChE,CAAC,gBAAgB,qNAAqN,EACtO,CAAC,SAAS,+CAA+C,CAC1D,CAAC;AAEF,MAAM,uBAAuB,IAAI,IAA6C,CAC5E,CAAC,gBAAgB,+BAA+B,EAChD,CAAC,SAAS,OAAU,CACrB,CAAC;;;;;AA8BF,SAAgB,aAAa,EAC3B,SACA,OAAO,MACP,UAAU,gBACV,MAAM,OAAO,MACb,OACA,aACA,eACA,cACA,QACA,gBAAgB,OAChB,qBAAqB,OACrB,WACA,kBACA,iBACA,eACA,iBACA,UACA,GAAG,mBACiB;CACpB,MAAM,oBAAoB,kBAAkB,IAAI,KAAK,IAAI;CACzD,MAAM,uBAAuB,qBAAqB,IAAI,QAAQ,IAAI,qBAAqB,IAAI,eAAe;CAC1G,MAAM,uBAAuB,GAAG,qBAAqB,IAAI,QAAQ,EAAE,iBAAiB;CACpF,MAAM,2BAA2B,QAAQ,QAAQ,SAAS,QAAQ,eAAe;CACjF,MAAM,qBAAqB,gBAAgB,QAAQ,4BAA4B,iBAAiB;CAIhG,MAAM,mBAAmB,MAAM,SAAS,QAAQ,SAAS,CAAC,OAAO,QAAQ,CAAC,SAAS;CAEnF,MAAM,+BAA+B,EADZ,SAAS,SACwB,gBAAgB;AAE1E,KAAI,QAAQ,IAAI,aAAa,gBAAgB,6BAC3C,SAAQ,KACN,sKACD;AAGH,QACE,qBAAC;EAAO,GAAI;aACT,WAAW,QACV,oBAAC;GAAc;aACZ;IACa,EAGlB,qBAAC;GACC,WAAW,GACT,6BACA,mBACA,sBACA,UACD;GACD,cAAc,uBAAuB,EAAE,WAAW,sBAAsB,GAAG;GAC3E,eAAe;;IAEd,gCACC,oBAAC;KAAY,WAAU;eAAU;MAAoB;IAEtD,sBACC,oBAAC;KAAa,WAAW,GAAG,oDAAoD,gBAAgB;eAC7F,gBACC,4CACG,4BACC,qBAAC;MAAI,WAAW,GAAG,0BAA0B,QAAQ,QAAQ,QAAQ;iBAClE,QAAQ,QACP,oBAAC;OAAI,WAAU;iBACb,oBAAC,QAAK,WAAU,yBAAyB;QACrC,GAEN,SAAS,QAAQ,eAAe,SAChC,qBAAC;OAAI,WAAU;kBACZ,SAAS,OACR,oBAAC;QAAY,WAAU;kBACpB;SACW,GACZ,MACH,eAAe,OACd,oBAAC;QAAkB,WAAU;kBAC1B;SACiB,GAClB;QACA;OAEJ,EAGP,iBAAiB,OAChB,oBAAC;MAAI,WAAW,GAAG,4BAA4B,OAAO;gBACnD;OACG,GACJ,QACH;MAEQ;IAGhB,oBACC,oBAAC;KACC,WAAW,GACT,oBACA,gBAAgB,cAAc,aAC9B,cACD;KAEA;MACU;IAGd,UAAU,OACT,oBAAC;KAAa,WAAW,GAAG,oEAAoE,gBAAgB;eAC7G;MACY,GACb;;IACU;GACT;;AAIb,MAAa,mBAAmB;AAChC,MAAa,sBAAsB;AACnC,MAAa,oBAAoB;AACjC,MAAa,oBAAoB;AACjC,MAAa,0BAA0B"}
1
+ {"version":3,"file":"dialog.js","names":[],"sources":["../../../src/components/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n cn,\n} from \"@hexclave/ui\";\nimport React from \"react\";\n\nexport type DesignDialogSize =\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"xl\"\n | \"2xl\"\n | \"3xl\"\n | \"4xl\"\n | \"5xl\"\n | \"6xl\"\n | \"7xl\"\n | \"full\";\n\nexport type DesignDialogVariant = \"glassmorphic\" | \"plain\";\n\nconst dialogSizeClasses = new Map<DesignDialogSize, string>([\n [\"sm\", \"max-w-sm\"],\n [\"md\", \"max-w-md\"],\n [\"lg\", \"max-w-lg\"],\n [\"xl\", \"max-w-xl\"],\n [\"2xl\", \"max-w-2xl\"],\n [\"3xl\", \"max-w-3xl\"],\n [\"4xl\", \"max-w-4xl\"],\n [\"5xl\", \"max-w-5xl\"],\n [\"6xl\", \"max-w-6xl\"],\n [\"7xl\", \"max-w-7xl\"],\n [\"full\", \"max-w-[calc(100vw-2rem)]\"],\n]);\n\nconst dialogSurfaceClasses = new Map<DesignDialogVariant, string>([\n [\"glassmorphic\", \"border-0 sm:rounded-2xl bg-white/95 backdrop-blur-2xl ring-1 ring-black/[0.08] shadow-[0_24px_48px_-12px_rgba(0,0,0,0.25),0_4px_24px_-8px_rgba(0,0,0,0.12)] dark:bg-background/80 dark:ring-white/[0.06]\"],\n [\"plain\", \"border border-black/[0.08] bg-white shadow-lg sm:rounded-lg dark:border-white/[0.06] dark:bg-background\"],\n]);\n\nexport const designDialogGlassmorphicSurfaceClass = dialogSurfaceClasses.get(\"glassmorphic\") ?? \"\";\nexport const designDialogGlassmorphicOverlayClass = \"bg-black/50 backdrop-blur-sm\";\n\ntype DesignDialogIcon = React.ElementType<{ className?: string }>;\n\ntype DesignDialogRootProps = Omit<React.ComponentProps<typeof Dialog>, \"children\">;\n\nexport type DesignDialogProps = {\n trigger?: React.ReactElement,\n size?: DesignDialogSize,\n variant?: DesignDialogVariant,\n icon?: DesignDialogIcon | null,\n title?: React.ReactNode,\n description?: React.ReactNode,\n headerContent?: React.ReactNode,\n customHeader?: React.ReactNode,\n footer?: React.ReactNode,\n noBodyPadding?: boolean,\n hideTopCloseButton?: boolean,\n className?: string,\n overlayClassName?: string,\n headerClassName?: string,\n bodyClassName?: string,\n footerClassName?: string,\n children?: React.ReactNode,\n contentProps?: Omit<\n React.ComponentPropsWithoutRef<typeof DialogContent>,\n \"className\" | \"children\" | \"overlayProps\" | \"noCloseButton\"\n >,\n} & DesignDialogRootProps;\n\n/**\n * Canonical dashboard modal surface. This wraps the base dialog primitives with\n * a reusable glassmorphic shell and consistent header/body/footer regions.\n */\nexport function DesignDialog({\n trigger,\n size = \"lg\",\n variant = \"glassmorphic\",\n icon: Icon = null,\n title,\n description,\n headerContent,\n customHeader,\n footer,\n noBodyPadding = false,\n hideTopCloseButton = false,\n className,\n overlayClassName,\n headerClassName,\n bodyClassName,\n footerClassName,\n contentProps,\n children,\n ...dialogRootProps\n}: DesignDialogProps) {\n const resolvedSizeClass = dialogSizeClasses.get(size) ?? \"max-w-lg\";\n const resolvedSurfaceClass = dialogSurfaceClasses.get(variant) ?? dialogSurfaceClasses.get(\"glassmorphic\");\n const resolvedOverlayClass = cn(\n variant === \"glassmorphic\" ? designDialogGlassmorphicOverlayClass : undefined,\n overlayClassName,\n );\n const shouldRenderTopHeaderRow = Icon != null || title != null || description != null;\n const shouldRenderHeader = customHeader != null || shouldRenderTopHeaderRow || headerContent != null;\n // Use toArray + filter(Boolean) instead of Children.count so that\n // expressions like `{condition && <Foo/>}` resolving to `false` don't\n // produce an empty DialogBody (which would still render padding/borders).\n const shouldRenderBody = React.Children.toArray(children).filter(Boolean).length > 0;\n const hasStandardTitle = title != null;\n const needsAccessibleTitleFallback = !hasStandardTitle && customHeader == null;\n\n if (process.env.NODE_ENV !== \"production\" && needsAccessibleTitleFallback) {\n console.warn(\n \"[DesignDialog] Rendered without a `title` or `customHeader`. Every dialog needs an accessible name — pass `title`, or render a `DialogTitle` inside `customHeader`.\",\n );\n }\n\n return (\n <Dialog {...dialogRootProps}>\n {trigger != null && (\n <DialogTrigger asChild>\n {trigger}\n </DialogTrigger>\n )}\n\n <DialogContent\n className={cn(\n \"gap-0 h-auto max-h-[min(100dvh-2rem,36rem)] overflow-hidden p-0\",\n resolvedSizeClass,\n resolvedSurfaceClass,\n className\n )}\n overlayProps={resolvedOverlayClass ? { className: resolvedOverlayClass } : undefined}\n noCloseButton={hideTopCloseButton}\n {...contentProps}\n >\n {needsAccessibleTitleFallback && (\n <DialogTitle className=\"sr-only\">Dialog</DialogTitle>\n )}\n {shouldRenderHeader && (\n <DialogHeader className={cn(\"shrink-0 px-6 pt-6 pb-4 border-b border-foreground/[0.06]\", headerClassName)}>\n {customHeader ?? (\n <>\n {shouldRenderTopHeaderRow && (\n <div className={cn(\n \"flex gap-3\",\n description != null ? \"items-start\" : \"items-center\",\n Icon == null && \"gap-0\",\n )}>\n {Icon != null && (\n <div className=\"h-9 w-9 rounded-xl bg-primary/10 ring-1 ring-primary/15 flex items-center justify-center shrink-0\">\n <Icon className=\"h-4 w-4 text-primary\" />\n </div>\n )}\n {(title != null || description != null) && (\n <div className=\"flex-1 min-w-0 space-y-1\">\n {title != null ? (\n <DialogTitle className=\"text-base font-semibold leading-snug\">\n {title}\n </DialogTitle>\n ) : null}\n {description != null ? (\n <DialogDescription className=\"text-xs\">\n {description}\n </DialogDescription>\n ) : null}\n </div>\n )}\n </div>\n )}\n\n {headerContent != null ? (\n <div className={cn(shouldRenderTopHeaderRow && \"mt-4\")}>\n {headerContent}\n </div>\n ) : null}\n </>\n )}\n </DialogHeader>\n )}\n\n {shouldRenderBody && (\n <DialogBody\n className={cn(\n \"mx-0 my-0 w-auto min-h-0 overflow-y-auto\",\n noBodyPadding ? \"px-0 py-0\" : \"px-6 py-4\",\n bodyClassName\n )}\n >\n {children}\n </DialogBody>\n )}\n\n {footer != null ? (\n <DialogFooter className={cn(\"shrink-0 px-6 py-3 border-t border-foreground/[0.06] bg-foreground/[0.02]\", footerClassName)}>\n {footer}\n </DialogFooter>\n ) : null}\n </DialogContent>\n </Dialog>\n );\n}\n\nexport const DesignDialogRoot = Dialog;\nexport const DesignDialogTrigger = DialogTrigger;\nexport const DesignDialogClose = DialogClose;\nexport const DesignDialogTitle = DialogTitle;\nexport const DesignDialogDescription = DialogDescription;\n"],"mappings":";;;;;;;AA+BA,MAAM,oBAAoB,IAAI,IAA8B;CAC1D,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,MAAM,WAAW;CAClB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,OAAO,YAAY;CACpB,CAAC,QAAQ,2BAA2B;CACrC,CAAC;AAEF,MAAM,uBAAuB,IAAI,IAAiC,CAChE,CAAC,gBAAgB,2MAA2M,EAC5N,CAAC,SAAS,0GAA0G,CACrH,CAAC;AAEF,MAAa,uCAAuC,qBAAqB,IAAI,eAAe,IAAI;AAChG,MAAa,uCAAuC;;;;;AAkCpD,SAAgB,aAAa,EAC3B,SACA,OAAO,MACP,UAAU,gBACV,MAAM,OAAO,MACb,OACA,aACA,eACA,cACA,QACA,gBAAgB,OAChB,qBAAqB,OACrB,WACA,kBACA,iBACA,eACA,iBACA,cACA,UACA,GAAG,mBACiB;CACpB,MAAM,oBAAoB,kBAAkB,IAAI,KAAK,IAAI;CACzD,MAAM,uBAAuB,qBAAqB,IAAI,QAAQ,IAAI,qBAAqB,IAAI,eAAe;CAC1G,MAAM,uBAAuB,GAC3B,YAAY,iBAAiB,uCAAuC,QACpE,iBACD;CACD,MAAM,2BAA2B,QAAQ,QAAQ,SAAS,QAAQ,eAAe;CACjF,MAAM,qBAAqB,gBAAgB,QAAQ,4BAA4B,iBAAiB;CAIhG,MAAM,mBAAmB,MAAM,SAAS,QAAQ,SAAS,CAAC,OAAO,QAAQ,CAAC,SAAS;CAEnF,MAAM,+BAA+B,EADZ,SAAS,SACwB,gBAAgB;AAE1E,KAAI,QAAQ,IAAI,aAAa,gBAAgB,6BAC3C,SAAQ,KACN,sKACD;AAGH,QACE,qBAAC;EAAO,GAAI;aACT,WAAW,QACV,oBAAC;GAAc;aACZ;IACa,EAGlB,qBAAC;GACC,WAAW,GACT,mEACA,mBACA,sBACA,UACD;GACD,cAAc,uBAAuB,EAAE,WAAW,sBAAsB,GAAG;GAC3E,eAAe;GACf,GAAI;;IAEH,gCACC,oBAAC;KAAY,WAAU;eAAU;MAAoB;IAEtD,sBACC,oBAAC;KAAa,WAAW,GAAG,6DAA6D,gBAAgB;eACtG,gBACC,4CACG,4BACC,qBAAC;MAAI,WAAW,GACd,cACA,eAAe,OAAO,gBAAgB,gBACtC,QAAQ,QAAQ,QACjB;iBACE,QAAQ,QACP,oBAAC;OAAI,WAAU;iBACb,oBAAC,QAAK,WAAU,yBAAyB;QACrC,GAEN,SAAS,QAAQ,eAAe,SAChC,qBAAC;OAAI,WAAU;kBACZ,SAAS,OACR,oBAAC;QAAY,WAAU;kBACpB;SACW,GACZ,MACH,eAAe,OACd,oBAAC;QAAkB,WAAU;kBAC1B;SACiB,GAClB;QACA;OAEJ,EAGP,iBAAiB,OAChB,oBAAC;MAAI,WAAW,GAAG,4BAA4B,OAAO;gBACnD;OACG,GACJ,QACH;MAEQ;IAGhB,oBACC,oBAAC;KACC,WAAW,GACT,4CACA,gBAAgB,cAAc,aAC9B,cACD;KAEA;MACU;IAGd,UAAU,OACT,oBAAC;KAAa,WAAW,GAAG,6EAA6E,gBAAgB;eACtH;MACY,GACb;;IACU;GACT;;AAIb,MAAa,mBAAmB;AAChC,MAAa,sBAAsB;AACnC,MAAa,oBAAoB;AACjC,MAAa,oBAAoB;AACjC,MAAa,0BAA0B"}
@@ -7,37 +7,40 @@ import React from "react";
7
7
 
8
8
  //#region src/components/input.tsx
9
9
  const DesignInput = forwardRefIfNeeded(({ className, type, prefixItem, leadingIcon, size = "md", ...props }, ref) => {
10
- const sizeClasses = size === "sm" ? "h-7 px-2 text-xs" : size === "lg" ? "h-10 px-4 text-sm" : "h-9 px-3 text-sm";
11
- const baseClasses = cn("stack-scope flex w-full rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06]", "file:border-0 file:bg-transparent file:text-sm file:font-medium", "placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/[0.1]", "disabled:cursor-not-allowed disabled:opacity-50", "transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06]", sizeClasses);
10
+ const heightTextClasses = size === "sm" ? "h-7 text-xs" : size === "lg" ? "h-10 text-sm" : "h-9 text-sm";
11
+ const horizontalPaddingClasses = size === "sm" ? "px-2" : size === "lg" ? "px-4" : "px-3";
12
+ const baseClasses = cn("stack-scope flex w-full rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06]", "file:border-0 file:bg-transparent file:text-sm file:font-medium", "placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/[0.1]", "disabled:cursor-not-allowed disabled:opacity-50", "transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06]", heightTextClasses);
13
+ const leadingIconClasses = size === "sm" ? "left-2.5 [&_svg]:size-3" : size === "lg" ? "left-3.5 [&_svg]:size-4" : "left-3 [&_svg]:size-3.5";
14
+ const leadingIconPadding = size === "sm" ? "pl-8" : size === "lg" ? "pl-10" : "pl-9";
12
15
  if (prefixItem) return /* @__PURE__ */ jsxs("div", {
13
- className: "flex flex-row items-center flex-1 rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06] overflow-hidden transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06] focus-within:ring-1 focus-within:ring-foreground/[0.1]",
16
+ className: "flex w-full flex-row items-center overflow-hidden rounded-xl border border-black/[0.08] bg-white/80 shadow-sm ring-1 ring-black/[0.08] transition-all duration-150 hover:bg-white hover:transition-none dark:border-white/[0.06] dark:bg-foreground/[0.03] dark:ring-white/[0.06] focus-within:ring-1 focus-within:ring-foreground/[0.1] dark:hover:bg-foreground/[0.06]",
14
17
  children: [/* @__PURE__ */ jsx("div", {
15
18
  className: cn("flex self-stretch items-center justify-center select-none text-muted-foreground/70 border-r border-black/[0.06] dark:border-white/[0.06] bg-black/[0.03] dark:bg-white/[0.02]", size === "sm" ? "px-2.5 text-xs" : size === "lg" ? "px-3.5 text-sm" : "px-3 text-sm"),
16
19
  children: prefixItem
17
20
  }), /* @__PURE__ */ jsx("input", {
18
21
  type,
19
- className: cn("stack-scope flex w-full bg-transparent", "file:border-0 file:bg-transparent file:text-sm file:font-medium", "placeholder:text-muted-foreground/50 focus-visible:outline-none", "disabled:cursor-not-allowed disabled:opacity-50", sizeClasses, "rounded-none border-0 shadow-none ring-0 focus-visible:ring-0", className),
22
+ className: cn("stack-scope flex w-full bg-transparent", "file:border-0 file:bg-transparent file:text-sm file:font-medium", "placeholder:text-muted-foreground/50 focus-visible:outline-none", "disabled:cursor-not-allowed disabled:opacity-50", heightTextClasses, horizontalPaddingClasses, "rounded-none border-0 shadow-none ring-0 focus-visible:ring-0", className),
20
23
  ref,
21
24
  ...props
22
25
  })]
23
26
  });
24
27
  if (leadingIcon) return /* @__PURE__ */ jsxs("div", {
25
- className: "relative flex flex-row items-center flex-1",
28
+ className: cn("relative w-full", className),
26
29
  children: [/* @__PURE__ */ jsx("div", {
27
- className: "pointer-events-none absolute left-2.5 flex items-center text-muted-foreground",
30
+ className: cn("pointer-events-none absolute top-1/2 -translate-y-1/2 text-muted-foreground [&_svg]:block", leadingIconClasses),
28
31
  children: leadingIcon
29
32
  }), /* @__PURE__ */ jsx("input", {
30
33
  type,
31
- className: cn(baseClasses, "pl-8", className),
34
+ className: cn(baseClasses, leadingIconPadding),
32
35
  ref,
33
36
  ...props
34
37
  })]
35
38
  });
36
39
  return /* @__PURE__ */ jsx("div", {
37
- className: "flex flex-row items-center flex-1",
40
+ className: "w-full",
38
41
  children: /* @__PURE__ */ jsx("input", {
39
42
  type,
40
- className: cn(baseClasses, className),
43
+ className: cn(baseClasses, horizontalPaddingClasses, className),
41
44
  ref,
42
45
  ...props
43
46
  })
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","names":[],"sources":["../../../src/components/input.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRefIfNeeded } from \"@hexclave/shared/dist/utils/react\";\nimport React from \"react\";\n\nimport { cn } from \"@hexclave/ui\";\n\nexport type DesignInputProps = {\n prefixItem?: React.ReactNode,\n leadingIcon?: React.ReactNode,\n size?: \"sm\" | \"md\" | \"lg\",\n} & Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">;\n\nexport const DesignInput = forwardRefIfNeeded<HTMLInputElement, DesignInputProps>(\n ({ className, type, prefixItem, leadingIcon, size = \"md\", ...props }, ref) => {\n const sizeClasses = size === \"sm\"\n ? \"h-7 px-2 text-xs\"\n : size === \"lg\"\n ? \"h-10 px-4 text-sm\"\n : \"h-9 px-3 text-sm\";\n const baseClasses = cn(\n \"stack-scope flex w-full rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06]\",\n \"file:border-0 file:bg-transparent file:text-sm file:font-medium\",\n \"placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/[0.1]\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06]\",\n sizeClasses\n );\n\n if (prefixItem) {\n return (\n <div className=\"flex flex-row items-center flex-1 rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06] overflow-hidden transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06] focus-within:ring-1 focus-within:ring-foreground/[0.1]\">\n <div className={cn(\n \"flex self-stretch items-center justify-center select-none text-muted-foreground/70 border-r border-black/[0.06] dark:border-white/[0.06] bg-black/[0.03] dark:bg-white/[0.02]\",\n size === \"sm\" ? \"px-2.5 text-xs\" : size === \"lg\" ? \"px-3.5 text-sm\" : \"px-3 text-sm\"\n )}>\n {prefixItem}\n </div>\n <input\n type={type}\n className={cn(\n \"stack-scope flex w-full bg-transparent\",\n \"file:border-0 file:bg-transparent file:text-sm file:font-medium\",\n \"placeholder:text-muted-foreground/50 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n sizeClasses,\n \"rounded-none border-0 shadow-none ring-0 focus-visible:ring-0\",\n className\n )}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n\n if (leadingIcon) {\n return (\n <div className=\"relative flex flex-row items-center flex-1\">\n <div className=\"pointer-events-none absolute left-2.5 flex items-center text-muted-foreground\">\n {leadingIcon}\n </div>\n <input\n type={type}\n className={cn(baseClasses, \"pl-8\", className)}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n\n return (\n <div className=\"flex flex-row items-center flex-1\">\n <input\n type={type}\n className={cn(baseClasses, className)}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n);\nDesignInput.displayName = \"DesignInput\";\n"],"mappings":";;;;;;;;AAaA,MAAa,cAAc,oBACxB,EAAE,WAAW,MAAM,YAAY,aAAa,OAAO,MAAM,GAAG,SAAS,QAAQ;CAC5E,MAAM,cAAc,SAAS,OACzB,qBACA,SAAS,OACP,sBACA;CACN,MAAM,cAAc,GAClB,0LACA,mEACA,4HACA,mDACA,oGACA,YACD;AAED,KAAI,WACF,QACE,qBAAC;EAAI,WAAU;aACb,oBAAC;GAAI,WAAW,GACd,iLACA,SAAS,OAAO,mBAAmB,SAAS,OAAO,mBAAmB,eACvE;aACE;IACG,EACN,oBAAC;GACO;GACN,WAAW,GACT,0CACA,mEACA,mEACA,mDACA,aACA,iEACA,UACD;GACI;GACL,GAAI;IACJ;GACE;AAIV,KAAI,YACF,QACE,qBAAC;EAAI,WAAU;aACb,oBAAC;GAAI,WAAU;aACZ;IACG,EACN,oBAAC;GACO;GACN,WAAW,GAAG,aAAa,QAAQ,UAAU;GACxC;GACL,GAAI;IACJ;GACE;AAIV,QACE,oBAAC;EAAI,WAAU;YACb,oBAAC;GACO;GACN,WAAW,GAAG,aAAa,UAAU;GAChC;GACL,GAAI;IACJ;GACE;EAGX;AACD,YAAY,cAAc"}
1
+ {"version":3,"file":"input.js","names":[],"sources":["../../../src/components/input.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRefIfNeeded } from \"@hexclave/shared/dist/utils/react\";\nimport React from \"react\";\n\nimport { cn } from \"@hexclave/ui\";\n\nexport type DesignInputProps = {\n prefixItem?: React.ReactNode,\n leadingIcon?: React.ReactNode,\n size?: \"sm\" | \"md\" | \"lg\",\n} & Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">;\n\nexport const DesignInput = forwardRefIfNeeded<HTMLInputElement, DesignInputProps>(\n ({ className, type, prefixItem, leadingIcon, size = \"md\", ...props }, ref) => {\n const heightTextClasses = size === \"sm\"\n ? \"h-7 text-xs\"\n : size === \"lg\"\n ? \"h-10 text-sm\"\n : \"h-9 text-sm\";\n const horizontalPaddingClasses = size === \"sm\" ? \"px-2\" : size === \"lg\" ? \"px-4\" : \"px-3\";\n const baseClasses = cn(\n \"stack-scope flex w-full rounded-xl border border-black/[0.08] dark:border-white/[0.06] bg-white/80 dark:bg-foreground/[0.03] shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06]\",\n \"file:border-0 file:bg-transparent file:text-sm file:font-medium\",\n \"placeholder:text-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/[0.1]\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"transition-all duration-150 hover:transition-none hover:bg-white dark:hover:bg-foreground/[0.06]\",\n heightTextClasses\n );\n\n const leadingIconClasses = size === \"sm\"\n ? \"left-2.5 [&_svg]:size-3\"\n : size === \"lg\"\n ? \"left-3.5 [&_svg]:size-4\"\n : \"left-3 [&_svg]:size-3.5\";\n const leadingIconPadding = size === \"sm\" ? \"pl-8\" : size === \"lg\" ? \"pl-10\" : \"pl-9\";\n\n if (prefixItem) {\n return (\n <div className=\"flex w-full flex-row items-center overflow-hidden rounded-xl border border-black/[0.08] bg-white/80 shadow-sm ring-1 ring-black/[0.08] transition-all duration-150 hover:bg-white hover:transition-none dark:border-white/[0.06] dark:bg-foreground/[0.03] dark:ring-white/[0.06] focus-within:ring-1 focus-within:ring-foreground/[0.1] dark:hover:bg-foreground/[0.06]\">\n <div className={cn(\n \"flex self-stretch items-center justify-center select-none text-muted-foreground/70 border-r border-black/[0.06] dark:border-white/[0.06] bg-black/[0.03] dark:bg-white/[0.02]\",\n size === \"sm\" ? \"px-2.5 text-xs\" : size === \"lg\" ? \"px-3.5 text-sm\" : \"px-3 text-sm\"\n )}>\n {prefixItem}\n </div>\n <input\n type={type}\n className={cn(\n \"stack-scope flex w-full bg-transparent\",\n \"file:border-0 file:bg-transparent file:text-sm file:font-medium\",\n \"placeholder:text-muted-foreground/50 focus-visible:outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n heightTextClasses,\n horizontalPaddingClasses,\n \"rounded-none border-0 shadow-none ring-0 focus-visible:ring-0\",\n className\n )}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n\n if (leadingIcon) {\n return (\n <div className={cn(\"relative w-full\", className)}>\n <div className={cn(\n \"pointer-events-none absolute top-1/2 -translate-y-1/2 text-muted-foreground [&_svg]:block\",\n leadingIconClasses,\n )}>\n {leadingIcon}\n </div>\n <input\n type={type}\n className={cn(baseClasses, leadingIconPadding)}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n\n return (\n <div className=\"w-full\">\n <input\n type={type}\n className={cn(baseClasses, horizontalPaddingClasses, className)}\n ref={ref}\n {...props}\n />\n </div>\n );\n }\n);\nDesignInput.displayName = \"DesignInput\";\n"],"mappings":";;;;;;;;AAaA,MAAa,cAAc,oBACxB,EAAE,WAAW,MAAM,YAAY,aAAa,OAAO,MAAM,GAAG,SAAS,QAAQ;CAC5E,MAAM,oBAAoB,SAAS,OAC/B,gBACA,SAAS,OACP,iBACA;CACN,MAAM,2BAA2B,SAAS,OAAO,SAAS,SAAS,OAAO,SAAS;CACnF,MAAM,cAAc,GAClB,0LACA,mEACA,4HACA,mDACA,oGACA,kBACD;CAED,MAAM,qBAAqB,SAAS,OAChC,4BACA,SAAS,OACP,4BACA;CACN,MAAM,qBAAqB,SAAS,OAAO,SAAS,SAAS,OAAO,UAAU;AAE9E,KAAI,WACF,QACE,qBAAC;EAAI,WAAU;aACb,oBAAC;GAAI,WAAW,GACd,iLACA,SAAS,OAAO,mBAAmB,SAAS,OAAO,mBAAmB,eACvE;aACE;IACG,EACN,oBAAC;GACO;GACN,WAAW,GACT,0CACA,mEACA,mEACA,mDACA,mBACA,0BACA,iEACA,UACD;GACI;GACL,GAAI;IACJ;GACE;AAIV,KAAI,YACF,QACE,qBAAC;EAAI,WAAW,GAAG,mBAAmB,UAAU;aAC9C,oBAAC;GAAI,WAAW,GACd,6FACA,mBACD;aACE;IACG,EACN,oBAAC;GACO;GACN,WAAW,GAAG,aAAa,mBAAmB;GACzC;GACL,GAAI;IACJ;GACE;AAIV,QACE,oBAAC;EAAI,WAAU;YACb,oBAAC;GACO;GACN,WAAW,GAAG,aAAa,0BAA0B,UAAU;GAC1D;GACL,GAAI;IACJ;GACE;EAGX;AACD,YAAY,cAAc"}
@@ -56,7 +56,7 @@ function DesignPillToggle({ options, selected, onSelect, size = "md", glassmorph
56
56
  type: "button",
57
57
  onClick: () => handleClick(option.id),
58
58
  disabled: loadingOptionId !== null,
59
- className: cn("relative flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none", sizeClass.button, isActive ? cn("bg-background text-foreground shadow-sm ring-1", glassmorphic ? "ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:text-[hsl(240,71%,90%)] dark:ring-[hsl(240,71%,70%)]/20" : activeRingClass) : cn("text-muted-foreground hover:text-foreground", glassmorphic ? "hover:bg-background/50" : "hover:bg-black/[0.06] dark:hover:bg-white/[0.04]")),
59
+ className: cn("relative flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none", sizeClass.button, isActive ? cn("bg-white dark:bg-background text-foreground shadow-sm ring-1", glassmorphic ? "ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:text-[hsl(240,71%,90%)] dark:ring-[hsl(240,71%,70%)]/20" : activeRingClass) : cn("text-muted-foreground hover:text-foreground", glassmorphic ? "hover:bg-background/50" : "hover:bg-black/[0.06] dark:hover:bg-white/[0.04]")),
60
60
  children: [loadingOptionId === option.id && /* @__PURE__ */ jsx(Spinner, {
61
61
  size: 12,
62
62
  className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none"
@@ -1 +1 @@
1
- {"version":3,"file":"pill-toggle.js","names":[],"sources":["../../../src/components/pill-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { cn, Spinner, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"@hexclave/ui\";\nimport { TooltipPortal } from \"@radix-ui/react-tooltip\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { useGlassmorphicDefault } from \"./card\";\n\ntype DesignPillToggleSize = \"sm\" | \"md\" | \"lg\";\ntype DesignPillToggleGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nexport type DesignPillToggleOption = {\n id: string,\n label: string,\n icon?: React.ElementType,\n};\n\nexport type DesignPillToggleProps = {\n options: DesignPillToggleOption[],\n selected: string,\n onSelect: (id: string) => void | Promise<void>,\n size?: DesignPillToggleSize,\n glassmorphic?: boolean,\n gradient?: DesignPillToggleGradient,\n /** When false, hides labels and shows a tooltip on hover instead. Defaults to true. */\n showLabels?: boolean,\n className?: string,\n};\n\ntype SizeClass = {\n button: string,\n icon: string,\n};\n\nconst sizeClasses = new Map<DesignPillToggleSize, SizeClass>([\n [\"sm\", { button: \"px-3 py-1.5 text-xs\", icon: \"h-3.5 w-3.5\" }],\n [\"md\", { button: \"px-4 py-2 text-sm\", icon: \"h-4 w-4\" }],\n [\"lg\", { button: \"px-5 py-2.5 text-sm\", icon: \"h-4 w-4\" }],\n]);\n\nconst gradientClasses = new Map<DesignPillToggleGradient, string>([\n [\"blue\", \"ring-blue-500/20 dark:ring-blue-400/20\"],\n [\"cyan\", \"ring-cyan-500/20 dark:ring-cyan-400/20\"],\n [\"purple\", \"ring-purple-500/20 dark:ring-purple-400/20\"],\n [\"green\", \"ring-emerald-500/20 dark:ring-emerald-400/20\"],\n [\"orange\", \"ring-amber-500/20 dark:ring-amber-400/20\"],\n [\"default\", \"ring-black/[0.12] dark:ring-white/[0.06]\"],\n]);\n\nfunction getMapValueOrThrow<TKey, TValue>(map: Map<TKey, TValue>, key: TKey, mapName: string) {\n const value = map.get(key);\n if (!value) {\n throw new Error(`Missing ${mapName} entry for key \"${String(key)}\"`);\n }\n return value;\n}\n\nexport function DesignPillToggle({\n options,\n selected,\n onSelect,\n size = \"md\",\n glassmorphic: glassmorphicProp,\n gradient = \"default\",\n showLabels = true,\n className,\n}: DesignPillToggleProps) {\n const glassmorphic = useGlassmorphicDefault(glassmorphicProp);\n const sizeClass = getMapValueOrThrow(sizeClasses, size, \"sizeClasses\");\n const activeRingClass = getMapValueOrThrow(gradientClasses, gradient, \"gradientClasses\");\n\n const [loadingOptionId, setLoadingOptionId] = useState<string | null>(null);\n\n const handleClick = (optionId: string) => {\n const result = onSelect(optionId);\n if (result && typeof (result as Promise<void>).then === \"function\") {\n setLoadingOptionId(optionId);\n runAsynchronouslyWithAlert(\n Promise.resolve(result).finally(() => setLoadingOptionId(null))\n );\n }\n };\n\n return (\n <TooltipProvider>\n <div\n className={cn(\n \"inline-flex items-center gap-1 p-1 rounded-xl\",\n glassmorphic\n ? \"bg-foreground/[0.04] backdrop-blur-sm\"\n : \"bg-black/[0.08] dark:bg-white/[0.04]\",\n className\n )}\n >\n {options.map((option) => {\n const isActive = selected === option.id;\n const Icon = option.icon;\n\n const pill = (\n <button\n type=\"button\"\n key={option.id}\n onClick={() => handleClick(option.id)}\n disabled={loadingOptionId !== null}\n className={cn(\n \"relative flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none\",\n sizeClass.button,\n isActive\n ? cn(\n \"bg-background text-foreground shadow-sm ring-1\",\n glassmorphic\n ? \"ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:text-[hsl(240,71%,90%)] dark:ring-[hsl(240,71%,70%)]/20\"\n : activeRingClass\n )\n : cn(\n \"text-muted-foreground hover:text-foreground\",\n glassmorphic\n ? \"hover:bg-background/50\"\n : \"hover:bg-black/[0.06] dark:hover:bg-white/[0.04]\"\n )\n )}\n >\n {loadingOptionId === option.id && (\n <Spinner\n size={12}\n className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none\"\n />\n )}\n <span className={cn(\n \"flex items-center gap-2\",\n loadingOptionId === option.id && \"invisible\"\n )}>\n {Icon && <Icon className={sizeClass.icon} />}\n {showLabels && option.label}\n </span>\n </button>\n );\n\n if (!showLabels) {\n return (\n <Tooltip key={option.id} delayDuration={0}>\n <TooltipTrigger asChild>\n {pill}\n </TooltipTrigger>\n <TooltipPortal>\n <TooltipContent side=\"top\">\n {option.label}\n </TooltipContent>\n </TooltipPortal>\n </Tooltip>\n );\n }\n\n return pill;\n })}\n </div>\n </TooltipProvider>\n );\n}\n"],"mappings":";;;;;;;;;;AAkCA,MAAM,cAAc,IAAI,IAAqC;CAC3D,CAAC,MAAM;EAAE,QAAQ;EAAuB,MAAM;EAAe,CAAC;CAC9D,CAAC,MAAM;EAAE,QAAQ;EAAqB,MAAM;EAAW,CAAC;CACxD,CAAC,MAAM;EAAE,QAAQ;EAAuB,MAAM;EAAW,CAAC;CAC3D,CAAC;AAEF,MAAM,kBAAkB,IAAI,IAAsC;CAChE,CAAC,QAAQ,yCAAyC;CAClD,CAAC,QAAQ,yCAAyC;CAClD,CAAC,UAAU,6CAA6C;CACxD,CAAC,SAAS,+CAA+C;CACzD,CAAC,UAAU,2CAA2C;CACtD,CAAC,WAAW,2CAA2C;CACxD,CAAC;AAEF,SAAS,mBAAiC,KAAwB,KAAW,SAAiB;CAC5F,MAAM,QAAQ,IAAI,IAAI,IAAI;AAC1B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,WAAW,QAAQ,kBAAkB,OAAO,IAAI,CAAC,GAAG;AAEtE,QAAO;;AAGT,SAAgB,iBAAiB,EAC/B,SACA,UACA,UACA,OAAO,MACP,cAAc,kBACd,WAAW,WACX,aAAa,MACb,aACwB;CACxB,MAAM,eAAe,uBAAuB,iBAAiB;CAC7D,MAAM,YAAY,mBAAmB,aAAa,MAAM,cAAc;CACtE,MAAM,kBAAkB,mBAAmB,iBAAiB,UAAU,kBAAkB;CAExF,MAAM,CAAC,iBAAiB,sBAAsB,SAAwB,KAAK;CAE3E,MAAM,eAAe,aAAqB;EACxC,MAAM,SAAS,SAAS,SAAS;AACjC,MAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE,sBAAmB,SAAS;AAC5B,8BACE,QAAQ,QAAQ,OAAO,CAAC,cAAc,mBAAmB,KAAK,CAAC,CAChE;;;AAIL,QACE,oBAAC,6BACC,oBAAC;EACC,WAAW,GACT,iDACA,eACI,0CACA,wCACJ,UACD;YAEA,QAAQ,KAAK,WAAW;GACvB,MAAM,WAAW,aAAa,OAAO;GACrC,MAAM,OAAO,OAAO;GAEpB,MAAM,OACJ,qBAAC;IACC,MAAK;IAEL,eAAe,YAAY,OAAO,GAAG;IACrC,UAAU,oBAAoB;IAC9B,WAAW,GACT,6GACA,UAAU,QACV,WACI,GACA,kDACA,eACI,sHACA,gBACL,GACC,GACA,+CACA,eACI,2BACA,mDACL,CACJ;eAEA,oBAAoB,OAAO,MAC1B,oBAAC;KACC,MAAM;KACN,WAAU;MACV,EAEJ,qBAAC;KAAK,WAAW,GACf,2BACA,oBAAoB,OAAO,MAAM,YAClC;gBACE,QAAQ,oBAAC,QAAK,WAAW,UAAU,OAAQ,EAC3C,cAAc,OAAO;MACjB;MAjCF,OAAO,GAkCL;AAGX,OAAI,CAAC,WACH,QACE,qBAAC;IAAwB,eAAe;eACtC,oBAAC;KAAe;eACb;MACc,EACjB,oBAAC,2BACC,oBAAC;KAAe,MAAK;eAClB,OAAO;MACO,GACH;MARJ,OAAO,GASX;AAId,UAAO;IACP;GACE,GACU"}
1
+ {"version":3,"file":"pill-toggle.js","names":[],"sources":["../../../src/components/pill-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { cn, Spinner, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"@hexclave/ui\";\nimport { TooltipPortal } from \"@radix-ui/react-tooltip\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { useGlassmorphicDefault } from \"./card\";\n\ntype DesignPillToggleSize = \"sm\" | \"md\" | \"lg\";\ntype DesignPillToggleGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nexport type DesignPillToggleOption = {\n id: string,\n label: string,\n icon?: React.ElementType,\n};\n\nexport type DesignPillToggleProps = {\n options: DesignPillToggleOption[],\n selected: string,\n onSelect: (id: string) => void | Promise<void>,\n size?: DesignPillToggleSize,\n glassmorphic?: boolean,\n gradient?: DesignPillToggleGradient,\n /** When false, hides labels and shows a tooltip on hover instead. Defaults to true. */\n showLabels?: boolean,\n className?: string,\n};\n\ntype SizeClass = {\n button: string,\n icon: string,\n};\n\nconst sizeClasses = new Map<DesignPillToggleSize, SizeClass>([\n [\"sm\", { button: \"px-3 py-1.5 text-xs\", icon: \"h-3.5 w-3.5\" }],\n [\"md\", { button: \"px-4 py-2 text-sm\", icon: \"h-4 w-4\" }],\n [\"lg\", { button: \"px-5 py-2.5 text-sm\", icon: \"h-4 w-4\" }],\n]);\n\nconst gradientClasses = new Map<DesignPillToggleGradient, string>([\n [\"blue\", \"ring-blue-500/20 dark:ring-blue-400/20\"],\n [\"cyan\", \"ring-cyan-500/20 dark:ring-cyan-400/20\"],\n [\"purple\", \"ring-purple-500/20 dark:ring-purple-400/20\"],\n [\"green\", \"ring-emerald-500/20 dark:ring-emerald-400/20\"],\n [\"orange\", \"ring-amber-500/20 dark:ring-amber-400/20\"],\n [\"default\", \"ring-black/[0.12] dark:ring-white/[0.06]\"],\n]);\n\nfunction getMapValueOrThrow<TKey, TValue>(map: Map<TKey, TValue>, key: TKey, mapName: string) {\n const value = map.get(key);\n if (!value) {\n throw new Error(`Missing ${mapName} entry for key \"${String(key)}\"`);\n }\n return value;\n}\n\nexport function DesignPillToggle({\n options,\n selected,\n onSelect,\n size = \"md\",\n glassmorphic: glassmorphicProp,\n gradient = \"default\",\n showLabels = true,\n className,\n}: DesignPillToggleProps) {\n const glassmorphic = useGlassmorphicDefault(glassmorphicProp);\n const sizeClass = getMapValueOrThrow(sizeClasses, size, \"sizeClasses\");\n const activeRingClass = getMapValueOrThrow(gradientClasses, gradient, \"gradientClasses\");\n\n const [loadingOptionId, setLoadingOptionId] = useState<string | null>(null);\n\n const handleClick = (optionId: string) => {\n const result = onSelect(optionId);\n if (result && typeof (result as Promise<void>).then === \"function\") {\n setLoadingOptionId(optionId);\n runAsynchronouslyWithAlert(\n Promise.resolve(result).finally(() => setLoadingOptionId(null))\n );\n }\n };\n\n return (\n <TooltipProvider>\n <div\n className={cn(\n \"inline-flex items-center gap-1 p-1 rounded-xl\",\n glassmorphic\n ? \"bg-foreground/[0.04] backdrop-blur-sm\"\n : \"bg-black/[0.08] dark:bg-white/[0.04]\",\n className\n )}\n >\n {options.map((option) => {\n const isActive = selected === option.id;\n const Icon = option.icon;\n\n const pill = (\n <button\n type=\"button\"\n key={option.id}\n onClick={() => handleClick(option.id)}\n disabled={loadingOptionId !== null}\n className={cn(\n \"relative flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none\",\n sizeClass.button,\n isActive\n ? cn(\n \"bg-white dark:bg-background text-foreground shadow-sm ring-1\",\n glassmorphic\n ? \"ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:text-[hsl(240,71%,90%)] dark:ring-[hsl(240,71%,70%)]/20\"\n : activeRingClass\n )\n : cn(\n \"text-muted-foreground hover:text-foreground\",\n glassmorphic\n ? \"hover:bg-background/50\"\n : \"hover:bg-black/[0.06] dark:hover:bg-white/[0.04]\"\n )\n )}\n >\n {loadingOptionId === option.id && (\n <Spinner\n size={12}\n className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none\"\n />\n )}\n <span className={cn(\n \"flex items-center gap-2\",\n loadingOptionId === option.id && \"invisible\"\n )}>\n {Icon && <Icon className={sizeClass.icon} />}\n {showLabels && option.label}\n </span>\n </button>\n );\n\n if (!showLabels) {\n return (\n <Tooltip key={option.id} delayDuration={0}>\n <TooltipTrigger asChild>\n {pill}\n </TooltipTrigger>\n <TooltipPortal>\n <TooltipContent side=\"top\">\n {option.label}\n </TooltipContent>\n </TooltipPortal>\n </Tooltip>\n );\n }\n\n return pill;\n })}\n </div>\n </TooltipProvider>\n );\n}\n"],"mappings":";;;;;;;;;;AAkCA,MAAM,cAAc,IAAI,IAAqC;CAC3D,CAAC,MAAM;EAAE,QAAQ;EAAuB,MAAM;EAAe,CAAC;CAC9D,CAAC,MAAM;EAAE,QAAQ;EAAqB,MAAM;EAAW,CAAC;CACxD,CAAC,MAAM;EAAE,QAAQ;EAAuB,MAAM;EAAW,CAAC;CAC3D,CAAC;AAEF,MAAM,kBAAkB,IAAI,IAAsC;CAChE,CAAC,QAAQ,yCAAyC;CAClD,CAAC,QAAQ,yCAAyC;CAClD,CAAC,UAAU,6CAA6C;CACxD,CAAC,SAAS,+CAA+C;CACzD,CAAC,UAAU,2CAA2C;CACtD,CAAC,WAAW,2CAA2C;CACxD,CAAC;AAEF,SAAS,mBAAiC,KAAwB,KAAW,SAAiB;CAC5F,MAAM,QAAQ,IAAI,IAAI,IAAI;AAC1B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,WAAW,QAAQ,kBAAkB,OAAO,IAAI,CAAC,GAAG;AAEtE,QAAO;;AAGT,SAAgB,iBAAiB,EAC/B,SACA,UACA,UACA,OAAO,MACP,cAAc,kBACd,WAAW,WACX,aAAa,MACb,aACwB;CACxB,MAAM,eAAe,uBAAuB,iBAAiB;CAC7D,MAAM,YAAY,mBAAmB,aAAa,MAAM,cAAc;CACtE,MAAM,kBAAkB,mBAAmB,iBAAiB,UAAU,kBAAkB;CAExF,MAAM,CAAC,iBAAiB,sBAAsB,SAAwB,KAAK;CAE3E,MAAM,eAAe,aAAqB;EACxC,MAAM,SAAS,SAAS,SAAS;AACjC,MAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE,sBAAmB,SAAS;AAC5B,8BACE,QAAQ,QAAQ,OAAO,CAAC,cAAc,mBAAmB,KAAK,CAAC,CAChE;;;AAIL,QACE,oBAAC,6BACC,oBAAC;EACC,WAAW,GACT,iDACA,eACI,0CACA,wCACJ,UACD;YAEA,QAAQ,KAAK,WAAW;GACvB,MAAM,WAAW,aAAa,OAAO;GACrC,MAAM,OAAO,OAAO;GAEpB,MAAM,OACJ,qBAAC;IACC,MAAK;IAEL,eAAe,YAAY,OAAO,GAAG;IACrC,UAAU,oBAAoB;IAC9B,WAAW,GACT,6GACA,UAAU,QACV,WACI,GACA,gEACA,eACI,sHACA,gBACL,GACC,GACA,+CACA,eACI,2BACA,mDACL,CACJ;eAEA,oBAAoB,OAAO,MAC1B,oBAAC;KACC,MAAM;KACN,WAAU;MACV,EAEJ,qBAAC;KAAK,WAAW,GACf,2BACA,oBAAoB,OAAO,MAAM,YAClC;gBACE,QAAQ,oBAAC,QAAK,WAAW,UAAU,OAAQ,EAC3C,cAAc,OAAO;MACjB;MAjCF,OAAO,GAkCL;AAGX,OAAI,CAAC,WACH,QACE,qBAAC;IAAwB,eAAe;eACtC,oBAAC;KAAe;eACb;MACc,EACjB,oBAAC,2BACC,oBAAC;KAAe,MAAK;eAClB,OAAO;MACO,GACH;MARJ,OAAO,GASX;AAId,UAAO;IACP;GACE,GACU"}
@@ -64,7 +64,7 @@ function DesignCategoryTabs({ categories, selectedCategory, onSelect, showBadge
64
64
  }
65
65
  };
66
66
  return /* @__PURE__ */ jsxs("div", {
67
- className: cn("flex w-full min-w-0 items-center gap-2", glassmorphic ? "rounded-xl bg-black/[0.08] dark:bg-white/[0.04] p-1 backdrop-blur-sm" : "border-b border-gray-300 dark:border-gray-800", className),
67
+ className: cn("flex w-full min-w-0 items-center gap-2", glassmorphic ? "rounded-xl bg-zinc-100/90 p-1 ring-1 ring-black/[0.06] backdrop-blur-sm dark:bg-white/[0.04] dark:ring-white/[0.06]" : "border-b border-gray-300 dark:border-gray-800", className),
68
68
  ...props,
69
69
  children: [/* @__PURE__ */ jsx("div", {
70
70
  className: cn("flex min-h-0 min-w-0 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden"),
@@ -75,7 +75,7 @@ function DesignCategoryTabs({ categories, selectedCategory, onSelect, showBadge
75
75
  return /* @__PURE__ */ jsxs("button", {
76
76
  onClick: () => handleSelect(category.id),
77
77
  disabled: loadingCategoryId !== null,
78
- className: cn("font-medium transition-all duration-150 hover:transition-none relative flex flex-shrink-0 items-center justify-center gap-2 whitespace-nowrap", "hover:text-gray-900 dark:hover:text-gray-100", sizeClass.button, glassmorphic ? "rounded-lg" : "", isActive ? cn(gradientClass.activeText, glassmorphic && "bg-background shadow-sm ring-1 ring-black/[0.12] dark:ring-white/[0.06]") : "text-gray-700 dark:text-gray-400"),
78
+ className: cn("font-medium transition-all duration-150 hover:transition-none relative flex flex-shrink-0 items-center justify-center gap-2 whitespace-nowrap", "hover:text-gray-900 dark:hover:text-gray-100", sizeClass.button, glassmorphic ? "rounded-lg" : "", isActive ? cn(gradientClass.activeText, glassmorphic && "bg-white shadow-sm ring-1 ring-black/[0.12] dark:bg-background dark:ring-white/[0.06]") : cn("text-gray-700 dark:text-gray-400", glassmorphic && "rounded-lg hover:bg-white/50 dark:hover:bg-white/[0.06]")),
79
79
  children: [
80
80
  loadingCategoryId === category.id && /* @__PURE__ */ jsx(Spinner, {
81
81
  size: 12,
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","names":[],"sources":["../../../src/components/tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, type ReactNode } from \"react\";\nimport { cn, Spinner } from \"@hexclave/ui\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { useGlassmorphicDefault } from \"./card\";\n\ntype DesignTabsSize = \"sm\" | \"md\";\ntype DesignTabsGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nexport type DesignCategoryTabItem = {\n id: string,\n label: string,\n count?: number,\n badgeCount?: number,\n icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>,\n};\n\nexport type DesignCategoryTabsProps = Omit<React.ComponentProps<\"div\">, \"onSelect\"> & {\n categories: DesignCategoryTabItem[],\n selectedCategory: string,\n onSelect: (id: string) => void | Promise<void>,\n showBadge?: boolean,\n size?: DesignTabsSize,\n glassmorphic?: boolean,\n gradient?: DesignTabsGradient,\n /** Renders inside the tab bar after the tab buttons (not a tab). */\n trailing?: ReactNode,\n};\n\ntype TabSizeClass = {\n button: string,\n badge: string,\n};\n\ntype GradientClass = {\n activeText: string,\n activeBadge: string,\n underline: string,\n};\n\nconst tabSizeClasses = new Map<DesignTabsSize, TabSizeClass>([\n [\"sm\", { button: \"px-3 py-2 text-xs\", badge: \"text-[10px] px-1.5 py-0.5\" }],\n [\"md\", { button: \"px-4 py-3 text-sm\", badge: \"text-xs px-1.5 py-0.5\" }],\n]);\n\nconst gradientClasses = new Map<DesignTabsGradient, GradientClass>([\n [\n \"blue\",\n {\n activeText: \"text-blue-700 dark:text-blue-400\",\n activeBadge: \"bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400\",\n underline: \"bg-blue-700 dark:bg-blue-400\",\n },\n ],\n [\n \"cyan\",\n {\n activeText: \"text-cyan-700 dark:text-cyan-300\",\n activeBadge: \"bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300\",\n underline: \"bg-cyan-600 dark:bg-cyan-400\",\n },\n ],\n [\n \"purple\",\n {\n activeText: \"text-purple-700 dark:text-purple-300\",\n activeBadge: \"bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300\",\n underline: \"bg-purple-600 dark:bg-purple-400\",\n },\n ],\n [\n \"green\",\n {\n activeText: \"text-emerald-700 dark:text-emerald-300\",\n activeBadge: \"bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300\",\n underline: \"bg-emerald-600 dark:bg-emerald-400\",\n },\n ],\n [\n \"orange\",\n {\n activeText: \"text-amber-700 dark:text-amber-300\",\n activeBadge: \"bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300\",\n underline: \"bg-amber-600 dark:bg-amber-400\",\n },\n ],\n [\n \"default\",\n {\n activeText: \"text-foreground\",\n activeBadge: \"bg-foreground/10 text-foreground\",\n underline: \"bg-foreground/80\",\n },\n ],\n]);\n\nfunction getMapValueOrThrow<TKey, TValue>(map: Map<TKey, TValue>, key: TKey, mapName: string) {\n const value = map.get(key);\n if (!value) {\n throw new Error(`Missing ${mapName} entry for key \"${String(key)}\"`);\n }\n return value;\n}\n\nexport function DesignCategoryTabs({\n categories,\n selectedCategory,\n onSelect,\n showBadge = true,\n size = \"sm\",\n glassmorphic: glassmorphicProp,\n gradient = \"blue\",\n trailing,\n className,\n ...props\n}: DesignCategoryTabsProps) {\n const glassmorphic = useGlassmorphicDefault(glassmorphicProp);\n const sizeClass = getMapValueOrThrow(tabSizeClasses, size, \"tabSizeClasses\");\n const gradientClass = getMapValueOrThrow(gradientClasses, gradient, \"gradientClasses\");\n const [loadingCategoryId, setLoadingCategoryId] = useState<string | null>(null);\n\n const handleSelect = (categoryId: string) => {\n const result = onSelect(categoryId);\n if (result && typeof (result as Promise<void>).then === \"function\") {\n setLoadingCategoryId(categoryId);\n runAsynchronouslyWithAlert(\n Promise.resolve(result).finally(() => setLoadingCategoryId(null))\n );\n }\n };\n\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 items-center gap-2\",\n glassmorphic\n ? \"rounded-xl bg-black/[0.08] dark:bg-white/[0.04] p-1 backdrop-blur-sm\"\n : \"border-b border-gray-300 dark:border-gray-800\",\n className\n )}\n {...props}\n >\n <div\n className={cn(\n \"flex min-h-0 min-w-0 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden\",\n )}\n >\n {categories.map((category) => {\n const isActive = selectedCategory === category.id;\n const badgeValue = category.badgeCount ?? category.count;\n const shouldShowBadge = showBadge && badgeValue !== undefined;\n\n return (\n <button\n key={category.id}\n onClick={() => handleSelect(category.id)}\n disabled={loadingCategoryId !== null}\n className={cn(\n \"font-medium transition-all duration-150 hover:transition-none relative flex flex-shrink-0 items-center justify-center gap-2 whitespace-nowrap\",\n \"hover:text-gray-900 dark:hover:text-gray-100\",\n sizeClass.button,\n glassmorphic ? \"rounded-lg\" : \"\",\n isActive\n ? cn(\n gradientClass.activeText,\n glassmorphic && \"bg-background shadow-sm ring-1 ring-black/[0.12] dark:ring-white/[0.06]\"\n )\n : \"text-gray-700 dark:text-gray-400\"\n )}\n >\n {loadingCategoryId === category.id && (\n <Spinner\n size={12}\n className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none\"\n />\n )}\n <span className={cn(\n \"flex items-center gap-2\",\n loadingCategoryId === category.id && \"invisible\"\n )}>\n {category.icon && (\n <category.icon className=\"h-4 w-4 shrink-0\" aria-hidden />\n )}\n {category.label}\n {shouldShowBadge && (\n <span\n className={cn(\n \"rounded-full\",\n sizeClass.badge,\n isActive\n ? gradientClass.activeBadge\n : \"bg-gray-200 dark:bg-gray-800 text-gray-600 dark:text-gray-400\"\n )}\n >\n {badgeValue}\n </span>\n )}\n </span>\n {!glassmorphic && isActive && (\n <div className={cn(\"absolute bottom-0 left-0 right-0 h-0.5\", gradientClass.underline)} />\n )}\n </button>\n );\n })}\n </div>\n {trailing != null ? (\n <div className=\"flex shrink-0 items-center\">\n {trailing}\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAyCA,MAAM,iBAAiB,IAAI,IAAkC,CAC3D,CAAC,MAAM;CAAE,QAAQ;CAAqB,OAAO;CAA6B,CAAC,EAC3E,CAAC,MAAM;CAAE,QAAQ;CAAqB,OAAO;CAAyB,CAAC,CACxE,CAAC;AAEF,MAAM,kBAAkB,IAAI,IAAuC;CACjE,CACE,QACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,QACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,UACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,SACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,UACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,WACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACF,CAAC;AAEF,SAAS,mBAAiC,KAAwB,KAAW,SAAiB;CAC5F,MAAM,QAAQ,IAAI,IAAI,IAAI;AAC1B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,WAAW,QAAQ,kBAAkB,OAAO,IAAI,CAAC,GAAG;AAEtE,QAAO;;AAGT,SAAgB,mBAAmB,EACjC,YACA,kBACA,UACA,YAAY,MACZ,OAAO,MACP,cAAc,kBACd,WAAW,QACX,UACA,WACA,GAAG,SACuB;CAC1B,MAAM,eAAe,uBAAuB,iBAAiB;CAC7D,MAAM,YAAY,mBAAmB,gBAAgB,MAAM,iBAAiB;CAC5E,MAAM,gBAAgB,mBAAmB,iBAAiB,UAAU,kBAAkB;CACtF,MAAM,CAAC,mBAAmB,wBAAwB,SAAwB,KAAK;CAE/E,MAAM,gBAAgB,eAAuB;EAC3C,MAAM,SAAS,SAAS,WAAW;AACnC,MAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE,wBAAqB,WAAW;AAChC,8BACE,QAAQ,QAAQ,OAAO,CAAC,cAAc,qBAAqB,KAAK,CAAC,CAClE;;;AAIL,QACE,qBAAC;EACC,WAAW,GACT,0CACA,eACI,yEACA,iDACJ,UACD;EACD,GAAI;aAEJ,oBAAC;GACC,WAAW,GACT,oGACD;aAEA,WAAW,KAAK,aAAa;IAC5B,MAAM,WAAW,qBAAqB,SAAS;IAC/C,MAAM,aAAa,SAAS,cAAc,SAAS;IACnD,MAAM,kBAAkB,aAAa,eAAe;AAEpD,WACE,qBAAC;KAEC,eAAe,aAAa,SAAS,GAAG;KACxC,UAAU,sBAAsB;KAChC,WAAW,GACT,iJACA,gDACA,UAAU,QACV,eAAe,eAAe,IAC9B,WACI,GACA,cAAc,YACd,gBAAgB,0EACjB,GACC,mCACL;;MAEA,sBAAsB,SAAS,MAC9B,oBAAC;OACC,MAAM;OACN,WAAU;QACV;MAEJ,qBAAC;OAAK,WAAW,GACf,2BACA,sBAAsB,SAAS,MAAM,YACtC;;QACE,SAAS,QACR,oBAAC,SAAS;SAAK,WAAU;SAAmB;UAAc;QAE3D,SAAS;QACT,mBACC,oBAAC;SACC,WAAW,GACT,gBACA,UAAU,OACV,WACI,cAAc,cACd,gEACL;mBAEA;UACI;;QAEJ;MACN,CAAC,gBAAgB,YAChB,oBAAC,SAAI,WAAW,GAAG,0CAA0C,cAAc,UAAU,GAAI;;OA7CtF,SAAS,GA+CP;KAEX;IACE,EACL,YAAY,OACX,oBAAC;GAAI,WAAU;aACZ;IACG,GACJ;GACA"}
1
+ {"version":3,"file":"tabs.js","names":[],"sources":["../../../src/components/tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, type ReactNode } from \"react\";\nimport { cn, Spinner } from \"@hexclave/ui\";\nimport { runAsynchronouslyWithAlert } from \"@hexclave/shared/dist/utils/promises\";\nimport { useGlassmorphicDefault } from \"./card\";\n\ntype DesignTabsSize = \"sm\" | \"md\";\ntype DesignTabsGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nexport type DesignCategoryTabItem = {\n id: string,\n label: string,\n count?: number,\n badgeCount?: number,\n icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>,\n};\n\nexport type DesignCategoryTabsProps = Omit<React.ComponentProps<\"div\">, \"onSelect\"> & {\n categories: DesignCategoryTabItem[],\n selectedCategory: string,\n onSelect: (id: string) => void | Promise<void>,\n showBadge?: boolean,\n size?: DesignTabsSize,\n glassmorphic?: boolean,\n gradient?: DesignTabsGradient,\n /** Renders inside the tab bar after the tab buttons (not a tab). */\n trailing?: ReactNode,\n};\n\ntype TabSizeClass = {\n button: string,\n badge: string,\n};\n\ntype GradientClass = {\n activeText: string,\n activeBadge: string,\n underline: string,\n};\n\nconst tabSizeClasses = new Map<DesignTabsSize, TabSizeClass>([\n [\"sm\", { button: \"px-3 py-2 text-xs\", badge: \"text-[10px] px-1.5 py-0.5\" }],\n [\"md\", { button: \"px-4 py-3 text-sm\", badge: \"text-xs px-1.5 py-0.5\" }],\n]);\n\nconst gradientClasses = new Map<DesignTabsGradient, GradientClass>([\n [\n \"blue\",\n {\n activeText: \"text-blue-700 dark:text-blue-400\",\n activeBadge: \"bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400\",\n underline: \"bg-blue-700 dark:bg-blue-400\",\n },\n ],\n [\n \"cyan\",\n {\n activeText: \"text-cyan-700 dark:text-cyan-300\",\n activeBadge: \"bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300\",\n underline: \"bg-cyan-600 dark:bg-cyan-400\",\n },\n ],\n [\n \"purple\",\n {\n activeText: \"text-purple-700 dark:text-purple-300\",\n activeBadge: \"bg-purple-100 dark:bg-purple-900/30 text-purple-700 dark:text-purple-300\",\n underline: \"bg-purple-600 dark:bg-purple-400\",\n },\n ],\n [\n \"green\",\n {\n activeText: \"text-emerald-700 dark:text-emerald-300\",\n activeBadge: \"bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300\",\n underline: \"bg-emerald-600 dark:bg-emerald-400\",\n },\n ],\n [\n \"orange\",\n {\n activeText: \"text-amber-700 dark:text-amber-300\",\n activeBadge: \"bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300\",\n underline: \"bg-amber-600 dark:bg-amber-400\",\n },\n ],\n [\n \"default\",\n {\n activeText: \"text-foreground\",\n activeBadge: \"bg-foreground/10 text-foreground\",\n underline: \"bg-foreground/80\",\n },\n ],\n]);\n\nfunction getMapValueOrThrow<TKey, TValue>(map: Map<TKey, TValue>, key: TKey, mapName: string) {\n const value = map.get(key);\n if (!value) {\n throw new Error(`Missing ${mapName} entry for key \"${String(key)}\"`);\n }\n return value;\n}\n\nexport function DesignCategoryTabs({\n categories,\n selectedCategory,\n onSelect,\n showBadge = true,\n size = \"sm\",\n glassmorphic: glassmorphicProp,\n gradient = \"blue\",\n trailing,\n className,\n ...props\n}: DesignCategoryTabsProps) {\n const glassmorphic = useGlassmorphicDefault(glassmorphicProp);\n const sizeClass = getMapValueOrThrow(tabSizeClasses, size, \"tabSizeClasses\");\n const gradientClass = getMapValueOrThrow(gradientClasses, gradient, \"gradientClasses\");\n const [loadingCategoryId, setLoadingCategoryId] = useState<string | null>(null);\n\n const handleSelect = (categoryId: string) => {\n const result = onSelect(categoryId);\n if (result && typeof (result as Promise<void>).then === \"function\") {\n setLoadingCategoryId(categoryId);\n runAsynchronouslyWithAlert(\n Promise.resolve(result).finally(() => setLoadingCategoryId(null))\n );\n }\n };\n\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 items-center gap-2\",\n glassmorphic\n ? \"rounded-xl bg-zinc-100/90 p-1 ring-1 ring-black/[0.06] backdrop-blur-sm dark:bg-white/[0.04] dark:ring-white/[0.06]\"\n : \"border-b border-gray-300 dark:border-gray-800\",\n className\n )}\n {...props}\n >\n <div\n className={cn(\n \"flex min-h-0 min-w-0 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden\",\n )}\n >\n {categories.map((category) => {\n const isActive = selectedCategory === category.id;\n const badgeValue = category.badgeCount ?? category.count;\n const shouldShowBadge = showBadge && badgeValue !== undefined;\n\n return (\n <button\n key={category.id}\n onClick={() => handleSelect(category.id)}\n disabled={loadingCategoryId !== null}\n className={cn(\n \"font-medium transition-all duration-150 hover:transition-none relative flex flex-shrink-0 items-center justify-center gap-2 whitespace-nowrap\",\n \"hover:text-gray-900 dark:hover:text-gray-100\",\n sizeClass.button,\n glassmorphic ? \"rounded-lg\" : \"\",\n isActive\n ? cn(\n gradientClass.activeText,\n glassmorphic && \"bg-white shadow-sm ring-1 ring-black/[0.12] dark:bg-background dark:ring-white/[0.06]\"\n )\n : cn(\n \"text-gray-700 dark:text-gray-400\",\n glassmorphic && \"rounded-lg hover:bg-white/50 dark:hover:bg-white/[0.06]\",\n )\n )}\n >\n {loadingCategoryId === category.id && (\n <Spinner\n size={12}\n className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none\"\n />\n )}\n <span className={cn(\n \"flex items-center gap-2\",\n loadingCategoryId === category.id && \"invisible\"\n )}>\n {category.icon && (\n <category.icon className=\"h-4 w-4 shrink-0\" aria-hidden />\n )}\n {category.label}\n {shouldShowBadge && (\n <span\n className={cn(\n \"rounded-full\",\n sizeClass.badge,\n isActive\n ? gradientClass.activeBadge\n : \"bg-gray-200 dark:bg-gray-800 text-gray-600 dark:text-gray-400\"\n )}\n >\n {badgeValue}\n </span>\n )}\n </span>\n {!glassmorphic && isActive && (\n <div className={cn(\"absolute bottom-0 left-0 right-0 h-0.5\", gradientClass.underline)} />\n )}\n </button>\n );\n })}\n </div>\n {trailing != null ? (\n <div className=\"flex shrink-0 items-center\">\n {trailing}\n </div>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAyCA,MAAM,iBAAiB,IAAI,IAAkC,CAC3D,CAAC,MAAM;CAAE,QAAQ;CAAqB,OAAO;CAA6B,CAAC,EAC3E,CAAC,MAAM;CAAE,QAAQ;CAAqB,OAAO;CAAyB,CAAC,CACxE,CAAC;AAEF,MAAM,kBAAkB,IAAI,IAAuC;CACjE,CACE,QACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,QACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,UACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,SACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,UACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACD,CACE,WACA;EACE,YAAY;EACZ,aAAa;EACb,WAAW;EACZ,CACF;CACF,CAAC;AAEF,SAAS,mBAAiC,KAAwB,KAAW,SAAiB;CAC5F,MAAM,QAAQ,IAAI,IAAI,IAAI;AAC1B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,WAAW,QAAQ,kBAAkB,OAAO,IAAI,CAAC,GAAG;AAEtE,QAAO;;AAGT,SAAgB,mBAAmB,EACjC,YACA,kBACA,UACA,YAAY,MACZ,OAAO,MACP,cAAc,kBACd,WAAW,QACX,UACA,WACA,GAAG,SACuB;CAC1B,MAAM,eAAe,uBAAuB,iBAAiB;CAC7D,MAAM,YAAY,mBAAmB,gBAAgB,MAAM,iBAAiB;CAC5E,MAAM,gBAAgB,mBAAmB,iBAAiB,UAAU,kBAAkB;CACtF,MAAM,CAAC,mBAAmB,wBAAwB,SAAwB,KAAK;CAE/E,MAAM,gBAAgB,eAAuB;EAC3C,MAAM,SAAS,SAAS,WAAW;AACnC,MAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE,wBAAqB,WAAW;AAChC,8BACE,QAAQ,QAAQ,OAAO,CAAC,cAAc,qBAAqB,KAAK,CAAC,CAClE;;;AAIL,QACE,qBAAC;EACC,WAAW,GACT,0CACA,eACI,wHACA,iDACJ,UACD;EACD,GAAI;aAEJ,oBAAC;GACC,WAAW,GACT,oGACD;aAEA,WAAW,KAAK,aAAa;IAC5B,MAAM,WAAW,qBAAqB,SAAS;IAC/C,MAAM,aAAa,SAAS,cAAc,SAAS;IACnD,MAAM,kBAAkB,aAAa,eAAe;AAEpD,WACE,qBAAC;KAEC,eAAe,aAAa,SAAS,GAAG;KACxC,UAAU,sBAAsB;KAChC,WAAW,GACT,iJACA,gDACA,UAAU,QACV,eAAe,eAAe,IAC9B,WACI,GACA,cAAc,YACd,gBAAgB,wFACjB,GACC,GACA,oCACA,gBAAgB,0DACjB,CACJ;;MAEA,sBAAsB,SAAS,MAC9B,oBAAC;OACC,MAAM;OACN,WAAU;QACV;MAEJ,qBAAC;OAAK,WAAW,GACf,2BACA,sBAAsB,SAAS,MAAM,YACtC;;QACE,SAAS,QACR,oBAAC,SAAS;SAAK,WAAU;SAAmB;UAAc;QAE3D,SAAS;QACT,mBACC,oBAAC;SACC,WAAW,GACT,gBACA,UAAU,OACV,WACI,cAAc,cACd,gEACL;mBAEA;UACI;;QAEJ;MACN,CAAC,gBAAgB,YAChB,oBAAC,SAAI,WAAW,GAAG,0CAA0C,cAAc,UAAU,GAAI;;OAhDtF,SAAS,GAkDP;KAEX;IACE,EACL,YAAY,OACX,oBAAC;GAAI,WAAU;aACZ;IACG,GACJ;GACA"}
@@ -3,7 +3,7 @@ import { DesignBadge, DesignBadgeColor, DesignBadgeContentMode, DesignBadgeProps
3
3
  import { DesignButton, DesignButtonProps, DesignOriginalButtonProps } from "./components/button";
4
4
  import { DesignCard, DesignCardProps, DesignCardTint, DesignCardTintProps, useGlassmorphicDefault, useInsideDesignCard } from "./components/card";
5
5
  import { CursorBlastEffect, CursorBlastEffectProps } from "./components/cursor-blast-effect";
6
- import { DesignDialog, DesignDialogClose, DesignDialogDescription, DesignDialogProps, DesignDialogRoot, DesignDialogSize, DesignDialogTitle, DesignDialogTrigger, DesignDialogVariant } from "./components/dialog";
6
+ import { DesignDialog, DesignDialogClose, DesignDialogDescription, DesignDialogProps, DesignDialogRoot, DesignDialogSize, DesignDialogTitle, DesignDialogTrigger, DesignDialogVariant, designDialogGlassmorphicOverlayClass, designDialogGlassmorphicSurfaceClass } from "./components/dialog";
7
7
  import { DesignEditMode, useDesignEditMode } from "./components/edit-mode";
8
8
  import { DesignInput, DesignInputProps } from "./components/input";
9
9
  import { DesignPillToggle, DesignPillToggleOption, DesignPillToggleProps } from "./components/pill-toggle";
@@ -21,4 +21,4 @@ import { DesignProgressBar, DesignProgressBarProps } from "./components/progress
21
21
  import { DesignEmptyState, DesignEmptyStateProps } from "./components/empty-state";
22
22
  export * from "./components/analytics-chart";
23
23
  export * from "./components/data-grid";
24
- export { CursorBlastEffect, type CursorBlastEffectProps, DESIGN_CHART_AXIS_TICK_STYLE, DESIGN_CHART_COLORS, DESIGN_CHART_GRID_COLOR, DesignAlert, type DesignAlertProps, DesignBadge, type DesignBadgeColor, type DesignBadgeContentMode, type DesignBadgeProps, type DesignBadgeSize, DesignButton, type DesignButtonProps, DesignCard, type DesignCardProps, DesignCardTint, type DesignCardTintProps, type DesignCategoryTabItem, DesignCategoryTabs, type DesignCategoryTabsProps, DesignChartCard, type DesignChartCardProps, type DesignChartColorEntry, type DesignChartColorName, type DesignChartConfig, DesignChartContainer, DesignChartLegendContent, DesignChartStyle, DesignChartTooltip, DesignChartTooltipContent, DesignDialog, DesignDialogClose, DesignDialogDescription, type DesignDialogProps, DesignDialogRoot, type DesignDialogSize, DesignDialogTitle, DesignDialogTrigger, type DesignDialogVariant, DesignEditMode, DesignEmptyState, type DesignEmptyStateProps, DesignInput, type DesignInputProps, DesignMetricCard, type DesignMetricCardProps, type DesignMetricCardTrend, type DesignOriginalButtonProps, DesignPillToggle, type DesignPillToggleOption, type DesignPillToggleProps, DesignProgressBar, type DesignProgressBarProps, DesignSeparator, type DesignSeparatorProps, DesignSkeleton, type DesignSkeletonProps, DesignTable, DesignTableBody, DesignTableCell, DesignTableHead, DesignTableHeader, DesignTableRow, getDesignChartColor, getPayloadConfigFromPayload, useDesignChart, useDesignEditMode, useGlassmorphicDefault, useInsideDesignCard };
24
+ export { CursorBlastEffect, type CursorBlastEffectProps, DESIGN_CHART_AXIS_TICK_STYLE, DESIGN_CHART_COLORS, DESIGN_CHART_GRID_COLOR, DesignAlert, type DesignAlertProps, DesignBadge, type DesignBadgeColor, type DesignBadgeContentMode, type DesignBadgeProps, type DesignBadgeSize, DesignButton, type DesignButtonProps, DesignCard, type DesignCardProps, DesignCardTint, type DesignCardTintProps, type DesignCategoryTabItem, DesignCategoryTabs, type DesignCategoryTabsProps, DesignChartCard, type DesignChartCardProps, type DesignChartColorEntry, type DesignChartColorName, type DesignChartConfig, DesignChartContainer, DesignChartLegendContent, DesignChartStyle, DesignChartTooltip, DesignChartTooltipContent, DesignDialog, DesignDialogClose, DesignDialogDescription, type DesignDialogProps, DesignDialogRoot, type DesignDialogSize, DesignDialogTitle, DesignDialogTrigger, type DesignDialogVariant, DesignEditMode, DesignEmptyState, type DesignEmptyStateProps, DesignInput, type DesignInputProps, DesignMetricCard, type DesignMetricCardProps, type DesignMetricCardTrend, type DesignOriginalButtonProps, DesignPillToggle, type DesignPillToggleOption, type DesignPillToggleProps, DesignProgressBar, type DesignProgressBarProps, DesignSeparator, type DesignSeparatorProps, DesignSkeleton, type DesignSkeletonProps, DesignTable, DesignTableBody, DesignTableCell, DesignTableHead, DesignTableHeader, DesignTableRow, designDialogGlassmorphicOverlayClass, designDialogGlassmorphicSurfaceClass, getDesignChartColor, getPayloadConfigFromPayload, useDesignChart, useDesignEditMode, useGlassmorphicDefault, useInsideDesignCard };
package/dist/esm/index.js CHANGED
@@ -3,7 +3,7 @@ import { DesignBadge } from "./components/badge.js";
3
3
  import { DesignButton } from "./components/button.js";
4
4
  import { DesignCard, DesignCardTint, useGlassmorphicDefault, useInsideDesignCard } from "./components/card.js";
5
5
  import { CursorBlastEffect } from "./components/cursor-blast-effect.js";
6
- import { DesignDialog, DesignDialogClose, DesignDialogDescription, DesignDialogRoot, DesignDialogTitle, DesignDialogTrigger } from "./components/dialog.js";
6
+ import { DesignDialog, DesignDialogClose, DesignDialogDescription, DesignDialogRoot, DesignDialogTitle, DesignDialogTrigger, designDialogGlassmorphicOverlayClass, designDialogGlassmorphicSurfaceClass } from "./components/dialog.js";
7
7
  import { DesignEditMode, useDesignEditMode } from "./components/edit-mode.js";
8
8
  import { DesignInput } from "./components/input.js";
9
9
  import { DesignPillToggle } from "./components/pill-toggle.js";
@@ -24,4 +24,4 @@ export * from "./components/analytics-chart/index.js"
24
24
 
25
25
  export * from "./components/data-grid/index.js"
26
26
 
27
- export { CursorBlastEffect, DESIGN_CHART_AXIS_TICK_STYLE, DESIGN_CHART_COLORS, DESIGN_CHART_GRID_COLOR, DesignAlert, DesignBadge, DesignButton, DesignCard, DesignCardTint, DesignCategoryTabs, DesignChartCard, DesignChartContainer, DesignChartLegendContent, DesignChartStyle, DesignChartTooltip, DesignChartTooltipContent, DesignDialog, DesignDialogClose, DesignDialogDescription, DesignDialogRoot, DesignDialogTitle, DesignDialogTrigger, DesignEditMode, DesignEmptyState, DesignInput, DesignMetricCard, DesignPillToggle, DesignProgressBar, DesignSeparator, DesignSkeleton, DesignTable, DesignTableBody, DesignTableCell, DesignTableHead, DesignTableHeader, DesignTableRow, getDesignChartColor, getPayloadConfigFromPayload, useDesignChart, useDesignEditMode, useGlassmorphicDefault, useInsideDesignCard };
27
+ export { CursorBlastEffect, DESIGN_CHART_AXIS_TICK_STYLE, DESIGN_CHART_COLORS, DESIGN_CHART_GRID_COLOR, DesignAlert, DesignBadge, DesignButton, DesignCard, DesignCardTint, DesignCategoryTabs, DesignChartCard, DesignChartContainer, DesignChartLegendContent, DesignChartStyle, DesignChartTooltip, DesignChartTooltipContent, DesignDialog, DesignDialogClose, DesignDialogDescription, DesignDialogRoot, DesignDialogTitle, DesignDialogTrigger, DesignEditMode, DesignEmptyState, DesignInput, DesignMetricCard, DesignPillToggle, DesignProgressBar, DesignSeparator, DesignSkeleton, DesignTable, DesignTableBody, DesignTableCell, DesignTableHead, DesignTableHeader, DesignTableRow, designDialogGlassmorphicOverlayClass, designDialogGlassmorphicSurfaceClass, getDesignChartColor, getPayloadConfigFromPayload, useDesignChart, useDesignEditMode, useGlassmorphicDefault, useInsideDesignCard };
package/dist/index.d.ts CHANGED
@@ -23,7 +23,7 @@ import { UseDataSourceResult, useDataSource } from "./components/data-grid/use-d
23
23
  import { useDataGridUrlState } from "./components/data-grid/use-url-state.js";
24
24
  import { applyQuickSearch, buildRowComparator, createDefaultDataGridState, defaultFormatAbsolute, defaultFormatRelative, defaultMatchRow, defaultParseDate, exportToCsv, formatGridDate, paginateRows, resolveColumnValue } from "./components/data-grid/state.js";
25
25
  import { DATA_GRID_DEFAULT_STRINGS, resolveDataGridStrings } from "./components/data-grid/strings.js";
26
- import { DesignDialog, DesignDialogClose, DesignDialogDescription, DesignDialogProps, DesignDialogRoot, DesignDialogSize, DesignDialogTitle, DesignDialogTrigger, DesignDialogVariant } from "./components/dialog.js";
26
+ import { DesignDialog, DesignDialogClose, DesignDialogDescription, DesignDialogProps, DesignDialogRoot, DesignDialogSize, DesignDialogTitle, DesignDialogTrigger, DesignDialogVariant, designDialogGlassmorphicOverlayClass, designDialogGlassmorphicSurfaceClass } from "./components/dialog.js";
27
27
  import { DesignEditMode, useDesignEditMode } from "./components/edit-mode.js";
28
28
  import { DesignEmptyState, DesignEmptyStateProps } from "./components/empty-state.js";
29
29
  import { DesignInput, DesignInputProps } from "./components/input.js";
@@ -34,4 +34,4 @@ import { DesignSeparator, DesignSeparatorProps } from "./components/separator.js
34
34
  import { DesignSkeleton, DesignSkeletonProps } from "./components/skeleton.js";
35
35
  import { DesignTable, DesignTableBody, DesignTableCell, DesignTableHead, DesignTableHeader, DesignTableRow } from "./components/table.js";
36
36
  import { DesignCategoryTabItem, DesignCategoryTabs, DesignCategoryTabsProps } from "./components/tabs.js";
37
- export { ANALYTICS_CHART_DEFAULT_LAYERS, ANALYTICS_CHART_DEFAULT_PALETTE, ANALYTICS_CHART_DEFAULT_STATE, ANALYTICS_CHART_DEFAULT_STRINGS, AnalyticsChart, AnalyticsChartAnnotationsLayer, AnalyticsChartAreaLayer, AnalyticsChartBarLayer, AnalyticsChartDataLayer, AnalyticsChartDelta, AnalyticsChartLayer, AnalyticsChartLayerType, AnalyticsChartLayers, AnalyticsChartLineLayer, AnalyticsChartPalette, AnalyticsChartPieProps, AnalyticsChartPieState, AnalyticsChartProps, AnalyticsChartSegmentRamp, AnalyticsChartSeries, AnalyticsChartState, AnalyticsChartStrings, AnalyticsChartStrokeStyle, AnalyticsChartTimeseriesState, AnalyticsChartTooltipContext, AnalyticsChartTooltipLayerView, AnalyticsChartTooltipSegmentRow, AnalyticsChartView, Annotation, CursorBlastEffect, type CursorBlastEffectProps, DATA_GRID_DEFAULT_STRINGS, DEFAULT_COL_WIDTH, DEFAULT_FORMAT_KIND, DEFAULT_MAX_COL_WIDTH, DESIGN_CHART_AXIS_TICK_STYLE, DESIGN_CHART_COLORS, DESIGN_CHART_GRID_COLOR, DataGrid, DataGridCallbacks, DataGridCellContext, DataGridColumnAlign, DataGridColumnDef, DataGridColumnPin, DataGridColumnPinning, DataGridColumnType, DataGridColumnVisibility, DataGridDataPaginationMode, DataGridDataSource, DataGridDateDisplay, DataGridDateFormat, DataGridFetchParams, DataGridFetchResult, DataGridFooterContext, DataGridHeaderContext, DataGridPaginationMode, DataGridPaginationModel, DataGridProps, DataGridSelectOption, DataGridSelectionMode, DataGridSelectionModel, DataGridSortItem, DataGridSortModel, DataGridState, DataGridStrings, DataGridToolbar, DataGridToolbarContext, DefaultAnalyticsChartTooltip, DefaultAnalyticsChartTooltipProps, DesignAlert, type DesignAlertProps, DesignBadge, type DesignBadgeColor, type DesignBadgeContentMode, type DesignBadgeProps, type DesignBadgeSize, DesignButton, type DesignButtonProps, DesignCard, type DesignCardProps, DesignCardTint, type DesignCardTintProps, type DesignCategoryTabItem, DesignCategoryTabs, type DesignCategoryTabsProps, DesignChartCard, type DesignChartCardProps, type DesignChartColorEntry, type DesignChartColorName, type DesignChartConfig, DesignChartContainer, DesignChartLegendContent, DesignChartStyle, DesignChartTooltip, DesignChartTooltipContent, DesignDialog, DesignDialogClose, DesignDialogDescription, type DesignDialogProps, DesignDialogRoot, type DesignDialogSize, DesignDialogTitle, DesignDialogTrigger, type DesignDialogVariant, DesignEditMode, DesignEmptyState, type DesignEmptyStateProps, DesignInput, type DesignInputProps, DesignMetricCard, type DesignMetricCardProps, type DesignMetricCardTrend, type DesignOriginalButtonProps, DesignPillToggle, type DesignPillToggleOption, type DesignPillToggleProps, DesignProgressBar, type DesignProgressBarProps, DesignSeparator, type DesignSeparatorProps, DesignSkeleton, type DesignSkeletonProps, DesignTable, DesignTableBody, DesignTableCell, DesignTableHead, DesignTableHeader, DesignTableRow, EMPTY_MATRIX, EMPTY_SERIES, FORMAT_KIND_TYPES, FormatKind, FormatKindCurrency, FormatKindDatetime, FormatKindDuration, FormatKindNumeric, FormatKindPercent, FormatKindShort, FormatKindType, Margin, Point, ResolvedDataLayerStyle, RowId, STROKE_DASHARRAY, TrendPill, UseDataSourceResult, applyQuickSearch, buildRampColors, buildRowComparator, buildSegmentThemeMap, clampColumnWidth, computeLocalInProgressIdx, createDefaultDataGridState, defaultFormatAbsolute, defaultFormatRelative, defaultMatchRow, defaultParseDate, exportToCsv, findAnnotationsLayer, findCompareLayer, findLayerById, findPrimaryLayer, formatDelta, formatGridDate, formatValue, getDesignChartColor, getEffectiveMaxWidth, getEffectiveMinWidth, getPayloadConfigFromPayload, isAnalyticsChartDataLayer, isDataGridInteractiveRowClickTarget, isTimeseriesState, paginateRows, patchLayerById, pointValue, resolveAnalyticsChartPalette, resolveAnalyticsChartStrings, resolveColumnValue, resolveDataGridStrings, resolveDataLayerStyle, setLayerById, useDataGridUrlState, useDataSource, useDesignChart, useDesignEditMode, useGlassmorphicDefault, useInsideDesignCard };
37
+ export { ANALYTICS_CHART_DEFAULT_LAYERS, ANALYTICS_CHART_DEFAULT_PALETTE, ANALYTICS_CHART_DEFAULT_STATE, ANALYTICS_CHART_DEFAULT_STRINGS, AnalyticsChart, AnalyticsChartAnnotationsLayer, AnalyticsChartAreaLayer, AnalyticsChartBarLayer, AnalyticsChartDataLayer, AnalyticsChartDelta, AnalyticsChartLayer, AnalyticsChartLayerType, AnalyticsChartLayers, AnalyticsChartLineLayer, AnalyticsChartPalette, AnalyticsChartPieProps, AnalyticsChartPieState, AnalyticsChartProps, AnalyticsChartSegmentRamp, AnalyticsChartSeries, AnalyticsChartState, AnalyticsChartStrings, AnalyticsChartStrokeStyle, AnalyticsChartTimeseriesState, AnalyticsChartTooltipContext, AnalyticsChartTooltipLayerView, AnalyticsChartTooltipSegmentRow, AnalyticsChartView, Annotation, CursorBlastEffect, type CursorBlastEffectProps, DATA_GRID_DEFAULT_STRINGS, DEFAULT_COL_WIDTH, DEFAULT_FORMAT_KIND, DEFAULT_MAX_COL_WIDTH, DESIGN_CHART_AXIS_TICK_STYLE, DESIGN_CHART_COLORS, DESIGN_CHART_GRID_COLOR, DataGrid, DataGridCallbacks, DataGridCellContext, DataGridColumnAlign, DataGridColumnDef, DataGridColumnPin, DataGridColumnPinning, DataGridColumnType, DataGridColumnVisibility, DataGridDataPaginationMode, DataGridDataSource, DataGridDateDisplay, DataGridDateFormat, DataGridFetchParams, DataGridFetchResult, DataGridFooterContext, DataGridHeaderContext, DataGridPaginationMode, DataGridPaginationModel, DataGridProps, DataGridSelectOption, DataGridSelectionMode, DataGridSelectionModel, DataGridSortItem, DataGridSortModel, DataGridState, DataGridStrings, DataGridToolbar, DataGridToolbarContext, DefaultAnalyticsChartTooltip, DefaultAnalyticsChartTooltipProps, DesignAlert, type DesignAlertProps, DesignBadge, type DesignBadgeColor, type DesignBadgeContentMode, type DesignBadgeProps, type DesignBadgeSize, DesignButton, type DesignButtonProps, DesignCard, type DesignCardProps, DesignCardTint, type DesignCardTintProps, type DesignCategoryTabItem, DesignCategoryTabs, type DesignCategoryTabsProps, DesignChartCard, type DesignChartCardProps, type DesignChartColorEntry, type DesignChartColorName, type DesignChartConfig, DesignChartContainer, DesignChartLegendContent, DesignChartStyle, DesignChartTooltip, DesignChartTooltipContent, DesignDialog, DesignDialogClose, DesignDialogDescription, type DesignDialogProps, DesignDialogRoot, type DesignDialogSize, DesignDialogTitle, DesignDialogTrigger, type DesignDialogVariant, DesignEditMode, DesignEmptyState, type DesignEmptyStateProps, DesignInput, type DesignInputProps, DesignMetricCard, type DesignMetricCardProps, type DesignMetricCardTrend, type DesignOriginalButtonProps, DesignPillToggle, type DesignPillToggleOption, type DesignPillToggleProps, DesignProgressBar, type DesignProgressBarProps, DesignSeparator, type DesignSeparatorProps, DesignSkeleton, type DesignSkeletonProps, DesignTable, DesignTableBody, DesignTableCell, DesignTableHead, DesignTableHeader, DesignTableRow, EMPTY_MATRIX, EMPTY_SERIES, FORMAT_KIND_TYPES, FormatKind, FormatKindCurrency, FormatKindDatetime, FormatKindDuration, FormatKindNumeric, FormatKindPercent, FormatKindShort, FormatKindType, Margin, Point, ResolvedDataLayerStyle, RowId, STROKE_DASHARRAY, TrendPill, UseDataSourceResult, applyQuickSearch, buildRampColors, buildRowComparator, buildSegmentThemeMap, clampColumnWidth, computeLocalInProgressIdx, createDefaultDataGridState, defaultFormatAbsolute, defaultFormatRelative, defaultMatchRow, defaultParseDate, designDialogGlassmorphicOverlayClass, designDialogGlassmorphicSurfaceClass, exportToCsv, findAnnotationsLayer, findCompareLayer, findLayerById, findPrimaryLayer, formatDelta, formatGridDate, formatValue, getDesignChartColor, getEffectiveMaxWidth, getEffectiveMinWidth, getPayloadConfigFromPayload, isAnalyticsChartDataLayer, isDataGridInteractiveRowClickTarget, isTimeseriesState, paginateRows, patchLayerById, pointValue, resolveAnalyticsChartPalette, resolveAnalyticsChartStrings, resolveColumnValue, resolveDataGridStrings, resolveDataLayerStyle, setLayerById, useDataGridUrlState, useDataSource, useDesignChart, useDesignEditMode, useGlassmorphicDefault, useInsideDesignCard };
package/dist/index.js CHANGED
@@ -238,6 +238,18 @@ Object.defineProperty(exports, 'DesignTableRow', {
238
238
  return __components_table_js.DesignTableRow;
239
239
  }
240
240
  });
241
+ Object.defineProperty(exports, 'designDialogGlassmorphicOverlayClass', {
242
+ enumerable: true,
243
+ get: function () {
244
+ return __components_dialog_js.designDialogGlassmorphicOverlayClass;
245
+ }
246
+ });
247
+ Object.defineProperty(exports, 'designDialogGlassmorphicSurfaceClass', {
248
+ enumerable: true,
249
+ get: function () {
250
+ return __components_dialog_js.designDialogGlassmorphicSurfaceClass;
251
+ }
252
+ });
241
253
  Object.defineProperty(exports, 'getDesignChartColor', {
242
254
  enumerable: true,
243
255
  get: function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexclave/dashboard-ui-components",
3
- "version": "1.0.5",
3
+ "version": "1.0.8",
4
4
  "repository": "https://github.com/hexclave/hexclave",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -50,8 +50,8 @@
50
50
  "@tanstack/react-table": "^8.21.3",
51
51
  "@tanstack/react-virtual": "^3.13.0",
52
52
  "class-variance-authority": "^0.7.0",
53
- "@hexclave/shared": "1.0.5",
54
- "@hexclave/ui": "1.0.5"
53
+ "@hexclave/shared": "1.0.8",
54
+ "@hexclave/ui": "1.0.8"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/react": "^19.0.0",
@@ -23,7 +23,7 @@ const variantStyles = new Map<DesignAlertVariant, VariantStyles>([
23
23
  [
24
24
  "default",
25
25
  {
26
- container: "bg-background border-border",
26
+ container: "border-black/[0.08] bg-white/90 ring-1 ring-black/[0.06] dark:border-border dark:bg-background dark:ring-0",
27
27
  icon: "text-foreground",
28
28
  title: "text-foreground",
29
29
  },
@@ -55,9 +55,9 @@ const variantStyles = new Map<DesignAlertVariant, VariantStyles>([
55
55
  [
56
56
  "info",
57
57
  {
58
- container: "bg-blue-500/[0.06] border-blue-500/30",
59
- icon: "text-blue-500",
60
- title: "text-blue-600 dark:text-blue-400",
58
+ container: "border-blue-500/20 bg-blue-50/90 ring-1 ring-blue-500/10 dark:border-blue-500/30 dark:bg-blue-500/[0.06] dark:ring-0",
59
+ icon: "text-blue-600 dark:text-blue-400",
60
+ title: "text-blue-700 dark:text-blue-400",
61
61
  },
62
62
  ],
63
63
  ]);
@@ -94,7 +94,7 @@ export function DesignBadge({
94
94
  return (
95
95
  <div
96
96
  className={cn(
97
- "inline-flex items-center gap-1.5 rounded-full font-medium",
97
+ "inline-flex max-w-full items-center gap-1.5 whitespace-nowrap rounded-full font-medium leading-none",
98
98
  colorClasses,
99
99
  sizeClasses
100
100
  )}
@@ -17,10 +17,10 @@ const designButtonVariants = cva(
17
17
  destructive:
18
18
  "bg-destructive text-destructive-foreground hover:bg-destructive/90",
19
19
  outline:
20
- "border border-input bg-white/85 dark:bg-background hover:bg-white dark:hover:bg-accent hover:text-accent-foreground",
20
+ "border border-input bg-white/85 dark:bg-background hover:bg-zinc-50 dark:hover:bg-accent dark:hover:text-accent-foreground",
21
21
  secondary:
22
- "bg-secondary text-secondary-foreground hover:bg-secondary/80",
23
- ghost: "hover:bg-accent hover:text-accent-foreground",
22
+ "bg-white dark:bg-secondary text-secondary-foreground hover:bg-zinc-50 dark:hover:bg-secondary/80",
23
+ ghost: "hover:bg-zinc-100 dark:hover:bg-accent dark:hover:text-accent-foreground",
24
24
  link: "text-primary underline-offset-4 hover:underline",
25
25
  plain: "",
26
26
  },
@@ -84,16 +84,16 @@ function QuickSearch({
84
84
  }) {
85
85
  return (
86
86
  <div className="relative flex min-w-0 flex-1 items-center sm:flex-initial">
87
- <MagnifyingGlass className="absolute left-2.5 h-3.5 w-3.5 text-muted-foreground/50 pointer-events-none" />
87
+ <MagnifyingGlass className="absolute left-2.5 h-3.5 w-3.5 text-muted-foreground/60 pointer-events-none" />
88
88
  <input
89
89
  type="text"
90
90
  className={cn(
91
91
  "h-8 w-full sm:w-52 pl-8 pr-7 rounded-xl text-xs",
92
- "bg-background",
93
- "border border-black/[0.08] dark:border-white/[0.08]",
94
- "placeholder:text-muted-foreground/40",
92
+ "border border-black/[0.08] dark:border-white/[0.06]",
93
+ "bg-white dark:bg-background shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06]",
94
+ "placeholder:text-muted-foreground/50",
95
95
  "focus:outline-none focus:ring-1 focus:ring-foreground/[0.1]",
96
- "transition-all duration-150",
96
+ "transition-all duration-150 hover:transition-none hover:ring-black/[0.12] dark:hover:ring-white/[0.1]",
97
97
  )}
98
98
  placeholder={placeholder}
99
99
  value={value}
@@ -234,13 +234,13 @@ function ColumnManager<TRow>({
234
234
  <span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground">
235
235
  {strings.dateFormat}
236
236
  </span>
237
- <div className="inline-flex items-center gap-0.5 rounded-lg bg-foreground/[0.04] p-0.5">
237
+ <div className="inline-flex items-center gap-0.5 rounded-lg bg-zinc-100/90 p-0.5 ring-1 ring-black/[0.06] dark:bg-foreground/[0.04] dark:ring-white/[0.06]">
238
238
  <button
239
239
  className={cn(
240
- "px-2 py-0.5 rounded-md text-[11px] font-medium transition-colors duration-75",
240
+ "px-2 py-0.5 rounded-md text-[11px] font-medium transition-colors duration-150 hover:transition-none",
241
241
  dateDisplay === "relative"
242
- ? "bg-background text-foreground shadow-sm ring-1 ring-foreground/[0.06]"
243
- : "text-muted-foreground hover:text-foreground",
242
+ ? "bg-white text-foreground shadow-sm ring-1 ring-black/[0.12] dark:bg-background dark:ring-white/[0.06]"
243
+ : "text-muted-foreground hover:text-foreground hover:bg-white/50 dark:hover:bg-white/[0.06]",
244
244
  )}
245
245
  onClick={() => onDateDisplayChange("relative")}
246
246
  >
@@ -248,10 +248,10 @@ function ColumnManager<TRow>({
248
248
  </button>
249
249
  <button
250
250
  className={cn(
251
- "px-2 py-0.5 rounded-md text-[11px] font-medium transition-colors duration-75",
251
+ "px-2 py-0.5 rounded-md text-[11px] font-medium transition-colors duration-150 hover:transition-none",
252
252
  dateDisplay === "absolute"
253
- ? "bg-background text-foreground shadow-sm ring-1 ring-foreground/[0.06]"
254
- : "text-muted-foreground hover:text-foreground",
253
+ ? "bg-white text-foreground shadow-sm ring-1 ring-black/[0.12] dark:bg-background dark:ring-white/[0.06]"
254
+ : "text-muted-foreground hover:text-foreground hover:bg-white/50 dark:hover:bg-white/[0.06]",
255
255
  )}
256
256
  onClick={() => onDateDisplayChange("absolute")}
257
257
  >
@@ -101,8 +101,43 @@ class MockIntersectionObserver implements IntersectionObserver {
101
101
  }
102
102
 
103
103
  class MockResizeObserver implements ResizeObserver {
104
+ private readonly callback: ResizeObserverCallback;
105
+
106
+ constructor(callback: ResizeObserverCallback) {
107
+ this.callback = callback;
108
+ }
109
+
104
110
  disconnect() {}
105
- observe() {}
111
+ observe(target: Element) {
112
+ const el = target instanceof HTMLElement ? target : null;
113
+ const parentWidth = el?.parentElement instanceof HTMLElement ? el.parentElement.clientWidth : 0;
114
+ const width = (el?.clientWidth ?? 0) > 0 ? (el?.clientWidth ?? 320) : parentWidth > 0 ? parentWidth : 320;
115
+ const height = (el?.clientHeight ?? 0) > 0 ? (el?.clientHeight ?? 400) : 400;
116
+ this.callback(
117
+ [
118
+ {
119
+ target,
120
+ contentRect: {
121
+ x: 0,
122
+ y: 0,
123
+ width,
124
+ height,
125
+ top: 0,
126
+ left: 0,
127
+ right: width,
128
+ bottom: height,
129
+ toJSON() {
130
+ return this;
131
+ },
132
+ } as DOMRectReadOnly,
133
+ borderBoxSize: [],
134
+ contentBoxSize: [],
135
+ devicePixelContentBoxSize: [],
136
+ },
137
+ ],
138
+ this,
139
+ );
140
+ }
106
141
  unobserve() {}
107
142
  }
108
143
 
@@ -307,6 +342,12 @@ describe("DataGrid controlled callbacks", () => {
307
342
  describe("DataGrid horizontal scrolling", () => {
308
343
  beforeEach(() => {
309
344
  vi.stubGlobal("ResizeObserver", MockResizeObserver);
345
+ Object.defineProperty(HTMLElement.prototype, "clientWidth", {
346
+ configurable: true,
347
+ get() {
348
+ return 320;
349
+ },
350
+ });
310
351
  vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(
311
352
  function getBoundingClientRect() {
312
353
  return {
@@ -512,9 +512,10 @@ function DefaultFooter<TRow>({
512
512
  <span>{strings.rowsPerPage}</span>
513
513
  <select
514
514
  className={cn(
515
- "h-7 rounded-lg border border-black/[0.08] dark:border-white/[0.08] bg-background px-1.5",
515
+ "h-7 rounded-lg border border-black/[0.08] dark:border-white/[0.06] px-1.5",
516
+ "bg-white dark:bg-background shadow-sm ring-1 ring-black/[0.08] dark:ring-white/[0.06]",
516
517
  "text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-foreground/[0.1]",
517
- "cursor-pointer",
518
+ "cursor-pointer transition-all duration-150 hover:transition-none hover:ring-black/[0.12] dark:hover:ring-white/[0.1]",
518
519
  )}
519
520
  value={state.pagination.pageSize}
520
521
  onChange={(e) => setPageSize(Number(e.target.value))}
@@ -798,12 +799,22 @@ export function DataGrid<TRow>(props: DataGridProps<TRow>) {
798
799
  const grid = gridRef.current;
799
800
  const scroller = scrollContainerRef.current;
800
801
  if (!grid) return;
801
- const update = () => {
802
- const w = scroller?.clientWidth ?? grid.clientWidth;
803
- if (w > 0) setContainerWidth(w);
802
+ const update = (entries?: ResizeObserverEntry[]) => {
803
+ let measured = 0;
804
+ if (entries != null) {
805
+ for (const entry of entries) {
806
+ measured = Math.max(measured, entry.contentRect.width);
807
+ }
808
+ }
809
+ if (measured <= 0) {
810
+ const scrollerWidth = scroller?.clientWidth ?? 0;
811
+ const gridWidth = grid.clientWidth;
812
+ measured = scrollerWidth > 0 ? scrollerWidth : gridWidth;
813
+ }
814
+ if (measured > 0) setContainerWidth(measured);
804
815
  };
805
816
  update();
806
- const observer = new ResizeObserver(update);
817
+ const observer = new ResizeObserver((entries) => update(entries));
807
818
  observer.observe(grid);
808
819
  if (scroller) observer.observe(scroller);
809
820
  return () => observer.disconnect();