@hex-core/components 1.3.0 → 1.4.0
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/README.md +183 -9
- package/dist/accordion.d.ts +13 -0
- package/dist/accordion.js +62 -0
- package/dist/accordion.js.map +1 -0
- package/dist/alert-dialog.d.ts +34 -0
- package/dist/alert-dialog.js +125 -0
- package/dist/alert-dialog.js.map +1 -0
- package/dist/alert.d.ts +17 -0
- package/dist/alert.js +54 -0
- package/dist/alert.js.map +1 -0
- package/dist/aspect-ratio.d.ts +7 -0
- package/dist/aspect-ratio.js +8 -0
- package/dist/aspect-ratio.js.map +1 -0
- package/dist/avatar.d.ts +11 -0
- package/dist/avatar.js +44 -0
- package/dist/avatar.js.map +1 -0
- package/dist/badge.d.ts +22 -0
- package/dist/badge.js +36 -0
- package/dist/badge.js.map +1 -0
- package/dist/breadcrumb.d.ts +27 -0
- package/dist/breadcrumb.js +120 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/button-variants-Bx6gCUFp.d.ts +19 -0
- package/dist/button.d.ts +13 -0
- package/dist/button.js +113 -0
- package/dist/button.js.map +1 -0
- package/dist/calendar.d.ts +17 -0
- package/dist/calendar.js +126 -0
- package/dist/calendar.js.map +1 -0
- package/dist/card.d.ts +16 -0
- package/dist/card.js +68 -0
- package/dist/card.js.map +1 -0
- package/dist/checkbox.d.ts +11 -0
- package/dist/checkbox.js +65 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/cluster.d.ts +34 -0
- package/dist/cluster.js +50 -0
- package/dist/cluster.js.map +1 -0
- package/dist/collapsible.d.ts +11 -0
- package/dist/collapsible.js +10 -0
- package/dist/collapsible.js.map +1 -0
- package/dist/color-picker.d.ts +44 -0
- package/dist/color-picker.js +321 -0
- package/dist/color-picker.js.map +1 -0
- package/dist/combobox.d.ts +45 -0
- package/dist/combobox.js +226 -0
- package/dist/combobox.js.map +1 -0
- package/dist/command.d.ts +111 -0
- package/dist/command.js +232 -0
- package/dist/command.js.map +1 -0
- package/dist/container.d.ts +41 -0
- package/dist/container.js +39 -0
- package/dist/container.js.map +1 -0
- package/dist/context-menu.d.ts +37 -0
- package/dist/context-menu.js +130 -0
- package/dist/context-menu.js.map +1 -0
- package/dist/data-table.d.ts +33 -0
- package/dist/data-table.js +103 -0
- package/dist/data-table.js.map +1 -0
- package/dist/date-picker.d.ts +43 -0
- package/dist/date-picker.js +221 -0
- package/dist/date-picker.js.map +1 -0
- package/dist/dialog.d.ts +46 -0
- package/dist/dialog.js +125 -0
- package/dist/dialog.js.map +1 -0
- package/dist/drawer.d.ts +41 -0
- package/dist/drawer.js +82 -0
- package/dist/drawer.js.map +1 -0
- package/dist/dropdown-menu.d.ts +39 -0
- package/dist/dropdown-menu.js +133 -0
- package/dist/dropdown-menu.js.map +1 -0
- package/dist/dropzone.d.ts +54 -0
- package/dist/dropzone.js +194 -0
- package/dist/dropzone.js.map +1 -0
- package/dist/file-tree.d.ts +53 -0
- package/dist/file-tree.js +322 -0
- package/dist/file-tree.js.map +1 -0
- package/dist/form.d.ts +45 -0
- package/dist/form.js +114 -0
- package/dist/form.js.map +1 -0
- package/dist/grid.d.ts +50 -0
- package/dist/grid.js +58 -0
- package/dist/grid.js.map +1 -0
- package/dist/hover-card.d.ts +11 -0
- package/dist/hover-card.js +34 -0
- package/dist/hover-card.js.map +1 -0
- package/dist/index.d.ts +98 -1564
- package/dist/index.js +527 -5536
- package/dist/index.js.map +1 -1
- package/dist/input-otp.d.ts +19 -0
- package/dist/input-otp.js +71 -0
- package/dist/input-otp.js.map +1 -0
- package/dist/input.d.ts +6 -0
- package/dist/input.js +40 -0
- package/dist/input.js.map +1 -0
- package/dist/label.d.ts +11 -0
- package/dist/label.js +22 -0
- package/dist/label.js.map +1 -0
- package/dist/menubar.d.ts +35 -0
- package/dist/menubar.js +106 -0
- package/dist/menubar.js.map +1 -0
- package/dist/multi-combobox.d.ts +51 -0
- package/dist/multi-combobox.js +258 -0
- package/dist/multi-combobox.js.map +1 -0
- package/dist/navigation-menu.d.ts +23 -0
- package/dist/navigation-menu.js +108 -0
- package/dist/navigation-menu.js.map +1 -0
- package/dist/pagination.d.ts +40 -0
- package/dist/pagination.js +195 -0
- package/dist/pagination.js.map +1 -0
- package/dist/popover.d.ts +13 -0
- package/dist/popover.js +35 -0
- package/dist/popover.js.map +1 -0
- package/dist/progress.d.ts +10 -0
- package/dist/progress.js +38 -0
- package/dist/progress.js.map +1 -0
- package/dist/radio-group.d.ts +9 -0
- package/dist/radio-group.js +44 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/resizable.d.ts +28 -0
- package/dist/resizable.js +66 -0
- package/dist/resizable.js.map +1 -0
- package/dist/schemas.d.ts +121 -0
- package/dist/schemas.js +4643 -0
- package/dist/schemas.js.map +1 -0
- package/dist/scroll-area.d.ts +18 -0
- package/dist/scroll-area.js +55 -0
- package/dist/scroll-area.js.map +1 -0
- package/dist/select.d.ts +21 -0
- package/dist/select.js +136 -0
- package/dist/select.js.map +1 -0
- package/dist/separator.d.ts +11 -0
- package/dist/separator.js +29 -0
- package/dist/separator.js.map +1 -0
- package/dist/sheet.d.ts +39 -0
- package/dist/sheet.js +140 -0
- package/dist/sheet.js.map +1 -0
- package/dist/sidebar.d.ts +75 -0
- package/dist/sidebar.js +201 -0
- package/dist/sidebar.js.map +1 -0
- package/dist/skeleton.d.ts +11 -0
- package/dist/skeleton.js +21 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/slider.d.ts +20 -0
- package/dist/slider.js +55 -0
- package/dist/slider.js.map +1 -0
- package/dist/sonner.d.ts +14 -0
- package/dist/sonner.js +27 -0
- package/dist/sonner.js.map +1 -0
- package/dist/spacer.d.ts +38 -0
- package/dist/spacer.js +43 -0
- package/dist/spacer.js.map +1 -0
- package/dist/stack.d.ts +34 -0
- package/dist/stack.js +49 -0
- package/dist/stack.js.map +1 -0
- package/dist/stepper.d.ts +48 -0
- package/dist/stepper.js +226 -0
- package/dist/stepper.js.map +1 -0
- package/dist/switch.d.ts +11 -0
- package/dist/switch.js +47 -0
- package/dist/switch.js.map +1 -0
- package/dist/table.d.ts +24 -0
- package/dist/table.js +85 -0
- package/dist/table.js.map +1 -0
- package/dist/tabs.d.ts +13 -0
- package/dist/tabs.js +57 -0
- package/dist/tabs.js.map +1 -0
- package/dist/textarea.d.ts +10 -0
- package/dist/textarea.js +36 -0
- package/dist/textarea.js.map +1 -0
- package/dist/time-picker.d.ts +34 -0
- package/dist/time-picker.js +50 -0
- package/dist/time-picker.js.map +1 -0
- package/dist/timeline.d.ts +42 -0
- package/dist/timeline.js +84 -0
- package/dist/timeline.js.map +1 -0
- package/dist/toggle-group.d.ts +17 -0
- package/dist/toggle-group.js +83 -0
- package/dist/toggle-group.js.map +1 -0
- package/dist/toggle.d.ts +19 -0
- package/dist/toggle.js +49 -0
- package/dist/toggle.js.map +1 -0
- package/dist/tooltip.d.ts +13 -0
- package/dist/tooltip.js +33 -0
- package/dist/tooltip.js.map +1 -0
- package/package.json +68 -16
package/dist/card.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/components/card/card.tsx
|
|
7
|
+
function cn(...inputs) {
|
|
8
|
+
return twMerge(clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
var Card = React.forwardRef(
|
|
11
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
12
|
+
"div",
|
|
13
|
+
{
|
|
14
|
+
ref,
|
|
15
|
+
className: cn(
|
|
16
|
+
"rounded-lg border border-foreground/[0.08] bg-card text-card-foreground",
|
|
17
|
+
"shadow-sm transition-all duration-[var(--duration-normal,200ms)] ease-out",
|
|
18
|
+
"hover:shadow-md",
|
|
19
|
+
className
|
|
20
|
+
),
|
|
21
|
+
...props
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
Card.displayName = "Card";
|
|
26
|
+
var CardHeader = React.forwardRef(
|
|
27
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
28
|
+
"div",
|
|
29
|
+
{
|
|
30
|
+
ref,
|
|
31
|
+
className: cn("flex flex-col space-y-1.5 p-[var(--space-6,1.5rem)]", className),
|
|
32
|
+
...props
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
CardHeader.displayName = "CardHeader";
|
|
37
|
+
var CardTitle = React.forwardRef(
|
|
38
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
39
|
+
"h3",
|
|
40
|
+
{
|
|
41
|
+
ref,
|
|
42
|
+
className: cn("text-2xl font-semibold leading-none tracking-tight", className),
|
|
43
|
+
...props
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
CardTitle.displayName = "CardTitle";
|
|
48
|
+
var CardDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
|
|
49
|
+
CardDescription.displayName = "CardDescription";
|
|
50
|
+
var CardContent = React.forwardRef(
|
|
51
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-[var(--space-6,1.5rem)] pt-0", className), ...props })
|
|
52
|
+
);
|
|
53
|
+
CardContent.displayName = "CardContent";
|
|
54
|
+
var CardFooter = React.forwardRef(
|
|
55
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
56
|
+
"div",
|
|
57
|
+
{
|
|
58
|
+
ref,
|
|
59
|
+
className: cn("flex items-center p-[var(--space-6,1.5rem)] pt-0", className),
|
|
60
|
+
...props
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
CardFooter.displayName = "CardFooter";
|
|
65
|
+
|
|
66
|
+
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
|
|
67
|
+
//# sourceMappingURL=card.js.map
|
|
68
|
+
//# sourceMappingURL=card.js.map
|
package/dist/card.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts","../src/components/card/card.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACHA,IAAM,IAAA,GAAa,KAAA,CAAA,UAAA;AAAA,EAClB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACV,yEAAA;AAAA,QACA,2EAAA;AAAA,QACA,iBAAA;AAAA,QACA;AAAA,OACD;AAAA,MACC,GAAG;AAAA;AAAA;AAGP;AACA,IAAA,CAAK,WAAA,GAAc,MAAA;AAGnB,IAAM,UAAA,GAAmB,KAAA,CAAA,UAAA;AAAA,EACxB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,qDAAA,EAAuD,SAAS,CAAA;AAAA,MAC7E,GAAG;AAAA;AAAA;AAGP;AACA,UAAA,CAAW,WAAA,GAAc,YAAA;AAGzB,IAAM,SAAA,GAAkB,KAAA,CAAA,UAAA;AAAA,EACvB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,oDAAA,EAAsD,SAAS,CAAA;AAAA,MAC5E,GAAG;AAAA;AAAA;AAGP;AACA,SAAA,CAAU,WAAA,GAAc,WAAA;AAGxB,IAAM,kBAAwB,KAAA,CAAA,UAAA,CAG5B,CAAC,EAAE,SAAA,EAAW,GAAG,OAAM,EAAG,GAAA,yBAC1B,GAAA,EAAA,EAAE,GAAA,EAAU,WAAW,EAAA,CAAG,+BAAA,EAAiC,SAAS,CAAA,EAAI,GAAG,OAAO,CACnF;AACD,eAAA,CAAgB,WAAA,GAAc,iBAAA;AAG9B,IAAM,WAAA,GAAoB,KAAA,CAAA,UAAA;AAAA,EACzB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAU,WAAW,EAAA,CAAG,gCAAA,EAAkC,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO;AAExF;AACA,WAAA,CAAY,WAAA,GAAc,aAAA;AAG1B,IAAM,UAAA,GAAmB,KAAA,CAAA,UAAA;AAAA,EACxB,CAAC,EAAE,SAAA,EAAW,GAAG,KAAA,IAAS,GAAA,qBACzB,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,kDAAA,EAAoD,SAAS,CAAA;AAAA,MAC1E,GAAG;AAAA;AAAA;AAGP;AACA,UAAA,CAAW,WAAA,GAAc,YAAA","file":"card.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\n\n// Card consumes tokens --space-6, --space-4, --duration-normal.\n// Fallbacks match Tailwind defaults for consumers without a theme loaded.\n\n/** A container card with subtle shadow and border. */\nconst Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\n\t\t\t\t\"rounded-lg border border-foreground/[0.08] bg-card text-card-foreground\",\n\t\t\t\t\"shadow-sm transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\t\"hover:shadow-md\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCard.displayName = \"Card\";\n\n/** The header section of a Card. */\nconst CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"flex flex-col space-y-1.5 p-[var(--space-6,1.5rem)]\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** The title element inside a CardHeader. */\nconst CardTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<h3\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"text-2xl font-semibold leading-none tracking-tight\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** A description element inside a CardHeader. */\nconst CardDescription = React.forwardRef<\n\tHTMLParagraphElement,\n\tReact.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n\t<p ref={ref} className={cn(\"text-sm text-muted-foreground\", className)} {...props} />\n));\nCardDescription.displayName = \"CardDescription\";\n\n/** The main content area of a Card. */\nconst CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div ref={ref} className={cn(\"p-[var(--space-6,1.5rem)] pt-0\", className)} {...props} />\n\t),\n);\nCardContent.displayName = \"CardContent\";\n\n/** The footer section of a Card. */\nconst CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n\t({ className, ...props }, ref) => (\n\t\t<div\n\t\t\tref={ref}\n\t\t\tclassName={cn(\"flex items-center p-[var(--space-6,1.5rem)] pt-0\", className)}\n\t\t\t{...props}\n\t\t/>\n\t),\n);\nCardFooter.displayName = \"CardFooter\";\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* An accessible checkbox component built on Radix UI.
|
|
6
|
+
* Supports checked, unchecked, and indeterminate states with smooth animations.
|
|
7
|
+
*/
|
|
8
|
+
type CheckboxProps = React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>;
|
|
9
|
+
declare const Checkbox: React.ForwardRefExoticComponent<Omit<CheckboxPrimitive.CheckboxProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
10
|
+
|
|
11
|
+
export { Checkbox, type CheckboxProps };
|
package/dist/checkbox.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
6
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
function cn(...inputs) {
|
|
9
|
+
return twMerge(clsx(inputs));
|
|
10
|
+
}
|
|
11
|
+
var Checkbox = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
12
|
+
CheckboxPrimitive.Root,
|
|
13
|
+
{
|
|
14
|
+
ref,
|
|
15
|
+
className: cn(
|
|
16
|
+
"group h-4 w-4 shrink-0 rounded-sm border border-input",
|
|
17
|
+
"transition-all duration-[var(--duration-normal,200ms)] ease-out",
|
|
18
|
+
"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]",
|
|
19
|
+
"hover:border-ring/50 hover:shadow-md",
|
|
20
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
21
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
22
|
+
"data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground",
|
|
23
|
+
"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground",
|
|
24
|
+
className
|
|
25
|
+
),
|
|
26
|
+
...props,
|
|
27
|
+
children: /* @__PURE__ */ jsxs(CheckboxPrimitive.Indicator, { className: cn("flex items-center justify-center text-current"), children: [
|
|
28
|
+
/* @__PURE__ */ jsx(
|
|
29
|
+
"svg",
|
|
30
|
+
{
|
|
31
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
32
|
+
viewBox: "0 0 24 24",
|
|
33
|
+
fill: "none",
|
|
34
|
+
stroke: "currentColor",
|
|
35
|
+
strokeWidth: "3",
|
|
36
|
+
strokeLinecap: "round",
|
|
37
|
+
strokeLinejoin: "round",
|
|
38
|
+
className: "hidden h-3.5 w-3.5 group-data-[state=checked]:block",
|
|
39
|
+
"aria-hidden": "true",
|
|
40
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
41
|
+
}
|
|
42
|
+
),
|
|
43
|
+
/* @__PURE__ */ jsx(
|
|
44
|
+
"svg",
|
|
45
|
+
{
|
|
46
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
47
|
+
viewBox: "0 0 24 24",
|
|
48
|
+
fill: "none",
|
|
49
|
+
stroke: "currentColor",
|
|
50
|
+
strokeWidth: "3",
|
|
51
|
+
strokeLinecap: "round",
|
|
52
|
+
strokeLinejoin: "round",
|
|
53
|
+
className: "hidden h-3.5 w-3.5 group-data-[state=indeterminate]:block",
|
|
54
|
+
"aria-hidden": "true",
|
|
55
|
+
children: /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
] })
|
|
59
|
+
}
|
|
60
|
+
));
|
|
61
|
+
Checkbox.displayName = "Checkbox";
|
|
62
|
+
|
|
63
|
+
export { Checkbox };
|
|
64
|
+
//# sourceMappingURL=checkbox.js.map
|
|
65
|
+
//# sourceMappingURL=checkbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts","../src/primitives/checkbox/checkbox.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACEA,IAAM,QAAA,GAAiB,iBAGrB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC3B,GAAA;AAAA,EAAmB,iBAAA,CAAA,IAAA;AAAA,EAAlB;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACV,uDAAA;AAAA,MACA,iEAAA;AAAA,MACA,qDAAA;AAAA,MACA,sCAAA;AAAA,MACA,qGAAA;AAAA,MACA,iDAAA;AAAA,MACA,kHAAA;AAAA,MACA,oIAAA;AAAA,MACA;AAAA,KACD;AAAA,IACC,GAAG,KAAA;AAAA,IAEJ,+BAAmB,iBAAA,CAAA,SAAA,EAAlB,EAA4B,SAAA,EAAW,EAAA,CAAG,+CAA+C,CAAA,EAGzF,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACA,KAAA,EAAM,4BAAA;AAAA,UACN,OAAA,EAAQ,WAAA;AAAA,UACR,IAAA,EAAK,MAAA;AAAA,UACL,MAAA,EAAO,cAAA;AAAA,UACP,WAAA,EAAY,GAAA;AAAA,UACZ,aAAA,EAAc,OAAA;AAAA,UACd,cAAA,EAAe,OAAA;AAAA,UACf,SAAA,EAAU,qDAAA;AAAA,UACV,aAAA,EAAY,MAAA;AAAA,UAEZ,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAS,MAAA,EAAO,gBAAA,EAAiB;AAAA;AAAA,OACnC;AAAA,sBACA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACA,KAAA,EAAM,4BAAA;AAAA,UACN,OAAA,EAAQ,WAAA;AAAA,UACR,IAAA,EAAK,MAAA;AAAA,UACL,MAAA,EAAO,cAAA;AAAA,UACP,WAAA,EAAY,GAAA;AAAA,UACZ,aAAA,EAAc,OAAA;AAAA,UACd,cAAA,EAAe,OAAA;AAAA,UACf,SAAA,EAAU,2DAAA;AAAA,UACV,aAAA,EAAY,MAAA;AAAA,UAEZ,QAAA,kBAAA,GAAA,CAAC,UAAK,EAAA,EAAG,GAAA,EAAI,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK;AAAA;AAAA;AACtC,KAAA,EACD;AAAA;AACD,CACA;AACD,QAAA,CAAS,WAAA,GAAc,UAAA","file":"checkbox.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\";\nimport { cn } from \"../../lib/utils.js\";\n\n/**\n * An accessible checkbox component built on Radix UI.\n * Supports checked, unchecked, and indeterminate states with smooth animations.\n */\nexport type CheckboxProps = React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>;\n\nconst Checkbox = React.forwardRef<\n\tReact.ComponentRef<typeof CheckboxPrimitive.Root>,\n\tCheckboxProps\n>(({ className, ...props }, ref) => (\n\t<CheckboxPrimitive.Root\n\t\tref={ref}\n\t\tclassName={cn(\n\t\t\t\"group h-4 w-4 shrink-0 rounded-sm border border-input\",\n\t\t\t\"transition-all duration-[var(--duration-normal,200ms)] ease-out\",\n\t\t\t\"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]\",\n\t\t\t\"hover:border-ring/50 hover:shadow-md\",\n\t\t\t\"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\",\n\t\t\t\"disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\"data-[state=checked]:bg-primary data-[state=checked]:border-primary data-[state=checked]:text-primary-foreground\",\n\t\t\t\"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:border-primary data-[state=indeterminate]:text-primary-foreground\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t<CheckboxPrimitive.Indicator className={cn(\"flex items-center justify-center text-current\")}>\n\t\t\t{/* ✓ when checked; dash when indeterminate. The Root has `group`, so each icon\n\t\t\t shows only when the Root's data-state matches. */}\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"3\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tclassName=\"hidden h-3.5 w-3.5 group-data-[state=checked]:block\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<polyline points=\"20 6 9 17 4 12\" />\n\t\t\t</svg>\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"3\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\tclassName=\"hidden h-3.5 w-3.5 group-data-[state=indeterminate]:block\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n\t\t\t</svg>\n\t\t</CheckboxPrimitive.Indicator>\n\t</CheckboxPrimitive.Root>\n));\nCheckbox.displayName = \"Checkbox\";\n\nexport { Checkbox };\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* CVA variants for Cluster — horizontal flex flow with wrap.
|
|
8
|
+
* `gap` and `justify` pull from shared layout-variant maps; `align` adds
|
|
9
|
+
* `baseline` (text-baseline alignment for mixed-size siblings).
|
|
10
|
+
*/
|
|
11
|
+
declare const clusterVariants: (props?: ({
|
|
12
|
+
gap?: "sm" | "lg" | "md" | "xl" | "xs" | null | undefined;
|
|
13
|
+
align?: "center" | "start" | "end" | "stretch" | "baseline" | null | undefined;
|
|
14
|
+
justify?: "center" | "start" | "end" | "between" | null | undefined;
|
|
15
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
16
|
+
/** Props for the Cluster component. */
|
|
17
|
+
interface ClusterProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof clusterVariants> {
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Horizontal flex flow with wrap. Children flow left-to-right and wrap to next line as needed.
|
|
21
|
+
* @param props - Cluster props including `gap`, `align`, and `justify` variant keys.
|
|
22
|
+
* @returns A flex row that wraps with consistent gap.
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* <Cluster gap="sm">
|
|
26
|
+
* <Badge>react</Badge>
|
|
27
|
+
* <Badge>typescript</Badge>
|
|
28
|
+
* <Badge>tailwind</Badge>
|
|
29
|
+
* </Cluster>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare function Cluster({ className, gap, align, justify, ...props }: ClusterProps): react_jsx_runtime.JSX.Element;
|
|
33
|
+
|
|
34
|
+
export { Cluster, type ClusterProps, clusterVariants };
|
package/dist/cluster.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { cva } from 'class-variance-authority';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
// src/primitives/cluster/cluster.tsx
|
|
7
|
+
function cn(...inputs) {
|
|
8
|
+
return twMerge(clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/primitives/_shared/layout-variants.ts
|
|
12
|
+
var gapVariants = {
|
|
13
|
+
xs: "gap-[var(--gap-xs,0.25rem)]",
|
|
14
|
+
sm: "gap-[var(--gap-sm,0.5rem)]",
|
|
15
|
+
md: "gap-[var(--gap-md,1rem)]",
|
|
16
|
+
lg: "gap-[var(--gap-lg,1.5rem)]",
|
|
17
|
+
xl: "gap-[var(--gap-xl,2rem)]"
|
|
18
|
+
};
|
|
19
|
+
var justifyVariants = {
|
|
20
|
+
start: "justify-start",
|
|
21
|
+
center: "justify-center",
|
|
22
|
+
end: "justify-end",
|
|
23
|
+
between: "justify-between"
|
|
24
|
+
};
|
|
25
|
+
var clusterAlignVariants = {
|
|
26
|
+
start: "items-start",
|
|
27
|
+
center: "items-center",
|
|
28
|
+
end: "items-end",
|
|
29
|
+
stretch: "items-stretch",
|
|
30
|
+
baseline: "items-baseline"
|
|
31
|
+
};
|
|
32
|
+
var clusterVariants = cva("flex flex-wrap", {
|
|
33
|
+
variants: {
|
|
34
|
+
gap: gapVariants,
|
|
35
|
+
align: clusterAlignVariants,
|
|
36
|
+
justify: justifyVariants
|
|
37
|
+
},
|
|
38
|
+
defaultVariants: {
|
|
39
|
+
gap: "md",
|
|
40
|
+
align: "center",
|
|
41
|
+
justify: "start"
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
function Cluster({ className, gap, align, justify, ...props }) {
|
|
45
|
+
return /* @__PURE__ */ jsx("div", { className: cn(clusterVariants({ gap, align, justify }), className), ...props });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { Cluster, clusterVariants };
|
|
49
|
+
//# sourceMappingURL=cluster.js.map
|
|
50
|
+
//# sourceMappingURL=cluster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts","../src/primitives/_shared/layout-variants.ts","../src/primitives/cluster/cluster.tsx"],"names":[],"mappings":";;;;;;AAQO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;;;ACCO,IAAM,WAAA,GAAc;AAAA,EAC1B,EAAA,EAAI,6BAAA;AAAA,EACJ,EAAA,EAAI,4BAAA;AAAA,EACJ,EAAA,EAAI,0BAAA;AAAA,EACJ,EAAA,EAAI,4BAAA;AAAA,EACJ,EAAA,EAAI;AACL,CAAA;AAGO,IAAM,eAAA,GAAkB;AAAA,EAC9B,KAAA,EAAO,eAAA;AAAA,EACP,MAAA,EAAQ,gBAAA;AAAA,EACR,GAAA,EAAK,aAAA;AAAA,EACL,OAAA,EAAS;AACV,CAAA;AAWO,IAAM,oBAAA,GAAuB;AAAA,EACnC,KAAA,EAAO,aAAA;AAAA,EACP,MAAA,EAAQ,cAAA;AAAA,EACR,GAAA,EAAK,WAAA;AAAA,EACL,OAAA,EAAS,eAAA;AAAA,EACT,QAAA,EAAU;AACX,CAAA;AC5BA,IAAM,eAAA,GAAkB,IAAI,gBAAA,EAAkB;AAAA,EAC7C,QAAA,EAAU;AAAA,IACT,GAAA,EAAK,WAAA;AAAA,IACL,KAAA,EAAO,oBAAA;AAAA,IACP,OAAA,EAAS;AAAA,GACV;AAAA,EACA,eAAA,EAAiB;AAAA,IAChB,GAAA,EAAK,IAAA;AAAA,IACL,KAAA,EAAO,QAAA;AAAA,IACP,OAAA,EAAS;AAAA;AAEX,CAAC;AAoBD,SAAS,OAAA,CAAQ,EAAE,SAAA,EAAW,GAAA,EAAK,OAAO,OAAA,EAAS,GAAG,OAAM,EAAiB;AAC5E,EAAA,uBACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,gBAAgB,EAAE,GAAA,EAAK,KAAA,EAAO,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AAEtF","file":"cluster.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge class names with Tailwind CSS conflict resolution.\n * @param inputs - Class values (strings, arrays, objects) to merge\n * @returns A single merged class string with Tailwind conflicts resolved\n */\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","/**\n * Single source of truth for layout-primitive CVA variant maps.\n *\n * Stack, Cluster, Grid all share `gap` and `justify` value sets; align values\n * differ slightly (`stretch` for column-like flows, `baseline` for row flows).\n * Centralizing the maps here keeps token names and Tailwind classes in one\n * file — when the gap scale changes (renamed token, new step, etc.), all\n * three components update together.\n */\n\n/** Gap scale bound to `--gap-*` tokens. Used by Stack, Cluster, Grid. */\nexport const gapVariants = {\n\txs: \"gap-[var(--gap-xs,0.25rem)]\",\n\tsm: \"gap-[var(--gap-sm,0.5rem)]\",\n\tmd: \"gap-[var(--gap-md,1rem)]\",\n\tlg: \"gap-[var(--gap-lg,1.5rem)]\",\n\txl: \"gap-[var(--gap-xl,2rem)]\",\n} as const;\n\n/** `justify-content` values shared by Stack and Cluster. */\nexport const justifyVariants = {\n\tstart: \"justify-start\",\n\tcenter: \"justify-center\",\n\tend: \"justify-end\",\n\tbetween: \"justify-between\",\n} as const;\n\n/** Cross-axis `align-items` values for vertical/grid flows (column-like). */\nexport const flexAlignVariants = {\n\tstart: \"items-start\",\n\tcenter: \"items-center\",\n\tend: \"items-end\",\n\tstretch: \"items-stretch\",\n} as const;\n\n/** Cross-axis `align-items` values for horizontal flows. Includes `baseline`. */\nexport const clusterAlignVariants = {\n\tstart: \"items-start\",\n\tcenter: \"items-center\",\n\tend: \"items-end\",\n\tstretch: \"items-stretch\",\n\tbaseline: \"items-baseline\",\n} as const;\n","import { type VariantProps, cva } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"../../lib/utils.js\";\nimport {\n\tclusterAlignVariants,\n\tgapVariants,\n\tjustifyVariants,\n} from \"../_shared/layout-variants.js\";\n\n/**\n * CVA variants for Cluster — horizontal flex flow with wrap.\n * `gap` and `justify` pull from shared layout-variant maps; `align` adds\n * `baseline` (text-baseline alignment for mixed-size siblings).\n */\nconst clusterVariants = cva(\"flex flex-wrap\", {\n\tvariants: {\n\t\tgap: gapVariants,\n\t\talign: clusterAlignVariants,\n\t\tjustify: justifyVariants,\n\t},\n\tdefaultVariants: {\n\t\tgap: \"md\",\n\t\talign: \"center\",\n\t\tjustify: \"start\",\n\t},\n});\n\n/** Props for the Cluster component. */\nexport interface ClusterProps\n\textends React.HTMLAttributes<HTMLDivElement>,\n\t\tVariantProps<typeof clusterVariants> {}\n\n/**\n * Horizontal flex flow with wrap. Children flow left-to-right and wrap to next line as needed.\n * @param props - Cluster props including `gap`, `align`, and `justify` variant keys.\n * @returns A flex row that wraps with consistent gap.\n * @example\n * ```tsx\n * <Cluster gap=\"sm\">\n * <Badge>react</Badge>\n * <Badge>typescript</Badge>\n * <Badge>tailwind</Badge>\n * </Cluster>\n * ```\n */\nfunction Cluster({ className, gap, align, justify, ...props }: ClusterProps) {\n\treturn (\n\t\t<div className={cn(clusterVariants({ gap, align, justify }), className)} {...props} />\n\t);\n}\n\nexport { Cluster, clusterVariants };\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
3
|
+
|
|
4
|
+
/** Root container controlling the expanded state of the content. */
|
|
5
|
+
declare const Collapsible: React.ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleProps & React.RefAttributes<HTMLDivElement>>;
|
|
6
|
+
/** The element that toggles the Collapsible open/closed. */
|
|
7
|
+
declare const CollapsibleTrigger: React.ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
8
|
+
/** The collapsible content shown/hidden by the trigger. */
|
|
9
|
+
declare const CollapsibleContent: React.ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleContentProps & React.RefAttributes<HTMLDivElement>>;
|
|
10
|
+
|
|
11
|
+
export { Collapsible, CollapsibleContent, CollapsibleTrigger };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
3
|
+
|
|
4
|
+
var Collapsible = CollapsiblePrimitive.Root;
|
|
5
|
+
var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
|
|
6
|
+
var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
|
|
7
|
+
|
|
8
|
+
export { Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger };
|
|
9
|
+
//# sourceMappingURL=collapsible.js.map
|
|
10
|
+
//# sourceMappingURL=collapsible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/collapsible/collapsible.tsx"],"names":["CollapsibleTrigger","CollapsibleContent"],"mappings":";;AAKA,IAAM,WAAA,GAAmC,oBAAA,CAAA;AAGzC,IAAMA,mBAAAA,GAA0C,oBAAA,CAAA;AAGhD,IAAMC,mBAAAA,GAA0C,oBAAA,CAAA","file":"collapsible.js","sourcesContent":["\"use client\";\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\";\n\n/** Root container controlling the expanded state of the content. */\nconst Collapsible = CollapsiblePrimitive.Root;\n\n/** The element that toggles the Collapsible open/closed. */\nconst CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;\n\n/** The collapsible content shown/hidden by the trigger. */\nconst CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent };\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/** Props for the ColorPicker component. */
|
|
4
|
+
interface ColorPickerProps {
|
|
5
|
+
/**
|
|
6
|
+
* Current color as an HSL triplet string (`"<H> <S>% <L>%"`, e.g. `"240 5.9% 10%"`).
|
|
7
|
+
* Match the format used by `@hex-core/tokens`; round-trip safe.
|
|
8
|
+
*/
|
|
9
|
+
value: string;
|
|
10
|
+
/**
|
|
11
|
+
* Called with the next HSL triplet whenever the user drags a slider or commits a valid hex value.
|
|
12
|
+
* Not called for invalid hex input — the picker keeps the prior value until the input parses cleanly.
|
|
13
|
+
*/
|
|
14
|
+
onChange: (value: string) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Disable interaction. Native `disabled` attribute is set on the trigger so the
|
|
17
|
+
* popover doesn't open via mouse or keyboard activation. Tab focus still lands
|
|
18
|
+
* on the trigger per browser defaults; if you want to fully remove it from the
|
|
19
|
+
* tab order, wrap in a parent that handles `tabIndex` accordingly.
|
|
20
|
+
*/
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** Accessible name for the trigger button (defaults to "Pick color"). */
|
|
23
|
+
"aria-label"?: string;
|
|
24
|
+
/** Additional class names merged onto the trigger. */
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* HSL-native color picker. Edits an HSL triplet directly via three sliders
|
|
29
|
+
* (H/S/L), with a hex input as a display adapter.
|
|
30
|
+
*
|
|
31
|
+
* Round-trip safe: triplet → hex → triplet preserves the slider state because
|
|
32
|
+
* sliders are the source of truth and hex updates them only when valid.
|
|
33
|
+
*
|
|
34
|
+
* @param props - Controlled component; `value` and `onChange` are required.
|
|
35
|
+
* @returns A trigger button that opens a popover with H/S/L sliders + hex input.
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* const [color, setColor] = React.useState("240 5.9% 10%");
|
|
39
|
+
* <ColorPicker value={color} onChange={setColor} aria-label="Primary color" />
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
declare function ColorPicker({ value, onChange, disabled, "aria-label": ariaLabel, className, }: ColorPickerProps): react_jsx_runtime.JSX.Element;
|
|
43
|
+
|
|
44
|
+
export { ColorPicker, type ColorPickerProps };
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as React5 from 'react';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
|
+
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
7
|
+
import { cva } from 'class-variance-authority';
|
|
8
|
+
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
9
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
10
|
+
|
|
11
|
+
function cn(...inputs) {
|
|
12
|
+
return twMerge(clsx(inputs));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/lib/color.ts
|
|
16
|
+
function parseHslTriplet(triplet) {
|
|
17
|
+
const parts = triplet.trim().split(/\s+/);
|
|
18
|
+
return {
|
|
19
|
+
h: Number.parseFloat(parts[0]) || 0,
|
|
20
|
+
s: Number.parseFloat(parts[1]) || 0,
|
|
21
|
+
l: Number.parseFloat(parts[2]) || 0
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function formatHslTriplet({ h, s, l }) {
|
|
25
|
+
const round = (n) => Math.abs(n - Math.round(n)) < 1e-6 ? `${Math.round(n)}` : n.toFixed(1);
|
|
26
|
+
return `${Math.round(h)} ${round(s)}% ${round(l)}%`;
|
|
27
|
+
}
|
|
28
|
+
function hslToRgb(h, s, l) {
|
|
29
|
+
const sN = s / 100;
|
|
30
|
+
const lN = l / 100;
|
|
31
|
+
const k = (n) => (n + h / 30) % 12;
|
|
32
|
+
const a = sN * Math.min(lN, 1 - lN);
|
|
33
|
+
const f = (n) => lN - a * Math.max(-1, Math.min(k(n) - 3, 9 - k(n), 1));
|
|
34
|
+
return {
|
|
35
|
+
r: Math.round(255 * f(0)),
|
|
36
|
+
g: Math.round(255 * f(8)),
|
|
37
|
+
b: Math.round(255 * f(4))
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function rgbToHsl(r, g, b) {
|
|
41
|
+
const rN = r / 255;
|
|
42
|
+
const gN = g / 255;
|
|
43
|
+
const bN = b / 255;
|
|
44
|
+
const max = Math.max(rN, gN, bN);
|
|
45
|
+
const min = Math.min(rN, gN, bN);
|
|
46
|
+
let h = 0;
|
|
47
|
+
let s = 0;
|
|
48
|
+
const l = (max + min) / 2;
|
|
49
|
+
if (max !== min) {
|
|
50
|
+
const d = max - min;
|
|
51
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
52
|
+
if (max === rN) h = (gN - bN) / d + (gN < bN ? 6 : 0);
|
|
53
|
+
else if (max === gN) h = (bN - rN) / d + 2;
|
|
54
|
+
else h = (rN - gN) / d + 4;
|
|
55
|
+
h /= 6;
|
|
56
|
+
}
|
|
57
|
+
return { h: h * 360, s: s * 100, l: l * 100 };
|
|
58
|
+
}
|
|
59
|
+
function hslTripletToHex(triplet) {
|
|
60
|
+
const { h, s, l } = parseHslTriplet(triplet);
|
|
61
|
+
const { r, g, b } = hslToRgb(h, s, l);
|
|
62
|
+
const toHex = (n) => n.toString(16).padStart(2, "0");
|
|
63
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
64
|
+
}
|
|
65
|
+
function hexToHslTriplet(hex) {
|
|
66
|
+
const clean = hex.trim().replace(/^#/, "");
|
|
67
|
+
let normalized;
|
|
68
|
+
if (/^[0-9a-fA-F]{3}$/.test(clean)) {
|
|
69
|
+
normalized = clean.split("").map((c) => c + c).join("");
|
|
70
|
+
} else if (/^[0-9a-fA-F]{6}$/.test(clean)) {
|
|
71
|
+
normalized = clean;
|
|
72
|
+
} else {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const r = Number.parseInt(normalized.slice(0, 2), 16);
|
|
76
|
+
const g = Number.parseInt(normalized.slice(2, 4), 16);
|
|
77
|
+
const b = Number.parseInt(normalized.slice(4, 6), 16);
|
|
78
|
+
return formatHslTriplet(rgbToHsl(r, g, b));
|
|
79
|
+
}
|
|
80
|
+
var Input = React5.forwardRef(
|
|
81
|
+
({ className, type, ...props }, ref) => {
|
|
82
|
+
return /* @__PURE__ */ jsx(
|
|
83
|
+
"input",
|
|
84
|
+
{
|
|
85
|
+
type,
|
|
86
|
+
className: cn(
|
|
87
|
+
"flex h-[var(--control-height-md,2.5rem)] w-full rounded-md border border-input bg-background px-[var(--space-3,0.75rem)] py-[var(--space-2,0.5rem)] text-sm",
|
|
88
|
+
"transition-all duration-[var(--duration-normal,200ms)] ease-out",
|
|
89
|
+
// inset-ring gives a self-borne edge so the input field is visible on flat
|
|
90
|
+
// surfaces (token border alone is too low-contrast on bg-background=white).
|
|
91
|
+
"shadow-sm inset-ring-1 inset-ring-foreground/[0.06]",
|
|
92
|
+
"file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground",
|
|
93
|
+
"placeholder:text-muted-foreground",
|
|
94
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
95
|
+
"focus-visible:shadow-md focus-visible:border-ring/50",
|
|
96
|
+
"hover:border-ring/30 hover:shadow-md",
|
|
97
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
98
|
+
className
|
|
99
|
+
),
|
|
100
|
+
ref,
|
|
101
|
+
...props
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
Input.displayName = "Input";
|
|
107
|
+
var labelVariants = cva(
|
|
108
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
109
|
+
);
|
|
110
|
+
var Label = React5.forwardRef(
|
|
111
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(LabelPrimitive.Root, { ref, className: cn(labelVariants(), className), ...props })
|
|
112
|
+
);
|
|
113
|
+
Label.displayName = "Label";
|
|
114
|
+
var Slider = React5.forwardRef(({ className, thumbLabels, ...props }, ref) => {
|
|
115
|
+
const values = props.value ?? props.defaultValue ?? [0];
|
|
116
|
+
const rootLabel = props["aria-label"];
|
|
117
|
+
const rootLabelledBy = props["aria-labelledby"];
|
|
118
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production" && thumbLabels && thumbLabels.length !== values.length) {
|
|
119
|
+
console.warn(
|
|
120
|
+
`Slider: thumbLabels.length (${thumbLabels.length}) does not match value.length (${values.length}). Missing labels fall back to indexed names; extra labels are ignored.`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
return /* @__PURE__ */ jsxs(
|
|
124
|
+
SliderPrimitive.Root,
|
|
125
|
+
{
|
|
126
|
+
ref,
|
|
127
|
+
className: cn("relative flex w-full touch-none select-none items-center", className),
|
|
128
|
+
...props,
|
|
129
|
+
children: [
|
|
130
|
+
/* @__PURE__ */ jsx(SliderPrimitive.Track, { className: "relative h-2 w-full grow overflow-hidden rounded-full border border-foreground/[0.08] bg-secondary", children: /* @__PURE__ */ jsx(SliderPrimitive.Range, { className: "absolute h-full bg-primary" }) }),
|
|
131
|
+
values.map((_, i) => {
|
|
132
|
+
const explicit = thumbLabels?.[i];
|
|
133
|
+
const fallback = values.length === 1 ? rootLabel : rootLabel ? `${rootLabel} (${i + 1} of ${values.length})` : void 0;
|
|
134
|
+
return /* @__PURE__ */ jsx(
|
|
135
|
+
SliderPrimitive.Thumb,
|
|
136
|
+
{
|
|
137
|
+
"aria-label": explicit ?? fallback,
|
|
138
|
+
"aria-labelledby": explicit || fallback ? void 0 : rootLabelledBy,
|
|
139
|
+
className: cn(
|
|
140
|
+
"block h-5 w-5 rounded-full border-2 border-primary bg-background",
|
|
141
|
+
"transition-all duration-[var(--duration-normal,200ms)] ease-out shadow-md",
|
|
142
|
+
"hover:shadow-lg hover:scale-110",
|
|
143
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
144
|
+
"disabled:pointer-events-none disabled:opacity-50"
|
|
145
|
+
)
|
|
146
|
+
},
|
|
147
|
+
i
|
|
148
|
+
);
|
|
149
|
+
})
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
Slider.displayName = "Slider";
|
|
155
|
+
var Popover = PopoverPrimitive.Root;
|
|
156
|
+
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
157
|
+
var PopoverContent = React5.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
158
|
+
PopoverPrimitive.Content,
|
|
159
|
+
{
|
|
160
|
+
ref,
|
|
161
|
+
align,
|
|
162
|
+
sideOffset,
|
|
163
|
+
className: cn(
|
|
164
|
+
"z-50 w-72 rounded-md border border-foreground/[0.08] bg-popover p-[var(--space-4,1rem)] text-popover-foreground shadow-md outline-none",
|
|
165
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
166
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
167
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
168
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
169
|
+
className
|
|
170
|
+
),
|
|
171
|
+
...props
|
|
172
|
+
}
|
|
173
|
+
) }));
|
|
174
|
+
PopoverContent.displayName = "PopoverContent";
|
|
175
|
+
var INTEGER_EPSILON = 1e-6;
|
|
176
|
+
var looksInteger = (n) => Math.abs(n - Math.round(n)) < INTEGER_EPSILON;
|
|
177
|
+
function ColorPicker({
|
|
178
|
+
value,
|
|
179
|
+
onChange,
|
|
180
|
+
disabled,
|
|
181
|
+
"aria-label": ariaLabel = "Pick color",
|
|
182
|
+
className
|
|
183
|
+
}) {
|
|
184
|
+
const hsl = React5.useMemo(() => parseHslTriplet(value), [value]);
|
|
185
|
+
const hex = React5.useMemo(() => hslTripletToHex(value), [value]);
|
|
186
|
+
const update = React5.useCallback(
|
|
187
|
+
(patch) => {
|
|
188
|
+
onChange(formatHslTriplet({ ...hsl, ...patch }));
|
|
189
|
+
},
|
|
190
|
+
[hsl, onChange]
|
|
191
|
+
);
|
|
192
|
+
const hexInputRef = React5.useRef(null);
|
|
193
|
+
const [hexBuffer, setHexBuffer] = React5.useState(hex);
|
|
194
|
+
React5.useEffect(() => {
|
|
195
|
+
if (typeof document === "undefined" || document.activeElement !== hexInputRef.current) {
|
|
196
|
+
setHexBuffer(hex);
|
|
197
|
+
}
|
|
198
|
+
}, [hex]);
|
|
199
|
+
const handleHexChange = (e) => {
|
|
200
|
+
const next = e.target.value;
|
|
201
|
+
setHexBuffer(next);
|
|
202
|
+
const triplet = hexToHslTriplet(next);
|
|
203
|
+
if (triplet !== null) onChange(triplet);
|
|
204
|
+
};
|
|
205
|
+
const hexId = React5.useId();
|
|
206
|
+
return /* @__PURE__ */ jsxs(Popover, { children: [
|
|
207
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
208
|
+
"button",
|
|
209
|
+
{
|
|
210
|
+
type: "button",
|
|
211
|
+
disabled,
|
|
212
|
+
"aria-label": ariaLabel,
|
|
213
|
+
className: cn(
|
|
214
|
+
"inline-flex h-9 items-center gap-2 rounded-md border border-input bg-background px-3 text-sm shadow-sm",
|
|
215
|
+
"transition-all duration-[var(--duration-normal,200ms)] ease-out",
|
|
216
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
217
|
+
"hover:shadow-md disabled:pointer-events-none disabled:opacity-50",
|
|
218
|
+
className
|
|
219
|
+
),
|
|
220
|
+
children: [
|
|
221
|
+
/* @__PURE__ */ jsx(
|
|
222
|
+
"span",
|
|
223
|
+
{
|
|
224
|
+
"aria-hidden": "true",
|
|
225
|
+
className: "h-5 w-5 rounded-sm border border-border",
|
|
226
|
+
style: { backgroundColor: `hsl(${value})` }
|
|
227
|
+
}
|
|
228
|
+
),
|
|
229
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs uppercase", children: hex })
|
|
230
|
+
]
|
|
231
|
+
}
|
|
232
|
+
) }),
|
|
233
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "w-72 p-4", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
234
|
+
/* @__PURE__ */ jsx(
|
|
235
|
+
SliderRow,
|
|
236
|
+
{
|
|
237
|
+
label: "Hue",
|
|
238
|
+
suffix: "\xB0",
|
|
239
|
+
value: hsl.h,
|
|
240
|
+
max: 360,
|
|
241
|
+
step: 1,
|
|
242
|
+
onChange: (h) => update({ h })
|
|
243
|
+
}
|
|
244
|
+
),
|
|
245
|
+
/* @__PURE__ */ jsx(
|
|
246
|
+
SliderRow,
|
|
247
|
+
{
|
|
248
|
+
label: "Saturation",
|
|
249
|
+
suffix: "%",
|
|
250
|
+
value: hsl.s,
|
|
251
|
+
max: 100,
|
|
252
|
+
step: 0.1,
|
|
253
|
+
onChange: (s) => update({ s })
|
|
254
|
+
}
|
|
255
|
+
),
|
|
256
|
+
/* @__PURE__ */ jsx(
|
|
257
|
+
SliderRow,
|
|
258
|
+
{
|
|
259
|
+
label: "Lightness",
|
|
260
|
+
suffix: "%",
|
|
261
|
+
value: hsl.l,
|
|
262
|
+
max: 100,
|
|
263
|
+
step: 0.1,
|
|
264
|
+
onChange: (l) => update({ l })
|
|
265
|
+
}
|
|
266
|
+
),
|
|
267
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-2", children: [
|
|
268
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1", children: [
|
|
269
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: hexId, className: "text-xs", children: "Hex" }),
|
|
270
|
+
/* @__PURE__ */ jsx(
|
|
271
|
+
Input,
|
|
272
|
+
{
|
|
273
|
+
id: hexId,
|
|
274
|
+
ref: hexInputRef,
|
|
275
|
+
value: hexBuffer,
|
|
276
|
+
onChange: handleHexChange,
|
|
277
|
+
className: "font-mono text-xs uppercase",
|
|
278
|
+
spellCheck: false,
|
|
279
|
+
autoComplete: "off"
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
] }),
|
|
283
|
+
/* @__PURE__ */ jsx(
|
|
284
|
+
"span",
|
|
285
|
+
{
|
|
286
|
+
"aria-hidden": "true",
|
|
287
|
+
className: "h-9 w-9 shrink-0 rounded-md border border-border",
|
|
288
|
+
style: { backgroundColor: `hsl(${value})` }
|
|
289
|
+
}
|
|
290
|
+
)
|
|
291
|
+
] })
|
|
292
|
+
] }) })
|
|
293
|
+
] });
|
|
294
|
+
}
|
|
295
|
+
function SliderRow({ label, suffix, value, max, step, onChange }) {
|
|
296
|
+
const display = looksInteger(value) ? `${Math.round(value)}` : value.toFixed(1);
|
|
297
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
298
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
299
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs", children: label }),
|
|
300
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono text-xs tabular-nums text-muted-foreground", children: [
|
|
301
|
+
display,
|
|
302
|
+
suffix
|
|
303
|
+
] })
|
|
304
|
+
] }),
|
|
305
|
+
/* @__PURE__ */ jsx(
|
|
306
|
+
Slider,
|
|
307
|
+
{
|
|
308
|
+
value: [value],
|
|
309
|
+
min: 0,
|
|
310
|
+
max,
|
|
311
|
+
step,
|
|
312
|
+
"aria-label": label,
|
|
313
|
+
onValueChange: (values) => onChange(values[0] ?? 0)
|
|
314
|
+
}
|
|
315
|
+
)
|
|
316
|
+
] });
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export { ColorPicker };
|
|
320
|
+
//# sourceMappingURL=color-picker.js.map
|
|
321
|
+
//# sourceMappingURL=color-picker.js.map
|