@jbpark/ui-kit 3.3.0 → 3.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.
Files changed (68) hide show
  1. package/dist/Button.d.mts +12 -0
  2. package/dist/Button.d.mts.map +1 -1
  3. package/dist/Button.mjs +5 -2
  4. package/dist/Button.mjs.map +1 -1
  5. package/dist/components/atoms/checkbox/checkbox.d.mts +7 -3
  6. package/dist/components/atoms/checkbox/checkbox.d.mts.map +1 -1
  7. package/dist/components/atoms/checkbox/checkbox.mjs +17 -9
  8. package/dist/components/atoms/checkbox/checkbox.mjs.map +1 -1
  9. package/dist/components/atoms/checkbox/group.d.mts +8 -9
  10. package/dist/components/atoms/checkbox/group.d.mts.map +1 -1
  11. package/dist/components/atoms/checkbox/group.mjs +11 -12
  12. package/dist/components/atoms/checkbox/group.mjs.map +1 -1
  13. package/dist/components/atoms/color-picker.d.mts +6 -2
  14. package/dist/components/atoms/color-picker.d.mts.map +1 -1
  15. package/dist/components/atoms/color-picker.mjs +18 -10
  16. package/dist/components/atoms/color-picker.mjs.map +1 -1
  17. package/dist/components/atoms/date-picker.d.mts +2 -0
  18. package/dist/components/atoms/date-picker.d.mts.map +1 -1
  19. package/dist/components/atoms/date-picker.mjs +15 -9
  20. package/dist/components/atoms/date-picker.mjs.map +1 -1
  21. package/dist/components/atoms/float-button/back-top.d.mts +1 -0
  22. package/dist/components/atoms/float-button/back-top.d.mts.map +1 -1
  23. package/dist/components/atoms/float-button/back-top.mjs +11 -3
  24. package/dist/components/atoms/float-button/back-top.mjs.map +1 -1
  25. package/dist/components/atoms/input/input.d.mts +2 -1
  26. package/dist/components/atoms/input/input.d.mts.map +1 -1
  27. package/dist/components/atoms/input/input.mjs +5 -2
  28. package/dist/components/atoms/input/input.mjs.map +1 -1
  29. package/dist/components/atoms/input/search.d.mts +2 -0
  30. package/dist/components/atoms/input/search.d.mts.map +1 -1
  31. package/dist/components/atoms/input/search.mjs +9 -4
  32. package/dist/components/atoms/input/search.mjs.map +1 -1
  33. package/dist/components/atoms/option-group.d.mts +15 -0
  34. package/dist/components/atoms/option-group.d.mts.map +1 -0
  35. package/dist/components/atoms/option-group.mjs +9 -0
  36. package/dist/components/atoms/option-group.mjs.map +1 -0
  37. package/dist/components/atoms/popover.d.mts +6 -0
  38. package/dist/components/atoms/popover.d.mts.map +1 -1
  39. package/dist/components/atoms/popover.mjs +75 -160
  40. package/dist/components/atoms/popover.mjs.map +1 -1
  41. package/dist/components/atoms/radio/group.d.mts +6 -9
  42. package/dist/components/atoms/radio/group.d.mts.map +1 -1
  43. package/dist/components/atoms/radio/group.mjs +26 -23
  44. package/dist/components/atoms/radio/group.mjs.map +1 -1
  45. package/dist/components/atoms/radio/radio.d.mts +7 -3
  46. package/dist/components/atoms/radio/radio.d.mts.map +1 -1
  47. package/dist/components/atoms/radio/radio.mjs +18 -11
  48. package/dist/components/atoms/radio/radio.mjs.map +1 -1
  49. package/dist/components/atoms/select.d.mts +1 -1
  50. package/dist/components/atoms/select.d.mts.map +1 -1
  51. package/dist/components/atoms/select.mjs.map +1 -1
  52. package/dist/components/atoms/skeleton/button.mjs +2 -2
  53. package/dist/components/atoms/skeleton/button.mjs.map +1 -1
  54. package/dist/components/atoms/skeleton/skeleton.mjs +2 -2
  55. package/dist/components/atoms/skeleton/skeleton.mjs.map +1 -1
  56. package/dist/components/atoms/spin.d.mts +1 -2
  57. package/dist/components/atoms/spin.d.mts.map +1 -1
  58. package/dist/components/atoms/spin.mjs +12 -10
  59. package/dist/components/atoms/spin.mjs.map +1 -1
  60. package/dist/components/atoms/switch.d.mts.map +1 -1
  61. package/dist/components/atoms/switch.mjs +6 -8
  62. package/dist/components/atoms/switch.mjs.map +1 -1
  63. package/dist/core/radio-group.d.mts +5 -1
  64. package/dist/core/radio-group.d.mts.map +1 -1
  65. package/dist/core/radio-group.mjs +7 -1
  66. package/dist/core/radio-group.mjs.map +1 -1
  67. package/dist/style.css +8 -123
  68. package/package.json +2 -2
