@petnow/ui 4.1.8 → 4.1.9

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Popup-BCBW_e8Q.js","names":[],"sources":["../src/components/ui/dialog.tsx","../src/components/v1/popup/Popup.tsx"],"sourcesContent":["import { Dialog as DialogPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/utils/TailwindUtil\";\n\nconst Dialog = DialogPrimitive.Root;\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogPortal = DialogPrimitive.Portal;\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/40 duration-200\",\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 bg-background fixed top-1/2 left-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg p-6 shadow-lg duration-200 outline-none\",\n className,\n )}\n {...props}\n />\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nfunction DialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn(\"flex flex-col gap-2\", className)} {...props} />;\n}\n\nfunction DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn(\"flex flex-col gap-2 sm:flex-row sm:justify-end\", className)} {...props} />;\n}\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title ref={ref} className={cn(\"text-lg font-semibold\", className)} {...props} />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description ref={ref} className={cn(\"text-muted-foreground text-sm\", className)} {...props} />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../../../utils/TailwindUtil\";\nimport { CTAButton } from \"../cta-button/CTAButton\";\n\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"@/components/ui/dialog\";\n\ntype PopupAction = {\n label: string | React.ReactNode;\n icon?: React.ComponentType<{ className?: string }>;\n onClick?: () => void;\n};\n\nexport interface PopupProps {\n isOpen: boolean;\n setIsOpen: (isOpen: boolean) => void;\n onClose?: () => void;\n title?: string | React.ReactNode;\n description?: string | React.ReactNode;\n content?: React.ReactNode;\n confirm?: PopupAction;\n cancel?: PopupAction;\n preventEasyClose?: boolean;\n className?: string;\n}\n\nconst Popup = ({\n isOpen,\n setIsOpen,\n onClose,\n title,\n description,\n content,\n confirm,\n cancel,\n preventEasyClose = false,\n className,\n}: PopupProps) => {\n const handleClose = () => {\n setIsOpen(false);\n onClose?.();\n };\n\n const handleConfirmAction = (action?: PopupAction) => () => {\n action?.onClick?.();\n };\n\n const handleCancelAction = (action?: PopupAction) => () => {\n action?.onClick?.();\n handleClose();\n };\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (preventEasyClose && !nextOpen) {\n return;\n }\n\n if (!nextOpen) {\n onClose?.();\n }\n\n setIsOpen(nextOpen);\n };\n\n return (\n <Dialog open={isOpen} onOpenChange={handleOpenChange}>\n <DialogContent\n onEscapeKeyDown={preventEasyClose ? (event) => event.preventDefault() : undefined}\n onInteractOutside={preventEasyClose ? (event) => event.preventDefault() : undefined}\n className={cn(\n \"bg-surface-base-neutral-1 flex max-h-[440px] w-[300px] max-w-[300px] flex-col gap-4 overflow-hidden rounded-[16px] p-4\",\n className,\n )}\n >\n <div className=\"flex w-full flex-col gap-2 overflow-y-auto\">\n {title && <DialogTitle className=\"text-title-18-bold text-text-prominent-neutral-4\">{title}</DialogTitle>}\n {description && (\n <div className=\"overflow-y-auto\">\n <DialogDescription className=\"text-body-16-medium text-text-prominent-neutral-3\">\n {description}\n </DialogDescription>\n </div>\n )}\n {content && <div className=\"overflow-y-auto\">{content}</div>}\n </div>\n {(confirm || cancel) && (\n <div className=\"flex w-full flex-col gap-2\">\n {confirm && (\n <CTAButton\n label={confirm.label}\n icon={confirm.icon}\n size=\"medium\"\n hierarchy=\"primary\"\n onClick={handleConfirmAction(confirm)}\n />\n )}\n {cancel && (\n <CTAButton\n label={cancel.label}\n icon={cancel.icon}\n size=\"medium\"\n hierarchy=\"tertiary\"\n onClick={handleCancelAction(cancel)}\n />\n )}\n </div>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n\nexport { Popup };\n"],"mappings":";;;;;;AAKA,IAAM,IAAS,EAAgB;AACT,EAAgB;AACtC,IAAM,IAAe,EAAgB;AACjB,EAAgB;AAEpC,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAgB,SAAjB;CACO;CACL,WAAW,EACT,uKACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAc,cAAc,EAAgB,QAAQ;AAEpD,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,CAAgB,CAAA,GAChB,kBAAC,EAAgB,SAAjB;CACO;CACL,WAAW,EACT,gRACA,CACF;CACA,GAAI;AACL,CAAA,CACW,EAAA,CAAA,CACf;AACD,EAAc,cAAc,EAAgB,QAAQ;AAUpD,IAAM,IAAc,EAAM,YAGvB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAgB,OAAjB;CAA4B;CAAK,WAAW,EAAG,yBAAyB,CAAS;CAAG,GAAI;AAAQ,CAAA,CACjG;AACD,EAAY,cAAc,EAAgB,MAAM;AAEhD,IAAM,IAAoB,EAAM,YAG7B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAgB,aAAjB;CAAkC;CAAK,WAAW,EAAG,iCAAiC,CAAS;CAAG,GAAI;AAAQ,CAAA,CAC/G;AACD,EAAkB,cAAc,EAAgB,YAAY;;;ACrC5D,IAAM,KAAS,EACb,WACA,cACA,YACA,UACA,gBACA,YACA,YACA,WACA,sBAAmB,IACnB,mBACgB;CAChB,IAAM,UAAoB;EAExB,AADA,EAAU,EAAK,GACf,IAAU;CACZ;CAuBA,OACE,kBAAC,GAAD;EAAQ,MAAM;EAAQ,eAbE,MAAsB;GAC1C,KAAoB,CAAC,MAIpB,KACH,IAAU,GAGZ,EAAU,CAAQ;EACpB;YAII,kBAAC,GAAD;GACE,iBAAiB,KAAoB,MAAU,EAAM,eAAe,IAAI,KAAA;GACxE,mBAAmB,KAAoB,MAAU,EAAM,eAAe,IAAI,KAAA;GAC1E,WAAW,EACT,0HACA,CACF;aANF,CAQE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACG,KAAS,kBAAC,GAAD;MAAa,WAAU;gBAAoD;KAAmB,CAAA;KACvG,KACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAmB,WAAU;iBAC1B;MACgB,CAAA;KAChB,CAAA;KAEN,KAAW,kBAAC,OAAD;MAAK,WAAU;gBAAmB;KAAa,CAAA;IACxD;QACH,KAAW,MACX,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KACC,kBAAC,GAAD;KACE,OAAO,EAAQ;KACf,MAAM,EAAQ;KACd,MAAK;KACL,WAAU;KACV,WAlDe,YAA+B;MAC1D,GAAQ,UAAU;KACpB,GAgD2C,CAAO;IACrC,CAAA,GAEF,KACC,kBAAC,GAAD;KACE,OAAO,EAAO;KACd,MAAM,EAAO;KACb,MAAK;KACL,WAAU;KACV,WAvDc,YAA+B;MAEzD,AADA,GAAQ,UAAU,GAClB,EAAY;KACd,GAoD0C,CAAM;IACnC,CAAA,CAEA;KAEM;;CACT,CAAA;AAEZ"}
1
+ {"version":3,"file":"Popup-BCBW_e8Q.js","names":[],"sources":["../src/components/ui/dialog.tsx","../src/components/v1/popup/Popup.tsx"],"sourcesContent":["import { Dialog as DialogPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/utils/TailwindUtil\";\n\nconst Dialog = DialogPrimitive.Root;\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogPortal = DialogPrimitive.Portal;\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/40 duration-200\",\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 bg-background fixed top-1/2 left-1/2 z-50 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg p-6 shadow-lg duration-200 outline-none\",\n className,\n )}\n {...props}\n />\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nfunction DialogHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn(\"flex flex-col gap-2\", className)} {...props} />;\n}\n\nfunction DialogFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn(\"flex flex-col gap-2 sm:flex-row sm:justify-end\", className)} {...props} />;\n}\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title ref={ref} className={cn(\"text-lg font-semibold\", className)} {...props} />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description ref={ref} className={cn(\"text-muted-foreground text-sm\", className)} {...props} />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"../../../utils/TailwindUtil\";\nimport { CTAButton } from \"../cta-button/CTAButton\";\n\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"@/components/ui/dialog\";\n\ntype PopupAction = {\n label: string | React.ReactNode;\n icon?: React.ComponentType<{ className?: string }>;\n onClick?: () => void;\n};\n\nexport interface PopupProps {\n isOpen: boolean;\n setIsOpen: (isOpen: boolean) => void;\n onClose?: () => void;\n title?: string | React.ReactNode;\n description?: string | React.ReactNode;\n content?: React.ReactNode;\n confirm?: PopupAction;\n cancel?: PopupAction;\n preventEasyClose?: boolean;\n className?: string;\n}\n\nconst Popup = ({\n isOpen,\n setIsOpen,\n onClose,\n title,\n description,\n content,\n confirm,\n cancel,\n preventEasyClose = false,\n className,\n}: PopupProps) => {\n const handleClose = () => {\n setIsOpen(false);\n onClose?.();\n };\n\n const handleConfirmAction = (action?: PopupAction) => () => {\n action?.onClick?.();\n };\n\n const handleCancelAction = (action?: PopupAction) => () => {\n action?.onClick?.();\n handleClose();\n };\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (preventEasyClose && !nextOpen) {\n return;\n }\n\n if (!nextOpen) {\n onClose?.();\n }\n\n setIsOpen(nextOpen);\n };\n\n return (\n <Dialog open={isOpen} onOpenChange={handleOpenChange}>\n <DialogContent\n onEscapeKeyDown={preventEasyClose ? (event) => event.preventDefault() : undefined}\n onInteractOutside={preventEasyClose ? (event) => event.preventDefault() : undefined}\n className={cn(\n \"bg-surface-base-neutral-1 flex max-h-[440px] w-[300px] max-w-[300px] flex-col gap-4 overflow-hidden rounded-[16px] p-4\",\n className,\n )}\n >\n <div className=\"flex w-full flex-col gap-2 overflow-y-auto\">\n {title && <DialogTitle className=\"text-title-18-bold text-text-prominent-neutral-4\">{title}</DialogTitle>}\n {description && (\n <div className=\"overflow-y-auto\">\n <DialogDescription className=\"text-body-16-medium text-text-prominent-neutral-3\">\n {description}\n </DialogDescription>\n </div>\n )}\n {content && <div className=\"overflow-y-auto\">{content}</div>}\n </div>\n {(confirm || cancel) && (\n <div className=\"flex w-full flex-col gap-2\">\n {confirm && (\n <CTAButton\n label={confirm.label}\n icon={confirm.icon}\n size=\"medium\"\n hierarchy=\"primary\"\n onClick={handleConfirmAction(confirm)}\n />\n )}\n {cancel && (\n <CTAButton\n label={cancel.label}\n icon={cancel.icon}\n size=\"medium\"\n hierarchy=\"tertiary\"\n onClick={handleCancelAction(cancel)}\n />\n )}\n </div>\n )}\n </DialogContent>\n </Dialog>\n );\n};\n\nexport { Popup };\n"],"mappings":";;;;;;AAKA,IAAM,IAAS,EAAgB;AACT,EAAgB;AACtC,IAAM,IAAe,EAAgB;AACjB,EAAgB;AAEpC,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAgB,SAAjB;CACO;CACL,WAAW,EACT,uKACA,CACF;CACA,GAAI;AACL,CAAA,CACF;AACD,EAAc,cAAc,EAAgB,QAAQ;AAEpD,IAAM,IAAgB,EAAM,YAGzB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,CAAgB,CAAA,GAChB,kBAAC,EAAgB,SAAjB;CACO;CACL,WAAW,EACT,gRACA,CACF;CACA,GAAI;AACL,CAAA,CACW,EAAA,CAAA,CACf;AACD,EAAc,cAAc,EAAgB,QAAQ;AAUpD,IAAM,IAAc,EAAM,YAGvB,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAgB,OAAjB;CAA4B;CAAK,WAAW,EAAG,yBAAyB,CAAS;CAAG,GAAI;AAAQ,CAAA,CACjG;AACD,EAAY,cAAc,EAAgB,MAAM;AAEhD,IAAM,IAAoB,EAAM,YAG7B,EAAE,cAAW,GAAG,KAAS,MAC1B,kBAAC,EAAgB,aAAjB;CAAkC;CAAK,WAAW,EAAG,iCAAiC,CAAS;CAAG,GAAI;AAAQ,CAAA,CAC/G;AACD,EAAkB,cAAc,EAAgB,YAAY;;;ACrC5D,IAAM,KAAS,EACb,WACA,cACA,YACA,UACA,gBACA,YACA,YACA,WACA,sBAAmB,IACnB,mBACgB;CAChB,IAAM,UAAoB;EAExB,AADA,EAAU,EAAK,GACf,IAAU;CACZ;CAuBA,OACE,kBAAC,GAAD;EAAQ,MAAM;EAAQ,eAbE,MAAsB;GAC1C,KAAoB,CAAC,MAIpB,KACH,IAAU,GAGZ,EAAU,CAAQ;EACpB;YAII,kBAAC,GAAD;GACE,iBAAiB,KAAoB,MAAU,EAAM,eAAe,IAAI,KAAA;GACxE,mBAAmB,KAAoB,MAAU,EAAM,eAAe,IAAI,KAAA;GAC1E,WAAW,EACT,0HACA,CACF;aANF,CAQE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACG,KAAS,kBAAC,GAAD;MAAa,WAAU;gBAAoD;KAAmB,CAAA;KACvG,KACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAmB,WAAU;iBAC1B;MACgB,CAAA;KAChB,CAAA;KAEN,KAAW,kBAAC,OAAD;MAAK,WAAU;gBAAmB;KAAa,CAAA;IACxD;QACH,KAAW,MACX,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KACC,kBAAC,GAAD;KACE,OAAO,EAAQ;KACf,MAAM,EAAQ;KACd,MAAK;KACL,WAAU;KACV,WAlDe,YAA+B;MAC1D,GAAQ,UAAU;KACpB,EAgDuB,CAAoB,CAAO;IACrC,CAAA,GAEF,KACC,kBAAC,GAAD;KACE,OAAO,EAAO;KACd,MAAM,EAAO;KACb,MAAK;KACL,WAAU;KACV,WAvDc,YAA+B;MAEzD,AADA,GAAQ,UAAU,GAClB,EAAY;KACd,EAoDuB,CAAmB,CAAM;IACnC,CAAA,CAEA;KAEM;;CACT,CAAA;AAEZ"}
package/dist/v0/tabs.js CHANGED
@@ -1,62 +1,74 @@
1
1
  "use client";
