@hexclave/dashboard-ui-components 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/alert.js +4 -4
- package/dist/components/alert.js.map +1 -1
- package/dist/components/badge.js +1 -1
- package/dist/components/badge.js.map +1 -1
- package/dist/components/button.d.ts +4 -4
- package/dist/components/button.js +3 -3
- package/dist/components/button.js.map +1 -1
- package/dist/components/data-grid/data-grid-toolbar.js +5 -5
- package/dist/components/data-grid/data-grid-toolbar.js.map +1 -1
- package/dist/components/data-grid/data-grid.d.ts.map +1 -1
- package/dist/components/data-grid/data-grid.js +11 -5
- package/dist/components/data-grid/data-grid.js.map +1 -1
- package/dist/components/data-grid/data-grid.test.js +34 -1
- package/dist/components/data-grid/data-grid.test.js.map +1 -1
- package/dist/components/dialog.d.ts +6 -2
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/dialog.js +14 -10
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/input.js +12 -9
- package/dist/components/input.js.map +1 -1
- package/dist/components/pill-toggle.js +1 -1
- package/dist/components/pill-toggle.js.map +1 -1
- package/dist/components/tabs.js +2 -2
- package/dist/components/tabs.js.map +1 -1
- package/dist/dashboard-ui-components.global.js +4967 -4933
- package/dist/dashboard-ui-components.global.js.map +4 -4
- package/dist/esm/components/alert.js +4 -4
- package/dist/esm/components/alert.js.map +1 -1
- package/dist/esm/components/badge.js +1 -1
- package/dist/esm/components/badge.js.map +1 -1
- package/dist/esm/components/button.d.ts +4 -4
- package/dist/esm/components/button.js +3 -3
- package/dist/esm/components/button.js.map +1 -1
- package/dist/esm/components/data-grid/data-grid-toolbar.js +5 -5
- package/dist/esm/components/data-grid/data-grid-toolbar.js.map +1 -1
- package/dist/esm/components/data-grid/data-grid.d.ts.map +1 -1
- package/dist/esm/components/data-grid/data-grid.js +11 -5
- package/dist/esm/components/data-grid/data-grid.js.map +1 -1
- package/dist/esm/components/data-grid/data-grid.test.js +34 -1
- package/dist/esm/components/data-grid/data-grid.test.js.map +1 -1
- package/dist/esm/components/dialog.d.ts +6 -2
- package/dist/esm/components/dialog.d.ts.map +1 -1
- package/dist/esm/components/dialog.js +13 -11
- package/dist/esm/components/dialog.js.map +1 -1
- package/dist/esm/components/input.js +12 -9
- package/dist/esm/components/input.js.map +1 -1
- package/dist/esm/components/pill-toggle.js +1 -1
- package/dist/esm/components/pill-toggle.js.map +1 -1
- package/dist/esm/components/tabs.js +2 -2
- package/dist/esm/components/tabs.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -0
- package/package.json +3 -3
- package/src/components/alert.tsx +4 -4
- package/src/components/badge.tsx +1 -1
- package/src/components/button.tsx +3 -3
- package/src/components/data-grid/data-grid-toolbar.tsx +12 -12
- package/src/components/data-grid/data-grid.test.tsx +42 -1
- package/src/components/data-grid/data-grid.tsx +17 -6
- package/src/components/dialog.tsx +24 -13
- package/src/components/input.tsx +24 -12
- package/src/components/pill-toggle.tsx +1 -1
- package/src/components/tabs.tsx +6 -3
- package/src/index.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","names":["React","Dialog","DialogTrigger","DialogContent","DialogTitle","DialogHeader","DialogDescription","DialogBody","DialogFooter","DialogClose"],"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-
|
|
1
|
+
{"version":3,"file":"dialog.js","names":["React","Dialog","DialogTrigger","DialogContent","DialogTitle","DialogHeader","DialogDescription","DialogBody","DialogFooter","DialogClose"],"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,4CACJ,YAAY,iBAAiB,uCAAuC,QACpE,iBACD;CACD,MAAM,2BAA2B,QAAQ,QAAQ,SAAS,QAAQ,eAAe;CACjF,MAAM,qBAAqB,gBAAgB,QAAQ,4BAA4B,iBAAiB;CAIhG,MAAM,mBAAmBA,cAAM,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,4CAACC;EAAO,GAAI;aACT,WAAW,QACV,2CAACC;GAAc;aACZ;IACa,EAGlB,4CAACC;GACC,gCACE,mEACA,mBACA,sBACA,UACD;GACD,cAAc,uBAAuB,EAAE,WAAW,sBAAsB,GAAG;GAC3E,eAAe;GACf,GAAI;;IAEH,gCACC,2CAACC;KAAY,WAAU;eAAU;MAAoB;IAEtD,sBACC,2CAACC;KAAa,gCAAc,6DAA6D,gBAAgB;eACtG,gBACC,qFACG,4BACC,4CAAC;MAAI,gCACH,cACA,eAAe,OAAO,gBAAgB,gBACtC,QAAQ,QAAQ,QACjB;iBACE,QAAQ,QACP,2CAAC;OAAI,WAAU;iBACb,2CAAC,QAAK,WAAU,yBAAyB;QACrC,GAEN,SAAS,QAAQ,eAAe,SAChC,4CAAC;OAAI,WAAU;kBACZ,SAAS,OACR,2CAACD;QAAY,WAAU;kBACpB;SACW,GACZ,MACH,eAAe,OACd,2CAACE;QAAkB,WAAU;kBAC1B;SACiB,GAClB;QACA;OAEJ,EAGP,iBAAiB,OAChB,2CAAC;MAAI,gCAAc,4BAA4B,OAAO;gBACnD;OACG,GACJ,QACH;MAEQ;IAGhB,oBACC,2CAACC;KACC,gCACE,4CACA,gBAAgB,cAAc,aAC9B,cACD;KAEA;MACU;IAGd,UAAU,OACT,2CAACC;KAAa,gCAAc,6EAA6E,gBAAgB;eACtH;MACY,GACb;;IACU;GACT;;AAIb,MAAa,mBAAmBP;AAChC,MAAa,sBAAsBC;AACnC,MAAa,oBAAoBO;AACjC,MAAa,oBAAoBL;AACjC,MAAa,0BAA0BE"}
|
package/dist/components/input.js
CHANGED
|
@@ -10,37 +10,40 @@ react = require_chunk.__toESM(react);
|
|
|
10
10
|
|
|
11
11
|
//#region src/components/input.tsx
|
|
12
12
|
const DesignInput = (0, _hexclave_shared_dist_utils_react.forwardRefIfNeeded)(({ className, type, prefixItem, leadingIcon, size = "md", ...props }, ref) => {
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const heightTextClasses = size === "sm" ? "h-7 text-xs" : size === "lg" ? "h-10 text-sm" : "h-9 text-sm";
|
|
14
|
+
const horizontalPaddingClasses = size === "sm" ? "px-2" : size === "lg" ? "px-4" : "px-3";
|
|
15
|
+
const baseClasses = (0, _hexclave_ui.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);
|
|
16
|
+
const leadingIconClasses = size === "sm" ? "left-2.5 [&_svg]:size-3" : size === "lg" ? "left-3.5 [&_svg]:size-4" : "left-3 [&_svg]:size-3.5";
|
|
17
|
+
const leadingIconPadding = size === "sm" ? "pl-8" : size === "lg" ? "pl-10" : "pl-9";
|
|
15
18
|
if (prefixItem) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
16
|
-
className: "flex flex-row items-center
|
|
19
|
+
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]",
|
|
17
20
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
18
21
|
className: (0, _hexclave_ui.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"),
|
|
19
22
|
children: prefixItem
|
|
20
23
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
21
24
|
type,
|
|
22
|
-
className: (0, _hexclave_ui.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",
|
|
25
|
+
className: (0, _hexclave_ui.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),
|
|
23
26
|
ref,
|
|
24
27
|
...props
|
|
25
28
|
})]
|
|
26
29
|
});
|
|
27
30
|
if (leadingIcon) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
28
|
-
className: "relative
|
|
31
|
+
className: (0, _hexclave_ui.cn)("relative w-full", className),
|
|
29
32
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
30
|
-
className: "pointer-events-none absolute
|
|
33
|
+
className: (0, _hexclave_ui.cn)("pointer-events-none absolute top-1/2 -translate-y-1/2 text-muted-foreground [&_svg]:block", leadingIconClasses),
|
|
31
34
|
children: leadingIcon
|
|
32
35
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
33
36
|
type,
|
|
34
|
-
className: (0, _hexclave_ui.cn)(baseClasses,
|
|
37
|
+
className: (0, _hexclave_ui.cn)(baseClasses, leadingIconPadding),
|
|
35
38
|
ref,
|
|
36
39
|
...props
|
|
37
40
|
})]
|
|
38
41
|
});
|
|
39
42
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
40
|
-
className: "
|
|
43
|
+
className: "w-full",
|
|
41
44
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
42
45
|
type,
|
|
43
|
-
className: (0, _hexclave_ui.cn)(baseClasses, className),
|
|
46
|
+
className: (0, _hexclave_ui.cn)(baseClasses, horizontalPaddingClasses, className),
|
|
44
47
|
ref,
|
|
45
48
|
...props
|
|
46
49
|
})
|
|
@@ -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
|
|
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,yEACV,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,mCACJ,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,4CAAC;EAAI,WAAU;aACb,2CAAC;GAAI,gCACH,iLACA,SAAS,OAAO,mBAAmB,SAAS,OAAO,mBAAmB,eACvE;aACE;IACG,EACN,2CAAC;GACO;GACN,gCACE,0CACA,mEACA,mEACA,mDACA,mBACA,0BACA,iEACA,UACD;GACI;GACL,GAAI;IACJ;GACE;AAIV,KAAI,YACF,QACE,4CAAC;EAAI,gCAAc,mBAAmB,UAAU;aAC9C,2CAAC;GAAI,gCACH,6FACA,mBACD;aACE;IACG,EACN,2CAAC;GACO;GACN,gCAAc,aAAa,mBAAmB;GACzC;GACL,GAAI;IACJ;GACE;AAIV,QACE,2CAAC;EAAI,WAAU;YACb,2CAAC;GACO;GACN,gCAAc,aAAa,0BAA0B,UAAU;GAC1D;GACL,GAAI;IACJ;GACE;EAGX;AACD,YAAY,cAAc"}
|
|
@@ -58,7 +58,7 @@ function DesignPillToggle({ options, selected, onSelect, size = "md", glassmorph
|
|
|
58
58
|
type: "button",
|
|
59
59
|
onClick: () => handleClick(option.id),
|
|
60
60
|
disabled: loadingOptionId !== null,
|
|
61
|
-
className: (0, _hexclave_ui.cn)("relative flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none", sizeClass.button, isActive ? (0, _hexclave_ui.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) : (0, _hexclave_ui.cn)("text-muted-foreground hover:text-foreground", glassmorphic ? "hover:bg-background/50" : "hover:bg-black/[0.06] dark:hover:bg-white/[0.04]")),
|
|
61
|
+
className: (0, _hexclave_ui.cn)("relative flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none", sizeClass.button, isActive ? (0, _hexclave_ui.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) : (0, _hexclave_ui.cn)("text-muted-foreground hover:text-foreground", glassmorphic ? "hover:bg-background/50" : "hover:bg-black/[0.06] dark:hover:bg-white/[0.04]")),
|
|
62
62
|
children: [loadingOptionId === option.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.Spinner, {
|
|
63
63
|
size: 12,
|
|
64
64
|
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":["TooltipProvider","Spinner","Tooltip","TooltipTrigger","TooltipPortal","TooltipContent"],"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,qDAAsC,iBAAiB;CAC7D,MAAM,YAAY,mBAAmB,aAAa,MAAM,cAAc;CACtE,MAAM,kBAAkB,mBAAmB,iBAAiB,UAAU,kBAAkB;CAExF,MAAM,CAAC,iBAAiB,0CAA8C,KAAK;CAE3E,MAAM,eAAe,aAAqB;EACxC,MAAM,SAAS,SAAS,SAAS;AACjC,MAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE,sBAAmB,SAAS;AAC5B,wEACE,QAAQ,QAAQ,OAAO,CAAC,cAAc,mBAAmB,KAAK,CAAC,CAChE;;;AAIL,QACE,2CAACA,0CACC,2CAAC;EACC,gCACE,iDACA,eACI,0CACA,wCACJ,UACD;YAEA,QAAQ,KAAK,WAAW;GACvB,MAAM,WAAW,aAAa,OAAO;GACrC,MAAM,OAAO,OAAO;GAEpB,MAAM,OACJ,4CAAC;IACC,MAAK;IAEL,eAAe,YAAY,OAAO,GAAG;IACrC,UAAU,oBAAoB;IAC9B,gCACE,6GACA,UAAU,QACV,gCAEI,
|
|
1
|
+
{"version":3,"file":"pill-toggle.js","names":["TooltipProvider","Spinner","Tooltip","TooltipTrigger","TooltipPortal","TooltipContent"],"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,qDAAsC,iBAAiB;CAC7D,MAAM,YAAY,mBAAmB,aAAa,MAAM,cAAc;CACtE,MAAM,kBAAkB,mBAAmB,iBAAiB,UAAU,kBAAkB;CAExF,MAAM,CAAC,iBAAiB,0CAA8C,KAAK;CAE3E,MAAM,eAAe,aAAqB;EACxC,MAAM,SAAS,SAAS,SAAS;AACjC,MAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE,sBAAmB,SAAS;AAC5B,wEACE,QAAQ,QAAQ,OAAO,CAAC,cAAc,mBAAmB,KAAK,CAAC,CAChE;;;AAIL,QACE,2CAACA,0CACC,2CAAC;EACC,gCACE,iDACA,eACI,0CACA,wCACJ,UACD;YAEA,QAAQ,KAAK,WAAW;GACvB,MAAM,WAAW,aAAa,OAAO;GACrC,MAAM,OAAO,OAAO;GAEpB,MAAM,OACJ,4CAAC;IACC,MAAK;IAEL,eAAe,YAAY,OAAO,GAAG;IACrC,UAAU,oBAAoB;IAC9B,gCACE,6GACA,UAAU,QACV,gCAEI,gEACA,eACI,sHACA,gBACL,wBAEC,+CACA,eACI,2BACA,mDACL,CACJ;eAEA,oBAAoB,OAAO,MAC1B,2CAACC;KACC,MAAM;KACN,WAAU;MACV,EAEJ,4CAAC;KAAK,gCACJ,2BACA,oBAAoB,OAAO,MAAM,YAClC;gBACE,QAAQ,2CAAC,QAAK,WAAW,UAAU,OAAQ,EAC3C,cAAc,OAAO;MACjB;MAjCF,OAAO,GAkCL;AAGX,OAAI,CAAC,WACH,QACE,4CAACC;IAAwB,eAAe;eACtC,2CAACC;KAAe;eACb;MACc,EACjB,2CAACC,mDACC,2CAACC;KAAe,MAAK;eAClB,OAAO;MACO,GACH;MARJ,OAAO,GASX;AAId,UAAO;IACP;GACE,GACU"}
|
package/dist/components/tabs.js
CHANGED
|
@@ -66,7 +66,7 @@ function DesignCategoryTabs({ categories, selectedCategory, onSelect, showBadge
|
|
|
66
66
|
}
|
|
67
67
|
};
|
|
68
68
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
69
|
-
className: (0, _hexclave_ui.cn)("flex w-full min-w-0 items-center gap-2", glassmorphic ? "rounded-xl bg-black/[0.
|
|
69
|
+
className: (0, _hexclave_ui.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),
|
|
70
70
|
...props,
|
|
71
71
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
72
72
|
className: (0, _hexclave_ui.cn)("flex min-h-0 min-w-0 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden"),
|
|
@@ -77,7 +77,7 @@ function DesignCategoryTabs({ categories, selectedCategory, onSelect, showBadge
|
|
|
77
77
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
78
78
|
onClick: () => handleSelect(category.id),
|
|
79
79
|
disabled: loadingCategoryId !== null,
|
|
80
|
-
className: (0, _hexclave_ui.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 ? (0, _hexclave_ui.cn)(gradientClass.activeText, glassmorphic && "bg-
|
|
80
|
+
className: (0, _hexclave_ui.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 ? (0, _hexclave_ui.cn)(gradientClass.activeText, glassmorphic && "bg-white shadow-sm ring-1 ring-black/[0.12] dark:bg-background dark:ring-white/[0.06]") : (0, _hexclave_ui.cn)("text-gray-700 dark:text-gray-400", glassmorphic && "rounded-lg hover:bg-white/50 dark:hover:bg-white/[0.06]")),
|
|
81
81
|
children: [
|
|
82
82
|
loadingCategoryId === category.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hexclave_ui.Spinner, {
|
|
83
83
|
size: 12,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","names":["Spinner"],"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.
|
|
1
|
+
{"version":3,"file":"tabs.js","names":["Spinner"],"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,qDAAsC,iBAAiB;CAC7D,MAAM,YAAY,mBAAmB,gBAAgB,MAAM,iBAAiB;CAC5E,MAAM,gBAAgB,mBAAmB,iBAAiB,UAAU,kBAAkB;CACtF,MAAM,CAAC,mBAAmB,4CAAgD,KAAK;CAE/E,MAAM,gBAAgB,eAAuB;EAC3C,MAAM,SAAS,SAAS,WAAW;AACnC,MAAI,UAAU,OAAQ,OAAyB,SAAS,YAAY;AAClE,wBAAqB,WAAW;AAChC,wEACE,QAAQ,QAAQ,OAAO,CAAC,cAAc,qBAAqB,KAAK,CAAC,CAClE;;;AAIL,QACE,4CAAC;EACC,gCACE,0CACA,eACI,wHACA,iDACJ,UACD;EACD,GAAI;aAEJ,2CAAC;GACC,gCACE,oGACD;aAEA,WAAW,KAAK,aAAa;IAC5B,MAAM,WAAW,qBAAqB,SAAS;IAC/C,MAAM,aAAa,SAAS,cAAc,SAAS;IACnD,MAAM,kBAAkB,aAAa,eAAe;AAEpD,WACE,4CAAC;KAEC,eAAe,aAAa,SAAS,GAAG;KACxC,UAAU,sBAAsB;KAChC,gCACE,iJACA,gDACA,UAAU,QACV,eAAe,eAAe,IAC9B,gCAEI,cAAc,YACd,gBAAgB,wFACjB,wBAEC,oCACA,gBAAgB,0DACjB,CACJ;;MAEA,sBAAsB,SAAS,MAC9B,2CAACA;OACC,MAAM;OACN,WAAU;QACV;MAEJ,4CAAC;OAAK,gCACJ,2BACA,sBAAsB,SAAS,MAAM,YACtC;;QACE,SAAS,QACR,2CAAC,SAAS;SAAK,WAAU;SAAmB;UAAc;QAE3D,SAAS;QACT,mBACC,2CAAC;SACC,gCACE,gBACA,UAAU,OACV,WACI,cAAc,cACd,gEACL;mBAEA;UACI;;QAEJ;MACN,CAAC,gBAAgB,YAChB,2CAAC,SAAI,gCAAc,0CAA0C,cAAc,UAAU,GAAI;;OAhDtF,SAAS,GAkDP;KAEX;IACE,EACL,YAAY,OACX,2CAAC;GAAI,WAAU;aACZ;IACG,GACJ;GACA"}
|