package/dist/Button.d.mts CHANGED
@@ -11,8 +11,19 @@ interface Props extends Omit<ButtonProps, 'size' | 'variant' | 'type'> {
11
11
  danger?: boolean;
12
12
  disabled?: boolean;
13
13
  size?: 'small' | 'middle' | 'large';
14
+ /**
15
+ * antd-style visual preset. Maps to a `variant` internally — passing
16
+ * both `type` and `variant` lets `variant` win, so it can override the
17
+ * preset for one-off cases without needing every value duplicated here.
18
+ */
14
19
  type?: 'primary' | 'default' | 'dashed' | 'text' | 'link';
15
20
  variant?: 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link';
21
+ /**
22
+ * Native `<button>` `type` (`button`/`submit`/`reset`), kept separate
23
+ * from the antd-style `type` above. Defaults to `'button'` so a Button
24
+ * placed inside a `<form>` doesn't submit it unless explicitly opted in.
25
+ */
26
+ htmlType?: 'button' | 'submit' | 'reset';
16
27
  shape?: 'default' | 'circle' | 'round';
17
28
  color?: PresetColors | 'default' | 'primary' | 'danger';
18
29
  loading?: boolean | {
@@ -24,6 +35,7 @@ declare const Button: ({
24
35
  className,
25
36
  type,
26
37
  variant,
38
+ htmlType,
27
39
  size,
28
40
  color,
29
41
  shape,
@@ -1 +1 @@
1
- {"version":3,"file":"Button.d.mts","names":[],"sources":["../src/components/atoms/button.tsx"],"mappings":";;;;;KAQK,WAAA,GAAc,OAAA;AAAA,KAEd,YAAA;AAAA,UAeY,KAAA,SAAc,IAAA,CAAK,WAAA;EAClC,IAAA,GAAO,KAAA,CAAM,SAAA;EACb,KAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;EACA,IAAA;EACA,OAAA;EACA,KAAA;EACA,KAAA,GAAQ,YAAA;EACR,OAAA;IAAsB,IAAA,EAAM,KAAA,CAAM,SAAA;EAAA;AAAA;AAAA,cAkD9B,MAAA;EAAU,IAAA;EAAA,SAAA;EAAA,IAAA;EAAA,OAAA;EAAA,IAAA;EAAA,KAAA;EAAA,KAAA;EAAA,KAAA;EAAA,QAAA;EAAA,OAAA;EAAA,MAAA;EAAA,QAAA;EAAA,WAAA;EAAA,GAAA;AAAA,GAeb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"Button.d.mts","names":[],"sources":["../src/components/atoms/button.tsx"],"mappings":";;;;;KAQK,WAAA,GAAc,OAAA;AAAA,KAEd,YAAA;AAAA,UAeY,KAAA,SAAc,IAAA,CAAK,WAAA;EAClC,IAAA,GAAO,KAAA,CAAM,SAAA;EACb,KAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;EAtB6B;AAAA;;;;EA4B7B,IAAA;EACA,OAAA;EAZqB;;;;;EAkBrB,QAAA;EACA,KAAA;EACA,KAAA,GAAQ,YAAA;EACR,OAAA;IAAsB,IAAA,EAAM,KAAA,CAAM,SAAA;EAAA;AAAA;AAAA,cAkD9B,MAAA;EAAU,IAAA;EAAA,SAAA;EAAA,IAAA;EAAA,OAAA;EAAA,QAAA;EAAA,IAAA;EAAA,KAAA;EAAA,KAAA;EAAA,KAAA;EAAA,QAAA;EAAA,OAAA;EAAA,MAAA;EAAA,QAAA;EAAA,WAAA;EAAA,GAAA;AAAA,GAgBb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
package/dist/Button.mjs CHANGED
@@ -37,14 +37,17 @@ const shapesClasses = {
37
37
  circle: "rounded-full",
38
38
  round: "rounded-2xl"
39
39
  };
40
- const Button = ({ icon, className, type = "default", variant, size = "middle", color = "default", shape = "default", block = false, disabled, loading, danger, children, onMouseDown, ...props }) => {
40
+ const Button = ({ icon, className, type = "default", variant, htmlType = "button", size = "middle", color = "default", shape = "default", block = false, disabled, loading, danger, children, onMouseDown, ...props }) => {
41
41
  const iconOnly = icon && !children;
42
42
  const computedColor = danger ? "danger" : color;
43
43
  const colored = computedColor && computedColor !== "default";
44
44
  const resolvedVariant = variant ?? typeToVariant[type] ?? "solid";
45
+ const isLoading = !!loading;
45
46
  const displayIcon = loading ? typeof loading === "object" ? loading.icon : /* @__PURE__ */ jsx(LoaderCircle, { className: "animate-spin" }) : icon;
46
47
  return /* @__PURE__ */ jsxs(Core, {
47
- disabled,
48
+ type: htmlType,
49
+ disabled: disabled || isLoading,
50
+ "aria-busy": isLoading,
48
51
  variant: "default",
49
52
  "data-color": computedColor,
50
53
  className: cn("inline-flex items-center justify-center gap-x-2", "rounded-lg", "cursor-pointer", "h-auto py-0", "transition-all", variantClasses[resolvedVariant], sizesClasses[size], iconOnly && ["p-0", iconClasses[size]], shapesClasses[shape || "default"], block && "w-full", colored && (resolvedVariant === "solid" ? [
@@ -1 +1 @@
1
- {"version":3,"file":"Button.mjs","names":["button.Button"],"sources":["../src/components/atoms/button.tsx"],"sourcesContent":["'use client';\n\nimport { LoaderCircle } from 'lucide-react';\n\nimport { button } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nconst Core = button.Button;\ntype ButtonProps = button.Props;\n\ntype PresetColors =\n | 'blue'\n | 'purple'\n | 'cyan'\n | 'green'\n | 'magenta'\n | 'pink'\n | 'red'\n | 'orange'\n | 'yellow'\n | 'volcano'\n | 'geekblue'\n | 'lime'\n | 'gold';\n\nexport interface Props extends Omit<ButtonProps, 'size' | 'variant' | 'type'> {\n icon?: React.ReactNode;\n block?: boolean;\n danger?: boolean;\n disabled?: boolean;\n size?: 'small' | 'middle' | 'large';\n type?: 'primary' | 'default' | 'dashed' | 'text' | 'link';\n variant?: 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link';\n shape?: 'default' | 'circle' | 'round';\n color?: PresetColors | 'default' | 'primary' | 'danger';\n loading?: boolean | { icon: React.ReactNode };\n}\n\nconst variantClasses: Record<string, string> = {\n solid: '',\n outlined: cn(\n 'border border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n 'bg-background text-foreground',\n 'hover:bg-accent',\n ),\n dashed: cn(\n 'border border-dashed border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n 'bg-background text-foreground',\n 'hover:bg-accent',\n ),\n filled: cn('bg-muted text-foreground', 'hover:bg-muted/80'),\n text: cn('bg-transparent text-foreground', 'hover:bg-accent'),\n link: cn(\n 'bg-transparent text-primary',\n 'underline-offset-4 hover:underline',\n 'hover:bg-primary/10',\n ),\n};\n\nconst typeToVariant: Record<string, string> = {\n primary: 'solid',\n default: 'outlined',\n dashed: 'dashed',\n text: 'text',\n link: 'link',\n};\n\nconst sizesClasses: Record<string, string> = {\n small: 'h-6 px-3 text-sm',\n middle: 'h-8 px-4 text-base',\n large: 'h-10 px-5 text-lg',\n};\n\nconst iconClasses: Record<string, string> = {\n small: `size-6 [&_svg:not([class*='size-'])]:size-3`,\n middle: `size-8 [&_svg:not([class*='size-'])]:size-4`,\n large: `size-10 [&_svg:not([class*='size-'])]:size-5`,\n};\n\nconst shapesClasses = {\n default: 'rounded-sm',\n circle: 'rounded-full',\n round: 'rounded-2xl',\n};\n\nconst Button = ({\n icon,\n className,\n type = 'default',\n variant,\n size = 'middle',\n color = 'default',\n shape = 'default',\n block = false,\n disabled,\n loading,\n danger,\n children,\n onMouseDown,\n ...props\n}: Props) => {\n const iconOnly = icon && !children;\n const computedColor = danger ? 'danger' : color;\n const colored = computedColor && computedColor !== 'default';\n const resolvedVariant = variant ?? typeToVariant[type] ?? 'solid';\n\n const displayIcon = loading ? (\n typeof loading === 'object' ? (\n loading.icon\n ) : (\n <LoaderCircle className=\"animate-spin\" />\n )\n ) : (\n icon\n );\n\n return (\n <Core\n disabled={disabled}\n variant=\"default\"\n data-color={computedColor}\n className={cn(\n 'inline-flex items-center justify-center gap-x-2',\n 'rounded-lg',\n 'cursor-pointer',\n 'h-auto py-0',\n 'transition-all',\n variantClasses[resolvedVariant],\n sizesClasses[size],\n iconOnly && ['p-0', iconClasses[size]],\n shapesClasses[shape || 'default'],\n block && 'w-full',\n colored &&\n (resolvedVariant === 'solid'\n ? [\n 'bg-(--btn-bg)',\n 'hover:bg-(--btn-bg-hover)',\n 'active:bg-(--btn-bg-active)',\n 'text-(--btn-fg)',\n 'border-(--btn-border)',\n ]\n : [\n 'text-(--btn-bg)',\n 'border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n //\n ]),\n className,\n //\n )}\n onMouseDown={e => {\n onMouseDown?.(e);\n }}\n {...props}\n >\n {displayIcon}\n {children}\n </Core>\n );\n};\n\nexport default Button;\n"],"mappings":";;;;;;;;AAOA,MAAM,OAAOA;AA+Bb,MAAM,iBAAyC;CAC7C,OAAO;CACP,UAAU,GACR,yEACA,iCACA,kBACD;CACD,QAAQ,GACN,uFACA,iCACA,kBACD;CACD,QAAQ,GAAG,4BAA4B,oBAAoB;CAC3D,MAAM,GAAG,kCAAkC,kBAAkB;CAC7D,MAAM,GACJ,+BACA,sCACA,sBACD;CACF;AAED,MAAM,gBAAwC;CAC5C,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;CACN,MAAM;CACP;AAED,MAAM,eAAuC;CAC3C,OAAO;CACP,QAAQ;CACR,OAAO;CACR;AAED,MAAM,cAAsC;CAC1C,OAAO;CACP,QAAQ;CACR,OAAO;CACR;AAED,MAAM,gBAAgB;CACpB,SAAS;CACT,QAAQ;CACR,OAAO;CACR;AAED,MAAM,UAAU,EACd,MACA,WACA,OAAO,WACP,SACA,OAAO,UACP,QAAQ,WACR,QAAQ,WACR,QAAQ,OACR,UACA,SACA,QACA,UACA,aACA,GAAG,YACQ;CACX,MAAM,WAAW,QAAQ,CAAC;CAC1B,MAAM,gBAAgB,SAAS,WAAW;CAC1C,MAAM,UAAU,iBAAiB,kBAAkB;CACnD,MAAM,kBAAkB,WAAW,cAAc,SAAS;CAE1D,MAAM,cAAc,UAClB,OAAO,YAAY,WACjB,QAAQ,OAER,oBAAC,gBAAa,WAAU,iBAAiB,GAG3C;AAGF,QACE,qBAAC;EACW;EACV,SAAQ;EACR,cAAY;EACZ,WAAW,GACT,mDACA,cACA,kBACA,eACA,kBACA,eAAe,kBACf,aAAa,OACb,YAAY,CAAC,OAAO,YAAY,MAAM,EACtC,cAAc,SAAS,YACvB,SAAS,UACT,YACG,oBAAoB,UACjB;GACE;GACA;GACA;GACA;GACA;GACD,GACD,CACE,mBACA,iEAED,GACP,UAED;EACD,cAAa,MAAK;AAChB,iBAAc,EAAE;;EAElB,GAAI;aAEH,aACA;GACI"}
1
+ {"version":3,"file":"Button.mjs","names":["button.Button"],"sources":["../src/components/atoms/button.tsx"],"sourcesContent":["'use client';\n\nimport { LoaderCircle } from 'lucide-react';\n\nimport { button } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nconst Core = button.Button;\ntype ButtonProps = button.Props;\n\ntype PresetColors =\n | 'blue'\n | 'purple'\n | 'cyan'\n | 'green'\n | 'magenta'\n | 'pink'\n | 'red'\n | 'orange'\n | 'yellow'\n | 'volcano'\n | 'geekblue'\n | 'lime'\n | 'gold';\n\nexport interface Props extends Omit<ButtonProps, 'size' | 'variant' | 'type'> {\n icon?: React.ReactNode;\n block?: boolean;\n danger?: boolean;\n disabled?: boolean;\n size?: 'small' | 'middle' | 'large';\n /**\n * antd-style visual preset. Maps to a `variant` internally — passing\n * both `type` and `variant` lets `variant` win, so it can override the\n * preset for one-off cases without needing every value duplicated here.\n */\n type?: 'primary' | 'default' | 'dashed' | 'text' | 'link';\n variant?: 'solid' | 'outlined' | 'dashed' | 'filled' | 'text' | 'link';\n /**\n * Native `<button>` `type` (`button`/`submit`/`reset`), kept separate\n * from the antd-style `type` above. Defaults to `'button'` so a Button\n * placed inside a `<form>` doesn't submit it unless explicitly opted in.\n */\n htmlType?: 'button' | 'submit' | 'reset';\n shape?: 'default' | 'circle' | 'round';\n color?: PresetColors | 'default' | 'primary' | 'danger';\n loading?: boolean | { icon: React.ReactNode };\n}\n\nconst variantClasses: Record<string, string> = {\n solid: '',\n outlined: cn(\n 'border border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n 'bg-background text-foreground',\n 'hover:bg-accent',\n ),\n dashed: cn(\n 'border border-dashed border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n 'bg-background text-foreground',\n 'hover:bg-accent',\n ),\n filled: cn('bg-muted text-foreground', 'hover:bg-muted/80'),\n text: cn('bg-transparent text-foreground', 'hover:bg-accent'),\n link: cn(\n 'bg-transparent text-primary',\n 'underline-offset-4 hover:underline',\n 'hover:bg-primary/10',\n ),\n};\n\nconst typeToVariant: Record<string, string> = {\n primary: 'solid',\n default: 'outlined',\n dashed: 'dashed',\n text: 'text',\n link: 'link',\n};\n\nconst sizesClasses: Record<string, string> = {\n small: 'h-6 px-3 text-sm',\n middle: 'h-8 px-4 text-base',\n large: 'h-10 px-5 text-lg',\n};\n\nconst iconClasses: Record<string, string> = {\n small: `size-6 [&_svg:not([class*='size-'])]:size-3`,\n middle: `size-8 [&_svg:not([class*='size-'])]:size-4`,\n large: `size-10 [&_svg:not([class*='size-'])]:size-5`,\n};\n\nconst shapesClasses = {\n default: 'rounded-sm',\n circle: 'rounded-full',\n round: 'rounded-2xl',\n};\n\nconst Button = ({\n icon,\n className,\n type = 'default',\n variant,\n htmlType = 'button',\n size = 'middle',\n color = 'default',\n shape = 'default',\n block = false,\n disabled,\n loading,\n danger,\n children,\n onMouseDown,\n ...props\n}: Props) => {\n const iconOnly = icon && !children;\n const computedColor = danger ? 'danger' : color;\n const colored = computedColor && computedColor !== 'default';\n const resolvedVariant = variant ?? typeToVariant[type] ?? 'solid';\n const isLoading = !!loading;\n\n const displayIcon = loading ? (\n typeof loading === 'object' ? (\n loading.icon\n ) : (\n <LoaderCircle className=\"animate-spin\" />\n )\n ) : (\n icon\n );\n\n return (\n <Core\n type={htmlType}\n disabled={disabled || isLoading}\n aria-busy={isLoading}\n variant=\"default\"\n data-color={computedColor}\n className={cn(\n 'inline-flex items-center justify-center gap-x-2',\n 'rounded-lg',\n 'cursor-pointer',\n 'h-auto py-0',\n 'transition-all',\n variantClasses[resolvedVariant],\n sizesClasses[size],\n iconOnly && ['p-0', iconClasses[size]],\n shapesClasses[shape || 'default'],\n block && 'w-full',\n colored &&\n (resolvedVariant === 'solid'\n ? [\n 'bg-(--btn-bg)',\n 'hover:bg-(--btn-bg-hover)',\n 'active:bg-(--btn-bg-active)',\n 'text-(--btn-fg)',\n 'border-(--btn-border)',\n ]\n : [\n 'text-(--btn-bg)',\n 'border-[color-mix(in_oklch,var(--btn-border),transparent_50%)]',\n //\n ]),\n className,\n //\n )}\n onMouseDown={e => {\n onMouseDown?.(e);\n }}\n {...props}\n >\n {displayIcon}\n {children}\n </Core>\n );\n};\n\nexport default Button;\n"],"mappings":";;;;;;;;AAOA,MAAM,OAAOA;AA0Cb,MAAM,iBAAyC;CAC7C,OAAO;CACP,UAAU,GACR,yEACA,iCACA,kBACD;CACD,QAAQ,GACN,uFACA,iCACA,kBACD;CACD,QAAQ,GAAG,4BAA4B,oBAAoB;CAC3D,MAAM,GAAG,kCAAkC,kBAAkB;CAC7D,MAAM,GACJ,+BACA,sCACA,sBACD;CACF;AAED,MAAM,gBAAwC;CAC5C,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;CACN,MAAM;CACP;AAED,MAAM,eAAuC;CAC3C,OAAO;CACP,QAAQ;CACR,OAAO;CACR;AAED,MAAM,cAAsC;CAC1C,OAAO;CACP,QAAQ;CACR,OAAO;CACR;AAED,MAAM,gBAAgB;CACpB,SAAS;CACT,QAAQ;CACR,OAAO;CACR;AAED,MAAM,UAAU,EACd,MACA,WACA,OAAO,WACP,SACA,WAAW,UACX,OAAO,UACP,QAAQ,WACR,QAAQ,WACR,QAAQ,OACR,UACA,SACA,QACA,UACA,aACA,GAAG,YACQ;CACX,MAAM,WAAW,QAAQ,CAAC;CAC1B,MAAM,gBAAgB,SAAS,WAAW;CAC1C,MAAM,UAAU,iBAAiB,kBAAkB;CACnD,MAAM,kBAAkB,WAAW,cAAc,SAAS;CAC1D,MAAM,YAAY,CAAC,CAAC;CAEpB,MAAM,cAAc,UAClB,OAAO,YAAY,WACjB,QAAQ,OAER,oBAAC,gBAAa,WAAU,iBAAiB,GAG3C;AAGF,QACE,qBAAC;EACC,MAAM;EACN,UAAU,YAAY;EACtB,aAAW;EACX,SAAQ;EACR,cAAY;EACZ,WAAW,GACT,mDACA,cACA,kBACA,eACA,kBACA,eAAe,kBACf,aAAa,OACb,YAAY,CAAC,OAAO,YAAY,MAAM,EACtC,cAAc,SAAS,YACvB,SAAS,UACT,YACG,oBAAoB,UACjB;GACE;GACA;GACA;GACA;GACA;GACD,GACD,CACE,mBACA,iEAED,GACP,UAED;EACD,cAAa,MAAK;AAChB,iBAAc,EAAE;;EAElB,GAAI;aAEH,aACA;GACI"}
@@ -1,4 +1,5 @@
1
- import { OptionValue } from "./group.mjs";
1
+ import { OptionValue } from "../option-group.mjs";
2
+ import "./group.mjs";
2
3
  import * as react_jsx_runtime0 from "react/jsx-runtime";
3
4
 
4
5
  //#region src/components/atoms/checkbox/checkbox.d.ts
@@ -7,11 +8,13 @@ interface Props extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onChange'>
7
8
  defaultChecked?: boolean;
8
9
  checked?: boolean;
9
10
  value?: OptionValue;
11
+ /** Native form field name — participates in `FormData` when set. */
12
+ name?: string;
10
13
  disabled?: boolean;
11
- icons?: {
14
+ icons?: Partial<{
12
15
  checked: React.ReactNode;
13
16
  unchecked: React.ReactNode;
14
- };
17
+ }>;
15
18
  children?: React.ReactNode;
16
19
  onChange?: (checked: boolean) => void;
17
20
  }
@@ -24,6 +27,7 @@ declare const Checkbox: ({
24
27
  disabled,
25
28
  defaultChecked,
26
29
  checked: _checked,
30
+ name,
27
31
  onChange: _onChange,
28
32
  ...props
29
33
  }: Props) => react_jsx_runtime0.JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.d.mts","names":[],"sources":["../../../../src/components/atoms/checkbox/checkbox.tsx"],"mappings":";;;;UAciB,KAAA,SAAc,IAAA,CAC7B,KAAA,CAAM,wBAAA;EAGN,SAAA;EACA,cAAA;EACA,OAAA;EACA,KAAA,GAAQ,WAAA;EACR,QAAA;EACA,KAAA;IAAU,OAAA,EAAS,KAAA,CAAM,SAAA;IAAW,SAAA,EAAW,KAAA,CAAM,SAAA;EAAA;EACrD,QAAA,GAAW,KAAA,CAAM,SAAA;EACjB,QAAA,IAAY,OAAA;AAAA;AAAA,cAGR,QAAA;EAAY,SAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA;EAAA,SAAA;EAAA,KAAA;EAAA,QAAA;EAAA,cAAA;EAAA,OAAA,EAAA,QAAA;EAAA,QAAA,EAAA,SAAA;EAAA,GAAA;AAAA,GAWf,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"checkbox.d.mts","names":[],"sources":["../../../../src/components/atoms/checkbox/checkbox.tsx"],"mappings":";;;;;UAeiB,KAAA,SAAc,IAAA,CAC7B,KAAA,CAAM,wBAAA;EAGN,SAAA;EACA,cAAA;EACA,OAAA;EACA,KAAA,GAAQ,WAAA;EAPa;EASrB,IAAA;EACA,QAAA;EACA,KAAA,GAAQ,OAAA;IAAU,OAAA,EAAS,KAAA,CAAM,SAAA;IAAW,SAAA,EAAW,KAAA,CAAM,SAAA;EAAA;EAC7D,QAAA,GAAW,KAAA,CAAM,SAAA;EACjB,QAAA,IAAY,OAAA;AAAA;AAAA,cAGR,QAAA;EAAY,SAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA;EAAA,SAAA;EAAA,KAAA;EAAA,QAAA;EAAA,cAAA;EAAA,OAAA,EAAA,QAAA;EAAA,IAAA;EAAA,QAAA,EAAA,SAAA;EAAA,GAAA;AAAA,GAYf,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -4,29 +4,35 @@ import { cn } from "../../../utils.mjs";
4
4
  import { checkbox_exports } from "../../../core/checkbox.mjs";
5
5
  import { label_exports } from "../../../core/label.mjs";
6
6
  import { Square, SquareCheck } from "lucide-react";
7
- import { useId, useState } from "react";
7
+ import { useId } from "react";
8
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
+ import { useControllableState } from "@jbpark/use-hooks";
9
10
 
10
11
  //#region src/components/atoms/checkbox/checkbox.tsx
11
12
  const { Checkbox: CoreCheckbox } = checkbox_exports;
12
13
  const { Label: CoreLabel } = label_exports;
13
- const Checkbox = ({ placement = "left", value: _value = "", children, className, icons, disabled, defaultChecked, checked: _checked, onChange: _onChange = () => {}, ...props }) => {
14
- const [uncontrolledChecked, setUncontrolledChecked] = useState(defaultChecked || false);
14
+ const Checkbox = ({ placement = "left", value: _value = "", children, className, icons, disabled, defaultChecked, checked: _checked, name, onChange: _onChange = () => {}, ...props }) => {
15
+ const [checked, setChecked] = useControllableState({
16
+ value: _checked,
17
+ defaultValue: defaultChecked ?? false,
18
+ onChange: _onChange
19
+ });
15
20
  const id = useId();
16
- const controlled = _checked !== void 0;
17
- const checked = controlled ? _checked : uncontrolledChecked;
21
+ const itemValue = String(_value);
18
22
  const cursorClassName = disabled ? "cursor-not-allowed" : "cursor-pointer";
19
23
  const onChange = (next) => {
20
24
  if (disabled) return;
21
- if (!controlled) setUncontrolledChecked(next);
22
- _onChange(next);
25
+ setChecked(next);
23
26
  };
24
27
  const renderContent = icons ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
25
28
  /* @__PURE__ */ jsx("input", {
26
29
  id,
27
30
  hidden: true,
28
31
  type: "checkbox",
32
+ name,
33
+ value: itemValue,
29
34
  checked,
35
+ disabled,
30
36
  onChange: (e) => {
31
37
  onChange(e.target.checked);
32
38
  }
@@ -38,12 +44,12 @@ const Checkbox = ({ placement = "left", value: _value = "", children, className,
38
44
  tabIndex: disabled ? -1 : 0,
39
45
  className: cn(cursorClassName, disabled && "opacity-50"),
40
46
  onClick: () => {
41
- document.getElementById(id)?.click();
47
+ onChange(!checked);
42
48
  },
43
49
  onKeyDown: (e) => {
44
50
  if (e.key === "Enter" || e.key === " ") {
45
51
  e.preventDefault();
46
- document.getElementById(id)?.click();
52
+ onChange(!checked);
47
53
  }
48
54
  },
49
55
  children: checked ? icons.checked ?? /* @__PURE__ */ jsx(SquareCheck, {}) : icons.unchecked ?? /* @__PURE__ */ jsx(Square, {})
@@ -55,6 +61,8 @@ const Checkbox = ({ placement = "left", value: _value = "", children, className,
55
61
  })
56
62
  ] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(CoreCheckbox, {
57
63
  id,
64
+ name,
65
+ value: itemValue,
58
66
  checked,
59
67
  disabled,
60
68
  className: cn(cursorClassName),
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.mjs","names":["checkbox","label"],"sources":["../../../../src/components/atoms/checkbox/checkbox.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useState } from 'react';\n\nimport { Square, SquareCheck } from 'lucide-react';\n\nimport { checkbox, label } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nimport { type OptionValue } from './group';\n\nconst { Checkbox: CoreCheckbox } = checkbox;\nconst { Label: CoreLabel } = label;\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'onChange'\n> {\n placement?: 'left' | 'right';\n defaultChecked?: boolean;\n checked?: boolean;\n value?: OptionValue;\n disabled?: boolean;\n icons?: { checked: React.ReactNode; unchecked: React.ReactNode };\n children?: React.ReactNode;\n onChange?: (checked: boolean) => void;\n}\n\nconst Checkbox = ({\n placement = 'left',\n value: _value = '',\n children,\n className,\n icons,\n disabled,\n defaultChecked,\n checked: _checked,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [uncontrolledChecked, setUncontrolledChecked] = useState<boolean>(\n defaultChecked || false,\n );\n\n const id = useId();\n const controlled = _checked !== undefined;\n const checked = controlled ? _checked : uncontrolledChecked;\n\n const cursorClassName = disabled ? 'cursor-not-allowed' : 'cursor-pointer';\n\n const onChange = (next: boolean) => {\n if (disabled) {\n return;\n }\n\n if (!controlled) {\n setUncontrolledChecked(next);\n }\n _onChange(next);\n };\n\n const renderContent = icons ? (\n <>\n <input\n id={id}\n hidden\n type=\"checkbox\"\n checked={checked}\n onChange={e => {\n onChange(e.target.checked);\n }}\n />\n <span\n role=\"checkbox\"\n aria-checked={checked}\n aria-disabled={disabled}\n tabIndex={disabled ? -1 : 0}\n className={cn(cursorClassName, disabled && 'opacity-50')}\n onClick={() => {\n document.getElementById(id)?.click();\n }}\n onKeyDown={e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n document.getElementById(id)?.click();\n }\n }}\n >\n {checked\n ? (icons.checked ?? <SquareCheck />)\n : (icons.unchecked ?? <Square />)}\n </span>\n {children && (\n <label\n className={cn(cursorClassName, disabled && 'opacity-50')}\n htmlFor={id}\n >\n {children}\n </label>\n )}\n </>\n ) : (\n <>\n <CoreCheckbox\n id={id}\n checked={checked}\n disabled={disabled}\n className={cn(cursorClassName)}\n onCheckedChange={onChange}\n />\n {children && (\n <CoreLabel htmlFor={id} className={cn(cursorClassName, 'text-left')}>\n {children}\n </CoreLabel>\n )}\n </>\n );\n\n return (\n <div\n className={cn(\n 'flex items-center gap-x-2',\n placement === 'right' && 'flex-row-reverse',\n cursorClassName,\n className,\n //\n )}\n {...props}\n >\n {renderContent}\n </div>\n );\n};\n\nexport default Checkbox;\n"],"mappings":";;;;;;;;;;AAWA,MAAM,EAAE,UAAU,iBAAiBA;AACnC,MAAM,EAAE,OAAO,cAAcC;AAgB7B,MAAM,YAAY,EAChB,YAAY,QACZ,OAAO,SAAS,IAChB,UACA,WACA,OACA,UACA,gBACA,SAAS,UACT,UAAU,kBAAkB,IAC5B,GAAG,YACQ;CACX,MAAM,CAAC,qBAAqB,0BAA0B,SACpD,kBAAkB,MACnB;CAED,MAAM,KAAK,OAAO;CAClB,MAAM,aAAa,aAAa;CAChC,MAAM,UAAU,aAAa,WAAW;CAExC,MAAM,kBAAkB,WAAW,uBAAuB;CAE1D,MAAM,YAAY,SAAkB;AAClC,MAAI,SACF;AAGF,MAAI,CAAC,WACH,wBAAuB,KAAK;AAE9B,YAAU,KAAK;;CAGjB,MAAM,gBAAgB,QACpB;EACE,oBAAC;GACK;GACJ;GACA,MAAK;GACI;GACT,WAAU,MAAK;AACb,aAAS,EAAE,OAAO,QAAQ;;IAE5B;EACF,oBAAC;GACC,MAAK;GACL,gBAAc;GACd,iBAAe;GACf,UAAU,WAAW,KAAK;GAC1B,WAAW,GAAG,iBAAiB,YAAY,aAAa;GACxD,eAAe;AACb,aAAS,eAAe,GAAG,EAAE,OAAO;;GAEtC,YAAW,MAAK;AACd,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,OAAE,gBAAgB;AAClB,cAAS,eAAe,GAAG,EAAE,OAAO;;;aAIvC,UACI,MAAM,WAAW,oBAAC,gBAAc,GAChC,MAAM,aAAa,oBAAC,WAAS;IAC7B;EACN,YACC,oBAAC;GACC,WAAW,GAAG,iBAAiB,YAAY,aAAa;GACxD,SAAS;GAER;IACK;KAET,GAEH,8CACE,oBAAC;EACK;EACK;EACC;EACV,WAAW,GAAG,gBAAgB;EAC9B,iBAAiB;GACjB,EACD,YACC,oBAAC;EAAU,SAAS;EAAI,WAAW,GAAG,iBAAiB,YAAY;EAChE;GACS,IAEb;AAGL,QACE,oBAAC;EACC,WAAW,GACT,6BACA,cAAc,WAAW,oBACzB,iBACA,UAED;EACD,GAAI;YAEH;GACG"}
1
+ {"version":3,"file":"checkbox.mjs","names":["checkbox","label"],"sources":["../../../../src/components/atoms/checkbox/checkbox.tsx"],"sourcesContent":["'use client';\n\nimport { useId } from 'react';\n\nimport { useControllableState } from '@jbpark/use-hooks';\nimport { Square, SquareCheck } from 'lucide-react';\n\nimport { checkbox, label } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nimport { type OptionValue } from './group';\n\nconst { Checkbox: CoreCheckbox } = checkbox;\nconst { Label: CoreLabel } = label;\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'onChange'\n> {\n placement?: 'left' | 'right';\n defaultChecked?: boolean;\n checked?: boolean;\n value?: OptionValue;\n /** Native form field name — participates in `FormData` when set. */\n name?: string;\n disabled?: boolean;\n icons?: Partial<{ checked: React.ReactNode; unchecked: React.ReactNode }>;\n children?: React.ReactNode;\n onChange?: (checked: boolean) => void;\n}\n\nconst Checkbox = ({\n placement = 'left',\n value: _value = '',\n children,\n className,\n icons,\n disabled,\n defaultChecked,\n checked: _checked,\n name,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [checked, setChecked] = useControllableState<boolean>({\n value: _checked,\n defaultValue: defaultChecked ?? false,\n onChange: _onChange,\n });\n\n const id = useId();\n const itemValue = String(_value);\n\n const cursorClassName = disabled ? 'cursor-not-allowed' : 'cursor-pointer';\n\n const onChange = (next: boolean) => {\n if (disabled) {\n return;\n }\n\n setChecked(next);\n };\n\n const renderContent = icons ? (\n <>\n <input\n id={id}\n hidden\n type=\"checkbox\"\n name={name}\n value={itemValue}\n checked={checked}\n disabled={disabled}\n onChange={e => {\n onChange(e.target.checked);\n }}\n />\n <span\n role=\"checkbox\"\n aria-checked={checked}\n aria-disabled={disabled}\n tabIndex={disabled ? -1 : 0}\n className={cn(cursorClassName, disabled && 'opacity-50')}\n onClick={() => {\n onChange(!checked);\n }}\n onKeyDown={e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onChange(!checked);\n }\n }}\n >\n {checked\n ? (icons.checked ?? <SquareCheck />)\n : (icons.unchecked ?? <Square />)}\n </span>\n {children && (\n <label\n className={cn(cursorClassName, disabled && 'opacity-50')}\n htmlFor={id}\n >\n {children}\n </label>\n )}\n </>\n ) : (\n <>\n <CoreCheckbox\n id={id}\n name={name}\n value={itemValue}\n checked={checked}\n disabled={disabled}\n className={cn(cursorClassName)}\n onCheckedChange={onChange}\n />\n {children && (\n <CoreLabel htmlFor={id} className={cn(cursorClassName, 'text-left')}>\n {children}\n </CoreLabel>\n )}\n </>\n );\n\n return (\n <div\n className={cn(\n 'flex items-center gap-x-2',\n placement === 'right' && 'flex-row-reverse',\n cursorClassName,\n className,\n //\n )}\n {...props}\n >\n {renderContent}\n </div>\n );\n};\n\nexport default Checkbox;\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,EAAE,UAAU,iBAAiBA;AACnC,MAAM,EAAE,OAAO,cAAcC;AAkB7B,MAAM,YAAY,EAChB,YAAY,QACZ,OAAO,SAAS,IAChB,UACA,WACA,OACA,UACA,gBACA,SAAS,UACT,MACA,UAAU,kBAAkB,IAC5B,GAAG,YACQ;CACX,MAAM,CAAC,SAAS,cAAc,qBAA8B;EAC1D,OAAO;EACP,cAAc,kBAAkB;EAChC,UAAU;EACX,CAAC;CAEF,MAAM,KAAK,OAAO;CAClB,MAAM,YAAY,OAAO,OAAO;CAEhC,MAAM,kBAAkB,WAAW,uBAAuB;CAE1D,MAAM,YAAY,SAAkB;AAClC,MAAI,SACF;AAGF,aAAW,KAAK;;CAGlB,MAAM,gBAAgB,QACpB;EACE,oBAAC;GACK;GACJ;GACA,MAAK;GACC;GACN,OAAO;GACE;GACC;GACV,WAAU,MAAK;AACb,aAAS,EAAE,OAAO,QAAQ;;IAE5B;EACF,oBAAC;GACC,MAAK;GACL,gBAAc;GACd,iBAAe;GACf,UAAU,WAAW,KAAK;GAC1B,WAAW,GAAG,iBAAiB,YAAY,aAAa;GACxD,eAAe;AACb,aAAS,CAAC,QAAQ;;GAEpB,YAAW,MAAK;AACd,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,OAAE,gBAAgB;AAClB,cAAS,CAAC,QAAQ;;;aAIrB,UACI,MAAM,WAAW,oBAAC,gBAAc,GAChC,MAAM,aAAa,oBAAC,WAAS;IAC7B;EACN,YACC,oBAAC;GACC,WAAW,GAAG,iBAAiB,YAAY,aAAa;GACxD,SAAS;GAER;IACK;KAET,GAEH,8CACE,oBAAC;EACK;EACE;EACN,OAAO;EACE;EACC;EACV,WAAW,GAAG,gBAAgB;EAC9B,iBAAiB;GACjB,EACD,YACC,oBAAC;EAAU,SAAS;EAAI,WAAW,GAAG,iBAAiB,YAAY;EAChE;GACS,IAEb;AAGL,QACE,oBAAC;EACC,WAAW,GACT,6BACA,cAAc,WAAW,oBACzB,iBACA,UAED;EACD,GAAI;YAEH;GACG"}
@@ -1,20 +1,17 @@
1
+ import { OptionGroupClassNames, OptionValue, Options } from "../option-group.mjs";
1
2
  import * as react_jsx_runtime0 from "react/jsx-runtime";
2
3
 
3
4
  //#region src/components/atoms/checkbox/group.d.ts
4
- type OptionValue = string | number | boolean;
5
- type Option = {
6
- label: string;
7
- value: OptionValue;
8
- disabled?: boolean;
9
- };
10
- type Options = string[] | number[] | boolean[] | Option[];
11
5
  interface Props extends Omit<React.ComponentPropsWithoutRef<'ul'>, 'onChange' | 'defaultValue' | 'value'> {
12
6
  options?: Options;
13
7
  orientation?: 'vertical' | 'horizontal';
14
8
  placement?: 'left' | 'right';
15
- classNames?: Record<string, string>;
9
+ classNames?: OptionGroupClassNames;
16
10
  defaultValue?: OptionValue[];
17
11
  value?: OptionValue[];
12
+ /** Native form field name, shared across every option's checkbox. */
13
+ name?: string;
14
+ disabled?: boolean;
18
15
  onChange?: (values: OptionValue[]) => void;
19
16
  }
20
17
  declare const Group: ({
@@ -23,11 +20,13 @@ declare const Group: ({
23
20
  className,
24
21
  classNames,
25
22
  options: _options,
23
+ name,
24
+ disabled,
26
25
  defaultValue,
27
26
  value: _value,
28
27
  onChange: _onChange,
29
28
  ...props
30
29
  }: Props) => react_jsx_runtime0.JSX.Element;
31
30
  //#endregion
32
- export { Group, OptionValue };
31
+ export { Group };
33
32
  //# sourceMappingURL=group.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"group.d.mts","names":[],"sources":["../../../../src/components/atoms/checkbox/group.tsx"],"mappings":";;;KAQY,WAAA;AAAA,KAEP,MAAA;EACH,KAAA;EACA,KAAA,EAAO,WAAA;EACP,QAAA;AAAA;AAAA,KAGG,OAAA,qCAA4C,MAAA;AAAA,UAEhC,KAAA,SAAc,IAAA,CAC7B,KAAA,CAAM,wBAAA;EAGN,OAAA,GAAU,OAAA;EACV,WAAA;EACA,SAAA;EACA,UAAA,GAAa,MAAA;EACb,YAAA,GAAe,WAAA;EACf,KAAA,GAAQ,WAAA;EACR,QAAA,IAAY,MAAA,EAAQ,WAAA;AAAA;AAAA,cAGhB,KAAA;EAAS,WAAA;EAAA,SAAA;EAAA,SAAA;EAAA,UAAA;EAAA,OAAA,EAAA,QAAA;EAAA,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA,EAAA,SAAA;EAAA,GAAA;AAAA,GAUZ,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"group.d.mts","names":[],"sources":["../../../../src/components/atoms/checkbox/group.tsx"],"mappings":";;;;UAiBiB,KAAA,SAAc,IAAA,CAC7B,KAAA,CAAM,wBAAA;EAGN,OAAA,GAAU,OAAA;EACV,WAAA;EACA,SAAA;EACA,UAAA,GAAa,qBAAA;EACb,YAAA,GAAe,WAAA;EACf,KAAA,GAAQ,WAAA;EAFK;EAIb,IAAA;EACA,QAAA;EACA,QAAA,IAAY,MAAA,EAAQ,WAAA;AAAA;AAAA,cAGhB,KAAA;EAAS,WAAA;EAAA,SAAA;EAAA,SAAA;EAAA,UAAA;EAAA,OAAA,EAAA,QAAA;EAAA,IAAA;EAAA,QAAA;EAAA,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA,EAAA,SAAA;EAAA,GAAA;AAAA,GAYZ,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -2,22 +2,20 @@
2
2
 
3
3
  import { cn } from "../../../utils.mjs";
4
4
  import Checkbox from "./checkbox.mjs";
5
- import { useState } from "react";
5
+ import { normalizeOptions } from "../option-group.mjs";
6
6
  import { jsx } from "react/jsx-runtime";
7
+ import { useControllableState } from "@jbpark/use-hooks";
7
8
 
8
9
  //#region src/components/atoms/checkbox/group.tsx
9
- const Group = ({ orientation = "vertical", placement = "left", className, classNames = {}, options: _options = [], defaultValue, value: _value, onChange: _onChange = () => {}, ...props }) => {
10
- const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue || []);
11
- const controlled = _value !== void 0;
12
- const value = controlled ? _value : uncontrolledValue;
13
- const options = _options.map((item) => typeof item === "object" ? item : {
14
- label: `${item}`,
15
- value: item
10
+ const Group = ({ orientation = "vertical", placement = "left", className, classNames = {}, options: _options = [], name, disabled, defaultValue, value: _value, onChange: _onChange = () => {}, ...props }) => {
11
+ const [value, setValue] = useControllableState({
12
+ value: _value,
13
+ defaultValue: defaultValue ?? [],
14
+ onChange: _onChange
16
15
  });
16
+ const options = normalizeOptions(_options);
17
17
  const onChange = (checked, optionValue) => {
18
- const nextValue = checked ? [...value, optionValue] : value.filter((v) => v !== optionValue);
19
- if (!controlled) setUncontrolledValue(nextValue);
20
- _onChange(nextValue);
18
+ setValue(checked ? [...value, optionValue] : value.filter((v) => v !== optionValue));
21
19
  };
22
20
  return /* @__PURE__ */ jsx("ul", {
23
21
  ...props,
@@ -29,9 +27,10 @@ const Group = ({ orientation = "vertical", placement = "left", className, classN
29
27
  children: /* @__PURE__ */ jsx(Checkbox, {
30
28
  placement,
31
29
  className: cn(classNames?.item),
30
+ name,
32
31
  value: item.value,
33
32
  checked,
34
- disabled: item.disabled,
33
+ disabled: disabled || item.disabled,
35
34
  onChange: (checked) => onChange(checked, item.value),
36
35
  children: item.label
37
36
  })
@@ -1 +1 @@
1
- {"version":3,"file":"group.mjs","names":[],"sources":["../../../../src/components/atoms/checkbox/group.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Checkbox from './checkbox';\n\nexport type OptionValue = string | number | boolean;\n\ntype Option = {\n label: string;\n value: OptionValue;\n disabled?: boolean;\n};\n\ntype Options = string[] | number[] | boolean[] | Option[];\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'ul'>,\n 'onChange' | 'defaultValue' | 'value'\n> {\n options?: Options;\n orientation?: 'vertical' | 'horizontal';\n placement?: 'left' | 'right';\n classNames?: Record<string, string>;\n defaultValue?: OptionValue[];\n value?: OptionValue[];\n onChange?: (values: OptionValue[]) => void;\n}\n\nconst Group = ({\n orientation = 'vertical',\n placement = 'left',\n className,\n classNames = {},\n options: _options = [],\n defaultValue,\n value: _value,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [uncontrolledValue, setUncontrolledValue] = useState<OptionValue[]>(\n defaultValue || [],\n );\n\n const controlled = _value !== undefined;\n const value = controlled ? _value : uncontrolledValue;\n\n const options: Option[] = _options.map(item =>\n typeof item === 'object'\n ? item\n : {\n label: `${item}`,\n value: item,\n },\n );\n\n const onChange = (checked: boolean, optionValue: OptionValue) => {\n const nextValue = checked\n ? [...value, optionValue]\n : value.filter(v => v !== optionValue);\n\n if (!controlled) {\n setUncontrolledValue(nextValue);\n }\n _onChange(nextValue);\n };\n\n return (\n <ul\n {...props}\n className={cn(\n orientation === 'vertical' ? 'space-y-2' : 'flex gap-2',\n className,\n )}\n >\n {options.map((item: Option) => {\n const checked = value.includes(item.value);\n\n return (\n <li\n key={String(item.value)}\n className={cn('flex', classNames?.wrapper)}\n >\n <Checkbox\n placement={placement}\n className={cn(classNames?.item)}\n value={item.value}\n checked={checked}\n disabled={item.disabled}\n onChange={checked => onChange(checked, item.value)}\n >\n {item.label}\n </Checkbox>\n </li>\n );\n })}\n </ul>\n );\n};\n\nexport default Group;\n"],"mappings":";;;;;;;;AA+BA,MAAM,SAAS,EACb,cAAc,YACd,YAAY,QACZ,WACA,aAAa,EAAE,EACf,SAAS,WAAW,EAAE,EACtB,cACA,OAAO,QACP,UAAU,kBAAkB,IAC5B,GAAG,YACQ;CACX,MAAM,CAAC,mBAAmB,wBAAwB,SAChD,gBAAgB,EAAE,CACnB;CAED,MAAM,aAAa,WAAW;CAC9B,MAAM,QAAQ,aAAa,SAAS;CAEpC,MAAM,UAAoB,SAAS,KAAI,SACrC,OAAO,SAAS,WACZ,OACA;EACE,OAAO,GAAG;EACV,OAAO;EACR,CACN;CAED,MAAM,YAAY,SAAkB,gBAA6B;EAC/D,MAAM,YAAY,UACd,CAAC,GAAG,OAAO,YAAY,GACvB,MAAM,QAAO,MAAK,MAAM,YAAY;AAExC,MAAI,CAAC,WACH,sBAAqB,UAAU;AAEjC,YAAU,UAAU;;AAGtB,QACE,oBAAC;EACC,GAAI;EACJ,WAAW,GACT,gBAAgB,aAAa,cAAc,cAC3C,UACD;YAEA,QAAQ,KAAK,SAAiB;GAC7B,MAAM,UAAU,MAAM,SAAS,KAAK,MAAM;AAE1C,UACE,oBAAC;IAEC,WAAW,GAAG,QAAQ,YAAY,QAAQ;cAE1C,oBAAC;KACY;KACX,WAAW,GAAG,YAAY,KAAK;KAC/B,OAAO,KAAK;KACH;KACT,UAAU,KAAK;KACf,WAAU,YAAW,SAAS,SAAS,KAAK,MAAM;eAEjD,KAAK;MACG;MAZN,OAAO,KAAK,MAAM,CAapB;IAEP;GACC"}
1
+ {"version":3,"file":"group.mjs","names":[],"sources":["../../../../src/components/atoms/checkbox/group.tsx"],"sourcesContent":["'use client';\n\nimport { useControllableState } from '@jbpark/use-hooks';\n\nimport { cn } from '@repo/ui/utils';\n\nimport {\n type Option,\n type OptionGroupClassNames,\n type OptionValue,\n type Options,\n normalizeOptions,\n} from '../option-group';\nimport Checkbox from './checkbox';\n\nexport type { OptionValue };\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'ul'>,\n 'onChange' | 'defaultValue' | 'value'\n> {\n options?: Options;\n orientation?: 'vertical' | 'horizontal';\n placement?: 'left' | 'right';\n classNames?: OptionGroupClassNames;\n defaultValue?: OptionValue[];\n value?: OptionValue[];\n /** Native form field name, shared across every option's checkbox. */\n name?: string;\n disabled?: boolean;\n onChange?: (values: OptionValue[]) => void;\n}\n\nconst Group = ({\n orientation = 'vertical',\n placement = 'left',\n className,\n classNames = {},\n options: _options = [],\n name,\n disabled,\n defaultValue,\n value: _value,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [value, setValue] = useControllableState<OptionValue[]>({\n value: _value,\n defaultValue: defaultValue ?? [],\n onChange: _onChange,\n });\n\n const options: Option[] = normalizeOptions(_options);\n\n const onChange = (checked: boolean, optionValue: OptionValue) => {\n const nextValue = checked\n ? [...value, optionValue]\n : value.filter(v => v !== optionValue);\n\n setValue(nextValue);\n };\n\n return (\n <ul\n {...props}\n className={cn(\n orientation === 'vertical' ? 'space-y-2' : 'flex gap-2',\n className,\n )}\n >\n {options.map((item: Option) => {\n const checked = value.includes(item.value);\n\n return (\n <li\n key={String(item.value)}\n className={cn('flex', classNames?.wrapper)}\n >\n <Checkbox\n placement={placement}\n className={cn(classNames?.item)}\n name={name}\n value={item.value}\n checked={checked}\n disabled={disabled || item.disabled}\n onChange={checked => onChange(checked, item.value)}\n >\n {item.label}\n </Checkbox>\n </li>\n );\n })}\n </ul>\n );\n};\n\nexport default Group;\n"],"mappings":";;;;;;;;;AAiCA,MAAM,SAAS,EACb,cAAc,YACd,YAAY,QACZ,WACA,aAAa,EAAE,EACf,SAAS,WAAW,EAAE,EACtB,MACA,UACA,cACA,OAAO,QACP,UAAU,kBAAkB,IAC5B,GAAG,YACQ;CACX,MAAM,CAAC,OAAO,YAAY,qBAAoC;EAC5D,OAAO;EACP,cAAc,gBAAgB,EAAE;EAChC,UAAU;EACX,CAAC;CAEF,MAAM,UAAoB,iBAAiB,SAAS;CAEpD,MAAM,YAAY,SAAkB,gBAA6B;AAK/D,WAJkB,UACd,CAAC,GAAG,OAAO,YAAY,GACvB,MAAM,QAAO,MAAK,MAAM,YAAY,CAErB;;AAGrB,QACE,oBAAC;EACC,GAAI;EACJ,WAAW,GACT,gBAAgB,aAAa,cAAc,cAC3C,UACD;YAEA,QAAQ,KAAK,SAAiB;GAC7B,MAAM,UAAU,MAAM,SAAS,KAAK,MAAM;AAE1C,UACE,oBAAC;IAEC,WAAW,GAAG,QAAQ,YAAY,QAAQ;cAE1C,oBAAC;KACY;KACX,WAAW,GAAG,YAAY,KAAK;KACzB;KACN,OAAO,KAAK;KACH;KACT,UAAU,YAAY,KAAK;KAC3B,WAAU,YAAW,SAAS,SAAS,KAAK,MAAM;eAEjD,KAAK;MACG;MAbN,OAAO,KAAK,MAAM,CAcpB;IAEP;GACC"}
@@ -1,17 +1,21 @@
1
1
  import * as react_jsx_runtime0 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/components/atoms/color-picker.d.ts
4
- interface Props {
4
+ interface Props extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onChange' | 'defaultValue' | 'value' | 'onClick' | 'onKeyDown'> {
5
5
  defaultValue?: string;
6
6
  value?: string;
7
7
  showText?: boolean;
8
+ disabled?: boolean;
8
9
  onChange?: (color: string) => void;
9
10
  }
10
11
  declare const ColorPicker: ({
11
12
  defaultValue,
12
13
  value: _value,
13
14
  showText,
14
- onChange: _onChange
15
+ disabled,
16
+ className,
17
+ onChange: _onChange,
18
+ ...props
15
19
  }: Props) => react_jsx_runtime0.JSX.Element;
16
20
  //#endregion
17
21
  export { ColorPicker };
@@ -1 +1 @@
1
- {"version":3,"file":"color-picker.d.mts","names":[],"sources":["../../../src/components/atoms/color-picker.tsx"],"mappings":";;;UASU,KAAA;EACR,YAAA;EACA,KAAA;EACA,QAAA;EACA,QAAA,IAAY,KAAA;AAAA;AAAA,cAGR,WAAA;EAAe,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA;EAAA,QAAA,EAAA;AAAA,GAKlB,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"color-picker.d.mts","names":[],"sources":["../../../src/components/atoms/color-picker.tsx"],"mappings":";;;UAUiB,KAAA,SAAc,IAAA,CAC7B,KAAA,CAAM,wBAAA;EAGN,YAAA;EACA,KAAA;EACA,QAAA;EACA,QAAA;EACA,QAAA,IAAY,KAAA;AAAA;AAAA,cAGR,WAAA;EAAe,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA;EAAA,QAAA;EAAA,SAAA;EAAA,QAAA,EAAA,SAAA;EAAA,GAAA;AAAA,GAQlB,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -2,18 +2,20 @@
2
2
 
3
3
  import { cn } from "../../utils.mjs";
4
4
  import Popover from "./popover.mjs";
5
- import { useState } from "react";
6
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useControllableState } from "@jbpark/use-hooks";
7
7
  import { HexColorPicker } from "react-colorful";
8
8
 
9
9
  //#region src/components/atoms/color-picker.tsx
10
- const ColorPicker = ({ defaultValue, value: _value, showText, onChange: _onChange = () => {} }) => {
11
- const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue || "#fff");
12
- const controlled = _value !== void 0;
13
- const value = controlled ? _value : uncontrolledValue;
10
+ const ColorPicker = ({ defaultValue, value: _value, showText, disabled, className, onChange: _onChange = () => {}, ...props }) => {
11
+ const [value, setValue] = useControllableState({
12
+ value: _value,
13
+ defaultValue: defaultValue ?? "#fff",
14
+ onChange: _onChange
15
+ });
14
16
  const onChange = (color) => {
15
- if (!controlled) setUncontrolledValue(color);
16
- _onChange(color);
17
+ if (disabled) return;
18
+ setValue(color);
17
19
  };
18
20
  return /* @__PURE__ */ jsx(Popover, {
19
21
  placement: "bottomLeft",
@@ -23,16 +25,22 @@ const ColorPicker = ({ defaultValue, value: _value, showText, onChange: _onChang
23
25
  }),
24
26
  children: /* @__PURE__ */ jsxs("div", {
25
27
  role: "button",
26
- tabIndex: 0,
27
- className: cn("inline-flex items-center", "rounded border p-0.5"),
28
+ tabIndex: disabled ? -1 : 0,
29
+ "aria-disabled": disabled,
30
+ className: cn("inline-flex items-center", "rounded border p-0.5", disabled && "cursor-not-allowed opacity-50", className),
31
+ ...props,
32
+ onClick: (e) => {
33
+ if (disabled) e.preventDefault();
34
+ },
28
35
  onKeyDown: (e) => {
36
+ if (disabled) return;
29
37
  if (e.key === "Enter" || e.key === " ") {
30
38
  e.preventDefault();
31
39
  e.currentTarget.click();
32
40
  }
33
41
  },
34
42
  children: [/* @__PURE__ */ jsx("div", {
35
- className: cn("size-6 cursor-pointer rounded border", "shadow-sm"),
43
+ className: cn("size-6 rounded border", "shadow-sm", disabled ? "cursor-not-allowed" : "cursor-pointer"),
36
44
  style: { backgroundColor: value }
37
45
  }), showText && /* @__PURE__ */ jsx("span", {
38
46
  className: "px-1 font-mono text-sm font-medium",
@@ -1 +1 @@
1
- {"version":3,"file":"color-picker.mjs","names":[],"sources":["../../../src/components/atoms/color-picker.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\nimport { HexColorPicker } from 'react-colorful';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Popover from './popover';\n\ninterface Props {\n defaultValue?: string;\n value?: string;\n showText?: boolean;\n onChange?: (color: string) => void;\n}\n\nconst ColorPicker = ({\n defaultValue,\n value: _value,\n showText,\n onChange: _onChange = () => {},\n}: Props) => {\n const [uncontrolledValue, setUncontrolledValue] = useState<string>(\n defaultValue || '#fff',\n );\n\n const controlled = _value !== undefined;\n const value = controlled ? _value : uncontrolledValue;\n\n const onChange = (color: string) => {\n if (!controlled) {\n setUncontrolledValue(color);\n }\n _onChange(color);\n };\n\n return (\n <Popover\n placement=\"bottomLeft\"\n content={<HexColorPicker color={value} onChange={onChange} />}\n >\n <div\n role=\"button\"\n tabIndex={0}\n className={cn(\n 'inline-flex items-center',\n 'rounded border p-0.5',\n //\n )}\n onKeyDown={e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.currentTarget.click();\n }\n }}\n >\n <div\n className={cn(\n 'size-6 cursor-pointer rounded border',\n 'shadow-sm',\n //\n )}\n style={{ backgroundColor: value }}\n />\n {showText && (\n <span className=\"px-1 font-mono text-sm font-medium\">\n {value.toUpperCase()}\n </span>\n )}\n </div>\n </Popover>\n );\n};\n\nexport default ColorPicker;\n"],"mappings":";;;;;;;;;AAgBA,MAAM,eAAe,EACnB,cACA,OAAO,QACP,UACA,UAAU,kBAAkB,SACjB;CACX,MAAM,CAAC,mBAAmB,wBAAwB,SAChD,gBAAgB,OACjB;CAED,MAAM,aAAa,WAAW;CAC9B,MAAM,QAAQ,aAAa,SAAS;CAEpC,MAAM,YAAY,UAAkB;AAClC,MAAI,CAAC,WACH,sBAAqB,MAAM;AAE7B,YAAU,MAAM;;AAGlB,QACE,oBAAC;EACC,WAAU;EACV,SAAS,oBAAC;GAAe,OAAO;GAAiB;IAAY;YAE7D,qBAAC;GACC,MAAK;GACL,UAAU;GACV,WAAW,GACT,4BACA,uBAED;GACD,YAAW,MAAK;AACd,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,OAAE,gBAAgB;AAClB,OAAE,cAAc,OAAO;;;cAI3B,oBAAC;IACC,WAAW,GACT,wCACA,YAED;IACD,OAAO,EAAE,iBAAiB,OAAO;KACjC,EACD,YACC,oBAAC;IAAK,WAAU;cACb,MAAM,aAAa;KACf;IAEL;GACE"}
1
+ {"version":3,"file":"color-picker.mjs","names":[],"sources":["../../../src/components/atoms/color-picker.tsx"],"sourcesContent":["'use client';\n\nimport { HexColorPicker } from 'react-colorful';\n\nimport { useControllableState } from '@jbpark/use-hooks';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Popover from './popover';\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'onChange' | 'defaultValue' | 'value' | 'onClick' | 'onKeyDown'\n> {\n defaultValue?: string;\n value?: string;\n showText?: boolean;\n disabled?: boolean;\n onChange?: (color: string) => void;\n}\n\nconst ColorPicker = ({\n defaultValue,\n value: _value,\n showText,\n disabled,\n className,\n onChange: _onChange = () => {},\n ...props\n}: Props) => {\n const [value, setValue] = useControllableState<string>({\n value: _value,\n defaultValue: defaultValue ?? '#fff',\n onChange: _onChange,\n });\n\n const onChange = (color: string) => {\n if (disabled) {\n return;\n }\n setValue(color);\n };\n\n return (\n <Popover\n placement=\"bottomLeft\"\n content={<HexColorPicker color={value} onChange={onChange} />}\n >\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n className={cn(\n 'inline-flex items-center',\n 'rounded border p-0.5',\n disabled && 'cursor-not-allowed opacity-50',\n className,\n )}\n {...props}\n onClick={e => {\n if (disabled) {\n e.preventDefault();\n }\n }}\n onKeyDown={e => {\n if (disabled) {\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.currentTarget.click();\n }\n }}\n >\n <div\n className={cn(\n 'size-6 rounded border',\n 'shadow-sm',\n disabled ? 'cursor-not-allowed' : 'cursor-pointer',\n )}\n style={{ backgroundColor: value }}\n />\n {showText && (\n <span className=\"px-1 font-mono text-sm font-medium\">\n {value.toUpperCase()}\n </span>\n )}\n </div>\n </Popover>\n );\n};\n\nexport default ColorPicker;\n"],"mappings":";;;;;;;;;AAqBA,MAAM,eAAe,EACnB,cACA,OAAO,QACP,UACA,UACA,WACA,UAAU,kBAAkB,IAC5B,GAAG,YACQ;CACX,MAAM,CAAC,OAAO,YAAY,qBAA6B;EACrD,OAAO;EACP,cAAc,gBAAgB;EAC9B,UAAU;EACX,CAAC;CAEF,MAAM,YAAY,UAAkB;AAClC,MAAI,SACF;AAEF,WAAS,MAAM;;AAGjB,QACE,oBAAC;EACC,WAAU;EACV,SAAS,oBAAC;GAAe,OAAO;GAAiB;IAAY;YAE7D,qBAAC;GACC,MAAK;GACL,UAAU,WAAW,KAAK;GAC1B,iBAAe;GACf,WAAW,GACT,4BACA,wBACA,YAAY,iCACZ,UACD;GACD,GAAI;GACJ,UAAS,MAAK;AACZ,QAAI,SACF,GAAE,gBAAgB;;GAGtB,YAAW,MAAK;AACd,QAAI,SACF;AAEF,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,OAAE,gBAAgB;AAClB,OAAE,cAAc,OAAO;;;cAI3B,oBAAC;IACC,WAAW,GACT,yBACA,aACA,WAAW,uBAAuB,iBACnC;IACD,OAAO,EAAE,iBAAiB,OAAO;KACjC,EACD,YACC,oBAAC;IAAK,WAAU;cACb,MAAM,aAAa;KACf;IAEL;GACE"}
@@ -6,6 +6,7 @@ interface Props {
6
6
  value?: Date;
7
7
  placeholder?: string;
8
8
  className?: string;
9
+ disabled?: boolean;
9
10
  onChange?: (date: Date | undefined) => void;
10
11
  }
11
12
  declare const DatePicker: ({
@@ -13,6 +14,7 @@ declare const DatePicker: ({
13
14
  value: _value,
14
15
  placeholder,
15
16
  className,
17
+ disabled,
16
18
  onChange: _onChange
17
19
  }: Props) => react_jsx_runtime0.JSX.Element;
18
20
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"date-picker.d.mts","names":[],"sources":["../../../src/components/atoms/date-picker.tsx"],"mappings":";;;UAeU,KAAA;EACR,YAAA,GAAe,IAAA;EACf,KAAA,GAAQ,IAAA;EACR,WAAA;EACA,SAAA;EACA,QAAA,IAAY,IAAA,EAAM,IAAA;AAAA;AAAA,cAGd,UAAA;EAAc,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,WAAA;EAAA,SAAA;EAAA,QAAA,EAAA;AAAA,GAMjB,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"date-picker.d.mts","names":[],"sources":["../../../src/components/atoms/date-picker.tsx"],"mappings":";;;UAgBU,KAAA;EACR,YAAA,GAAe,IAAA;EACf,KAAA,GAAQ,IAAA;EACR,WAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA,IAAY,IAAA,EAAM,IAAA;AAAA;AAAA,cAGd,UAAA;EAAc,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,WAAA;EAAA,SAAA;EAAA,QAAA;EAAA,QAAA,EAAA;AAAA,GAOjB,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -7,29 +7,35 @@ import Popover from "./popover.mjs";
7
7
  import { CalendarIcon } from "lucide-react";
8
8
  import { useState } from "react";
9
9
  import { jsx } from "react/jsx-runtime";
10
+ import { useControllableState } from "@jbpark/use-hooks";
10
11
  import { format } from "date-fns";
11
12
 
12
13
  //#region src/components/atoms/date-picker.tsx
13
14
  const { Calendar } = calendar_exports;
14
- const DatePicker = ({ defaultValue, value: _value, placeholder = "Pick a date", className, onChange: _onChange = () => {} }) => {
15
- const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
16
- const controlled = _value !== void 0;
17
- const value = controlled ? _value : uncontrolledValue;
18
- const onChange = (date) => {
19
- if (!controlled) setUncontrolledValue(date);
20
- _onChange(date);
21
- };
15
+ const DatePicker = ({ defaultValue, value: _value, placeholder = "Pick a date", className, disabled, onChange: _onChange = () => {} }) => {
16
+ const [value, onChange] = useControllableState({
17
+ value: _value,
18
+ defaultValue,
19
+ onChange: _onChange
20
+ });
21
+ const [open, setOpen] = useState(false);
22
22
  return /* @__PURE__ */ jsx(Popover, {
23
23
  placement: "bottomLeft",
24
+ open,
25
+ onOpenChange: setOpen,
24
26
  content: /* @__PURE__ */ jsx(Calendar, {
25
27
  mode: "single",
26
28
  selected: value,
27
- onSelect: onChange
29
+ onSelect: (date) => {
30
+ onChange(date);
31
+ setOpen(false);
32
+ }
28
33
  }),
29
34
  children: /* @__PURE__ */ jsx(Button, {
30
35
  type: "default",
31
36
  icon: /* @__PURE__ */ jsx(CalendarIcon, {}),
32
37
  "data-empty": !value,
38
+ disabled,
33
39
  className: cn("w-full justify-start text-left font-normal", "data-[empty=true]:text-muted-foreground", className),
34
40
  children: value ? format(value, "PPP") : placeholder
35
41
  })
@@ -1 +1 @@
1
- {"version":3,"file":"date-picker.mjs","names":["calendar"],"sources":["../../../src/components/atoms/date-picker.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\n\nimport { format } from 'date-fns';\nimport { CalendarIcon } from 'lucide-react';\n\nimport { calendar } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from './button';\nimport Popover from './popover';\n\nconst { Calendar } = calendar;\n\ninterface Props {\n defaultValue?: Date;\n value?: Date;\n placeholder?: string;\n className?: string;\n onChange?: (date: Date | undefined) => void;\n}\n\nconst DatePicker = ({\n defaultValue,\n value: _value,\n placeholder = 'Pick a date',\n className,\n onChange: _onChange = () => {},\n}: Props) => {\n const [uncontrolledValue, setUncontrolledValue] = useState<Date | undefined>(\n defaultValue,\n );\n\n const controlled = _value !== undefined;\n const value = controlled ? _value : uncontrolledValue;\n\n const onChange = (date: Date | undefined) => {\n if (!controlled) {\n setUncontrolledValue(date);\n }\n _onChange(date);\n };\n\n return (\n <Popover\n placement=\"bottomLeft\"\n content={<Calendar mode=\"single\" selected={value} onSelect={onChange} />}\n >\n <Button\n type=\"default\"\n icon={<CalendarIcon />}\n data-empty={!value}\n className={cn(\n 'w-full justify-start text-left font-normal',\n 'data-[empty=true]:text-muted-foreground',\n className,\n //\n )}\n >\n {value ? format(value, 'PPP') : placeholder}\n </Button>\n </Popover>\n );\n};\n\nexport default DatePicker;\nexport type { Props };\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,EAAE,aAAaA;AAUrB,MAAM,cAAc,EAClB,cACA,OAAO,QACP,cAAc,eACd,WACA,UAAU,kBAAkB,SACjB;CACX,MAAM,CAAC,mBAAmB,wBAAwB,SAChD,aACD;CAED,MAAM,aAAa,WAAW;CAC9B,MAAM,QAAQ,aAAa,SAAS;CAEpC,MAAM,YAAY,SAA2B;AAC3C,MAAI,CAAC,WACH,sBAAqB,KAAK;AAE5B,YAAU,KAAK;;AAGjB,QACE,oBAAC;EACC,WAAU;EACV,SAAS,oBAAC;GAAS,MAAK;GAAS,UAAU;GAAO,UAAU;IAAY;YAExE,oBAAC;GACC,MAAK;GACL,MAAM,oBAAC,iBAAe;GACtB,cAAY,CAAC;GACb,WAAW,GACT,8CACA,2CACA,UAED;aAEA,QAAQ,OAAO,OAAO,MAAM,GAAG;IACzB;GACD"}
1
+ {"version":3,"file":"date-picker.mjs","names":["calendar"],"sources":["../../../src/components/atoms/date-picker.tsx"],"sourcesContent":["'use client';\n\nimport { useState } from 'react';\n\nimport { useControllableState } from '@jbpark/use-hooks';\nimport { format } from 'date-fns';\nimport { CalendarIcon } from 'lucide-react';\n\nimport { calendar } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nimport Button from './button';\nimport Popover from './popover';\n\nconst { Calendar } = calendar;\n\ninterface Props {\n defaultValue?: Date;\n value?: Date;\n placeholder?: string;\n className?: string;\n disabled?: boolean;\n onChange?: (date: Date | undefined) => void;\n}\n\nconst DatePicker = ({\n defaultValue,\n value: _value,\n placeholder = 'Pick a date',\n className,\n disabled,\n onChange: _onChange = () => {},\n}: Props) => {\n const [value, onChange] = useControllableState<Date | undefined>({\n value: _value,\n defaultValue,\n onChange: _onChange,\n });\n const [open, setOpen] = useState(false);\n\n return (\n <Popover\n placement=\"bottomLeft\"\n open={open}\n onOpenChange={setOpen}\n content={\n <Calendar\n mode=\"single\"\n selected={value}\n onSelect={date => {\n onChange(date);\n setOpen(false);\n }}\n />\n }\n >\n <Button\n type=\"default\"\n icon={<CalendarIcon />}\n data-empty={!value}\n disabled={disabled}\n className={cn(\n 'w-full justify-start text-left font-normal',\n 'data-[empty=true]:text-muted-foreground',\n className,\n //\n )}\n >\n {value ? format(value, 'PPP') : placeholder}\n </Button>\n </Popover>\n );\n};\n\nexport default DatePicker;\nexport type { Props };\n"],"mappings":";;;;;;;;;;;;;AAcA,MAAM,EAAE,aAAaA;AAWrB,MAAM,cAAc,EAClB,cACA,OAAO,QACP,cAAc,eACd,WACA,UACA,UAAU,kBAAkB,SACjB;CACX,MAAM,CAAC,OAAO,YAAY,qBAAuC;EAC/D,OAAO;EACP;EACA,UAAU;EACX,CAAC;CACF,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;AAEvC,QACE,oBAAC;EACC,WAAU;EACJ;EACN,cAAc;EACd,SACE,oBAAC;GACC,MAAK;GACL,UAAU;GACV,WAAU,SAAQ;AAChB,aAAS,KAAK;AACd,YAAQ,MAAM;;IAEhB;YAGJ,oBAAC;GACC,MAAK;GACL,MAAM,oBAAC,iBAAe;GACtB,cAAY,CAAC;GACH;GACV,WAAW,GACT,8CACA,2CACA,UAED;aAEA,QAAQ,OAAO,OAAO,MAAM,GAAG;IACzB;GACD"}
@@ -8,6 +8,7 @@ interface Props extends Props$1 {
8
8
  onClick?: (e: MouseEvent<HTMLElement>) => void;
9
9
  }
10
10
  declare const BackTop: ({
11
+ ref,
11
12
  visibilityHeight,
12
13
  className,
13
14
  onClick,
@@ -1 +1 @@
1
- {"version":3,"file":"back-top.d.mts","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"mappings":";;;;;UAYiB,KAAA,SAAc,OAAA;EAC7B,gBAAA;EACA,OAAA,IAAW,CAAA,EAAG,UAAA,CAAW,WAAA;AAAA;AAAA,cAGrB,OAAA;EAAW,gBAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAKd,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"back-top.d.mts","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"mappings":";;;;;UAYiB,KAAA,SAAc,OAAA;EAC7B,gBAAA;EACA,OAAA,IAAW,CAAA,EAAG,UAAA,CAAW,WAAA;AAAA;AAAA,cAGrB,OAAA;EAAW,GAAA;EAAA,gBAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAMd,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -3,18 +3,26 @@
3
3
  import { cn } from "../../../utils.mjs";
4
4
  import FloatButton from "./float-button.mjs";
5
5
  import { ArrowUp } from "lucide-react";
6
+ import { useRef } from "react";
6
7
  import { jsx } from "react/jsx-runtime";
7
8
  import { useWindowScroll } from "@jbpark/use-hooks";
8
9
 
9
10
  //#region src/components/atoms/float-button/back-top.tsx
10
- const BackTop = ({ visibilityHeight = 450, className, onClick, ...props }) => {
11
- const { y } = useWindowScroll();
11
+ const BackTop = ({ ref, visibilityHeight = 450, className, onClick, ...props }) => {
12
+ const buttonRef = useRef(null);
13
+ const { y } = useWindowScroll(buttonRef);
14
+ const setRefs = (node) => {
15
+ buttonRef.current = node;
16
+ if (typeof ref === "function") ref(node);
17
+ else if (ref) ref.current = node;
18
+ };
12
19
  return /* @__PURE__ */ jsx(FloatButton, {
20
+ ref: setRefs,
13
21
  "aria-label": "맨 위로",
14
22
  icon: /* @__PURE__ */ jsx(ArrowUp, {}),
15
23
  className: cn(className, (!y || visibilityHeight > y) && "hidden"),
16
24
  onClick: (e) => {
17
- window.scrollTo({
25
+ (buttonRef.current?.ownerDocument.defaultView ?? window).scrollTo({
18
26
  left: 0,
19
27
  top: 0,
20
28
  behavior: "smooth"
@@ -1 +1 @@
1
- {"version":3,"file":"back-top.mjs","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"sourcesContent":["'use client';\n\nimport { MouseEvent } from 'react';\n\nimport { useWindowScroll } from '@jbpark/use-hooks';\nimport { ArrowUp } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { type Props as ButtonProps } from '../button';\nimport FloatButton from './float-button';\n\nexport interface Props extends ButtonProps {\n visibilityHeight?: number;\n onClick?: (e: MouseEvent<HTMLElement>) => void;\n}\n\nconst BackTop = ({\n visibilityHeight = 450,\n className,\n onClick,\n ...props\n}: Props) => {\n const { y } = useWindowScroll();\n\n return (\n <FloatButton\n aria-label=\"맨 위로\"\n icon={<ArrowUp />}\n className={cn(\n className,\n (!y || visibilityHeight > y) && 'hidden',\n //\n )}\n onClick={e => {\n window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });\n onClick?.(e);\n }}\n {...props}\n />\n );\n};\n\nexport default BackTop;\n"],"mappings":";;;;;;;;;AAiBA,MAAM,WAAW,EACf,mBAAmB,KACnB,WACA,SACA,GAAG,YACQ;CACX,MAAM,EAAE,MAAM,iBAAiB;AAE/B,QACE,oBAAC;EACC,cAAW;EACX,MAAM,oBAAC,YAAU;EACjB,WAAW,GACT,YACC,CAAC,KAAK,mBAAmB,MAAM,SAEjC;EACD,UAAS,MAAK;AACZ,UAAO,SAAS;IAAE,MAAM;IAAG,KAAK;IAAG,UAAU;IAAU,CAAC;AACxD,aAAU,EAAE;;EAEd,GAAI;GACJ"}
1
+ {"version":3,"file":"back-top.mjs","names":[],"sources":["../../../../src/components/atoms/float-button/back-top.tsx"],"sourcesContent":["'use client';\n\nimport { type MouseEvent, useRef } from 'react';\n\nimport { useWindowScroll } from '@jbpark/use-hooks';\nimport { ArrowUp } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport { type Props as ButtonProps } from '../button';\nimport FloatButton from './float-button';\n\nexport interface Props extends ButtonProps {\n visibilityHeight?: number;\n onClick?: (e: MouseEvent<HTMLElement>) => void;\n}\n\nconst BackTop = ({\n ref,\n visibilityHeight = 450,\n className,\n onClick,\n ...props\n}: Props) => {\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n // Track/scroll whichever window actually renders this button — not\n // necessarily the host `window`, since this can be portaled into an\n // iframe (e.g. live-editor's Renderer).\n const { y } = useWindowScroll(buttonRef);\n\n const setRefs = (node: HTMLButtonElement | null) => {\n buttonRef.current = node;\n\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref) {\n ref.current = node;\n }\n };\n\n return (\n <FloatButton\n ref={setRefs}\n aria-label=\"맨 위로\"\n icon={<ArrowUp />}\n className={cn(\n className,\n (!y || visibilityHeight > y) && 'hidden',\n //\n )}\n onClick={e => {\n const view = buttonRef.current?.ownerDocument.defaultView ?? window;\n view.scrollTo({ left: 0, top: 0, behavior: 'smooth' });\n onClick?.(e);\n }}\n {...props}\n />\n );\n};\n\nexport default BackTop;\n"],"mappings":";;;;;;;;;;AAiBA,MAAM,WAAW,EACf,KACA,mBAAmB,KACnB,WACA,SACA,GAAG,YACQ;CACX,MAAM,YAAY,OAA0B,KAAK;CAKjD,MAAM,EAAE,MAAM,gBAAgB,UAAU;CAExC,MAAM,WAAW,SAAmC;AAClD,YAAU,UAAU;AAEpB,MAAI,OAAO,QAAQ,WACjB,KAAI,KAAK;WACA,IACT,KAAI,UAAU;;AAIlB,QACE,oBAAC;EACC,KAAK;EACL,cAAW;EACX,MAAM,oBAAC,YAAU;EACjB,WAAW,GACT,YACC,CAAC,KAAK,mBAAmB,MAAM,SAEjC;EACD,UAAS,MAAK;AAEZ,IADa,UAAU,SAAS,cAAc,eAAe,QACxD,SAAS;IAAE,MAAM;IAAG,KAAK;IAAG,UAAU;IAAU,CAAC;AACtD,aAAU,EAAE;;EAEd,GAAI;GACJ"}
@@ -2,8 +2,9 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
2
 
3
3
  //#region src/components/atoms/input/input.d.ts
4
4
  declare const Input: ({
5
+ ref,
5
6
  ...props
6
- }: React.ComponentPropsWithoutRef<"input">) => react_jsx_runtime0.JSX.Element;
7
+ }: React.ComponentPropsWithRef<"input">) => react_jsx_runtime0.JSX.Element;
7
8
  //#endregion
8
9
  export { Input };
9
10
  //# sourceMappingURL=input.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"input.d.mts","names":[],"sources":["../../../../src/components/atoms/input/input.tsx"],"mappings":";;;cAIM,KAAA;EAAA,GAAS;AAAA,GAAc,KAAA,CAAM,wBAAA,cAAiC,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"input.d.mts","names":[],"sources":["../../../../src/components/atoms/input/input.tsx"],"mappings":";;;cAIM,KAAA;EAAS,GAAA;EAAA,GAAA;AAAA,GAAmB,KAAA,CAAM,qBAAA,cAA8B,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -3,8 +3,11 @@ import { jsx } from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/atoms/input/input.tsx
5
5
  const { Input: Core } = input_exports;
6
- const Input = ({ ...props }) => {
7
- return /* @__PURE__ */ jsx(Core, { ...props });
6
+ const Input = ({ ref, ...props }) => {
7
+ return /* @__PURE__ */ jsx(Core, {
8
+ ref,
9
+ ...props
10
+ });
8
11
  };
9
12
 
10
13
  //#endregion