2
2
  import { t as e } from "../TailwindUtil-DiNvXuNl.js";
3
3
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
4
- import { useRef as r, useState as i } from "react";
5
- import a from "react-swipeable-views";
4
+ import { useEffect as r, useRef as i, useState as a } from "react";
5
+ import { useKeenSlider as o } from "keen-slider/react";
6
+ import "keen-slider/keen-slider.min.css";
6
7
  //#region src/components/v0/tabs/Tabs.tsx
7
- var o = (e) => typeof e == "function" ? e : null, s = o(a.default?.default) ?? o(a.default) ?? o(a), c = ({ className: a, tabList: o, isCuratedcontent: c, unswipeableContent: l, defaultIndex: u = 0, onTabChange: d, disabled: f, allowScrollToSection: p = !0 }) => {
8
- let [m, h] = i(u), g = r(null), _ = (e) => {
8
+ var s = ({ className: s, tabList: c, isCuratedcontent: l, unswipeableContent: u, defaultIndex: d = 0, onTabChange: f, disabled: p, allowScrollToSection: m = !0 }) => {
9
+ let [h, g] = a(d), _ = i(null), v = i(h), y = i(f);
10
+ r(() => {
11
+ v.current = h, y.current = f;
12
+ });
13
+ let [b, x] = o({
14
+ initial: d,
15
+ drag: !p,
16
+ dragEnded: (e) => {
17
+ let t = e.track.absToRel(e.animator.targetIdx ?? e.track.details.abs);
18
+ t !== v.current && (g(t), y.current?.(t));
19
+ }
20
+ }), S = (e) => {
9
21
  e.current && window.scrollTo({
10
22
  top: e.current.offsetTop - 50,
11
23
  behavior: "smooth"
12
24
  });
13
- }, v = (e) => {
14
- h(e), p && _(g), d?.(e);
25
+ }, C = (e) => {
26
+ g(e), v.current = e, m && S(_), x.current?.moveToIdx(e), f?.(e);
15
27
  };
16
28
  return /* @__PURE__ */ n("div", {
17
- ref: g,
29
+ ref: _,
18
30
  className: "w-full",
19
31
  children: [
20
32
  /* @__PURE__ */ n("div", {
21
- className: e(a?.tab, `z-50 mb-[20px] flex w-full flex-col bg-white ${c && "sticky top-[50px]"}`),
33
+ className: e(s?.tab, `z-50 mb-[20px] flex w-full flex-col bg-white ${l && "sticky top-[50px]"}`),
22
34
  children: [/* @__PURE__ */ t("div", {
23
35
  className: "flex",
24
- children: o.map((n, r) => /* @__PURE__ */ t("div", {
36
+ children: c.map((n, r) => /* @__PURE__ */ t("div", {
25
37
  className: "flex flex-1 flex-col",
26
38
  children: /* @__PURE__ */ t("button", {
27
- className: e(a?.tabTitle, `cursor-pointer ${m === r ? "text-petnow-grey-30 text-label-large" : "text-petnow-grey-70 text-body-large disabled:opacity-40"}`),
28
- onClick: () => v(r),
29
- disabled: f,
39
+ className: e(s?.tabTitle, `cursor-pointer ${h === r ? "text-petnow-grey-30 text-label-large" : "text-petnow-grey-70 text-body-large disabled:opacity-40"}`),
40
+ onClick: () => C(r),
41
+ disabled: p,
30
42
  children: n.displayName
31
43
  })
32
44
  }, n.key))
33
45
  }), /* @__PURE__ */ t("div", {
34
- className: e(a?.underline, `relative h-[2px] w-full ${f ? "bg-petnow-grey-70/40" : "bg-petnow-grey-70"}`),
46
+ className: e(s?.underline, `relative h-[2px] w-full ${p ? "bg-petnow-grey-70/40" : "bg-petnow-grey-70"}`),
35
47
  children: /* @__PURE__ */ t("div", {
36
- className: e(a?.selectedUnderline, "bg-petnow-grey-30 absolute h-[2px] transition-all duration-200"),
48
+ className: e(s?.selectedUnderline, "bg-petnow-grey-30 absolute h-[2px] transition-all duration-200"),
37
49
  style: (() => {
38
- let e = 100 / o.length;
50
+ let e = 100 / c.length;
39
51
  return {
40
52
  width: `${e}%`,
41
- left: `${m * e}%`
53
+ left: `${h * e}%`
42
54
  };
43
55
  })()
44
56
  })
45
57
  })]
46
58
  }),
47
- l,
48
- s ? /* @__PURE__ */ t(s, {
49
- index: m,
50
- onChangeIndex: (e) => {
51
- h(e), d?.(e);
52
- },
53
- disabled: f,
54
- children: o.map((e) => /* @__PURE__ */ t("div", { children: e.content }, e.key))
55
- }) : /* @__PURE__ */ t("div", { children: o[m]?.content })
59
+ u,
60
+ /* @__PURE__ */ t("div", {
61
+ ref: b,
62
+ className: "keen-slider",
63
+ children: c.map((e) => /* @__PURE__ */ t("div", {
64
+ className: "keen-slider__slide",
65
+ children: e.content
66
+ }, e.key))
67
+ })
56
68
  ]
57
69
  });
58
70
  };
59
71
  //#endregion
60
- export { c as default };
72
+ export { s as default };
61
73
 
62
74
  //# sourceMappingURL=tabs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","names":[],"sources":["../../src/components/v0/tabs/Tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport { ReactNode, useRef, useState } from \"react\";\nimport SwipeableViewsImport from \"react-swipeable-views\";\n\nimport { cn } from \"../../../utils/TailwindUtil\";\n\ntype SwipeableViewsProps = {\n index: number;\n onChangeIndex?: (index: number) => void;\n disabled?: boolean;\n children?: ReactNode;\n};\n\nconst asSwipeableViews = (candidate: unknown): React.ComponentType<SwipeableViewsProps> | null => {\n return typeof candidate === \"function\" ? (candidate as React.ComponentType<SwipeableViewsProps>) : null;\n};\n\nconst SwipeableViews =\n asSwipeableViews((SwipeableViewsImport as { default?: { default?: unknown } }).default?.default) ??\n asSwipeableViews((SwipeableViewsImport as { default?: unknown }).default) ??\n asSwipeableViews(SwipeableViewsImport);\n\ninterface TabItem {\n readonly displayName: string;\n readonly key: string;\n readonly content: ReactNode;\n}\n\ninterface Props<T extends TabItem> {\n tabList: Readonly<T[]>;\n isCuratedcontent?: true;\n unswipeableContent?: ReactNode;\n defaultIndex?: number;\n onTabChange?: (index: number) => void;\n disabled?: boolean;\n className?: {\n tab?: string;\n tabTitle?: string;\n selectedUnderline?: string;\n underline?: string;\n };\n allowScrollToSection?: boolean;\n}\n\nconst Tabs = <T extends TabItem>({\n className,\n tabList,\n isCuratedcontent,\n unswipeableContent,\n defaultIndex = 0,\n onTabChange,\n disabled,\n allowScrollToSection = true,\n}: Props<T>) => {\n const [currentTabIndex, setCurrentTabIndex] = useState<number>(defaultIndex);\n const TabRef = useRef<HTMLDivElement>(null);\n\n const scrollToSection = (elementRef: React.RefObject<HTMLDivElement | null>) => {\n if (elementRef.current) {\n window.scrollTo({\n top: elementRef.current.offsetTop - 50,\n behavior: \"smooth\",\n });\n }\n };\n\n const handleTabClick = (index: number) => {\n setCurrentTabIndex(index);\n if (allowScrollToSection) scrollToSection(TabRef);\n onTabChange?.(index);\n };\n\n const underlineStyle = () => {\n const listLength = tabList.length;\n const widthPercent = 100 / listLength;\n return {\n width: `${widthPercent}%`,\n left: `${currentTabIndex * widthPercent}%`,\n };\n };\n\n return (\n <div ref={TabRef} className=\"w-full\">\n <div\n className={cn(\n className?.tab,\n `z-50 mb-[20px] flex w-full flex-col bg-white ${isCuratedcontent && \"sticky top-[50px]\"}`,\n )}\n >\n <div className=\"flex\">\n {tabList.map((tab, index) => (\n <div key={tab.key} className=\"flex flex-1 flex-col\">\n <button\n className={cn(\n className?.tabTitle,\n `cursor-pointer ${\n currentTabIndex === index\n ? \"text-petnow-grey-30 text-label-large\"\n : \"text-petnow-grey-70 text-body-large disabled:opacity-40\"\n }`,\n )}\n onClick={() => handleTabClick(index)}\n disabled={disabled}\n >\n {tab.displayName}\n </button>\n </div>\n ))}\n </div>\n <div\n className={cn(\n className?.underline,\n `relative h-[2px] w-full ${disabled ? \"bg-petnow-grey-70/40\" : \"bg-petnow-grey-70\"}`,\n )}\n >\n <div\n className={cn(\n className?.selectedUnderline,\n \"bg-petnow-grey-30 absolute h-[2px] transition-all duration-200\",\n )}\n style={underlineStyle()}\n />\n </div>\n </div>\n\n {unswipeableContent}\n\n {SwipeableViews ? (\n <SwipeableViews\n index={currentTabIndex}\n onChangeIndex={(index) => {\n setCurrentTabIndex(index);\n onTabChange?.(index);\n }}\n disabled={disabled}\n >\n {tabList.map((tab) => (\n <div key={tab.key}>{tab.content}</div>\n ))}\n </SwipeableViews>\n ) : (\n <div>{tabList[currentTabIndex]?.content}</div>\n )}\n </div>\n );\n};\n\nexport default Tabs;\n"],"mappings":";;;;;;AAcA,IAAM,KAAoB,MACjB,OAAO,KAAc,aAAc,IAAyD,MAG/F,IACJ,EAAkB,EAA6D,SAAS,OAAO,KAC/F,EAAkB,EAA+C,OAAO,KACxE,EAAiB,CAAoB,GAwBjC,KAA2B,EAC/B,cACA,YACA,qBACA,uBACA,kBAAe,GACf,gBACA,aACA,0BAAuB,SACT;CACd,IAAM,CAAC,GAAiB,KAAsB,EAAiB,CAAY,GACrE,IAAS,EAAuB,IAAI,GAEpC,KAAmB,MAAuD;EAC9E,AAAI,EAAW,WACb,OAAO,SAAS;GACd,KAAK,EAAW,QAAQ,YAAY;GACpC,UAAU;EACZ,CAAC;CAEL,GAEM,KAAkB,MAAkB;EAGxC,AAFA,EAAmB,CAAK,GACpB,KAAsB,EAAgB,CAAM,GAChD,IAAc,CAAK;CACrB;CAWA,OACE,kBAAC,OAAD;EAAK,KAAK;EAAQ,WAAU;YAA5B;GACE,kBAAC,OAAD;IACE,WAAW,EACT,GAAW,KACX,gDAAgD,KAAoB,qBACtE;cAJF,CAME,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAQ,KAAK,GAAK,MACjB,kBAAC,OAAD;MAAmB,WAAU;gBAC3B,kBAAC,UAAD;OACE,WAAW,EACT,GAAW,UACX,kBACE,MAAoB,IAChB,yCACA,2DAER;OACA,eAAe,EAAe,CAAK;OACzB;iBAET,EAAI;MACC,CAAA;KACL,GAfK,EAAI,GAeT,CACN;IACE,CAAA,GACL,kBAAC,OAAD;KACE,WAAW,EACT,GAAW,WACX,2BAA2B,IAAW,yBAAyB,qBACjE;eAEA,kBAAC,OAAD;MACE,WAAW,EACT,GAAW,mBACX,gEACF;MACA,cAhDmB;OAE3B,IAAM,IAAe,MADF,EAAQ;OAE3B,OAAO;QACL,OAAO,GAAG,EAAa;QACvB,MAAM,GAAG,IAAkB,EAAa;OAC1C;MACF,GAyCgC;KACvB,CAAA;IACE,CAAA,CACF;;GAEJ;GAEA,IACC,kBAAC,GAAD;IACE,OAAO;IACP,gBAAgB,MAAU;KAExB,AADA,EAAmB,CAAK,GACxB,IAAc,CAAK;IACrB;IACU;cAET,EAAQ,KAAK,MACZ,kBAAC,OAAD,EAAA,UAAoB,EAAI,QAAa,GAA3B,EAAI,GAAuB,CACtC;GACa,CAAA,IAEhB,kBAAC,OAAD,EAAA,UAAM,EAAQ,IAAkB,QAAa,CAAA;EAE5C;;AAET"}
1
+ {"version":3,"file":"tabs.js","names":[],"sources":["../../src/components/v0/tabs/Tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport { ReactNode, useEffect, useRef, useState } from \"react\";\nimport { useKeenSlider } from \"keen-slider/react\";\n\nimport \"keen-slider/keen-slider.min.css\";\n\nimport { cn } from \"../../../utils/TailwindUtil\";\n\ninterface TabItem {\n readonly displayName: string;\n readonly key: string;\n readonly content: ReactNode;\n}\n\ninterface Props<T extends TabItem> {\n tabList: Readonly<T[]>;\n isCuratedcontent?: true;\n unswipeableContent?: ReactNode;\n defaultIndex?: number;\n onTabChange?: (index: number) => void;\n disabled?: boolean;\n className?: {\n tab?: string;\n tabTitle?: string;\n selectedUnderline?: string;\n underline?: string;\n };\n allowScrollToSection?: boolean;\n}\n\nconst Tabs = <T extends TabItem>({\n className,\n tabList,\n isCuratedcontent,\n unswipeableContent,\n defaultIndex = 0,\n onTabChange,\n disabled,\n allowScrollToSection = true,\n}: Props<T>) => {\n const [currentTabIndex, setCurrentTabIndex] = useState<number>(defaultIndex);\n const TabRef = useRef<HTMLDivElement>(null);\n // keen-slider keeps the callbacks it was created with, so they read the latest values from refs.\n const currentTabIndexRef = useRef(currentTabIndex);\n const onTabChangeRef = useRef(onTabChange);\n\n useEffect(() => {\n currentTabIndexRef.current = currentTabIndex;\n onTabChangeRef.current = onTabChange;\n });\n\n // When a swipe is released, keen-slider has already started snapping and `animator.targetIdx`\n // holds the tab it lands on, so the tab changes once per swipe, as with react-swipeable-views.\n const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({\n initial: defaultIndex,\n drag: !disabled,\n dragEnded: (instance) => {\n const index = instance.track.absToRel(instance.animator.targetIdx ?? instance.track.details.abs);\n if (index === currentTabIndexRef.current) return;\n setCurrentTabIndex(index);\n onTabChangeRef.current?.(index);\n },\n });\n\n const scrollToSection = (elementRef: React.RefObject<HTMLDivElement | null>) => {\n if (elementRef.current) {\n window.scrollTo({\n top: elementRef.current.offsetTop - 50,\n behavior: \"smooth\",\n });\n }\n };\n\n const handleTabClick = (index: number) => {\n setCurrentTabIndex(index);\n currentTabIndexRef.current = index;\n if (allowScrollToSection) scrollToSection(TabRef);\n slider.current?.moveToIdx(index);\n onTabChange?.(index);\n };\n\n const underlineStyle = () => {\n const listLength = tabList.length;\n const widthPercent = 100 / listLength;\n return {\n width: `${widthPercent}%`,\n left: `${currentTabIndex * widthPercent}%`,\n };\n };\n\n return (\n <div ref={TabRef} className=\"w-full\">\n <div\n className={cn(\n className?.tab,\n `z-50 mb-[20px] flex w-full flex-col bg-white ${isCuratedcontent && \"sticky top-[50px]\"}`,\n )}\n >\n <div className=\"flex\">\n {tabList.map((tab, index) => (\n <div key={tab.key} className=\"flex flex-1 flex-col\">\n <button\n className={cn(\n className?.tabTitle,\n `cursor-pointer ${\n currentTabIndex === index\n ? \"text-petnow-grey-30 text-label-large\"\n : \"text-petnow-grey-70 text-body-large disabled:opacity-40\"\n }`,\n )}\n onClick={() => handleTabClick(index)}\n disabled={disabled}\n >\n {tab.displayName}\n </button>\n </div>\n ))}\n </div>\n <div\n className={cn(\n className?.underline,\n `relative h-[2px] w-full ${disabled ? \"bg-petnow-grey-70/40\" : \"bg-petnow-grey-70\"}`,\n )}\n >\n <div\n className={cn(\n className?.selectedUnderline,\n \"bg-petnow-grey-30 absolute h-[2px] transition-all duration-200\",\n )}\n style={underlineStyle()}\n />\n </div>\n </div>\n\n {unswipeableContent}\n\n <div ref={sliderRef} className=\"keen-slider\">\n {tabList.map((tab) => (\n <div key={tab.key} className=\"keen-slider__slide\">\n {tab.content}\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default Tabs;\n"],"mappings":";;;;;;;AA+BA,IAAM,KAA2B,EAC/B,cACA,YACA,qBACA,uBACA,kBAAe,GACf,gBACA,aACA,0BAAuB,SACT;CACd,IAAM,CAAC,GAAiB,KAAsB,EAAiB,CAAY,GACrE,IAAS,EAAuB,IAAI,GAEpC,IAAqB,EAAO,CAAe,GAC3C,IAAiB,EAAO,CAAW;CAEzC,QAAgB;EAEd,AADA,EAAmB,UAAU,GAC7B,EAAe,UAAU;CAC3B,CAAC;CAID,IAAM,CAAC,GAAW,KAAU,EAA8B;EACxD,SAAS;EACT,MAAM,CAAC;EACP,YAAY,MAAa;GACvB,IAAM,IAAQ,EAAS,MAAM,SAAS,EAAS,SAAS,aAAa,EAAS,MAAM,QAAQ,GAAG;GAC3F,MAAU,EAAmB,YACjC,EAAmB,CAAK,GACxB,EAAe,UAAU,CAAK;EAChC;CACF,CAAC,GAEK,KAAmB,MAAuD;EAC9E,AAAI,EAAW,WACb,OAAO,SAAS;GACd,KAAK,EAAW,QAAQ,YAAY;GACpC,UAAU;EACZ,CAAC;CAEL,GAEM,KAAkB,MAAkB;EAKxC,AAJA,EAAmB,CAAK,GACxB,EAAmB,UAAU,GACzB,KAAsB,EAAgB,CAAM,GAChD,EAAO,SAAS,UAAU,CAAK,GAC/B,IAAc,CAAK;CACrB;CAWA,OACE,kBAAC,OAAD;EAAK,KAAK;EAAQ,WAAU;YAA5B;GACE,kBAAC,OAAD;IACE,WAAW,EACT,GAAW,KACX,gDAAgD,KAAoB,qBACtE;cAJF,CAME,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAQ,KAAK,GAAK,MACjB,kBAAC,OAAD;MAAmB,WAAU;gBAC3B,kBAAC,UAAD;OACE,WAAW,EACT,GAAW,UACX,kBACE,MAAoB,IAChB,yCACA,2DAER;OACA,eAAe,EAAe,CAAK;OACzB;iBAET,EAAI;MACC,CAAA;KACL,GAfK,EAAI,GAeT,CACN;IACE,CAAA,GACL,kBAAC,OAAD;KACE,WAAW,EACT,GAAW,WACX,2BAA2B,IAAW,yBAAyB,qBACjE;eAEA,kBAAC,OAAD;MACE,WAAW,EACT,GAAW,mBACX,gEACF;MACA,cAhDmB;OAE3B,IAAM,IAAe,MADF,EAAQ;OAE3B,OAAO;QACL,OAAO,GAAG,EAAa;QACvB,MAAM,GAAG,IAAkB,EAAa;OAC1C;MACF,EAyCiB,CAAe;KACvB,CAAA;IACE,CAAA,CACF;;GAEJ;GAED,kBAAC,OAAD;IAAK,KAAK;IAAW,WAAU;cAC5B,EAAQ,KAAK,MACZ,kBAAC,OAAD;KAAmB,WAAU;eAC1B,EAAI;IACF,GAFK,EAAI,GAET,CACN;GACE,CAAA;EACF;;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"text-field.js","names":[],"sources":["../../src/components/v1/text-field/TextField.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { CTAButton } from \"../cta-button/CTAButton\";\nimport { CancelFilledIcon } from \"../icons/action/CancelFilledIcon\";\nimport { ChevronLeftIcon } from \"../icons/action/ChevronLeftIcon\";\n\nimport { cn } from \"@/utils/TailwindUtil\";\n\n// TextField Normal 컴포넌트 스타일 정의\nconst textFieldNormalContainerVariants = cva(\n \"flex items-center rounded-[4px] bg-surface-base-neutral-2 border transition-colors duration-200\",\n {\n variants: {\n size: {\n large: \"gap-2 p-[15px] min-h-[56px]\",\n small: \"gap-3 p-[11px] min-h-[48px]\",\n },\n hasError: {\n true: \"border-border-prominent-error\",\n false: \"border-transparent\",\n },\n disabled: {\n true: \"opacity-50\",\n false: \"\",\n },\n },\n defaultVariants: {\n size: \"large\",\n disabled: false,\n hasError: false,\n },\n },\n);\n\nconst textFieldAssistiveAreaVariants = cva(\"\", {\n variants: {\n size: {\n large: \"text-body-16-regular\",\n small: \"text-caption-12-medium\",\n },\n hasError: {\n true: \"text-text-prominent-error\",\n false: \"text-text-base-neutral-2\",\n },\n },\n defaultVariants: {\n size: \"large\",\n hasError: false,\n },\n});\n\ninterface TextFieldNormalProps extends Omit<React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, \"size\"> {\n subtitle?: string;\n isRequired?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n disabled?: boolean;\n multiLine?: boolean;\n className?: string;\n rightElement?: React.ReactNode;\n showCounter?: boolean;\n size?: \"large\" | \"small\";\n}\n\nconst TextFieldNormal = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, TextFieldNormalProps>(\n (\n {\n onChange,\n subtitle,\n isRequired = false,\n assistiveText,\n errorText,\n disabled = false,\n multiLine = false,\n className,\n rightElement,\n showCounter = false,\n value,\n maxLength,\n size = \"large\",\n ...inputProps\n },\n ref,\n ) => {\n const hasError = !!errorText;\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement | HTMLTextAreaElement);\n\n const handleContainerClick = React.useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n const stringValue = typeof value === \"string\" ? value : \"\";\n const currentLength = stringValue.length;\n\n const inputPropsForInput = inputProps as React.ComponentPropsWithoutRef<\"input\">;\n const inputPropsForTextarea = inputProps as React.ComponentPropsWithoutRef<\"textarea\">;\n\n // 사이즈별 폰트 크기\n const inputFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n const subtitleFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const assistiveFontSize = size === \"large\" ? \"text-body-16-regular\" : \"text-caption-12-medium\";\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {subtitle && (\n <span className={cn(subtitleFontSize, \"text-text-base-neutral-5\")}>\n {subtitle}\n {isRequired && <span className=\"text-text-prominent-accent-1\">*</span>}\n </span>\n )}\n\n <div\n onClick={disabled ? undefined : handleContainerClick}\n className={cn(\n \"group overflow-hidden\",\n textFieldNormalContainerVariants({ size, disabled, hasError }),\n !disabled && !hasError && \"focus-within:border-border-base-neutral-4\",\n multiLine && \"h-[120px] items-start\",\n )}\n >\n {multiLine ? (\n <textarea\n {...inputPropsForTextarea}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLTextAreaElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 h-full min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"resize-none overflow-y-auto\",\n )}\n />\n ) : (\n <input\n {...inputPropsForInput}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLInputElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"overflow-hidden text-ellipsis whitespace-nowrap\",\n )}\n />\n )}\n\n {rightElement && <div className=\"shrink-0\">{rightElement}</div>}\n\n <button\n type=\"button\"\n onClick={() =>\n onChange &&\n onChange({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)\n }\n tabIndex={-1}\n disabled={disabled}\n className={cn(\"hidden shrink-0\", {\n flex: hasError,\n \"group-focus-within:flex\": !disabled && currentLength > 0,\n })}\n >\n <CancelFilledIcon className=\"text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer\" />\n </button>\n </div>\n\n {(assistiveText || errorText || (maxLength && showCounter)) && (\n <div className=\"flex items-center justify-between gap-2\">\n {(assistiveText || errorText) && (\n <span className={cn(assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {errorText || assistiveText}\n </span>\n )}\n {maxLength && showCounter && (\n <span className={cn(\"ml-auto\", assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {currentLength}/{maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldNormal.displayName = \"TextFieldNormal\";\n\n// TextField Select 컴포넌트\nconst textFieldSelectVariants = cva(\n \"flex items-center justify-between rounded-[4px] bg-surface-base-neutral-2 border transition-colors duration-200\",\n {\n variants: {\n size: {\n large: \"gap-2 p-[15px] min-h-[56px]\",\n small: \"gap-3 p-[11px] min-h-[48px]\",\n },\n hasError: {\n true: \"border-border-prominent-error\",\n false: \"border-transparent\",\n },\n disabled: {\n true: \"opacity-50\",\n false: \"\",\n },\n },\n defaultVariants: {\n size: \"large\",\n },\n },\n);\n\ninterface TextFieldSelectProps extends VariantProps<typeof textFieldSelectVariants> {\n label?: string;\n placeholder: string;\n value?: string;\n isRequired?: boolean;\n disabled?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n onPress?: () => void;\n className?: string;\n size?: \"large\" | \"small\";\n}\n\nconst TextFieldSelect = ({\n label,\n placeholder,\n value,\n isRequired = false,\n disabled = false,\n assistiveText,\n errorText,\n onPress,\n className,\n size = \"large\",\n}: TextFieldSelectProps) => {\n const hasError = !!errorText;\n\n // 사이즈별 폰트 크기\n const labelFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const valueFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n\n return (\n <div className={cn(\"flex w-full flex-col gap-2\", className)}>\n {/* Label with optional asterisk */}\n {label && (\n <div className=\"flex items-start\">\n <span className={cn(labelFontSize, \"text-text-base-neutral-5\")}>{label}</span>\n {isRequired && <span className={cn(labelFontSize, \"text-text-prominent-accent-1\")}>*</span>}\n </div>\n )}\n {/* Select Field */}\n <button\n type=\"button\"\n className={textFieldSelectVariants({ size, hasError, disabled })}\n onClick={onPress}\n disabled={disabled}\n >\n <span\n className={cn(valueFontSize, \"flex-1\", value ? \"text-text-base-neutral-5\" : \"text-text-base-neutral-2\")}\n style={{ textAlign: \"left\", overflow: \"hidden\", textOverflow: \"ellipsis\" }}\n >\n {value || placeholder}\n </span>\n <ChevronLeftIcon className=\"text-icon-base-neutral-3 rotate-270\" />\n </button>\n {/* Assistive/Error Text */}\n {(assistiveText || errorText) && (\n <div className=\"flex items-start gap-2\">\n <span className={textFieldAssistiveAreaVariants({ size, hasError })}>{errorText || assistiveText}</span>\n </div>\n )}\n </div>\n );\n};\n\n// TextField With Button 컴포넌트\ninterface TextFieldWithButtonProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, \"size\"> {\n subtitle?: string;\n isRequired?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n disabled?: boolean;\n multiLine?: boolean;\n className?: string;\n showCounter?: boolean;\n size?: \"large\" | \"small\";\n fieldRightElement?: React.ReactNode;\n buttonText: string;\n onButtonClick: () => void;\n buttonDisabled?: boolean;\n}\n\nconst TextFieldWithButton = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, TextFieldWithButtonProps>(\n (\n {\n onChange,\n subtitle,\n isRequired = false,\n assistiveText,\n errorText,\n disabled = false,\n multiLine = false,\n className,\n showCounter = false,\n value,\n maxLength,\n size = \"large\",\n fieldRightElement,\n buttonText,\n onButtonClick,\n buttonDisabled = false,\n ...inputProps\n },\n ref,\n ) => {\n const hasError = !!errorText;\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement | HTMLTextAreaElement);\n\n const handleContainerClick = React.useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n const stringValue = typeof value === \"string\" ? value : \"\";\n const currentLength = stringValue.length;\n\n const inputPropsForInput = inputProps as React.ComponentPropsWithoutRef<\"input\">;\n const inputPropsForTextarea = inputProps as React.ComponentPropsWithoutRef<\"textarea\">;\n\n // 사이즈별 폰트 크기\n const inputFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n const subtitleFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const assistiveFontSize = size === \"large\" ? \"text-body-16-regular\" : \"text-caption-12-medium\";\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {subtitle && (\n <span className={cn(subtitleFontSize, \"text-text-base-neutral-5\")}>\n {subtitle}\n {isRequired && <span className=\"text-text-prominent-accent-1\">*</span>}\n </span>\n )}\n\n <div className=\"flex items-center gap-2\">\n <div\n onClick={disabled ? undefined : handleContainerClick}\n className={cn(\n \"group flex-1 overflow-hidden\",\n textFieldNormalContainerVariants({ size, disabled, hasError }),\n !disabled && !hasError && \"focus-within:border-border-base-neutral-4\",\n multiLine && \"h-[120px] items-start\",\n )}\n >\n {multiLine ? (\n <textarea\n {...inputPropsForTextarea}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLTextAreaElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"resize-none overflow-y-auto\",\n )}\n />\n ) : (\n <input\n {...inputPropsForInput}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLInputElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"overflow-hidden text-ellipsis whitespace-nowrap\",\n )}\n />\n )}\n\n {fieldRightElement && <div className=\"shrink-0\">{fieldRightElement}</div>}\n\n <button\n type=\"button\"\n onClick={() =>\n onChange &&\n onChange({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)\n }\n tabIndex={-1}\n disabled={disabled}\n className={cn(\"hidden shrink-0\", {\n flex: hasError,\n \"group-focus-within:flex\": !disabled && currentLength > 0,\n })}\n >\n <CancelFilledIcon className=\"text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer\" />\n </button>\n </div>\n\n <div className=\"shrink-0\">\n <CTAButton\n label={buttonText}\n onClick={onButtonClick}\n size=\"medium\"\n hierarchy=\"tertiary\"\n disabled={buttonDisabled || disabled}\n />\n </div>\n </div>\n\n {(assistiveText || errorText || (maxLength && showCounter)) && (\n <div className=\"flex items-center justify-between gap-2\">\n {(assistiveText || errorText) && (\n <span className={cn(assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {errorText || assistiveText}\n </span>\n )}\n {maxLength && showCounter && (\n <span className={cn(\"ml-auto\", assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {currentLength}/{maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldWithButton.displayName = \"TextFieldWithButton\";\n\nexport { TextFieldNormal, TextFieldSelect, TextFieldWithButton };\n"],"mappings":"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"}
1
+ {"version":3,"file":"text-field.js","names":[],"sources":["../../src/components/v1/text-field/TextField.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { CTAButton } from \"../cta-button/CTAButton\";\nimport { CancelFilledIcon } from \"../icons/action/CancelFilledIcon\";\nimport { ChevronLeftIcon } from \"../icons/action/ChevronLeftIcon\";\n\nimport { cn } from \"@/utils/TailwindUtil\";\n\n// TextField Normal 컴포넌트 스타일 정의\nconst textFieldNormalContainerVariants = cva(\n \"flex items-center rounded-[4px] bg-surface-base-neutral-2 border transition-colors duration-200\",\n {\n variants: {\n size: {\n large: \"gap-2 p-[15px] min-h-[56px]\",\n small: \"gap-3 p-[11px] min-h-[48px]\",\n },\n hasError: {\n true: \"border-border-prominent-error\",\n false: \"border-transparent\",\n },\n disabled: {\n true: \"opacity-50\",\n false: \"\",\n },\n },\n defaultVariants: {\n size: \"large\",\n disabled: false,\n hasError: false,\n },\n },\n);\n\nconst textFieldAssistiveAreaVariants = cva(\"\", {\n variants: {\n size: {\n large: \"text-body-16-regular\",\n small: \"text-caption-12-medium\",\n },\n hasError: {\n true: \"text-text-prominent-error\",\n false: \"text-text-base-neutral-2\",\n },\n },\n defaultVariants: {\n size: \"large\",\n hasError: false,\n },\n});\n\ninterface TextFieldNormalProps extends Omit<React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, \"size\"> {\n subtitle?: string;\n isRequired?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n disabled?: boolean;\n multiLine?: boolean;\n className?: string;\n rightElement?: React.ReactNode;\n showCounter?: boolean;\n size?: \"large\" | \"small\";\n}\n\nconst TextFieldNormal = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, TextFieldNormalProps>(\n (\n {\n onChange,\n subtitle,\n isRequired = false,\n assistiveText,\n errorText,\n disabled = false,\n multiLine = false,\n className,\n rightElement,\n showCounter = false,\n value,\n maxLength,\n size = \"large\",\n ...inputProps\n },\n ref,\n ) => {\n const hasError = !!errorText;\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement | HTMLTextAreaElement);\n\n const handleContainerClick = React.useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n const stringValue = typeof value === \"string\" ? value : \"\";\n const currentLength = stringValue.length;\n\n const inputPropsForInput = inputProps as React.ComponentPropsWithoutRef<\"input\">;\n const inputPropsForTextarea = inputProps as React.ComponentPropsWithoutRef<\"textarea\">;\n\n // 사이즈별 폰트 크기\n const inputFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n const subtitleFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const assistiveFontSize = size === \"large\" ? \"text-body-16-regular\" : \"text-caption-12-medium\";\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {subtitle && (\n <span className={cn(subtitleFontSize, \"text-text-base-neutral-5\")}>\n {subtitle}\n {isRequired && <span className=\"text-text-prominent-accent-1\">*</span>}\n </span>\n )}\n\n <div\n onClick={disabled ? undefined : handleContainerClick}\n className={cn(\n \"group overflow-hidden\",\n textFieldNormalContainerVariants({ size, disabled, hasError }),\n !disabled && !hasError && \"focus-within:border-border-base-neutral-4\",\n multiLine && \"h-[120px] items-start\",\n )}\n >\n {multiLine ? (\n <textarea\n {...inputPropsForTextarea}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLTextAreaElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 h-full min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"resize-none overflow-y-auto\",\n )}\n />\n ) : (\n <input\n {...inputPropsForInput}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLInputElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"overflow-hidden text-ellipsis whitespace-nowrap\",\n )}\n />\n )}\n\n {rightElement && <div className=\"shrink-0\">{rightElement}</div>}\n\n <button\n type=\"button\"\n onClick={() =>\n onChange &&\n onChange({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)\n }\n tabIndex={-1}\n disabled={disabled}\n className={cn(\"hidden shrink-0\", {\n flex: hasError,\n \"group-focus-within:flex\": !disabled && currentLength > 0,\n })}\n >\n <CancelFilledIcon className=\"text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer\" />\n </button>\n </div>\n\n {(assistiveText || errorText || (maxLength && showCounter)) && (\n <div className=\"flex items-center justify-between gap-2\">\n {(assistiveText || errorText) && (\n <span className={cn(assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {errorText || assistiveText}\n </span>\n )}\n {maxLength && showCounter && (\n <span className={cn(\"ml-auto\", assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {currentLength}/{maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldNormal.displayName = \"TextFieldNormal\";\n\n// TextField Select 컴포넌트\nconst textFieldSelectVariants = cva(\n \"flex items-center justify-between rounded-[4px] bg-surface-base-neutral-2 border transition-colors duration-200\",\n {\n variants: {\n size: {\n large: \"gap-2 p-[15px] min-h-[56px]\",\n small: \"gap-3 p-[11px] min-h-[48px]\",\n },\n hasError: {\n true: \"border-border-prominent-error\",\n false: \"border-transparent\",\n },\n disabled: {\n true: \"opacity-50\",\n false: \"\",\n },\n },\n defaultVariants: {\n size: \"large\",\n },\n },\n);\n\ninterface TextFieldSelectProps extends VariantProps<typeof textFieldSelectVariants> {\n label?: string;\n placeholder: string;\n value?: string;\n isRequired?: boolean;\n disabled?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n onPress?: () => void;\n className?: string;\n size?: \"large\" | \"small\";\n}\n\nconst TextFieldSelect = ({\n label,\n placeholder,\n value,\n isRequired = false,\n disabled = false,\n assistiveText,\n errorText,\n onPress,\n className,\n size = \"large\",\n}: TextFieldSelectProps) => {\n const hasError = !!errorText;\n\n // 사이즈별 폰트 크기\n const labelFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const valueFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n\n return (\n <div className={cn(\"flex w-full flex-col gap-2\", className)}>\n {/* Label with optional asterisk */}\n {label && (\n <div className=\"flex items-start\">\n <span className={cn(labelFontSize, \"text-text-base-neutral-5\")}>{label}</span>\n {isRequired && <span className={cn(labelFontSize, \"text-text-prominent-accent-1\")}>*</span>}\n </div>\n )}\n {/* Select Field */}\n <button\n type=\"button\"\n className={textFieldSelectVariants({ size, hasError, disabled })}\n onClick={onPress}\n disabled={disabled}\n >\n <span\n className={cn(valueFontSize, \"flex-1\", value ? \"text-text-base-neutral-5\" : \"text-text-base-neutral-2\")}\n style={{ textAlign: \"left\", overflow: \"hidden\", textOverflow: \"ellipsis\" }}\n >\n {value || placeholder}\n </span>\n <ChevronLeftIcon className=\"text-icon-base-neutral-3 rotate-270\" />\n </button>\n {/* Assistive/Error Text */}\n {(assistiveText || errorText) && (\n <div className=\"flex items-start gap-2\">\n <span className={textFieldAssistiveAreaVariants({ size, hasError })}>{errorText || assistiveText}</span>\n </div>\n )}\n </div>\n );\n};\n\n// TextField With Button 컴포넌트\ninterface TextFieldWithButtonProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, \"size\"> {\n subtitle?: string;\n isRequired?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n disabled?: boolean;\n multiLine?: boolean;\n className?: string;\n showCounter?: boolean;\n size?: \"large\" | \"small\";\n fieldRightElement?: React.ReactNode;\n buttonText: string;\n onButtonClick: () => void;\n buttonDisabled?: boolean;\n}\n\nconst TextFieldWithButton = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, TextFieldWithButtonProps>(\n (\n {\n onChange,\n subtitle,\n isRequired = false,\n assistiveText,\n errorText,\n disabled = false,\n multiLine = false,\n className,\n showCounter = false,\n value,\n maxLength,\n size = \"large\",\n fieldRightElement,\n buttonText,\n onButtonClick,\n buttonDisabled = false,\n ...inputProps\n },\n ref,\n ) => {\n const hasError = !!errorText;\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement | HTMLTextAreaElement);\n\n const handleContainerClick = React.useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n const stringValue = typeof value === \"string\" ? value : \"\";\n const currentLength = stringValue.length;\n\n const inputPropsForInput = inputProps as React.ComponentPropsWithoutRef<\"input\">;\n const inputPropsForTextarea = inputProps as React.ComponentPropsWithoutRef<\"textarea\">;\n\n // 사이즈별 폰트 크기\n const inputFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n const subtitleFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const assistiveFontSize = size === \"large\" ? \"text-body-16-regular\" : \"text-caption-12-medium\";\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {subtitle && (\n <span className={cn(subtitleFontSize, \"text-text-base-neutral-5\")}>\n {subtitle}\n {isRequired && <span className=\"text-text-prominent-accent-1\">*</span>}\n </span>\n )}\n\n <div className=\"flex items-center gap-2\">\n <div\n onClick={disabled ? undefined : handleContainerClick}\n className={cn(\n \"group flex-1 overflow-hidden\",\n textFieldNormalContainerVariants({ size, disabled, hasError }),\n !disabled && !hasError && \"focus-within:border-border-base-neutral-4\",\n multiLine && \"h-[120px] items-start\",\n )}\n >\n {multiLine ? (\n <textarea\n {...inputPropsForTextarea}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLTextAreaElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"resize-none overflow-y-auto\",\n )}\n />\n ) : (\n <input\n {...inputPropsForInput}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLInputElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"overflow-hidden text-ellipsis whitespace-nowrap\",\n )}\n />\n )}\n\n {fieldRightElement && <div className=\"shrink-0\">{fieldRightElement}</div>}\n\n <button\n type=\"button\"\n onClick={() =>\n onChange &&\n onChange({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)\n }\n tabIndex={-1}\n disabled={disabled}\n className={cn(\"hidden shrink-0\", {\n flex: hasError,\n \"group-focus-within:flex\": !disabled && currentLength > 0,\n })}\n >\n <CancelFilledIcon className=\"text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer\" />\n </button>\n </div>\n\n <div className=\"shrink-0\">\n <CTAButton\n label={buttonText}\n onClick={onButtonClick}\n size=\"medium\"\n hierarchy=\"tertiary\"\n disabled={buttonDisabled || disabled}\n />\n </div>\n </div>\n\n {(assistiveText || errorText || (maxLength && showCounter)) && (\n <div className=\"flex items-center justify-between gap-2\">\n {(assistiveText || errorText) && (\n <span className={cn(assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {errorText || assistiveText}\n </span>\n )}\n {maxLength && showCounter && (\n <span className={cn(\"ml-auto\", assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {currentLength}/{maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldWithButton.displayName = \"TextFieldWithButton\";\n\nexport { TextFieldNormal, TextFieldSelect, TextFieldWithButton };\n"],"mappings":";;;;;;;;;AAYA,IAAM,IAAmC,EACvC,mGACA;CACE,UAAU;EACR,MAAM;GACJ,OAAO;GACP,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,MAAM;EACN,UAAU;EACV,UAAU;CACZ;AACF,CACF,GAEM,IAAiC,EAAI,IAAI;CAC7C,UAAU;EACR,MAAM;GACJ,OAAO;GACP,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,MAAM;EACN,UAAU;CACZ;AACF,CAAC,GAeK,IAAkB,EAAM,YAE1B,EACE,aACA,aACA,gBAAa,IACb,kBACA,cACA,cAAW,IACX,eAAY,IACZ,cACA,iBACA,iBAAc,IACd,UACA,cACA,UAAO,SACP,GAAG,KAEL,MACG;CACH,IAAM,IAAW,CAAC,CAAC,GACb,IAAW,EAAM,OAA+C,IAAI;CAE1E,EAAM,oBAAoB,SAAW,EAAS,OAAiD;CAE/F,IAAM,IAAuB,EAAM,kBAAkB;EACnD,EAAS,SAAS,MAAM;CAC1B,GAAG,CAAC,CAAC,GAGC,KADc,OAAO,KAAU,WAAW,IAAQ,GAAA,CACtB,QAE5B,IAAqB,GACrB,IAAwB,GAGxB,IAAgB,MAAS,UAAU,0BAA0B,wBAC7D,IAAmB,MAAS,UAAU,uBAAuB,sBAC7D,IAAoB,MAAS,UAAU,yBAAyB;CAEtE,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,uBAAuB,CAAS;YAAnD;GACG,KACC,kBAAC,QAAD;IAAM,WAAW,EAAG,GAAkB,0BAA0B;cAAhE,CACG,GACA,KAAc,kBAAC,QAAD;KAAM,WAAU;eAA+B;IAAO,CAAA,CACjE;;GAGR,kBAAC,OAAD;IACE,SAAS,IAAW,KAAA,IAAY;IAChC,WAAW,EACT,yBACA,EAAiC;KAAE;KAAM;KAAU;IAAS,CAAC,GAC7D,CAAC,KAAY,CAAC,KAAY,6CAC1B,KAAa,uBACf;cAPF;KASG,IACC,kBAAC,YAAD;MACE,GAAI;MACM;MACV,KAAK;MACE;MACI;MACD;MACV,WAAW,EACT,iJACA,GACA,6BACF;KACD,CAAA,IAED,kBAAC,SAAD;MACE,GAAI;MACM;MACV,KAAK;MACE;MACI;MACD;MACV,WAAW,EACT,0IACA,GACA,iDACF;KACD,CAAA;KAGF,KAAgB,kBAAC,OAAD;MAAK,WAAU;gBAAY;KAAkB,CAAA;KAE9D,kBAAC,UAAD;MACE,MAAK;MACL,eACE,KACA,EAAS,EAAE,QAAQ,EAAE,OAAO,GAAG,EAAE,CAA8D;MAEjG,UAAU;MACA;MACV,WAAW,EAAG,mBAAmB;OAC/B,MAAM;OACN,2BAA2B,CAAC,KAAY,IAAgB;MAC1D,CAAC;gBAED,kBAAC,GAAD,EAAkB,WAAU,2DAA4D,CAAA;KAClF,CAAA;IACL;;IAEH,KAAiB,KAAc,KAAa,MAC5C,kBAAC,OAAD;IAAK,WAAU;cAAf,EACI,KAAiB,MACjB,kBAAC,QAAD;KAAM,WAAW,EAAG,GAAmB,EAA+B;MAAE;MAAM;KAAS,CAAC,CAAC;eACtF,KAAa;IACV,CAAA,GAEP,KAAa,KACZ,kBAAC,QAAD;KAAM,WAAW,EAAG,WAAW,GAAmB,EAA+B;MAAE;MAAM;KAAS,CAAC,CAAC;eAApG;MACG;MAAc;MAAE;KACb;MAEL;;EAEJ;;AAET,CACF;AACA,EAAgB,cAAc;AAG9B,IAAM,IAA0B,EAC9B,mHACA;CACE,UAAU;EACR,MAAM;GACJ,OAAO;GACP,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB,EACf,MAAM,QACR;AACF,CACF,GAeM,KAAmB,EACvB,UACA,gBACA,UACA,gBAAa,IACb,cAAW,IACX,kBACA,cACA,YACA,cACA,UAAO,cACmB;CAC1B,IAAM,IAAW,CAAC,CAAC,GAGb,IAAgB,MAAS,UAAU,uBAAuB,sBAC1D,IAAgB,MAAS,UAAU,0BAA0B;CAEnE,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,8BAA8B,CAAS;YAA1D;GAEG,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAW,EAAG,GAAe,0BAA0B;eAAI;IAAY,CAAA,GAC5E,KAAc,kBAAC,QAAD;KAAM,WAAW,EAAG,GAAe,8BAA8B;eAAG;IAAO,CAAA,CACvF;;GAGP,kBAAC,UAAD;IACE,MAAK;IACL,WAAW,EAAwB;KAAE;KAAM;KAAU;IAAS,CAAC;IAC/D,SAAS;IACC;cAJZ,CAME,kBAAC,QAAD;KACE,WAAW,EAAG,GAAe,UAAU,IAAQ,6BAA6B,0BAA0B;KACtG,OAAO;MAAE,WAAW;MAAQ,UAAU;MAAU,cAAc;KAAW;eAExE,KAAS;IACN,CAAA,GACN,kBAAC,GAAD,EAAiB,WAAU,sCAAuC,CAAA,CAC5D;;IAEN,KAAiB,MACjB,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,QAAD;KAAM,WAAW,EAA+B;MAAE;MAAM;KAAS,CAAC;eAAI,KAAa;IAAoB,CAAA;GACpG,CAAA;EAEJ;;AAET,GAoBM,IAAsB,EAAM,YAE9B,EACE,aACA,aACA,gBAAa,IACb,kBACA,cACA,cAAW,IACX,eAAY,IACZ,cACA,iBAAc,IACd,UACA,cACA,UAAO,SACP,sBACA,eACA,kBACA,oBAAiB,IACjB,GAAG,KAEL,MACG;CACH,IAAM,IAAW,CAAC,CAAC,GACb,IAAW,EAAM,OAA+C,IAAI;CAE1E,EAAM,oBAAoB,SAAW,EAAS,OAAiD;CAE/F,IAAM,IAAuB,EAAM,kBAAkB;EACnD,EAAS,SAAS,MAAM;CAC1B,GAAG,CAAC,CAAC,GAGC,KADc,OAAO,KAAU,WAAW,IAAQ,GAAA,CACtB,QAE5B,IAAqB,GACrB,IAAwB,GAGxB,IAAgB,MAAS,UAAU,0BAA0B,wBAC7D,IAAmB,MAAS,UAAU,uBAAuB,sBAC7D,IAAoB,MAAS,UAAU,yBAAyB;CAEtE,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,uBAAuB,CAAS;YAAnD;GACG,KACC,kBAAC,QAAD;IAAM,WAAW,EAAG,GAAkB,0BAA0B;cAAhE,CACG,GACA,KAAc,kBAAC,QAAD;KAAM,WAAU;eAA+B;IAAO,CAAA,CACjE;;GAGR,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KACE,SAAS,IAAW,KAAA,IAAY;KAChC,WAAW,EACT,gCACA,EAAiC;MAAE;MAAM;MAAU;KAAS,CAAC,GAC7D,CAAC,KAAY,CAAC,KAAY,6CAC1B,KAAa,uBACf;eAPF;MASG,IACC,kBAAC,YAAD;OACE,GAAI;OACM;OACV,KAAK;OACE;OACI;OACD;OACV,WAAW,EACT,0IACA,GACA,6BACF;MACD,CAAA,IAED,kBAAC,SAAD;OACE,GAAI;OACM;OACV,KAAK;OACE;OACI;OACD;OACV,WAAW,EACT,0IACA,GACA,iDACF;MACD,CAAA;MAGF,KAAqB,kBAAC,OAAD;OAAK,WAAU;iBAAY;MAAuB,CAAA;MAExE,kBAAC,UAAD;OACE,MAAK;OACL,eACE,KACA,EAAS,EAAE,QAAQ,EAAE,OAAO,GAAG,EAAE,CAA8D;OAEjG,UAAU;OACA;OACV,WAAW,EAAG,mBAAmB;QAC/B,MAAM;QACN,2BAA2B,CAAC,KAAY,IAAgB;OAC1D,CAAC;iBAED,kBAAC,GAAD,EAAkB,WAAU,2DAA4D,CAAA;MAClF,CAAA;KACL;QAEL,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MACE,OAAO;MACP,SAAS;MACT,MAAK;MACL,WAAU;MACV,UAAU,KAAkB;KAC7B,CAAA;IACE,CAAA,CACF;;IAEH,KAAiB,KAAc,KAAa,MAC5C,kBAAC,OAAD;IAAK,WAAU;cAAf,EACI,KAAiB,MACjB,kBAAC,QAAD;KAAM,WAAW,EAAG,GAAmB,EAA+B;MAAE;MAAM;KAAS,CAAC,CAAC;eACtF,KAAa;IACV,CAAA,GAEP,KAAa,KACZ,kBAAC,QAAD;KAAM,WAAW,EAAG,WAAW,GAAmB,EAA+B;MAAE;MAAM;KAAS,CAAC,CAAC;eAApG;MACG;MAAc;MAAE;KACb;MAEL;;EAEJ;;AAET,CACF;AACA,EAAoB,cAAc"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@petnow/ui",
3
- "version": "4.1.8",
3
+ "version": "4.1.9",
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@11.1.3",
6
6
  "engines": {
@@ -21,7 +21,6 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@headlessui/react": "^2.2.9",
24
- "@types/react-swipeable-views": "^0.13.6",
25
24
  "class-variance-authority": "^0.7.1",
26
25
  "clsx": "^2.1.1",
27
26
  "date-fns": "^4.4.0",
@@ -31,7 +30,6 @@
31
30
  "react-datepicker": "^8.3.0",
32
31
  "react-daum-postcode": "^4.0.0",
33
32
  "react-icons": "^5.6.0",
34
- "react-swipeable-views": "^0.14.1",
35
33
  "shadcn": "^4.11.0",
36
34
  "tailwind-merge": "^3.6.0",
37
35
  "tw-animate-css": "^1.4.0"
@@ -68,11 +66,11 @@
68
66
  "prettier-plugin-tailwindcss": "^0.6.14",
69
67
  "react": "^19.2.7",
70
68
  "react-dom": "^19.2.7",
71
- "storybook": "10.4.1",
69
+ "storybook": "10.6.2",
72
70
  "tailwindcss": "^4.1.14",
73
71
  "ts-jest": "^29.4.6",
74
72
  "typescript": "^5.7.2",
75
- "vite": "^8.0.16",
73
+ "vite": "^8.1.6",
76
74
  "vite-plugin-dts": "^5.0.1"
77
75
  },
78
76
  "peerDependencies": {