@owodesign/owoui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,96 @@
1
+ import{Plus as Ot,ArrowRight as _t}from"lucide-react";import{clsx as qn}from"clsx";import{clsx as En}from"clsx";import{jsx as T,jsxs as Ie}from"react/jsx-runtime";var An={xs:12,sm:14,md:16,lg:24};function Hn({px:e}){let n=Math.PI*2*9;return Ie("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",children:[T("circle",{cx:"12",cy:"12",r:9,stroke:"currentColor",strokeWidth:"3",opacity:"0.2"}),T("circle",{cx:"12",cy:"12",r:9,stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeDasharray:`${n*.28} ${n*.72}`})]})}function On({px:e}){return Ie("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",children:[T("path",{d:"M12 2a10 10 0 0 1 10 10",opacity:"0.9"}),T("path",{d:"M12 2a10 10 0 0 0-7.07 2.93",opacity:"0.2"}),T("path",{d:"M4.93 4.93A10 10 0 0 0 2 12",opacity:"0.2"}),T("path",{d:"M2 12a10 10 0 0 0 2.93 7.07",opacity:"0.2"}),T("path",{d:"M4.93 19.07A10 10 0 0 0 12 22",opacity:"0.2"}),T("path",{d:"M12 22a10 10 0 0 0 7.07-2.93",opacity:"0.2"}),T("path",{d:"M19.07 19.07A10 10 0 0 0 22 12",opacity:"0.2"})]})}function _n({px:e}){return T("svg",{width:e,height:e,viewBox:"0 0 24 24",children:[0,1,2,3,4,5,6,7].map(n=>{let o=n/8*360,a=.15+n/8*.85;return T("circle",{cx:"12",cy:"3.5",r:"1.8",fill:"currentColor",opacity:a,transform:`rotate(${o} 12 12)`},n)})})}function Fn({px:e}){return T("svg",{width:e,height:e,viewBox:"0 0 24 24",children:[0,1,2,3].map(t=>Ie("rect",{x:3+t*5.5,y:"4",width:"3",height:"16",rx:"1.5",fill:"currentColor",opacity:"0.3",children:[T("animate",{attributeName:"opacity",values:"0.3;1;0.3",dur:"1s",begin:`${t*.15}s`,repeatCount:"indefinite"}),T("animate",{attributeName:"height",values:"16;8;16",dur:"1s",begin:`${t*.15}s`,repeatCount:"indefinite"}),T("animate",{attributeName:"y",values:"4;8;4",dur:"1s",begin:`${t*.15}s`,repeatCount:"indefinite"})]},t))})}function Vn({px:e}){let t=e*.14,n=e*.33,o=e/2-n,a=e/2,i=e/2+n,r=e/2;return T("svg",{width:e,height:e,viewBox:`0 0 ${e} ${e}`,children:[o,a,i].map((p,c)=>Ie("circle",{cx:p,cy:r,r:t,fill:"currentColor",opacity:"0.4",children:[T("animate",{attributeName:"cy",values:`${r};${r-e*.25};${r}`,dur:"0.6s",begin:`${c*.12}s`,repeatCount:"indefinite",calcMode:"spline",keySplines:"0.4 0 0.2 1;0.4 0 0.2 1"}),T("animate",{attributeName:"opacity",values:"0.4;1;0.4",dur:"0.6s",begin:`${c*.12}s`,repeatCount:"indefinite"})]},c))})}function Wn({px:e}){return Ie("svg",{width:e,height:e,viewBox:"0 0 24 24",children:[Ie("circle",{cx:"12",cy:"12",r:"0",fill:"currentColor",opacity:"0",children:[T("animate",{attributeName:"r",values:"4;10;4",dur:"1.2s",repeatCount:"indefinite"}),T("animate",{attributeName:"opacity",values:"0.8;0.1;0.8",dur:"1.2s",repeatCount:"indefinite"})]}),T("circle",{cx:"12",cy:"12",r:"3.5",fill:"currentColor",opacity:"0.7"})]})}function Gn({px:e}){return Ie("svg",{width:e,height:e,viewBox:"0 0 24 24",children:[T("circle",{cx:"12",cy:"12",r:"8",stroke:"currentColor",strokeWidth:"1.5",fill:"none",opacity:"0.15"}),T("circle",{cx:"12",cy:"4",r:"2.2",fill:"currentColor",children:T("animateTransform",{attributeName:"transform",type:"rotate",from:"0 12 12",to:"360 12 12",dur:"0.9s",repeatCount:"indefinite"})}),T("circle",{cx:"12",cy:"20",r:"1.5",fill:"currentColor",opacity:"0.5",children:T("animateTransform",{attributeName:"transform",type:"rotate",from:"0 12 12",to:"-360 12 12",dur:"0.9s",repeatCount:"indefinite"})})]})}function $n({px:e}){let t=e*.14,n=e*.33,o=e/2-n,a=e/2,i=e/2+n,r=e/2;return T("svg",{width:e,height:e,viewBox:`0 0 ${e} ${e}`,children:[o,a,i].map((p,c)=>T("circle",{cx:p,cy:r,r:t,fill:"currentColor",opacity:"0.25",children:T("animate",{attributeName:"opacity",values:"0.25;1;0.25",dur:"0.9s",begin:`${c*.2}s`,repeatCount:"indefinite"})},c))})}var Un={ring:Hn,arc:On,dots:_n,bars:Fn,bounce:Vn,pulse:Wn,orbit:Gn,flow:$n},Kn=new Set(["ring","arc","dots"]);function ie({variant:e="ring",size:t="md",className:n,label:o}){let a=typeof t=="number"?t:An[t],i=Un[e];return T("span",{"aria-hidden":!o,"aria-label":o,role:o?"img":void 0,className:En("ui-spinner inline-flex",Kn.has(e)&&"motion-safe:animate-spin",n),children:T(i,{px:a})})}import{Fragment as Yn,jsx as Be,jsxs as Qn}from"react/jsx-runtime";function Xn({variant:e="secondary",size:t="md",loading:n=!1,className:o}){return qn("ui-button","inline-flex items-center justify-center gap-2 rounded-md border font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset disabled:cursor-not-allowed disabled:opacity-[var(--button-disabled-opacity)]",t==="sm"?"min-h-8 px-3 text-xs":"min-h-9 px-4 text-sm",n&&"pointer-events-none cursor-wait",o)}function d(e){let{variant:t="secondary",size:n="md",loading:o=!1,leadingIcon:a,trailingIcon:i,className:r,children:p,...c}=e,s=Qn(Yn,{children:[o?Be("span",{className:"shrink-0",children:Be(ie,{size:n==="sm"?"sm":"md"})}):a?Be("span",{className:"shrink-0",children:a}):null,Be("span",{children:p}),!o&&i?Be("span",{className:"shrink-0",children:i}):null]}),u=Xn({variant:t,size:n,loading:o,className:r});if("href"in e&&e.href){let{href:m,...g}=c;return Be("a",{href:m,"data-variant":t,"data-size":n,"data-loading":o?"true":void 0,"aria-disabled":o||void 0,tabIndex:o?-1:void 0,className:u,onClick:o?w=>w.preventDefault():void 0,...g,children:s})}let l=c;return Be("button",{type:l.type??"button","data-variant":t,"data-size":n,"data-loading":o?"true":void 0,disabled:l.disabled||o,className:u,...l,children:s})}var bt=[],Zn=[{group:"actions",componentId:"button"},{group:"actions",componentId:"dropdown-menu"},{group:"actions",componentId:"icon-button"},{group:"forms",componentId:"input"},{group:"forms",componentId:"field"},{group:"forms",componentId:"select"},{group:"forms",componentId:"segmented-control"},{group:"forms",componentId:"switch"},{group:"feedback",componentId:"badge"},{group:"feedback",componentId:"status-notice"},{group:"feedback",componentId:"empty-state"},{group:"feedback",componentId:"spinner"},{group:"feedback",componentId:"skeleton"},{group:"feedback",componentId:"dialog"},{group:"feedback",componentId:"toast"},{group:"feedback",componentId:"avatar"},{group:"feedback",componentId:"tooltip"},{group:"layout",componentId:"drawer"},{group:"layout",componentId:"panel"}];function y(e){bt.push(e)}function Jn(e,t){return bt.find(n=>n.group===e&&n.componentId===t)}function jn(){let e={actions:[],forms:[],feedback:[],layout:[]};for(let t of bt)e[t.group].push(t);return e}var eo={actions:"Actions",forms:"Forms",feedback:"Feedback",layout:"Layout"},to=["actions","forms","feedback","layout"];import{jsx as _,jsxs as We}from"react/jsx-runtime";y({group:"actions",componentId:"button",componentName:"Button",description:"Primary action trigger. Supports variants, sizes, icons, loading, and disabled states.",props:[{name:"variant",type:"'primary' | 'secondary' | 'ghost' | 'danger'",default:"'secondary'",description:"Visual style variant."},{name:"size",type:"'sm' | 'md'",default:"'md'",description:"Button size."},{name:"loading",type:"boolean",default:"false",description:"Shows loading state and sets cursor-wait."},{name:"leadingIcon",type:"ReactNode",description:"Icon rendered before children."},{name:"trailingIcon",type:"ReactNode",description:"Icon rendered after children."},{name:"href",type:"string",description:"When set, renders as a Next.js Link."},{name:"disabled",type:"boolean",default:"false",description:"Disables the button."}],renderPlayground:e=>_(d,{variant:e.variant,size:e.size,loading:!!e.loading,disabled:!!e.disabled,children:"Button"}),stories:[{id:"variants",title:"Variants",description:"primary / secondary / ghost / danger",source:`<Button variant="primary">Primary</Button>
2
+ <Button variant="secondary">Secondary</Button>
3
+ <Button variant="ghost">Ghost</Button>
4
+ <Button variant="danger">Danger</Button>`,render:()=>We("div",{className:"flex flex-wrap items-center gap-3",children:[_(d,{variant:"primary",children:"Primary"}),_(d,{variant:"secondary",children:"Secondary"}),_(d,{variant:"ghost",children:"Ghost"}),_(d,{variant:"danger",children:"Danger"})]})},{id:"sizes",title:"Sizes",description:"sm / md",render:()=>We("div",{className:"flex flex-wrap items-center gap-3",children:[_(d,{size:"sm",children:"Small"}),_(d,{size:"md",children:"Medium"})]})},{id:"with-icons",title:"With Icons",description:"leadingIcon / trailingIcon",render:()=>We("div",{className:"flex flex-wrap items-center gap-3",children:[_(d,{variant:"primary",leadingIcon:_(Ot,{size:16}),children:"Create"}),_(d,{variant:"secondary",trailingIcon:_(_t,{size:16}),children:"Next"}),_(d,{variant:"ghost",leadingIcon:_(Ot,{size:16}),trailingIcon:_(_t,{size:16}),children:"Both"})]})},{id:"loading-disabled",title:"Loading & Disabled",render:()=>We("div",{className:"flex flex-wrap items-center gap-3",children:[_(d,{variant:"primary",loading:!0,children:"Saving\u2026"}),_(d,{variant:"secondary",loading:!0,children:"Loading"}),_(d,{variant:"secondary",disabled:!0,children:"Disabled"}),_(d,{variant:"danger",disabled:!0,children:"Disabled Danger"})]})},{id:"all-variants-sm",title:"All Variants (sm)",render:()=>We("div",{className:"flex flex-wrap items-center gap-3",children:[_(d,{variant:"primary",size:"sm",children:"Primary"}),_(d,{variant:"secondary",size:"sm",children:"Secondary"}),_(d,{variant:"ghost",size:"sm",children:"Ghost"}),_(d,{variant:"danger",size:"sm",children:"Danger"})]})}]});import{X as Ge,Settings as et,Trash2 as oo,ChevronRight as ao}from"lucide-react";import{clsx as no}from"clsx";import{jsx as Ft}from"react/jsx-runtime";function Y({variant:e="ghost",size:t="md",label:n,icon:o,className:a,...i}){let r=no("ui-icon-button","inline-flex items-center justify-center rounded-md transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset disabled:cursor-not-allowed disabled:opacity-50",t==="sm"?"h-7 w-7":"h-8 w-8",a);if("href"in i&&i.href){let{href:c,...s}=i;return Ft("a",{href:c,"aria-label":n,title:s.title??n,"data-variant":e,"data-size":t,className:r,...s,children:o})}let p=i;return Ft("button",{type:p.type??"button","aria-label":n,title:p.title??n,"data-variant":e,"data-size":t,className:r,...p,children:o})}import{jsx as F,jsxs as tt}from"react/jsx-runtime";y({group:"actions",componentId:"icon-button",componentName:"IconButton",description:"Icon-only action button. Supports ghost/subtle variants, sm/md sizes.",props:[{name:"variant",type:"'ghost' | 'subtle'",default:"'ghost'",description:"Visual style variant."},{name:"size",type:"'sm' | 'md'",default:"'md'",description:"Button size."},{name:"label",type:"string",description:"Accessible label used for aria-label and title fallback."},{name:"icon",type:"ReactNode",description:"Icon content rendered inside the button."},{name:"href",type:"string",description:"When set, renders as a Next.js Link instead of a button."},{name:"disabled",type:"boolean",default:"false",description:"Disables button interaction when rendered as a button."}],renderPlayground:e=>F(Y,{variant:e.variant,size:e.size,disabled:!!e.disabled,label:"Settings",icon:F(et,{size:e.size==="sm"?14:16})}),stories:[{id:"variants",title:"Variants",description:"ghost / subtle",render:()=>tt("div",{className:"flex items-center gap-3",children:[F(Y,{variant:"ghost",label:"Close",icon:F(Ge,{size:16})}),F(Y,{variant:"subtle",label:"Settings",icon:F(et,{size:16})})]})},{id:"sizes",title:"Sizes",description:"sm / md",render:()=>tt("div",{className:"flex items-center gap-3",children:[F(Y,{size:"sm",label:"Small",icon:F(Ge,{size:14})}),F(Y,{size:"md",label:"Medium",icon:F(Ge,{size:16})})]})},{id:"use-cases",title:"Use Cases",render:()=>tt("div",{className:"flex items-center gap-3",children:[F(Y,{label:"Close",icon:F(Ge,{size:16})}),F(Y,{label:"Settings",icon:F(et,{size:16})}),F(Y,{label:"Delete",icon:F(oo,{size:16})}),F(Y,{label:"Navigate",icon:F(ao,{size:16})})]})},{id:"disabled",title:"Disabled",render:()=>tt("div",{className:"flex items-center gap-3",children:[F(Y,{label:"Disabled ghost",icon:F(Ge,{size:16}),disabled:!0}),F(Y,{variant:"subtle",label:"Disabled subtle",icon:F(et,{size:16}),disabled:!0})]})}]});import{clsx as io}from"clsx";import{jsx as Wt}from"react/jsx-runtime";function Vt(e){return io("ui-input w-full rounded-lg px-3 py-2 text-sm placeholder:text-[var(--field-placeholder)] focus:outline-none focus:ring-1",e)}function de(e){let{className:t,tone:n="default",...o}=e;return e.as==="textarea"?Wt("textarea",{"data-tone":n,className:Vt(t),...o}):Wt("input",{"data-tone":n,className:Vt(t),...o})}import{jsx as Se,jsxs as Gt}from"react/jsx-runtime";y({group:"forms",componentId:"input",componentName:"Input",description:"Unified input element. Renders as input or textarea via the `as` prop. For dropdown selection, use the Select component.",props:[{name:"as",type:"'input' | 'textarea'",default:"'input'",description:"Chooses which native form element to render."},{name:"tone",type:"'default' | 'warning'",default:"'default'",description:"Visual tone for neutral or warning emphasis."},{name:"className",type:"string",description:"Additional CSS classes for the rendered element."},{name:"placeholder",type:"string",description:"Placeholder text for input or textarea variants."},{name:"rows",type:"number",description:'Textarea row count when `as="textarea"`.'}],renderPlayground:e=>Se("div",{className:"max-w-xs",children:Se(de,{as:e.as,tone:e.tone,placeholder:"Type something\u2026"})}),stories:[{id:"text-input",title:"Text Input",render:()=>Gt("div",{className:"max-w-xs space-y-3",children:[Se(de,{"aria-label":"Default input",name:"demo-default",autoComplete:"off",placeholder:"e.g., hello world\u2026"}),Se(de,{"aria-label":"With value",name:"demo-value",autoComplete:"off",placeholder:"e.g., hello world\u2026",defaultValue:"Hello world"})]})},{id:"textarea",title:"Textarea",render:()=>Se("div",{className:"max-w-sm",children:Se(de,{as:"textarea","aria-label":"Textarea",placeholder:"Write something\u2026",rows:3})})},{id:"tones",title:"Tones",description:"default / warning",render:()=>Gt("div",{className:"max-w-xs space-y-3",children:[Se(de,{tone:"default","aria-label":"Default tone",name:"demo-tone-default",autoComplete:"off",placeholder:"Default tone\u2026"}),Se(de,{tone:"warning","aria-label":"Warning tone",name:"demo-tone-warning",autoComplete:"off",placeholder:"Warning tone\u2026"})]})}]});import{useState as uo}from"react";import{clsx as ro}from"clsx";import{jsx as $t,jsxs as so}from"react/jsx-runtime";function Ee({label:e,help:t,htmlFor:n,children:o,className:a,...i}){return so("div",{className:ro("ui-field block",a),...i,children:[$t("label",{htmlFor:n,className:"ui-field__label mb-1 block text-xs",children:e}),o,t?$t("span",{className:"ui-field__help mt-1 block text-xs",children:t}):null]})}import{clsx as Ae}from"clsx";import{useCallback as vt,useEffect as Ut,useId as lo,useMemo as co,useRef as Kt,useState as qt}from"react";import{jsx as $e,jsxs as Xt}from"react/jsx-runtime";function ce({value:e,onChange:t,options:n,placeholder:o="Select\u2026",size:a="md",tone:i="default",disabled:r=!1,className:p,ariaLabel:c,renderValue:s,renderOption:u}){let[l,m]=qt(!1),[g,w]=qt(-1),M=Kt(null),v=Kt(null),h=lo(),D=n.find(f=>f.value===e),N=co(()=>n.reduce((f,k,Z)=>(k.disabled||f.push(Z),f),[]),[n]),z=vt(()=>{if(r||n.length===0)return;m(!0);let f=n.findIndex(k=>k.value===e);w(f>=0?f:N[0]??-1)},[r,n,e,N]),S=vt(()=>{m(!1),w(-1)},[]),W=vt(f=>{f.disabled||(t(f.value),S())},[t,S]);Ut(()=>{if(!l)return;function f(k){M.current&&!M.current.contains(k.target)&&S()}return document.addEventListener("mousedown",f),()=>document.removeEventListener("mousedown",f)},[l,S]),Ut(()=>{if(!l||g<0)return;v.current?.children[g]?.scrollIntoView({block:"nearest"})},[l,g]);function G(f){if(!r)switch(f.key){case"Enter":case" ":{f.preventDefault(),l?g>=0&&n[g]&&!n[g].disabled&&W(n[g]):z();break}case"ArrowDown":{if(f.preventDefault(),!l)z();else{let k=N.indexOf(g),Z=N[k+1];Z!==void 0&&w(Z)}break}case"ArrowUp":{if(f.preventDefault(),!l)z();else{let k=N.indexOf(g),Z=N[k-1];Z!==void 0&&w(Z)}break}case"Escape":{l&&(f.preventDefault(),S());break}case"Tab":{l&&S();break}}}let q=e!==""&&D,I=s?s({open:l,placeholder:o,selectedOption:D}):$e("span",{className:Ae("truncate",!q&&"ui-select__placeholder"),children:q?D.label:o});return Xt("div",{ref:M,"data-state":l?"open":"closed","data-disabled":r||void 0,"data-size":a,"data-tone":i,className:Ae("ui-select relative inline-block",p),children:[Xt("button",{type:"button",role:"combobox","aria-expanded":l,"aria-haspopup":"listbox","aria-controls":h,"aria-label":c,"aria-activedescendant":l&&g>=0?`${h}-opt-${g}`:void 0,"data-state":l?"open":"closed","data-disabled":r||void 0,"data-tone":i,"data-size":a,"data-open":l||void 0,"data-has-value":q||void 0,disabled:r,className:Ae("ui-select__trigger flex w-full items-center justify-between gap-2 rounded-lg text-left transition-colors focus:outline-none focus:ring-1",a==="sm"?"min-h-7 px-2 py-1 text-xs":"min-h-9 px-3 py-2 text-sm"),onClick:()=>l?S():z(),onKeyDown:G,children:[I,$e("svg",{"aria-hidden":"true",className:Ae("ui-select__chevron h-3.5 w-3.5 shrink-0 transition-transform",l&&"rotate-180"),viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:$e("path",{d:"M4 6l4 4 4-4"})})]}),l&&$e("ul",{ref:v,id:h,role:"listbox","aria-label":c,"data-state":"open",className:Ae("ui-select__dropdown absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-lg py-1 ring-1",a==="sm"?"text-xs":"text-sm"),children:n.map((f,k)=>$e("li",{id:`${h}-opt-${k}`,role:"option","aria-selected":f.value===e,"aria-disabled":f.disabled||void 0,"data-state":f.value===e?"selected":k===g?"highlighted":"idle","data-focused":k===g||void 0,"data-selected":f.value===e||void 0,"data-disabled":f.disabled||void 0,"data-highlighted":k===g||void 0,className:Ae("ui-select__option cursor-default select-none px-3 py-1.5 transition-colors",f.disabled&&"cursor-not-allowed opacity-50"),onClick:()=>W(f),onMouseEnter:()=>!f.disabled&&w(k),children:u?u({option:f,index:k,selected:f.value===e,highlighted:k===g}):f.label},f.value))})]})}import{jsx as re}from"react/jsx-runtime";function po(){let[e,t]=uo("");return re("div",{className:"max-w-xs pb-36",children:re(Ee,{label:"Category",htmlFor:"sb-category",children:re(ce,{value:e,onChange:t,options:[{value:"tech",label:"Technology"},{value:"design",label:"Design"},{value:"other",label:"Other"}],placeholder:"Select a category",ariaLabel:"Category"})})})}y({group:"forms",componentId:"field",componentName:"Field",description:"Form field wrapper with label and optional help text.",props:[{name:"label",type:"ReactNode",description:"Visible field label rendered above the control."},{name:"help",type:"ReactNode",description:"Optional helper text rendered below the control."},{name:"htmlFor",type:"string",description:"Associates the label with the inner form control id."},{name:"children",type:"ReactNode",description:"Form control content, such as Input or Select."}],stories:[{id:"basic",title:"Basic Field",render:()=>re("div",{className:"max-w-xs",children:re(Ee,{label:"Username",htmlFor:"sb-username",children:re(de,{id:"sb-username",name:"username",autoComplete:"username",placeholder:"Enter username"})})})},{id:"with-help",title:"With Help Text",render:()=>re("div",{className:"max-w-xs",children:re(Ee,{label:"Email",htmlFor:"sb-email",help:"We'll never share your email.",children:re(de,{id:"sb-email",type:"email",name:"email",autoComplete:"email",spellCheck:!1,placeholder:"you@example.com"})})})},{id:"with-textarea",title:"With Textarea",render:()=>re("div",{className:"max-w-sm",children:re(Ee,{label:"Bio",htmlFor:"sb-bio",help:"Brief description about yourself.",children:re(de,{as:"textarea",id:"sb-bio",name:"bio",autoComplete:"off",placeholder:"Tell us about yourself\u2026",rows:3})})})},{id:"with-select",title:"With Select",render:()=>re(po,{})}]});import{useState as Ue}from"react";import{jsx as J,jsxs as ht}from"react/jsx-runtime";function mo(){let[e,t]=Ue("");return J("div",{className:"max-w-xs pb-44",children:J(ce,{value:e,onChange:t,options:[{value:"apple",label:"Apple"},{value:"banana",label:"Banana"},{value:"cherry",label:"Cherry"},{value:"dragonfruit",label:"Dragonfruit"}],placeholder:"Choose a fruit\u2026",ariaLabel:"Fruit select"})})}function fo(){let[e,t]=Ue("apple"),[n,o]=Ue("apple"),a=[{value:"apple",label:"Apple"},{value:"banana",label:"Banana"},{value:"cherry",label:"Cherry"}];return ht("div",{className:"flex max-w-xs flex-col gap-3 pb-36",children:[J(ce,{value:e,onChange:t,options:[...a],size:"sm",ariaLabel:"Small select"}),J(ce,{value:n,onChange:o,options:[...a],size:"md",ariaLabel:"Medium select"})]})}function go(){let[e,t]=Ue("a"),[n,o]=Ue("a"),a=[{value:"a",label:"Option A"},{value:"b",label:"Option B"}];return ht("div",{className:"flex max-w-xs flex-col gap-3 pb-28",children:[J(ce,{value:e,onChange:t,options:[...a],tone:"default",ariaLabel:"Default tone"}),J(ce,{value:n,onChange:o,options:[...a],tone:"warning",ariaLabel:"Warning tone"})]})}function bo(){return ht("div",{className:"flex max-w-xs flex-col gap-3 pb-28",children:[J(ce,{value:"",onChange:()=>{},options:[{value:"a",label:"Option A"}],disabled:!0,placeholder:"Disabled",ariaLabel:"Disabled select"}),J(ce,{value:"",onChange:()=>{},options:[{value:"a",label:"Enabled"},{value:"b",label:"Disabled option",disabled:!0},{value:"c",label:"Also enabled"}],placeholder:"Has disabled option",ariaLabel:"Disabled option select"})]})}y({group:"forms",componentId:"select",componentName:"Select",description:"Custom dropdown select with keyboard navigation and design-system styling.",props:[{name:"value",type:"string",description:"Currently selected value."},{name:"onChange",type:"(value: T) => void",description:"Callback when selection changes."},{name:"options",type:"SelectOption<T>[]",description:"Array of { value, label, disabled? }."},{name:"placeholder",type:"string",default:"'Select\u2026'",description:"Placeholder text when no value is selected."},{name:"size",type:"'sm' | 'md'",default:"'md'",description:"Trigger size."},{name:"tone",type:"'default' | 'warning'",default:"'default'",description:"Visual tone."},{name:"disabled",type:"boolean",default:"false",description:"Disables the entire select."},{name:"ariaLabel",type:"string",description:"Accessible label for the trigger button."}],renderPlayground:(e,t)=>J("div",{className:"max-w-xs pb-36",children:J(ce,{value:String(e.value??""),onChange:n=>t("value",n),options:[{value:"apple",label:"Apple"},{value:"banana",label:"Banana"},{value:"cherry",label:"Cherry"}],size:e.size,tone:e.tone,disabled:!!e.disabled,ariaLabel:"Playground select"})}),stories:[{id:"default",title:"Default",render:()=>J(mo,{})},{id:"sizes",title:"Sizes",description:"sm / md",render:()=>J(fo,{})},{id:"tones",title:"Tones",description:"default / warning",render:()=>J(go,{})},{id:"disabled",title:"Disabled",description:"Whole component disabled & individual option disabled.",render:()=>J(bo,{})}]});import{useState as Jt}from"react";import{clsx as Yt}from"clsx";import{jsx as Qt}from"react/jsx-runtime";function nt({value:e,onChange:t,options:n,size:o="sm",className:a,ariaLabel:i}){return Qt("div",{role:"tablist","aria-label":i,className:Yt("ui-segmented-control inline-flex rounded-md p-0.5 ring-1",o==="sm"?"text-xs":"text-sm",a),children:n.map(r=>{let p=r.value===e;return Qt("button",{type:"button",role:"tab","aria-selected":p,disabled:r.disabled,"data-active":p?"true":void 0,className:Yt("ui-segmented-control__item rounded font-medium transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-inset disabled:cursor-not-allowed disabled:opacity-50",o==="sm"?"px-2.5 py-1":"px-3 py-1.5"),onClick:()=>t(r.value),children:r.label},r.value)})})}import{jsx as Ke,jsxs as ho}from"react/jsx-runtime";function Zt({size:e,label:t}){let[n,o]=Jt("a");return Ke(nt,{value:n,onChange:o,options:[{value:"a",label:"Alpha"},{value:"b",label:"Beta"},{value:"c",label:"Gamma"}],size:e,ariaLabel:t})}function vo(){let[e,t]=Jt("on");return Ke(nt,{value:e,onChange:t,options:[{value:"on",label:"On"},{value:"off",label:"Off"},{value:"auto",label:"Auto",disabled:!0}],ariaLabel:"Mode with disabled"})}y({group:"forms",componentId:"segmented-control",componentName:"SegmentedControl",description:"Tab-like toggle for mutually exclusive options.",props:[{name:"value",type:"T extends string",description:"Currently selected option value."},{name:"onChange",type:"(value: T) => void",description:"Called when a new option is selected."},{name:"options",type:"Array<{ value: T; label: string; disabled?: boolean }>",description:"Selectable option list."},{name:"size",type:"'sm' | 'md'",default:"'sm'",description:"Control size."},{name:"ariaLabel",type:"string",description:"Accessible label for the tablist."}],stories:[{id:"sizes",title:"Sizes",description:"sm / md",render:()=>ho("div",{className:"flex flex-wrap items-center gap-4",children:[Ke(Zt,{size:"sm",label:"Small"}),Ke(Zt,{size:"md",label:"Medium"})]})},{id:"with-disabled",title:"With Disabled Option",render:()=>Ke(vo,{})}]});import{useState as ot}from"react";import{clsx as jt}from"clsx";import{jsx as en}from"react/jsx-runtime";var yo={sm:"h-5 w-9",md:"h-6 w-11"},wo={sm:"h-3.5 w-3.5",md:"h-4.5 w-4.5"},xo={sm:"translate-x-4",md:"translate-x-5"};function xe({checked:e,onChange:t,size:n="md",disabled:o=!1,className:a,ariaLabel:i}){return en("button",{type:"button",role:"switch","aria-checked":e,"aria-label":i,disabled:o,"data-size":n,className:jt("ui-switch relative inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",yo[n],o&&"cursor-not-allowed opacity-50",a),onClick:()=>t(!e),children:en("span",{"aria-hidden":"true",className:jt("ui-switch__thumb pointer-events-none inline-block rounded-full bg-white shadow transition-transform",wo[n],e?xo[n]:"translate-x-0.5")})})}import{jsx as be,jsxs as yt}from"react/jsx-runtime";function No(){let[e,t]=ot(!1);return be(xe,{checked:e,onChange:t,ariaLabel:"Demo toggle"})}function So(){let[e,t]=ot(!0),[n,o]=ot(!0);return yt("div",{className:"flex items-center gap-4",children:[be(xe,{checked:e,onChange:t,size:"sm",ariaLabel:"Small switch"}),be(xe,{checked:n,onChange:o,size:"md",ariaLabel:"Medium switch"})]})}function To(){let[e,t]=ot(!1);return yt("label",{className:"inline-flex items-center gap-2 text-sm text-[var(--color-n800)]",children:[be(xe,{checked:e,onChange:t,ariaLabel:"Notifications"}),"Enable notifications"]})}y({group:"forms",componentId:"switch",componentName:"Switch",description:"Toggle switch for boolean settings.",props:[{name:"checked",type:"boolean",description:"Controlled checked state."},{name:"onChange",type:"(checked: boolean) => void",description:"Callback when toggled."},{name:"size",type:"'sm' | 'md'",default:"'md'",description:"Switch size."},{name:"disabled",type:"boolean",default:"false",description:"Disables the switch."},{name:"ariaLabel",type:"string",description:"Accessible label."}],renderPlayground:(e,t)=>be(xe,{checked:!!e.checked,onChange:n=>t("checked",n),size:e.size,disabled:!!e.disabled,ariaLabel:"Playground switch"}),stories:[{id:"default",title:"Default",render:()=>be(No,{})},{id:"sizes",title:"Sizes",description:"sm / md",render:()=>be(So,{})},{id:"with-label",title:"With Label",render:()=>be(To,{})},{id:"disabled",title:"Disabled",render:()=>yt("div",{className:"flex items-center gap-4",children:[be(xe,{checked:!1,onChange:()=>{},disabled:!0,ariaLabel:"Disabled off"}),be(xe,{checked:!0,onChange:()=>{},disabled:!0,ariaLabel:"Disabled on"})]})}]});import{clsx as Co}from"clsx";import{jsx as Do}from"react/jsx-runtime";function K({tone:e="neutral",variant:t="soft",size:n="xs",className:o,children:a,...i}){return Do("span",{"data-tone":e,"data-variant":t,"data-size":n,className:Co("ui-badge inline-flex items-center rounded-full border text-[var(--badge-text)]",n==="xs"?"px-2.5 py-1 text-[11px]":"px-3 py-1 text-xs font-medium",o),...i,children:a})}import{jsx as j,jsxs as He}from"react/jsx-runtime";y({group:"feedback",componentId:"badge",componentName:"Badge",description:"Inline label for status, categories, or counts. Token-driven: --badge-bg, --badge-text, --badge-border.",props:[{name:"tone",type:"'neutral' | 'info' | 'success' | 'warning' | 'danger'",default:"'neutral'",description:"Semantic color tone."},{name:"variant",type:"'soft' | 'outline'",default:"'soft'",description:"Fill style. Soft uses tinted background; outline uses transparent bg with visible border."},{name:"size",type:"'xs' | 'sm'",default:"'xs'",description:"Compact or slightly larger badge size."},{name:"children",type:"ReactNode",description:"Badge content."}],renderPlayground:e=>j(K,{tone:e.tone,variant:e.variant,size:e.size,children:"Badge"}),stories:[{id:"tones-soft",title:"Tones (Soft)",description:"neutral / info / success / warning / danger \u2014 soft variant",render:()=>He("div",{className:"flex flex-wrap items-center gap-3",children:[j(K,{tone:"neutral",children:"Neutral"}),j(K,{tone:"info",children:"Info"}),j(K,{tone:"success",children:"Success"}),j(K,{tone:"warning",children:"Warning"}),j(K,{tone:"danger",children:"Danger"})]})},{id:"tones-outline",title:"Tones (Outline)",description:"Same tones with outline variant \u2014 transparent bg, colored border.",render:()=>He("div",{className:"flex flex-wrap items-center gap-3",children:[j(K,{tone:"neutral",variant:"outline",children:"Neutral"}),j(K,{tone:"info",variant:"outline",children:"Info"}),j(K,{tone:"success",variant:"outline",children:"Success"}),j(K,{tone:"warning",variant:"outline",children:"Warning"}),j(K,{tone:"danger",variant:"outline",children:"Danger"})]})},{id:"sizes",title:"Sizes",description:"xs / sm",render:()=>He("div",{className:"flex flex-wrap items-center gap-3",children:[j(K,{size:"xs",tone:"info",children:"XS Badge"}),j(K,{size:"sm",tone:"info",children:"SM Badge"})]})},{id:"variant-comparison",title:"Variant Comparison",description:"Soft vs outline side by side for each tone.",render:()=>j("div",{className:"space-y-3",children:["neutral","info","success","warning","danger"].map(e=>He("div",{className:"flex items-center gap-3",children:[He(K,{size:"sm",tone:e,variant:"soft",children:[e," soft"]}),He(K,{size:"sm",tone:e,variant:"outline",children:[e," outline"]})]},e))})}]});import{Info as Io,CheckCircle2 as Bo,TriangleAlert as Ro,CircleAlert as Lo}from"lucide-react";import{clsx as ko}from"clsx";import{Fragment as Po,jsx as wt,jsxs as Mo}from"react/jsx-runtime";function ue({tone:e="neutral",icon:t,className:n,children:o,...a}){return wt("div",{"data-tone":e,className:ko("ui-status-notice rounded-md border px-4 py-3 text-sm",t&&"ui-status-notice--with-icon grid grid-cols-[auto_minmax(0,1fr)] gap-3",n),...a,children:t?Mo(Po,{children:[wt("span",{className:"ui-status-notice__icon mt-0.5 shrink-0","aria-hidden":"true",children:t}),wt("div",{className:"min-w-0",children:o})]}):o})}import{jsx as ee,jsxs as tn}from"react/jsx-runtime";y({group:"feedback",componentId:"status-notice",componentName:"StatusNotice",description:"Block-level feedback banner. Supports neutral plus semantic tones, with optional icon slot.",props:[{name:"tone",type:"'neutral' | 'info' | 'success' | 'warning' | 'danger'",default:"'neutral'",description:"Semantic message tone."},{name:"icon",type:"ReactNode",description:"Optional leading icon slot."},{name:"children",type:"ReactNode",description:"Notice content."},{name:"className",type:"string",description:"Additional classes for layout or spacing."}],renderPlayground:e=>ee(ue,{tone:e.tone,children:"This is a status notice."}),stories:[{id:"tones",title:"Tones",description:"info / success / warning / danger",render:()=>tn("div",{className:"space-y-3",children:[ee(ue,{tone:"neutral",children:"General system guidance without a semantic alert state."}),ee(ue,{tone:"info",children:"This is an informational notice."}),ee(ue,{tone:"success",children:"Operation completed successfully."}),ee(ue,{tone:"warning",children:"Please review before continuing."}),ee(ue,{tone:"danger",children:"Something went wrong. Please try again."})]})},{id:"with-icons",title:"With Icons",render:()=>tn("div",{className:"space-y-3",children:[ee(ue,{tone:"info",icon:ee(Io,{size:16}),children:"Background indexing is still in progress."}),ee(ue,{tone:"success",icon:ee(Bo,{size:16}),children:"Draft and main are fully aligned."}),ee(ue,{tone:"warning",icon:ee(Ro,{size:16}),children:"One route conflict still needs manual review."}),ee(ue,{tone:"danger",icon:ee(Lo,{size:16}),children:"Publishing failed. Retry after refreshing the snapshot."})]})}]});import{clsx as zo}from"clsx";import{jsx as qe,jsxs as Eo}from"react/jsx-runtime";function Te({tone:e="neutral",icon:t,title:n,description:o,action:a,className:i,children:r,...p}){let c=t||n||o||a;return qe("div",{"data-tone":e,className:zo("ui-empty-state rounded-lg border px-4 py-3 text-sm",i),...p,children:c?Eo("div",{className:"flex flex-col items-center gap-2 py-4 text-center",children:[t&&qe("div",{className:"ui-empty-state__icon text-lg",children:t}),n&&qe("div",{className:"ui-empty-state__title font-medium",children:n}),o&&qe("div",{className:"ui-empty-state__description",children:o}),a&&qe("div",{className:"mt-2",children:a})]}):r})}import{jsx as Ce,jsxs as Ao}from"react/jsx-runtime";y({group:"feedback",componentId:"empty-state",componentName:"EmptyState",description:"Placeholder for empty lists or missing content. Token-driven: --empty-state-bg, --empty-state-border, --empty-state-title, --empty-state-text, --empty-state-icon.",props:[{name:"tone",type:"'neutral' | 'notice' | 'warning'",default:"'neutral'",description:"Semantic tone for contextual emphasis."},{name:"icon",type:"ReactNode",description:"Optional icon displayed above title."},{name:"title",type:"ReactNode",description:"Optional title text."},{name:"description",type:"ReactNode",description:"Optional description text."},{name:"action",type:"ReactNode",description:"Optional action slot (e.g. a button)."},{name:"children",type:"ReactNode",description:"Fallback content when structured slots are not used."}],stories:[{id:"basic",title:"Basic (children)",render:()=>Ce(Te,{children:"No items found."})},{id:"structured",title:"Structured Slots",description:"Using title, description, and action slots.",render:()=>Ce(Te,{title:"No posts yet",description:"Create your first post to get started.",action:Ce(d,{variant:"primary",size:"sm",children:"Create Post"})})},{id:"tones",title:"Tones",description:"neutral / notice / warning",render:()=>Ao("div",{className:"space-y-4",children:[Ce(Te,{tone:"neutral",title:"Neutral",description:"Default empty state."}),Ce(Te,{tone:"notice",title:"Notice",description:"Informational empty state."}),Ce(Te,{tone:"warning",title:"Warning",description:"Attention-drawing empty state."})]})},{id:"with-icon",title:"With Icon",render:()=>Ce(Te,{icon:Ce("span",{className:"text-2xl",children:"\u{1F4ED}"}),title:"Inbox empty",description:"You have no new messages."})}]});import{jsx as te,jsxs as Oe}from"react/jsx-runtime";y({group:"feedback",componentId:"spinner",componentName:"Spinner",description:"Animated loading indicator with multiple icon styles. Used standalone or composed into other components (e.g. Button loading state).",props:[{name:"variant",type:"'ring' | 'arc' | 'dots' | 'bars' | 'bounce' | 'pulse' | 'orbit' | 'flow'",default:"'ring'",description:"Spinner icon style."},{name:"size",type:"'xs' | 'sm' | 'md' | 'lg'",default:"'md'",description:"Preset size, or pass a number for custom pixel size."},{name:"label",type:"string",description:"Accessible label. When set, spinner is announced to screen readers."},{name:"className",type:"string",description:"Additional CSS classes."}],renderPlayground:e=>te(ie,{variant:e.variant,size:e.size}),stories:[{id:"variants",title:"Variants",description:"ring / arc / dots / bars / bounce / pulse / orbit / flow",render:()=>te("div",{className:"flex flex-wrap items-center gap-8",children:["ring","arc","dots","bars","bounce","pulse","orbit","flow"].map(e=>Oe("div",{className:"flex flex-col items-center gap-2",children:[te(ie,{variant:e,size:"lg"}),te("span",{className:"text-[11px] text-[var(--color-n500)]",children:e})]},e))})},{id:"sizes",title:"Sizes",description:"xs / sm / md / lg",render:()=>Oe("div",{className:"flex items-center gap-4",children:[te(ie,{size:"xs"}),te(ie,{size:"sm"}),te(ie,{size:"md"}),te(ie,{size:"lg"})]})},{id:"with-text",title:"Inline with Text",render:()=>Oe("div",{className:"space-y-3",children:[Oe("div",{className:"flex items-center gap-2 text-sm text-[var(--color-n600)]",children:[te(ie,{variant:"ring",size:"sm"}),te("span",{children:"Loading data\u2026"})]}),Oe("div",{className:"flex items-center gap-2 text-sm text-[var(--color-n600)]",children:[te(ie,{variant:"flow",size:"sm"}),te("span",{children:"Processing\u2026"})]}),Oe("div",{className:"flex items-center gap-2 text-sm text-[var(--color-n600)]",children:[te(ie,{variant:"bounce",size:"sm"}),te("span",{children:"Waiting for response\u2026"})]})]})}]});import{clsx as Ho}from"clsx";import{jsx as _o}from"react/jsx-runtime";var Oo={slow:"4s",default:"3s",fast:"2s"};function H({className:e,animation:t="scan",tone:n="default",speed:o="default",style:a,...i}){let r=n==="warm"?"emphasis":n,p={...a,"--ui-skeleton-scan-duration":Oo[o]};return _o("div",{className:Ho("ui-skeleton rounded",e),"data-animation":t,"data-tone":r,"aria-hidden":"true",style:p,...i})}import{jsx as B,jsxs as se}from"react/jsx-runtime";y({group:"feedback",componentId:"skeleton",componentName:"Skeleton",description:"Loading placeholder with `scan` or `pulse` animation and configurable speed.",props:[{name:"animation",type:"'pulse' | 'scan'",default:"'scan'",description:"Chooses the loading motion style."},{name:"tone",type:"'default' | 'emphasis'",default:"'default'",description:"Semantic emphasis level of the placeholder."},{name:"speed",type:"'slow' | 'default' | 'fast'",default:"'default'",description:"Scan animation speed: slow (4s), default (3s), fast (2s)."},{name:"className",type:"string",description:"Controls skeleton shape and dimensions."}],renderPlayground:e=>se("div",{className:"space-y-3",children:[B(H,{animation:e.animation,tone:e.tone,speed:e.speed,className:"h-4 w-48"}),B(H,{animation:e.animation,tone:e.tone,speed:e.speed,className:"h-4 w-64"})]}),stories:[{id:"scan",title:"Scan",render:()=>se("div",{className:"space-y-4",children:[B(H,{className:"h-4 w-48"}),B(H,{className:"h-4 w-64"}),B(H,{className:"h-4 w-32"})]})},{id:"scan-speed",title:"Scan Speed",render:()=>se("div",{className:"space-y-4",children:[se("div",{className:"space-y-2",children:[B("div",{className:"text-xs font-medium text-[var(--color-n500)]",children:"Slow \xB7 4s"}),B(H,{speed:"slow",className:"h-4 w-64"})]}),se("div",{className:"space-y-2",children:[B("div",{className:"text-xs font-medium text-[var(--color-n500)]",children:"Default \xB7 3s"}),B(H,{className:"h-4 w-64"})]}),se("div",{className:"space-y-2",children:[B("div",{className:"text-xs font-medium text-[var(--color-n500)]",children:"Fast \xB7 2s"}),B(H,{speed:"fast",className:"h-4 w-64"})]})]})},{id:"pulse",title:"Pulse",render:()=>se("div",{className:"space-y-4",children:[B(H,{animation:"pulse",className:"h-4 w-48"}),B(H,{animation:"pulse",className:"h-4 w-64"}),B(H,{animation:"pulse",className:"h-4 w-32"})]})},{id:"on-surfaces",title:"On Different Surfaces",description:"Verifies shimmer visibility against various backgrounds.",render:()=>B("div",{className:"grid gap-4 sm:grid-cols-3",children:[{label:"Canvas",bg:"var(--color-surface-canvas)"},{label:"Base",bg:"var(--color-surface-base)"},{label:"Inset",bg:"var(--color-surface-inset)"}].map(({label:e,bg:t})=>se("div",{className:"rounded-lg p-4",style:{backgroundColor:t},children:[B("p",{className:"mb-2 text-[11px] font-medium text-[var(--color-n500)]",children:e}),se("div",{className:"space-y-2",children:[B(H,{className:"h-4 w-full"}),B(H,{className:"h-4 w-3/4"})]})]},e))})},{id:"card-placeholder",title:"Card Placeholder",render:()=>se("div",{className:"max-w-sm space-y-3 rounded-lg border border-[var(--color-surface-border)] p-4",children:[B(H,{className:"h-5 w-3/4"}),B(H,{className:"h-4 w-full"}),B(H,{className:"h-4 w-5/6"}),se("div",{className:"flex gap-2 pt-2",children:[B(H,{animation:"pulse",className:"h-8 w-20 rounded-md"}),B(H,{animation:"pulse",className:"h-8 w-20 rounded-md"})]})]})},{id:"avatar-line",title:"Avatar + Lines",render:()=>se("div",{className:"flex items-start gap-3",children:[B(H,{className:"h-10 w-10 shrink-0 rounded-full"}),se("div",{className:"flex-1 space-y-2",children:[B(H,{animation:"pulse",className:"h-4 w-32"}),B(H,{className:"h-3 w-48"})]})]})}]});import{useState as at}from"react";import{clsx as Xe}from"clsx";import{useEffect as Fo,useRef as nn,useCallback as Vo}from"react";import{jsx as Ye,jsxs as Uo}from"react/jsx-runtime";function Wo({className:e,children:t,...n}){return Ye("div",{className:Xe("ui-dialog__header px-5 pt-5 pb-1 text-base font-semibold",e),...n,children:t})}function Go({className:e,children:t,...n}){return Ye("div",{className:Xe("ui-dialog__body px-5 py-3 text-sm",e),...n,children:t})}function $o({className:e,children:t,...n}){return Ye("div",{className:Xe("ui-dialog__footer flex items-center justify-end gap-2 px-5 pt-3 pb-5",e),...n,children:t})}function R({open:e,onClose:t,size:n="sm",children:o,className:a,overlayClassName:i,panelClassName:r,...p}){let c=nn(null),s=nn(null),u=Vo(l=>{l.key==="Escape"&&(l.stopPropagation(),t())},[t]);return Fo(()=>(e?(s.current=document.activeElement,document.body.style.overflow="hidden",requestAnimationFrame(()=>{let l=c.current;if(!l)return;let m=l.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');m?m.focus():l.focus()}),document.addEventListener("keydown",u)):(document.body.style.overflow="",s.current?.focus()),()=>{document.removeEventListener("keydown",u),document.body.style.overflow=""}),[e,u]),e?Uo("div",{"data-state":"open",className:"ui-dialog-overlay fixed inset-0 z-50 flex items-center justify-center",children:[Ye("button",{type:"button","aria-label":"Close dialog","data-state":"open",className:Xe("ui-dialog-backdrop absolute inset-0 bg-black/30",i),onClick:t}),Ye("div",{ref:c,role:"dialog","aria-modal":"true",tabIndex:-1,"data-state":"open","data-size":n,className:Xe("ui-dialog relative z-10 w-full rounded-xl shadow-xl","animate-[dialog-in_0.2s_var(--ease-standard)]",n==="sm"?"max-w-[26rem]":"max-w-[32rem]",r,a),...p,children:o})]}):null}R.Header=Wo;R.Body=Go;R.Footer=$o;import{createContext as Ko,useCallback as on,useContext as qo,useRef as Xo,useState as Yo}from"react";import{Fragment as Qo,jsx as _e,jsxs as xt}from"react/jsx-runtime";var an=Ko(null);function rn(){let e=qo(an);if(!e)throw new Error("useConfirm must be used within <ConfirmProvider>");return e}function sn({children:e}){let[t,n]=Yo(null),o=Xo(null),a=on(r=>(o.current&&o.current.resolve(!1),new Promise(p=>{let c={options:r,resolve:p};o.current=c,n(c)})),[]),i=on(r=>{o.current&&(o.current.resolve(r),o.current=null),n(null)},[]);return xt(an.Provider,{value:a,children:[e,_e(R,{open:t!==null,onClose:()=>i(!1),children:t&&xt(Qo,{children:[_e(R.Header,{children:t.options.title}),_e(R.Body,{children:typeof t.options.description=="string"?_e("p",{className:"whitespace-pre-wrap",children:t.options.description}):t.options.description}),xt(R.Footer,{children:[_e(d,{variant:"ghost",size:"sm",onClick:()=>i(!1),children:t.options.cancelLabel??"\u53D6\u6D88"}),_e(d,{variant:t.options.variant??"primary",size:"sm",onClick:()=>i(!0),children:t.options.confirmLabel??"\u786E\u8BA4"})]})]})})]})}import{Fragment as Nt,jsx as b,jsxs as L}from"react/jsx-runtime";function Zo(){let[e,t]=at(!1);return L(Nt,{children:[b(d,{variant:"primary",size:"sm",onClick:()=>t(!0),children:"Open Dialog"}),L(R,{open:e,onClose:()=>t(!1),children:[b(R.Header,{children:"Basic Dialog"}),b(R.Body,{children:b("p",{children:"This is a basic dialog with header, body, and footer sections."})}),L(R.Footer,{children:[b(d,{variant:"ghost",size:"sm",onClick:()=>t(!1),children:"Cancel"}),b(d,{variant:"primary",size:"sm",onClick:()=>t(!1),children:"Confirm"})]})]})]})}function Jo(){let[e,t]=at(!1);return L(Nt,{children:[b(d,{variant:"danger",size:"sm",onClick:()=>t(!0),children:"Delete Item"}),L(R,{open:e,onClose:()=>t(!1),children:[b(R.Header,{children:"Delete Draft"}),L(R.Body,{children:[b("p",{children:"Are you sure you want to delete the ZH locale draft?"}),L("p",{className:"mt-2",children:["Article ID: post-20260320-example",b("br",{}),"Category: post"]}),b("p",{className:"mt-2",children:"This action cannot be undone."})]}),L(R.Footer,{children:[b(d,{variant:"ghost",size:"sm",onClick:()=>t(!1),children:"Cancel"}),b(d,{variant:"danger",size:"sm",onClick:()=>t(!1),children:"Delete"})]})]})]})}function jo(){let[e,t]=at(!1);return L(Nt,{children:[b(d,{variant:"secondary",size:"sm",onClick:()=>t(!0),children:"Open Medium Dialog"}),L(R,{open:e,onClose:()=>t(!1),size:"md",children:[b(R.Header,{children:"Publish Confirmation"}),L(R.Body,{children:[b("p",{children:"You are about to publish the current draft branch."}),L("div",{className:"mt-3 rounded-lg border border-[var(--color-surface-border)] bg-[var(--color-surface-base)] p-3 text-sm",children:[L("div",{className:"flex justify-between",children:[b("span",{children:"Articles:"}),b("span",{children:"3"})]}),L("div",{className:"flex justify-between",children:[b("span",{children:"Languages:"}),b("span",{children:"ZH, EN"})]}),L("div",{className:"flex justify-between",children:[b("span",{children:"Branch:"}),b("span",{children:"draft"})]})]}),b("p",{className:"mt-3",children:"This will trigger a Cloudflare deployment."})]}),L(R.Footer,{children:[b(d,{variant:"ghost",size:"sm",onClick:()=>t(!1),children:"Cancel"}),b(d,{variant:"primary",size:"sm",onClick:()=>t(!1),children:"Publish"})]})]})]})}function ea(){let e=rn(),[t,n]=at("");return L("div",{className:"flex flex-col gap-3",children:[L("div",{className:"flex gap-2",children:[b(d,{variant:"primary",size:"sm",onClick:async()=>{let i=await e({title:"Confirm Action",description:"This demonstrates the useConfirm() hook. Click confirm or cancel.",confirmLabel:"Do it",cancelLabel:"Nope"});n(i?"Confirmed!":"Cancelled.")},children:"useConfirm()"}),b(d,{variant:"danger",size:"sm",onClick:async()=>{let i=await e({title:"Delete Everything",description:"This is a danger variant confirm dialog.",confirmLabel:"Delete",variant:"danger"});n(i?"Deleted!":"Cancelled.")},children:"Danger Confirm"})]}),t&&L("p",{className:"text-sm text-[var(--color-n600)]",children:["Result: ",t]})]})}function ta(){return b(sn,{children:b(ea,{})})}y({group:"feedback",componentId:"dialog",componentName:"Dialog",description:"Modal dialog for confirmations and focused tasks. Supports declarative usage via <Dialog> and imperative usage via `useConfirm()` hook. The imperative API requires `<ConfirmProvider>` in an ancestor (mounted in admin layout).",props:[{name:"open",type:"boolean",default:"false",description:"Controls dialog visibility."},{name:"size",type:"'sm' | 'md'",default:"'sm'",description:"Dialog width."},{name:"onClose",type:"() => void",description:"Called on backdrop click or Escape key."}],renderPlayground:(e,t)=>{let n=e.size||"sm",o=!!e.open;return L("div",{className:"flex flex-col items-center gap-4",children:[L(d,{variant:"primary",size:"sm",onClick:()=>t("open",!0),children:["Open Dialog (",n,")"]}),L(R,{open:o,onClose:()=>t("open",!1),size:n,children:[b(R.Header,{children:"Playground Dialog"}),b(R.Body,{children:L("p",{children:["Toggle the ",b("code",{className:"rounded bg-[var(--color-surface-subtle)] px-1 py-0.5 text-xs",children:"open"})," and ",b("code",{className:"rounded bg-[var(--color-surface-subtle)] px-1 py-0.5 text-xs",children:"size"})," controls below."]})}),L(R.Footer,{children:[b(d,{variant:"ghost",size:"sm",onClick:()=>t("open",!1),children:"Cancel"}),b(d,{variant:"primary",size:"sm",onClick:()=>t("open",!1),children:"Confirm"})]})]})]})},stories:[{id:"provider-setup",title:"Provider Setup",description:"useConfirm() requires <ConfirmProvider> in an ancestor. Mount it once in your layout \u2014 all descendant components can then call useConfirm().",source:`// src/app/qadmin/layout.tsx
5
+ import { ConfirmProvider } from '../../components/ConfirmDialog';
6
+
7
+ export default function AdminLayout({ children }) {
8
+ return (
9
+ <ThemeProvider>
10
+ <ConfirmProvider>
11
+ {children}
12
+ </ConfirmProvider>
13
+ </ThemeProvider>
14
+ );
15
+ }
16
+
17
+ // Any descendant component
18
+ import { useConfirm } from '../../components/ConfirmDialog';
19
+
20
+ function MyComponent() {
21
+ const confirm = useConfirm();
22
+
23
+ const handleDelete = async () => {
24
+ const ok = await confirm({
25
+ title: 'Delete draft',
26
+ description: 'This cannot be undone.',
27
+ confirmLabel: 'Delete',
28
+ variant: 'danger',
29
+ });
30
+ if (!ok) return;
31
+ // proceed with deletion
32
+ };
33
+ }`,render:()=>L("div",{className:"rounded-lg border border-[var(--color-surface-border)] bg-[var(--color-surface-subtle)] px-4 py-3 text-sm text-[var(--color-n600)]",children:[b("p",{className:"font-medium text-[var(--color-n800)]",children:"Provider is already mounted in admin layout."}),L("p",{className:"mt-1",children:["Click the ",b("strong",{children:"Code"})," button below to see the setup example."]})]})},{id:"basic",title:"Basic Dialog",description:"Standard confirmation dialog with header, body, and footer.",source:`<Dialog open={open} onClose={() => setOpen(false)}>
34
+ <Dialog.Header>Title</Dialog.Header>
35
+ <Dialog.Body>Content here.</Dialog.Body>
36
+ <Dialog.Footer>
37
+ <Button variant="ghost" onClick={close}>Cancel</Button>
38
+ <Button variant="primary" onClick={close}>Confirm</Button>
39
+ </Dialog.Footer>
40
+ </Dialog>`,render:()=>b(Zo,{})},{id:"danger",title:"Danger Dialog",description:"Destructive action confirmation with danger-styled button.",render:()=>b(Jo,{})},{id:"medium",title:"Medium Size",description:"Wider dialog for content-heavy confirmations.",render:()=>b(jo,{})},{id:"use-confirm",title:"useConfirm() Hook",description:"Imperative confirm API that returns a Promise<boolean>. Replaces window.confirm.",source:`const confirm = useConfirm();
41
+ const ok = await confirm({
42
+ title: 'Confirm',
43
+ description: 'Are you sure?',
44
+ variant: 'danger',
45
+ });`,render:()=>b(ta,{})}]});import{clsx as ln}from"clsx";import{createContext as na,useCallback as dn,useContext as oa,useMemo as aa,useRef as cn,useState as ia}from"react";import{jsx as $,jsxs as Qe}from"react/jsx-runtime";var pn=na(null),St=5,un=4e3;function mn(){let e=oa(pn);if(!e)throw new Error("useToast must be used within <ToastProvider>");return e}function ra({tone:e}){let t={width:16,height:16,viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};switch(e){case"success":return $("svg",{...t,children:$("path",{d:"M3.5 8.5l3 3 6-7"})});case"warning":return Qe("svg",{...t,children:[$("path",{d:"M8 5v4"}),$("circle",{cx:"8",cy:"11.5",r:"0.5",fill:"currentColor",stroke:"none"})]});case"danger":return $("svg",{...t,children:$("path",{d:"M4.5 4.5l7 7M11.5 4.5l-7 7"})});case"info":return Qe("svg",{...t,children:[$("circle",{cx:"8",cy:"3.5",r:"1.2",fill:"currentColor",stroke:"none"}),$("path",{d:"M8 7v5.5"})]})}}function sa(e,t){return typeof e=="string"?{message:e,duration:t??un}:{title:e.title,message:e.message,duration:e.duration??t??un}}function la({item:e,onDismiss:t,renderToast:n}){let o=()=>t(e.id),a=$(ra,{tone:e.tone});return n?$("div",{role:"status","aria-live":"polite","data-state":"open","data-tone":e.tone,className:ln("ui-toast pointer-events-auto rounded-lg border text-sm backdrop-blur-sm","animate-[toast-in_0.25s_var(--ease-standard)]"),children:n({item:e,dismiss:o,icon:a})}):Qe("div",{role:"status","aria-live":"polite","data-state":"open","data-tone":e.tone,className:ln("ui-toast pointer-events-auto flex items-start gap-2 rounded-lg border px-4 py-3 text-sm backdrop-blur-sm","animate-[toast-in_0.25s_var(--ease-standard)]"),children:[$("span",{className:"ui-toast__icon mt-0.5 shrink-0","aria-hidden":"true",children:a}),Qe("span",{className:"min-w-0 flex-1",children:[e.title?$("span",{className:"ui-toast__title block font-medium",children:e.title}):null,$("span",{className:"block",children:e.message})]}),$("button",{type:"button",onClick:o,className:"ui-toast__close -mr-1 -mt-0.5 shrink-0 rounded p-0.5 text-current opacity-50 transition-opacity hover:opacity-100","aria-label":"Dismiss",children:$("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:$("path",{d:"M4 4l8 8M12 4l-8 8"})})})]})}function fn({children:e,renderToast:t}){let[n,o]=ia([]),a=cn(0),i=cn(new Map),r=dn(s=>{let u=i.current.get(s);u&&clearTimeout(u),i.current.delete(s),o(l=>l.filter(m=>m.id!==s))},[]),p=dn((s,u,l)=>{let m=a.current++,g=sa(u,l),w={id:m,tone:s,...g};o(M=>{let v=[...M,w];if(v.length>St){let h=v.slice(0,v.length-St);for(let D of h){let N=i.current.get(D.id);N&&clearTimeout(N),i.current.delete(D.id)}return v.slice(-St)}return v}),w.duration>0&&i.current.set(m,setTimeout(()=>r(m),w.duration))},[r]),c=aa(()=>({success:(s,u)=>p("success",s,u),warning:(s,u)=>p("warning",s,u),danger:(s,u)=>p("danger",s,u),info:(s,u)=>p("info",s,u)}),[p]);return Qe(pn.Provider,{value:c,children:[e,$("div",{"aria-label":"Notifications","data-state":n.length>0?"open":"closed",className:"pointer-events-none fixed bottom-4 right-4 z-[9999] flex flex-col-reverse gap-2",children:n.map(s=>$(la,{item:s,onDismiss:r,renderToast:t},s.id))})]})}import{jsx as ve,jsxs as Tt}from"react/jsx-runtime";function da(){let e=mn();return Tt("div",{className:"flex flex-wrap gap-2",children:[ve(d,{size:"sm",variant:"secondary",onClick:()=>e.success("Changes saved successfully."),children:"Success"}),ve(d,{size:"sm",variant:"secondary",onClick:()=>e.warning("Draft has unsaved changes."),children:"Warning"}),ve(d,{size:"sm",variant:"secondary",onClick:()=>e.danger("Failed to publish post."),children:"Danger"}),ve(d,{size:"sm",variant:"secondary",onClick:()=>e.info("New version available."),children:"Info"}),ve(d,{size:"sm",variant:"secondary",onClick:()=>e.success({title:"Draft Saved",message:"All local changes are now synced to the draft branch."}),children:"With Title"})]})}function ca(){return ve(fn,{children:ve(da,{})})}y({group:"feedback",componentId:"toast",componentName:"Toast",description:"Transient notification messages triggered via `useToast()` hook. Requires `<ToastProvider>` wrapper.",props:[{name:"toast.success({ title, message, duration? })",type:"function",description:"Show a success toast with optional title."},{name:"toast.success(msg, duration?)",type:"function",description:"Show a success toast."},{name:"toast.warning(msg, duration?)",type:"function",description:"Show a warning toast."},{name:"toast.danger(msg, duration?)",type:"function",description:"Show a danger toast."},{name:"toast.info(msg, duration?)",type:"function",description:"Show an info toast."}],stories:[{id:"provider-setup",title:"Provider Setup",description:"useToast() requires <ToastProvider> in an ancestor. Mount it once in your layout \u2014 all descendant components can then call useToast().",source:`// src/app/qadmin/layout.tsx
46
+ import { ToastProvider } from '../../components/Toast';
47
+
48
+ export default function AdminLayout({ children }) {
49
+ return (
50
+ <ThemeProvider>
51
+ <ToastProvider>
52
+ {children}
53
+ </ToastProvider>
54
+ </ThemeProvider>
55
+ );
56
+ }
57
+
58
+ // Any descendant component
59
+ import { useToast } from '../../components/Toast';
60
+
61
+ function MyComponent() {
62
+ const toast = useToast();
63
+
64
+ const handleSave = async () => {
65
+ try {
66
+ await saveDraft();
67
+ toast.success('Draft saved.');
68
+ } catch {
69
+ toast.danger('Failed to save draft.');
70
+ }
71
+ };
72
+ }`,render:()=>Tt("div",{className:"rounded-lg border border-[var(--color-surface-border)] bg-[var(--color-surface-subtle)] px-4 py-3 text-sm text-[var(--color-n600)]",children:[ve("p",{className:"font-medium text-[var(--color-n800)]",children:"ToastProvider is not yet mounted in admin layout."}),Tt("p",{className:"mt-1",children:["Add it to the layout before using useToast(). Click the ",ve("strong",{children:"Code"})," button below to see the setup example."]})]})},{id:"all-tones",title:"All Tones",description:"Click buttons to trigger toasts, including the optional title layout.",render:()=>ve(ca,{})}]});import{clsx as ua}from"clsx";import{useState as pa}from"react";import{jsx as Ct}from"react/jsx-runtime";var ma={xs:"h-6 w-6 text-[10px]",sm:"h-8 w-8 text-xs",md:"h-10 w-10 text-sm",lg:"h-14 w-14 text-lg"};function fa(e){let t=e.trim().split(/\s+/);return t.length>=2?(t[0][0]+t[t.length-1][0]).toUpperCase():e.slice(0,2).toUpperCase()}function ne({src:e,alt:t,name:n,size:o="md",tone:a="neutral",className:i}){let[r,p]=pa(!1),c=e&&!r,s=n?fa(n):"?";return Ct("span",{"data-tone":a,className:ua("ui-avatar inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full font-medium select-none",ma[o],i),children:c?Ct("img",{src:e,alt:t??n??"",className:"h-full w-full object-cover",onError:()=>p(!0)}):Ct("span",{"aria-label":t??n,children:s})})}import{jsx as oe,jsxs as Fe}from"react/jsx-runtime";y({group:"feedback",componentId:"avatar",componentName:"Avatar",description:"User avatar with image or initials fallback. Token-driven: --avatar-bg, --avatar-text, --avatar-border.",props:[{name:"src",type:"string",description:"Image URL."},{name:"alt",type:"string",description:"Alt text for the image."},{name:"name",type:"string",description:"User name, used to derive initials fallback."},{name:"size",type:"'xs' | 'sm' | 'md' | 'lg'",default:"'md'",description:"Avatar size."},{name:"tone",type:"'neutral' | 'subtle'",default:"'neutral'",description:"Fallback background tone."}],renderPlayground:e=>oe(ne,{name:"Alice Bob",size:e.size,tone:e.tone}),stories:[{id:"sizes",title:"Sizes",description:"xs / sm / md / lg",render:()=>Fe("div",{className:"flex items-end gap-3",children:[oe(ne,{name:"Alice",size:"xs"}),oe(ne,{name:"Bob Chen",size:"sm"}),oe(ne,{name:"Carol Davis",size:"md"}),oe(ne,{name:"David",size:"lg"})]})},{id:"tones",title:"Tones",description:"neutral (default) vs subtle \u2014 applies to initials fallback.",render:()=>Fe("div",{className:"flex items-center gap-4",children:[Fe("div",{className:"text-center",children:[oe(ne,{name:"Neutral",size:"lg",tone:"neutral"}),oe("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"neutral"})]}),Fe("div",{className:"text-center",children:[oe(ne,{name:"Subtle",size:"lg",tone:"subtle"}),oe("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"subtle"})]})]})},{id:"with-image",title:"With Image",render:()=>Fe("div",{className:"flex items-center gap-3",children:[oe(ne,{src:"https://api.dicebear.com/9.x/initials/svg?seed=QQ",name:"Q",size:"md"}),oe(ne,{src:"https://api.dicebear.com/9.x/initials/svg?seed=AB",name:"Alice Bob",size:"lg"})]})},{id:"fallback",title:"Fallback",description:"When image fails to load, initials are shown.",render:()=>Fe("div",{className:"flex items-center gap-3",children:[oe(ne,{src:"/broken-url.jpg",name:"Fallback User",size:"md"}),oe(ne,{name:"No Image",size:"md"}),oe(ne,{size:"md"})]})}]});import{clsx as ga}from"clsx";import{cloneElement as ba,isValidElement as va,useCallback as it,useEffect as gn,useId as ha,useLayoutEffect as ya,useRef as rt,useState as Dt}from"react";import{createPortal as wa}from"react-dom";import{Fragment as Da,jsx as kt,jsxs as yn}from"react/jsx-runtime";var Ze=6,bn=8,st=4,xa={top:"bottom",bottom:"top",left:"right",right:"left"},Na={top:{left:"50%",top:"100%",transform:"translateX(-50%)"},bottom:{left:"50%",top:-Ze,transform:"translateX(-50%) rotate(180deg)"},left:{top:"50%",left:"100%",transform:"translateY(-50%) rotate(-90deg)"},right:{top:"50%",left:-Ze,transform:"translateY(-50%) rotate(90deg)"}};function vn(e,t,n,o){switch(e){case"top":return{top:t.top-n.height-o,left:t.left+t.width/2-n.width/2};case"bottom":return{top:t.bottom+o,left:t.left+t.width/2-n.width/2};case"left":return{top:t.top+t.height/2-n.height/2,left:t.left-n.width-o};case"right":return{top:t.top+t.height/2-n.height/2,left:t.right+o}}}function hn(e,t){let n=window.innerWidth,o=window.innerHeight;return e.top>=0&&e.left>=0&&e.top+t.height<=o&&e.left+t.width<=n}function Sa(e,t,n,o){let a=o?bn+Ze:bn,i=vn(n,e,t,a),r=n,p=i;if(!hn(i,t)){let m=xa[n],g=vn(m,e,t,a);hn(g,t)&&(r=m,p=g)}let c=window.innerWidth,s=window.innerHeight,u=Math.max(st,Math.min(p.left,c-t.width-st)),l=Math.max(st,Math.min(p.top,s-t.height-st));return{placement:r,top:l,left:u}}function Ta(e,t){return n=>{e.current=n;let o=t.props.ref;typeof o=="function"?o(n):o&&typeof o=="object"&&"current"in o&&(o.current=n)}}var Ca={compact:"px-2 py-1 text-[11px] max-w-[200px]",default:"px-3 py-2 text-xs max-w-xs"};function fe({content:e,placement:t="top",density:n="default",showDelay:o=300,hideDelay:a=150,arrow:i=!0,renderArrow:r,className:p,children:c}){let[s,u]=Dt(!1),[l,m]=Dt(null),[g,w]=Dt(t),M=rt(null),v=rt(null),h=rt(void 0),D=rt(void 0),N=ha(),z=it(()=>{clearTimeout(h.current),clearTimeout(D.current)},[]),S=it(()=>{z(),h.current=setTimeout(()=>u(!0),o)},[z,o]),W=it(()=>{z(),D.current=setTimeout(()=>u(!1),a)},[z,a]),G=it(I=>{I.key==="Escape"&&s&&u(!1)},[s]);if(ya(()=>{if(!s||!M.current||!v.current)return;function I(){if(!M.current||!v.current)return;let f=M.current.getBoundingClientRect(),k=v.current.getBoundingClientRect(),Z=Sa(f,k,t,i),Me=document.body.getBoundingClientRect();m({top:Z.top+window.scrollY-Me.top,left:Z.left+window.scrollX-Me.left}),w(Z.placement)}return I(),window.addEventListener("scroll",I,!0),window.addEventListener("resize",I),()=>{window.removeEventListener("scroll",I,!0),window.removeEventListener("resize",I)}},[s,t,i]),gn(()=>{if(s)return document.addEventListener("keydown",G),()=>document.removeEventListener("keydown",G)},[s,G]),gn(()=>z,[z]),!va(c))return c;let q=ba(c,{ref:Ta(M,c),"data-state":s?"open":"closed",onMouseEnter:I=>{S();let f=c.props.onMouseEnter;f?.(I)},onMouseLeave:I=>{W();let f=c.props.onMouseLeave;f?.(I)},onFocus:I=>{S();let f=c.props.onFocus;f?.(I)},onBlur:I=>{W();let f=c.props.onBlur;f?.(I)},"aria-describedby":s?N:void 0});return yn(Da,{children:[q,s&&wa(yn("div",{ref:v,id:N,role:"tooltip","data-state":s?"open":"closed","data-placement":g,"data-density":n,className:ga("ui-tooltip absolute z-[9999] rounded-lg leading-relaxed",Ca[n],"animate-[tooltip-in_0.15s_var(--ease-standard)]",p),style:l?{top:l.top,left:l.left}:{position:"fixed",visibility:"hidden"},onMouseEnter:S,onMouseLeave:W,children:[e,i&&kt("span",{className:"ui-tooltip__arrow absolute",style:Na[g],children:r?r({placement:g}):kt("svg",{width:Ze*2,height:Ze,viewBox:"0 0 12 6",children:kt("path",{d:"M0 0l6 6 6-6z",fill:"currentColor"})})})]}),document.body)]})}import{Settings as ka}from"lucide-react";import{jsx as A,jsxs as Pt}from"react/jsx-runtime";y({group:"feedback",componentId:"tooltip",componentName:"Tooltip",description:"Hover/focus-triggered floating label. Token-driven: --tooltip-bg, --tooltip-border, --tooltip-text, --tooltip-shadow, --tooltip-arrow-color.",props:[{name:"content",type:"ReactNode",description:"Tooltip content shown on hover/focus."},{name:"placement",type:"'top' | 'bottom' | 'left' | 'right'",default:"'top'",description:"Preferred placement. Auto-flips if clipped by viewport."},{name:"density",type:"'compact' | 'default'",default:"'default'",description:"Controls padding and max-width. Compact is tighter for icon labels."},{name:"showDelay",type:"number",default:"300",description:"Delay in ms before showing."},{name:"hideDelay",type:"number",default:"150",description:"Delay in ms before hiding."},{name:"arrow",type:"boolean",default:"true",description:"Whether to show the directional arrow."},{name:"children",type:"ReactElement",description:"Trigger element."}],stories:[{id:"placements",title:"Placements",description:"top / bottom / left / right \u2014 hover each button.",render:()=>Pt("div",{className:"flex flex-wrap items-center justify-center gap-4 py-12",children:[A(fe,{content:"Placed on top",placement:"top",children:A(d,{variant:"secondary",size:"sm",children:"Top"})}),A(fe,{content:"Placed on bottom",placement:"bottom",children:A(d,{variant:"secondary",size:"sm",children:"Bottom"})}),A(fe,{content:"Placed on left",placement:"left",children:A(d,{variant:"secondary",size:"sm",children:"Left"})}),A(fe,{content:"Placed on right",placement:"right",children:A(d,{variant:"secondary",size:"sm",children:"Right"})})]})},{id:"density",title:"Density",description:"compact vs default \u2014 compact is tighter for icon labels.",render:()=>Pt("div",{className:"flex flex-wrap items-center justify-center gap-6 py-12",children:[A(fe,{content:"Compact tooltip",density:"compact",children:A(d,{variant:"secondary",size:"sm",children:"Compact"})}),A(fe,{content:"Default density tooltip with more room for content",density:"default",children:A(d,{variant:"secondary",size:"sm",children:"Default"})})]})},{id:"rich-content",title:"Rich Content",description:"Tooltip supports ReactNode content.",render:()=>A("div",{className:"flex justify-center py-8",children:A(fe,{content:Pt("div",{children:[A("p",{className:"font-medium",children:"Keyboard shortcut"}),A("p",{className:"mt-1 opacity-80",children:"Press Ctrl+S to save your work."})]}),children:A(d,{variant:"secondary",size:"sm",children:"Hover for shortcut"})})})},{id:"on-icon-button",title:"On IconButton",description:"Common pattern: tooltip on icon-only buttons.",render:()=>A("div",{className:"flex justify-center py-8",children:A(fe,{content:"Settings",density:"compact",children:A(Y,{label:"Settings",icon:A(ka,{size:16})})})})},{id:"no-arrow",title:"Without Arrow",render:()=>A("div",{className:"flex justify-center py-8",children:A(fe,{content:"No arrow variant",arrow:!1,children:A(d,{variant:"secondary",size:"sm",children:"Hover me"})})})}]});import{useState as $a}from"react";import{clsx as ke}from"clsx";import{Children as Pa,cloneElement as Ma,createContext as wn,isValidElement as Ia,useCallback as Q,useContext as Mt,useEffect as Re,useId as lt,useLayoutEffect as Ba,useMemo as ct,useRef as De,useState as Je}from"react";import{createPortal as Ra}from"react-dom";import{jsx as ae,jsxs as Cn}from"react/jsx-runtime";var xn=wn(null),It=wn(null);function Bt(e){let t=Mt(xn);if(!t)throw new Error(`${e} must be used within DropdownMenu.`);return t}function Nn(e){let t=Mt(It);if(!t)throw new Error(`${e} must be used within DropdownMenu.Content.`);return t}function Ve(e,t){return n=>{e?.(n),t(n)}}function Sn(...e){return t=>{for(let n of e)n&&(typeof n=="function"?n(t):n.current=t)}}function dt(e){return typeof e=="string"||typeof e=="number"?String(e):Array.isArray(e)?e.map(dt).join(" "):!e||typeof e=="boolean"?"":Ia(e)?dt(e.props.children):""}function La(e){return[...e].sort((t,n)=>{let o=t.ref.current,a=n.ref.current;if(!o||!a)return 0;let i=o.compareDocumentPosition(a);return i&Node.DOCUMENT_POSITION_FOLLOWING?-1:i&Node.DOCUMENT_POSITION_PRECEDING?1:0})}function za(e){let{anchorRect:t,contentRect:n,sideOffset:o,alignOffset:a,collisionPadding:i}=e,r=window.innerWidth,p=window.innerHeight;function c(v,h){let D=0,N=0;return v==="bottom"?(D=t.bottom+o,h==="start"?N=t.left+a:h==="end"?N=t.right-n.width+a:N=t.left+(t.width-n.width)/2+a):v==="top"?(D=t.top-n.height-o,h==="start"?N=t.left+a:h==="end"?N=t.right-n.width+a:N=t.left+(t.width-n.width)/2+a):v==="right"?(N=t.right+o,h==="start"?D=t.top+a:h==="end"?D=t.bottom-n.height+a:D=t.top+(t.height-n.height)/2+a):(N=t.left-n.width-o,h==="start"?D=t.top+a:h==="end"?D=t.bottom-n.height+a:D=t.top+(t.height-n.height)/2+a),{top:D,left:N}}let s={top:"bottom",bottom:"top",left:"right",right:"left"},u=e.side,l=e.align,m=c(u,l);if(m.left<i||m.top<i||m.left+n.width>r-i||m.top+n.height>p-i){let v=c(s[u],l);v.left>=i&&v.top>=i&&v.left+n.width<=r-i&&v.top+n.height<=p-i&&(u=s[u],m=v)}let w=r-n.width-i,M=p-n.height-i;return m.left=Math.max(i,Math.min(m.left,w)),m.top=Math.max(i,Math.min(m.top,M)),{top:m.top,left:m.left,side:u,align:l}}function Tn({open:e,defaultOpen:t=!1,onOpenChange:n,side:o="bottom",align:a="start",sideOffset:i=8,alignOffset:r=0,collisionPadding:p=8,portal:c=!0,contentRole:s="menu",children:u}){let l=Mt(It),[m,g]=Je(t),w=e!==void 0,M=w?e:m,v=De(null),h=De(null),D=De("selected"),N=lt(),z=lt(),S=Q(k=>{w||g(k),n?.(k)},[w,n]),W=Q(()=>{S(!1)},[S]),G=Q(()=>{S(!1),l?.closeTree()},[l,S]),q=Q(()=>{S(!M)},[M,S]),I=Q(()=>{v.current?.focus()},[]),f=ct(()=>({open:M,setOpen:S,toggleOpen:q,triggerRef:v,contentRef:h,side:o,align:a,sideOffset:i,alignOffset:r,collisionPadding:p,portal:c,contentRole:s,triggerId:N,contentId:z,focusIntentRef:D,parentList:l,isSubmenu:!!l,closeSelf:W,closeTree:G,focusTrigger:I}),[M,a,r,W,G,p,s,l,c,S,o,i,q,N,z,I]);return ae(xn.Provider,{value:f,children:u})}function Ea({asChild:e=!1,disabled:t=!1,className:n,children:o}){let{open:a,setOpen:i,toggleOpen:r,triggerRef:p,contentRole:c,triggerId:s,contentId:u,focusIntentRef:l,isSubmenu:m}=Bt("DropdownMenu.Trigger"),g=Pa.only(o),w=g.props??{},M=typeof w.className=="string"?w.className:void 0,v={id:s,"data-state":a?"open":"closed","aria-expanded":a,"aria-haspopup":c,"aria-controls":a?u:void 0,onClick:Ve(w.onClick,h=>{if(t){h.preventDefault();return}l.current="selected",r()}),onKeyDown:Ve(w.onKeyDown,h=>{t||(h.key==="ArrowDown"?(h.preventDefault(),l.current="first",i(!0)):h.key==="ArrowUp"?(h.preventDefault(),l.current="last",i(!0)):!m&&(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),l.current="selected",r()))})};return e?Ma(g,{...v,ref:Sn(p,w.ref),className:ke(n,M),type:g.type==="button"?w.type??"button":w.type}):ae("button",{ref:p,disabled:t,type:"button",className:ke("ui-dropdown-menu__trigger",n),...v,children:g})}function Aa({className:e,children:t,style:n,matchTriggerWidth:o=!1,maxHeight:a=320,...i}){let{open:r,setOpen:p,triggerRef:c,contentRef:s,side:u,align:l,sideOffset:m,alignOffset:g,collisionPadding:w,portal:M,contentRole:v,triggerId:h,contentId:D,focusIntentRef:N,parentList:z,isSubmenu:S,closeSelf:W,closeTree:G,focusTrigger:q}=Bt("DropdownMenu.Content"),I=De([]),[f,k]=Je(null),[Z,Me]=Je(null),[je,Bn]=Je(null),[mt,Rn]=Je(!1),ft=De(""),Le=De(null),zt=Q(x=>(I.current=[...I.current.filter(O=>O.id!==x.id),x],()=>{I.current=I.current.filter(O=>O.id!==x.id)}),[]),le=Q(()=>La(I.current),[]),Et=Q(x=>{N.current=x},[N]);Re(()=>{Rn(!0)},[]);let Ln=ct(()=>({role:v,highlightedId:f,setHighlightedId:k,registerItem:zt,getItems:le,requestFocusIntent:Et,closeTree:G,closeSelf:W,focusTrigger:q,activeSubmenuId:Z,setActiveSubmenuId:Me,contentRef:s}),[Z,W,G,s,v,q,le,f,zt,Et]),ze=Q(()=>{if(!c.current||!s.current)return;let x=c.current.getBoundingClientRect(),O=s.current.getBoundingClientRect();Bn(za({anchorRect:x,contentRect:O,side:u,align:l,sideOffset:m,alignOffset:g,collisionPadding:w}))},[l,g,w,s,u,m,c]);Ba(()=>{if(!(!r||!mt))return ze(),window.addEventListener("resize",ze),window.addEventListener("scroll",ze,!0),()=>{window.removeEventListener("resize",ze),window.removeEventListener("scroll",ze,!0)}},[mt,r,ze]),Re(()=>{if(!r){k(null),Me(null);return}let x=le().filter(C=>!C.disabled);if(x.length===0)return;let O=x[0];N.current==="last"?O=x[x.length-1]:N.current==="selected"&&(O=x.find(C=>C.selected)??x[0]),k(O.id),requestAnimationFrame(()=>{s.current?.focus(),O.ref.current?.scrollIntoView({block:"nearest"})})},[s,N,le,r]),Re(()=>{if(!r)return;function x(O){let C=O.target,X=c.current?.contains(C),ye=s.current?.contains(C);if(!X&&!ye){let ge=z?.contentRef.current?.contains(C);if(S&&ge){W(),z?.setActiveSubmenuId(null);return}G()}}return document.addEventListener("mousedown",x),()=>document.removeEventListener("mousedown",x)},[W,G,s,S,r,z,c]),Re(()=>{if(r)return()=>{Le.current&&clearTimeout(Le.current)}},[r]);let Ne=Q(x=>{if(k(x),!x){Me(null);return}le().find(C=>C.id===x)?.submenu||Me(null)},[le]),gt=Q((x,O="first")=>{let C=le().filter(we=>!we.disabled);if(C.length===0)return;let X=C.findIndex(we=>we.id===f);if(X===-1){Ne(O==="last"?C[C.length-1].id:C[0].id);return}let ye=(X+x+C.length)%C.length,ge=C[ye];Ne(ge.id),ge.ref.current?.scrollIntoView({block:"nearest"})},[le,f,Ne]),At=Q(x=>{let O=x.length===1?x.toLowerCase():"";if(!O)return;Le.current&&clearTimeout(Le.current),ft.current+=O,Le.current=setTimeout(()=>{ft.current="",Le.current=null},350);let C=le().filter(we=>!we.disabled);if(C.length===0)return;let X=C.findIndex(we=>we.id===f),ge=(X>=0?[...C.slice(X+1),...C.slice(0,X+1)]:C).find(we=>we.textValue.toLowerCase().startsWith(ft.current));ge&&(Ne(ge.id),ge.ref.current?.scrollIntoView({block:"nearest"}))},[le,f,Ne]),zn=Q(x=>{let O=le(),C=O.find(X=>X.id===f)??null;switch(x.key){case"ArrowDown":x.preventDefault(),gt(1);break;case"ArrowUp":x.preventDefault(),gt(-1,"last");break;case"Home":x.preventDefault();{let X=O.find(ye=>!ye.disabled);X&&Ne(X.id)}break;case"End":x.preventDefault();{let X=O.filter(ge=>!ge.disabled),ye=X[X.length-1];ye&&Ne(ye.id)}break;case"Enter":case" ":C&&!C.disabled&&(x.preventDefault(),C.click());break;case"ArrowRight":C?.submenu&&(x.preventDefault(),C.openSubmenu?.());break;case"ArrowLeft":S&&(x.preventDefault(),W(),q(),z?.setActiveSubmenuId(null));break;case"Tab":G();break;case"Escape":x.preventDefault(),W(),q(),S&&z?.setActiveSubmenuId(null);break;default:At(x.key)}},[W,G,q,le,At,f,Ne,S,gt,z]);if(!r||!mt)return null;let Ht=ae(It.Provider,{value:Ln,children:ae("div",{ref:s,id:D,role:v,tabIndex:-1,"aria-labelledby":v==="menu"?h:void 0,"data-state":"open","data-side":je?.side??u,"data-align":je?.align??l,className:ke("ui-dropdown-menu__content",S&&"ui-dropdown-menu__content--submenu",e),style:{...n,position:"fixed",top:je?.top??0,left:je?.left??0,maxHeight:a,minWidth:o?c.current?.getBoundingClientRect().width:void 0},onKeyDown:zn,...i,children:t})});return M?Ra(Ht,document.body):Ht}function Ha({className:e,children:t,...n}){return ae("div",{className:ke("ui-dropdown-menu__group",e),...n,children:t})}function Oa({className:e,children:t,...n}){return ae("div",{className:ke("ui-dropdown-menu__label",e),...n,children:t})}function _a({className:e,...t}){return ae("div",{role:"separator",className:ke("ui-dropdown-menu__separator",e),...t})}function Fa({className:e,children:t,inset:n=!1,disabled:o=!1,selected:a=!1,destructive:i=!1,closeOnSelect:r=!0,shortcut:p,indicator:c,onSelect:s,onMouseEnter:u,onClick:l,...m}){let g=lt(),w=De(null),{role:M,highlightedId:v,setHighlightedId:h,registerItem:D,closeTree:N,setActiveSubmenuId:z}=Nn("DropdownMenu.Item"),S=ct(()=>dt(t),[t]),W=v===g,G=Q(()=>{o||(s?.(),r&&N())},[r,N,o,s]);return Re(()=>D({id:g,ref:w,disabled:o,submenu:!1,selected:a,textValue:S,closeOnSelect:r,click:G}),[r,o,G,g,D,a,S]),Cn("button",{ref:w,id:g,type:"button",role:M==="listbox"?"option":"menuitem",tabIndex:-1,disabled:o,"aria-selected":M==="listbox"?a:void 0,"data-highlighted":W||void 0,"data-selected":a||void 0,"data-disabled":o||void 0,"data-destructive":i||void 0,className:ke("ui-dropdown-menu__item",n&&"ui-dropdown-menu__item--inset",e),onMouseEnter:Ve(u,()=>{o||(h(g),z(null))}),onClick:Ve(l,q=>{q.preventDefault(),G()}),...m,children:[ae("span",{className:"ui-dropdown-menu__item-main",children:t}),p?ae("span",{className:"ui-dropdown-menu__shortcut",children:p}):null,a?ae("span",{className:"ui-dropdown-menu__indicator",children:c??"\u2713"}):null]})}function Va(e){return ae(Tn,{side:"right",align:"start",sideOffset:6,...e,contentRole:"menu"})}function Wa({className:e,children:t,inset:n=!1,disabled:o=!1,destructive:a=!1,shortcut:i,onSelect:r,onMouseEnter:p,onClick:c,...s}){let u=lt(),l=De(null),m=Bt("DropdownMenu.SubTrigger"),{highlightedId:g,setHighlightedId:w,registerItem:M,setActiveSubmenuId:v,activeSubmenuId:h}=Nn("DropdownMenu.SubTrigger"),D=ct(()=>dt(t),[t]),N=g===u,z=m.open&&h===u,S=Q(()=>{o||(m.focusIntentRef.current="first",w(u),v(u),m.setOpen(!0))},[o,u,v,w,m]);return Re(()=>M({id:u,ref:l,disabled:o,submenu:!0,selected:!1,textValue:D,closeOnSelect:!1,click:S,openSubmenu:S}),[o,u,S,M,D]),Re(()=>{h!==u&&m.open&&m.setOpen(!1)},[h,u,m]),Cn("button",{ref:Sn(l,m.triggerRef),id:m.triggerId,type:"button",role:"menuitem",tabIndex:-1,"aria-haspopup":"menu","aria-expanded":m.open,"aria-controls":m.open?m.contentId:void 0,"data-highlighted":N||void 0,"data-state":z?"open":"closed","data-disabled":o||void 0,"data-destructive":a||void 0,className:ke("ui-dropdown-menu__item ui-dropdown-menu__sub-trigger",n&&"ui-dropdown-menu__item--inset",e),onMouseEnter:Ve(p,()=>{S()}),onClick:Ve(c,W=>{W.preventDefault(),S(),r?.()}),...s,children:[ae("span",{className:"ui-dropdown-menu__item-main",children:t}),i?ae("span",{className:"ui-dropdown-menu__shortcut",children:i}):null,ae("span",{className:"ui-dropdown-menu__submenu-indicator","aria-hidden":"true",children:"\u203A"})]})}var Ga=Object.assign(Tn,{Trigger:Ea,Content:Aa,Group:Ha,Label:Oa,Item:Fa,Separator:_a,Submenu:Va,SubTrigger:Wa}),E=Ga;import{jsx as V,jsxs as he}from"react/jsx-runtime";function Ua(){return V("div",{className:"flex min-h-52 items-start justify-start pb-48",children:he(E,{align:"start",children:[V(E.Trigger,{asChild:!0,children:V("button",{className:"rounded-lg border border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg)] px-3 py-2 text-sm font-medium text-[var(--ui-text-primary)]",children:"Workspace"})}),he(E.Content,{children:[he(E.Group,{children:[V(E.Item,{children:"Open settings"}),V(E.Item,{children:"Duplicate workspace"})]}),V(E.Separator,{}),he(E.Submenu,{children:[V(E.SubTrigger,{children:"Theme"}),he(E.Content,{children:[V(E.Item,{children:"Light"}),V(E.Item,{selected:!0,children:"Elevated"}),V(E.Item,{children:"Glass"})]})]}),V(E.Separator,{}),V(E.Item,{destructive:!0,children:"Delete workspace"})]})]})})}function Ka(){let[e,t]=$a("gpt-4.1-mini");return V("div",{className:"flex min-h-64 items-end pb-44",children:he(E,{contentRole:"listbox",side:"top",align:"end",children:[V(E.Trigger,{asChild:!0,children:he("button",{className:"inline-flex items-center gap-2 rounded-lg border border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg)] px-3 py-2 text-sm text-[var(--ui-text-primary)]",children:[V("span",{children:e}),V("span",{className:"text-xs text-[var(--ui-text-muted)]",children:"\u25BC"})]})}),he(E.Content,{className:"w-64",children:[he(E.Group,{children:[V(E.Label,{children:"OpenAI"}),["gpt-4.1-mini","gpt-4.1","o4-mini"].map(n=>V(E.Item,{selected:n===e,onSelect:()=>t(n),children:n},n))]}),he(E.Group,{children:[V(E.Label,{children:"Custom"}),["claude-sonnet-4","gemini-2.5-pro"].map(n=>V(E.Item,{selected:n===e,onSelect:()=>t(n),children:n},n))]})]})]})})}y({group:"actions",componentId:"dropdown-menu",componentName:"DropdownMenu",description:"Industrial dropdown primitive for action menus, grouped pickers, and nested submenus.",props:[{name:"open",type:"boolean",description:"Controlled open state."},{name:"defaultOpen",type:"boolean",description:"Initial open state for uncontrolled usage."},{name:"onOpenChange",type:"(open: boolean) => void",description:"Open-state change callback."},{name:"side",type:"'top' | 'bottom' | 'left' | 'right'",default:"'bottom'",description:"Preferred content side."},{name:"align",type:"'start' | 'center' | 'end'",default:"'start'",description:"Alignment relative to trigger."},{name:"contentRole",type:"'menu' | 'listbox'",default:"'menu'",description:"Semantic role for action menus vs pickers."}],stories:[{id:"actions",title:"Action Menu",description:"Standard action menu with submenu and destructive item.",render:()=>V(Ua,{})},{id:"picker",title:"Grouped Picker",description:"Model-picker style listbox with selected state.",render:()=>V(Ka,{})}]});import{useState as Ya}from"react";import{clsx as Dn}from"clsx";import{Fragment as qa,jsx as kn,jsxs as Xa}from"react/jsx-runtime";function Rt({as:e="aside",open:t,children:n,side:o="right",position:a="fixed",showBackdrop:i=!0,onClose:r,closeLabel:p="\u5173\u95ED\u62BD\u5C49",backdropClassName:c,className:s,...u}){let l=o==="left"?"-translate-x-full":"translate-x-full",m=o==="left"?"left-0 top-0":"right-0 top-0",g=a==="fixed"?"fixed":"absolute";return Xa(qa,{children:[i&&t&&r&&kn("button",{type:"button","aria-label":p,"data-state":"open",className:Dn("ui-drawer-backdrop inset-0 z-10",g,c),onClick:r}),kn(e,{"aria-hidden":!t,"data-state":t?"open":"closed","data-side":o,className:Dn("ui-drawer",g,m,"z-20 flex max-w-full transform flex-col transition-transform duration-200 ease-in-out",t?"pointer-events-auto visible translate-x-0":`pointer-events-none invisible ${l}`,s),...u,children:n})]})}import{jsx as U,jsxs as Pe}from"react/jsx-runtime";function Lt({side:e="right",showBackdrop:t=!0}){let[n,o]=Ya(!1);return Pe("div",{className:"relative h-[26rem] overflow-hidden rounded-xl border border-[var(--color-surface-border)] bg-[var(--color-surface-canvas)]",children:[U("div",{className:"flex h-full items-center justify-center",children:U(d,{variant:"primary",size:"sm",onClick:()=>o(!0),children:"Open Drawer"})}),U(Rt,{open:n,onClose:()=>o(!1),side:e,position:"absolute",showBackdrop:t,"aria-label":"Post settings",className:"h-full w-80 max-w-full border-l",children:Pe("div",{className:"flex h-full flex-col",children:[Pe("div",{className:"flex items-center justify-between border-b border-[var(--panel-section-border,var(--color-surface-border))] px-4 py-3",children:[U("span",{className:"text-sm font-semibold text-n800",children:"Post Settings"}),U(d,{variant:"ghost",size:"sm",onClick:()=>o(!1),children:"Close"})]}),Pe("div",{className:"flex-1 space-y-3 overflow-y-auto p-4",children:[U("p",{className:"text-sm text-n600",children:"Drawer now uses --drawer-surface, --drawer-border, and --drawer-shadow tokens from CSS."}),U("div",{className:"rounded-lg border border-[var(--color-surface-border)] bg-[var(--color-surface-base)] p-3 text-sm text-n700",children:"Forms, filters, or settings can go here."})]}),Pe("div",{className:"flex justify-end gap-2 border-t border-[var(--panel-section-border,var(--color-surface-border))] px-4 py-3",children:[U(d,{variant:"ghost",size:"sm",onClick:()=>o(!1),children:"Cancel"}),U(d,{variant:"primary",size:"sm",onClick:()=>o(!1),children:"Save"})]})]})})]})}y({group:"layout",componentId:"drawer",componentName:"Drawer",description:"Sliding overlay container for left/right drawers with optional backdrop. Token-driven: --drawer-surface, --drawer-border, --drawer-shadow, --drawer-backdrop.",props:[{name:"open",type:"boolean",default:"false",description:"Controls whether the drawer is visible."},{name:"side",type:"'left' | 'right'",default:"'right'",description:"Slide-in edge."},{name:"position",type:"'fixed' | 'absolute'",default:"'fixed'",description:"Positioning mode for app shell or local preview containers."},{name:"showBackdrop",type:"boolean",default:"true",description:"Whether to render a clickable backdrop when open."},{name:"onClose",type:"() => void",description:"Called when the backdrop is clicked."}],stories:[{id:"right",title:"Right Drawer",description:"Standard right-side drawer with backdrop.",source:`<Drawer
73
+ open={open}
74
+ onClose={() => setOpen(false)}
75
+ side="right"
76
+ position="absolute"
77
+ aria-label="Post settings"
78
+ className="h-full w-80 border-l"
79
+ >
80
+ <div className="flex h-full flex-col">
81
+ <div className="border-b px-4 py-3">Header</div>
82
+ <div className="flex-1 overflow-y-auto p-4">Body</div>
83
+ <div className="border-t px-4 py-3">Footer</div>
84
+ </div>
85
+ </Drawer>`,render:()=>U(Lt,{side:"right"})},{id:"left",title:"Left Drawer",description:"Left-side variant for navigation or contextual tools.",render:()=>U(Lt,{side:"left"})},{id:"without-backdrop",title:"Without Backdrop",description:"Useful inside bounded shells where overlay dimming is not desired.",render:()=>U(Lt,{side:"right",showBackdrop:!1})},{id:"floating-hierarchy",title:"Floating Hierarchy",description:"Drawers belong to the floating layer: backdrop separates context, surface defines body, shadow lifts the panel above the page.",render:()=>U("div",{className:"rounded-xl bg-[var(--color-surface-subtle)] p-5",children:Pe("div",{className:"relative h-[20rem] overflow-hidden rounded-xl border border-[var(--color-surface-border)] bg-[var(--color-surface-canvas)]",children:[U("div",{className:"absolute inset-0 bg-[var(--color-overlay-strong)]"}),Pe("div",{className:"ui-drawer absolute inset-y-0 right-0 flex w-80 max-w-full flex-col border-l",children:[U("div",{className:"border-b border-[var(--drawer-border)] px-4 py-3 text-sm font-semibold text-[var(--color-n800)]",children:"Drawer Surface"}),Pe("div",{className:"flex-1 space-y-3 p-4 text-sm text-[var(--color-n600)]",children:[U("p",{children:"Backdrop handles separation from the page."}),U("p",{children:"Surface defines the drawer body."}),U("p",{children:"Shadow confirms it is a floating layer, not a static card."})]})]})]})})}]});import{clsx as ut}from"clsx";import{jsx as pt}from"react/jsx-runtime";function Qa(e){switch(e){case"none":return"";case"sm":return"p-4";case"lg":return"p-6";default:return"p-5"}}function pe({as:e="section",variant:t="default",padding:n="none",className:o,children:a,...i}){return pt(e,{"data-variant":t,className:ut("ui-panel rounded-lg border",Qa(n),o),...i,children:a})}function Pn({className:e,children:t,...n}){return pt("div",{className:ut("ui-panel-header border-b px-6 py-5",e),...n,children:t})}function Mn({className:e,children:t,...n}){return pt("div",{className:ut("px-6 py-5",e),...n,children:t})}function In({className:e,children:t,...n}){return pt("div",{className:ut("ui-panel-footer border-t px-6 py-4",e),...n,children:t})}import{jsx as P,jsxs as me}from"react/jsx-runtime";y({group:"layout",componentId:"panel",componentName:"Panel",description:"Container card driven by surface hierarchy and structured sections (header/body/footer), not by blanket shadow elevation.",props:[{name:"as",type:"ElementType",default:"'section'",description:"Root element tag."},{name:"variant",type:"'default' | 'subtle' | 'raised'",default:"'default'",description:"Surface hierarchy variant. `raised` includes shadow."},{name:"padding",type:"'none' | 'sm' | 'md' | 'lg'",default:"'none'",description:"Inner padding size."}],renderPlayground:e=>P(pe,{variant:e.variant,padding:e.padding,children:P("p",{className:"text-sm",children:"Panel content"})}),stories:[{id:"variants",title:"Variants",description:"default / subtle / raised \u2014 semantic feedback should use StatusNotice instead of overloading panel surface variants.",render:()=>me("div",{className:"grid gap-4 sm:grid-cols-3",children:[me(pe,{variant:"default",padding:"md",children:[P("p",{className:"text-sm font-medium",children:"Default"}),P("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Standard container."})]}),me(pe,{variant:"subtle",padding:"md",children:[P("p",{className:"text-sm font-medium",children:"Subtle"}),P("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Reduced emphasis."})]}),me(pe,{variant:"raised",padding:"md",children:[P("p",{className:"text-sm font-medium",children:"Raised"}),P("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Elevated surface with shadow."})]})]})},{id:"with-sections",title:"With Sections",description:"PanelHeader + PanelBody + PanelFooter",source:`<Panel variant="default">
86
+ <PanelHeader>
87
+ <h3>Panel Title</h3>
88
+ </PanelHeader>
89
+ <PanelBody>
90
+ <p>Body content here.</p>
91
+ </PanelBody>
92
+ <PanelFooter>
93
+ <Button variant="ghost" size="sm">Cancel</Button>
94
+ <Button variant="primary" size="sm">Confirm</Button>
95
+ </PanelFooter>
96
+ </Panel>`,render:()=>me(pe,{variant:"default",className:"max-w-md",children:[P(Pn,{children:P("h3",{className:"text-sm font-semibold",children:"Panel Title"})}),P(Mn,{children:P("p",{className:"text-sm text-[var(--color-n600)]",children:"This is the body content of the panel. It can contain any elements."})}),P(In,{children:me("div",{className:"flex justify-end gap-2",children:[P(d,{variant:"ghost",size:"sm",children:"Cancel"}),P(d,{variant:"primary",size:"sm",children:"Confirm"})]})})]})},{id:"on-surfaces",title:"On Different Surfaces",description:"Verifies panel contrast against canvas, subtle, and inset backgrounds.",render:()=>P("div",{className:"grid gap-4 sm:grid-cols-3",children:[{label:"Canvas",bg:"var(--color-surface-canvas)"},{label:"Subtle",bg:"var(--color-surface-subtle)"},{label:"Inset",bg:"var(--color-surface-inset)"}].map(({label:e,bg:t})=>me("div",{className:"rounded-lg p-4",style:{backgroundColor:t},children:[P("p",{className:"mb-2 text-[11px] font-medium text-[var(--color-n500)]",children:e}),P(pe,{variant:"default",padding:"md",children:P("p",{className:"text-sm",children:"Default panel"})})]},e))})},{id:"surface-not-shadow",title:"Surface, Not Shadow",description:"Dashboard-style panels should build depth with surface tokens first. The panel itself stays border-led instead of floating like a popover.",render:()=>P("div",{className:"rounded-xl bg-[var(--color-surface-subtle)] p-5",children:me("div",{className:"grid gap-4 lg:grid-cols-3",children:[me(pe,{variant:"default",padding:"md",children:[P("p",{className:"text-sm font-medium",children:"Default"}),P("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Primary reading card."})]}),me(pe,{variant:"subtle",padding:"md",children:[P("p",{className:"text-sm font-medium",children:"Subtle"}),P("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Secondary summary area."})]}),me(pe,{variant:"raised",padding:"md",children:[P("p",{className:"text-sm font-medium",children:"Raised"}),P("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"A slightly lifted surface with --panel-shadow."})]})]})})},{id:"padding",title:"Padding Sizes",description:"none / sm / md / lg",render:()=>P("div",{className:"space-y-3",children:["none","sm","md","lg"].map(e=>P(pe,{variant:"default",padding:e,children:me("span",{className:"text-xs",children:["padding=","\u201C",e,"\u201D"]})},e))})}]});export{jn as getGroupedStories,Jn as getStoriesByGroupAndComponent,eo as groupLabels,to as groupOrder,y as registerStories,Zn as storybookStoryPaths};
@@ -0,0 +1,32 @@
1
+ declare const semanticTokenKeys: readonly ["--ui-surface-bg", "--ui-surface-bg-subtle", "--ui-surface-bg-raised", "--ui-surface-bg-inset", "--ui-surface-border", "--ui-surface-border-strong", "--ui-surface-shadow", "--ui-surface-shadow-strong", "--ui-surface-blur", "--ui-text-primary", "--ui-text-secondary", "--ui-text-muted", "--ui-text-on-accent", "--ui-accent-bg", "--ui-accent-bg-hover", "--ui-accent-text", "--ui-success-bg", "--ui-success-border", "--ui-success-text", "--ui-warning-bg", "--ui-warning-border", "--ui-warning-text", "--ui-danger-bg", "--ui-danger-border", "--ui-danger-text", "--ui-info-bg", "--ui-info-border", "--ui-info-text", "--ui-control-radius-sm", "--ui-control-radius-md", "--ui-control-radius-lg", "--ui-control-border-width", "--ui-control-focus-ring", "--ui-control-focus-ring-offset", "--ui-motion-duration-fast", "--ui-motion-duration-default", "--ui-motion-ease-standard", "--ui-density-compact", "--ui-density-default", "--ui-density-comfortable"];
2
+ type SemanticTokenKey = (typeof semanticTokenKeys)[number];
3
+ declare const tokenGroups: readonly [{
4
+ readonly id: "surface";
5
+ readonly label: "Surface";
6
+ readonly tokens: readonly ["--ui-surface-bg", "--ui-surface-bg-subtle", "--ui-surface-bg-raised", "--ui-surface-bg-inset", "--ui-surface-border", "--ui-surface-border-strong", "--ui-surface-shadow", "--ui-surface-shadow-strong", "--ui-surface-blur"];
7
+ }, {
8
+ readonly id: "text";
9
+ readonly label: "Text";
10
+ readonly tokens: readonly ["--ui-text-primary", "--ui-text-secondary", "--ui-text-muted", "--ui-text-on-accent"];
11
+ }, {
12
+ readonly id: "accent";
13
+ readonly label: "Accent";
14
+ readonly tokens: readonly ["--ui-accent-bg", "--ui-accent-bg-hover", "--ui-accent-text"];
15
+ }, {
16
+ readonly id: "feedback";
17
+ readonly label: "Feedback";
18
+ readonly tokens: readonly ["--ui-success-bg", "--ui-success-border", "--ui-success-text", "--ui-warning-bg", "--ui-warning-border", "--ui-warning-text", "--ui-danger-bg", "--ui-danger-border", "--ui-danger-text", "--ui-info-bg", "--ui-info-border", "--ui-info-text"];
19
+ }, {
20
+ readonly id: "control";
21
+ readonly label: "Control";
22
+ readonly tokens: readonly ["--ui-control-radius-sm", "--ui-control-radius-md", "--ui-control-radius-lg", "--ui-control-border-width", "--ui-control-focus-ring", "--ui-control-focus-ring-offset"];
23
+ }, {
24
+ readonly id: "motion-density";
25
+ readonly label: "Motion & Density";
26
+ readonly tokens: readonly ["--ui-motion-duration-fast", "--ui-motion-duration-default", "--ui-motion-ease-standard", "--ui-density-compact", "--ui-density-default", "--ui-density-comfortable"];
27
+ }];
28
+ declare const presetNames: readonly ["default", "flat", "elevated", "glass"];
29
+ type OwoUiPresetName = (typeof presetNames)[number];
30
+ declare const tokenDescriptions: Record<SemanticTokenKey, string>;
31
+
32
+ export { type OwoUiPresetName, type SemanticTokenKey, presetNames, semanticTokenKeys, tokenDescriptions, tokenGroups };
@@ -0,0 +1 @@
1
+ var e=["--ui-surface-bg","--ui-surface-bg-subtle","--ui-surface-bg-raised","--ui-surface-bg-inset","--ui-surface-border","--ui-surface-border-strong","--ui-surface-shadow","--ui-surface-shadow-strong","--ui-surface-blur","--ui-text-primary","--ui-text-secondary","--ui-text-muted","--ui-text-on-accent","--ui-accent-bg","--ui-accent-bg-hover","--ui-accent-text","--ui-success-bg","--ui-success-border","--ui-success-text","--ui-warning-bg","--ui-warning-border","--ui-warning-text","--ui-danger-bg","--ui-danger-border","--ui-danger-text","--ui-info-bg","--ui-info-border","--ui-info-text","--ui-control-radius-sm","--ui-control-radius-md","--ui-control-radius-lg","--ui-control-border-width","--ui-control-focus-ring","--ui-control-focus-ring-offset","--ui-motion-duration-fast","--ui-motion-duration-default","--ui-motion-ease-standard","--ui-density-compact","--ui-density-default","--ui-density-comfortable"],r=[{id:"surface",label:"Surface",tokens:["--ui-surface-bg","--ui-surface-bg-subtle","--ui-surface-bg-raised","--ui-surface-bg-inset","--ui-surface-border","--ui-surface-border-strong","--ui-surface-shadow","--ui-surface-shadow-strong","--ui-surface-blur"]},{id:"text",label:"Text",tokens:["--ui-text-primary","--ui-text-secondary","--ui-text-muted","--ui-text-on-accent"]},{id:"accent",label:"Accent",tokens:["--ui-accent-bg","--ui-accent-bg-hover","--ui-accent-text"]},{id:"feedback",label:"Feedback",tokens:["--ui-success-bg","--ui-success-border","--ui-success-text","--ui-warning-bg","--ui-warning-border","--ui-warning-text","--ui-danger-bg","--ui-danger-border","--ui-danger-text","--ui-info-bg","--ui-info-border","--ui-info-text"]},{id:"control",label:"Control",tokens:["--ui-control-radius-sm","--ui-control-radius-md","--ui-control-radius-lg","--ui-control-border-width","--ui-control-focus-ring","--ui-control-focus-ring-offset"]},{id:"motion-density",label:"Motion & Density",tokens:["--ui-motion-duration-fast","--ui-motion-duration-default","--ui-motion-ease-standard","--ui-density-compact","--ui-density-default","--ui-density-comfortable"]}],o=["default","flat","elevated","glass"],t={"--ui-surface-bg":"Default component surface background.","--ui-surface-bg-subtle":"Lower-emphasis surface background.","--ui-surface-bg-raised":"Raised surface background for floating or elevated panels.","--ui-surface-bg-inset":"Inset surface background for inputs and compact controls.","--ui-surface-border":"Default component border color.","--ui-surface-border-strong":"Higher-emphasis border or focus-adjacent border color.","--ui-surface-shadow":"Default surface shadow for raised UI.","--ui-surface-shadow-strong":"Higher-emphasis shadow for popovers and overlays.","--ui-surface-blur":"Backdrop blur amount for translucent surface styles.","--ui-text-primary":"Primary readable foreground text color.","--ui-text-secondary":"Secondary readable foreground text color.","--ui-text-muted":"Muted or tertiary text color.","--ui-text-on-accent":"Readable text color when placed on accent surfaces.","--ui-accent-bg":"Primary accent background color.","--ui-accent-bg-hover":"Primary accent hover color.","--ui-accent-text":"Readable text color used on accent backgrounds.","--ui-success-bg":"Success background treatment.","--ui-success-border":"Success border treatment.","--ui-success-text":"Success foreground text color.","--ui-warning-bg":"Warning background treatment.","--ui-warning-border":"Warning border treatment.","--ui-warning-text":"Warning foreground text color.","--ui-danger-bg":"Danger background treatment.","--ui-danger-border":"Danger border treatment.","--ui-danger-text":"Danger foreground text color.","--ui-info-bg":"Info background treatment.","--ui-info-border":"Info border treatment.","--ui-info-text":"Info foreground text color.","--ui-control-radius-sm":"Small control radius.","--ui-control-radius-md":"Default control radius.","--ui-control-radius-lg":"Large control radius.","--ui-control-border-width":"Default border width for controls.","--ui-control-focus-ring":"Focus ring color.","--ui-control-focus-ring-offset":"Focus ring offset base color.","--ui-motion-duration-fast":"Fast motion duration.","--ui-motion-duration-default":"Default motion duration.","--ui-motion-ease-standard":"Default motion easing curve.","--ui-density-compact":"Compact density scale.","--ui-density-default":"Default density scale.","--ui-density-comfortable":"Comfortable density scale."};export{o as presetNames,e as semanticTokenKeys,t as tokenDescriptions,r as tokenGroups};
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@owodesign/owoui",
3
+ "version": "0.1.0",
4
+ "description": "Reusable React UI foundation components and theme presets.",
5
+ "type": "module",
6
+ "main": "./dist/index.min.js",
7
+ "module": "./dist/index.min.js",
8
+ "types": "./dist/index.d.ts",
9
+ "license": "MIT",
10
+ "keywords": [
11
+ "react",
12
+ "ui",
13
+ "design-system",
14
+ "owoui",
15
+ "@owodesign/owoui",
16
+ "components"
17
+ ],
18
+ "engines": {
19
+ "node": ">=20"
20
+ },
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.min.js"
25
+ },
26
+ "./tokens": {
27
+ "types": "./dist/tokens.d.ts",
28
+ "import": "./dist/tokens.min.js"
29
+ },
30
+ "./tokens.css": "./src/tokens.css",
31
+ "./storybook": {
32
+ "types": "./dist/storybook/index.d.ts",
33
+ "import": "./dist/storybook/index.min.js"
34
+ },
35
+ "./storybook/catalog": {
36
+ "types": "./dist/storybook/catalog.d.ts",
37
+ "import": "./dist/storybook/catalog.js"
38
+ },
39
+ "./storybook/catalog.json": "./dist/storybook/catalog.json",
40
+ "./style.css": "./src/style.css",
41
+ "./flat.css": "./src/flat.css",
42
+ "./elevated.css": "./src/elevated.css",
43
+ "./glass.css": "./src/glass.css"
44
+ },
45
+ "files": [
46
+ "dist",
47
+ "src/style.css",
48
+ "src/tokens.css",
49
+ "src/flat.css",
50
+ "src/elevated.css",
51
+ "src/glass.css",
52
+ "src/styles"
53
+ ],
54
+ "sideEffects": [
55
+ "./src/style.css",
56
+ "./src/tokens.css",
57
+ "./src/flat.css",
58
+ "./src/elevated.css",
59
+ "./src/glass.css",
60
+ "./src/styles/**/*.css",
61
+ "./src/storybook/**/*.ts",
62
+ "./src/storybook/**/*.tsx"
63
+ ],
64
+ "scripts": {
65
+ "build": "npm run build:lib && npm run build:storybook && npm run build:storybook:catalog",
66
+ "build:lib": "tsup",
67
+ "build:storybook": "tsup --config tsup.storybook.config.ts",
68
+ "build:storybook:catalog": "node scripts/build-storybook-catalog.mjs",
69
+ "typecheck": "tsc --noEmit -p tsconfig.json",
70
+ "consumer:smoke": "node examples/consumer-smoke.mjs",
71
+ "pack:inspect": "npm_config_cache=/tmp/owoui-npm-cache npm pack --dry-run --json .",
72
+ "release:check": "npm run build && npm run typecheck && npm run consumer:smoke && npm run pack:inspect"
73
+ },
74
+ "publishConfig": {
75
+ "access": "public"
76
+ },
77
+ "dependencies": {
78
+ "clsx": "^2.1.1",
79
+ "lucide-react": "^0.576.0"
80
+ },
81
+ "peerDependencies": {
82
+ "react": "^18.0.0 || ^19.0.0",
83
+ "react-dom": "^18.0.0 || ^19.0.0"
84
+ },
85
+ "devDependencies": {
86
+ "@types/react": "^19.0.0",
87
+ "@types/react-dom": "^19.0.0",
88
+ "tailwindcss": "^4.2.1",
89
+ "tsup": "^8.5.1"
90
+ }
91
+ }
@@ -0,0 +1,20 @@
1
+ @import "./style.css";
2
+
3
+ :root,
4
+ .owoui-theme-elevated {
5
+ --color-surface-canvas: #f4f7fb;
6
+ --color-surface-base: rgba(255, 255, 255, 0.88);
7
+ --color-surface-subtle: rgba(248, 250, 252, 0.94);
8
+ --color-surface-raised: rgba(255, 255, 255, 0.96);
9
+ --color-surface-inset: #eef2f7;
10
+ --color-surface-border: rgba(148, 163, 184, 0.22);
11
+ --color-surface-ring: rgba(59, 130, 246, 0.28);
12
+ --color-overlay-soft: rgba(240, 244, 250, 0.62);
13
+ --color-overlay-strong: rgba(15, 23, 42, 0.24);
14
+ --shadow-raised: 0 16px 40px rgba(15, 23, 42, 0.14);
15
+ --shadow-popover: 0 28px 60px rgba(15, 23, 42, 0.18);
16
+ --drawer-panel-shadow: 0 28px 60px rgba(15, 23, 42, 0.18);
17
+ --select-dropdown-shadow: 0 22px 50px rgba(15, 23, 42, 0.16);
18
+ --tooltip-shadow: 0 14px 36px rgba(15, 23, 42, 0.14);
19
+ --theme-picker-shadow: 0 24px 56px rgba(15, 23, 42, 0.16);
20
+ }
package/src/flat.css ADDED
@@ -0,0 +1 @@
1
+ @import "./style.css";
package/src/glass.css ADDED
@@ -0,0 +1,17 @@
1
+ @import "./style.css";
2
+
3
+ :root,
4
+ .owoui-theme-glass {
5
+ --color-surface-canvas: linear-gradient(180deg, #edf3ff 0%, #f7fbff 42%, #f2f7fb 100%);
6
+ --color-surface-base: rgba(255, 255, 255, 0.62);
7
+ --color-surface-subtle: rgba(255, 255, 255, 0.48);
8
+ --color-surface-raised: rgba(255, 255, 255, 0.72);
9
+ --color-surface-inset: rgba(236, 243, 251, 0.82);
10
+ --color-surface-border: rgba(255, 255, 255, 0.42);
11
+ --color-surface-ring: rgba(148, 163, 184, 0.28);
12
+ --color-overlay-soft: rgba(240, 246, 255, 0.48);
13
+ --color-overlay-strong: rgba(15, 23, 42, 0.18);
14
+ --shadow-raised: 0 16px 44px rgba(15, 23, 42, 0.10);
15
+ --shadow-popover: 0 24px 64px rgba(15, 23, 42, 0.14);
16
+ --ui-surface-blur: 18px;
17
+ }
package/src/style.css ADDED
@@ -0,0 +1,20 @@
1
+ @import "tailwindcss";
2
+ @import "./styles/tokens.css";
3
+ @import "./styles/ui/avatar.css";
4
+ @import "./styles/ui/badge.css";
5
+ @import "./styles/ui/button.css";
6
+ @import "./styles/ui/dialog.css";
7
+ @import "./styles/ui/dropdown-menu.css";
8
+ @import "./styles/ui/drawer.css";
9
+ @import "./styles/ui/empty-state.css";
10
+ @import "./styles/ui/field.css";
11
+ @import "./styles/ui/icon-button.css";
12
+ @import "./styles/ui/input.css";
13
+ @import "./styles/ui/panel.css";
14
+ @import "./styles/ui/segmented-control.css";
15
+ @import "./styles/ui/select.css";
16
+ @import "./styles/ui/skeleton.css";
17
+ @import "./styles/ui/status-notice.css";
18
+ @import "./styles/ui/switch.css";
19
+ @import "./styles/ui/toast.css";
20
+ @import "./styles/ui/tooltip.css";