@hexclave/dashboard-ui-components 1.0.14 → 1.0.15
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/analytics-chart/analytics-chart.js +2 -2
- package/dist/components/analytics-chart/index.js +2 -2
- package/dist/components/button.d.ts +2 -2
- package/dist/components/data-grid/data-grid.js +2 -2
- package/dist/components/data-grid/index.js +2 -2
- package/dist/components/data-grid/use-url-state.js +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 +3 -3
- package/dist/dashboard-ui-components.global.js.map +1 -1
- package/dist/esm/components/analytics-chart/analytics-chart.js +2 -2
- package/dist/esm/components/analytics-chart/index.js +2 -2
- package/dist/esm/components/button.d.ts +2 -2
- package/dist/esm/components/data-grid/data-grid.js +2 -2
- package/dist/esm/components/data-grid/index.js +2 -2
- package/dist/esm/components/data-grid/use-url-state.js +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/package.json +3 -3
- package/src/components/pill-toggle.tsx +1 -1
- package/src/components/tabs.tsx +2 -2
|
@@ -7,8 +7,6 @@ let _hexclave_ui = require("@hexclave/ui");
|
|
|
7
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
8
|
let react = require("react");
|
|
9
9
|
let recharts = require("recharts");
|
|
10
|
-
let __state_js = require("./state.js");
|
|
11
|
-
let __strings_js = require("./strings.js");
|
|
12
10
|
let ___chart_container_js = require("../chart-container.js");
|
|
13
11
|
let __default_analytics_chart_tooltip_js = require("./default-analytics-chart-tooltip.js");
|
|
14
12
|
let __format_js = require("./format.js");
|
|
@@ -17,6 +15,8 @@ let ___button_js = require("../button.js");
|
|
|
17
15
|
let __analytics_chart_pie_js = require("./analytics-chart-pie.js");
|
|
18
16
|
let __palette_js = require("./palette.js");
|
|
19
17
|
let __render_data_series_js = require("./render-data-series.js");
|
|
18
|
+
let __state_js = require("./state.js");
|
|
19
|
+
let __strings_js = require("./strings.js");
|
|
20
20
|
|
|
21
21
|
//#region src/components/analytics-chart/analytics-chart.tsx
|
|
22
22
|
const FALLBACK_PRIMARY_STYLE = {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_chunk = require('../../chunk-BE-pF4vm.js');
|
|
3
|
-
let __state_js = require("./state.js");
|
|
4
|
-
let __strings_js = require("./strings.js");
|
|
5
3
|
let __default_analytics_chart_tooltip_js = require("./default-analytics-chart-tooltip.js");
|
|
6
4
|
let __format_js = require("./format.js");
|
|
7
5
|
let __types_js = require("./types.js");
|
|
8
6
|
let __palette_js = require("./palette.js");
|
|
7
|
+
let __state_js = require("./state.js");
|
|
8
|
+
let __strings_js = require("./strings.js");
|
|
9
9
|
let __analytics_chart_js = require("./analytics-chart.js");
|
|
10
10
|
|
|
11
11
|
Object.defineProperty(exports, 'ANALYTICS_CHART_DEFAULT_LAYERS', {
|
|
@@ -4,7 +4,7 @@ import { VariantProps } from "class-variance-authority";
|
|
|
4
4
|
|
|
5
5
|
//#region src/components/button.d.ts
|
|
6
6
|
declare const designButtonVariants: (props?: ({
|
|
7
|
-
variant?: "
|
|
7
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "plain" | null | undefined;
|
|
8
8
|
size?: "sm" | "lg" | "default" | "icon" | null | undefined;
|
|
9
9
|
} & class_variance_authority_types0.ClassProp) | undefined) => string;
|
|
10
10
|
type DesignOriginalButtonProps = {
|
|
@@ -36,7 +36,7 @@ declare const DesignButton: React.FC<{
|
|
|
36
36
|
} & {
|
|
37
37
|
asChild?: boolean;
|
|
38
38
|
} & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
|
|
39
|
-
variant?: "
|
|
39
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "plain" | null | undefined;
|
|
40
40
|
size?: "sm" | "lg" | "default" | "icon" | null | undefined;
|
|
41
41
|
} & class_variance_authority_types0.ClassProp) | undefined) => string> & {
|
|
42
42
|
ref?: React.Ref<HTMLButtonElement> | undefined;
|
|
@@ -7,14 +7,14 @@ let _hexclave_ui = require("@hexclave/ui");
|
|
|
7
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
8
|
let react = require("react");
|
|
9
9
|
react = require_chunk.__toESM(react);
|
|
10
|
+
let __state_js = require("./state.js");
|
|
11
|
+
let __strings_js = require("./strings.js");
|
|
10
12
|
let _hexclave_shared_dist_utils_errors = require("@hexclave/shared/dist/utils/errors");
|
|
11
13
|
let _tanstack_react_table = require("@tanstack/react-table");
|
|
12
14
|
let _tanstack_react_virtual = require("@tanstack/react-virtual");
|
|
13
15
|
let ___skeleton_js = require("../skeleton.js");
|
|
14
16
|
let __data_grid_sizing_js = require("./data-grid-sizing.js");
|
|
15
17
|
let __data_grid_toolbar_js = require("./data-grid-toolbar.js");
|
|
16
|
-
let __state_js = require("./state.js");
|
|
17
|
-
let __strings_js = require("./strings.js");
|
|
18
18
|
|
|
19
19
|
//#region src/components/data-grid/data-grid.tsx
|
|
20
20
|
function getEventTargetElement(target) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_chunk = require('../../chunk-BE-pF4vm.js');
|
|
3
|
-
let __data_grid_sizing_js = require("./data-grid-sizing.js");
|
|
4
|
-
let __data_grid_toolbar_js = require("./data-grid-toolbar.js");
|
|
5
3
|
let __state_js = require("./state.js");
|
|
6
4
|
let __strings_js = require("./strings.js");
|
|
5
|
+
let __data_grid_sizing_js = require("./data-grid-sizing.js");
|
|
6
|
+
let __data_grid_toolbar_js = require("./data-grid-toolbar.js");
|
|
7
7
|
let __data_grid_js = require("./data-grid.js");
|
|
8
8
|
let __use_data_source_js = require("./use-data-source.js");
|
|
9
9
|
let __use_url_state_js = require("./use-url-state.js");
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
4
|
const require_chunk = require('../../chunk-BE-pF4vm.js');
|
|
5
5
|
let react = require("react");
|
|
6
|
-
let __data_grid_sizing_js = require("./data-grid-sizing.js");
|
|
7
6
|
let __state_js = require("./state.js");
|
|
7
|
+
let __data_grid_sizing_js = require("./data-grid-sizing.js");
|
|
8
8
|
|
|
9
9
|
//#region src/components/data-grid/use-url-state.ts
|
|
10
10
|
function serializeWidths(widths, columns) {
|
|
@@ -88,7 +88,7 @@ function DesignPillToggle({ options, selected, onSelect, size = "md", glassmorph
|
|
|
88
88
|
ref: toggleRef,
|
|
89
89
|
className: (0, _hexclave_ui.cn)("relative inline-flex items-center gap-1 p-1 rounded-xl", glassmorphic ? "bg-foreground/[0.04] backdrop-blur-sm" : "bg-black/[0.08] dark:bg-white/[0.04]", className),
|
|
90
90
|
children: [sliderMetrics != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
91
|
-
className: (0, _hexclave_ui.cn)("pointer-events-none absolute inset-y-1 left-0 z-0 rounded-lg bg-background shadow-sm ring-1", glassmorphic ? "ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:ring-[hsl(240,71%,70%)]/20" : activeRingClass),
|
|
91
|
+
className: (0, _hexclave_ui.cn)("pointer-events-none absolute inset-y-1 left-0 z-0 rounded-lg bg-white dark:bg-background shadow-sm ring-1", glassmorphic ? "ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:ring-[hsl(240,71%,70%)]/20" : activeRingClass),
|
|
92
92
|
style: {
|
|
93
93
|
transition: prefersReducedMotion ? void 0 : sliderTransition,
|
|
94
94
|
transform: `translateX(${sliderMetrics.left}px)`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pill-toggle.js","names":["Spinner","Tooltip","TooltipTrigger","TooltipPortal","TooltipContent","TooltipProvider"],"sources":["../../src/components/pill-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { cn, Spinner, Tooltip, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger } from \"@hexclave/ui\";\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 iconOnlyButton: string,\n icon: string,\n};\n\ntype SliderMetrics = {\n left: number,\n width: number,\n};\n\nconst sliderTransition = \"transform 200ms ease-out, width 200ms ease-out\";\n\nconst sizeClasses = new Map<DesignPillToggleSize, SizeClass>([\n [\"sm\", { button: \"px-3 py-1.5 text-xs\", iconOnlyButton: \"h-7 w-7 text-xs\", icon: \"h-3.5 w-3.5\" }],\n [\"md\", { button: \"px-4 py-2 text-sm\", iconOnlyButton: \"h-9 w-9 text-sm\", icon: \"h-4 w-4\" }],\n [\"lg\", { button: \"px-5 py-2.5 text-sm\", iconOnlyButton: \"h-10 w-10 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 const [sliderMetrics, setSliderMetrics] = useState<SliderMetrics | null>(null);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const toggleRef = useRef<HTMLDivElement | null>(null);\n const optionRefs = useRef(new Map<string, HTMLButtonElement>());\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 useEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n const mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const updatePrefersReducedMotion = () => setPrefersReducedMotion(mediaQuery.matches);\n\n updatePrefersReducedMotion();\n mediaQuery.addEventListener(\"change\", updatePrefersReducedMotion);\n\n return () => mediaQuery.removeEventListener(\"change\", updatePrefersReducedMotion);\n }, []);\n\n useEffect(() => {\n const toggle = toggleRef.current;\n const selectedButton = optionRefs.current.get(selected);\n\n if (!toggle || !selectedButton) {\n setSliderMetrics(null);\n return;\n }\n\n const updateSliderMetrics = () => {\n setSliderMetrics({\n left: selectedButton.offsetLeft,\n width: selectedButton.offsetWidth,\n });\n };\n\n updateSliderMetrics();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const resizeObserver = new ResizeObserver(updateSliderMetrics);\n resizeObserver.observe(toggle);\n resizeObserver.observe(selectedButton);\n\n return () => resizeObserver.disconnect();\n }, [options, selected]);\n\n const body = (\n <div\n ref={toggleRef}\n className={cn(\n \"relative 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 {sliderMetrics != null && (\n <div\n className={cn(\n \"pointer-events-none absolute inset-y-1 left-0 z-0 rounded-lg bg-background shadow-sm ring-1\",\n glassmorphic\n ? \"ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:ring-[hsl(240,71%,70%)]/20\"\n : activeRingClass\n )}\n style={{\n transition: prefersReducedMotion ? undefined : sliderTransition,\n transform: `translateX(${sliderMetrics.left}px)`,\n width: sliderMetrics.width,\n }}\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 ref={(element) => {\n if (element) {\n optionRefs.current.set(option.id, element);\n } else {\n optionRefs.current.delete(option.id);\n }\n }}\n onClick={() => handleClick(option.id)}\n disabled={loadingOptionId !== null}\n aria-label={showLabels ? undefined : option.label}\n className={cn(\n \"relative z-10 flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none\",\n showLabels ? sizeClass.button : sizeClass.iconOnlyButton,\n !showLabels && \"justify-center p-0\",\n isActive\n ? cn(\"text-foreground\", glassmorphic && \"dark:text-[hsl(240,71%,90%)]\")\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 );\n\n // Tooltips require a TooltipProvider in scope. Wrap defensively so callers\n // outside an existing provider (e.g. inside a PageLayout actions slot) work.\n return showLabels ? body : <TooltipProvider>{body}</TooltipProvider>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pill-toggle.js","names":["Spinner","Tooltip","TooltipTrigger","TooltipPortal","TooltipContent","TooltipProvider"],"sources":["../../src/components/pill-toggle.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { cn, Spinner, Tooltip, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger } from \"@hexclave/ui\";\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 iconOnlyButton: string,\n icon: string,\n};\n\ntype SliderMetrics = {\n left: number,\n width: number,\n};\n\nconst sliderTransition = \"transform 200ms ease-out, width 200ms ease-out\";\n\nconst sizeClasses = new Map<DesignPillToggleSize, SizeClass>([\n [\"sm\", { button: \"px-3 py-1.5 text-xs\", iconOnlyButton: \"h-7 w-7 text-xs\", icon: \"h-3.5 w-3.5\" }],\n [\"md\", { button: \"px-4 py-2 text-sm\", iconOnlyButton: \"h-9 w-9 text-sm\", icon: \"h-4 w-4\" }],\n [\"lg\", { button: \"px-5 py-2.5 text-sm\", iconOnlyButton: \"h-10 w-10 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 const [sliderMetrics, setSliderMetrics] = useState<SliderMetrics | null>(null);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const toggleRef = useRef<HTMLDivElement | null>(null);\n const optionRefs = useRef(new Map<string, HTMLButtonElement>());\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 useEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n const mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const updatePrefersReducedMotion = () => setPrefersReducedMotion(mediaQuery.matches);\n\n updatePrefersReducedMotion();\n mediaQuery.addEventListener(\"change\", updatePrefersReducedMotion);\n\n return () => mediaQuery.removeEventListener(\"change\", updatePrefersReducedMotion);\n }, []);\n\n useEffect(() => {\n const toggle = toggleRef.current;\n const selectedButton = optionRefs.current.get(selected);\n\n if (!toggle || !selectedButton) {\n setSliderMetrics(null);\n return;\n }\n\n const updateSliderMetrics = () => {\n setSliderMetrics({\n left: selectedButton.offsetLeft,\n width: selectedButton.offsetWidth,\n });\n };\n\n updateSliderMetrics();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const resizeObserver = new ResizeObserver(updateSliderMetrics);\n resizeObserver.observe(toggle);\n resizeObserver.observe(selectedButton);\n\n return () => resizeObserver.disconnect();\n }, [options, selected]);\n\n const body = (\n <div\n ref={toggleRef}\n className={cn(\n \"relative 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 {sliderMetrics != null && (\n <div\n className={cn(\n \"pointer-events-none absolute inset-y-1 left-0 z-0 rounded-lg bg-white dark:bg-background shadow-sm ring-1\",\n glassmorphic\n ? \"ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:ring-[hsl(240,71%,70%)]/20\"\n : activeRingClass\n )}\n style={{\n transition: prefersReducedMotion ? undefined : sliderTransition,\n transform: `translateX(${sliderMetrics.left}px)`,\n width: sliderMetrics.width,\n }}\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 ref={(element) => {\n if (element) {\n optionRefs.current.set(option.id, element);\n } else {\n optionRefs.current.delete(option.id);\n }\n }}\n onClick={() => handleClick(option.id)}\n disabled={loadingOptionId !== null}\n aria-label={showLabels ? undefined : option.label}\n className={cn(\n \"relative z-10 flex items-center gap-2 font-medium rounded-lg transition-all duration-150 hover:transition-none\",\n showLabels ? sizeClass.button : sizeClass.iconOnlyButton,\n !showLabels && \"justify-center p-0\",\n isActive\n ? cn(\"text-foreground\", glassmorphic && \"dark:text-[hsl(240,71%,90%)]\")\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 );\n\n // Tooltips require a TooltipProvider in scope. Wrap defensively so callers\n // outside an existing provider (e.g. inside a PageLayout actions slot) work.\n return showLabels ? body : <TooltipProvider>{body}</TooltipProvider>;\n}\n"],"mappings":"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"}
|
package/dist/components/tabs.js
CHANGED
|
@@ -103,10 +103,10 @@ function DesignCategoryTabs({ categories, selectedCategory, onSelect, showBadge
|
|
|
103
103
|
...props,
|
|
104
104
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
105
105
|
ref: tabListRef,
|
|
106
|
-
className: (0, _hexclave_ui.cn)("relative flex min-h-0 min-w-0 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden"),
|
|
106
|
+
className: (0, _hexclave_ui.cn)("relative flex min-h-0 min-w-0 flex-1 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden"),
|
|
107
107
|
children: [
|
|
108
108
|
glassmorphic && sliderMetrics != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
109
|
-
className: "pointer-events-none absolute inset-y-0 left-0 z-0 rounded-lg bg-
|
|
109
|
+
className: "pointer-events-none absolute inset-y-0 left-0 z-0 rounded-lg bg-white shadow-sm ring-1 ring-black/[0.12] motion-reduce:transition-none dark:bg-background dark:ring-white/[0.06]",
|
|
110
110
|
style: {
|
|
111
111
|
transition: prefersReducedMotion ? void 0 : sliderTransition,
|
|
112
112
|
transform: `translateX(${sliderMetrics.left}px)`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","names":["Spinner"],"sources":["../../src/components/tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, 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\ntype SliderMetrics = {\n left: number,\n width: number,\n};\n\nconst sliderTransition = \"transform 200ms ease-out, width 200ms ease-out\";\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 const [sliderMetrics, setSliderMetrics] = useState<SliderMetrics | null>(null);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const tabListRef = useRef<HTMLDivElement | null>(null);\n const tabButtonRefs = useRef(new Map<string, HTMLButtonElement>());\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 useEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n const mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const updatePrefersReducedMotion = () => setPrefersReducedMotion(mediaQuery.matches);\n\n updatePrefersReducedMotion();\n mediaQuery.addEventListener(\"change\", updatePrefersReducedMotion);\n\n return () => mediaQuery.removeEventListener(\"change\", updatePrefersReducedMotion);\n }, []);\n\n useEffect(() => {\n const tabList = tabListRef.current;\n const selectedButton = tabButtonRefs.current.get(selectedCategory);\n\n if (!tabList || !selectedButton) {\n setSliderMetrics(null);\n return;\n }\n\n const updateSliderMetrics = () => {\n setSliderMetrics({\n left: selectedButton.offsetLeft,\n width: selectedButton.offsetWidth,\n });\n };\n\n updateSliderMetrics();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const resizeObserver = new ResizeObserver(updateSliderMetrics);\n resizeObserver.observe(tabList);\n resizeObserver.observe(selectedButton);\n\n return () => resizeObserver.disconnect();\n }, [categories, selectedCategory]);\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 ref={tabListRef}\n className={cn(\n \"relative flex min-h-0 min-w-0 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden\",\n )}\n >\n {glassmorphic && sliderMetrics != null && (\n <div\n className=\"pointer-events-none absolute inset-y-0 left-0 z-0 rounded-lg bg-background shadow-sm ring-1 ring-black/[0.12] motion-reduce:transition-none dark:ring-white/[0.06]\"\n style={{\n transition: prefersReducedMotion ? undefined : sliderTransition,\n transform: `translateX(${sliderMetrics.left}px)`,\n width: sliderMetrics.width,\n }}\n />\n )}\n {!glassmorphic && sliderMetrics != null && (\n <div\n className={cn(\n \"pointer-events-none absolute bottom-0 left-0 h-0.5 motion-reduce:transition-none\",\n gradientClass.underline\n )}\n style={{\n transition: prefersReducedMotion ? undefined : sliderTransition,\n transform: `translateX(${sliderMetrics.left}px)`,\n width: sliderMetrics.width,\n }}\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 ref={(element) => {\n if (element) {\n tabButtonRefs.current.set(category.id, element);\n } else {\n tabButtonRefs.current.delete(category.id);\n }\n }}\n onClick={() => handleSelect(category.id)}\n disabled={loadingCategoryId !== null}\n className={cn(\n \"font-medium transition-all duration-150 hover:transition-none relative z-10 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 ? gradientClass.activeText\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 </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":"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"}
|
|
1
|
+
{"version":3,"file":"tabs.js","names":["Spinner"],"sources":["../../src/components/tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, 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\ntype SliderMetrics = {\n left: number,\n width: number,\n};\n\nconst sliderTransition = \"transform 200ms ease-out, width 200ms ease-out\";\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 const [sliderMetrics, setSliderMetrics] = useState<SliderMetrics | null>(null);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const tabListRef = useRef<HTMLDivElement | null>(null);\n const tabButtonRefs = useRef(new Map<string, HTMLButtonElement>());\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 useEffect(() => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n const mediaQuery = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const updatePrefersReducedMotion = () => setPrefersReducedMotion(mediaQuery.matches);\n\n updatePrefersReducedMotion();\n mediaQuery.addEventListener(\"change\", updatePrefersReducedMotion);\n\n return () => mediaQuery.removeEventListener(\"change\", updatePrefersReducedMotion);\n }, []);\n\n useEffect(() => {\n const tabList = tabListRef.current;\n const selectedButton = tabButtonRefs.current.get(selectedCategory);\n\n if (!tabList || !selectedButton) {\n setSliderMetrics(null);\n return;\n }\n\n const updateSliderMetrics = () => {\n setSliderMetrics({\n left: selectedButton.offsetLeft,\n width: selectedButton.offsetWidth,\n });\n };\n\n updateSliderMetrics();\n\n if (typeof ResizeObserver === \"undefined\") return;\n const resizeObserver = new ResizeObserver(updateSliderMetrics);\n resizeObserver.observe(tabList);\n resizeObserver.observe(selectedButton);\n\n return () => resizeObserver.disconnect();\n }, [categories, selectedCategory]);\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 ref={tabListRef}\n className={cn(\n \"relative flex min-h-0 min-w-0 flex-1 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden\",\n )}\n >\n {glassmorphic && sliderMetrics != null && (\n <div\n className=\"pointer-events-none absolute inset-y-0 left-0 z-0 rounded-lg bg-white shadow-sm ring-1 ring-black/[0.12] motion-reduce:transition-none dark:bg-background dark:ring-white/[0.06]\"\n style={{\n transition: prefersReducedMotion ? undefined : sliderTransition,\n transform: `translateX(${sliderMetrics.left}px)`,\n width: sliderMetrics.width,\n }}\n />\n )}\n {!glassmorphic && sliderMetrics != null && (\n <div\n className={cn(\n \"pointer-events-none absolute bottom-0 left-0 h-0.5 motion-reduce:transition-none\",\n gradientClass.underline\n )}\n style={{\n transition: prefersReducedMotion ? undefined : sliderTransition,\n transform: `translateX(${sliderMetrics.left}px)`,\n width: sliderMetrics.width,\n }}\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 ref={(element) => {\n if (element) {\n tabButtonRefs.current.set(category.id, element);\n } else {\n tabButtonRefs.current.delete(category.id);\n }\n }}\n onClick={() => handleSelect(category.id)}\n disabled={loadingCategoryId !== null}\n className={cn(\n \"font-medium transition-all duration-150 hover:transition-none relative z-10 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 ? gradientClass.activeText\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 </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":"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"}
|
|
@@ -18492,7 +18492,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
18492
18492
|
"div",
|
|
18493
18493
|
{
|
|
18494
18494
|
className: cn(
|
|
18495
|
-
"pointer-events-none absolute inset-y-1 left-0 z-0 rounded-lg bg-background shadow-sm ring-1",
|
|
18495
|
+
"pointer-events-none absolute inset-y-1 left-0 z-0 rounded-lg bg-white dark:bg-background shadow-sm ring-1",
|
|
18496
18496
|
glassmorphic ? "ring-foreground/[0.06] dark:bg-[hsl(240,71%,70%)]/10 dark:ring-[hsl(240,71%,70%)]/20" : activeRingClass
|
|
18497
18497
|
),
|
|
18498
18498
|
style: {
|
|
@@ -18796,13 +18796,13 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
|
|
|
18796
18796
|
{
|
|
18797
18797
|
ref: tabListRef,
|
|
18798
18798
|
className: cn(
|
|
18799
|
-
"relative flex min-h-0 min-w-0 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden"
|
|
18799
|
+
"relative flex min-h-0 min-w-0 flex-1 items-center gap-1 overflow-x-auto flex-nowrap [&::-webkit-scrollbar]:hidden"
|
|
18800
18800
|
),
|
|
18801
18801
|
children: [
|
|
18802
18802
|
glassmorphic && sliderMetrics != null && /* @__PURE__ */ jsx(
|
|
18803
18803
|
"div",
|
|
18804
18804
|
{
|
|
18805
|
-
className: "pointer-events-none absolute inset-y-0 left-0 z-0 rounded-lg bg-
|
|
18805
|
+
className: "pointer-events-none absolute inset-y-0 left-0 z-0 rounded-lg bg-white shadow-sm ring-1 ring-black/[0.12] motion-reduce:transition-none dark:bg-background dark:ring-white/[0.06]",
|
|
18806
18806
|
style: {
|
|
18807
18807
|
transition: prefersReducedMotion ? void 0 : sliderTransition2,
|
|
18808
18808
|
transform: `translateX(${sliderMetrics.left}px)`,
|