@jbpark/ui-kit 3.5.0 → 3.7.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 (57) hide show
  1. package/dist/Space.mjs +3 -1
  2. package/dist/Space.mjs.map +1 -1
  3. package/dist/components/atoms/popover.d.mts.map +1 -1
  4. package/dist/components/atoms/popover.mjs +71 -19
  5. package/dist/components/atoms/popover.mjs.map +1 -1
  6. package/dist/components/atoms/skeleton/button.d.mts +1 -1
  7. package/dist/components/atoms/skeleton/button.d.mts.map +1 -1
  8. package/dist/components/atoms/skeleton/button.mjs +5 -2
  9. package/dist/components/atoms/skeleton/button.mjs.map +1 -1
  10. package/dist/components/atoms/skeleton/node.d.mts +1 -1
  11. package/dist/components/atoms/skeleton/node.d.mts.map +1 -1
  12. package/dist/components/atoms/skeleton/node.mjs +5 -2
  13. package/dist/components/atoms/skeleton/node.mjs.map +1 -1
  14. package/dist/components/molecules/collapse.mjs +1 -1
  15. package/dist/components/molecules/collapse.mjs.map +1 -1
  16. package/dist/components/molecules/marquees/item.d.mts.map +1 -1
  17. package/dist/components/molecules/marquees/item.mjs +3 -8
  18. package/dist/components/molecules/marquees/item.mjs.map +1 -1
  19. package/dist/components/molecules/reveals/reveals.d.mts +5 -0
  20. package/dist/components/molecules/reveals/reveals.d.mts.map +1 -1
  21. package/dist/components/molecules/reveals/reveals.mjs +6 -1
  22. package/dist/components/molecules/reveals/reveals.mjs.map +1 -1
  23. package/dist/components/molecules/upload.d.mts +10 -1
  24. package/dist/components/molecules/upload.d.mts.map +1 -1
  25. package/dist/components/molecules/upload.mjs +23 -6
  26. package/dist/components/molecules/upload.mjs.map +1 -1
  27. package/dist/components/organisms/drawer.d.mts.map +1 -1
  28. package/dist/components/organisms/drawer.mjs +37 -13
  29. package/dist/components/organisms/drawer.mjs.map +1 -1
  30. package/dist/components/organisms/list/list.mjs +1 -6
  31. package/dist/components/organisms/list/list.mjs.map +1 -1
  32. package/dist/components/organisms/modal.d.mts +1 -0
  33. package/dist/components/organisms/modal.d.mts.map +1 -1
  34. package/dist/components/organisms/modal.mjs +14 -9
  35. package/dist/components/organisms/modal.mjs.map +1 -1
  36. package/dist/components/organisms/swiper/swiper.d.mts.map +1 -1
  37. package/dist/components/organisms/swiper/swiper.mjs +5 -1
  38. package/dist/components/organisms/swiper/swiper.mjs.map +1 -1
  39. package/dist/components/organisms/toast.d.mts.map +1 -1
  40. package/dist/components/organisms/toast.mjs +11 -4
  41. package/dist/components/organisms/toast.mjs.map +1 -1
  42. package/dist/components/templates/layout/header.mjs +1 -1
  43. package/dist/components/templates/layout/header.mjs.map +1 -1
  44. package/dist/components/templates/layout/layout.d.mts.map +1 -1
  45. package/dist/components/templates/layout/layout.mjs +23 -7
  46. package/dist/components/templates/layout/layout.mjs.map +1 -1
  47. package/dist/components/templates/layout/sider-context.mjs +20 -0
  48. package/dist/components/templates/layout/sider-context.mjs.map +1 -0
  49. package/dist/components/templates/layout/sider.d.mts.map +1 -1
  50. package/dist/components/templates/layout/sider.mjs +4 -2
  51. package/dist/components/templates/layout/sider.mjs.map +1 -1
  52. package/dist/core/badge.d.mts +1 -1
  53. package/dist/core/button.d.mts +2 -2
  54. package/dist/providers/Config/index.mjs +6 -2
  55. package/dist/providers/Config/index.mjs.map +1 -1
  56. package/dist/style.css +210 -6
  57. package/package.json +1 -1
