@sth87/shadcn-design-system 0.0.34 → 0.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -2
- package/dist/AI_CONTEXT.md +3 -0
- package/dist/cjs/components/FloatLabel.cjs +1 -1
- package/dist/cjs/components/FloatLabel.cjs.map +1 -1
- package/dist/cjs/components/Input/Input.cjs +1 -1
- package/dist/cjs/components/Input/Input.cjs.map +1 -1
- package/dist/cjs/components/Select/Select.cjs +1 -1
- package/dist/cjs/components/Select/Select.cjs.map +1 -1
- package/dist/cjs/components/Textarea/Textarea.cjs +1 -1
- package/dist/cjs/components/Textarea/Textarea.cjs.map +1 -1
- package/dist/cjs/styles/index.css +1 -1
- package/dist/esm/components/FloatLabel.js +30 -19
- package/dist/esm/components/FloatLabel.js.map +1 -1
- package/dist/esm/components/Input/Input.js +91 -85
- package/dist/esm/components/Input/Input.js.map +1 -1
- package/dist/esm/components/Select/Select.js +100 -94
- package/dist/esm/components/Select/Select.js.map +1 -1
- package/dist/esm/components/Textarea/Textarea.js +58 -52
- package/dist/esm/components/Textarea/Textarea.js.map +1 -1
- package/dist/esm/styles/index.css +1 -1
- package/dist/types/components/FloatLabel.d.ts +1 -0
- package/dist/types/components/FloatLabel.d.ts.map +1 -1
- package/dist/types/components/Input/Input.d.ts +1 -0
- package/dist/types/components/Input/Input.d.ts.map +1 -1
- package/dist/types/components/Select/Select.d.ts +2 -0
- package/dist/types/components/Select/Select.d.ts.map +1 -1
- package/dist/types/components/Textarea/Textarea.d.ts +1 -0
- package/dist/types/components/Textarea/Textarea.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,9 +5,27 @@ A modern, fully-typed React design system built on top of **shadcn/ui** with enh
|
|
|
5
5
|
[](https://www.npmjs.com/package/@sth87/shadcn-design-system)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## 📚 Documentation
|
|
9
9
|
|
|
10
|
-
[
|
|
10
|
+
- 📖 **[Storybook](https://design-system-sth-kappa.vercel.app)** - Interactive component documentation
|
|
11
|
+
- 📦 **[NPM Package](https://www.npmjs.com/package/@sth87/shadcn-design-system)** - Latest package on npm
|
|
12
|
+
|
|
13
|
+
## 🤖 AI Skills
|
|
14
|
+
|
|
15
|
+
Add this design system skill to your AI Agent so it can automatically recognize components, props, and usage patterns:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx skills add https://github.com/sonth87/design-system/tree/main/skills/shadcn-design-system --skill shadcn-design-system
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Once added, the AI Agent can:
|
|
22
|
+
- Know exactly how to import and use each component
|
|
23
|
+
- Generate code with correct props, types, and examples
|
|
24
|
+
- Understand design tokens, hooks, and utilities in this design system
|
|
25
|
+
|
|
26
|
+
> See full reference at [docs/SKILL.md](docs/SKILL.md)
|
|
27
|
+
|
|
28
|
+
---
|
|
11
29
|
|
|
12
30
|
## 📦 Installation
|
|
13
31
|
|
package/dist/AI_CONTEXT.md
CHANGED
|
@@ -1309,6 +1309,7 @@ type InputProps = BaseInputProps & {
|
|
|
1309
1309
|
onClear?: () => void;
|
|
1310
1310
|
prefixIcon?: React.ReactNode;
|
|
1311
1311
|
suffixIcon?: React.ReactNode;
|
|
1312
|
+
required?: boolean;
|
|
1312
1313
|
};
|
|
1313
1314
|
```
|
|
1314
1315
|
|
|
@@ -2111,6 +2112,7 @@ type SelectProps = Omit<ComboboxProps, "ref"> & {
|
|
|
2111
2112
|
onChange?: (value: string | string[]) => void;
|
|
2112
2113
|
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
|
|
2113
2114
|
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
|
|
2115
|
+
required?: boolean;
|
|
2114
2116
|
};
|
|
2115
2117
|
```
|
|
2116
2118
|
|
|
@@ -2895,6 +2897,7 @@ type TextareaProps = Omit<
|
|
|
2895
2897
|
infoTooltip?: React.ReactNode;
|
|
2896
2898
|
clearable?: boolean;
|
|
2897
2899
|
onClear?: () => void;
|
|
2900
|
+
required?: boolean;
|
|
2898
2901
|
};
|
|
2899
2902
|
```
|
|
2900
2903
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),u=require("react"),f=require("../packages/ui/src/lib/utils.cjs"),g=require("../packages/ui/src/components/label.cjs"),h=require("./Tooltip/Tooltip.cjs"),w=require("lucide-react");function x(o){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const a in o)if(a!=="default"){const r=Object.getOwnPropertyDescriptor(o,a);Object.defineProperty(t,a,r.get?r:{enumerable:!0,get:()=>o[a]})}}return t.default=o,Object.freeze(t)}const b=x(u),c=b.forwardRef(({className:o,infoTooltip:t,size:a="xl",shouldFloat:r,required:s,children:p,...l},i)=>{const e=a==="lg"||!1;return n.jsxs(g.Label,{className:f.cn("absolute start-2 select-none pointer-events-none","bg-background px-3 translate-y-2","flex",{"top-0.5 origin-left scale-75 translate-x-1 max-w-full h-3 py-0 bg-transparent":!e,"peer-placeholder-shown:top-0 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-x-0 peer-placeholder-shown:w-[calc(100%-(--spacing(4)))] peer-placeholder-shown:h-[calc(100%-(--spacing(4)))] peer-placeholder-shown:py-3 peer-placeholder-shown:bg-background":!e,"peer-focus:top-0.5 peer-focus:origin-left peer-focus:scale-75 peer-focus:translate-x-1 peer-focus:text-primary peer-focus:max-w-full peer-focus:h-3 peer-focus:py-0 peer-focus:bg-transparent":!e,"group-focus-within:top-0.5 group-focus-within:origin-left group-focus-within:scale-75 group-focus-within:translate-x-1 group-focus-within:text-primary group-focus-within:max-w-full group-focus-within:h-3 group-focus-within:py-0 group-focus-within:bg-transparent":!e},{"-top-3.5 origin-left scale-75 translate-x-0 max-w-full w-auto h-3 py-0":e,"peer-placeholder-shown:-top-0.5 peer-placeholder-shown:scale-100 peer-placeholder-shown:w-[calc(100%-(--spacing(4)))] peer-placeholder-shown:h-[calc(100%-(--spacing(3)))] peer-placeholder-shown:py-2 peer-placeholder-shown:bg-background":e,"peer-focus:-top-3.5 peer-focus:origin-left peer-focus:scale-75 peer-focus:text-primary peer-focus:max-w-full peer-focus:w-auto peer-focus:h-3 peer-focus:py-0":e,"group-focus-within:-top-3.5 group-focus-within:origin-left group-focus-within:scale-75 group-focus-within:text-primary group-focus-within:max-w-full group-focus-within:w-auto group-focus-within:h-3 group-focus-within:py-0":e},{"top-0.5 origin-left scale-75 translate-x-1 max-w-full h-3 py-0":typeof r=="boolean"&&r&&!e,"top-0 scale-100 translate-x-0 w-[calc(100%-(--spacing(4)))] h-[calc(100%-(--spacing(4)))] py-3 bg-background":typeof r=="boolean"&&!r&&!e},{"-top-3.5 origin-left scale-75 translate-x-0 max-w-full h-3 py-0":typeof r=="boolean"&&r&&e,"top-0 scale-100 translate-x-0 w-[calc(100%-(--spacing(4)))] h-[calc(100%-(--spacing(4)))] py-3 bg-background":typeof r=="boolean"&&!r&&e},"will-change-transform transition-all duration-300 ease-in-out",o),ref:i,...l,children:[n.jsxs("span",{className:"truncate whitespace-nowrap max-w-full pointer-events-none",children:[p,s&&n.jsx("span",{className:"text-error ml-0.5",children:"*"})]}),t&&n.jsx(h.Tooltip,{content:t,children:n.jsx(w.Info,{className:"size-3.5 min-w-3.5 z-10 pointer-events-auto"})})]})});c.displayName="FloatingLabel";exports.FloatingLabel=c;
|
|
2
2
|
//# sourceMappingURL=FloatLabel.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FloatLabel.cjs","sources":["../../../src/components/FloatLabel.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { cn } from \"@dsui/ui/lib/utils\";\nimport { Label } from \"@dsui/ui/components/label\";\nimport { Tooltip } from \"./Tooltip/Tooltip\";\nimport { Info } from \"lucide-react\";\n\nconst FloatingLabel = React.forwardRef<\n React.ElementRef<typeof Label>,\n React.ComponentPropsWithoutRef<typeof Label> & {\n infoTooltip?: React.ReactNode;\n size?: string;\n shouldFloat?: boolean;\n }\n>(\n (\n {
|
|
1
|
+
{"version":3,"file":"FloatLabel.cjs","sources":["../../../src/components/FloatLabel.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { cn } from \"@dsui/ui/lib/utils\";\nimport { Label } from \"@dsui/ui/components/label\";\nimport { Tooltip } from \"./Tooltip/Tooltip\";\nimport { Info } from \"lucide-react\";\n\nconst FloatingLabel = React.forwardRef<\n React.ElementRef<typeof Label>,\n React.ComponentPropsWithoutRef<typeof Label> & {\n infoTooltip?: React.ReactNode;\n size?: string;\n shouldFloat?: boolean;\n required?: boolean;\n }\n>(\n (\n {\n className,\n infoTooltip,\n size = \"xl\",\n shouldFloat,\n required,\n children,\n ...props\n },\n ref\n ) => {\n const lagerSize = size === \"lg\" || false;\n\n return (\n <Label\n className={cn(\n \"absolute start-2 select-none pointer-events-none\",\n \"bg-background px-3 translate-y-2\",\n \"flex\",\n {\n \"top-0.5 origin-left scale-75 translate-x-1 max-w-full h-3 py-0 bg-transparent\":\n !lagerSize,\n // State empty (placeholder shown) - ở giữa input\n \"peer-placeholder-shown:top-0 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-x-0 peer-placeholder-shown:w-[calc(100%-(--spacing(4)))] peer-placeholder-shown:h-[calc(100%-(--spacing(4)))] peer-placeholder-shown:py-3 peer-placeholder-shown:bg-background\":\n !lagerSize,\n // // State focus - nằm trên input\n \"peer-focus:top-0.5 peer-focus:origin-left peer-focus:scale-75 peer-focus:translate-x-1 peer-focus:text-primary peer-focus:max-w-full peer-focus:h-3 peer-focus:py-0 peer-focus:bg-transparent\":\n !lagerSize,\n \"group-focus-within:top-0.5 group-focus-within:origin-left group-focus-within:scale-75 group-focus-within:translate-x-1 group-focus-within:text-primary group-focus-within:max-w-full group-focus-within:h-3 group-focus-within:py-0 group-focus-within:bg-transparent\":\n !lagerSize,\n },\n {\n \"-top-3.5 origin-left scale-75 translate-x-0 max-w-full w-auto h-3 py-0\":\n lagerSize,\n // State empty (placeholder shown) - ở giữa input\n \"peer-placeholder-shown:-top-0.5 peer-placeholder-shown:scale-100 peer-placeholder-shown:w-[calc(100%-(--spacing(4)))] peer-placeholder-shown:h-[calc(100%-(--spacing(3)))] peer-placeholder-shown:py-2 peer-placeholder-shown:bg-background\":\n lagerSize,\n // // State focus - nằm trên input\n \"peer-focus:-top-3.5 peer-focus:origin-left peer-focus:scale-75 peer-focus:text-primary peer-focus:max-w-full peer-focus:w-auto peer-focus:h-3 peer-focus:py-0\":\n lagerSize,\n \"group-focus-within:-top-3.5 group-focus-within:origin-left group-focus-within:scale-75 group-focus-within:text-primary group-focus-within:max-w-full group-focus-within:w-auto group-focus-within:h-3 group-focus-within:py-0\":\n lagerSize,\n },\n\n // State when shouldFloat prop is set\n {\n \"top-0.5 origin-left scale-75 translate-x-1 max-w-full h-3 py-0\":\n typeof shouldFloat === \"boolean\" && shouldFloat && !lagerSize,\n \"top-0 scale-100 translate-x-0 w-[calc(100%-(--spacing(4)))] h-[calc(100%-(--spacing(4)))] py-3 bg-background\":\n typeof shouldFloat === \"boolean\" && !shouldFloat && !lagerSize,\n },\n {\n \"-top-3.5 origin-left scale-75 translate-x-0 max-w-full h-3 py-0\":\n typeof shouldFloat === \"boolean\" && shouldFloat && lagerSize,\n \"top-0 scale-100 translate-x-0 w-[calc(100%-(--spacing(4)))] h-[calc(100%-(--spacing(4)))] py-3 bg-background\":\n typeof shouldFloat === \"boolean\" && !shouldFloat && lagerSize,\n },\n \"will-change-transform transition-all duration-300 ease-in-out\",\n className\n )}\n ref={ref}\n {...props}\n >\n <span className=\"truncate whitespace-nowrap max-w-full pointer-events-none\">\n {children}\n {required && <span className=\"text-error ml-0.5\">*</span>}\n </span>\n\n {infoTooltip && (\n <Tooltip content={infoTooltip}>\n <Info className=\"size-3.5 min-w-3.5 z-10 pointer-events-auto\" />\n </Tooltip>\n )}\n </Label>\n );\n }\n);\n\nFloatingLabel.displayName = \"FloatingLabel\";\n\nexport { FloatingLabel };\n"],"names":["FloatingLabel","React","className","infoTooltip","size","shouldFloat","required","children","props","ref","lagerSize","jsxs","Label","cn","jsx","Tooltip","Info"],"mappings":"kkBAOMA,EAAgBC,EAAM,WAS1B,CACE,CACE,UAAAC,EACA,YAAAC,EACA,KAAAC,EAAO,KACP,YAAAC,EACA,SAAAC,EACA,SAAAC,EACA,GAAGC,CAAA,EAELC,IACG,CACH,MAAMC,EAAYN,IAAS,MAAQ,GAEnC,OACEO,EAAAA,KAACC,EAAAA,MAAA,CACC,UAAWC,EAAAA,GACT,mDACA,mCACA,OACA,CACE,gFACE,CAACH,EAEH,gRACE,CAACA,EAEH,gMACE,CAACA,EACH,wQACE,CAACA,CAAA,EAEL,CACE,yEACEA,EAEF,8OACEA,EAEF,gKACEA,EACF,gOACEA,CAAA,EAIJ,CACE,iEACE,OAAOL,GAAgB,WAAaA,GAAe,CAACK,EACtD,+GACE,OAAOL,GAAgB,WAAa,CAACA,GAAe,CAACK,CAAA,EAEzD,CACE,kEACE,OAAOL,GAAgB,WAAaA,GAAeK,EACrD,+GACE,OAAOL,GAAgB,WAAa,CAACA,GAAeK,CAAA,EAExD,gEACAR,CAAA,EAEF,IAAAO,EACC,GAAGD,EAEJ,SAAA,CAAAG,EAAAA,KAAC,OAAA,CAAK,UAAU,4DACb,SAAA,CAAAJ,EACAD,GAAYQ,EAAAA,IAAC,OAAA,CAAK,UAAU,oBAAoB,SAAA,GAAA,CAAC,CAAA,EACpD,EAECX,SACEY,UAAA,CAAQ,QAASZ,EAChB,SAAAW,EAAAA,IAACE,EAAAA,KAAA,CAAK,UAAU,6CAAA,CAA8C,CAAA,CAChE,CAAA,CAAA,CAAA,CAIR,CACF,EAEAhB,EAAc,YAAc"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const t=require("react/jsx-runtime"),a=require("react"),Q=require("../../packages/ui/src/components/input.cjs"),l=require("../../packages/ui/src/lib/utils.cjs"),W=require("../FloatLabel.cjs"),m=require("lucide-react"),Y=require("use-mask-input"),Z=require("../Tooltip/Tooltip.cjs"),F=require("../../packages/ui/src/components/label.cjs"),D=a.forwardRef(({className:_,label:v,helperText:p,state:N,size:i,isFloatLabel:o,type:r,mask:f,maskOptions:E,maxLength:x,showCharCount:M,infoTooltip:j,clearable:b,onClear:P,prefixIcon:u,suffixIcon:c,placeholder:B=" ",required:w,...e},H)=>{const[g,R]=a.useState(()=>typeof e.value=="string"?e.value.length:typeof e.defaultValue=="string"?e.defaultValue.length:0),O=n=>{R(n.target.value.length),e.onChange&&e.onChange(n)},T=()=>{if(s.current){s.current.value="",R(0);const n={target:s.current,currentTarget:s.current};e.onChange?.(n),P&&P()}},C=a.useId(),s=a.useRef(null),U=a.useCallback(n=>{if(s&&(s.current=n),f&&n){const d=Y.withMask(f,E);typeof d=="function"&&d(n)}},[f,E]);a.useImperativeHandle(H,()=>s.current);const[V,X]=a.useState(!1),A={default:"text-muted-foreground",success:"text-success",warning:"text-warning",error:"text-error"},y=o?i==="xl"||i==="lg"?i:"xl":i||"normal",k=(()=>{const n={xs:{prefix:"pl-8",suffix:"pr-8"},sm:{prefix:"pl-9",suffix:"pr-9"},normal:{prefix:"pl-10",suffix:"pr-10"},lg:{prefix:"pl-11",suffix:"pr-11"},xl:{prefix:"pl-12",suffix:"pr-12"}};return n[y]||n.normal})(),q={xs:"size-3",sm:"size-3.5",normal:"size-4",lg:"size-4",xl:"size-4"}[y]||"size-4",G=()=>{const n=r==="number"||r==="password"||r==="datetime"||b&&(g>0||e?.value);return n&&c?r==="password"&&b&&(g>0||e?.value)?"pr-20":"pr-16":n?r==="password"&&b&&(g>0||e?.value)?"pr-16":"pr-10":c?k.suffix:""},I=(()=>{const n={xs:{left:"left-2.5",right:"right-2.5"},sm:{left:"left-3",right:"right-3"},normal:{left:"left-3",right:"right-3"},lg:{left:"left-3.5",right:"right-3.5"},xl:{left:"left-4",right:"right-4"}};return n[y]||n.normal})(),J=()=>{if(s.current){const n=Number(e.step||1),d=e.max?Number(e.max):1/0,z=Number(s.current.value||0),S=Math.min(z+n,d);s.current.value=String(S);const h=new Event("input",{bubbles:!0});s.current.dispatchEvent(h),e.onChange?.(h)}},K=()=>{if(s.current){const n=Number(e.step||1),d=e.min?Number(e.min):-1/0,z=Number(s.current.value||0),S=Math.max(z-n,d);s.current.value=String(S);const h=new Event("input",{bubbles:!0});s.current.dispatchEvent(h),e.onChange?.(h)}};return t.jsx("div",{className:_,children:t.jsxs("div",{className:l.cn("flex flex-col gap-1.5 relative flex-auto",{"floating-label relative":o}),children:[!o&&v&&t.jsxs(F.Label,{htmlFor:C,className:"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",children:[t.jsxs("span",{children:[v,w&&t.jsx("span",{className:"text-error ml-0.5",children:"*"})]}),j&&t.jsx(Z.Tooltip,{content:j,children:t.jsx(m.Info,{className:"size-3.5 min-w-3.5"})})]}),t.jsxs("div",{className:"relative",children:[u&&t.jsx("div",{className:l.cn("absolute top-1/2 -translate-y-1/2 text-muted-foreground leading-0",I.left),children:a.isValidElement(u)?a.cloneElement(u,{className:l.cn(q,u.props?.className)}):u}),t.jsx(Q.Input,{ref:U,id:C,className:l.cn("peer",{"pt-5 pb-1":o&&i!=="lg","[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none [-moz-appearance:textfield] pr-8":r==="number"},u&&k.prefix,f&&"placeholder:text-slate-400 placeholder:opacity-100",G()),state:N,size:o?i==="xl"||i==="lg"?i:"xl":i,type:r==="password"?V?"text":"password":r,placeholder:B,maxLength:x,onChange:O,required:w,...e}),o&&t.jsx(W.FloatingLabel,{htmlFor:C,size:i,infoTooltip:j,required:w,children:v}),r==="number"&&t.jsxs("div",{className:"absolute right-1 top-0 h-full flex flex-col gap-0.5",children:[t.jsx("button",{type:"button",onClick:J,disabled:e.disabled,className:l.cn("h-1/2 w-6 flex items-center justify-center rounded cursor-pointer hover:scale-150 transition-transform","disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent"),tabIndex:-1,children:t.jsx(m.ChevronUp,{className:"size-3"})}),t.jsx("button",{type:"button",onClick:K,disabled:e.disabled,className:l.cn("h-1/2 w-6 flex items-center justify-center rounded cursor-pointer hover:scale-150 transition-transform","disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent"),tabIndex:-1,children:t.jsx(m.ChevronDown,{className:"size-3"})})]}),b&&(g>0||e?.value)&&!e.disabled&&r!=="number"&&t.jsx("button",{type:"button",tabIndex:-1,className:l.cn("absolute top-1/2 -translate-y-1/2 p-1 rounded hover:bg-accent transition-colors cursor-pointer",r==="password"?c?"right-14":"right-10":c?"right-10":"right-2"),onClick:T,disabled:e.disabled,children:t.jsx(m.X,{className:"size-4"})}),r==="password"&&t.jsx("button",{type:"button",tabIndex:-1,className:l.cn("absolute top-1/2 -translate-y-1/2 p-1 rounded hover:bg-accent transition-colors",c?"right-10":"right-2"),onClick:()=>X(n=>!n),disabled:e.disabled,children:V?t.jsx(m.EyeOff,{className:"size-4"}):t.jsx(m.Eye,{className:"size-4"})}),c&&t.jsx("div",{className:l.cn("absolute top-1/2 -translate-y-1/2 text-muted-foreground leading-0",I.right),children:a.isValidElement(c)?a.cloneElement(c,{className:l.cn(q,c.props?.className)}):c})]}),(p||M&&typeof x=="number")&&t.jsxs("div",{className:"flex items-center justify-between text-xs gap-2",children:[p&&t.jsx("p",{className:l.cn("text-xs",N?A?.[N]:""),children:p}),M&&typeof x=="number"&&t.jsxs("span",{className:"ml-auto text-muted-foreground",children:[g," / ",x]})]})]})})});D.displayName="Input";exports.default=D;
|
|
2
2
|
//# sourceMappingURL=Input.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.cjs","sources":["../../../../src/components/Input/Input.tsx"],"sourcesContent":["import React, { type ChangeEvent } from \"react\";\nimport {\n Input as SInput,\n type InputProps as SInputProps,\n} from \"@dsui/ui/components/input\";\nimport { cn } from \"@dsui/ui/lib/utils\";\nimport { FloatingLabel } from \"@/components/FloatLabel\";\nimport { Eye, EyeOff, ChevronDown, ChevronUp, Info, X } from \"lucide-react\";\nimport { withMask, type Options } from \"use-mask-input\";\nimport { Tooltip } from \"../Tooltip/Tooltip\";\nimport { Label } from \"../Label\";\n\n// Re-export base input props to avoid external dependency issues\nexport type BaseInputProps = Omit<React.ComponentProps<\"input\">, \"size\"> & {\n size?: \"normal\" | \"sm\" | \"xs\" | \"lg\" | \"xl\";\n state?: \"default\" | \"success\" | \"error\" | \"warning\";\n};\n\nexport type InputProps = BaseInputProps & {\n label?: string;\n helperText?: React.ReactNode;\n isFloatLabel?: boolean;\n mask?: string;\n maskOptions?: {\n placeholder?: string;\n inputFormat?: string;\n outputFormat?: string;\n showMaskOnHover?: boolean;\n showMaskOnFocus?: boolean;\n separate?: boolean;\n } & Options;\n maxLength?: number;\n showCharCount?: boolean;\n infoTooltip?: React.ReactNode;\n clearable?: boolean;\n onClear?: () => void;\n prefixIcon?: React.ReactNode;\n suffixIcon?: React.ReactNode;\n};\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n label,\n helperText,\n state,\n size,\n isFloatLabel,\n type,\n mask,\n maskOptions,\n maxLength,\n showCharCount,\n infoTooltip,\n clearable,\n onClear,\n prefixIcon,\n suffixIcon,\n placeholder = \" \",\n ...props\n },\n ref\n ) => {\n // Character count state\n const [charCount, setCharCount] = React.useState(() => {\n if (typeof props.value === \"string\") return props.value.length;\n if (typeof props.defaultValue === \"string\")\n return props.defaultValue.length;\n return 0;\n });\n\n const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n setCharCount(e.target.value.length);\n if (props.onChange) props.onChange(e);\n };\n\n const handleClear = () => {\n if (innerRef.current) {\n innerRef.current.value = \"\";\n setCharCount(0);\n const event = {\n target: innerRef.current,\n currentTarget: innerRef.current,\n } as React.ChangeEvent<HTMLInputElement>;\n props.onChange?.(event);\n if (onClear) onClear();\n }\n };\n\n const inputId = React.useId();\n const innerRef = React.useRef<HTMLInputElement>(null);\n\n // Combine refs\n const combinedRef = React.useCallback(\n (element: HTMLInputElement | null) => {\n // Set innerRef\n if (innerRef) {\n (\n innerRef as React.MutableRefObject<HTMLInputElement | null>\n ).current = element;\n }\n\n // Apply mask if provided\n if (mask && element) {\n const maskRefCallback = withMask(mask, maskOptions);\n if (typeof maskRefCallback === \"function\") {\n maskRefCallback(element);\n }\n }\n },\n [mask, maskOptions]\n );\n\n // Expose ref to parent\n React.useImperativeHandle(ref, () => innerRef.current!);\n\n const [showPassword, setShowPassword] = React.useState(false);\n\n // State\n const helperTextStyles = {\n default: \"text-muted-foreground\",\n success: \"text-success\",\n warning: \"text-warning\",\n error: \"text-error\",\n };\n\n // Calculate current size\n const currentSize = isFloatLabel\n ? size === \"xl\" || size === \"lg\"\n ? size\n : \"xl\"\n : size || \"normal\";\n\n // Calculate padding based on size and icons\n const getPadding = () => {\n const sizeMap = {\n xs: { prefix: \"pl-8\", suffix: \"pr-8\" },\n sm: { prefix: \"pl-9\", suffix: \"pr-9\" },\n normal: { prefix: \"pl-10\", suffix: \"pr-10\" },\n lg: { prefix: \"pl-11\", suffix: \"pr-11\" },\n xl: { prefix: \"pl-12\", suffix: \"pr-12\" },\n };\n\n return sizeMap[currentSize as keyof typeof sizeMap] || sizeMap.normal;\n };\n\n const padding = getPadding();\n\n // Get icon size class based on current size\n const getIconSizeClass = () => {\n const sizeMap = {\n xs: \"size-3\",\n sm: \"size-3.5\",\n normal: \"size-4\",\n lg: \"size-4\",\n xl: \"size-4\",\n };\n return sizeMap[currentSize as keyof typeof sizeMap] || \"size-4\";\n };\n\n const iconSizeClass = getIconSizeClass();\n\n // Calculate right padding considering built-in icons\n const getRightPadding = () => {\n const hasBuiltInSuffix =\n type === \"number\" ||\n type === \"password\" ||\n type === \"datetime\" ||\n (clearable && (charCount > 0 || props?.value));\n\n if (hasBuiltInSuffix && suffixIcon) {\n return type === \"password\" &&\n clearable &&\n (charCount > 0 || props?.value)\n ? \"pr-20\" // password + clear + custom icon\n : \"pr-16\"; // one built-in + custom icon\n }\n\n if (hasBuiltInSuffix) {\n return type === \"password\" &&\n clearable &&\n (charCount > 0 || props?.value)\n ? \"pr-16\" // password + clear\n : \"pr-10\"; // single built-in icon\n }\n\n if (suffixIcon) {\n return padding.suffix;\n }\n\n return \"\";\n };\n\n // Icon position calculations\n const getIconPosition = () => {\n const sizeMap = {\n xs: { left: \"left-2.5\", right: \"right-2.5\" },\n sm: { left: \"left-3\", right: \"right-3\" },\n normal: { left: \"left-3\", right: \"right-3\" },\n lg: { left: \"left-3.5\", right: \"right-3.5\" },\n xl: { left: \"left-4\", right: \"right-4\" },\n };\n\n return sizeMap[currentSize as keyof typeof sizeMap] || sizeMap.normal;\n };\n\n const iconPosition = getIconPosition();\n\n /* Spinner Button Handlers */\n const handleIncrement = () => {\n if (innerRef.current) {\n const step = Number(props.step || 1);\n const max = props.max ? Number(props.max) : Infinity;\n const currentValue = Number(innerRef.current.value || 0);\n const newValue = Math.min(currentValue + step, max);\n\n innerRef.current.value = String(newValue);\n const event = new Event(\"input\", { bubbles: true });\n innerRef.current.dispatchEvent(event);\n props.onChange?.(event as unknown as ChangeEvent<HTMLInputElement>);\n }\n };\n\n const handleDecrement = () => {\n if (innerRef.current) {\n const step = Number(props.step || 1);\n const min = props.min ? Number(props.min) : -Infinity;\n const currentValue = Number(innerRef.current.value || 0);\n const newValue = Math.max(currentValue - step, min);\n\n innerRef.current.value = String(newValue);\n const event = new Event(\"input\", { bubbles: true });\n innerRef.current.dispatchEvent(event);\n props.onChange?.(event as unknown as ChangeEvent<HTMLInputElement>);\n }\n };\n /* End Spinner Button Handlers */\n\n return (\n <div className={className}>\n <div\n className={cn(\"flex flex-col gap-1.5 relative flex-auto\", {\n \"floating-label relative\": isFloatLabel,\n })}\n >\n {!isFloatLabel && label && (\n <Label\n htmlFor={inputId}\n className=\"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n {infoTooltip && (\n <Tooltip content={infoTooltip}>\n <Info className=\"size-3.5 min-w-3.5\" />\n </Tooltip>\n )}\n </Label>\n )}\n\n <div className=\"relative\">\n {/* Prefix Icon */}\n {prefixIcon && (\n <div\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 text-muted-foreground leading-0\",\n iconPosition.left\n )}\n >\n {React.isValidElement(prefixIcon)\n ? React.cloneElement(prefixIcon, {\n className: cn(\n iconSizeClass,\n (prefixIcon.props as any)?.className\n ),\n } as Partial<unknown>)\n : prefixIcon}\n </div>\n )}\n\n <SInput\n ref={combinedRef}\n id={inputId}\n className={cn(\n \"peer\",\n {\n \"pt-5 pb-1\": isFloatLabel && size !== \"lg\",\n \"[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none [-moz-appearance:textfield] pr-8\":\n type === \"number\",\n // \"[-webkit-text-fill-color:var(--foreground)]\": mask,\n },\n prefixIcon && padding.prefix,\n mask && \"placeholder:text-slate-400 placeholder:opacity-100\",\n getRightPadding()\n // className,\n )}\n state={state}\n size={\n isFloatLabel\n ? size === \"xl\" || size === \"lg\"\n ? size\n : \"xl\"\n : size\n }\n type={\n type === \"password\"\n ? showPassword\n ? \"text\"\n : \"password\"\n : type\n }\n placeholder={placeholder}\n maxLength={maxLength}\n onChange={handleInput}\n {...props}\n />\n {isFloatLabel && (\n <FloatingLabel\n htmlFor={inputId}\n size={size}\n infoTooltip={infoTooltip}\n >\n {label}\n </FloatingLabel>\n )}\n\n {/* Spinner Buttons */}\n {type === \"number\" && (\n <div className=\"absolute right-1 top-0 h-full flex flex-col gap-0.5\">\n <button\n type=\"button\"\n onClick={handleIncrement}\n disabled={props.disabled}\n className={cn(\n \"h-1/2 w-6 flex items-center justify-center rounded cursor-pointer hover:scale-150 transition-transform\",\n \"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent\"\n )}\n tabIndex={-1}\n >\n <ChevronUp className=\"size-3\" />\n </button>\n <button\n type=\"button\"\n onClick={handleDecrement}\n disabled={props.disabled}\n className={cn(\n \"h-1/2 w-6 flex items-center justify-center rounded cursor-pointer hover:scale-150 transition-transform\",\n \"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent\"\n )}\n tabIndex={-1}\n >\n <ChevronDown className=\"size-3\" />\n </button>\n </div>\n )}\n\n {/* Clear Button */}\n {clearable &&\n (charCount > 0 || props?.value) &&\n !props.disabled &&\n type !== \"number\" && (\n <button\n type=\"button\"\n tabIndex={-1}\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 p-1 rounded hover:bg-accent transition-colors cursor-pointer\",\n type === \"password\"\n ? suffixIcon\n ? \"right-14\"\n : \"right-10\"\n : suffixIcon\n ? \"right-10\"\n : \"right-2\"\n )}\n onClick={handleClear}\n disabled={props.disabled}\n >\n <X className=\"size-4\" />\n </button>\n )}\n\n {/* Show/Hide Password Button */}\n {type === \"password\" && (\n <button\n type=\"button\"\n tabIndex={-1}\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 p-1 rounded hover:bg-accent transition-colors\",\n suffixIcon ? \"right-10\" : \"right-2\"\n )}\n onClick={() => setShowPassword((prev) => !prev)}\n disabled={props.disabled}\n >\n {showPassword ? (\n <EyeOff className=\"size-4\" />\n ) : (\n <Eye className=\"size-4\" />\n )}\n </button>\n )}\n\n {/* Suffix Icon */}\n {suffixIcon && (\n <div\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 text-muted-foreground leading-0\",\n iconPosition.right\n )}\n >\n {React.isValidElement(suffixIcon)\n ? React.cloneElement(suffixIcon, {\n className: cn(\n iconSizeClass,\n (suffixIcon.props as any)?.className\n ),\n } as Partial<unknown>)\n : suffixIcon}\n </div>\n )}\n </div>\n\n {(helperText || (showCharCount && typeof maxLength === \"number\")) && (\n <div className=\"flex items-center justify-between text-xs gap-2\">\n {helperText && (\n <p\n className={cn(\n \"text-xs\",\n state ? helperTextStyles?.[state] : \"\"\n )}\n >\n {helperText}\n </p>\n )}\n {showCharCount && typeof maxLength === \"number\" && (\n <span className=\"ml-auto text-muted-foreground\">\n {charCount} / {maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\nexport default Input;\n"],"names":["Input","React","className","label","helperText","state","size","isFloatLabel","type","mask","maskOptions","maxLength","showCharCount","infoTooltip","clearable","onClear","prefixIcon","suffixIcon","placeholder","props","ref","charCount","setCharCount","handleInput","e","handleClear","innerRef","event","inputId","combinedRef","element","maskRefCallback","withMask","showPassword","setShowPassword","helperTextStyles","currentSize","padding","sizeMap","iconSizeClass","getRightPadding","hasBuiltInSuffix","iconPosition","handleIncrement","step","max","currentValue","newValue","handleDecrement","min","jsx","jsxs","cn","Label","Tooltip","Info","SInput","FloatingLabel","ChevronUp","ChevronDown","X","prev","EyeOff","Eye"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Input.cjs","sources":["../../../../src/components/Input/Input.tsx"],"sourcesContent":["import React, { type ChangeEvent } from \"react\";\nimport {\n Input as SInput,\n type InputProps as SInputProps,\n} from \"@dsui/ui/components/input\";\nimport { cn } from \"@dsui/ui/lib/utils\";\nimport { FloatingLabel } from \"@/components/FloatLabel\";\nimport { Eye, EyeOff, ChevronDown, ChevronUp, Info, X } from \"lucide-react\";\nimport { withMask, type Options } from \"use-mask-input\";\nimport { Tooltip } from \"../Tooltip/Tooltip\";\nimport { Label } from \"../Label\";\n\n// Re-export base input props to avoid external dependency issues\nexport type BaseInputProps = Omit<React.ComponentProps<\"input\">, \"size\"> & {\n size?: \"normal\" | \"sm\" | \"xs\" | \"lg\" | \"xl\";\n state?: \"default\" | \"success\" | \"error\" | \"warning\";\n};\n\nexport type InputProps = BaseInputProps & {\n label?: string;\n helperText?: React.ReactNode;\n isFloatLabel?: boolean;\n mask?: string;\n maskOptions?: {\n placeholder?: string;\n inputFormat?: string;\n outputFormat?: string;\n showMaskOnHover?: boolean;\n showMaskOnFocus?: boolean;\n separate?: boolean;\n } & Options;\n maxLength?: number;\n showCharCount?: boolean;\n infoTooltip?: React.ReactNode;\n clearable?: boolean;\n onClear?: () => void;\n prefixIcon?: React.ReactNode;\n suffixIcon?: React.ReactNode;\n required?: boolean;\n};\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n label,\n helperText,\n state,\n size,\n isFloatLabel,\n type,\n mask,\n maskOptions,\n maxLength,\n showCharCount,\n infoTooltip,\n clearable,\n onClear,\n prefixIcon,\n suffixIcon,\n placeholder = \" \",\n required,\n ...props\n },\n ref\n ) => {\n // Character count state\n const [charCount, setCharCount] = React.useState(() => {\n if (typeof props.value === \"string\") return props.value.length;\n if (typeof props.defaultValue === \"string\")\n return props.defaultValue.length;\n return 0;\n });\n\n const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n setCharCount(e.target.value.length);\n if (props.onChange) props.onChange(e);\n };\n\n const handleClear = () => {\n if (innerRef.current) {\n innerRef.current.value = \"\";\n setCharCount(0);\n const event = {\n target: innerRef.current,\n currentTarget: innerRef.current,\n } as React.ChangeEvent<HTMLInputElement>;\n props.onChange?.(event);\n if (onClear) onClear();\n }\n };\n\n const inputId = React.useId();\n const innerRef = React.useRef<HTMLInputElement>(null);\n\n // Combine refs\n const combinedRef = React.useCallback(\n (element: HTMLInputElement | null) => {\n // Set innerRef\n if (innerRef) {\n (\n innerRef as React.MutableRefObject<HTMLInputElement | null>\n ).current = element;\n }\n\n // Apply mask if provided\n if (mask && element) {\n const maskRefCallback = withMask(mask, maskOptions);\n if (typeof maskRefCallback === \"function\") {\n maskRefCallback(element);\n }\n }\n },\n [mask, maskOptions]\n );\n\n // Expose ref to parent\n React.useImperativeHandle(ref, () => innerRef.current!);\n\n const [showPassword, setShowPassword] = React.useState(false);\n\n // State\n const helperTextStyles = {\n default: \"text-muted-foreground\",\n success: \"text-success\",\n warning: \"text-warning\",\n error: \"text-error\",\n };\n\n // Calculate current size\n const currentSize = isFloatLabel\n ? size === \"xl\" || size === \"lg\"\n ? size\n : \"xl\"\n : size || \"normal\";\n\n // Calculate padding based on size and icons\n const getPadding = () => {\n const sizeMap = {\n xs: { prefix: \"pl-8\", suffix: \"pr-8\" },\n sm: { prefix: \"pl-9\", suffix: \"pr-9\" },\n normal: { prefix: \"pl-10\", suffix: \"pr-10\" },\n lg: { prefix: \"pl-11\", suffix: \"pr-11\" },\n xl: { prefix: \"pl-12\", suffix: \"pr-12\" },\n };\n\n return sizeMap[currentSize as keyof typeof sizeMap] || sizeMap.normal;\n };\n\n const padding = getPadding();\n\n // Get icon size class based on current size\n const getIconSizeClass = () => {\n const sizeMap = {\n xs: \"size-3\",\n sm: \"size-3.5\",\n normal: \"size-4\",\n lg: \"size-4\",\n xl: \"size-4\",\n };\n return sizeMap[currentSize as keyof typeof sizeMap] || \"size-4\";\n };\n\n const iconSizeClass = getIconSizeClass();\n\n // Calculate right padding considering built-in icons\n const getRightPadding = () => {\n const hasBuiltInSuffix =\n type === \"number\" ||\n type === \"password\" ||\n type === \"datetime\" ||\n (clearable && (charCount > 0 || props?.value));\n\n if (hasBuiltInSuffix && suffixIcon) {\n return type === \"password\" &&\n clearable &&\n (charCount > 0 || props?.value)\n ? \"pr-20\" // password + clear + custom icon\n : \"pr-16\"; // one built-in + custom icon\n }\n\n if (hasBuiltInSuffix) {\n return type === \"password\" &&\n clearable &&\n (charCount > 0 || props?.value)\n ? \"pr-16\" // password + clear\n : \"pr-10\"; // single built-in icon\n }\n\n if (suffixIcon) {\n return padding.suffix;\n }\n\n return \"\";\n };\n\n // Icon position calculations\n const getIconPosition = () => {\n const sizeMap = {\n xs: { left: \"left-2.5\", right: \"right-2.5\" },\n sm: { left: \"left-3\", right: \"right-3\" },\n normal: { left: \"left-3\", right: \"right-3\" },\n lg: { left: \"left-3.5\", right: \"right-3.5\" },\n xl: { left: \"left-4\", right: \"right-4\" },\n };\n\n return sizeMap[currentSize as keyof typeof sizeMap] || sizeMap.normal;\n };\n\n const iconPosition = getIconPosition();\n\n /* Spinner Button Handlers */\n const handleIncrement = () => {\n if (innerRef.current) {\n const step = Number(props.step || 1);\n const max = props.max ? Number(props.max) : Infinity;\n const currentValue = Number(innerRef.current.value || 0);\n const newValue = Math.min(currentValue + step, max);\n\n innerRef.current.value = String(newValue);\n const event = new Event(\"input\", { bubbles: true });\n innerRef.current.dispatchEvent(event);\n props.onChange?.(event as unknown as ChangeEvent<HTMLInputElement>);\n }\n };\n\n const handleDecrement = () => {\n if (innerRef.current) {\n const step = Number(props.step || 1);\n const min = props.min ? Number(props.min) : -Infinity;\n const currentValue = Number(innerRef.current.value || 0);\n const newValue = Math.max(currentValue - step, min);\n\n innerRef.current.value = String(newValue);\n const event = new Event(\"input\", { bubbles: true });\n innerRef.current.dispatchEvent(event);\n props.onChange?.(event as unknown as ChangeEvent<HTMLInputElement>);\n }\n };\n /* End Spinner Button Handlers */\n\n return (\n <div className={className}>\n <div\n className={cn(\"flex flex-col gap-1.5 relative flex-auto\", {\n \"floating-label relative\": isFloatLabel,\n })}\n >\n {!isFloatLabel && label && (\n <Label\n htmlFor={inputId}\n className=\"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n <span>\n {label}\n {required && <span className=\"text-error ml-0.5\">*</span>}\n </span>\n {infoTooltip && (\n <Tooltip content={infoTooltip}>\n <Info className=\"size-3.5 min-w-3.5\" />\n </Tooltip>\n )}\n </Label>\n )}\n\n <div className=\"relative\">\n {/* Prefix Icon */}\n {prefixIcon && (\n <div\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 text-muted-foreground leading-0\",\n iconPosition.left\n )}\n >\n {React.isValidElement(prefixIcon)\n ? React.cloneElement(prefixIcon, {\n className: cn(\n iconSizeClass,\n (prefixIcon.props as any)?.className\n ),\n } as Partial<unknown>)\n : prefixIcon}\n </div>\n )}\n\n <SInput\n ref={combinedRef}\n id={inputId}\n className={cn(\n \"peer\",\n {\n \"pt-5 pb-1\": isFloatLabel && size !== \"lg\",\n \"[&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none [-moz-appearance:textfield] pr-8\":\n type === \"number\",\n // \"[-webkit-text-fill-color:var(--foreground)]\": mask,\n },\n prefixIcon && padding.prefix,\n mask && \"placeholder:text-slate-400 placeholder:opacity-100\",\n getRightPadding()\n // className,\n )}\n state={state}\n size={\n isFloatLabel\n ? size === \"xl\" || size === \"lg\"\n ? size\n : \"xl\"\n : size\n }\n type={\n type === \"password\"\n ? showPassword\n ? \"text\"\n : \"password\"\n : type\n }\n placeholder={placeholder}\n maxLength={maxLength}\n onChange={handleInput}\n required={required}\n {...props}\n />\n {isFloatLabel && (\n <FloatingLabel\n htmlFor={inputId}\n size={size}\n infoTooltip={infoTooltip}\n required={required}\n >\n {label}\n </FloatingLabel>\n )}\n\n {/* Spinner Buttons */}\n {type === \"number\" && (\n <div className=\"absolute right-1 top-0 h-full flex flex-col gap-0.5\">\n <button\n type=\"button\"\n onClick={handleIncrement}\n disabled={props.disabled}\n className={cn(\n \"h-1/2 w-6 flex items-center justify-center rounded cursor-pointer hover:scale-150 transition-transform\",\n \"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent\"\n )}\n tabIndex={-1}\n >\n <ChevronUp className=\"size-3\" />\n </button>\n <button\n type=\"button\"\n onClick={handleDecrement}\n disabled={props.disabled}\n className={cn(\n \"h-1/2 w-6 flex items-center justify-center rounded cursor-pointer hover:scale-150 transition-transform\",\n \"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent\"\n )}\n tabIndex={-1}\n >\n <ChevronDown className=\"size-3\" />\n </button>\n </div>\n )}\n\n {/* Clear Button */}\n {clearable &&\n (charCount > 0 || props?.value) &&\n !props.disabled &&\n type !== \"number\" && (\n <button\n type=\"button\"\n tabIndex={-1}\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 p-1 rounded hover:bg-accent transition-colors cursor-pointer\",\n type === \"password\"\n ? suffixIcon\n ? \"right-14\"\n : \"right-10\"\n : suffixIcon\n ? \"right-10\"\n : \"right-2\"\n )}\n onClick={handleClear}\n disabled={props.disabled}\n >\n <X className=\"size-4\" />\n </button>\n )}\n\n {/* Show/Hide Password Button */}\n {type === \"password\" && (\n <button\n type=\"button\"\n tabIndex={-1}\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 p-1 rounded hover:bg-accent transition-colors\",\n suffixIcon ? \"right-10\" : \"right-2\"\n )}\n onClick={() => setShowPassword((prev) => !prev)}\n disabled={props.disabled}\n >\n {showPassword ? (\n <EyeOff className=\"size-4\" />\n ) : (\n <Eye className=\"size-4\" />\n )}\n </button>\n )}\n\n {/* Suffix Icon */}\n {suffixIcon && (\n <div\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 text-muted-foreground leading-0\",\n iconPosition.right\n )}\n >\n {React.isValidElement(suffixIcon)\n ? React.cloneElement(suffixIcon, {\n className: cn(\n iconSizeClass,\n (suffixIcon.props as any)?.className\n ),\n } as Partial<unknown>)\n : suffixIcon}\n </div>\n )}\n </div>\n\n {(helperText || (showCharCount && typeof maxLength === \"number\")) && (\n <div className=\"flex items-center justify-between text-xs gap-2\">\n {helperText && (\n <p\n className={cn(\n \"text-xs\",\n state ? helperTextStyles?.[state] : \"\"\n )}\n >\n {helperText}\n </p>\n )}\n {showCharCount && typeof maxLength === \"number\" && (\n <span className=\"ml-auto text-muted-foreground\">\n {charCount} / {maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\nexport default Input;\n"],"names":["Input","React","className","label","helperText","state","size","isFloatLabel","type","mask","maskOptions","maxLength","showCharCount","infoTooltip","clearable","onClear","prefixIcon","suffixIcon","placeholder","required","props","ref","charCount","setCharCount","handleInput","e","handleClear","innerRef","event","inputId","combinedRef","element","maskRefCallback","withMask","showPassword","setShowPassword","helperTextStyles","currentSize","padding","sizeMap","iconSizeClass","getRightPadding","hasBuiltInSuffix","iconPosition","handleIncrement","step","max","currentValue","newValue","handleDecrement","min","jsx","jsxs","cn","Label","Tooltip","Info","SInput","FloatingLabel","ChevronUp","ChevronDown","X","prev","EyeOff","Eye"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),a=require("react"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),a=require("react"),i=require("../../packages/ui/src/components/select.cjs"),Q=require("../../packages/ui/src/components/combobox.cjs"),x=require("../../packages/ui/src/lib/utils.cjs"),V=require("../FloatLabel.cjs"),U=require("lucide-react"),W=require("../Tooltip/Tooltip.cjs"),_=a.forwardRef(({className:b,label:o,helperText:v,state:m="default",size:t="normal",isFloatLabel:c,infoTooltip:j,clearable:y=!1,placeholder:N="",options:g=[],tagRender:d,multiple:p=!1,value:n,defaultValue:F,onValueChange:w,values:G,defaultValues:S,onValuesChange:q,search:h,clickToRemove:H=!0,overflowBehavior:P="wrap-when-open",disabled:I,onChange:f,onFocus:C,onBlur:k,required:M},R)=>{const u=a.useId(),[T,E]=a.useState(n??F??"");a.useEffect(()=>{!p&&n!==void 0&&E(n)},[p,n]);const A=a.useCallback(s=>{const r=s||"";n===void 0&&E(r),w?.(r),f?.(r)},[w,f,n]),D=a.useCallback(s=>{q?.(s),f?.(s)},[q,f]),J={default:"text-muted-foreground",success:"text-success",warning:"text-warning",error:"text-error"},O=c?t==="xl"||t==="lg"?t:"xl":t,K=a.useMemo(()=>{const s=new Map;return g.forEach(r=>{const l=r.group;s.has(l)||s.set(l,[]),s.get(l).push(r)}),s},[g]);return e.jsx("div",{className:b,children:e.jsxs("div",{ref:R,className:x.cn("flex flex-col gap-1.5 relative",{"floating-label relative":c}),children:[!c&&o&&e.jsxs("label",{htmlFor:u,className:"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",children:[e.jsxs("span",{children:[o,M&&e.jsx("span",{className:"text-error ml-0.5",children:"*"})]}),j&&e.jsx(W.Tooltip,{content:j,children:e.jsx(U.Info,{className:"size-3.5 min-w-3.5"})})]}),e.jsx("div",{className:"relative",children:p?e.jsxs(i.MultiSelect,{values:G,defaultValues:typeof S=="string"?[S]:S,onValuesChange:D,children:[e.jsx(i.MultiSelectTrigger,{id:u,disabled:I,className:x.cn("peer w-full",{"pt-5 pb-1":c&&t!=="lg"},b),size:O,state:m,onFocus:C,onBlur:k,children:e.jsx(i.MultiSelectValue,{placeholder:N,clickToRemove:H&&y,overflowBehavior:P})}),c&&e.jsx(V.FloatingLabel,{htmlFor:u,size:t,infoTooltip:j,required:M,children:o}),e.jsx(i.MultiSelectContent,{search:h,children:[...K.entries()].map(([s,r])=>s?e.jsxs(a.Fragment,{children:[e.jsx(i.MultiSelectGroup,{heading:s,children:r.map(l=>e.jsx(i.MultiSelectItem,{value:l.value,disabled:l?.disabled,icon:l?.icon,tagRender:!!d,children:d?d(l):l.label},l.value))}),e.jsx(i.MultiSelectSeparator,{})]},s):r.map(l=>e.jsx(i.MultiSelectItem,{value:l.value,disabled:l?.disabled,icon:l?.icon,tagRender:!!d,children:d?d(l):l.label},l.value)))})]}):e.jsxs(e.Fragment,{children:[e.jsx(Q.Combobox,{value:n??T,options:g,placeHolder:N,emptyText:typeof h=="object"?h.emptyMessage:"No results found",onChange:A,clearable:y,disabled:I,id:u,className:x.cn("peer w-full justify-start",{"pt-5 pb-1":c&&t!=="lg"}),size:O,state:m,dropdownClassName:x.cn("opacity-40",{"translate-y-[-8px]":c&&t!=="lg"}),searchable:!!h,tagRender:d,onFocus:C,onBlur:k}),c&&e.jsx(V.FloatingLabel,{htmlFor:u,size:t,infoTooltip:j,required:M,shouldFloat:!!(n??T),className:"pointer-events-none",children:o})]})}),v&&e.jsx("p",{className:x.cn("text-xs",m?J[m]:""),children:v})]})})});_.displayName="Select";exports.default=_;
|
|
2
2
|
//# sourceMappingURL=Select.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.cjs","sources":["../../../../src/components/Select/Select.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n MultiSelect as BaseMultiSelect,\n MultiSelectTrigger as BaseMultiSelectTrigger,\n MultiSelectValue as BaseMultiSelectValue,\n MultiSelectContent as BaseMultiSelectContent,\n MultiSelectItem as BaseMultiSelectItem,\n MultiSelectGroup as BaseMultiSelectGroup,\n MultiSelectSeparator as BaseMultiSelectSeparator,\n} from \"@dsui/ui/components/select\";\nimport {\n Combobox,\n type ComboboxProps,\n type SelectOption as SSelectOption,\n} from \"@dsui/ui/components/combobox\";\nimport { cn } from \"@dsui/ui/lib/utils\";\nimport { FloatingLabel } from \"@/components/FloatLabel\";\nimport { Info } from \"lucide-react\";\nimport { Tooltip } from \"../Tooltip/Tooltip\";\n\nexport type SelectOption = SSelectOption;\n\nexport type SelectProps = Omit<ComboboxProps, \"ref\"> & {\n label?: string;\n helperText?: React.ReactNode;\n state?: \"default\" | \"success\" | \"warning\" | \"error\";\n size?: \"xs\" | \"sm\" | \"normal\" | \"lg\" | \"xl\";\n isFloatLabel?: boolean;\n infoTooltip?: React.ReactNode;\n clearable?: boolean;\n placeholder?: string;\n options?: SelectOption[];\n tagRender?: (option: SelectOption) => React.ReactNode;\n multiple?: boolean;\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n values?: string[];\n defaultValues?: string | string[];\n onValuesChange?: (values: string[]) => void;\n search?: boolean | { placeholder?: string; emptyMessage?: string };\n clickToRemove?: boolean;\n overflowBehavior?: \"wrap\" | \"wrap-when-open\" | \"cutoff\";\n className?: string;\n disabled?: boolean;\n onChange?: (value: string | string[]) => void;\n onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;\n onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;\n};\n\nconst Select = React.forwardRef<HTMLDivElement, SelectProps>(\n (\n {\n className,\n label,\n helperText,\n state = \"default\",\n size = \"normal\",\n isFloatLabel,\n infoTooltip,\n clearable = false,\n placeholder = \"\",\n options = [],\n tagRender,\n multiple = false,\n value,\n defaultValue,\n onValueChange,\n values,\n defaultValues,\n onValuesChange,\n search,\n clickToRemove = true,\n overflowBehavior = \"wrap-when-open\",\n disabled,\n onChange,\n onFocus,\n onBlur,\n },\n ref\n ) => {\n const selectId = React.useId();\n\n // For single select, use controlled value or internal state\n const [internalValue, setInternalValue] = React.useState(\n value ?? defaultValue ?? \"\"\n );\n\n React.useEffect(() => {\n if (!multiple && value !== undefined) {\n setInternalValue(value);\n }\n }, [multiple, value]);\n\n // Handle single select value change\n const handleSingleValueChange = React.useCallback(\n (newValue?: string | null) => {\n const val = newValue || \"\";\n if (value === undefined) {\n setInternalValue(val);\n }\n onValueChange?.(val);\n onChange?.(val);\n },\n [onValueChange, onChange, value]\n );\n\n // Handle multi select values change\n const handleMultiValuesChange = React.useCallback(\n (newValues: string[]) => {\n onValuesChange?.(newValues);\n onChange?.(newValues);\n },\n [onValuesChange, onChange]\n );\n\n // Helper text styles\n const helperTextStyles = {\n default: \"text-muted-foreground\",\n success: \"text-success\",\n warning: \"text-warning\",\n error: \"text-error\",\n };\n\n // Calculate current size\n const currentSize = isFloatLabel\n ? size === \"xl\" || size === \"lg\"\n ? size\n : \"xl\"\n : size;\n\n // Group options by group property\n const groupedOptions = React.useMemo(() => {\n const groups = new Map<string | undefined, SelectOption[]>();\n options.forEach((option) => {\n const group = option.group;\n if (!groups.has(group)) {\n groups.set(group, []);\n }\n groups.get(group)!.push(option);\n });\n return groups;\n }, [options]);\n\n return (\n <div className={className}>\n <div\n ref={ref}\n className={cn(\"flex flex-col gap-1.5 relative\", {\n \"floating-label relative\": isFloatLabel,\n })}\n >\n {!isFloatLabel && label && (\n <label\n htmlFor={selectId}\n className=\"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n {infoTooltip && (\n <Tooltip content={infoTooltip}>\n <Info className=\"size-3.5 min-w-3.5\" />\n </Tooltip>\n )}\n </label>\n )}\n\n <div className=\"relative\">\n {!multiple ? (\n // Single Mode\n <>\n <Combobox\n value={value ?? internalValue}\n options={options}\n placeHolder={placeholder}\n emptyText={\n typeof search === \"object\"\n ? search.emptyMessage\n : \"No results found\"\n }\n onChange={handleSingleValueChange}\n clearable={clearable}\n disabled={disabled}\n id={selectId}\n className={cn(\n \"peer w-full justify-start\",\n {\n \"pt-5 pb-1\": isFloatLabel && size !== \"lg\",\n }\n // className,\n )}\n size={currentSize}\n state={state}\n dropdownClassName={cn(\"opacity-40\", {\n \"translate-y-[-8px]\": isFloatLabel && size !== \"lg\",\n })}\n searchable={!!search}\n tagRender={tagRender}\n onFocus={onFocus}\n onBlur={onBlur}\n />\n {isFloatLabel && (\n <FloatingLabel\n htmlFor={selectId}\n size={size}\n infoTooltip={infoTooltip}\n shouldFloat={!!(value ?? internalValue)}\n className=\"pointer-events-none\"\n >\n {label}\n </FloatingLabel>\n )}\n </>\n ) : (\n // Multi Mode\n <BaseMultiSelect\n values={values}\n defaultValues={\n typeof defaultValues === \"string\"\n ? [defaultValues]\n : defaultValues\n }\n onValuesChange={handleMultiValuesChange}\n >\n <BaseMultiSelectTrigger\n id={selectId}\n disabled={disabled}\n className={cn(\n \"peer w-full\",\n {\n \"pt-5 pb-1\": isFloatLabel && size !== \"lg\",\n },\n className\n )}\n size={currentSize}\n state={state}\n onFocus={onFocus}\n onBlur={onBlur}\n >\n <BaseMultiSelectValue\n placeholder={placeholder}\n clickToRemove={clickToRemove && clearable}\n overflowBehavior={overflowBehavior}\n />\n </BaseMultiSelectTrigger>\n\n {isFloatLabel && (\n <FloatingLabel\n htmlFor={selectId}\n size={size}\n infoTooltip={infoTooltip}\n >\n {label}\n </FloatingLabel>\n )}\n\n <BaseMultiSelectContent search={search}>\n {[...groupedOptions.entries()].map(([group, items]) => {\n if (group) {\n return (\n <React.Fragment key={group}>\n <BaseMultiSelectGroup heading={group}>\n {items.map((option) => (\n <BaseMultiSelectItem\n key={option.value}\n value={option.value}\n disabled={option?.disabled}\n icon={option?.icon}\n tagRender={!!tagRender}\n >\n {tagRender ? tagRender(option) : option.label}\n </BaseMultiSelectItem>\n ))}\n </BaseMultiSelectGroup>\n <BaseMultiSelectSeparator />\n </React.Fragment>\n );\n }\n return items.map((option) => (\n <BaseMultiSelectItem\n key={option.value}\n value={option.value}\n disabled={option?.disabled}\n icon={option?.icon}\n tagRender={!!tagRender}\n >\n {tagRender ? tagRender(option) : option.label}\n </BaseMultiSelectItem>\n ));\n })}\n </BaseMultiSelectContent>\n </BaseMultiSelect>\n )}\n </div>\n\n {helperText && (\n <p className={cn(\"text-xs\", state ? helperTextStyles[state] : \"\")}>\n {helperText}\n </p>\n )}\n </div>\n </div>\n );\n }\n);\n\nSelect.displayName = \"Select\";\nexport default Select;\n"],"names":["Select","React","className","label","helperText","state","size","isFloatLabel","infoTooltip","clearable","placeholder","options","tagRender","multiple","value","defaultValue","onValueChange","values","defaultValues","onValuesChange","search","clickToRemove","overflowBehavior","disabled","onChange","onFocus","onBlur","ref","selectId","internalValue","setInternalValue","handleSingleValueChange","newValue","val","handleMultiValuesChange","newValues","helperTextStyles","currentSize","groupedOptions","groups","option","group","jsx","jsxs","cn","Tooltip","Info","BaseMultiSelect","BaseMultiSelectTrigger","BaseMultiSelectValue","FloatingLabel","BaseMultiSelectContent","items","BaseMultiSelectGroup","BaseMultiSelectItem","BaseMultiSelectSeparator","Fragment","Combobox"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.cjs","sources":["../../../../src/components/Select/Select.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n MultiSelect as BaseMultiSelect,\n MultiSelectTrigger as BaseMultiSelectTrigger,\n MultiSelectValue as BaseMultiSelectValue,\n MultiSelectContent as BaseMultiSelectContent,\n MultiSelectItem as BaseMultiSelectItem,\n MultiSelectGroup as BaseMultiSelectGroup,\n MultiSelectSeparator as BaseMultiSelectSeparator,\n} from \"@dsui/ui/components/select\";\nimport {\n Combobox,\n type ComboboxProps,\n type SelectOption as SSelectOption,\n} from \"@dsui/ui/components/combobox\";\nimport { cn } from \"@dsui/ui/lib/utils\";\nimport { FloatingLabel } from \"@/components/FloatLabel\";\nimport { Info } from \"lucide-react\";\nimport { Tooltip } from \"../Tooltip/Tooltip\";\n\nexport type SelectOption = SSelectOption;\n\nexport type SelectProps = Omit<ComboboxProps, \"ref\"> & {\n label?: string;\n helperText?: React.ReactNode;\n state?: \"default\" | \"success\" | \"warning\" | \"error\";\n size?: \"xs\" | \"sm\" | \"normal\" | \"lg\" | \"xl\";\n isFloatLabel?: boolean;\n infoTooltip?: React.ReactNode;\n clearable?: boolean;\n placeholder?: string;\n options?: SelectOption[];\n tagRender?: (option: SelectOption) => React.ReactNode;\n multiple?: boolean;\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n values?: string[];\n defaultValues?: string | string[];\n onValuesChange?: (values: string[]) => void;\n search?: boolean | { placeholder?: string; emptyMessage?: string };\n clickToRemove?: boolean;\n overflowBehavior?: \"wrap\" | \"wrap-when-open\" | \"cutoff\";\n className?: string;\n disabled?: boolean;\n onChange?: (value: string | string[]) => void;\n onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;\n onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;\n required?: boolean;\n};\n\nconst Select = React.forwardRef<HTMLDivElement, SelectProps>(\n (\n {\n className,\n label,\n helperText,\n state = \"default\",\n size = \"normal\",\n isFloatLabel,\n infoTooltip,\n clearable = false,\n placeholder = \"\",\n options = [],\n tagRender,\n multiple = false,\n value,\n defaultValue,\n onValueChange,\n values,\n defaultValues,\n onValuesChange,\n search,\n clickToRemove = true,\n overflowBehavior = \"wrap-when-open\",\n disabled,\n onChange,\n onFocus,\n onBlur,\n required,\n },\n ref\n ) => {\n const selectId = React.useId();\n\n // For single select, use controlled value or internal state\n const [internalValue, setInternalValue] = React.useState(\n value ?? defaultValue ?? \"\"\n );\n\n React.useEffect(() => {\n if (!multiple && value !== undefined) {\n setInternalValue(value);\n }\n }, [multiple, value]);\n\n // Handle single select value change\n const handleSingleValueChange = React.useCallback(\n (newValue?: string | null) => {\n const val = newValue || \"\";\n if (value === undefined) {\n setInternalValue(val);\n }\n onValueChange?.(val);\n onChange?.(val);\n },\n [onValueChange, onChange, value]\n );\n\n // Handle multi select values change\n const handleMultiValuesChange = React.useCallback(\n (newValues: string[]) => {\n onValuesChange?.(newValues);\n onChange?.(newValues);\n },\n [onValuesChange, onChange]\n );\n\n // Helper text styles\n const helperTextStyles = {\n default: \"text-muted-foreground\",\n success: \"text-success\",\n warning: \"text-warning\",\n error: \"text-error\",\n };\n\n // Calculate current size\n const currentSize = isFloatLabel\n ? size === \"xl\" || size === \"lg\"\n ? size\n : \"xl\"\n : size;\n\n // Group options by group property\n const groupedOptions = React.useMemo(() => {\n const groups = new Map<string | undefined, SelectOption[]>();\n options.forEach((option) => {\n const group = option.group;\n if (!groups.has(group)) {\n groups.set(group, []);\n }\n groups.get(group)!.push(option);\n });\n return groups;\n }, [options]);\n\n return (\n <div className={className}>\n <div\n ref={ref}\n className={cn(\"flex flex-col gap-1.5 relative\", {\n \"floating-label relative\": isFloatLabel,\n })}\n >\n {!isFloatLabel && label && (\n <label\n htmlFor={selectId}\n className=\"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n <span>\n {label}\n {required && <span className=\"text-error ml-0.5\">*</span>}\n </span>\n {infoTooltip && (\n <Tooltip content={infoTooltip}>\n <Info className=\"size-3.5 min-w-3.5\" />\n </Tooltip>\n )}\n </label>\n )}\n\n <div className=\"relative\">\n {!multiple ? (\n // Single Mode\n <>\n <Combobox\n value={value ?? internalValue}\n options={options}\n placeHolder={placeholder}\n emptyText={\n typeof search === \"object\"\n ? search.emptyMessage\n : \"No results found\"\n }\n onChange={handleSingleValueChange}\n clearable={clearable}\n disabled={disabled}\n id={selectId}\n className={cn(\n \"peer w-full justify-start\",\n {\n \"pt-5 pb-1\": isFloatLabel && size !== \"lg\",\n }\n // className,\n )}\n size={currentSize}\n state={state}\n dropdownClassName={cn(\"opacity-40\", {\n \"translate-y-[-8px]\": isFloatLabel && size !== \"lg\",\n })}\n searchable={!!search}\n tagRender={tagRender}\n onFocus={onFocus}\n onBlur={onBlur}\n />\n {isFloatLabel && (\n <FloatingLabel\n htmlFor={selectId}\n size={size}\n infoTooltip={infoTooltip}\n required={required}\n shouldFloat={!!(value ?? internalValue)}\n className=\"pointer-events-none\"\n >\n {label}\n </FloatingLabel>\n )}\n </>\n ) : (\n // Multi Mode\n <BaseMultiSelect\n values={values}\n defaultValues={\n typeof defaultValues === \"string\"\n ? [defaultValues]\n : defaultValues\n }\n onValuesChange={handleMultiValuesChange}\n >\n <BaseMultiSelectTrigger\n id={selectId}\n disabled={disabled}\n className={cn(\n \"peer w-full\",\n {\n \"pt-5 pb-1\": isFloatLabel && size !== \"lg\",\n },\n className\n )}\n size={currentSize}\n state={state}\n onFocus={onFocus}\n onBlur={onBlur}\n >\n <BaseMultiSelectValue\n placeholder={placeholder}\n clickToRemove={clickToRemove && clearable}\n overflowBehavior={overflowBehavior}\n />\n </BaseMultiSelectTrigger>\n\n {isFloatLabel && (\n <FloatingLabel\n htmlFor={selectId}\n size={size}\n infoTooltip={infoTooltip}\n required={required}\n >\n {label}\n </FloatingLabel>\n )}\n\n <BaseMultiSelectContent search={search}>\n {[...groupedOptions.entries()].map(([group, items]) => {\n if (group) {\n return (\n <React.Fragment key={group}>\n <BaseMultiSelectGroup heading={group}>\n {items.map((option) => (\n <BaseMultiSelectItem\n key={option.value}\n value={option.value}\n disabled={option?.disabled}\n icon={option?.icon}\n tagRender={!!tagRender}\n >\n {tagRender ? tagRender(option) : option.label}\n </BaseMultiSelectItem>\n ))}\n </BaseMultiSelectGroup>\n <BaseMultiSelectSeparator />\n </React.Fragment>\n );\n }\n return items.map((option) => (\n <BaseMultiSelectItem\n key={option.value}\n value={option.value}\n disabled={option?.disabled}\n icon={option?.icon}\n tagRender={!!tagRender}\n >\n {tagRender ? tagRender(option) : option.label}\n </BaseMultiSelectItem>\n ));\n })}\n </BaseMultiSelectContent>\n </BaseMultiSelect>\n )}\n </div>\n\n {helperText && (\n <p className={cn(\"text-xs\", state ? helperTextStyles[state] : \"\")}>\n {helperText}\n </p>\n )}\n </div>\n </div>\n );\n }\n);\n\nSelect.displayName = \"Select\";\nexport default Select;\n"],"names":["Select","React","className","label","helperText","state","size","isFloatLabel","infoTooltip","clearable","placeholder","options","tagRender","multiple","value","defaultValue","onValueChange","values","defaultValues","onValuesChange","search","clickToRemove","overflowBehavior","disabled","onChange","onFocus","onBlur","required","ref","selectId","internalValue","setInternalValue","handleSingleValueChange","newValue","val","handleMultiValuesChange","newValues","helperTextStyles","currentSize","groupedOptions","groups","option","group","jsx","jsxs","cn","Tooltip","Info","BaseMultiSelect","BaseMultiSelectTrigger","BaseMultiSelectValue","FloatingLabel","BaseMultiSelectContent","items","BaseMultiSelectGroup","BaseMultiSelectItem","BaseMultiSelectSeparator","Fragment","Combobox"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),l=require("react"),
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),l=require("react"),T=require("../../packages/ui/src/components/textarea.cjs"),u=require("../../packages/ui/src/lib/utils.cjs"),b=require("lucide-react"),E=require("../Tooltip/Tooltip.cjs"),M=require("../FloatLabel.cjs"),V=require("../../packages/ui/src/components/label.cjs"),N=l.forwardRef(({className:y,label:d,helperText:i,state:o,size:t="normal",isFloatLabel:n,maxLength:a,showCharCount:h,infoTooltip:x,clearable:p,onClear:j,placeholder:w=" ",onChange:q,required:m,...r},I)=>{const[f,v]=l.useState(()=>typeof r.value=="string"?r.value.length:typeof r.defaultValue=="string"?r.defaultValue.length:0),R=c=>{v(c.target.value.length),q?.(c)},g=l.useId(),s=l.useRef(null);l.useImperativeHandle(I,()=>s.current);const S=()=>{if(s.current){s.current.value="",v(0);const c=new Event("input",{bubbles:!0});s.current.dispatchEvent(c),j&&j()}},C={default:"text-muted-foreground",success:"text-success",warning:"text-warning",error:"text-error"};return e.jsx("div",{className:y,children:e.jsxs("div",{className:u.cn("flex flex-col gap-1.5 relative",{"floating-label":n}),children:[!n&&d&&e.jsxs(V.Label,{htmlFor:g,className:"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",children:[e.jsxs("span",{children:[d,m&&e.jsx("span",{className:"text-error ml-0.5",children:"*"})]}),x&&e.jsx(E.Tooltip,{content:x,children:e.jsx(b.Info,{className:"size-3.5 min-w-3.5"})})]}),e.jsxs("div",{className:"relative",children:[e.jsx(T.Textarea,{ref:s,id:g,className:u.cn("peer resize-y",{"pt-6 pb-2":n&&(t==="lg"||t==="xl"),"pt-6 pb-1":n&&t!=="lg"&&t!=="xl","text-lg":(t==="xl"||t==="lg")&&!n},p&&f>0&&"pr-10"),placeholder:w,maxLength:a,onChange:R,state:o,size:n?t==="xl"||t==="lg"?t:"xl":t,required:m,...r}),n&&e.jsx(M.FloatingLabel,{htmlFor:g,size:t,infoTooltip:x,required:m,className:"peer-placeholder-shown:items-start",children:d}),p&&f>0&&e.jsx("button",{type:"button",tabIndex:-1,className:u.cn("absolute top-2 right-2 p-1 rounded hover:bg-accent transition-colors"),onClick:S,disabled:r.disabled,children:e.jsx(b.X,{className:"size-4"})})]}),(i||h&&typeof a=="number")&&e.jsxs("div",{className:"flex items-center justify-between text-xs gap-2",children:[i&&e.jsx("p",{className:u.cn("text-xs",o?C?.[o]:""),children:i}),h&&typeof a=="number"&&e.jsxs("span",{className:"ml-auto text-muted-foreground",children:[f," / ",a]})]})]})})});N.displayName="Textarea";exports.default=N;
|
|
2
2
|
//# sourceMappingURL=Textarea.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Textarea.cjs","sources":["../../../../src/components/Textarea/Textarea.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n Textarea as STextarea,\n type TextareaProps as STextareaProps,\n} from \"@dsui/ui/components/textarea\";\nimport { cn } from \"@dsui/ui/lib/utils\";\nimport { Info, X } from \"lucide-react\";\nimport { Tooltip } from \"../Tooltip/Tooltip\";\nimport { FloatingLabel } from \"@/components/FloatLabel\";\nimport { Label } from \"../Label\";\n\nexport type TextareaProps = Omit<\n STextareaProps,\n \"onChange\" | \"size\" | \"state\"\n> & {\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n size?: \"xs\" | \"sm\" | \"normal\" | \"lg\" | \"xl\";\n state?: \"default\" | \"success\" | \"warning\" | \"error\";\n label?: string;\n helperText?: React.ReactNode;\n isFloatLabel?: boolean;\n maxLength?: number;\n showCharCount?: boolean;\n infoTooltip?: React.ReactNode;\n clearable?: boolean;\n onClear?: () => void;\n};\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n {\n className,\n label,\n helperText,\n state,\n size = \"normal\",\n isFloatLabel,\n maxLength,\n showCharCount,\n infoTooltip,\n clearable,\n onClear,\n placeholder = \" \",\n onChange,\n ...props\n },\n ref\n ) => {\n // Character count state\n const [charCount, setCharCount] = React.useState(() => {\n if (typeof props.value === \"string\") return props.value.length;\n if (typeof props.defaultValue === \"string\")\n return props.defaultValue.length;\n return 0;\n });\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setCharCount(e.target.value.length);\n onChange?.(e);\n };\n\n const textareaId = React.useId();\n const innerRef = React.useRef<HTMLTextAreaElement>(null);\n\n // Combine refs\n React.useImperativeHandle(ref, () => innerRef.current!);\n\n const handleClear = () => {\n if (innerRef.current) {\n innerRef.current.value = \"\";\n setCharCount(0);\n const event = new Event(\"input\", { bubbles: true });\n innerRef.current.dispatchEvent(event);\n if (onClear) onClear();\n }\n };\n\n // State\n const helperTextStyles = {\n default: \"text-muted-foreground\",\n success: \"text-success\",\n warning: \"text-warning\",\n error: \"text-error\",\n };\n\n return (\n <div className={className}>\n <div\n className={cn(\"flex flex-col gap-1.5 relative\", {\n \"floating-label\": isFloatLabel,\n })}\n >\n {!isFloatLabel && label && (\n <Label\n htmlFor={textareaId}\n className=\"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n {label}\n {infoTooltip && (\n <Tooltip content={infoTooltip}>\n <Info className=\"size-3.5 min-w-3.5\" />\n </Tooltip>\n )}\n </Label>\n )}\n\n <div className=\"relative\">\n <STextarea\n ref={innerRef}\n id={textareaId}\n className={cn(\n \"peer resize-y\",\n {\n \"pt-6 pb-2\": isFloatLabel && (size === \"lg\" || size === \"xl\"),\n \"pt-6 pb-1\": isFloatLabel && size !== \"lg\" && size !== \"xl\",\n \"text-lg\": (size === \"xl\" || size === \"lg\") && !isFloatLabel,\n },\n clearable && charCount > 0 && \"pr-10\"\n // className\n )}\n placeholder={placeholder}\n maxLength={maxLength}\n onChange={handleInput}\n state={state}\n size={\n isFloatLabel\n ? size === \"xl\" || size === \"lg\"\n ? size\n : \"xl\"\n : size\n }\n {...props}\n />\n {isFloatLabel && (\n <FloatingLabel\n htmlFor={textareaId}\n size={size}\n infoTooltip={infoTooltip}\n className=\"peer-placeholder-shown:items-start\"\n >\n {label}\n </FloatingLabel>\n )}\n\n {/* Clear Button */}\n {clearable && charCount > 0 && (\n <button\n type=\"button\"\n tabIndex={-1}\n className={cn(\n \"absolute top-2 right-2 p-1 rounded hover:bg-accent transition-colors\"\n )}\n onClick={handleClear}\n disabled={props.disabled}\n >\n <X className=\"size-4\" />\n </button>\n )}\n </div>\n\n {(helperText || (showCharCount && typeof maxLength === \"number\")) && (\n <div className=\"flex items-center justify-between text-xs gap-2\">\n {helperText && (\n <p\n className={cn(\n \"text-xs\",\n state ? helperTextStyles?.[state] : \"\"\n )}\n >\n {helperText}\n </p>\n )}\n {showCharCount && typeof maxLength === \"number\" && (\n <span className=\"ml-auto text-muted-foreground\">\n {charCount} / {maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n );\n }\n);\n\nTextarea.displayName = \"Textarea\";\nexport default Textarea;\n"],"names":["Textarea","React","className","label","helperText","state","size","isFloatLabel","maxLength","showCharCount","infoTooltip","clearable","onClear","placeholder","onChange","props","ref","charCount","setCharCount","handleInput","e","textareaId","innerRef","handleClear","event","helperTextStyles","jsx","jsxs","cn","Label","Tooltip","Info","STextarea","FloatingLabel","X"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Textarea.cjs","sources":["../../../../src/components/Textarea/Textarea.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n Textarea as STextarea,\n type TextareaProps as STextareaProps,\n} from \"@dsui/ui/components/textarea\";\nimport { cn } from \"@dsui/ui/lib/utils\";\nimport { Info, X } from \"lucide-react\";\nimport { Tooltip } from \"../Tooltip/Tooltip\";\nimport { FloatingLabel } from \"@/components/FloatLabel\";\nimport { Label } from \"../Label\";\n\nexport type TextareaProps = Omit<\n STextareaProps,\n \"onChange\" | \"size\" | \"state\"\n> & {\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n size?: \"xs\" | \"sm\" | \"normal\" | \"lg\" | \"xl\";\n state?: \"default\" | \"success\" | \"warning\" | \"error\";\n label?: string;\n helperText?: React.ReactNode;\n isFloatLabel?: boolean;\n maxLength?: number;\n showCharCount?: boolean;\n infoTooltip?: React.ReactNode;\n clearable?: boolean;\n onClear?: () => void;\n required?: boolean;\n};\n\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n (\n {\n className,\n label,\n helperText,\n state,\n size = \"normal\",\n isFloatLabel,\n maxLength,\n showCharCount,\n infoTooltip,\n clearable,\n onClear,\n placeholder = \" \",\n onChange,\n required,\n ...props\n },\n ref\n ) => {\n // Character count state\n const [charCount, setCharCount] = React.useState(() => {\n if (typeof props.value === \"string\") return props.value.length;\n if (typeof props.defaultValue === \"string\")\n return props.defaultValue.length;\n return 0;\n });\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setCharCount(e.target.value.length);\n onChange?.(e);\n };\n\n const textareaId = React.useId();\n const innerRef = React.useRef<HTMLTextAreaElement>(null);\n\n // Combine refs\n React.useImperativeHandle(ref, () => innerRef.current!);\n\n const handleClear = () => {\n if (innerRef.current) {\n innerRef.current.value = \"\";\n setCharCount(0);\n const event = new Event(\"input\", { bubbles: true });\n innerRef.current.dispatchEvent(event);\n if (onClear) onClear();\n }\n };\n\n // State\n const helperTextStyles = {\n default: \"text-muted-foreground\",\n success: \"text-success\",\n warning: \"text-warning\",\n error: \"text-error\",\n };\n\n return (\n <div className={className}>\n <div\n className={cn(\"flex flex-col gap-1.5 relative\", {\n \"floating-label\": isFloatLabel,\n })}\n >\n {!isFloatLabel && label && (\n <Label\n htmlFor={textareaId}\n className=\"flex gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n >\n <span>\n {label}\n {required && <span className=\"text-error ml-0.5\">*</span>}\n </span>\n {infoTooltip && (\n <Tooltip content={infoTooltip}>\n <Info className=\"size-3.5 min-w-3.5\" />\n </Tooltip>\n )}\n </Label>\n )}\n\n <div className=\"relative\">\n <STextarea\n ref={innerRef}\n id={textareaId}\n className={cn(\n \"peer resize-y\",\n {\n \"pt-6 pb-2\": isFloatLabel && (size === \"lg\" || size === \"xl\"),\n \"pt-6 pb-1\": isFloatLabel && size !== \"lg\" && size !== \"xl\",\n \"text-lg\": (size === \"xl\" || size === \"lg\") && !isFloatLabel,\n },\n clearable && charCount > 0 && \"pr-10\"\n // className\n )}\n placeholder={placeholder}\n maxLength={maxLength}\n onChange={handleInput}\n state={state}\n size={\n isFloatLabel\n ? size === \"xl\" || size === \"lg\"\n ? size\n : \"xl\"\n : size\n }\n required={required}\n {...props}\n />\n {isFloatLabel && (\n <FloatingLabel\n htmlFor={textareaId}\n size={size}\n infoTooltip={infoTooltip}\n required={required}\n className=\"peer-placeholder-shown:items-start\"\n >\n {label}\n </FloatingLabel>\n )}\n\n {/* Clear Button */}\n {clearable && charCount > 0 && (\n <button\n type=\"button\"\n tabIndex={-1}\n className={cn(\n \"absolute top-2 right-2 p-1 rounded hover:bg-accent transition-colors\"\n )}\n onClick={handleClear}\n disabled={props.disabled}\n >\n <X className=\"size-4\" />\n </button>\n )}\n </div>\n\n {(helperText || (showCharCount && typeof maxLength === \"number\")) && (\n <div className=\"flex items-center justify-between text-xs gap-2\">\n {helperText && (\n <p\n className={cn(\n \"text-xs\",\n state ? helperTextStyles?.[state] : \"\"\n )}\n >\n {helperText}\n </p>\n )}\n {showCharCount && typeof maxLength === \"number\" && (\n <span className=\"ml-auto text-muted-foreground\">\n {charCount} / {maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n );\n }\n);\n\nTextarea.displayName = \"Textarea\";\nexport default Textarea;\n"],"names":["Textarea","React","className","label","helperText","state","size","isFloatLabel","maxLength","showCharCount","infoTooltip","clearable","onClear","placeholder","onChange","required","props","ref","charCount","setCharCount","handleInput","e","textareaId","innerRef","handleClear","event","helperTextStyles","jsx","jsxs","cn","Label","Tooltip","Info","STextarea","FloatingLabel","X"],"mappings":"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"}
|