package/dist/Space.mjs CHANGED
@@ -19,7 +19,9 @@ const Space = ({ loading, loader, children, size = "middle", orientation = "hori
19
19
  const [x, y] = typeof size === "string" ? sizes[size] || [0, 0] : Array.isArray(size) ? size : [size, size];
20
20
  const count = Children.count(children);
21
21
  if (loading) return /* @__PURE__ */ jsx("div", {
22
- className: cn(className),
22
+ className: cn(hidden && "hidden", className),
23
+ style,
24
+ ...props,
23
25
  children: loader || /* @__PURE__ */ jsx(Skeleton, {})
24
26
  });
25
27
  return /* @__PURE__ */ jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"Space.mjs","names":[],"sources":["../src/components/molecules/space.tsx"],"sourcesContent":["import { Children } from 'react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Skeleton from '../atoms/skeleton';\n\ninterface Props extends React.ComponentPropsWithRef<'div'> {\n loading?: boolean;\n loader?: React.ReactNode;\n orientation?: 'horizontal' | 'vertical';\n size?: 'small' | 'middle' | 'large' | number | number[];\n align?: 'start' | 'end' | 'center' | 'baseline';\n wrap?: boolean;\n split?: React.ReactNode;\n grid?: {\n rows?: number;\n cols?: number;\n };\n}\n\nconst sizes: Record<string, number[]> = {\n small: [4, 4],\n middle: [8, 8],\n large: [16, 16],\n};\n\nconst aligns: Record<string, string> = {\n start: 'items-start text-start',\n end: 'items-end text-end',\n center: 'items-center text-center',\n baseline: 'items-baseline text-baseline',\n};\n\nconst Space = ({\n loading,\n loader,\n children,\n size = 'middle',\n orientation = 'horizontal',\n align = 'center',\n wrap = false,\n split,\n className,\n grid,\n hidden,\n style,\n ...props\n}: Props) => {\n const [x, y] =\n typeof size === 'string'\n ? sizes[size] || [0, 0]\n : Array.isArray(size)\n ? size\n : [size, size];\n const count = Children.count(children);\n\n if (loading) {\n return <div className={cn(className)}>{loader || <Skeleton />}</div>;\n }\n\n return (\n <div\n className={cn(\n 'flex flex-nowrap',\n orientation === 'horizontal' ? 'flex-row' : 'flex-col',\n wrap && 'flex-wrap',\n aligns[align],\n grid && 'grid',\n hidden && 'hidden',\n className,\n )}\n style={{\n columnGap: x,\n rowGap: y,\n gridTemplateRows: grid?.rows\n ? `repeat(${grid.rows}, minmax(0, 1fr))`\n : undefined,\n gridTemplateColumns: grid?.cols\n ? `repeat(${grid.cols}, minmax(0, 1fr))`\n : undefined,\n ...style,\n }}\n {...props}\n >\n {Children.map(children, (child, i) => (\n <>\n {child}\n {split && i < count - 1 && split}\n </>\n ))}\n </div>\n );\n};\n\nexport default Space;\n"],"mappings":";;;;;;AAoBA,MAAM,QAAkC;CACtC,OAAO,CAAC,GAAG,EAAE;CACb,QAAQ,CAAC,GAAG,EAAE;CACd,OAAO,CAAC,IAAI,GAAG;CAChB;AAED,MAAM,SAAiC;CACrC,OAAO;CACP,KAAK;CACL,QAAQ;CACR,UAAU;CACX;AAED,MAAM,SAAS,EACb,SACA,QACA,UACA,OAAO,UACP,cAAc,cACd,QAAQ,UACR,OAAO,OACP,OACA,WACA,MACA,QACA,OACA,GAAG,YACQ;CACX,MAAM,CAAC,GAAG,KACR,OAAO,SAAS,WACZ,MAAM,SAAS,CAAC,GAAG,EAAE,GACrB,MAAM,QAAQ,KAAK,GACjB,OACA,CAAC,MAAM,KAAK;CACpB,MAAM,QAAQ,SAAS,MAAM,SAAS;AAEtC,KAAI,QACF,QAAO,oBAAC;EAAI,WAAW,GAAG,UAAU;YAAG,UAAU,oBAAC,aAAW;GAAO;AAGtE,QACE,oBAAC;EACC,WAAW,GACT,oBACA,gBAAgB,eAAe,aAAa,YAC5C,QAAQ,aACR,OAAO,QACP,QAAQ,QACR,UAAU,UACV,UACD;EACD,OAAO;GACL,WAAW;GACX,QAAQ;GACR,kBAAkB,MAAM,OACpB,UAAU,KAAK,KAAK,qBACpB;GACJ,qBAAqB,MAAM,OACvB,UAAU,KAAK,KAAK,qBACpB;GACJ,GAAG;GACJ;EACD,GAAI;YAEH,SAAS,IAAI,WAAW,OAAO,MAC9B,8CACG,OACA,SAAS,IAAI,QAAQ,KAAK,SAC1B,CACH;GACE"}
1
+ {"version":3,"file":"Space.mjs","names":[],"sources":["../src/components/molecules/space.tsx"],"sourcesContent":["import { Children } from 'react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Skeleton from '../atoms/skeleton';\n\ninterface Props extends React.ComponentPropsWithRef<'div'> {\n loading?: boolean;\n loader?: React.ReactNode;\n orientation?: 'horizontal' | 'vertical';\n size?: 'small' | 'middle' | 'large' | number | number[];\n align?: 'start' | 'end' | 'center' | 'baseline';\n wrap?: boolean;\n split?: React.ReactNode;\n grid?: {\n rows?: number;\n cols?: number;\n };\n}\n\nconst sizes: Record<string, number[]> = {\n small: [4, 4],\n middle: [8, 8],\n large: [16, 16],\n};\n\nconst aligns: Record<string, string> = {\n start: 'items-start text-start',\n end: 'items-end text-end',\n center: 'items-center text-center',\n baseline: 'items-baseline text-baseline',\n};\n\nconst Space = ({\n loading,\n loader,\n children,\n size = 'middle',\n orientation = 'horizontal',\n align = 'center',\n wrap = false,\n split,\n className,\n grid,\n hidden,\n style,\n ...props\n}: Props) => {\n const [x, y] =\n typeof size === 'string'\n ? sizes[size] || [0, 0]\n : Array.isArray(size)\n ? size\n : [size, size];\n const count = Children.count(children);\n\n if (loading) {\n return (\n <div\n className={cn(hidden && 'hidden', className)}\n style={style}\n {...props}\n >\n {loader || <Skeleton />}\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n 'flex flex-nowrap',\n orientation === 'horizontal' ? 'flex-row' : 'flex-col',\n wrap && 'flex-wrap',\n aligns[align],\n grid && 'grid',\n hidden && 'hidden',\n className,\n )}\n style={{\n columnGap: x,\n rowGap: y,\n gridTemplateRows: grid?.rows\n ? `repeat(${grid.rows}, minmax(0, 1fr))`\n : undefined,\n gridTemplateColumns: grid?.cols\n ? `repeat(${grid.cols}, minmax(0, 1fr))`\n : undefined,\n ...style,\n }}\n {...props}\n >\n {Children.map(children, (child, i) => (\n <>\n {child}\n {split && i < count - 1 && split}\n </>\n ))}\n </div>\n );\n};\n\nexport default Space;\n"],"mappings":";;;;;;AAoBA,MAAM,QAAkC;CACtC,OAAO,CAAC,GAAG,EAAE;CACb,QAAQ,CAAC,GAAG,EAAE;CACd,OAAO,CAAC,IAAI,GAAG;CAChB;AAED,MAAM,SAAiC;CACrC,OAAO;CACP,KAAK;CACL,QAAQ;CACR,UAAU;CACX;AAED,MAAM,SAAS,EACb,SACA,QACA,UACA,OAAO,UACP,cAAc,cACd,QAAQ,UACR,OAAO,OACP,OACA,WACA,MACA,QACA,OACA,GAAG,YACQ;CACX,MAAM,CAAC,GAAG,KACR,OAAO,SAAS,WACZ,MAAM,SAAS,CAAC,GAAG,EAAE,GACrB,MAAM,QAAQ,KAAK,GACjB,OACA,CAAC,MAAM,KAAK;CACpB,MAAM,QAAQ,SAAS,MAAM,SAAS;AAEtC,KAAI,QACF,QACE,oBAAC;EACC,WAAW,GAAG,UAAU,UAAU,UAAU;EACrC;EACP,GAAI;YAEH,UAAU,oBAAC,aAAW;GACnB;AAIV,QACE,oBAAC;EACC,WAAW,GACT,oBACA,gBAAgB,eAAe,aAAa,YAC5C,QAAQ,aACR,OAAO,QACP,QAAQ,QACR,UAAU,UACV,UACD;EACD,OAAO;GACL,WAAW;GACX,QAAQ;GACR,kBAAkB,MAAM,OACpB,UAAU,KAAK,KAAK,qBACpB;GACJ,qBAAqB,MAAM,OACvB,UAAU,KAAK,KAAK,qBACpB;GACJ,GAAG;GACJ;EACD,GAAI;YAEH,SAAS,IAAI,WAAW,OAAO,MAC9B,8CACG,OACA,SAAS,IAAI,QAAQ,KAAK,SAC1B,CACH;GACE"}
@@ -1 +1 @@
1
- {"version":3,"file":"popover.d.mts","names":[],"sources":["../../../src/components/atoms/popover.tsx"],"mappings":";;;KASK,SAAA;AAAA,UAcY,KAAA,SAAc,IAAA,CAC7B,KAAA,CAAM,wBAAA;EAGN,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,SAAA,GAAY,SAAA;EACZ,OAAA,EAAS,KAAA,CAAM,SAAA;EACf,IAAA;EACA,WAAA;EACA,YAAA,IAAgB,IAAA;AAAA;AAAA,cA4GZ,OAAA;EAAW,KAAA;EAAA,SAAA;EAAA,SAAA;EAAA,OAAA;EAAA,QAAA;EAAA,IAAA,EAAA,KAAA;EAAA,WAAA;EAAA,YAAA;EAAA,GAAA;AAAA,GAUd,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"popover.d.mts","names":[],"sources":["../../../src/components/atoms/popover.tsx"],"mappings":";;;KASK,SAAA;AAAA,UAcY,KAAA,SAAc,IAAA,CAC7B,KAAA,CAAM,wBAAA;EAGN,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,SAAA,GAAY,SAAA;EACZ,OAAA,EAAS,KAAA,CAAM,SAAA;EACf,IAAA;EACA,WAAA;EACA,YAAA,IAAgB,IAAA;AAAA;AAAA,cA6JZ,OAAA;EAAW,KAAA;EAAA,SAAA;EAAA,SAAA;EAAA,OAAA;EAAA,QAAA;EAAA,IAAA,EAAA,KAAA;EAAA,WAAA;EAAA,YAAA;EAAA,GAAA;AAAA,GAUd,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -86,27 +86,79 @@ const fillColorBySide = {
86
86
  left: "after:border-l-8 after:border-l-popover",
87
87
  right: "after:border-r-8 after:border-r-popover"
88
88
  };
89
- const offsetAxisBySide = {
90
- top: "x",
91
- bottom: "x",
92
- left: "y",
93
- right: "y"
94
- };
95
- const startEdgeByAxis = {
96
- x: "left",
97
- y: "top"
98
- };
99
- const endEdgeByAxis = {
100
- x: "right",
101
- y: "bottom"
89
+ const POSITION_CLASSES = {
90
+ top: {
91
+ start: {
92
+ wrapper: "top-full left-4",
93
+ before: "before:top-0 before:left-0",
94
+ after: "after:-top-px after:left-px"
95
+ },
96
+ center: {
97
+ wrapper: "top-full left-1/2 -translate-x-1/2",
98
+ before: "before:top-0 before:left-1/2 before:-translate-x-1/2",
99
+ after: "after:-top-px after:left-1/2 after:-translate-x-1/2"
100
+ },
101
+ end: {
102
+ wrapper: "top-full right-4",
103
+ before: "before:top-0 before:right-0",
104
+ after: "after:-top-px after:right-px"
105
+ }
106
+ },
107
+ bottom: {
108
+ start: {
109
+ wrapper: "bottom-full left-4",
110
+ before: "before:bottom-0 before:left-0",
111
+ after: "after:-bottom-px after:left-px"
112
+ },
113
+ center: {
114
+ wrapper: "bottom-full left-1/2 -translate-x-1/2",
115
+ before: "before:bottom-0 before:left-1/2 before:-translate-x-1/2",
116
+ after: "after:-bottom-px after:left-1/2 after:-translate-x-1/2"
117
+ },
118
+ end: {
119
+ wrapper: "bottom-full right-4",
120
+ before: "before:bottom-0 before:right-0",
121
+ after: "after:-bottom-px after:right-px"
122
+ }
123
+ },
124
+ left: {
125
+ start: {
126
+ wrapper: "left-full top-4",
127
+ before: "before:left-0 before:top-0",
128
+ after: "after:-left-px after:top-px"
129
+ },
130
+ center: {
131
+ wrapper: "left-full top-1/2 -translate-y-1/2",
132
+ before: "before:left-0 before:top-1/2 before:-translate-y-1/2",
133
+ after: "after:-left-px after:top-1/2 after:-translate-y-1/2"
134
+ },
135
+ end: {
136
+ wrapper: "left-full bottom-4",
137
+ before: "before:left-0 before:bottom-0",
138
+ after: "after:-left-px after:bottom-px"
139
+ }
140
+ },
141
+ right: {
142
+ start: {
143
+ wrapper: "right-full top-4",
144
+ before: "before:right-0 before:top-0",
145
+ after: "after:-right-px after:top-px"
146
+ },
147
+ center: {
148
+ wrapper: "right-full top-1/2 -translate-y-1/2",
149
+ before: "before:right-0 before:top-1/2 before:-translate-y-1/2",
150
+ after: "after:-right-px after:top-1/2 after:-translate-y-1/2"
151
+ },
152
+ end: {
153
+ wrapper: "right-full bottom-4",
154
+ before: "before:right-0 before:bottom-0",
155
+ after: "after:-right-px after:bottom-px"
156
+ }
157
+ }
102
158
  };
103
159
  const getArrowClassName = (side, align) => {
104
- const axis = offsetAxisBySide[side];
105
- const alignEdge = align === "start" ? startEdgeByAxis[axis] : align === "end" ? endEdgeByAxis[axis] : null;
106
- const positionAlign = alignEdge ? `${alignEdge}-4` : `${startEdgeByAxis[axis]}-1/2 -translate-${axis}-1/2`;
107
- const beforeAlign = alignEdge ? `before:${alignEdge}-0` : `before:${startEdgeByAxis[axis]}-1/2 before:-translate-${axis}-1/2`;
108
- const afterAlign = alignEdge ? `after:${alignEdge}-px` : `after:${startEdgeByAxis[axis]}-1/2 after:-translate-${axis}-1/2`;
109
- return cn(`absolute ${positionAlign} ${side}-full`, beforeBase, `before:${side}-0`, beforeAlign, borderShapeBySide[side], borderColorBySide[side], afterBase, `after:-${side}-px`, afterAlign, fillShapeBySide[side], fillColorBySide[side]);
160
+ const { wrapper, before, after } = POSITION_CLASSES[side][align];
161
+ return cn("absolute", wrapper, beforeBase, before, borderShapeBySide[side], borderColorBySide[side], afterBase, after, fillShapeBySide[side], fillColorBySide[side]);
110
162
  };
111
163
  const Popover = ({ title, placement = "top", className, content, children, open: _open, defaultOpen, onOpenChange, ...props }) => {
112
164
  const [open, setOpen] = useControllableState({
@@ -1 +1 @@
1
- {"version":3,"file":"popover.mjs","names":["popover"],"sources":["../../../src/components/atoms/popover.tsx"],"sourcesContent":["import { useControllableState } from '@jbpark/use-hooks';\n\nimport { popover } from '@repo/ui/core';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Typography from './typography';\n\nconst { Popover: CorePopover, PopoverContent, PopoverTrigger } = popover;\n\ntype Placement =\n | 'top'\n | 'left'\n | 'right'\n | 'bottom'\n | 'topLeft'\n | 'topRight'\n | 'bottomLeft'\n | 'bottomRight'\n | 'leftTop'\n | 'leftBottom'\n | 'rightTop'\n | 'rightBottom';\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'title' | 'content'\n> {\n title?: React.ReactNode;\n placement?: Placement;\n content: React.ReactNode;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\ntype Side = 'top' | 'bottom' | 'left' | 'right';\ntype Align = 'start' | 'center' | 'end';\n\nconst placementMap: Record<Placement, { side: Side; align: Align }> = {\n top: { side: 'top', align: 'center' },\n left: { side: 'left', align: 'center' },\n right: { side: 'right', align: 'center' },\n bottom: { side: 'bottom', align: 'center' },\n topLeft: { side: 'top', align: 'start' },\n topRight: { side: 'top', align: 'end' },\n bottomLeft: { side: 'bottom', align: 'start' },\n bottomRight: { side: 'bottom', align: 'end' },\n leftTop: { side: 'left', align: 'start' },\n leftBottom: { side: 'left', align: 'end' },\n rightTop: { side: 'right', align: 'start' },\n rightBottom: { side: 'right', align: 'end' },\n};\n\nconst beforeBase = 'before:content-[\"\"] before:absolute before:h-0 before:w-0';\nconst afterBase = 'after:content-[\"\"] after:absolute after:h-0 after:w-0';\n\nconst vBorderShape =\n 'before:border-l-[9px] before:border-r-[9px] before:border-l-transparent before:border-r-transparent';\nconst hBorderShape =\n 'before:border-t-[9px] before:border-b-[9px] before:border-t-transparent before:border-b-transparent';\nconst vFillShape =\n 'after:border-l-8 after:border-r-8 after:border-l-transparent after:border-r-transparent';\nconst hFillShape =\n 'after:border-t-8 after:border-b-8 after:border-t-transparent after:border-b-transparent';\n\n// Top/bottom placements draw a vertical-edge triangle (border-l/border-r) —\n// the arrow points up/down, so its left/right edges form the point. Left/\n// right placements draw the horizontal-edge equivalent.\nconst borderShapeBySide: Record<Side, string> = {\n top: vBorderShape,\n bottom: vBorderShape,\n left: hBorderShape,\n right: hBorderShape,\n};\nconst fillShapeBySide: Record<Side, string> = {\n top: vFillShape,\n bottom: vFillShape,\n left: hFillShape,\n right: hFillShape,\n};\nconst borderColorBySide: Record<Side, string> = {\n top: 'before:border-t-[9px] before:border-t-border',\n bottom: 'before:border-b-[9px] before:border-b-border',\n left: 'before:border-l-[9px] before:border-l-border',\n right: 'before:border-r-[9px] before:border-r-border',\n};\nconst fillColorBySide: Record<Side, string> = {\n top: 'after:border-t-8 after:border-t-popover',\n bottom: 'after:border-b-8 after:border-b-popover',\n left: 'after:border-l-8 after:border-l-popover',\n right: 'after:border-r-8 after:border-r-popover',\n};\n\n// `side` picks which edge of the content the arrow sits against; `align`\n// slides it along that edge. The offset axis (x for top/bottom, y for\n// left/right) is perpendicular to `side` — `align: 'center'` centers the\n// arrow with a translate, while `start`/`end` pin it 16px from that edge.\nconst offsetAxisBySide: Record<Side, 'x' | 'y'> = {\n top: 'x',\n bottom: 'x',\n left: 'y',\n right: 'y',\n};\nconst startEdgeByAxis = { x: 'left', y: 'top' } as const;\nconst endEdgeByAxis = { x: 'right', y: 'bottom' } as const;\n\nconst getArrowClassName = (side: Side, align: Align) => {\n const axis = offsetAxisBySide[side];\n const alignEdge =\n align === 'start'\n ? startEdgeByAxis[axis]\n : align === 'end'\n ? endEdgeByAxis[axis]\n : null;\n\n const positionAlign = alignEdge\n ? `${alignEdge}-4`\n : `${startEdgeByAxis[axis]}-1/2 -translate-${axis}-1/2`;\n const beforeAlign = alignEdge\n ? `before:${alignEdge}-0`\n : `before:${startEdgeByAxis[axis]}-1/2 before:-translate-${axis}-1/2`;\n const afterAlign = alignEdge\n ? `after:${alignEdge}-px`\n : `after:${startEdgeByAxis[axis]}-1/2 after:-translate-${axis}-1/2`;\n\n return cn(\n `absolute ${positionAlign} ${side}-full`,\n beforeBase,\n `before:${side}-0`,\n beforeAlign,\n borderShapeBySide[side],\n borderColorBySide[side],\n afterBase,\n `after:-${side}-px`,\n afterAlign,\n fillShapeBySide[side],\n fillColorBySide[side],\n );\n};\n\nconst Popover = ({\n title,\n placement = 'top',\n className,\n content,\n children,\n open: _open,\n defaultOpen,\n onOpenChange,\n ...props\n}: Props) => {\n const [open, setOpen] = useControllableState<boolean>({\n value: _open,\n defaultValue: defaultOpen ?? false,\n onChange: onOpenChange,\n });\n\n const { side, align } = placementMap[placement];\n\n return (\n <CorePopover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent\n {...props}\n align={align}\n side={side}\n sideOffset={16}\n className={cn('relative w-auto', className)}\n >\n {renderConditional(title, v => (\n <Typography.Title level={6}>{v}</Typography.Title>\n ))}\n {content}\n <div className={getArrowClassName(side, align)} />\n </PopoverContent>\n </CorePopover>\n );\n};\n\nexport default Popover;\n"],"mappings":";;;;;;;AAOA,MAAM,EAAE,SAAS,aAAa,gBAAgB,mBAAmBA;AA+BjE,MAAM,eAAgE;CACpE,KAAK;EAAE,MAAM;EAAO,OAAO;EAAU;CACrC,MAAM;EAAE,MAAM;EAAQ,OAAO;EAAU;CACvC,OAAO;EAAE,MAAM;EAAS,OAAO;EAAU;CACzC,QAAQ;EAAE,MAAM;EAAU,OAAO;EAAU;CAC3C,SAAS;EAAE,MAAM;EAAO,OAAO;EAAS;CACxC,UAAU;EAAE,MAAM;EAAO,OAAO;EAAO;CACvC,YAAY;EAAE,MAAM;EAAU,OAAO;EAAS;CAC9C,aAAa;EAAE,MAAM;EAAU,OAAO;EAAO;CAC7C,SAAS;EAAE,MAAM;EAAQ,OAAO;EAAS;CACzC,YAAY;EAAE,MAAM;EAAQ,OAAO;EAAO;CAC1C,UAAU;EAAE,MAAM;EAAS,OAAO;EAAS;CAC3C,aAAa;EAAE,MAAM;EAAS,OAAO;EAAO;CAC7C;AAED,MAAM,aAAa;AACnB,MAAM,YAAY;AAElB,MAAM,eACJ;AACF,MAAM,eACJ;AACF,MAAM,aACJ;AACF,MAAM,aACJ;AAKF,MAAM,oBAA0C;CAC9C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AACD,MAAM,kBAAwC;CAC5C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AACD,MAAM,oBAA0C;CAC9C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AACD,MAAM,kBAAwC;CAC5C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AAMD,MAAM,mBAA4C;CAChD,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AACD,MAAM,kBAAkB;CAAE,GAAG;CAAQ,GAAG;CAAO;AAC/C,MAAM,gBAAgB;CAAE,GAAG;CAAS,GAAG;CAAU;AAEjD,MAAM,qBAAqB,MAAY,UAAiB;CACtD,MAAM,OAAO,iBAAiB;CAC9B,MAAM,YACJ,UAAU,UACN,gBAAgB,QAChB,UAAU,QACR,cAAc,QACd;CAER,MAAM,gBAAgB,YAClB,GAAG,UAAU,MACb,GAAG,gBAAgB,MAAM,kBAAkB,KAAK;CACpD,MAAM,cAAc,YAChB,UAAU,UAAU,MACpB,UAAU,gBAAgB,MAAM,yBAAyB,KAAK;CAClE,MAAM,aAAa,YACf,SAAS,UAAU,OACnB,SAAS,gBAAgB,MAAM,wBAAwB,KAAK;AAEhE,QAAO,GACL,YAAY,cAAc,GAAG,KAAK,QAClC,YACA,UAAU,KAAK,KACf,aACA,kBAAkB,OAClB,kBAAkB,OAClB,WACA,UAAU,KAAK,MACf,YACA,gBAAgB,OAChB,gBAAgB,MACjB;;AAGH,MAAM,WAAW,EACf,OACA,YAAY,OACZ,WACA,SACA,UACA,MAAM,OACN,aACA,cACA,GAAG,YACQ;CACX,MAAM,CAAC,MAAM,WAAW,qBAA8B;EACpD,OAAO;EACP,cAAc,eAAe;EAC7B,UAAU;EACX,CAAC;CAEF,MAAM,EAAE,MAAM,UAAU,aAAa;AAErC,QACE,qBAAC;EAAkB;EAAM,cAAc;aACrC,oBAAC;GAAe;GAAS;IAA0B,EACnD,qBAAC;GACC,GAAI;GACG;GACD;GACN,YAAY;GACZ,WAAW,GAAG,mBAAmB,UAAU;;IAE1C,kBAAkB,QAAO,MACxB,oBAAC,WAAW;KAAM,OAAO;eAAI;MAAqB,CAClD;IACD;IACD,oBAAC,SAAI,WAAW,kBAAkB,MAAM,MAAM,GAAI;;IACnC;GACL"}
1
+ {"version":3,"file":"popover.mjs","names":["popover"],"sources":["../../../src/components/atoms/popover.tsx"],"sourcesContent":["import { useControllableState } from '@jbpark/use-hooks';\n\nimport { popover } from '@repo/ui/core';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Typography from './typography';\n\nconst { Popover: CorePopover, PopoverContent, PopoverTrigger } = popover;\n\ntype Placement =\n | 'top'\n | 'left'\n | 'right'\n | 'bottom'\n | 'topLeft'\n | 'topRight'\n | 'bottomLeft'\n | 'bottomRight'\n | 'leftTop'\n | 'leftBottom'\n | 'rightTop'\n | 'rightBottom';\n\nexport interface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'title' | 'content'\n> {\n title?: React.ReactNode;\n placement?: Placement;\n content: React.ReactNode;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n}\n\ntype Side = 'top' | 'bottom' | 'left' | 'right';\ntype Align = 'start' | 'center' | 'end';\n\nconst placementMap: Record<Placement, { side: Side; align: Align }> = {\n top: { side: 'top', align: 'center' },\n left: { side: 'left', align: 'center' },\n right: { side: 'right', align: 'center' },\n bottom: { side: 'bottom', align: 'center' },\n topLeft: { side: 'top', align: 'start' },\n topRight: { side: 'top', align: 'end' },\n bottomLeft: { side: 'bottom', align: 'start' },\n bottomRight: { side: 'bottom', align: 'end' },\n leftTop: { side: 'left', align: 'start' },\n leftBottom: { side: 'left', align: 'end' },\n rightTop: { side: 'right', align: 'start' },\n rightBottom: { side: 'right', align: 'end' },\n};\n\nconst beforeBase = 'before:content-[\"\"] before:absolute before:h-0 before:w-0';\nconst afterBase = 'after:content-[\"\"] after:absolute after:h-0 after:w-0';\n\nconst vBorderShape =\n 'before:border-l-[9px] before:border-r-[9px] before:border-l-transparent before:border-r-transparent';\nconst hBorderShape =\n 'before:border-t-[9px] before:border-b-[9px] before:border-t-transparent before:border-b-transparent';\nconst vFillShape =\n 'after:border-l-8 after:border-r-8 after:border-l-transparent after:border-r-transparent';\nconst hFillShape =\n 'after:border-t-8 after:border-b-8 after:border-t-transparent after:border-b-transparent';\n\n// Top/bottom placements draw a vertical-edge triangle (border-l/border-r) —\n// the arrow points up/down, so its left/right edges form the point. Left/\n// right placements draw the horizontal-edge equivalent.\nconst borderShapeBySide: Record<Side, string> = {\n top: vBorderShape,\n bottom: vBorderShape,\n left: hBorderShape,\n right: hBorderShape,\n};\nconst fillShapeBySide: Record<Side, string> = {\n top: vFillShape,\n bottom: vFillShape,\n left: hFillShape,\n right: hFillShape,\n};\nconst borderColorBySide: Record<Side, string> = {\n top: 'before:border-t-[9px] before:border-t-border',\n bottom: 'before:border-b-[9px] before:border-b-border',\n left: 'before:border-l-[9px] before:border-l-border',\n right: 'before:border-r-[9px] before:border-r-border',\n};\nconst fillColorBySide: Record<Side, string> = {\n top: 'after:border-t-8 after:border-t-popover',\n bottom: 'after:border-b-8 after:border-b-popover',\n left: 'after:border-l-8 after:border-l-popover',\n right: 'after:border-r-8 after:border-r-popover',\n};\n\n// Tailwind v4 only extracts class candidates that appear as *literal*\n// strings in source — none of these ever do if built via\n// `` `${side}-full` `` style interpolation, so they'd silently never make\n// it into the generated CSS. This table exists purely so every class the\n// arrow can need appears literally somewhere in this file.\nconst POSITION_CLASSES: Record<\n Side,\n Record<Align, { wrapper: string; before: string; after: string }>\n> = {\n top: {\n start: {\n wrapper: 'top-full left-4',\n before: 'before:top-0 before:left-0',\n after: 'after:-top-px after:left-px',\n },\n center: {\n wrapper: 'top-full left-1/2 -translate-x-1/2',\n before: 'before:top-0 before:left-1/2 before:-translate-x-1/2',\n after: 'after:-top-px after:left-1/2 after:-translate-x-1/2',\n },\n end: {\n wrapper: 'top-full right-4',\n before: 'before:top-0 before:right-0',\n after: 'after:-top-px after:right-px',\n },\n },\n bottom: {\n start: {\n wrapper: 'bottom-full left-4',\n before: 'before:bottom-0 before:left-0',\n after: 'after:-bottom-px after:left-px',\n },\n center: {\n wrapper: 'bottom-full left-1/2 -translate-x-1/2',\n before: 'before:bottom-0 before:left-1/2 before:-translate-x-1/2',\n after: 'after:-bottom-px after:left-1/2 after:-translate-x-1/2',\n },\n end: {\n wrapper: 'bottom-full right-4',\n before: 'before:bottom-0 before:right-0',\n after: 'after:-bottom-px after:right-px',\n },\n },\n left: {\n start: {\n wrapper: 'left-full top-4',\n before: 'before:left-0 before:top-0',\n after: 'after:-left-px after:top-px',\n },\n center: {\n wrapper: 'left-full top-1/2 -translate-y-1/2',\n before: 'before:left-0 before:top-1/2 before:-translate-y-1/2',\n after: 'after:-left-px after:top-1/2 after:-translate-y-1/2',\n },\n end: {\n wrapper: 'left-full bottom-4',\n before: 'before:left-0 before:bottom-0',\n after: 'after:-left-px after:bottom-px',\n },\n },\n right: {\n start: {\n wrapper: 'right-full top-4',\n before: 'before:right-0 before:top-0',\n after: 'after:-right-px after:top-px',\n },\n center: {\n wrapper: 'right-full top-1/2 -translate-y-1/2',\n before: 'before:right-0 before:top-1/2 before:-translate-y-1/2',\n after: 'after:-right-px after:top-1/2 after:-translate-y-1/2',\n },\n end: {\n wrapper: 'right-full bottom-4',\n before: 'before:right-0 before:bottom-0',\n after: 'after:-right-px after:bottom-px',\n },\n },\n};\n\nconst getArrowClassName = (side: Side, align: Align) => {\n const { wrapper, before, after } = POSITION_CLASSES[side][align];\n\n return cn(\n 'absolute',\n wrapper,\n beforeBase,\n before,\n borderShapeBySide[side],\n borderColorBySide[side],\n afterBase,\n after,\n fillShapeBySide[side],\n fillColorBySide[side],\n );\n};\n\nconst Popover = ({\n title,\n placement = 'top',\n className,\n content,\n children,\n open: _open,\n defaultOpen,\n onOpenChange,\n ...props\n}: Props) => {\n const [open, setOpen] = useControllableState<boolean>({\n value: _open,\n defaultValue: defaultOpen ?? false,\n onChange: onOpenChange,\n });\n\n const { side, align } = placementMap[placement];\n\n return (\n <CorePopover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent\n {...props}\n align={align}\n side={side}\n sideOffset={16}\n className={cn('relative w-auto', className)}\n >\n {renderConditional(title, v => (\n <Typography.Title level={6}>{v}</Typography.Title>\n ))}\n {content}\n <div className={getArrowClassName(side, align)} />\n </PopoverContent>\n </CorePopover>\n );\n};\n\nexport default Popover;\n"],"mappings":";;;;;;;AAOA,MAAM,EAAE,SAAS,aAAa,gBAAgB,mBAAmBA;AA+BjE,MAAM,eAAgE;CACpE,KAAK;EAAE,MAAM;EAAO,OAAO;EAAU;CACrC,MAAM;EAAE,MAAM;EAAQ,OAAO;EAAU;CACvC,OAAO;EAAE,MAAM;EAAS,OAAO;EAAU;CACzC,QAAQ;EAAE,MAAM;EAAU,OAAO;EAAU;CAC3C,SAAS;EAAE,MAAM;EAAO,OAAO;EAAS;CACxC,UAAU;EAAE,MAAM;EAAO,OAAO;EAAO;CACvC,YAAY;EAAE,MAAM;EAAU,OAAO;EAAS;CAC9C,aAAa;EAAE,MAAM;EAAU,OAAO;EAAO;CAC7C,SAAS;EAAE,MAAM;EAAQ,OAAO;EAAS;CACzC,YAAY;EAAE,MAAM;EAAQ,OAAO;EAAO;CAC1C,UAAU;EAAE,MAAM;EAAS,OAAO;EAAS;CAC3C,aAAa;EAAE,MAAM;EAAS,OAAO;EAAO;CAC7C;AAED,MAAM,aAAa;AACnB,MAAM,YAAY;AAElB,MAAM,eACJ;AACF,MAAM,eACJ;AACF,MAAM,aACJ;AACF,MAAM,aACJ;AAKF,MAAM,oBAA0C;CAC9C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AACD,MAAM,kBAAwC;CAC5C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AACD,MAAM,oBAA0C;CAC9C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AACD,MAAM,kBAAwC;CAC5C,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACR;AAOD,MAAM,mBAGF;CACF,KAAK;EACH,OAAO;GACL,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACD,QAAQ;GACN,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACD,KAAK;GACH,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACF;CACD,QAAQ;EACN,OAAO;GACL,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACD,QAAQ;GACN,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACD,KAAK;GACH,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACF;CACD,MAAM;EACJ,OAAO;GACL,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACD,QAAQ;GACN,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACD,KAAK;GACH,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACF;CACD,OAAO;EACL,OAAO;GACL,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACD,QAAQ;GACN,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACD,KAAK;GACH,SAAS;GACT,QAAQ;GACR,OAAO;GACR;EACF;CACF;AAED,MAAM,qBAAqB,MAAY,UAAiB;CACtD,MAAM,EAAE,SAAS,QAAQ,UAAU,iBAAiB,MAAM;AAE1D,QAAO,GACL,YACA,SACA,YACA,QACA,kBAAkB,OAClB,kBAAkB,OAClB,WACA,OACA,gBAAgB,OAChB,gBAAgB,MACjB;;AAGH,MAAM,WAAW,EACf,OACA,YAAY,OACZ,WACA,SACA,UACA,MAAM,OACN,aACA,cACA,GAAG,YACQ;CACX,MAAM,CAAC,MAAM,WAAW,qBAA8B;EACpD,OAAO;EACP,cAAc,eAAe;EAC7B,UAAU;EACX,CAAC;CAEF,MAAM,EAAE,MAAM,UAAU,aAAa;AAErC,QACE,qBAAC;EAAkB;EAAM,cAAc;aACrC,oBAAC;GAAe;GAAS;IAA0B,EACnD,qBAAC;GACC,GAAI;GACG;GACD;GACN,YAAY;GACZ,WAAW,GAAG,mBAAmB,UAAU;;IAE1C,kBAAkB,QAAO,MACxB,oBAAC,WAAW;KAAM,OAAO;eAAI;MAAqB,CAClD;IACD;IACD,oBAAC,SAAI,WAAW,kBAAkB,MAAM,MAAM,GAAI;;IACnC;GACL"}
@@ -3,7 +3,7 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/atoms/skeleton/button.d.ts
5
5
  declare const Button: ({
6
- className,
6
+ classNames,
7
7
  ...props
8
8
  }: Props) => react_jsx_runtime0.JSX.Element;
9
9
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.mts","names":[],"sources":["../../../../src/components/atoms/skeleton/button.tsx"],"mappings":";;;;cAIM,MAAA;EAAU,SAAA;EAAA,GAAA;AAAA,GAAyB,KAAA,KAAa,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"button.d.mts","names":[],"sources":["../../../../src/components/atoms/skeleton/button.tsx"],"mappings":";;;;cAIM,MAAA;EAAU,UAAA;EAAA,GAAA;AAAA,GAA0B,KAAA,KAAa,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -3,10 +3,13 @@ import Skeleton from "./skeleton.mjs";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
 
5
5
  //#region src/components/atoms/skeleton/button.tsx
6
- const Button = ({ className, ...props }) => {
6
+ const Button = ({ classNames, ...props }) => {
7
7
  return /* @__PURE__ */ jsx(Skeleton, {
8
8
  ...props,
9
- className: cn("h-9 w-15", "rounded-2xl", className)
9
+ classNames: {
10
+ ...classNames,
11
+ item: cn("h-9 w-15", "rounded-2xl", classNames?.item)
12
+ }
10
13
  });
11
14
  };
12
15
 
@@ -1 +1 @@
1
- {"version":3,"file":"button.mjs","names":[],"sources":["../../../../src/components/atoms/skeleton/button.tsx"],"sourcesContent":["import { cn } from '@repo/ui/utils';\n\nimport Skeleton, { type Props as SkeletonProps } from './skeleton';\n\nconst Button = ({ className, ...props }: SkeletonProps) => {\n return (\n <Skeleton\n {...props}\n className={cn(\n 'h-9 w-15',\n 'rounded-2xl',\n className,\n //\n )}\n />\n );\n};\nexport default Button;\n"],"mappings":";;;;;AAIA,MAAM,UAAU,EAAE,WAAW,GAAG,YAA2B;AACzD,QACE,oBAAC;EACC,GAAI;EACJ,WAAW,GACT,YACA,eACA,UAED;GACD"}
1
+ {"version":3,"file":"button.mjs","names":[],"sources":["../../../../src/components/atoms/skeleton/button.tsx"],"sourcesContent":["import { cn } from '@repo/ui/utils';\n\nimport Skeleton, { type Props as SkeletonProps } from './skeleton';\n\nconst Button = ({ classNames, ...props }: SkeletonProps) => {\n return (\n <Skeleton\n {...props}\n classNames={{\n ...classNames,\n item: cn(\n 'h-9 w-15',\n 'rounded-2xl',\n classNames?.item,\n //\n ),\n }}\n />\n );\n};\nexport default Button;\n"],"mappings":";;;;;AAIA,MAAM,UAAU,EAAE,YAAY,GAAG,YAA2B;AAC1D,QACE,oBAAC;EACC,GAAI;EACJ,YAAY;GACV,GAAG;GACH,MAAM,GACJ,YACA,eACA,YAAY,KAEb;GACF;GACD"}
@@ -3,7 +3,7 @@ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/atoms/skeleton/node.d.ts
5
5
  declare const Node: ({
6
- className,
6
+ classNames,
7
7
  ...props
8
8
  }: Props) => react_jsx_runtime0.JSX.Element;
9
9
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.mts","names":[],"sources":["../../../../src/components/atoms/skeleton/node.tsx"],"mappings":";;;;cAIM,IAAA;EAAQ,SAAA;EAAA,GAAA;AAAA,GAAyB,KAAA,KAAa,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"node.d.mts","names":[],"sources":["../../../../src/components/atoms/skeleton/node.tsx"],"mappings":";;;;cAIM,IAAA;EAAQ,UAAA;EAAA,GAAA;AAAA,GAA0B,KAAA,KAAa,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -3,11 +3,14 @@ import Skeleton from "./skeleton.mjs";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
 
5
5
  //#region src/components/atoms/skeleton/node.tsx
6
- const Node = ({ className, ...props }) => {
6
+ const Node = ({ classNames, ...props }) => {
7
7
  return /* @__PURE__ */ jsx(Skeleton, {
8
8
  ...props,
9
9
  avatar: false,
10
- className: cn("h-50 w-full min-w-80", "rounded-3xl", className)
10
+ classNames: {
11
+ ...classNames,
12
+ item: cn("h-50 w-full min-w-80", "rounded-3xl", classNames?.item)
13
+ }
11
14
  });
12
15
  };
13
16
 
@@ -1 +1 @@
1
- {"version":3,"file":"node.mjs","names":[],"sources":["../../../../src/components/atoms/skeleton/node.tsx"],"sourcesContent":["import { cn } from '@repo/ui/utils';\n\nimport Skeleton, { type Props as SkeletonProps } from './skeleton';\n\nconst Node = ({ className, ...props }: SkeletonProps) => {\n return (\n <Skeleton\n {...props}\n avatar={false}\n className={cn(\n 'h-50 w-full min-w-80',\n 'rounded-3xl',\n className,\n //\n )}\n />\n );\n};\nexport default Node;\n"],"mappings":";;;;;AAIA,MAAM,QAAQ,EAAE,WAAW,GAAG,YAA2B;AACvD,QACE,oBAAC;EACC,GAAI;EACJ,QAAQ;EACR,WAAW,GACT,wBACA,eACA,UAED;GACD"}
1
+ {"version":3,"file":"node.mjs","names":[],"sources":["../../../../src/components/atoms/skeleton/node.tsx"],"sourcesContent":["import { cn } from '@repo/ui/utils';\n\nimport Skeleton, { type Props as SkeletonProps } from './skeleton';\n\nconst Node = ({ classNames, ...props }: SkeletonProps) => {\n return (\n <Skeleton\n {...props}\n avatar={false}\n classNames={{\n ...classNames,\n item: cn(\n 'h-50 w-full min-w-80',\n 'rounded-3xl',\n classNames?.item,\n //\n ),\n }}\n />\n );\n};\nexport default Node;\n"],"mappings":";;;;;AAIA,MAAM,QAAQ,EAAE,YAAY,GAAG,YAA2B;AACxD,QACE,oBAAC;EACC,GAAI;EACJ,QAAQ;EACR,YAAY;GACV,GAAG;GACH,MAAM,GACJ,wBACA,eACA,YAAY,KAEb;GACF;GACD"}
@@ -26,7 +26,7 @@ const Collapse = ({ expandIcon, accordion = false, items = [], className, classN
26
26
  ...props,
27
27
  className,
28
28
  ...accordionProps,
29
- children: items.map(({ label, children, disabled }, key) => /* @__PURE__ */ jsxs(AccordionItem, {
29
+ children: items.map(({ key, label, children, disabled }) => /* @__PURE__ */ jsxs(AccordionItem, {
30
30
  value: `${key}`,
31
31
  className: cn("border-none", classNames?.item),
32
32
  disabled,
@@ -1 +1 @@
1
- {"version":3,"file":"collapse.mjs","names":["accordion"],"sources":["../../../src/components/molecules/collapse.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { accordion } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nconst { Accordion, AccordionItem, AccordionTrigger, AccordionContent } =\n accordion;\n\ninterface Item {\n key: React.Key;\n label: React.ReactNode;\n disabled?: boolean;\n children: React.ReactNode;\n}\n\ninterface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'onChange' | 'defaultValue' | 'value' | 'dir'\n> {\n items?: Item[];\n accordion?: boolean;\n expandIcon?: React.ReactNode;\n classNames?: {\n item?: string;\n header?: string;\n body?: string;\n };\n defaultActiveKey?: string[] | number[];\n activeKey?: string[] | number[];\n onChange?: (keys: string[]) => void;\n}\n\nconst Collapse = ({\n expandIcon,\n accordion = false,\n items = [],\n className,\n classNames,\n defaultActiveKey,\n activeKey: _activeKey,\n onChange: _onChange,\n ...props\n}: Props) => {\n const controlled = _activeKey !== undefined;\n\n const accordionProps = accordion\n ? {\n type: 'single' as const,\n onValueChange: (value: string) => {\n _onChange?.(value ? [value] : []);\n },\n ...(controlled\n ? { value: `${_activeKey?.[0] ?? ''}` }\n : { defaultValue: `${defaultActiveKey?.[0] ?? ''}` }),\n }\n : {\n type: 'multiple' as const,\n onValueChange: (values: string[]) => {\n _onChange?.(values);\n },\n ...(controlled\n ? { value: _activeKey?.map(key => `${key}`) }\n : { defaultValue: defaultActiveKey?.map(key => `${key}`) }),\n };\n\n return (\n <Accordion {...props} className={className} {...accordionProps}>\n {items.map(({ label, children, disabled }, key) => (\n <AccordionItem\n key={key}\n value={`${key}`}\n className={cn(\n 'border-none',\n classNames?.item,\n //\n )}\n disabled={disabled}\n >\n <AccordionTrigger\n className={cn(\n 'hover:no-underline',\n classNames?.header,\n disabled && 'cursor-no-drop opacity-50',\n //\n )}\n expandIcon={expandIcon}\n disabled={disabled}\n >\n {label}\n </AccordionTrigger>\n <AccordionContent\n className={cn(\n classNames?.body,\n //\n )}\n >\n {children}\n </AccordionContent>\n </AccordionItem>\n ))}\n </Accordion>\n );\n};\n\nexport default Collapse;\n"],"mappings":";;;;;;;;AAOA,MAAM,EAAE,WAAW,eAAe,kBAAkB,qBAClDA;AA0BF,MAAM,YAAY,EAChB,YACA,YAAY,OACZ,QAAQ,EAAE,EACV,WACA,YACA,kBACA,WAAW,YACX,UAAU,WACV,GAAG,YACQ;CACX,MAAM,aAAa,eAAe;CAElC,MAAM,iBAAiB,YACnB;EACE,MAAM;EACN,gBAAgB,UAAkB;AAChC,eAAY,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC;;EAEnC,GAAI,aACA,EAAE,OAAO,GAAG,aAAa,MAAM,MAAM,GACrC,EAAE,cAAc,GAAG,mBAAmB,MAAM,MAAM;EACvD,GACD;EACE,MAAM;EACN,gBAAgB,WAAqB;AACnC,eAAY,OAAO;;EAErB,GAAI,aACA,EAAE,OAAO,YAAY,KAAI,QAAO,GAAG,MAAM,EAAE,GAC3C,EAAE,cAAc,kBAAkB,KAAI,QAAO,GAAG,MAAM,EAAE;EAC7D;AAEL,QACE,oBAAC;EAAU,GAAI;EAAkB;EAAW,GAAI;YAC7C,MAAM,KAAK,EAAE,OAAO,UAAU,YAAY,QACzC,qBAAC;GAEC,OAAO,GAAG;GACV,WAAW,GACT,eACA,YAAY,KAEb;GACS;cAEV,oBAAC;IACC,WAAW,GACT,sBACA,YAAY,QACZ,YAAY,4BAEb;IACW;IACF;cAET;KACgB,EACnB,oBAAC;IACC,WAAW,GACT,YAAY,KAEb;IAEA;KACgB;KA5Bd,IA6BS,CAChB;GACQ"}
1
+ {"version":3,"file":"collapse.mjs","names":["accordion"],"sources":["../../../src/components/molecules/collapse.tsx"],"sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport { accordion } from '@repo/ui/core';\nimport { cn } from '@repo/ui/utils';\n\nconst { Accordion, AccordionItem, AccordionTrigger, AccordionContent } =\n accordion;\n\ninterface Item {\n key: React.Key;\n label: React.ReactNode;\n disabled?: boolean;\n children: React.ReactNode;\n}\n\ninterface Props extends Omit<\n React.ComponentPropsWithoutRef<'div'>,\n 'onChange' | 'defaultValue' | 'value' | 'dir'\n> {\n items?: Item[];\n accordion?: boolean;\n expandIcon?: React.ReactNode;\n classNames?: {\n item?: string;\n header?: string;\n body?: string;\n };\n defaultActiveKey?: string[] | number[];\n activeKey?: string[] | number[];\n onChange?: (keys: string[]) => void;\n}\n\nconst Collapse = ({\n expandIcon,\n accordion = false,\n items = [],\n className,\n classNames,\n defaultActiveKey,\n activeKey: _activeKey,\n onChange: _onChange,\n ...props\n}: Props) => {\n const controlled = _activeKey !== undefined;\n\n const accordionProps = accordion\n ? {\n type: 'single' as const,\n onValueChange: (value: string) => {\n _onChange?.(value ? [value] : []);\n },\n ...(controlled\n ? { value: `${_activeKey?.[0] ?? ''}` }\n : { defaultValue: `${defaultActiveKey?.[0] ?? ''}` }),\n }\n : {\n type: 'multiple' as const,\n onValueChange: (values: string[]) => {\n _onChange?.(values);\n },\n ...(controlled\n ? { value: _activeKey?.map(key => `${key}`) }\n : { defaultValue: defaultActiveKey?.map(key => `${key}`) }),\n };\n\n return (\n <Accordion {...props} className={className} {...accordionProps}>\n {items.map(({ key, label, children, disabled }) => (\n <AccordionItem\n key={key}\n value={`${key}`}\n className={cn(\n 'border-none',\n classNames?.item,\n //\n )}\n disabled={disabled}\n >\n <AccordionTrigger\n className={cn(\n 'hover:no-underline',\n classNames?.header,\n disabled && 'cursor-no-drop opacity-50',\n //\n )}\n expandIcon={expandIcon}\n disabled={disabled}\n >\n {label}\n </AccordionTrigger>\n <AccordionContent\n className={cn(\n classNames?.body,\n //\n )}\n >\n {children}\n </AccordionContent>\n </AccordionItem>\n ))}\n </Accordion>\n );\n};\n\nexport default Collapse;\n"],"mappings":";;;;;;;;AAOA,MAAM,EAAE,WAAW,eAAe,kBAAkB,qBAClDA;AA0BF,MAAM,YAAY,EAChB,YACA,YAAY,OACZ,QAAQ,EAAE,EACV,WACA,YACA,kBACA,WAAW,YACX,UAAU,WACV,GAAG,YACQ;CACX,MAAM,aAAa,eAAe;CAElC,MAAM,iBAAiB,YACnB;EACE,MAAM;EACN,gBAAgB,UAAkB;AAChC,eAAY,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC;;EAEnC,GAAI,aACA,EAAE,OAAO,GAAG,aAAa,MAAM,MAAM,GACrC,EAAE,cAAc,GAAG,mBAAmB,MAAM,MAAM;EACvD,GACD;EACE,MAAM;EACN,gBAAgB,WAAqB;AACnC,eAAY,OAAO;;EAErB,GAAI,aACA,EAAE,OAAO,YAAY,KAAI,QAAO,GAAG,MAAM,EAAE,GAC3C,EAAE,cAAc,kBAAkB,KAAI,QAAO,GAAG,MAAM,EAAE;EAC7D;AAEL,QACE,oBAAC;EAAU,GAAI;EAAkB;EAAW,GAAI;YAC7C,MAAM,KAAK,EAAE,KAAK,OAAO,UAAU,eAClC,qBAAC;GAEC,OAAO,GAAG;GACV,WAAW,GACT,eACA,YAAY,KAEb;GACS;cAEV,oBAAC;IACC,WAAW,GACT,sBACA,YAAY,QACZ,YAAY,4BAEb;IACW;IACF;cAET;KACgB,EACnB,oBAAC;IACC,WAAW,GACT,YAAY,KAEb;IAEA;KACgB;KA5Bd,IA6BS,CAChB;GACQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"item.d.mts","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"mappings":";;;UAQiB,SAAA;EACf,GAAA,GAAM,KAAA,CAAM,GAAA;EACZ,KAAA;EACA,QAAA;EACA,KAAA;EACA,YAAA;EACA,QAAA,GAAW,KAAA,CAAM,SAAA;AAAA;AAAA,UAGF,KAAA,SACP,IAAA,CAAK,KAAA,CAAM,wBAAA,iBAAyC,SAAA;EAC5D,KAAA;AAAA;AAAA,cAGI,IAAA;EAAQ,KAAA,EAAA,MAAA;EAAA,KAAA;EAAA,QAAA;EAAA,KAAA,EAAA,MAAA;EAAA,YAAA;EAAA;AAAA,GAOX,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"item.d.mts","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"mappings":";;;UAOiB,SAAA;EACf,GAAA,GAAM,KAAA,CAAM,GAAA;EACZ,KAAA;EACA,QAAA;EACA,KAAA;EACA,YAAA;EACA,QAAA,GAAW,KAAA,CAAM,SAAA;AAAA;AAAA,UAGF,KAAA,SACP,IAAA,CAAK,KAAA,CAAM,wBAAA,iBAAyC,SAAA;EAC5D,KAAA;AAAA;AAAA,cAYI,IAAA;EAAQ,KAAA,EAAA,MAAA;EAAA,KAAA;EAAA,QAAA;EAAA,KAAA,EAAA,MAAA;EAAA,YAAA;EAAA;AAAA,GAOX,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -2,18 +2,18 @@
2
2
 
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
- import { useEventListener } from "@jbpark/use-hooks";
6
5
  import { useGSAP } from "@gsap/react";
7
6
  import { gsap } from "gsap";
8
7
 
9
8
  //#region src/components/molecules/marquees/item.tsx
9
+ const INITIAL_AUTO_FILL_GUESS = 10;
10
10
  const Item = ({ width: _width, speed = 100, autoFill = false, pause: _pause = false, pauseOnHover = false, children }) => {
11
11
  const itemRefs = useRef([]);
12
12
  const containerRef = useRef(null);
13
13
  const tweenRef = useRef(null);
14
14
  const [width, setWidth] = useState(_width);
15
15
  const [pause, setPause] = useState(false);
16
- const [repeatCount, setRepeatCount] = useState(autoFill ? typeof autoFill === "boolean" ? 100 : autoFill : 0);
16
+ const [repeatCount, setRepeatCount] = useState(autoFill ? typeof autoFill === "boolean" ? INITIAL_AUTO_FILL_GUESS : autoFill : 0);
17
17
  const isPaused = _pause || pause;
18
18
  const hoverEvents = pauseOnHover ? {
19
19
  onMouseEnter: () => {
@@ -69,13 +69,8 @@ const Item = ({ width: _width, speed = 100, autoFill = false, pause: _pause = fa
69
69
  else tweenRef.current.play();
70
70
  }, [isPaused]);
71
71
  useEffect(() => {
72
- setRepeatCount(autoFill ? typeof autoFill === "boolean" ? 100 : autoFill : 0);
72
+ setRepeatCount(autoFill ? typeof autoFill === "boolean" ? INITIAL_AUTO_FILL_GUESS : autoFill : 0);
73
73
  }, [autoFill]);
74
- useEventListener("resize", () => {
75
- if (!tweenRef.current || !containerRef.current) return;
76
- if (isPaused) tweenRef.current.pause();
77
- else tweenRef.current.play();
78
- });
79
74
  return /* @__PURE__ */ jsx("div", {
80
75
  className: "flex overflow-hidden",
81
76
  ...hoverEvents,
@@ -1 +1 @@
1
- {"version":3,"file":"item.mjs","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useGSAP } from '@gsap/react';\nimport { useEventListener } from '@jbpark/use-hooks';\nimport { gsap } from 'gsap';\n\nexport interface ItemProps {\n key?: React.Key;\n speed?: number;\n autoFill?: boolean | number;\n pause?: boolean;\n pauseOnHover?: boolean;\n children?: React.ReactNode;\n}\n\nexport interface Props\n extends Omit<React.ComponentPropsWithoutRef<'div'>, 'key'>, ItemProps {\n width: string | number;\n}\n\nconst Item = ({\n width: _width,\n speed = 100,\n autoFill = false,\n pause: _pause = false,\n pauseOnHover = false,\n children,\n}: Props) => {\n const itemRefs = useRef<HTMLDivElement[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n const tweenRef = useRef<gsap.core.Tween | null>(null);\n\n const [width, setWidth] = useState<string | number>(_width);\n const [pause, setPause] = useState(false);\n const [repeatCount, setRepeatCount] = useState(\n autoFill ? (typeof autoFill === 'boolean' ? 100 : autoFill) : 0,\n );\n\n const isPaused = _pause || pause;\n\n const hoverEvents = pauseOnHover\n ? {\n onMouseEnter: () => {\n setPause(true);\n },\n onMouseLeave: () => {\n setPause(false);\n },\n }\n : {};\n\n useEffect(() => {\n if (\n !autoFill ||\n !children ||\n !itemRefs.current[0] ||\n typeof width === 'string'\n ) {\n return;\n }\n\n const itemWidth = itemRefs.current[0].offsetWidth;\n\n if (itemWidth >= width) {\n setWidth(itemWidth);\n setRepeatCount(0);\n return;\n }\n\n let totalWidth = 0;\n let repeatCount = 0;\n\n while (totalWidth < width) {\n totalWidth += itemWidth;\n repeatCount += 1;\n }\n\n setWidth(totalWidth);\n setRepeatCount(repeatCount - 1);\n }, [autoFill, width, children]);\n\n useEffect(() => {\n setWidth(_width);\n }, [_width]);\n\n useGSAP(\n () => {\n if (!containerRef.current || typeof width === 'string') {\n return;\n }\n\n if (tweenRef.current) {\n tweenRef.current.kill();\n }\n\n tweenRef.current = gsap.fromTo(\n containerRef.current,\n { x: 0 },\n {\n x: -width,\n duration: width / speed,\n repeat: -1,\n ease: 'linear',\n },\n );\n\n return () => {\n tweenRef.current?.kill();\n };\n },\n {\n scope: containerRef,\n dependencies: [width, speed],\n },\n );\n\n useEffect(() => {\n if (!tweenRef.current) {\n return;\n }\n\n if (isPaused) {\n tweenRef.current.pause();\n } else {\n tweenRef.current.play();\n }\n }, [isPaused]);\n\n useEffect(() => {\n setRepeatCount(\n autoFill ? (typeof autoFill === 'boolean' ? 100 : autoFill) : 0,\n );\n }, [autoFill]);\n\n useEventListener('resize', () => {\n if (!tweenRef.current || !containerRef.current) {\n return;\n }\n\n if (isPaused) {\n tweenRef.current.pause();\n } else {\n tweenRef.current.play();\n }\n });\n\n return (\n <div\n className=\"flex overflow-hidden\"\n {...hoverEvents}\n //\n >\n <div ref={containerRef} className=\"flex flex-nowrap\">\n {[...Array(2)].map((_, index) => (\n <div\n key={index}\n style={{ minWidth: width }}\n className=\"flex flex-nowrap\"\n >\n <div\n ref={el => {\n if (el) {\n itemRefs.current[index] = el;\n }\n }}\n >\n {children}\n </div>\n {[\n ...Array(typeof autoFill === 'number' ? autoFill : repeatCount),\n ].map((_, i) => (\n <div key={i}>{children}</div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Item;\n"],"mappings":";;;;;;;;;AAsBA,MAAM,QAAQ,EACZ,OAAO,QACP,QAAQ,KACR,WAAW,OACX,OAAO,SAAS,OAChB,eAAe,OACf,eACW;CACX,MAAM,WAAW,OAAyB,EAAE,CAAC;CAC7C,MAAM,eAAe,OAAuB,KAAK;CACjD,MAAM,WAAW,OAA+B,KAAK;CAErD,MAAM,CAAC,OAAO,YAAY,SAA0B,OAAO;CAC3D,MAAM,CAAC,OAAO,YAAY,SAAS,MAAM;CACzC,MAAM,CAAC,aAAa,kBAAkB,SACpC,WAAY,OAAO,aAAa,YAAY,MAAM,WAAY,EAC/D;CAED,MAAM,WAAW,UAAU;CAE3B,MAAM,cAAc,eAChB;EACE,oBAAoB;AAClB,YAAS,KAAK;;EAEhB,oBAAoB;AAClB,YAAS,MAAM;;EAElB,GACD,EAAE;AAEN,iBAAgB;AACd,MACE,CAAC,YACD,CAAC,YACD,CAAC,SAAS,QAAQ,MAClB,OAAO,UAAU,SAEjB;EAGF,MAAM,YAAY,SAAS,QAAQ,GAAG;AAEtC,MAAI,aAAa,OAAO;AACtB,YAAS,UAAU;AACnB,kBAAe,EAAE;AACjB;;EAGF,IAAI,aAAa;EACjB,IAAI,cAAc;AAElB,SAAO,aAAa,OAAO;AACzB,iBAAc;AACd,kBAAe;;AAGjB,WAAS,WAAW;AACpB,iBAAe,cAAc,EAAE;IAC9B;EAAC;EAAU;EAAO;EAAS,CAAC;AAE/B,iBAAgB;AACd,WAAS,OAAO;IACf,CAAC,OAAO,CAAC;AAEZ,eACQ;AACJ,MAAI,CAAC,aAAa,WAAW,OAAO,UAAU,SAC5C;AAGF,MAAI,SAAS,QACX,UAAS,QAAQ,MAAM;AAGzB,WAAS,UAAU,KAAK,OACtB,aAAa,SACb,EAAE,GAAG,GAAG,EACR;GACE,GAAG,CAAC;GACJ,UAAU,QAAQ;GAClB,QAAQ;GACR,MAAM;GACP,CACF;AAED,eAAa;AACX,YAAS,SAAS,MAAM;;IAG5B;EACE,OAAO;EACP,cAAc,CAAC,OAAO,MAAM;EAC7B,CACF;AAED,iBAAgB;AACd,MAAI,CAAC,SAAS,QACZ;AAGF,MAAI,SACF,UAAS,QAAQ,OAAO;MAExB,UAAS,QAAQ,MAAM;IAExB,CAAC,SAAS,CAAC;AAEd,iBAAgB;AACd,iBACE,WAAY,OAAO,aAAa,YAAY,MAAM,WAAY,EAC/D;IACA,CAAC,SAAS,CAAC;AAEd,kBAAiB,gBAAgB;AAC/B,MAAI,CAAC,SAAS,WAAW,CAAC,aAAa,QACrC;AAGF,MAAI,SACF,UAAS,QAAQ,OAAO;MAExB,UAAS,QAAQ,MAAM;GAEzB;AAEF,QACE,oBAAC;EACC,WAAU;EACV,GAAI;YAGJ,oBAAC;GAAI,KAAK;GAAc,WAAU;aAC/B,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,KAAK,GAAG,UACrB,qBAAC;IAEC,OAAO,EAAE,UAAU,OAAO;IAC1B,WAAU;eAEV,oBAAC;KACC,MAAK,OAAM;AACT,UAAI,GACF,UAAS,QAAQ,SAAS;;KAI7B;MACG,EACL,CACC,GAAG,MAAM,OAAO,aAAa,WAAW,WAAW,YAAY,CAChE,CAAC,KAAK,GAAG,MACR,oBAAC,SAAa,YAAJ,EAAmB,CAC7B;MAjBG,MAkBD,CACN;IACE;GACF"}
1
+ {"version":3,"file":"item.mjs","names":[],"sources":["../../../../src/components/molecules/marquees/item.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\n\nimport { useGSAP } from '@gsap/react';\nimport { gsap } from 'gsap';\n\nexport interface ItemProps {\n key?: React.Key;\n speed?: number;\n autoFill?: boolean | number;\n pause?: boolean;\n pauseOnHover?: boolean;\n children?: React.ReactNode;\n}\n\nexport interface Props\n extends Omit<React.ComponentPropsWithoutRef<'div'>, 'key'>, ItemProps {\n width: string | number;\n}\n\n// `autoFill={true}` (the default on `Marquees`) needs *some* repeat count\n// before the item can be measured and the real count computed — this is\n// only ever visible for that one render, but rendering 100 copies (200\n// with the 2x loop duplication) up front was needlessly heavy for the\n// common case. A modest guess still avoids visible gaps for typical\n// item/container width ratios while cutting the worst-case default\n// render by ~90%.\nconst INITIAL_AUTO_FILL_GUESS = 10;\n\nconst Item = ({\n width: _width,\n speed = 100,\n autoFill = false,\n pause: _pause = false,\n pauseOnHover = false,\n children,\n}: Props) => {\n const itemRefs = useRef<HTMLDivElement[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n const tweenRef = useRef<gsap.core.Tween | null>(null);\n\n const [width, setWidth] = useState<string | number>(_width);\n const [pause, setPause] = useState(false);\n const [repeatCount, setRepeatCount] = useState(\n autoFill\n ? typeof autoFill === 'boolean'\n ? INITIAL_AUTO_FILL_GUESS\n : autoFill\n : 0,\n );\n\n const isPaused = _pause || pause;\n\n const hoverEvents = pauseOnHover\n ? {\n onMouseEnter: () => {\n setPause(true);\n },\n onMouseLeave: () => {\n setPause(false);\n },\n }\n : {};\n\n useEffect(() => {\n if (\n !autoFill ||\n !children ||\n !itemRefs.current[0] ||\n typeof width === 'string'\n ) {\n return;\n }\n\n const itemWidth = itemRefs.current[0].offsetWidth;\n\n if (itemWidth >= width) {\n setWidth(itemWidth);\n setRepeatCount(0);\n return;\n }\n\n let totalWidth = 0;\n let repeatCount = 0;\n\n while (totalWidth < width) {\n totalWidth += itemWidth;\n repeatCount += 1;\n }\n\n setWidth(totalWidth);\n setRepeatCount(repeatCount - 1);\n }, [autoFill, width, children]);\n\n useEffect(() => {\n setWidth(_width);\n }, [_width]);\n\n useGSAP(\n () => {\n if (!containerRef.current || typeof width === 'string') {\n return;\n }\n\n if (tweenRef.current) {\n tweenRef.current.kill();\n }\n\n tweenRef.current = gsap.fromTo(\n containerRef.current,\n { x: 0 },\n {\n x: -width,\n duration: width / speed,\n repeat: -1,\n ease: 'linear',\n },\n );\n\n return () => {\n tweenRef.current?.kill();\n };\n },\n {\n scope: containerRef,\n dependencies: [width, speed],\n },\n );\n\n useEffect(() => {\n if (!tweenRef.current) {\n return;\n }\n\n if (isPaused) {\n tweenRef.current.pause();\n } else {\n tweenRef.current.play();\n }\n }, [isPaused]);\n\n useEffect(() => {\n setRepeatCount(\n autoFill\n ? typeof autoFill === 'boolean'\n ? INITIAL_AUTO_FILL_GUESS\n : autoFill\n : 0,\n );\n }, [autoFill]);\n\n return (\n <div\n className=\"flex overflow-hidden\"\n {...hoverEvents}\n //\n >\n <div ref={containerRef} className=\"flex flex-nowrap\">\n {[...Array(2)].map((_, index) => (\n <div\n key={index}\n style={{ minWidth: width }}\n className=\"flex flex-nowrap\"\n >\n <div\n ref={el => {\n if (el) {\n itemRefs.current[index] = el;\n }\n }}\n >\n {children}\n </div>\n {[\n ...Array(typeof autoFill === 'number' ? autoFill : repeatCount),\n ].map((_, i) => (\n <div key={i}>{children}</div>\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Item;\n"],"mappings":";;;;;;;;AA4BA,MAAM,0BAA0B;AAEhC,MAAM,QAAQ,EACZ,OAAO,QACP,QAAQ,KACR,WAAW,OACX,OAAO,SAAS,OAChB,eAAe,OACf,eACW;CACX,MAAM,WAAW,OAAyB,EAAE,CAAC;CAC7C,MAAM,eAAe,OAAuB,KAAK;CACjD,MAAM,WAAW,OAA+B,KAAK;CAErD,MAAM,CAAC,OAAO,YAAY,SAA0B,OAAO;CAC3D,MAAM,CAAC,OAAO,YAAY,SAAS,MAAM;CACzC,MAAM,CAAC,aAAa,kBAAkB,SACpC,WACI,OAAO,aAAa,YAClB,0BACA,WACF,EACL;CAED,MAAM,WAAW,UAAU;CAE3B,MAAM,cAAc,eAChB;EACE,oBAAoB;AAClB,YAAS,KAAK;;EAEhB,oBAAoB;AAClB,YAAS,MAAM;;EAElB,GACD,EAAE;AAEN,iBAAgB;AACd,MACE,CAAC,YACD,CAAC,YACD,CAAC,SAAS,QAAQ,MAClB,OAAO,UAAU,SAEjB;EAGF,MAAM,YAAY,SAAS,QAAQ,GAAG;AAEtC,MAAI,aAAa,OAAO;AACtB,YAAS,UAAU;AACnB,kBAAe,EAAE;AACjB;;EAGF,IAAI,aAAa;EACjB,IAAI,cAAc;AAElB,SAAO,aAAa,OAAO;AACzB,iBAAc;AACd,kBAAe;;AAGjB,WAAS,WAAW;AACpB,iBAAe,cAAc,EAAE;IAC9B;EAAC;EAAU;EAAO;EAAS,CAAC;AAE/B,iBAAgB;AACd,WAAS,OAAO;IACf,CAAC,OAAO,CAAC;AAEZ,eACQ;AACJ,MAAI,CAAC,aAAa,WAAW,OAAO,UAAU,SAC5C;AAGF,MAAI,SAAS,QACX,UAAS,QAAQ,MAAM;AAGzB,WAAS,UAAU,KAAK,OACtB,aAAa,SACb,EAAE,GAAG,GAAG,EACR;GACE,GAAG,CAAC;GACJ,UAAU,QAAQ;GAClB,QAAQ;GACR,MAAM;GACP,CACF;AAED,eAAa;AACX,YAAS,SAAS,MAAM;;IAG5B;EACE,OAAO;EACP,cAAc,CAAC,OAAO,MAAM;EAC7B,CACF;AAED,iBAAgB;AACd,MAAI,CAAC,SAAS,QACZ;AAGF,MAAI,SACF,UAAS,QAAQ,OAAO;MAExB,UAAS,QAAQ,MAAM;IAExB,CAAC,SAAS,CAAC;AAEd,iBAAgB;AACd,iBACE,WACI,OAAO,aAAa,YAClB,0BACA,WACF,EACL;IACA,CAAC,SAAS,CAAC;AAEd,QACE,oBAAC;EACC,WAAU;EACV,GAAI;YAGJ,oBAAC;GAAI,KAAK;GAAc,WAAU;aAC/B,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,KAAK,GAAG,UACrB,qBAAC;IAEC,OAAO,EAAE,UAAU,OAAO;IAC1B,WAAU;eAEV,oBAAC;KACC,MAAK,OAAM;AACT,UAAI,GACF,UAAS,QAAQ,SAAS;;KAI7B;MACG,EACL,CACC,GAAG,MAAM,OAAO,aAAa,WAAW,WAAW,YAAY,CAChE,CAAC,KAAK,GAAG,MACR,oBAAC,SAAa,YAAJ,EAAmB,CAC7B;MAjBG,MAkBD,CACN;IACE;GACF"}
@@ -22,6 +22,11 @@ declare const Reveals: ({
22
22
  cascade,
23
23
  duration,
24
24
  delay,
25
+ effect,
26
+ once,
27
+ viewport,
28
+ variants,
29
+ transition,
25
30
  ...props
26
31
  }: Props) => react_jsx_runtime0.JSX.Element;
27
32
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"reveals.d.mts","names":[],"sources":["../../../../src/components/molecules/reveals/reveals.tsx"],"mappings":";;;;UAMiB,KAAA,SACP,KAAA,CAAM,wBAAA,SAAiC,SAAA;EAC/C,OAAA;EACA,UAAA;IACE,IAAA;IACA,IAAA;EAAA;EAEF,IAAA;EACA,KAAA,GAAQ,SAAA;AAAA;AAAA,cAGG,QAAA;AAAA,cACA,KAAA;AAAA,cACA,OAAA;AAAA,cAEP,OAAA;EAAW,QAAA;EAAA,SAAA;EAAA,UAAA;EAAA,KAAA;EAAA,OAAA;EAAA,QAAA;EAAA,KAAA;EAAA,GAAA;AAAA,GASd,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"reveals.d.mts","names":[],"sources":["../../../../src/components/molecules/reveals/reveals.tsx"],"mappings":";;;;UAMiB,KAAA,SACP,KAAA,CAAM,wBAAA,SAAiC,SAAA;EAC/C,OAAA;EACA,UAAA;IACE,IAAA;IACA,IAAA;EAAA;EAEF,IAAA;EACA,KAAA,GAAQ,SAAA;AAAA;AAAA,cAGG,QAAA;AAAA,cACA,KAAA;AAAA,cACA,OAAA;AAAA,cAEP,OAAA;EAAW,QAAA;EAAA,SAAA;EAAA,UAAA;EAAA,KAAA;EAAA,OAAA;EAAA,QAAA;EAAA,KAAA;EAAA,MAAA;EAAA,IAAA;EAAA,QAAA;EAAA,QAAA;EAAA,UAAA;EAAA,GAAA;AAAA,GAcd,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -7,10 +7,15 @@ import { jsx } from "react/jsx-runtime";
7
7
  const DURATION = .6;
8
8
  const DELAY = 0;
9
9
  const CASCADE = .1;
10
- const Reveals = ({ children, className, classNames, items = [], cascade = CASCADE, duration = DURATION, delay = DELAY, ...props }) => {
10
+ const Reveals = ({ children, className, classNames, items = [], cascade = CASCADE, duration = DURATION, delay = DELAY, effect, once, viewport, variants, transition, ...props }) => {
11
11
  const renderItems = (items) => items.map((item, index) => /* @__PURE__ */ jsx(Item, {
12
+ effect,
12
13
  duration,
13
14
  delay: delay + cascade * index,
15
+ once,
16
+ viewport,
17
+ variants,
18
+ transition,
14
19
  ...item,
15
20
  className: cn(item.className, classNames?.item),
16
21
  children: item.children
@@ -1 +1 @@
1
- {"version":3,"file":"reveals.mjs","names":[],"sources":["../../../../src/components/molecules/reveals/reveals.tsx"],"sourcesContent":["import { Children } from 'react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Item, { type ItemProps } from './item';\n\nexport interface Props\n extends React.ComponentPropsWithoutRef<'div'>, ItemProps {\n cascade?: number;\n classNames?: {\n root?: string;\n item?: string;\n };\n once?: boolean;\n items?: ItemProps[];\n}\n\nexport const DURATION = 0.6;\nexport const DELAY = 0;\nexport const CASCADE = 0.1;\n\nconst Reveals = ({\n children,\n className,\n classNames,\n items = [],\n cascade = CASCADE,\n duration = DURATION,\n delay = DELAY,\n ...props\n}: Props) => {\n const renderItems = (items: ItemProps[]) =>\n items.map((item, index) => (\n <Item\n key={index}\n duration={duration}\n delay={delay + cascade * index}\n {...item}\n className={cn(\n item.className,\n classNames?.item,\n //\n )}\n >\n {item.children}\n </Item>\n ));\n\n return (\n <div\n className={cn(\n 'flex gap-5',\n className,\n classNames?.root,\n //\n )}\n {...props}\n >\n {renderItems(\n children\n ? Children.toArray(children).map(child => ({\n children: child,\n }))\n : items,\n )}\n </div>\n );\n};\n\nexport default Reveals;\n"],"mappings":";;;;;;AAiBA,MAAa,WAAW;AACxB,MAAa,QAAQ;AACrB,MAAa,UAAU;AAEvB,MAAM,WAAW,EACf,UACA,WACA,YACA,QAAQ,EAAE,EACV,UAAU,SACV,WAAW,UACX,QAAQ,OACR,GAAG,YACQ;CACX,MAAM,eAAe,UACnB,MAAM,KAAK,MAAM,UACf,oBAAC;EAEW;EACV,OAAO,QAAQ,UAAU;EACzB,GAAI;EACJ,WAAW,GACT,KAAK,WACL,YAAY,KAEb;YAEA,KAAK;IAVD,MAWA,CACP;AAEJ,QACE,oBAAC;EACC,WAAW,GACT,cACA,WACA,YAAY,KAEb;EACD,GAAI;YAEH,YACC,WACI,SAAS,QAAQ,SAAS,CAAC,KAAI,WAAU,EACvC,UAAU,OACX,EAAE,GACH,MACL;GACG"}
1
+ {"version":3,"file":"reveals.mjs","names":[],"sources":["../../../../src/components/molecules/reveals/reveals.tsx"],"sourcesContent":["import { Children } from 'react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Item, { type ItemProps } from './item';\n\nexport interface Props\n extends React.ComponentPropsWithoutRef<'div'>, ItemProps {\n cascade?: number;\n classNames?: {\n root?: string;\n item?: string;\n };\n once?: boolean;\n items?: ItemProps[];\n}\n\nexport const DURATION = 0.6;\nexport const DELAY = 0;\nexport const CASCADE = 0.1;\n\nconst Reveals = ({\n children,\n className,\n classNames,\n items = [],\n cascade = CASCADE,\n duration = DURATION,\n delay = DELAY,\n effect,\n once,\n viewport,\n variants,\n transition,\n ...props\n}: Props) => {\n const renderItems = (items: ItemProps[]) =>\n items.map((item, index) => (\n <Item\n key={index}\n effect={effect}\n duration={duration}\n delay={delay + cascade * index}\n once={once}\n viewport={viewport}\n variants={variants}\n transition={transition}\n {...item}\n className={cn(\n item.className,\n classNames?.item,\n //\n )}\n >\n {item.children}\n </Item>\n ));\n\n return (\n <div\n className={cn(\n 'flex gap-5',\n className,\n classNames?.root,\n //\n )}\n {...props}\n >\n {renderItems(\n children\n ? Children.toArray(children).map(child => ({\n children: child,\n }))\n : items,\n )}\n </div>\n );\n};\n\nexport default Reveals;\n"],"mappings":";;;;;;AAiBA,MAAa,WAAW;AACxB,MAAa,QAAQ;AACrB,MAAa,UAAU;AAEvB,MAAM,WAAW,EACf,UACA,WACA,YACA,QAAQ,EAAE,EACV,UAAU,SACV,WAAW,UACX,QAAQ,OACR,QACA,MACA,UACA,UACA,YACA,GAAG,YACQ;CACX,MAAM,eAAe,UACnB,MAAM,KAAK,MAAM,UACf,oBAAC;EAES;EACE;EACV,OAAO,QAAQ,UAAU;EACnB;EACI;EACA;EACE;EACZ,GAAI;EACJ,WAAW,GACT,KAAK,WACL,YAAY,KAEb;YAEA,KAAK;IAfD,MAgBA,CACP;AAEJ,QACE,oBAAC;EACC,WAAW,GACT,cACA,WACA,YAAY,KAEb;EACD,GAAI;YAEH,YACC,WACI,SAAS,QAAQ,SAAS,CAAC,KAAI,WAAU,EACvC,UAAU,OACX,EAAE,GACH,MACL;GACG"}
@@ -20,6 +20,14 @@ interface Props {
20
20
  item?: string;
21
21
  };
22
22
  onChange?: (files: UploadFile[]) => void;
23
+ /**
24
+ * Called once per file that didn't make it in — either bumped by
25
+ * `maxCount` or failed to read.
26
+ */
27
+ onReject?: (info: {
28
+ file: File;
29
+ reason: 'max-count' | 'read-error';
30
+ }) => void;
23
31
  }
24
32
  declare const Upload: ({
25
33
  defaultValue,
@@ -30,7 +38,8 @@ declare const Upload: ({
30
38
  disabled,
31
39
  className,
32
40
  classNames,
33
- onChange: _onChange
41
+ onChange: _onChange,
42
+ onReject
34
43
  }: Props) => react_jsx_runtime0.JSX.Element;
35
44
  //#endregion
36
45
  export { Upload, UploadFile };
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.mts","names":[],"sources":["../../../src/components/molecules/upload.tsx"],"mappings":";;;UAeiB,UAAA;EACf,GAAA;EACA,IAAA;EACA,GAAA;AAAA;AAAA,UAGe,KAAA;EACf,YAAA,GAAe,UAAA;EACf,KAAA,GAAQ,UAAA;EACR,QAAA;EACA,MAAA;EACA,QAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;IACE,QAAA;IACA,IAAA;IACA,IAAA;EAAA;EAEF,QAAA,IAAY,KAAA,EAAO,UAAA;AAAA;AAAA,cAOf,MAAA;EAAU,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA;EAAA,MAAA;EAAA,QAAA;EAAA,QAAA;EAAA,SAAA;EAAA,UAAA;EAAA,QAAA,EAAA;AAAA,GAUb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"upload.d.mts","names":[],"sources":["../../../src/components/molecules/upload.tsx"],"mappings":";;;UAgBiB,UAAA;EACf,GAAA;EACA,IAAA;EACA,GAAA;AAAA;AAAA,UAGe,KAAA;EACf,YAAA,GAAe,UAAA;EACf,KAAA,GAAQ,UAAA;EACR,QAAA;EACA,MAAA;EACA,QAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;IACE,QAAA;IACA,IAAA;IACA,IAAA;EAAA;EAEF,QAAA,IAAY,KAAA,EAAO,UAAA;EAKW;;;;EAA9B,QAAA,IAAY,IAAA;IAAQ,IAAA,EAAM,IAAA;IAAM,MAAA;EAAA;AAAA;AAAA,cAO5B,MAAA;EAAU,YAAA;EAAA,KAAA,EAAA,MAAA;EAAA,QAAA;EAAA,MAAA;EAAA,QAAA;EAAA,QAAA;EAAA,SAAA;EAAA,UAAA;EAAA,QAAA,EAAA,SAAA;EAAA;AAAA,GAWb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -6,10 +6,11 @@ import { Upload, X } from "lucide-react";
6
6
  import { useId } from "react";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { useControllableState, useFileDrop, useFileToDataUrl } from "@jbpark/use-hooks";
9
+ import { v4 } from "uuid";
9
10
 
10
11
  //#region src/components/molecules/upload.tsx
11
12
  const isImage = (file) => /^data:image\//.test(file.url) || /\.(png|jpe?g|gif|webp|svg)$/i.test(file.name);
12
- const Upload$1 = ({ defaultValue = [], value: _value, multiple = true, accept = "image/*", maxCount, disabled, className, classNames, onChange: _onChange = () => {} }) => {
13
+ const Upload$1 = ({ defaultValue = [], value: _value, multiple = true, accept = "image/*", maxCount, disabled, className, classNames, onChange: _onChange = () => {}, onReject }) => {
13
14
  const inputId = useId();
14
15
  const readAsDataUrl = useFileToDataUrl();
15
16
  const [files, setFiles] = useControllableState({
@@ -20,11 +21,27 @@ const Upload$1 = ({ defaultValue = [], value: _value, multiple = true, accept =
20
21
  const addFiles = async (incoming) => {
21
22
  const remaining = typeof maxCount === "number" ? Math.max(0, maxCount - files.length) : incoming.length;
22
23
  const accepted = incoming.slice(0, remaining);
23
- const uploaded = await Promise.all(accepted.map(async (file) => ({
24
- uid: `${file.name}-${file.lastModified}-${file.size}`,
25
- name: file.name,
26
- url: await readAsDataUrl(file)
27
- })));
24
+ incoming.slice(remaining).forEach((file) => onReject?.({
25
+ file,
26
+ reason: "max-count"
27
+ }));
28
+ if (accepted.length === 0) return;
29
+ const uploaded = (await Promise.all(accepted.map(async (file) => {
30
+ try {
31
+ return {
32
+ uid: `${file.name}-${file.lastModified}-${file.size}-${v4()}`,
33
+ name: file.name,
34
+ url: await readAsDataUrl(file)
35
+ };
36
+ } catch {
37
+ onReject?.({
38
+ file,
39
+ reason: "read-error"
40
+ });
41
+ return null;
42
+ }
43
+ }))).filter((file) => file !== null);
44
+ if (uploaded.length === 0) return;
28
45
  setFiles([...files, ...uploaded]);
29
46
  };
30
47
  const removeFile = (uid) => {
@@ -1 +1 @@
1
- {"version":3,"file":"upload.mjs","names":["Upload","UploadIcon"],"sources":["../../../src/components/molecules/upload.tsx"],"sourcesContent":["'use client';\n\nimport { useId } from 'react';\n\nimport {\n useControllableState,\n useFileDrop,\n useFileToDataUrl,\n} from '@jbpark/use-hooks';\nimport { Upload as UploadIcon, X } from 'lucide-react';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nexport interface UploadFile {\n uid: string;\n name: string;\n url: string;\n}\n\nexport interface Props {\n defaultValue?: UploadFile[];\n value?: UploadFile[];\n multiple?: boolean;\n accept?: string;\n maxCount?: number;\n disabled?: boolean;\n className?: string;\n classNames?: {\n dropzone?: string;\n list?: string;\n item?: string;\n };\n onChange?: (files: UploadFile[]) => void;\n}\n\nconst isImage = (file: UploadFile) =>\n /^data:image\\//.test(file.url) ||\n /\\.(png|jpe?g|gif|webp|svg)$/i.test(file.name);\n\nconst Upload = ({\n defaultValue = [],\n value: _value,\n multiple = true,\n accept = 'image/*',\n maxCount,\n disabled,\n className,\n classNames,\n onChange: _onChange = () => {},\n}: Props) => {\n const inputId = useId();\n const readAsDataUrl = useFileToDataUrl();\n const [files, setFiles] = useControllableState<UploadFile[]>({\n value: _value,\n defaultValue,\n onChange: _onChange,\n });\n\n const addFiles = async (incoming: File[]) => {\n const remaining =\n typeof maxCount === 'number'\n ? Math.max(0, maxCount - files.length)\n : incoming.length;\n\n const accepted = incoming.slice(0, remaining);\n\n const uploaded = await Promise.all(\n accepted.map(async file => ({\n uid: `${file.name}-${file.lastModified}-${file.size}`,\n name: file.name,\n url: await readAsDataUrl(file),\n })),\n );\n\n setFiles([...files, ...uploaded]);\n };\n\n const removeFile = (uid: string) => {\n setFiles(files.filter(file => file.uid !== uid));\n };\n\n const { dropRef, isDragging } = useFileDrop<HTMLLabelElement>({\n accept,\n multiple,\n disabled,\n onDrop: addFiles,\n });\n\n return (\n <div\n className={cn(\n 'flex flex-col gap-3',\n className,\n //\n )}\n >\n <label\n ref={dropRef}\n htmlFor={inputId}\n className={cn(\n 'flex cursor-pointer flex-col items-center justify-center gap-2',\n 'rounded-md border border-dashed p-6 text-center',\n 'text-muted-foreground text-sm',\n 'transition-colors',\n isDragging && 'border-primary bg-accent',\n disabled && 'pointer-events-none cursor-not-allowed opacity-50',\n classNames?.dropzone,\n //\n )}\n >\n <UploadIcon className=\"size-6\" />\n <span>Click or drag file{multiple ? 's' : ''} to upload</span>\n <input\n id={inputId}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n className=\"hidden\"\n onChange={e => {\n if (e.target.files?.length) {\n addFiles(Array.from(e.target.files));\n }\n e.target.value = '';\n }}\n />\n </label>\n\n {files.length > 0 && (\n <ul\n className={cn(\n 'flex flex-col gap-2',\n classNames?.list,\n //\n )}\n >\n {files.map(file => (\n <li\n key={file.uid}\n className={cn(\n 'flex items-center gap-2 rounded-md border p-2',\n classNames?.item,\n //\n )}\n >\n {isImage(file) && (\n <img\n src={file.url}\n alt=\"\"\n className=\"size-10 shrink-0 rounded object-cover\"\n />\n )}\n <span className=\"flex-1 truncate text-sm\">{file.name}</span>\n <Button\n type=\"text\"\n shape=\"circle\"\n size=\"small\"\n icon={<X className=\"size-4\" />}\n onClick={() => removeFile(file.uid)}\n className=\"text-muted-foreground hover:text-foreground shrink-0\"\n aria-label={`Remove ${file.name}`}\n />\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n\nexport default Upload;\n"],"mappings":";;;;;;;;;;AAqCA,MAAM,WAAW,SACf,gBAAgB,KAAK,KAAK,IAAI,IAC9B,+BAA+B,KAAK,KAAK,KAAK;AAEhD,MAAMA,YAAU,EACd,eAAe,EAAE,EACjB,OAAO,QACP,WAAW,MACX,SAAS,WACT,UACA,UACA,WACA,YACA,UAAU,kBAAkB,SACjB;CACX,MAAM,UAAU,OAAO;CACvB,MAAM,gBAAgB,kBAAkB;CACxC,MAAM,CAAC,OAAO,YAAY,qBAAmC;EAC3D,OAAO;EACP;EACA,UAAU;EACX,CAAC;CAEF,MAAM,WAAW,OAAO,aAAqB;EAC3C,MAAM,YACJ,OAAO,aAAa,WAChB,KAAK,IAAI,GAAG,WAAW,MAAM,OAAO,GACpC,SAAS;EAEf,MAAM,WAAW,SAAS,MAAM,GAAG,UAAU;EAE7C,MAAM,WAAW,MAAM,QAAQ,IAC7B,SAAS,IAAI,OAAM,UAAS;GAC1B,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,aAAa,GAAG,KAAK;GAC/C,MAAM,KAAK;GACX,KAAK,MAAM,cAAc,KAAK;GAC/B,EAAE,CACJ;AAED,WAAS,CAAC,GAAG,OAAO,GAAG,SAAS,CAAC;;CAGnC,MAAM,cAAc,QAAgB;AAClC,WAAS,MAAM,QAAO,SAAQ,KAAK,QAAQ,IAAI,CAAC;;CAGlD,MAAM,EAAE,SAAS,eAAe,YAA8B;EAC5D;EACA;EACA;EACA,QAAQ;EACT,CAAC;AAEF,QACE,qBAAC;EACC,WAAW,GACT,uBACA,UAED;aAED,qBAAC;GACC,KAAK;GACL,SAAS;GACT,WAAW,GACT,kEACA,mDACA,iCACA,qBACA,cAAc,4BACd,YAAY,qDACZ,YAAY,SAEb;;IAED,oBAACC,UAAW,WAAU,WAAW;IACjC,qBAAC;KAAK;KAAmB,WAAW,MAAM;KAAG;QAAiB;IAC9D,oBAAC;KACC,IAAI;KACJ,MAAK;KACG;KACE;KACA;KACV,WAAU;KACV,WAAU,MAAK;AACb,UAAI,EAAE,OAAO,OAAO,OAClB,UAAS,MAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AAEtC,QAAE,OAAO,QAAQ;;MAEnB;;IACI,EAEP,MAAM,SAAS,KACd,oBAAC;GACC,WAAW,GACT,uBACA,YAAY,KAEb;aAEA,MAAM,KAAI,SACT,qBAAC;IAEC,WAAW,GACT,iDACA,YAAY,KAEb;;KAEA,QAAQ,KAAK,IACZ,oBAAC;MACC,KAAK,KAAK;MACV,KAAI;MACJ,WAAU;OACV;KAEJ,oBAAC;MAAK,WAAU;gBAA2B,KAAK;OAAY;KAC5D,oBAAC;MACC,MAAK;MACL,OAAM;MACN,MAAK;MACL,MAAM,oBAAC,KAAE,WAAU,WAAW;MAC9B,eAAe,WAAW,KAAK,IAAI;MACnC,WAAU;MACV,cAAY,UAAU,KAAK;OAC3B;;MAvBG,KAAK,IAwBP,CACL;IACC;GAEH"}
1
+ {"version":3,"file":"upload.mjs","names":["Upload","uuid","UploadIcon"],"sources":["../../../src/components/molecules/upload.tsx"],"sourcesContent":["'use client';\n\nimport { useId } from 'react';\n\nimport {\n useControllableState,\n useFileDrop,\n useFileToDataUrl,\n} from '@jbpark/use-hooks';\nimport { Upload as UploadIcon, X } from 'lucide-react';\nimport { v4 as uuid } from 'uuid';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nexport interface UploadFile {\n uid: string;\n name: string;\n url: string;\n}\n\nexport interface Props {\n defaultValue?: UploadFile[];\n value?: UploadFile[];\n multiple?: boolean;\n accept?: string;\n maxCount?: number;\n disabled?: boolean;\n className?: string;\n classNames?: {\n dropzone?: string;\n list?: string;\n item?: string;\n };\n onChange?: (files: UploadFile[]) => void;\n /**\n * Called once per file that didn't make it in — either bumped by\n * `maxCount` or failed to read.\n */\n onReject?: (info: { file: File; reason: 'max-count' | 'read-error' }) => void;\n}\n\nconst isImage = (file: UploadFile) =>\n /^data:image\\//.test(file.url) ||\n /\\.(png|jpe?g|gif|webp|svg)$/i.test(file.name);\n\nconst Upload = ({\n defaultValue = [],\n value: _value,\n multiple = true,\n accept = 'image/*',\n maxCount,\n disabled,\n className,\n classNames,\n onChange: _onChange = () => {},\n onReject,\n}: Props) => {\n const inputId = useId();\n const readAsDataUrl = useFileToDataUrl();\n const [files, setFiles] = useControllableState<UploadFile[]>({\n value: _value,\n defaultValue,\n onChange: _onChange,\n });\n\n const addFiles = async (incoming: File[]) => {\n const remaining =\n typeof maxCount === 'number'\n ? Math.max(0, maxCount - files.length)\n : incoming.length;\n\n const accepted = incoming.slice(0, remaining);\n const rejected = incoming.slice(remaining);\n\n rejected.forEach(file => onReject?.({ file, reason: 'max-count' }));\n\n if (accepted.length === 0) {\n return;\n }\n\n const uploaded = (\n await Promise.all(\n accepted.map(async file => {\n try {\n return {\n // `uuid()` guarantees uniqueness even for the same file\n // added twice (identical name/lastModified/size), which\n // name+lastModified+size alone can't — a collision there\n // corrupted React's item keys and made removeFile's\n // uid-based filter delete both copies at once.\n uid: `${file.name}-${file.lastModified}-${file.size}-${uuid()}`,\n name: file.name,\n url: await readAsDataUrl(file),\n };\n } catch {\n onReject?.({ file, reason: 'read-error' });\n return null;\n }\n }),\n )\n ).filter((file): file is UploadFile => file !== null);\n\n if (uploaded.length === 0) {\n return;\n }\n\n setFiles([...files, ...uploaded]);\n };\n\n const removeFile = (uid: string) => {\n setFiles(files.filter(file => file.uid !== uid));\n };\n\n const { dropRef, isDragging } = useFileDrop<HTMLLabelElement>({\n accept,\n multiple,\n disabled,\n onDrop: addFiles,\n });\n\n return (\n <div\n className={cn(\n 'flex flex-col gap-3',\n className,\n //\n )}\n >\n <label\n ref={dropRef}\n htmlFor={inputId}\n className={cn(\n 'flex cursor-pointer flex-col items-center justify-center gap-2',\n 'rounded-md border border-dashed p-6 text-center',\n 'text-muted-foreground text-sm',\n 'transition-colors',\n isDragging && 'border-primary bg-accent',\n disabled && 'pointer-events-none cursor-not-allowed opacity-50',\n classNames?.dropzone,\n //\n )}\n >\n <UploadIcon className=\"size-6\" />\n <span>Click or drag file{multiple ? 's' : ''} to upload</span>\n <input\n id={inputId}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n className=\"hidden\"\n onChange={e => {\n if (e.target.files?.length) {\n addFiles(Array.from(e.target.files));\n }\n e.target.value = '';\n }}\n />\n </label>\n\n {files.length > 0 && (\n <ul\n className={cn(\n 'flex flex-col gap-2',\n classNames?.list,\n //\n )}\n >\n {files.map(file => (\n <li\n key={file.uid}\n className={cn(\n 'flex items-center gap-2 rounded-md border p-2',\n classNames?.item,\n //\n )}\n >\n {isImage(file) && (\n <img\n src={file.url}\n alt=\"\"\n className=\"size-10 shrink-0 rounded object-cover\"\n />\n )}\n <span className=\"flex-1 truncate text-sm\">{file.name}</span>\n <Button\n type=\"text\"\n shape=\"circle\"\n size=\"small\"\n icon={<X className=\"size-4\" />}\n onClick={() => removeFile(file.uid)}\n className=\"text-muted-foreground hover:text-foreground shrink-0\"\n aria-label={`Remove ${file.name}`}\n />\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n};\n\nexport default Upload;\n"],"mappings":";;;;;;;;;;;AA2CA,MAAM,WAAW,SACf,gBAAgB,KAAK,KAAK,IAAI,IAC9B,+BAA+B,KAAK,KAAK,KAAK;AAEhD,MAAMA,YAAU,EACd,eAAe,EAAE,EACjB,OAAO,QACP,WAAW,MACX,SAAS,WACT,UACA,UACA,WACA,YACA,UAAU,kBAAkB,IAC5B,eACW;CACX,MAAM,UAAU,OAAO;CACvB,MAAM,gBAAgB,kBAAkB;CACxC,MAAM,CAAC,OAAO,YAAY,qBAAmC;EAC3D,OAAO;EACP;EACA,UAAU;EACX,CAAC;CAEF,MAAM,WAAW,OAAO,aAAqB;EAC3C,MAAM,YACJ,OAAO,aAAa,WAChB,KAAK,IAAI,GAAG,WAAW,MAAM,OAAO,GACpC,SAAS;EAEf,MAAM,WAAW,SAAS,MAAM,GAAG,UAAU;AAG7C,EAFiB,SAAS,MAAM,UAAU,CAEjC,SAAQ,SAAQ,WAAW;GAAE;GAAM,QAAQ;GAAa,CAAC,CAAC;AAEnE,MAAI,SAAS,WAAW,EACtB;EAGF,MAAM,YACJ,MAAM,QAAQ,IACZ,SAAS,IAAI,OAAM,SAAQ;AACzB,OAAI;AACF,WAAO;KAML,KAAK,GAAG,KAAK,KAAK,GAAG,KAAK,aAAa,GAAG,KAAK,KAAK,GAAGC,IAAM;KAC7D,MAAM,KAAK;KACX,KAAK,MAAM,cAAc,KAAK;KAC/B;WACK;AACN,eAAW;KAAE;KAAM,QAAQ;KAAc,CAAC;AAC1C,WAAO;;IAET,CACH,EACD,QAAQ,SAA6B,SAAS,KAAK;AAErD,MAAI,SAAS,WAAW,EACtB;AAGF,WAAS,CAAC,GAAG,OAAO,GAAG,SAAS,CAAC;;CAGnC,MAAM,cAAc,QAAgB;AAClC,WAAS,MAAM,QAAO,SAAQ,KAAK,QAAQ,IAAI,CAAC;;CAGlD,MAAM,EAAE,SAAS,eAAe,YAA8B;EAC5D;EACA;EACA;EACA,QAAQ;EACT,CAAC;AAEF,QACE,qBAAC;EACC,WAAW,GACT,uBACA,UAED;aAED,qBAAC;GACC,KAAK;GACL,SAAS;GACT,WAAW,GACT,kEACA,mDACA,iCACA,qBACA,cAAc,4BACd,YAAY,qDACZ,YAAY,SAEb;;IAED,oBAACC,UAAW,WAAU,WAAW;IACjC,qBAAC;KAAK;KAAmB,WAAW,MAAM;KAAG;QAAiB;IAC9D,oBAAC;KACC,IAAI;KACJ,MAAK;KACG;KACE;KACA;KACV,WAAU;KACV,WAAU,MAAK;AACb,UAAI,EAAE,OAAO,OAAO,OAClB,UAAS,MAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AAEtC,QAAE,OAAO,QAAQ;;MAEnB;;IACI,EAEP,MAAM,SAAS,KACd,oBAAC;GACC,WAAW,GACT,uBACA,YAAY,KAEb;aAEA,MAAM,KAAI,SACT,qBAAC;IAEC,WAAW,GACT,iDACA,YAAY,KAEb;;KAEA,QAAQ,KAAK,IACZ,oBAAC;MACC,KAAK,KAAK;MACV,KAAI;MACJ,WAAU;OACV;KAEJ,oBAAC;MAAK,WAAU;gBAA2B,KAAK;OAAY;KAC5D,oBAAC;MACC,MAAK;MACL,OAAM;MACN,MAAK;MACL,MAAM,oBAAC,KAAE,WAAU,WAAW;MAC9B,eAAe,WAAW,KAAK,IAAI;MACnC,WAAU;MACV,cAAY,UAAU,KAAK;OAC3B;;MAvBG,KAAK,IAwBP,CACL;IACC;GAEH"}
@@ -1 +1 @@
1
- {"version":3,"file":"drawer.d.mts","names":[],"sources":["../../../src/components/organisms/drawer.tsx"],"mappings":";;;UA4BiB,KAAA;EACf,IAAA;EACA,QAAA,GAAW,KAAA,CAAM,SAAA;EACjB,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,QAAA;EACA,SAAA,GAAY,KAAA,CAAM,SAAA;EAClB,SAAA;EACA,IAAA;EACA,YAAA;EACA,SAAA;EACA,SAAA;EACA,OAAA;EACA,IAAA;EACA,SAAA;EACA,KAAA,GAAQ,KAAA,CAAM,aAAA;EACd,UAAA;IACE,IAAA;IACA,OAAA;IACA,SAAA;IACA,MAAA;IACA,KAAA;IACA,KAAA;IACA,KAAA;IACA,IAAA;IACA,MAAA;EAAA;EAEF,SAAA,GAAY,WAAA;EACZ,OAAA;AAAA;AAAA,cAqBI,MAAA;EAAU,IAAA;EAAA,KAAA;EAAA,KAAA;EAAA,MAAA;EAAA,QAAA;EAAA,SAAA;EAAA,SAAA;EAAA,IAAA;EAAA,YAAA;EAAA,SAAA;EAAA,SAAA;EAAA,OAAA;EAAA,IAAA;EAAA,SAAA;EAAA,UAAA;EAAA,KAAA;EAAA,QAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAqBb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"drawer.d.mts","names":[],"sources":["../../../src/components/organisms/drawer.tsx"],"mappings":";;;UA0CiB,KAAA;EACf,IAAA;EACA,QAAA,GAAW,KAAA,CAAM,SAAA;EACjB,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,QAAA;EACA,SAAA,GAAY,KAAA,CAAM,SAAA;EAClB,SAAA;EACA,IAAA;EACA,YAAA;EACA,SAAA;EACA,SAAA;EACA,OAAA;EACA,IAAA;EACA,SAAA;EACA,KAAA,GAAQ,KAAA,CAAM,aAAA;EACd,UAAA;IACE,IAAA;IACA,OAAA;IACA,SAAA;IACA,MAAA;IACA,KAAA;IACA,KAAA;IACA,KAAA;IACA,IAAA;IACA,MAAA;EAAA;EAEF,SAAA,GAAY,WAAA;EACZ,OAAA;AAAA;AAAA,cA8BI,MAAA;EAAU,IAAA;EAAA,KAAA;EAAA,KAAA;EAAA,MAAA;EAAA,QAAA;EAAA,SAAA;EAAA,SAAA;EAAA,IAAA;EAAA,YAAA;EAAA,SAAA;EAAA,SAAA;EAAA,OAAA;EAAA,IAAA;EAAA,SAAA;EAAA,UAAA;EAAA,KAAA;EAAA,QAAA;EAAA,SAAA;EAAA,OAAA;EAAA,GAAA;AAAA,GAqBb,KAAA,KAAK,kBAAA,CAAA,GAAA,CAAA,OAAA"}