@owodesign/owoui 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -5
- package/dist/index.d.ts +61 -3
- package/dist/index.min.js +1 -1
- package/dist/storybook/catalog.js +31 -1
- package/dist/storybook/catalog.json +31 -1
- package/dist/storybook/index.min.js +9 -8
- package/dist/storybook-static/app.css +4100 -0
- package/dist/storybook-static/assets/main.js +97 -0
- package/dist/storybook-static/index.html +14 -0
- package/dist/tokens.d.ts +4 -2
- package/dist/tokens.min.js +1 -1
- package/package.json +24 -14
- package/src/preset-default.css +27 -0
- package/src/preset-elevated.css +27 -0
- package/src/preset-flat.css +27 -0
- package/src/preset-glass.css +27 -0
- package/src/style.css +3 -0
- package/src/styles/tokens.css +132 -73
- package/src/styles/ui/collapsible.css +13 -0
- package/src/styles/ui/tabs.css +33 -0
- package/src/styles/ui/textarea.css +8 -0
- package/src/theme-dark.css +87 -0
- package/src/theme-light.css +41 -0
- package/src/dark.css +0 -70
- package/src/elevated.css +0 -20
- package/src/flat.css +0 -1
- package/src/glass.css +0 -17
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import{StrictMode as yi}from"react";import{createRoot as xi}from"react-dom/client";import{Plus as fn,ArrowRight as gn}from"lucide-react";import{clsx as zo}from"clsx";import{clsx as To}from"clsx";import{jsx as D,jsxs as Ae}from"react/jsx-runtime";var Co={xs:12,sm:14,md:16,lg:24};function So({px:e}){let n=Math.PI*2*9;return Ae("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",children:[D("circle",{cx:"12",cy:"12",r:9,stroke:"currentColor",strokeWidth:"3",opacity:"0.2"}),D("circle",{cx:"12",cy:"12",r:9,stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeDasharray:`${n*.28} ${n*.72}`})]})}function ko({px:e}){return Ae("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",children:[D("path",{d:"M12 2a10 10 0 0 1 10 10",opacity:"0.9"}),D("path",{d:"M12 2a10 10 0 0 0-7.07 2.93",opacity:"0.2"}),D("path",{d:"M4.93 4.93A10 10 0 0 0 2 12",opacity:"0.2"}),D("path",{d:"M2 12a10 10 0 0 0 2.93 7.07",opacity:"0.2"}),D("path",{d:"M4.93 19.07A10 10 0 0 0 12 22",opacity:"0.2"}),D("path",{d:"M12 22a10 10 0 0 0 7.07-2.93",opacity:"0.2"}),D("path",{d:"M19.07 19.07A10 10 0 0 0 22 12",opacity:"0.2"})]})}function Do({px:e}){return D("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,r=.15+n/8*.85;return D("circle",{cx:"12",cy:"3.5",r:"1.8",fill:"currentColor",opacity:r,transform:`rotate(${o} 12 12)`},n)})})}function Po({px:e}){return D("svg",{width:e,height:e,viewBox:"0 0 24 24",children:[0,1,2,3].map(t=>Ae("rect",{x:3+t*5.5,y:"4",width:"3",height:"16",rx:"1.5",fill:"currentColor",opacity:"0.3",children:[D("animate",{attributeName:"opacity",values:"0.3;1;0.3",dur:"1s",begin:`${t*.15}s`,repeatCount:"indefinite"}),D("animate",{attributeName:"height",values:"16;8;16",dur:"1s",begin:`${t*.15}s`,repeatCount:"indefinite"}),D("animate",{attributeName:"y",values:"4;8;4",dur:"1s",begin:`${t*.15}s`,repeatCount:"indefinite"})]},t))})}function Io({px:e}){let t=e*.14,n=e*.33,o=e/2-n,r=e/2,a=e/2+n,i=e/2;return D("svg",{width:e,height:e,viewBox:`0 0 ${e} ${e}`,children:[o,r,a].map((c,d)=>Ae("circle",{cx:c,cy:i,r:t,fill:"currentColor",opacity:"0.4",children:[D("animate",{attributeName:"cy",values:`${i};${i-e*.25};${i}`,dur:"0.6s",begin:`${d*.12}s`,repeatCount:"indefinite",calcMode:"spline",keySplines:"0.4 0 0.2 1;0.4 0 0.2 1"}),D("animate",{attributeName:"opacity",values:"0.4;1;0.4",dur:"0.6s",begin:`${d*.12}s`,repeatCount:"indefinite"})]},d))})}function Mo({px:e}){return Ae("svg",{width:e,height:e,viewBox:"0 0 24 24",children:[Ae("circle",{cx:"12",cy:"12",r:"0",fill:"currentColor",opacity:"0",children:[D("animate",{attributeName:"r",values:"4;10;4",dur:"1.2s",repeatCount:"indefinite"}),D("animate",{attributeName:"opacity",values:"0.8;0.1;0.8",dur:"1.2s",repeatCount:"indefinite"})]}),D("circle",{cx:"12",cy:"12",r:"3.5",fill:"currentColor",opacity:"0.7"})]})}function Ro({px:e}){return Ae("svg",{width:e,height:e,viewBox:"0 0 24 24",children:[D("circle",{cx:"12",cy:"12",r:"8",stroke:"currentColor",strokeWidth:"1.5",fill:"none",opacity:"0.15"}),D("circle",{cx:"12",cy:"4",r:"2.2",fill:"currentColor",children:D("animateTransform",{attributeName:"transform",type:"rotate",from:"0 12 12",to:"360 12 12",dur:"0.9s",repeatCount:"indefinite"})}),D("circle",{cx:"12",cy:"20",r:"1.5",fill:"currentColor",opacity:"0.5",children:D("animateTransform",{attributeName:"transform",type:"rotate",from:"0 12 12",to:"-360 12 12",dur:"0.9s",repeatCount:"indefinite"})})]})}function Lo({px:e}){let t=e*.14,n=e*.33,o=e/2-n,r=e/2,a=e/2+n,i=e/2;return D("svg",{width:e,height:e,viewBox:`0 0 ${e} ${e}`,children:[o,r,a].map((c,d)=>D("circle",{cx:c,cy:i,r:t,fill:"currentColor",opacity:"0.25",children:D("animate",{attributeName:"opacity",values:"0.25;1;0.25",dur:"0.9s",begin:`${d*.2}s`,repeatCount:"indefinite"})},d))})}var Bo={ring:So,arc:ko,dots:Do,bars:Po,bounce:Io,pulse:Mo,orbit:Ro,flow:Lo},Eo=new Set(["ring","arc","dots"]);function le({variant:e="ring",size:t="md",className:n,label:o}){let r=typeof t=="number"?t:Co[t],a=Bo[e];return D("span",{"aria-hidden":!o,"aria-label":o,role:o?"img":void 0,className:To("ui-spinner inline-flex",Eo.has(e)&&"motion-safe:animate-spin",n),children:D(a,{px:r})})}import{Fragment as Ho,jsx as He,jsxs as Oo}from"react/jsx-runtime";function Ao({variant:e="secondary",size:t="md",loading:n=!1,className:o}){return zo("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 f(e){let{variant:t="secondary",size:n="md",loading:o=!1,leadingIcon:r,trailingIcon:a,className:i,children:c,...d}=e,s=Oo(Ho,{children:[o?He("span",{className:"shrink-0",children:He(le,{size:n==="sm"?"sm":"md"})}):r?He("span",{className:"shrink-0",children:r}):null,He("span",{children:c}),!o&&a?He("span",{className:"shrink-0",children:a}):null]}),l=Ao({variant:t,size:n,loading:o,className:i});if("href"in e&&e.href){let{href:p,...m}=d;return He("a",{href:p,"data-variant":t,"data-size":n,"data-loading":o?"true":void 0,"aria-disabled":o||void 0,tabIndex:o?-1:void 0,className:l,onClick:o?b=>b.preventDefault():void 0,...m,children:s})}let u=d;return He("button",{type:u.type??"button","data-variant":t,"data-size":n,"data-loading":o?"true":void 0,disabled:u.disabled||o,className:l,...u,children:s})}var Ht=[],Ot=[{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:"forms",componentId:"textarea"},{group:"forms",componentId:"collapsible"},{group:"forms",componentId:"tabs"},{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 x(e){Ht.push(e)}function _t(e,t){return Ht.find(n=>n.group===e&&n.componentId===t)}function ut(){let e={actions:[],forms:[],feedback:[],layout:[]};for(let t of Ht)e[t.group].push(t);return e}var Ft={actions:"Actions",forms:"Forms",feedback:"Feedback",layout:"Layout"},pt=["actions","forms","feedback","layout"];import{jsx as V,jsxs as Ze}from"react/jsx-runtime";x({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=>V(f,{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:()=>Ze("div",{className:"flex flex-wrap items-center gap-3",children:[V(f,{variant:"primary",children:"Primary"}),V(f,{variant:"secondary",children:"Secondary"}),V(f,{variant:"ghost",children:"Ghost"}),V(f,{variant:"danger",children:"Danger"})]})},{id:"sizes",title:"Sizes",description:"sm / md",render:()=>Ze("div",{className:"flex flex-wrap items-center gap-3",children:[V(f,{size:"sm",children:"Small"}),V(f,{size:"md",children:"Medium"})]})},{id:"with-icons",title:"With Icons",description:"leadingIcon / trailingIcon",render:()=>Ze("div",{className:"flex flex-wrap items-center gap-3",children:[V(f,{variant:"primary",leadingIcon:V(fn,{size:16}),children:"Create"}),V(f,{variant:"secondary",trailingIcon:V(gn,{size:16}),children:"Next"}),V(f,{variant:"ghost",leadingIcon:V(fn,{size:16}),trailingIcon:V(gn,{size:16}),children:"Both"})]})},{id:"loading-disabled",title:"Loading & Disabled",render:()=>Ze("div",{className:"flex flex-wrap items-center gap-3",children:[V(f,{variant:"primary",loading:!0,children:"Saving\u2026"}),V(f,{variant:"secondary",loading:!0,children:"Loading"}),V(f,{variant:"secondary",disabled:!0,children:"Disabled"}),V(f,{variant:"danger",disabled:!0,children:"Disabled Danger"})]})},{id:"all-variants-sm",title:"All Variants (sm)",render:()=>Ze("div",{className:"flex flex-wrap items-center gap-3",children:[V(f,{variant:"primary",size:"sm",children:"Primary"}),V(f,{variant:"secondary",size:"sm",children:"Secondary"}),V(f,{variant:"ghost",size:"sm",children:"Ghost"}),V(f,{variant:"danger",size:"sm",children:"Danger"})]})}]});import{X as Qe,Settings as mt,Trash2 as Fo,ChevronRight as Vo}from"lucide-react";import{clsx as _o}from"clsx";import{jsx as bn}from"react/jsx-runtime";function J({variant:e="ghost",size:t="md",label:n,icon:o,className:r,...a}){let i=_o("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",r);if("href"in a&&a.href){let{href:d,...s}=a;return bn("a",{href:d,"aria-label":n,title:s.title??n,"data-variant":e,"data-size":t,className:i,...s,children:o})}let c=a;return bn("button",{type:c.type??"button","aria-label":n,title:c.title??n,"data-variant":e,"data-size":t,className:i,...c,children:o})}import{jsx as W,jsxs as ft}from"react/jsx-runtime";x({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=>W(J,{variant:e.variant,size:e.size,disabled:!!e.disabled,label:"Settings",icon:W(mt,{size:e.size==="sm"?14:16})}),stories:[{id:"variants",title:"Variants",description:"ghost / subtle",render:()=>ft("div",{className:"flex items-center gap-3",children:[W(J,{variant:"ghost",label:"Close",icon:W(Qe,{size:16})}),W(J,{variant:"subtle",label:"Settings",icon:W(mt,{size:16})})]})},{id:"sizes",title:"Sizes",description:"sm / md",render:()=>ft("div",{className:"flex items-center gap-3",children:[W(J,{size:"sm",label:"Small",icon:W(Qe,{size:14})}),W(J,{size:"md",label:"Medium",icon:W(Qe,{size:16})})]})},{id:"use-cases",title:"Use Cases",render:()=>ft("div",{className:"flex items-center gap-3",children:[W(J,{label:"Close",icon:W(Qe,{size:16})}),W(J,{label:"Settings",icon:W(mt,{size:16})}),W(J,{label:"Delete",icon:W(Fo,{size:16})}),W(J,{label:"Navigate",icon:W(Vo,{size:16})})]})},{id:"disabled",title:"Disabled",render:()=>ft("div",{className:"flex items-center gap-3",children:[W(J,{label:"Disabled ghost",icon:W(Qe,{size:16}),disabled:!0}),W(J,{variant:"subtle",label:"Disabled subtle",icon:W(mt,{size:16}),disabled:!0})]})}]});import{clsx as Wo}from"clsx";import{jsx as vn}from"react/jsx-runtime";function gt(e){return Wo("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 pe(e){let{className:t,tone:n="default",...o}=e;return e.as==="textarea"?vn("textarea",{"data-tone":n,className:gt(t),...o}):vn("input",{"data-tone":n,className:gt(t),...o})}import{jsx as Pe,jsxs as hn}from"react/jsx-runtime";x({group:"forms",componentId:"input",componentName:"Input",description:'Single-line text input. Legacy `as="textarea"` support remains available, but new multiline usage should prefer the dedicated Textarea primitive.',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=>Pe("div",{className:"max-w-xs",children:Pe(pe,{as:e.as,tone:e.tone,placeholder:"Type something\u2026"})}),stories:[{id:"text-input",title:"Text Input",render:()=>hn("div",{className:"max-w-xs space-y-3",children:[Pe(pe,{"aria-label":"Default input",name:"demo-default",autoComplete:"off",placeholder:"e.g., hello world\u2026"}),Pe(pe,{"aria-label":"With value",name:"demo-value",autoComplete:"off",placeholder:"e.g., hello world\u2026",defaultValue:"Hello world"})]})},{id:"textarea",title:"Textarea",render:()=>Pe("div",{className:"max-w-sm",children:Pe(pe,{as:"textarea","aria-label":"Textarea",placeholder:"Write something\u2026",rows:3})})},{id:"tones",title:"Tones",description:"default / warning",render:()=>hn("div",{className:"max-w-xs space-y-3",children:[Pe(pe,{tone:"default","aria-label":"Default tone",name:"demo-tone-default",autoComplete:"off",placeholder:"Default tone\u2026"}),Pe(pe,{tone:"warning","aria-label":"Warning tone",name:"demo-tone-warning",autoComplete:"off",placeholder:"Warning tone\u2026"})]})}]});import{useState as qo}from"react";import{clsx as $o}from"clsx";import{jsx as yn,jsxs as Go}from"react/jsx-runtime";function Ie({label:e,help:t,htmlFor:n,children:o,className:r,...a}){return Go("div",{className:$o("ui-field block",r),...a,children:[yn("label",{htmlFor:n,className:"ui-field__label mb-1 block text-xs",children:e}),o,t?yn("span",{className:"ui-field__help mt-1 block text-xs",children:t}):null]})}import{clsx as We}from"clsx";import{useCallback as Vt,useEffect as xn,useId as Uo,useMemo as Ko,useRef as wn,useState as Nn}from"react";import{jsx as Je,jsxs as Tn}from"react/jsx-runtime";function Q({value:e,onChange:t,options:n,placeholder:o="Select\u2026",size:r="md",tone:a="default",disabled:i=!1,className:c,ariaLabel:d,renderValue:s,renderOption:l}){let[u,p]=Nn(!1),[m,b]=Nn(-1),T=wn(null),y=wn(null),h=Uo(),k=n.find(v=>v.value===e),w=Ko(()=>n.reduce((v,I,ee)=>(I.disabled||v.push(ee),v),[]),[n]),z=Vt(()=>{if(i||n.length===0)return;p(!0);let v=n.findIndex(I=>I.value===e);b(v>=0?v:w[0]??-1)},[i,n,e,w]),S=Vt(()=>{p(!1),b(-1)},[]),G=Vt(v=>{v.disabled||(t(v.value),S())},[t,S]);xn(()=>{if(!u)return;function v(I){T.current&&!T.current.contains(I.target)&&S()}return document.addEventListener("mousedown",v),()=>document.removeEventListener("mousedown",v)},[u,S]),xn(()=>{if(!u||m<0)return;y.current?.children[m]?.scrollIntoView({block:"nearest"})},[u,m]);function U(v){if(!i)switch(v.key){case"Enter":case" ":{v.preventDefault(),u?m>=0&&n[m]&&!n[m].disabled&&G(n[m]):z();break}case"ArrowDown":{if(v.preventDefault(),!u)z();else{let I=w.indexOf(m),ee=w[I+1];ee!==void 0&&b(ee)}break}case"ArrowUp":{if(v.preventDefault(),!u)z();else{let I=w.indexOf(m),ee=w[I-1];ee!==void 0&&b(ee)}break}case"Escape":{u&&(v.preventDefault(),S());break}case"Tab":{u&&S();break}}}let X=e!==""&&k,R=s?s({open:u,placeholder:o,selectedOption:k}):Je("span",{className:We("truncate",!X&&"ui-select__placeholder"),children:X?k.label:o});return Tn("div",{ref:T,"data-state":u?"open":"closed","data-disabled":i||void 0,"data-size":r,"data-tone":a,className:We("ui-select relative inline-block",c),children:[Tn("button",{type:"button",role:"combobox","aria-expanded":u,"aria-haspopup":"listbox","aria-controls":h,"aria-label":d,"aria-activedescendant":u&&m>=0?`${h}-opt-${m}`:void 0,"data-state":u?"open":"closed","data-disabled":i||void 0,"data-tone":a,"data-size":r,"data-open":u||void 0,"data-has-value":X||void 0,disabled:i,className:We("ui-select__trigger flex w-full items-center justify-between gap-2 rounded-lg text-left transition-colors focus:outline-none focus:ring-1",r==="sm"?"min-h-7 px-2 py-1 text-xs":"min-h-9 px-3 py-2 text-sm"),onClick:()=>u?S():z(),onKeyDown:U,children:[R,Je("svg",{"aria-hidden":"true",className:We("ui-select__chevron h-3.5 w-3.5 shrink-0 transition-transform",u&&"rotate-180"),viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:Je("path",{d:"M4 6l4 4 4-4"})})]}),u&&Je("ul",{ref:y,id:h,role:"listbox","aria-label":d,"data-state":"open",className:We("ui-select__dropdown absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-lg py-1 ring-1",r==="sm"?"text-xs":"text-sm"),children:n.map((v,I)=>Je("li",{id:`${h}-opt-${I}`,role:"option","aria-selected":v.value===e,"aria-disabled":v.disabled||void 0,"data-state":v.value===e?"selected":I===m?"highlighted":"idle","data-focused":I===m||void 0,"data-selected":v.value===e||void 0,"data-disabled":v.disabled||void 0,"data-highlighted":I===m||void 0,className:We("ui-select__option cursor-default select-none px-3 py-1.5 transition-colors",v.disabled&&"cursor-not-allowed opacity-50"),onClick:()=>G(v),onMouseEnter:()=>!v.disabled&&b(I),children:l?l({option:v,index:I,selected:v.value===e,highlighted:I===m}):v.label},v.value))})]})}import{jsx as de}from"react/jsx-runtime";function Yo(){let[e,t]=qo("");return de("div",{className:"max-w-xs pb-36",children:de(Ie,{label:"Category",htmlFor:"sb-category",children:de(Q,{value:e,onChange:t,options:[{value:"tech",label:"Technology"},{value:"design",label:"Design"},{value:"other",label:"Other"}],placeholder:"Select a category",ariaLabel:"Category"})})})}x({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:()=>de("div",{className:"max-w-xs",children:de(Ie,{label:"Username",htmlFor:"sb-username",children:de(pe,{id:"sb-username",name:"username",autoComplete:"username",placeholder:"Enter username"})})})},{id:"with-help",title:"With Help Text",render:()=>de("div",{className:"max-w-xs",children:de(Ie,{label:"Email",htmlFor:"sb-email",help:"We'll never share your email.",children:de(pe,{id:"sb-email",type:"email",name:"email",autoComplete:"email",spellCheck:!1,placeholder:"you@example.com"})})})},{id:"with-textarea",title:"With Textarea",render:()=>de("div",{className:"max-w-sm",children:de(Ie,{label:"Bio",htmlFor:"sb-bio",help:"Brief description about yourself.",children:de(pe,{as:"textarea",id:"sb-bio",name:"bio",autoComplete:"off",placeholder:"Tell us about yourself\u2026",rows:3})})})},{id:"with-select",title:"With Select",render:()=>de(Yo,{})}]});import{useState as je}from"react";import{jsx as te,jsxs as Wt}from"react/jsx-runtime";function Xo(){let[e,t]=je("");return te("div",{className:"max-w-xs pb-44",children:te(Q,{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 Zo(){let[e,t]=je("apple"),[n,o]=je("apple"),r=[{value:"apple",label:"Apple"},{value:"banana",label:"Banana"},{value:"cherry",label:"Cherry"}];return Wt("div",{className:"flex max-w-xs flex-col gap-3 pb-36",children:[te(Q,{value:e,onChange:t,options:[...r],size:"sm",ariaLabel:"Small select"}),te(Q,{value:n,onChange:o,options:[...r],size:"md",ariaLabel:"Medium select"})]})}function Qo(){let[e,t]=je("a"),[n,o]=je("a"),r=[{value:"a",label:"Option A"},{value:"b",label:"Option B"}];return Wt("div",{className:"flex max-w-xs flex-col gap-3 pb-28",children:[te(Q,{value:e,onChange:t,options:[...r],tone:"default",ariaLabel:"Default tone"}),te(Q,{value:n,onChange:o,options:[...r],tone:"warning",ariaLabel:"Warning tone"})]})}function Jo(){return Wt("div",{className:"flex max-w-xs flex-col gap-3 pb-28",children:[te(Q,{value:"",onChange:()=>{},options:[{value:"a",label:"Option A"}],disabled:!0,placeholder:"Disabled",ariaLabel:"Disabled select"}),te(Q,{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"})]})}x({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)=>te("div",{className:"max-w-xs pb-36",children:te(Q,{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:()=>te(Xo,{})},{id:"sizes",title:"Sizes",description:"sm / md",render:()=>te(Zo,{})},{id:"tones",title:"Tones",description:"default / warning",render:()=>te(Qo,{})},{id:"disabled",title:"Disabled",description:"Whole component disabled & individual option disabled.",render:()=>te(Jo,{})}]});import{useState as Dn}from"react";import{clsx as Cn}from"clsx";import{jsx as Sn}from"react/jsx-runtime";function bt({value:e,onChange:t,options:n,size:o="sm",className:r,ariaLabel:a}){return Sn("div",{role:"tablist","aria-label":a,className:Cn("ui-segmented-control inline-flex rounded-md p-0.5 ring-1",o==="sm"?"text-xs":"text-sm",r),children:n.map(i=>{let c=i.value===e;return Sn("button",{type:"button",role:"tab","aria-selected":c,disabled:i.disabled,"data-active":c?"true":void 0,className:Cn("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(i.value),children:i.label},i.value)})})}import{jsx as et,jsxs as er}from"react/jsx-runtime";function kn({size:e,label:t}){let[n,o]=Dn("a");return et(bt,{value:n,onChange:o,options:[{value:"a",label:"Alpha"},{value:"b",label:"Beta"},{value:"c",label:"Gamma"}],size:e,ariaLabel:t})}function jo(){let[e,t]=Dn("on");return et(bt,{value:e,onChange:t,options:[{value:"on",label:"On"},{value:"off",label:"Off"},{value:"auto",label:"Auto",disabled:!0}],ariaLabel:"Mode with disabled"})}x({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:()=>er("div",{className:"flex flex-wrap items-center gap-4",children:[et(kn,{size:"sm",label:"Small"}),et(kn,{size:"md",label:"Medium"})]})},{id:"with-disabled",title:"With Disabled Option",render:()=>et(jo,{})}]});import{useState as vt}from"react";import{clsx as Pn}from"clsx";import{jsx as In}from"react/jsx-runtime";var tr={sm:"h-5 w-9",md:"h-6 w-11"},nr={sm:"h-3.5 w-3.5",md:"h-4.5 w-4.5"},or={sm:"translate-x-4",md:"translate-x-5"};function Ce({checked:e,onChange:t,size:n="md",disabled:o=!1,className:r,ariaLabel:a}){return In("button",{type:"button",role:"switch","aria-checked":e,"aria-label":a,disabled:o,"data-size":n,className:Pn("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",tr[n],o&&"cursor-not-allowed opacity-50",r),onClick:()=>t(!e),children:In("span",{"aria-hidden":"true",className:Pn("ui-switch__thumb pointer-events-none inline-block rounded-full bg-white shadow transition-transform",nr[n],e?or[n]:"translate-x-0.5")})})}import{jsx as he,jsxs as $t}from"react/jsx-runtime";function rr(){let[e,t]=vt(!1);return he(Ce,{checked:e,onChange:t,ariaLabel:"Demo toggle"})}function ar(){let[e,t]=vt(!0),[n,o]=vt(!0);return $t("div",{className:"flex items-center gap-4",children:[he(Ce,{checked:e,onChange:t,size:"sm",ariaLabel:"Small switch"}),he(Ce,{checked:n,onChange:o,size:"md",ariaLabel:"Medium switch"})]})}function ir(){let[e,t]=vt(!1);return $t("label",{className:"inline-flex items-center gap-2 text-sm text-[var(--color-n800)]",children:[he(Ce,{checked:e,onChange:t,ariaLabel:"Notifications"}),"Enable notifications"]})}x({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)=>he(Ce,{checked:!!e.checked,onChange:n=>t("checked",n),size:e.size,disabled:!!e.disabled,ariaLabel:"Playground switch"}),stories:[{id:"default",title:"Default",render:()=>he(rr,{})},{id:"sizes",title:"Sizes",description:"sm / md",render:()=>he(ar,{})},{id:"with-label",title:"With Label",render:()=>he(ir,{})},{id:"disabled",title:"Disabled",render:()=>$t("div",{className:"flex items-center gap-4",children:[he(Ce,{checked:!1,onChange:()=>{},disabled:!0,ariaLabel:"Disabled off"}),he(Ce,{checked:!0,onChange:()=>{},disabled:!0,ariaLabel:"Disabled on"})]})}]});import{useCallback as sr,useEffect as lr,useRef as dr}from"react";import{jsx as cr}from"react/jsx-runtime";function Oe({className:e,tone:t="default",resize:n="vertical",autoResize:o=!1,style:r,onInput:a,rows:i=3,...c}){let d=dr(null),s=a,l=sr(()=>{if(!o||!d.current)return;let m=d.current;m.style.height="auto",m.style.height=`${m.scrollHeight}px`},[o]);lr(()=>{l()},[l,c.value,c.defaultValue,i]);function u(m){l(),s?.(m)}let p={...r,resize:o?"none":n};return cr("textarea",{...c,ref:d,rows:i,"data-tone":t,"data-auto-resize":o||void 0,className:gt(`ui-textarea ${e??""}`),style:p,onInput:u})}import{jsx as Se,jsxs as ur}from"react/jsx-runtime";x({group:"forms",componentId:"textarea",componentName:"Textarea",description:"Dedicated multiline text input that matches the Input token contract while supporting resize and auto-resize behavior.",props:[{name:"tone",type:"'default' | 'warning'",default:"'default'",description:"Visual tone for neutral or warning emphasis."},{name:"rows",type:"number",default:"3",description:"Initial row count before any auto-resize behavior."},{name:"resize",type:"'none' | 'vertical' | 'both'",default:"'vertical'",description:"Controls native resize affordance."},{name:"autoResize",type:"boolean",default:"false",description:"Automatically grows height to fit content."}],renderPlayground:e=>Se("div",{className:"max-w-sm",children:Se(Oe,{tone:e.tone,rows:Number(e.rows??3),resize:e.resize??"vertical",autoResize:!!e.autoResize,placeholder:"Write something longer\u2026"})}),stories:[{id:"default",title:"Default",render:()=>Se("div",{className:"max-w-sm",children:Se(Oe,{"aria-label":"Default textarea",placeholder:"Write something longer\u2026",rows:4})})},{id:"tones-and-resize",title:"Tones And Resize",render:()=>ur("div",{className:"max-w-sm space-y-3",children:[Se(Oe,{"aria-label":"Default tone textarea",rows:3,placeholder:"Default tone\u2026",resize:"vertical"}),Se(Oe,{"aria-label":"Warning tone textarea",rows:3,placeholder:"Warning tone\u2026",tone:"warning",resize:"both"})]})},{id:"with-field",title:"With Field",render:()=>Se("div",{className:"max-w-sm",children:Se(Ie,{label:"System Prompt",help:"Supports the same visual contract as Input.",children:Se(Oe,{"aria-label":"System prompt",rows:5,autoResize:!0,defaultValue:`You are a concise assistant.
|
|
5
|
+
Keep responses short.`})})})}]});import{ChevronDown as wr}from"lucide-react";import{clsx as Gt}from"clsx";import{createContext as pr,useContext as mr,useEffect as fr,useId as gr,useMemo as br,useRef as Mn,useState as Ln}from"react";import{jsx as tt}from"react/jsx-runtime";var Bn=pr(null);function En(e){let t=mr(Bn);if(!t)throw new Error(`${e} must be used within Collapsible.Root`);return t}function vr({open:e,defaultOpen:t,onOpenChange:n}){let[o,r]=Ln(t??!1),a=e!==void 0,i=a?e:o;function c(d){a||r(d),n?.(d)}return[i,c]}function Rn({children:e,open:t,defaultOpen:n,onOpenChange:o,className:r,...a}){let[i,c]=vr({open:t,defaultOpen:n,onOpenChange:o}),d=gr(),s=br(()=>({open:i,setOpen:c,contentId:d}),[d,i,c]);return tt(Bn.Provider,{value:s,children:tt("div",{"data-state":i?"open":"closed",className:Gt("ui-collapsible",r),...a,children:e})})}function hr({children:e,className:t,onClick:n,...o}){let{open:r,setOpen:a,contentId:i}=En("Collapsible.Trigger");return tt("button",{type:"button","aria-expanded":r,"aria-controls":i,"data-state":r?"open":"closed",className:Gt("ui-collapsible__trigger",t),onClick:c=>{n?.(c),c.defaultPrevented||a(!r)},...o,children:e})}function yr({children:e,className:t,...n}){let{open:o,contentId:r}=En("Collapsible.Content"),[a,i]=Ln(o),c=Mn(null),d=Mn(null);return fr(()=>{let s=c.current,l=d.current;if(!s||!l)return;let u=0,p=0,m=()=>{s.style.height="auto",s.style.overflow="visible"};if(o&&i(!0),!a&&!o)return;let b=y=>{y.target!==s||y.propertyName!=="height"||(s.removeEventListener("transitionend",b),o?m():i(!1))};return(()=>{let y=l.scrollHeight;if(s.style.overflow="hidden",o){s.style.height="0px",u=window.requestAnimationFrame(()=>{s.addEventListener("transitionend",b),s.style.height=`${y}px`}),p=window.setTimeout(m,240);return}s.style.height=`${y}px`,u=window.requestAnimationFrame(()=>{s.addEventListener("transitionend",b),s.style.height="0px"}),p=window.setTimeout(()=>i(!1),240)})(),()=>{window.cancelAnimationFrame(u),window.clearTimeout(p),s.removeEventListener("transitionend",b)}},[o,a]),!a&&!o?null:tt("div",{id:r,ref:c,"data-state":o?"open":"closed","aria-hidden":!o,className:Gt("ui-collapsible__content",t),...n,children:tt("div",{ref:d,className:"ui-collapsible__content-inner",children:e})})}var xr=Object.assign(Rn,{Root:Rn,Trigger:hr,Content:yr}),ht=xr;import{jsx as yt,jsxs as zn}from"react/jsx-runtime";x({group:"forms",componentId:"collapsible",componentName:"Collapsible",description:"Composable primitive for disclosure sections, reasoning panels, and settings details blocks.",props:[{name:"open",type:"boolean",description:"Controlled open state."},{name:"defaultOpen",type:"boolean",default:"false",description:"Initial open state for uncontrolled usage."},{name:"onOpenChange",type:"(open: boolean) => void",description:"Change callback for controlled or uncontrolled state updates."}],stories:[{id:"default",title:"Default",render:()=>yt("div",{className:"max-w-lg rounded-xl border border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg)] p-3",children:zn(ht,{defaultOpen:!0,children:[zn(ht.Trigger,{className:"flex w-full items-center justify-between gap-3 rounded-lg px-2 py-2 text-left text-sm font-medium",children:[yt("span",{children:"Reasoning"}),yt(wr,{className:"h-4 w-4"})]}),yt(ht.Content,{className:"px-2 pb-2 pt-1 text-sm text-[var(--ui-text-secondary)]",children:"This area can hold AI reasoning, debug detail, or an advanced configuration section."})]})})}]});import{clsx as wt}from"clsx";import{createContext as Nr,useContext as Tr,useId as Cr,useMemo as Sr,useState as kr}from"react";import{jsx as nt}from"react/jsx-runtime";var Hn=Nr(null);function On(e){let t=Tr(Hn);if(!t)throw new Error(`${e} must be used within Tabs.Root`);return t}function xt(e){return e.replace(/[^a-zA-Z0-9_-]+/g,"-")}function Dr({value:e,defaultValue:t,onValueChange:n}){let[o,r]=kr(t??""),a=e!==void 0,i=a?e:o;function c(d){a||r(d),n?.(d)}return[i,c]}function An({children:e,value:t,defaultValue:n,onValueChange:o,className:r,...a}){let[i,c]=Dr({value:t,defaultValue:n,onValueChange:o}),d=Cr(),s=Sr(()=>({value:i,setValue:c,baseId:d}),[d,i,c]);return nt(Hn.Provider,{value:s,children:nt("div",{className:wt("ui-tabs",r),...a,children:e})})}function Pr({children:e,className:t,ariaLabel:n,...o}){return nt("div",{role:"tablist","aria-label":n,className:wt("ui-tabs__list flex items-end gap-1 border-b",t),...o,children:e})}function Ir({children:e,className:t,value:n,disabled:o,onClick:r,onKeyDown:a,...i}){let{value:c,setValue:d,baseId:s}=On("Tabs.Trigger"),l=c===n,u=`${s}-trigger-${xt(n)}`,p=`${s}-panel-${xt(n)}`;function m(b,T){let y=b.closest('[role="tablist"]');if(!y)return;let h=Array.from(y.querySelectorAll('[role="tab"]:not([disabled])')),k=h.indexOf(b);if(k<0)return;let w;T==="first"&&(w=h[0]),T==="last"&&(w=h[h.length-1]),T==="next"&&(w=h[(k+1)%h.length]),T==="prev"&&(w=h[(k-1+h.length)%h.length]),w&&(w.focus(),w.click())}return nt("button",{type:"button",id:u,role:"tab","aria-selected":l,"aria-controls":p,tabIndex:l?0:-1,"data-state":l?"active":"inactive",disabled:o,className:wt("ui-tabs__trigger relative -mb-px inline-flex min-h-9 items-center justify-center rounded-t-md border-b-2 px-3 py-2 text-sm font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-inset disabled:cursor-not-allowed disabled:opacity-50",t),onClick:b=>{r?.(b),!b.defaultPrevented&&!o&&d(n)},onKeyDown:b=>{if(a?.(b),b.defaultPrevented||o)return;let T=b.currentTarget;switch(b.key){case"ArrowRight":b.preventDefault(),m(T,"next");break;case"ArrowLeft":b.preventDefault(),m(T,"prev");break;case"Home":b.preventDefault(),m(T,"first");break;case"End":b.preventDefault(),m(T,"last");break}},...i,children:e})}function Mr({children:e,className:t,value:n,...o}){let{value:r,baseId:a}=On("Tabs.Content"),i=r===n,c=`${a}-trigger-${xt(n)}`,d=`${a}-panel-${xt(n)}`;return i?nt("div",{id:d,role:"tabpanel","aria-labelledby":c,"data-state":"active",className:wt("ui-tabs__content pt-4",t),...o,children:e}):null}var Rr=Object.assign(An,{Root:An,List:Pr,Trigger:Ir,Content:Mr}),ke=Rr;import{jsx as ye,jsxs as _n}from"react/jsx-runtime";x({group:"forms",componentId:"tabs",componentName:"Tabs",description:"Navigation-grade tab primitive with keyboard support and linked tab panels.",props:[{name:"value",type:"string",description:"Controlled active tab value."},{name:"defaultValue",type:"string",description:"Initial tab value for uncontrolled usage."},{name:"onValueChange",type:"(value: string) => void",description:"Change callback when the active tab changes."}],stories:[{id:"settings-tabs",title:"Settings Tabs",render:()=>ye("div",{className:"max-w-2xl",children:_n(ke,{defaultValue:"settings",children:[_n(ke.List,{ariaLabel:"Settings sections",children:[ye(ke.Trigger,{value:"settings",children:"Settings"}),ye(ke.Trigger,{value:"account",children:"Account"}),ye(ke.Trigger,{value:"admin",disabled:!0,children:"Admin"})]}),ye(ke.Content,{value:"settings",children:ye("div",{className:"rounded-xl border border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg)] p-4 text-sm text-[var(--ui-text-secondary)]",children:"Settings panel content."})}),ye(ke.Content,{value:"account",children:ye("div",{className:"rounded-xl border border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg)] p-4 text-sm text-[var(--ui-text-secondary)]",children:"Account panel content."})}),ye(ke.Content,{value:"admin",children:ye("div",{className:"rounded-xl border border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg)] p-4 text-sm text-[var(--ui-text-secondary)]",children:"Admin panel content."})})]})})}]});import{clsx as Lr}from"clsx";import{jsx as Br}from"react/jsx-runtime";function Y({tone:e="neutral",variant:t="soft",size:n="xs",className:o,children:r,...a}){return Br("span",{"data-tone":e,"data-variant":t,"data-size":n,className:Lr("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),...a,children:r})}import{jsx as ne,jsxs as $e}from"react/jsx-runtime";x({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=>ne(Y,{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:()=>$e("div",{className:"flex flex-wrap items-center gap-3",children:[ne(Y,{tone:"neutral",children:"Neutral"}),ne(Y,{tone:"info",children:"Info"}),ne(Y,{tone:"success",children:"Success"}),ne(Y,{tone:"warning",children:"Warning"}),ne(Y,{tone:"danger",children:"Danger"})]})},{id:"tones-outline",title:"Tones (Outline)",description:"Same tones with outline variant \u2014 transparent bg, colored border.",render:()=>$e("div",{className:"flex flex-wrap items-center gap-3",children:[ne(Y,{tone:"neutral",variant:"outline",children:"Neutral"}),ne(Y,{tone:"info",variant:"outline",children:"Info"}),ne(Y,{tone:"success",variant:"outline",children:"Success"}),ne(Y,{tone:"warning",variant:"outline",children:"Warning"}),ne(Y,{tone:"danger",variant:"outline",children:"Danger"})]})},{id:"sizes",title:"Sizes",description:"xs / sm",render:()=>$e("div",{className:"flex flex-wrap items-center gap-3",children:[ne(Y,{size:"xs",tone:"info",children:"XS Badge"}),ne(Y,{size:"sm",tone:"info",children:"SM Badge"})]})},{id:"variant-comparison",title:"Variant Comparison",description:"Soft vs outline side by side for each tone.",render:()=>ne("div",{className:"space-y-3",children:["neutral","info","success","warning","danger"].map(e=>$e("div",{className:"flex items-center gap-3",children:[$e(Y,{size:"sm",tone:e,variant:"soft",children:[e," soft"]}),$e(Y,{size:"sm",tone:e,variant:"outline",children:[e," outline"]})]},e))})}]});import{Info as Hr,CheckCircle2 as Or,TriangleAlert as _r,CircleAlert as Fr}from"lucide-react";import{clsx as Er}from"clsx";import{Fragment as zr,jsx as Ut,jsxs as Ar}from"react/jsx-runtime";function me({tone:e="neutral",icon:t,className:n,children:o,...r}){return Ut("div",{"data-tone":e,className:Er("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),...r,children:t?Ar(zr,{children:[Ut("span",{className:"ui-status-notice__icon mt-0.5 shrink-0","aria-hidden":"true",children:t}),Ut("div",{className:"min-w-0",children:o})]}):o})}import{jsx as oe,jsxs as Fn}from"react/jsx-runtime";x({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=>oe(me,{tone:e.tone,children:"This is a status notice."}),stories:[{id:"tones",title:"Tones",description:"info / success / warning / danger",render:()=>Fn("div",{className:"space-y-3",children:[oe(me,{tone:"neutral",children:"General system guidance without a semantic alert state."}),oe(me,{tone:"info",children:"This is an informational notice."}),oe(me,{tone:"success",children:"Operation completed successfully."}),oe(me,{tone:"warning",children:"Please review before continuing."}),oe(me,{tone:"danger",children:"Something went wrong. Please try again."})]})},{id:"with-icons",title:"With Icons",render:()=>Fn("div",{className:"space-y-3",children:[oe(me,{tone:"info",icon:oe(Hr,{size:16}),children:"Background indexing is still in progress."}),oe(me,{tone:"success",icon:oe(Or,{size:16}),children:"Draft and main are fully aligned."}),oe(me,{tone:"warning",icon:oe(_r,{size:16}),children:"One route conflict still needs manual review."}),oe(me,{tone:"danger",icon:oe(Fr,{size:16}),children:"Publishing failed. Retry after refreshing the snapshot."})]})}]});import{clsx as Vr}from"clsx";import{jsx as ot,jsxs as Wr}from"react/jsx-runtime";function Me({tone:e="neutral",icon:t,title:n,description:o,action:r,className:a,children:i,...c}){let d=t||n||o||r;return ot("div",{"data-tone":e,className:Vr("ui-empty-state rounded-lg border px-4 py-3 text-sm",a),...c,children:d?Wr("div",{className:"flex flex-col items-center gap-2 py-4 text-center",children:[t&&ot("div",{className:"ui-empty-state__icon text-lg",children:t}),n&&ot("div",{className:"ui-empty-state__title font-medium",children:n}),o&&ot("div",{className:"ui-empty-state__description",children:o}),r&&ot("div",{className:"mt-2",children:r})]}):i})}import{jsx as Re,jsxs as $r}from"react/jsx-runtime";x({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:()=>Re(Me,{children:"No items found."})},{id:"structured",title:"Structured Slots",description:"Using title, description, and action slots.",render:()=>Re(Me,{title:"No posts yet",description:"Create your first post to get started.",action:Re(f,{variant:"primary",size:"sm",children:"Create Post"})})},{id:"tones",title:"Tones",description:"neutral / notice / warning",render:()=>$r("div",{className:"space-y-4",children:[Re(Me,{tone:"neutral",title:"Neutral",description:"Default empty state."}),Re(Me,{tone:"notice",title:"Notice",description:"Informational empty state."}),Re(Me,{tone:"warning",title:"Warning",description:"Attention-drawing empty state."})]})},{id:"with-icon",title:"With Icon",render:()=>Re(Me,{icon:Re("span",{className:"text-2xl",children:"\u{1F4ED}"}),title:"Inbox empty",description:"You have no new messages."})}]});import{jsx as re,jsxs as Ge}from"react/jsx-runtime";x({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=>re(le,{variant:e.variant,size:e.size}),stories:[{id:"variants",title:"Variants",description:"ring / arc / dots / bars / bounce / pulse / orbit / flow",render:()=>re("div",{className:"flex flex-wrap items-center gap-8",children:["ring","arc","dots","bars","bounce","pulse","orbit","flow"].map(e=>Ge("div",{className:"flex flex-col items-center gap-2",children:[re(le,{variant:e,size:"lg"}),re("span",{className:"text-[11px] text-[var(--color-n500)]",children:e})]},e))})},{id:"sizes",title:"Sizes",description:"xs / sm / md / lg",render:()=>Ge("div",{className:"flex items-center gap-4",children:[re(le,{size:"xs"}),re(le,{size:"sm"}),re(le,{size:"md"}),re(le,{size:"lg"})]})},{id:"with-text",title:"Inline with Text",render:()=>Ge("div",{className:"space-y-3",children:[Ge("div",{className:"flex items-center gap-2 text-sm text-[var(--color-n600)]",children:[re(le,{variant:"ring",size:"sm"}),re("span",{children:"Loading data\u2026"})]}),Ge("div",{className:"flex items-center gap-2 text-sm text-[var(--color-n600)]",children:[re(le,{variant:"flow",size:"sm"}),re("span",{children:"Processing\u2026"})]}),Ge("div",{className:"flex items-center gap-2 text-sm text-[var(--color-n600)]",children:[re(le,{variant:"bounce",size:"sm"}),re("span",{children:"Waiting for response\u2026"})]})]})}]});import{clsx as Gr}from"clsx";import{jsx as Kr}from"react/jsx-runtime";var Ur={slow:"4s",default:"3s",fast:"2s"};function _({className:e,animation:t="scan",tone:n="default",speed:o="default",style:r,...a}){let i=n==="warm"?"emphasis":n,c={...r,"--ui-skeleton-scan-duration":Ur[o]};return Kr("div",{className:Gr("ui-skeleton rounded",e),"data-animation":t,"data-tone":i,"aria-hidden":"true",style:c,...a})}import{jsx as L,jsxs as ce}from"react/jsx-runtime";x({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=>ce("div",{className:"space-y-3",children:[L(_,{animation:e.animation,tone:e.tone,speed:e.speed,className:"h-4 w-48"}),L(_,{animation:e.animation,tone:e.tone,speed:e.speed,className:"h-4 w-64"})]}),stories:[{id:"scan",title:"Scan",render:()=>ce("div",{className:"space-y-4",children:[L(_,{className:"h-4 w-48"}),L(_,{className:"h-4 w-64"}),L(_,{className:"h-4 w-32"})]})},{id:"scan-speed",title:"Scan Speed",render:()=>ce("div",{className:"space-y-4",children:[ce("div",{className:"space-y-2",children:[L("div",{className:"text-xs font-medium text-[var(--color-n500)]",children:"Slow \xB7 4s"}),L(_,{speed:"slow",className:"h-4 w-64"})]}),ce("div",{className:"space-y-2",children:[L("div",{className:"text-xs font-medium text-[var(--color-n500)]",children:"Default \xB7 3s"}),L(_,{className:"h-4 w-64"})]}),ce("div",{className:"space-y-2",children:[L("div",{className:"text-xs font-medium text-[var(--color-n500)]",children:"Fast \xB7 2s"}),L(_,{speed:"fast",className:"h-4 w-64"})]})]})},{id:"pulse",title:"Pulse",render:()=>ce("div",{className:"space-y-4",children:[L(_,{animation:"pulse",className:"h-4 w-48"}),L(_,{animation:"pulse",className:"h-4 w-64"}),L(_,{animation:"pulse",className:"h-4 w-32"})]})},{id:"on-surfaces",title:"On Different Surfaces",description:"Verifies shimmer visibility against various backgrounds.",render:()=>L("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})=>ce("div",{className:"rounded-lg p-4",style:{backgroundColor:t},children:[L("p",{className:"mb-2 text-[11px] font-medium text-[var(--color-n500)]",children:e}),ce("div",{className:"space-y-2",children:[L(_,{className:"h-4 w-full"}),L(_,{className:"h-4 w-3/4"})]})]},e))})},{id:"card-placeholder",title:"Card Placeholder",render:()=>ce("div",{className:"max-w-sm space-y-3 rounded-lg border border-[var(--color-surface-border)] p-4",children:[L(_,{className:"h-5 w-3/4"}),L(_,{className:"h-4 w-full"}),L(_,{className:"h-4 w-5/6"}),ce("div",{className:"flex gap-2 pt-2",children:[L(_,{animation:"pulse",className:"h-8 w-20 rounded-md"}),L(_,{animation:"pulse",className:"h-8 w-20 rounded-md"})]})]})},{id:"avatar-line",title:"Avatar + Lines",render:()=>ce("div",{className:"flex items-start gap-3",children:[L(_,{className:"h-10 w-10 shrink-0 rounded-full"}),ce("div",{className:"flex-1 space-y-2",children:[L(_,{animation:"pulse",className:"h-4 w-32"}),L(_,{className:"h-3 w-48"})]})]})}]});import{useState as Tt}from"react";import{clsx as rt}from"clsx";import{useEffect as qr,useRef as Vn,useCallback as Yr}from"react";import{jsx as at,jsxs as Jr}from"react/jsx-runtime";function Xr({className:e,children:t,...n}){return at("div",{className:rt("ui-dialog__header px-5 pt-5 pb-1 text-base font-semibold",e),...n,children:t})}function Zr({className:e,children:t,...n}){return at("div",{className:rt("ui-dialog__body px-5 py-3 text-sm",e),...n,children:t})}function Qr({className:e,children:t,...n}){return at("div",{className:rt("ui-dialog__footer flex items-center justify-end gap-2 px-5 pt-3 pb-5",e),...n,children:t})}function B({open:e,onClose:t,size:n="sm",children:o,className:r,overlayClassName:a,panelClassName:i,...c}){let d=Vn(null),s=Vn(null),l=Yr(u=>{u.key==="Escape"&&(u.stopPropagation(),t())},[t]);return qr(()=>(e?(s.current=document.activeElement,document.body.style.overflow="hidden",requestAnimationFrame(()=>{let u=d.current;if(!u)return;let p=u.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');p?p.focus():u.focus()}),document.addEventListener("keydown",l)):(document.body.style.overflow="",s.current?.focus()),()=>{document.removeEventListener("keydown",l),document.body.style.overflow=""}),[e,l]),e?Jr("div",{"data-state":"open",className:"ui-dialog-overlay fixed inset-0 z-50 flex items-center justify-center",children:[at("button",{type:"button","aria-label":"Close dialog","data-state":"open",className:rt("ui-dialog-backdrop absolute inset-0 bg-black/30",a),onClick:t}),at("div",{ref:d,role:"dialog","aria-modal":"true",tabIndex:-1,"data-state":"open","data-size":n,className:rt("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]",i,r),...c,children:o})]}):null}B.Header=Xr;B.Body=Zr;B.Footer=Qr;import{createContext as jr,useCallback as Wn,useContext as ea,useRef as ta,useState as na}from"react";import{Fragment as oa,jsx as Ue,jsxs as Kt}from"react/jsx-runtime";var $n=jr(null);function Gn(){let e=ea($n);if(!e)throw new Error("useConfirm must be used within <ConfirmProvider>");return e}function Nt({children:e}){let[t,n]=na(null),o=ta(null),r=Wn(i=>(o.current&&o.current.resolve(!1),new Promise(c=>{let d={options:i,resolve:c};o.current=d,n(d)})),[]),a=Wn(i=>{o.current&&(o.current.resolve(i),o.current=null),n(null)},[]);return Kt($n.Provider,{value:r,children:[e,Ue(B,{open:t!==null,onClose:()=>a(!1),children:t&&Kt(oa,{children:[Ue(B.Header,{children:t.options.title}),Ue(B.Body,{children:typeof t.options.description=="string"?Ue("p",{className:"whitespace-pre-wrap",children:t.options.description}):t.options.description}),Kt(B.Footer,{children:[Ue(f,{variant:"ghost",size:"sm",onClick:()=>a(!1),children:t.options.cancelLabel??"\u53D6\u6D88"}),Ue(f,{variant:t.options.variant??"primary",size:"sm",onClick:()=>a(!0),children:t.options.confirmLabel??"\u786E\u8BA4"})]})]})})]})}import{Fragment as qt,jsx as N,jsxs as E}from"react/jsx-runtime";function ra(){let[e,t]=Tt(!1);return E(qt,{children:[N(f,{variant:"primary",size:"sm",onClick:()=>t(!0),children:"Open Dialog"}),E(B,{open:e,onClose:()=>t(!1),children:[N(B.Header,{children:"Basic Dialog"}),N(B.Body,{children:N("p",{children:"This is a basic dialog with header, body, and footer sections."})}),E(B.Footer,{children:[N(f,{variant:"ghost",size:"sm",onClick:()=>t(!1),children:"Cancel"}),N(f,{variant:"primary",size:"sm",onClick:()=>t(!1),children:"Confirm"})]})]})]})}function aa(){let[e,t]=Tt(!1);return E(qt,{children:[N(f,{variant:"danger",size:"sm",onClick:()=>t(!0),children:"Delete Item"}),E(B,{open:e,onClose:()=>t(!1),children:[N(B.Header,{children:"Delete Draft"}),E(B.Body,{children:[N("p",{children:"Are you sure you want to delete the ZH locale draft?"}),E("p",{className:"mt-2",children:["Article ID: post-20260320-example",N("br",{}),"Category: post"]}),N("p",{className:"mt-2",children:"This action cannot be undone."})]}),E(B.Footer,{children:[N(f,{variant:"ghost",size:"sm",onClick:()=>t(!1),children:"Cancel"}),N(f,{variant:"danger",size:"sm",onClick:()=>t(!1),children:"Delete"})]})]})]})}function ia(){let[e,t]=Tt(!1);return E(qt,{children:[N(f,{variant:"secondary",size:"sm",onClick:()=>t(!0),children:"Open Medium Dialog"}),E(B,{open:e,onClose:()=>t(!1),size:"md",children:[N(B.Header,{children:"Publish Confirmation"}),E(B.Body,{children:[N("p",{children:"You are about to publish the current draft branch."}),E("div",{className:"mt-3 rounded-lg border border-[var(--color-surface-border)] bg-[var(--color-surface-base)] p-3 text-sm",children:[E("div",{className:"flex justify-between",children:[N("span",{children:"Articles:"}),N("span",{children:"3"})]}),E("div",{className:"flex justify-between",children:[N("span",{children:"Languages:"}),N("span",{children:"ZH, EN"})]}),E("div",{className:"flex justify-between",children:[N("span",{children:"Branch:"}),N("span",{children:"draft"})]})]}),N("p",{className:"mt-3",children:"This will trigger a Cloudflare deployment."})]}),E(B.Footer,{children:[N(f,{variant:"ghost",size:"sm",onClick:()=>t(!1),children:"Cancel"}),N(f,{variant:"primary",size:"sm",onClick:()=>t(!1),children:"Publish"})]})]})]})}function sa(){let e=Gn(),[t,n]=Tt("");return E("div",{className:"flex flex-col gap-3",children:[E("div",{className:"flex gap-2",children:[N(f,{variant:"primary",size:"sm",onClick:async()=>{let a=await e({title:"Confirm Action",description:"This demonstrates the useConfirm() hook. Click confirm or cancel.",confirmLabel:"Do it",cancelLabel:"Nope"});n(a?"Confirmed!":"Cancelled.")},children:"useConfirm()"}),N(f,{variant:"danger",size:"sm",onClick:async()=>{let a=await e({title:"Delete Everything",description:"This is a danger variant confirm dialog.",confirmLabel:"Delete",variant:"danger"});n(a?"Deleted!":"Cancelled.")},children:"Danger Confirm"})]}),t&&E("p",{className:"text-sm text-[var(--color-n600)]",children:["Result: ",t]})]})}function la(){return N(Nt,{children:N(sa,{})})}x({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 E("div",{className:"flex flex-col items-center gap-4",children:[E(f,{variant:"primary",size:"sm",onClick:()=>t("open",!0),children:["Open Dialog (",n,")"]}),E(B,{open:o,onClose:()=>t("open",!1),size:n,children:[N(B.Header,{children:"Playground Dialog"}),N(B.Body,{children:E("p",{children:["Toggle the ",N("code",{className:"rounded bg-[var(--color-surface-subtle)] px-1 py-0.5 text-xs",children:"open"})," and ",N("code",{className:"rounded bg-[var(--color-surface-subtle)] px-1 py-0.5 text-xs",children:"size"})," controls below."]})}),E(B.Footer,{children:[N(f,{variant:"ghost",size:"sm",onClick:()=>t("open",!1),children:"Cancel"}),N(f,{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
|
|
6
|
+
import { ConfirmProvider } from '../../components/ConfirmDialog';
|
|
7
|
+
|
|
8
|
+
export default function AdminLayout({ children }) {
|
|
9
|
+
return (
|
|
10
|
+
<ThemeProvider>
|
|
11
|
+
<ConfirmProvider>
|
|
12
|
+
{children}
|
|
13
|
+
</ConfirmProvider>
|
|
14
|
+
</ThemeProvider>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Any descendant component
|
|
19
|
+
import { useConfirm } from '../../components/ConfirmDialog';
|
|
20
|
+
|
|
21
|
+
function MyComponent() {
|
|
22
|
+
const confirm = useConfirm();
|
|
23
|
+
|
|
24
|
+
const handleDelete = async () => {
|
|
25
|
+
const ok = await confirm({
|
|
26
|
+
title: 'Delete draft',
|
|
27
|
+
description: 'This cannot be undone.',
|
|
28
|
+
confirmLabel: 'Delete',
|
|
29
|
+
variant: 'danger',
|
|
30
|
+
});
|
|
31
|
+
if (!ok) return;
|
|
32
|
+
// proceed with deletion
|
|
33
|
+
};
|
|
34
|
+
}`,render:()=>E("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:[N("p",{className:"font-medium text-[var(--color-n800)]",children:"Provider is already mounted in admin layout."}),E("p",{className:"mt-1",children:["Click the ",N("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)}>
|
|
35
|
+
<Dialog.Header>Title</Dialog.Header>
|
|
36
|
+
<Dialog.Body>Content here.</Dialog.Body>
|
|
37
|
+
<Dialog.Footer>
|
|
38
|
+
<Button variant="ghost" onClick={close}>Cancel</Button>
|
|
39
|
+
<Button variant="primary" onClick={close}>Confirm</Button>
|
|
40
|
+
</Dialog.Footer>
|
|
41
|
+
</Dialog>`,render:()=>N(ra,{})},{id:"danger",title:"Danger Dialog",description:"Destructive action confirmation with danger-styled button.",render:()=>N(aa,{})},{id:"medium",title:"Medium Size",description:"Wider dialog for content-heavy confirmations.",render:()=>N(ia,{})},{id:"use-confirm",title:"useConfirm() Hook",description:"Imperative confirm API that returns a Promise<boolean>. Replaces window.confirm.",source:`const confirm = useConfirm();
|
|
42
|
+
const ok = await confirm({
|
|
43
|
+
title: 'Confirm',
|
|
44
|
+
description: 'Are you sure?',
|
|
45
|
+
variant: 'danger',
|
|
46
|
+
});`,render:()=>N(la,{})}]});import{clsx as Un}from"clsx";import{createContext as da,useCallback as Kn,useContext as ca,useMemo as ua,useRef as qn,useState as pa}from"react";import{jsx as K,jsxs as it}from"react/jsx-runtime";var Xn=da(null),Yt=5,Yn=4e3;function Zn(){let e=ca(Xn);if(!e)throw new Error("useToast must be used within <ToastProvider>");return e}function ma({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 K("svg",{...t,children:K("path",{d:"M3.5 8.5l3 3 6-7"})});case"warning":return it("svg",{...t,children:[K("path",{d:"M8 5v4"}),K("circle",{cx:"8",cy:"11.5",r:"0.5",fill:"currentColor",stroke:"none"})]});case"danger":return K("svg",{...t,children:K("path",{d:"M4.5 4.5l7 7M11.5 4.5l-7 7"})});case"info":return it("svg",{...t,children:[K("circle",{cx:"8",cy:"3.5",r:"1.2",fill:"currentColor",stroke:"none"}),K("path",{d:"M8 7v5.5"})]})}}function fa(e,t){return typeof e=="string"?{message:e,duration:t??Yn}:{title:e.title,message:e.message,duration:e.duration??t??Yn}}function ga({item:e,onDismiss:t,renderToast:n}){let o=()=>t(e.id),r=K(ma,{tone:e.tone});return n?K("div",{role:"status","aria-live":"polite","data-state":"open","data-tone":e.tone,className:Un("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:r})}):it("div",{role:"status","aria-live":"polite","data-state":"open","data-tone":e.tone,className:Un("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:[K("span",{className:"ui-toast__icon mt-0.5 shrink-0","aria-hidden":"true",children:r}),it("span",{className:"min-w-0 flex-1",children:[e.title?K("span",{className:"ui-toast__title block font-medium",children:e.title}):null,K("span",{className:"block",children:e.message})]}),K("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:K("svg",{width:"14",height:"14",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",children:K("path",{d:"M4 4l8 8M12 4l-8 8"})})})]})}function Ct({children:e,renderToast:t}){let[n,o]=pa([]),r=qn(0),a=qn(new Map),i=Kn(s=>{let l=a.current.get(s);l&&clearTimeout(l),a.current.delete(s),o(u=>u.filter(p=>p.id!==s))},[]),c=Kn((s,l,u)=>{let p=r.current++,m=fa(l,u),b={id:p,tone:s,...m};o(T=>{let y=[...T,b];if(y.length>Yt){let h=y.slice(0,y.length-Yt);for(let k of h){let w=a.current.get(k.id);w&&clearTimeout(w),a.current.delete(k.id)}return y.slice(-Yt)}return y}),b.duration>0&&a.current.set(p,setTimeout(()=>i(p),b.duration))},[i]),d=ua(()=>({success:(s,l)=>c("success",s,l),warning:(s,l)=>c("warning",s,l),danger:(s,l)=>c("danger",s,l),info:(s,l)=>c("info",s,l)}),[c]);return it(Xn.Provider,{value:d,children:[e,K("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=>K(ga,{item:s,onDismiss:i,renderToast:t},s.id))})]})}import{jsx as xe,jsxs as Xt}from"react/jsx-runtime";function ba(){let e=Zn();return Xt("div",{className:"flex flex-wrap gap-2",children:[xe(f,{size:"sm",variant:"secondary",onClick:()=>e.success("Changes saved successfully."),children:"Success"}),xe(f,{size:"sm",variant:"secondary",onClick:()=>e.warning("Draft has unsaved changes."),children:"Warning"}),xe(f,{size:"sm",variant:"secondary",onClick:()=>e.danger("Failed to publish post."),children:"Danger"}),xe(f,{size:"sm",variant:"secondary",onClick:()=>e.info("New version available."),children:"Info"}),xe(f,{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 va(){return xe(Ct,{children:xe(ba,{})})}x({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
|
|
47
|
+
import { ToastProvider } from '../../components/Toast';
|
|
48
|
+
|
|
49
|
+
export default function AdminLayout({ children }) {
|
|
50
|
+
return (
|
|
51
|
+
<ThemeProvider>
|
|
52
|
+
<ToastProvider>
|
|
53
|
+
{children}
|
|
54
|
+
</ToastProvider>
|
|
55
|
+
</ThemeProvider>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Any descendant component
|
|
60
|
+
import { useToast } from '../../components/Toast';
|
|
61
|
+
|
|
62
|
+
function MyComponent() {
|
|
63
|
+
const toast = useToast();
|
|
64
|
+
|
|
65
|
+
const handleSave = async () => {
|
|
66
|
+
try {
|
|
67
|
+
await saveDraft();
|
|
68
|
+
toast.success('Draft saved.');
|
|
69
|
+
} catch {
|
|
70
|
+
toast.danger('Failed to save draft.');
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}`,render:()=>Xt("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:[xe("p",{className:"font-medium text-[var(--color-n800)]",children:"ToastProvider is not yet mounted in admin layout."}),Xt("p",{className:"mt-1",children:["Add it to the layout before using useToast(). Click the ",xe("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:()=>xe(va,{})}]});import{clsx as ha}from"clsx";import{useState as ya}from"react";import{jsx as Zt}from"react/jsx-runtime";var xa={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 wa(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 ae({src:e,alt:t,name:n,size:o="md",tone:r="neutral",className:a}){let[i,c]=ya(!1),d=e&&!i,s=n?wa(n):"?";return Zt("span",{"data-tone":r,className:ha("ui-avatar inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full font-medium select-none",xa[o],a),children:d?Zt("img",{src:e,alt:t??n??"",className:"h-full w-full object-cover",onError:()=>c(!0)}):Zt("span",{"aria-label":t??n,children:s})})}import{jsx as ie,jsxs as Ke}from"react/jsx-runtime";x({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=>ie(ae,{name:"Alice Bob",size:e.size,tone:e.tone}),stories:[{id:"sizes",title:"Sizes",description:"xs / sm / md / lg",render:()=>Ke("div",{className:"flex items-end gap-3",children:[ie(ae,{name:"Alice",size:"xs"}),ie(ae,{name:"Bob Chen",size:"sm"}),ie(ae,{name:"Carol Davis",size:"md"}),ie(ae,{name:"David",size:"lg"})]})},{id:"tones",title:"Tones",description:"neutral (default) vs subtle \u2014 applies to initials fallback.",render:()=>Ke("div",{className:"flex items-center gap-4",children:[Ke("div",{className:"text-center",children:[ie(ae,{name:"Neutral",size:"lg",tone:"neutral"}),ie("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"neutral"})]}),Ke("div",{className:"text-center",children:[ie(ae,{name:"Subtle",size:"lg",tone:"subtle"}),ie("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"subtle"})]})]})},{id:"with-image",title:"With Image",render:()=>Ke("div",{className:"flex items-center gap-3",children:[ie(ae,{src:"https://api.dicebear.com/9.x/initials/svg?seed=QQ",name:"Q",size:"md"}),ie(ae,{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:()=>Ke("div",{className:"flex items-center gap-3",children:[ie(ae,{src:"/broken-url.jpg",name:"Fallback User",size:"md"}),ie(ae,{name:"No Image",size:"md"}),ie(ae,{size:"md"})]})}]});import{clsx as Na}from"clsx";import{cloneElement as Ta,isValidElement as Ca,useCallback as St,useEffect as Qn,useId as Sa,useLayoutEffect as ka,useRef as kt,useState as Qt}from"react";import{createPortal as Da}from"react-dom";import{Fragment as Ba,jsx as Jt,jsxs as to}from"react/jsx-runtime";var st=6,Jn=8,Dt=4,Pa={top:"bottom",bottom:"top",left:"right",right:"left"},Ia={top:{left:"50%",top:"100%",transform:"translateX(-50%)"},bottom:{left:"50%",top:-st,transform:"translateX(-50%) rotate(180deg)"},left:{top:"50%",left:"100%",transform:"translateY(-50%) rotate(-90deg)"},right:{top:"50%",left:-st,transform:"translateY(-50%) rotate(90deg)"}};function jn(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 eo(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 Ma(e,t,n,o){let r=o?Jn+st:Jn,a=jn(n,e,t,r),i=n,c=a;if(!eo(a,t)){let p=Pa[n],m=jn(p,e,t,r);eo(m,t)&&(i=p,c=m)}let d=window.innerWidth,s=window.innerHeight,l=Math.max(Dt,Math.min(c.left,d-t.width-Dt)),u=Math.max(Dt,Math.min(c.top,s-t.height-Dt));return{placement:i,top:u,left:l}}function Ra(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 La={compact:"px-2 py-1 text-[11px] max-w-[200px]",default:"px-3 py-2 text-xs max-w-xs"};function be({content:e,placement:t="top",density:n="default",showDelay:o=300,hideDelay:r=150,arrow:a=!0,renderArrow:i,className:c,children:d}){let[s,l]=Qt(!1),[u,p]=Qt(null),[m,b]=Qt(t),T=kt(null),y=kt(null),h=kt(void 0),k=kt(void 0),w=Sa(),z=St(()=>{clearTimeout(h.current),clearTimeout(k.current)},[]),S=St(()=>{z(),h.current=setTimeout(()=>l(!0),o)},[z,o]),G=St(()=>{z(),k.current=setTimeout(()=>l(!1),r)},[z,r]),U=St(R=>{R.key==="Escape"&&s&&l(!1)},[s]);if(ka(()=>{if(!s||!T.current||!y.current)return;function R(){if(!T.current||!y.current)return;let v=T.current.getBoundingClientRect(),I=y.current.getBoundingClientRect(),ee=Ma(v,I,t,a),ze=document.body.getBoundingClientRect();p({top:ee.top+window.scrollY-ze.top,left:ee.left+window.scrollX-ze.left}),b(ee.placement)}return R(),window.addEventListener("scroll",R,!0),window.addEventListener("resize",R),()=>{window.removeEventListener("scroll",R,!0),window.removeEventListener("resize",R)}},[s,t,a]),Qn(()=>{if(s)return document.addEventListener("keydown",U),()=>document.removeEventListener("keydown",U)},[s,U]),Qn(()=>z,[z]),!Ca(d))return d;let X=Ta(d,{ref:Ra(T,d),"data-state":s?"open":"closed",onMouseEnter:R=>{S();let v=d.props.onMouseEnter;v?.(R)},onMouseLeave:R=>{G();let v=d.props.onMouseLeave;v?.(R)},onFocus:R=>{S();let v=d.props.onFocus;v?.(R)},onBlur:R=>{G();let v=d.props.onBlur;v?.(R)},"aria-describedby":s?w:void 0});return to(Ba,{children:[X,s&&Da(to("div",{ref:y,id:w,role:"tooltip","data-state":s?"open":"closed","data-placement":m,"data-density":n,className:Na("ui-tooltip absolute z-[9999] rounded-lg leading-relaxed",La[n],"animate-[tooltip-in_0.15s_var(--ease-standard)]",c),style:u?{top:u.top,left:u.left}:{position:"fixed",visibility:"hidden"},onMouseEnter:S,onMouseLeave:G,children:[e,a&&Jt("span",{className:"ui-tooltip__arrow absolute",style:Ia[m],children:i?i({placement:m}):Jt("svg",{width:st*2,height:st,viewBox:"0 0 12 6",children:Jt("path",{d:"M0 0l6 6 6-6z",fill:"currentColor"})})})]}),document.body)]})}import{Settings as Ea}from"lucide-react";import{jsx as H,jsxs as jt}from"react/jsx-runtime";x({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:()=>jt("div",{className:"flex flex-wrap items-center justify-center gap-4 py-12",children:[H(be,{content:"Placed on top",placement:"top",children:H(f,{variant:"secondary",size:"sm",children:"Top"})}),H(be,{content:"Placed on bottom",placement:"bottom",children:H(f,{variant:"secondary",size:"sm",children:"Bottom"})}),H(be,{content:"Placed on left",placement:"left",children:H(f,{variant:"secondary",size:"sm",children:"Left"})}),H(be,{content:"Placed on right",placement:"right",children:H(f,{variant:"secondary",size:"sm",children:"Right"})})]})},{id:"density",title:"Density",description:"compact vs default \u2014 compact is tighter for icon labels.",render:()=>jt("div",{className:"flex flex-wrap items-center justify-center gap-6 py-12",children:[H(be,{content:"Compact tooltip",density:"compact",children:H(f,{variant:"secondary",size:"sm",children:"Compact"})}),H(be,{content:"Default density tooltip with more room for content",density:"default",children:H(f,{variant:"secondary",size:"sm",children:"Default"})})]})},{id:"rich-content",title:"Rich Content",description:"Tooltip supports ReactNode content.",render:()=>H("div",{className:"flex justify-center py-8",children:H(be,{content:jt("div",{children:[H("p",{className:"font-medium",children:"Keyboard shortcut"}),H("p",{className:"mt-1 opacity-80",children:"Press Ctrl+S to save your work."})]}),children:H(f,{variant:"secondary",size:"sm",children:"Hover for shortcut"})})})},{id:"on-icon-button",title:"On IconButton",description:"Common pattern: tooltip on icon-only buttons.",render:()=>H("div",{className:"flex justify-center py-8",children:H(be,{content:"Settings",density:"compact",children:H(J,{label:"Settings",icon:H(Ea,{size:16})})})})},{id:"no-arrow",title:"Without Arrow",render:()=>H("div",{className:"flex justify-center py-8",children:H(be,{content:"No arrow variant",arrow:!1,children:H(f,{variant:"secondary",size:"sm",children:"Hover me"})})})}]});import{useState as Qa}from"react";import{clsx as Be}from"clsx";import{Children as za,cloneElement as Aa,createContext as no,isValidElement as Ha,useCallback as j,useContext as en,useEffect as _e,useId as Pt,useLayoutEffect as Oa,useMemo as Mt,useRef as Le,useState as lt}from"react";import{createPortal as _a}from"react-dom";import{jsx as se,jsxs as so}from"react/jsx-runtime";var oo=no(null),tn=no(null);function nn(e){let t=en(oo);if(!t)throw new Error(`${e} must be used within DropdownMenu.`);return t}function ro(e){let t=en(tn);if(!t)throw new Error(`${e} must be used within DropdownMenu.Content.`);return t}function qe(e,t){return n=>{e?.(n),t(n)}}function ao(...e){return t=>{for(let n of e)n&&(typeof n=="function"?n(t):n.current=t)}}function It(e){return typeof e=="string"||typeof e=="number"?String(e):Array.isArray(e)?e.map(It).join(" "):!e||typeof e=="boolean"?"":Ha(e)?It(e.props.children):""}function Fa(e){return[...e].sort((t,n)=>{let o=t.ref.current,r=n.ref.current;if(!o||!r)return 0;let a=o.compareDocumentPosition(r);return a&Node.DOCUMENT_POSITION_FOLLOWING?-1:a&Node.DOCUMENT_POSITION_PRECEDING?1:0})}function Va(e){let{anchorRect:t,contentRect:n,sideOffset:o,alignOffset:r,collisionPadding:a}=e,i=window.innerWidth,c=window.innerHeight;function d(y,h){let k=0,w=0;return y==="bottom"?(k=t.bottom+o,h==="start"?w=t.left+r:h==="end"?w=t.right-n.width+r:w=t.left+(t.width-n.width)/2+r):y==="top"?(k=t.top-n.height-o,h==="start"?w=t.left+r:h==="end"?w=t.right-n.width+r:w=t.left+(t.width-n.width)/2+r):y==="right"?(w=t.right+o,h==="start"?k=t.top+r:h==="end"?k=t.bottom-n.height+r:k=t.top+(t.height-n.height)/2+r):(w=t.left-n.width-o,h==="start"?k=t.top+r:h==="end"?k=t.bottom-n.height+r:k=t.top+(t.height-n.height)/2+r),{top:k,left:w}}let s={top:"bottom",bottom:"top",left:"right",right:"left"},l=e.side,u=e.align,p=d(l,u);if(p.left<a||p.top<a||p.left+n.width>i-a||p.top+n.height>c-a){let y=d(s[l],u);y.left>=a&&y.top>=a&&y.left+n.width<=i-a&&y.top+n.height<=c-a&&(l=s[l],p=y)}let b=i-n.width-a,T=c-n.height-a;return p.left=Math.max(a,Math.min(p.left,b)),p.top=Math.max(a,Math.min(p.top,T)),{top:p.top,left:p.left,side:l,align:u}}function io({open:e,defaultOpen:t=!1,onOpenChange:n,side:o="bottom",align:r="start",sideOffset:a=8,alignOffset:i=0,collisionPadding:c=8,portal:d=!0,contentRole:s="menu",children:l}){let u=en(tn),[p,m]=lt(t),b=e!==void 0,T=b?e:p,y=Le(null),h=Le(null),k=Le("selected"),w=Pt(),z=Pt(),S=j(I=>{b||m(I),n?.(I)},[b,n]),G=j(()=>{S(!1)},[S]),U=j(()=>{S(!1),u?.closeTree()},[u,S]),X=j(()=>{S(!T)},[T,S]),R=j(()=>{y.current?.focus()},[]),v=Mt(()=>({open:T,setOpen:S,toggleOpen:X,triggerRef:y,contentRef:h,side:o,align:r,sideOffset:a,alignOffset:i,collisionPadding:c,portal:d,contentRole:s,triggerId:w,contentId:z,focusIntentRef:k,parentList:u,isSubmenu:!!u,closeSelf:G,closeTree:U,focusTrigger:R}),[T,r,i,G,U,c,s,u,d,S,o,a,X,w,z,R]);return se(oo.Provider,{value:v,children:l})}function Wa({asChild:e=!1,disabled:t=!1,className:n,children:o}){let{open:r,setOpen:a,toggleOpen:i,triggerRef:c,contentRole:d,triggerId:s,contentId:l,focusIntentRef:u,isSubmenu:p}=nn("DropdownMenu.Trigger"),m=za.only(o),b=m.props??{},T=typeof b.className=="string"?b.className:void 0,y={id:s,"data-state":r?"open":"closed","aria-expanded":r,"aria-haspopup":d,"aria-controls":r?l:void 0,onClick:qe(b.onClick,h=>{if(t){h.preventDefault();return}u.current="selected",i()}),onKeyDown:qe(b.onKeyDown,h=>{t||(h.key==="ArrowDown"?(h.preventDefault(),u.current="first",a(!0)):h.key==="ArrowUp"?(h.preventDefault(),u.current="last",a(!0)):!p&&(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),u.current="selected",i()))})};return e?Aa(m,{...y,ref:ao(c,b.ref),className:Be(n,T),type:m.type==="button"?b.type??"button":b.type}):se("button",{ref:c,disabled:t,type:"button",className:Be("ui-dropdown-menu__trigger",n),...y,children:m})}function $a({className:e,children:t,style:n,matchTriggerWidth:o=!1,maxHeight:r=320,...a}){let{open:i,setOpen:c,triggerRef:d,contentRef:s,side:l,align:u,sideOffset:p,alignOffset:m,collisionPadding:b,portal:T,contentRole:y,triggerId:h,contentId:k,focusIntentRef:w,parentList:z,isSubmenu:S,closeSelf:G,closeTree:U,focusTrigger:X}=nn("DropdownMenu.Content"),R=Le([]),[v,I]=lt(null),[ee,ze]=lt(null),[ct,yo]=lt(null),[Et,xo]=lt(!1),zt=Le(""),Fe=Le(null),cn=j(C=>(R.current=[...R.current.filter(F=>F.id!==C.id),C],()=>{R.current=R.current.filter(F=>F.id!==C.id)}),[]),ue=j(()=>Fa(R.current),[]),un=j(C=>{w.current=C},[w]);_e(()=>{xo(!0)},[]);let wo=Mt(()=>({role:y,highlightedId:v,setHighlightedId:I,registerItem:cn,getItems:ue,requestFocusIntent:un,closeTree:U,closeSelf:G,focusTrigger:X,activeSubmenuId:ee,setActiveSubmenuId:ze,contentRef:s}),[ee,G,U,s,y,X,ue,v,cn,un]),Ve=j(()=>{if(!d.current||!s.current)return;let C=d.current.getBoundingClientRect(),F=s.current.getBoundingClientRect();yo(Va({anchorRect:C,contentRect:F,side:l,align:u,sideOffset:p,alignOffset:m,collisionPadding:b}))},[u,m,b,s,l,p,d]);Oa(()=>{if(!(!i||!Et))return Ve(),window.addEventListener("resize",Ve),window.addEventListener("scroll",Ve,!0),()=>{window.removeEventListener("resize",Ve),window.removeEventListener("scroll",Ve,!0)}},[Et,i,Ve]),_e(()=>{if(!i){I(null),ze(null);return}let C=ue().filter(P=>!P.disabled);if(C.length===0)return;let F=C[0];w.current==="last"?F=C[C.length-1]:w.current==="selected"&&(F=C.find(P=>P.selected)??C[0]),I(F.id),requestAnimationFrame(()=>{s.current?.focus(),F.ref.current?.scrollIntoView({block:"nearest"})})},[s,w,ue,i]),_e(()=>{if(!i)return;function C(F){let P=F.target,Z=d.current?.contains(P),Ne=s.current?.contains(P);if(!Z&&!Ne){let ve=z?.contentRef.current?.contains(P);if(S&&ve){G(),z?.setActiveSubmenuId(null);return}U()}}return document.addEventListener("mousedown",C),()=>document.removeEventListener("mousedown",C)},[G,U,s,S,i,z,d]),_e(()=>{if(i)return()=>{Fe.current&&clearTimeout(Fe.current)}},[i]);let De=j(C=>{if(I(C),!C){ze(null);return}ue().find(P=>P.id===C)?.submenu||ze(null)},[ue]),At=j((C,F="first")=>{let P=ue().filter(Te=>!Te.disabled);if(P.length===0)return;let Z=P.findIndex(Te=>Te.id===v);if(Z===-1){De(F==="last"?P[P.length-1].id:P[0].id);return}let Ne=(Z+C+P.length)%P.length,ve=P[Ne];De(ve.id),ve.ref.current?.scrollIntoView({block:"nearest"})},[ue,v,De]),pn=j(C=>{let F=C.length===1?C.toLowerCase():"";if(!F)return;Fe.current&&clearTimeout(Fe.current),zt.current+=F,Fe.current=setTimeout(()=>{zt.current="",Fe.current=null},350);let P=ue().filter(Te=>!Te.disabled);if(P.length===0)return;let Z=P.findIndex(Te=>Te.id===v),ve=(Z>=0?[...P.slice(Z+1),...P.slice(0,Z+1)]:P).find(Te=>Te.textValue.toLowerCase().startsWith(zt.current));ve&&(De(ve.id),ve.ref.current?.scrollIntoView({block:"nearest"}))},[ue,v,De]),No=j(C=>{let F=ue(),P=F.find(Z=>Z.id===v)??null;switch(C.key){case"ArrowDown":C.preventDefault(),At(1);break;case"ArrowUp":C.preventDefault(),At(-1,"last");break;case"Home":C.preventDefault();{let Z=F.find(Ne=>!Ne.disabled);Z&&De(Z.id)}break;case"End":C.preventDefault();{let Z=F.filter(ve=>!ve.disabled),Ne=Z[Z.length-1];Ne&&De(Ne.id)}break;case"Enter":case" ":P&&!P.disabled&&(C.preventDefault(),P.click());break;case"ArrowRight":P?.submenu&&(C.preventDefault(),P.openSubmenu?.());break;case"ArrowLeft":S&&(C.preventDefault(),G(),X(),z?.setActiveSubmenuId(null));break;case"Tab":U();break;case"Escape":C.preventDefault(),G(),X(),S&&z?.setActiveSubmenuId(null);break;default:pn(C.key)}},[G,U,X,ue,pn,v,De,S,At,z]);if(!i||!Et)return null;let mn=se(tn.Provider,{value:wo,children:se("div",{ref:s,id:k,role:y,tabIndex:-1,"aria-labelledby":y==="menu"?h:void 0,"data-state":"open","data-side":ct?.side??l,"data-align":ct?.align??u,className:Be("ui-dropdown-menu__content",S&&"ui-dropdown-menu__content--submenu",e),style:{...n,position:"fixed",top:ct?.top??0,left:ct?.left??0,maxHeight:r,minWidth:o?d.current?.getBoundingClientRect().width:void 0},onKeyDown:No,...a,children:t})});return T?_a(mn,document.body):mn}function Ga({className:e,children:t,...n}){return se("div",{className:Be("ui-dropdown-menu__group",e),...n,children:t})}function Ua({className:e,children:t,...n}){return se("div",{className:Be("ui-dropdown-menu__label",e),...n,children:t})}function Ka({className:e,...t}){return se("div",{role:"separator",className:Be("ui-dropdown-menu__separator",e),...t})}function qa({className:e,children:t,inset:n=!1,disabled:o=!1,selected:r=!1,destructive:a=!1,closeOnSelect:i=!0,shortcut:c,indicator:d,onSelect:s,onMouseEnter:l,onClick:u,...p}){let m=Pt(),b=Le(null),{role:T,highlightedId:y,setHighlightedId:h,registerItem:k,closeTree:w,setActiveSubmenuId:z}=ro("DropdownMenu.Item"),S=Mt(()=>It(t),[t]),G=y===m,U=j(()=>{o||(s?.(),i&&w())},[i,w,o,s]);return _e(()=>k({id:m,ref:b,disabled:o,submenu:!1,selected:r,textValue:S,closeOnSelect:i,click:U}),[i,o,U,m,k,r,S]),so("button",{ref:b,id:m,type:"button",role:T==="listbox"?"option":"menuitem",tabIndex:-1,disabled:o,"aria-selected":T==="listbox"?r:void 0,"data-highlighted":G||void 0,"data-selected":r||void 0,"data-disabled":o||void 0,"data-destructive":a||void 0,className:Be("ui-dropdown-menu__item",n&&"ui-dropdown-menu__item--inset",e),onMouseEnter:qe(l,()=>{o||(h(m),z(null))}),onClick:qe(u,X=>{X.preventDefault(),U()}),...p,children:[se("span",{className:"ui-dropdown-menu__item-main",children:t}),c?se("span",{className:"ui-dropdown-menu__shortcut",children:c}):null,r?se("span",{className:"ui-dropdown-menu__indicator",children:d??"\u2713"}):null]})}function Ya(e){return se(io,{side:"right",align:"start",sideOffset:6,...e,contentRole:"menu"})}function Xa({className:e,children:t,inset:n=!1,disabled:o=!1,destructive:r=!1,shortcut:a,onSelect:i,onMouseEnter:c,onClick:d,...s}){let l=Pt(),u=Le(null),p=nn("DropdownMenu.SubTrigger"),{highlightedId:m,setHighlightedId:b,registerItem:T,setActiveSubmenuId:y,activeSubmenuId:h}=ro("DropdownMenu.SubTrigger"),k=Mt(()=>It(t),[t]),w=m===l,z=p.open&&h===l,S=j(()=>{o||(p.focusIntentRef.current="first",b(l),y(l),p.setOpen(!0))},[o,l,y,b,p]);return _e(()=>T({id:l,ref:u,disabled:o,submenu:!0,selected:!1,textValue:k,closeOnSelect:!1,click:S,openSubmenu:S}),[o,l,S,T,k]),_e(()=>{h!==l&&p.open&&p.setOpen(!1)},[h,l,p]),so("button",{ref:ao(u,p.triggerRef),id:p.triggerId,type:"button",role:"menuitem",tabIndex:-1,"aria-haspopup":"menu","aria-expanded":p.open,"aria-controls":p.open?p.contentId:void 0,"data-highlighted":w||void 0,"data-state":z?"open":"closed","data-disabled":o||void 0,"data-destructive":r||void 0,className:Be("ui-dropdown-menu__item ui-dropdown-menu__sub-trigger",n&&"ui-dropdown-menu__item--inset",e),onMouseEnter:qe(c,()=>{S()}),onClick:qe(d,G=>{G.preventDefault(),S(),i?.()}),...s,children:[se("span",{className:"ui-dropdown-menu__item-main",children:t}),a?se("span",{className:"ui-dropdown-menu__shortcut",children:a}):null,se("span",{className:"ui-dropdown-menu__submenu-indicator","aria-hidden":"true",children:"\u203A"})]})}var Za=Object.assign(io,{Trigger:Wa,Content:$a,Group:Ga,Label:Ua,Item:qa,Separator:Ka,Submenu:Ya,SubTrigger:Xa}),A=Za;import{jsx as $,jsxs as we}from"react/jsx-runtime";function Ja(){return $("div",{className:"flex min-h-52 items-start justify-start pb-48",children:we(A,{align:"start",children:[$(A.Trigger,{asChild:!0,children:$("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"})}),we(A.Content,{children:[we(A.Group,{children:[$(A.Item,{children:"Open settings"}),$(A.Item,{children:"Duplicate workspace"})]}),$(A.Separator,{}),we(A.Submenu,{children:[$(A.SubTrigger,{children:"Theme"}),we(A.Content,{children:[$(A.Item,{children:"Light"}),$(A.Item,{selected:!0,children:"Elevated"}),$(A.Item,{children:"Glass"})]})]}),$(A.Separator,{}),$(A.Item,{destructive:!0,children:"Delete workspace"})]})]})})}function ja(){let[e,t]=Qa("gpt-4.1-mini");return $("div",{className:"flex min-h-64 items-end pb-44",children:we(A,{contentRole:"listbox",side:"top",align:"end",children:[$(A.Trigger,{asChild:!0,children:we("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:[$("span",{children:e}),$("span",{className:"text-xs text-[var(--ui-text-muted)]",children:"\u25BC"})]})}),we(A.Content,{className:"w-64",children:[we(A.Group,{children:[$(A.Label,{children:"OpenAI"}),["gpt-4.1-mini","gpt-4.1","o4-mini"].map(n=>$(A.Item,{selected:n===e,onSelect:()=>t(n),children:n},n))]}),we(A.Group,{children:[$(A.Label,{children:"Custom"}),["claude-sonnet-4","gemini-2.5-pro"].map(n=>$(A.Item,{selected:n===e,onSelect:()=>t(n),children:n},n))]})]})]})})}x({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:()=>$(Ja,{})},{id:"picker",title:"Grouped Picker",description:"Model-picker style listbox with selected state.",render:()=>$(ja,{})}]});import{useState as ni}from"react";import{clsx as lo}from"clsx";import{Fragment as ei,jsx as co,jsxs as ti}from"react/jsx-runtime";function on({as:e="aside",open:t,children:n,side:o="right",position:r="fixed",showBackdrop:a=!0,onClose:i,closeLabel:c="\u5173\u95ED\u62BD\u5C49",backdropClassName:d,className:s,...l}){let u=o==="left"?"-translate-x-full":"translate-x-full",p=o==="left"?"left-0 top-0":"right-0 top-0",m=r==="fixed"?"fixed":"absolute";return ti(ei,{children:[a&&t&&i&&co("button",{type:"button","aria-label":c,"data-state":"open",className:lo("ui-drawer-backdrop inset-0 z-10",m,d),onClick:i}),co(e,{"aria-hidden":!t,"data-state":t?"open":"closed","data-side":o,className:lo("ui-drawer",m,p,"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 ${u}`,s),...l,children:n})]})}import{jsx as q,jsxs as Ee}from"react/jsx-runtime";function rn({side:e="right",showBackdrop:t=!0}){let[n,o]=ni(!1);return Ee("div",{className:"relative h-[26rem] overflow-hidden rounded-xl border border-[var(--color-surface-border)] bg-[var(--color-surface-canvas)]",children:[q("div",{className:"flex h-full items-center justify-center",children:q(f,{variant:"primary",size:"sm",onClick:()=>o(!0),children:"Open Drawer"})}),q(on,{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:Ee("div",{className:"flex h-full flex-col",children:[Ee("div",{className:"flex items-center justify-between border-b border-[var(--panel-section-border,var(--color-surface-border))] px-4 py-3",children:[q("span",{className:"text-sm font-semibold text-n800",children:"Post Settings"}),q(f,{variant:"ghost",size:"sm",onClick:()=>o(!1),children:"Close"})]}),Ee("div",{className:"flex-1 space-y-3 overflow-y-auto p-4",children:[q("p",{className:"text-sm text-n600",children:"Drawer now uses --drawer-surface, --drawer-border, and --drawer-shadow tokens from CSS."}),q("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."})]}),Ee("div",{className:"flex justify-end gap-2 border-t border-[var(--panel-section-border,var(--color-surface-border))] px-4 py-3",children:[q(f,{variant:"ghost",size:"sm",onClick:()=>o(!1),children:"Cancel"}),q(f,{variant:"primary",size:"sm",onClick:()=>o(!1),children:"Save"})]})]})})]})}x({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
|
|
74
|
+
open={open}
|
|
75
|
+
onClose={() => setOpen(false)}
|
|
76
|
+
side="right"
|
|
77
|
+
position="absolute"
|
|
78
|
+
aria-label="Post settings"
|
|
79
|
+
className="h-full w-80 border-l"
|
|
80
|
+
>
|
|
81
|
+
<div className="flex h-full flex-col">
|
|
82
|
+
<div className="border-b px-4 py-3">Header</div>
|
|
83
|
+
<div className="flex-1 overflow-y-auto p-4">Body</div>
|
|
84
|
+
<div className="border-t px-4 py-3">Footer</div>
|
|
85
|
+
</div>
|
|
86
|
+
</Drawer>`,render:()=>q(rn,{side:"right"})},{id:"left",title:"Left Drawer",description:"Left-side variant for navigation or contextual tools.",render:()=>q(rn,{side:"left"})},{id:"without-backdrop",title:"Without Backdrop",description:"Useful inside bounded shells where overlay dimming is not desired.",render:()=>q(rn,{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:()=>q("div",{className:"rounded-xl bg-[var(--color-surface-subtle)] p-5",children:Ee("div",{className:"relative h-[20rem] overflow-hidden rounded-xl border border-[var(--color-surface-border)] bg-[var(--color-surface-canvas)]",children:[q("div",{className:"absolute inset-0 bg-[var(--color-overlay-strong)]"}),Ee("div",{className:"ui-drawer absolute inset-y-0 right-0 flex w-80 max-w-full flex-col border-l",children:[q("div",{className:"border-b border-[var(--drawer-border)] px-4 py-3 text-sm font-semibold text-[var(--color-n800)]",children:"Drawer Surface"}),Ee("div",{className:"flex-1 space-y-3 p-4 text-sm text-[var(--color-n600)]",children:[q("p",{children:"Backdrop handles separation from the page."}),q("p",{children:"Surface defines the drawer body."}),q("p",{children:"Shadow confirms it is a floating layer, not a static card."})]})]})]})})}]});import{clsx as Rt}from"clsx";import{jsx as Lt}from"react/jsx-runtime";function oi(e){switch(e){case"none":return"";case"sm":return"p-4";case"lg":return"p-6";default:return"p-5"}}function fe({as:e="section",variant:t="default",padding:n="none",className:o,children:r,...a}){return Lt(e,{"data-variant":t,className:Rt("ui-panel rounded-lg border",oi(n),o),...a,children:r})}function uo({className:e,children:t,...n}){return Lt("div",{className:Rt("ui-panel-header border-b px-6 py-5",e),...n,children:t})}function po({className:e,children:t,...n}){return Lt("div",{className:Rt("px-6 py-5",e),...n,children:t})}function mo({className:e,children:t,...n}){return Lt("div",{className:Rt("ui-panel-footer border-t px-6 py-4",e),...n,children:t})}import{jsx as M,jsxs as ge}from"react/jsx-runtime";x({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=>M(fe,{variant:e.variant,padding:e.padding,children:M("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:()=>ge("div",{className:"grid gap-4 sm:grid-cols-3",children:[ge(fe,{variant:"default",padding:"md",children:[M("p",{className:"text-sm font-medium",children:"Default"}),M("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Standard container."})]}),ge(fe,{variant:"subtle",padding:"md",children:[M("p",{className:"text-sm font-medium",children:"Subtle"}),M("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Reduced emphasis."})]}),ge(fe,{variant:"raised",padding:"md",children:[M("p",{className:"text-sm font-medium",children:"Raised"}),M("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">
|
|
87
|
+
<PanelHeader>
|
|
88
|
+
<h3>Panel Title</h3>
|
|
89
|
+
</PanelHeader>
|
|
90
|
+
<PanelBody>
|
|
91
|
+
<p>Body content here.</p>
|
|
92
|
+
</PanelBody>
|
|
93
|
+
<PanelFooter>
|
|
94
|
+
<Button variant="ghost" size="sm">Cancel</Button>
|
|
95
|
+
<Button variant="primary" size="sm">Confirm</Button>
|
|
96
|
+
</PanelFooter>
|
|
97
|
+
</Panel>`,render:()=>ge(fe,{variant:"default",className:"max-w-md",children:[M(uo,{children:M("h3",{className:"text-sm font-semibold",children:"Panel Title"})}),M(po,{children:M("p",{className:"text-sm text-[var(--color-n600)]",children:"This is the body content of the panel. It can contain any elements."})}),M(mo,{children:ge("div",{className:"flex justify-end gap-2",children:[M(f,{variant:"ghost",size:"sm",children:"Cancel"}),M(f,{variant:"primary",size:"sm",children:"Confirm"})]})})]})},{id:"on-surfaces",title:"On Different Surfaces",description:"Verifies panel contrast against canvas, subtle, and inset backgrounds.",render:()=>M("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})=>ge("div",{className:"rounded-lg p-4",style:{backgroundColor:t},children:[M("p",{className:"mb-2 text-[11px] font-medium text-[var(--color-n500)]",children:e}),M(fe,{variant:"default",padding:"md",children:M("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:()=>M("div",{className:"rounded-xl bg-[var(--color-surface-subtle)] p-5",children:ge("div",{className:"grid gap-4 lg:grid-cols-3",children:[ge(fe,{variant:"default",padding:"md",children:[M("p",{className:"text-sm font-medium",children:"Default"}),M("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Primary reading card."})]}),ge(fe,{variant:"subtle",padding:"md",children:[M("p",{className:"text-sm font-medium",children:"Subtle"}),M("p",{className:"mt-1 text-xs text-[var(--color-n500)]",children:"Secondary summary area."})]}),ge(fe,{variant:"raised",padding:"md",children:[M("p",{className:"text-sm font-medium",children:"Raised"}),M("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:()=>M("div",{className:"space-y-3",children:["none","sm","md","lg"].map(e=>M(fe,{variant:"default",padding:e,children:ge("span",{className:"text-xs",children:["padding=","\u201C",e,"\u201D"]})},e))})}]});import{useEffect as Ye,useMemo as dt,useState as Xe}from"react";var an=["light","dark"];var Bt=["default","flat","elevated","glass"];import{clsx as sn}from"clsx";import{Check as ri,Clipboard as ai,Code2 as ii}from"lucide-react";import{jsx as g,jsxs as O}from"react/jsx-runtime";var fo="owoui-storybook-theme",go="owoui-storybook-preset";function si(){return window.localStorage.getItem(fo)==="dark"?"dark":"light"}function li(){let e=window.localStorage.getItem(go);return Bt.includes(e)?e:"default"}function di(){let[e,t]=Xe(()=>window.location.hash);return Ye(()=>{let n=()=>t(window.location.hash);return window.addEventListener("hashchange",n),()=>window.removeEventListener("hashchange",n)},[]),dt(()=>{let n=e.replace(/^#\/?/,""),[o="",r=""]=n.split("/");return{group:o,component:r}},[e])}function bo(e,t){window.location.hash=`#/${e}/${t}`}function ci({story:e}){let[t,n]=Xe(!1),[o,r]=Xe(!1);Ye(()=>{if(!o)return;let i=window.setTimeout(()=>r(!1),1500);return()=>window.clearTimeout(i)},[o]);let a=!!e.source;return O("div",{className:"overflow-hidden rounded-lg border border-[var(--ui-surface-border)]",children:[g("div",{className:"overflow-x-auto p-6",style:{backgroundColor:"var(--ui-surface-bg)"},children:g("div",{className:"min-w-0",children:e.render()})}),a?O("div",{className:"flex items-center justify-between border-t border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg-subtle)] px-3 py-1.5",children:[O("button",{type:"button",onClick:()=>n(i=>!i),className:sn("flex items-center gap-1 rounded px-2 py-0.5 text-[11px] transition-colors",t?"bg-[var(--ui-surface-bg)] text-[var(--ui-text-primary)] shadow-sm":"text-[var(--ui-text-muted)] hover:text-[var(--ui-text-secondary)]"),children:[g(ii,{size:12}),"Code"]}),t?O("button",{type:"button",onClick:async()=>{e.source&&(await navigator.clipboard.writeText(e.source),r(!0))},className:"flex items-center gap-1 rounded px-2 py-0.5 text-[11px] text-[var(--ui-text-muted)] transition-colors hover:text-[var(--ui-text-secondary)]",children:[o?g(ri,{size:12}):g(ai,{size:12}),o?"Copied":"Copy"]}):null]}):null,a&&t?g("pre",{className:"overflow-x-auto border-t border-[var(--ui-surface-border)] bg-[var(--color-code-block-bg)] p-4 text-xs leading-relaxed text-[var(--color-n700)]",children:g("code",{children:e.source})}):null]})}var ui=/^'[^']+'\s*(\s*\|\s*'[^']+')+$/;function pi(e){let t=e.trim();return ui.test(t)?{controlType:"select",options:[...t.matchAll(/'([^']+)'/g)].map(o=>o[1])}:t==="boolean"?{controlType:"boolean"}:t==="string"?{controlType:"string"}:t==="number"?{controlType:"number"}:{controlType:"skip"}}function mi(e,t,n){if(e===void 0||e==="")return t==="boolean"?!1:t==="select"&&n?.length?n[0]:t==="number"?0:"";let o=e.trim();return t==="boolean"?o==="true":t==="number"?Number(o)||0:/^'.*'$/.test(o)||/^".*"$/.test(o)?o.slice(1,-1):o}function fi(e){return e.flatMap(t=>{let{controlType:n,options:o}=pi(t.type);return n==="skip"?[]:[{name:t.name,controlType:n,options:o,defaultValue:mi(t.default,n,o),description:t.description}]})}function gi({control:e,value:t,onChange:n}){let o="rounded border border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg)] px-2 py-1 text-xs text-[var(--ui-text-primary)] focus:outline-none focus:ring-1 focus:ring-[var(--ui-accent-bg)]";switch(e.controlType){case"select":return g(Q,{value:String(t),onChange:r=>n(r),options:(e.options??[]).map(r=>({value:r,label:r})),size:"sm",ariaLabel:e.name,className:"min-w-[120px]"});case"boolean":return g("button",{type:"button",role:"switch","aria-checked":!!t,"aria-label":e.name,onClick:()=>n(!t),className:`relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors ${t?"bg-[var(--ui-accent-bg)]":"bg-[var(--color-n300)]"}`,children:g("span",{className:`pointer-events-none inline-block h-3.5 w-3.5 rounded-full bg-white shadow transition-transform ${t?"translate-x-4":"translate-x-0.5"}`})});case"string":return g("input",{type:"text",value:String(t??""),onChange:r=>n(r.target.value),className:`${o} w-full max-w-[200px]`,placeholder:e.name});case"number":return g("input",{type:"number",value:Number(t)||0,onChange:r=>n(Number(r.target.value)||0),className:`${o} w-20`});default:return null}}function bi({props:e,renderPlayground:t}){let n=dt(()=>fi(e),[e]),o=dt(()=>{let c={};for(let d of n)c[d.name]=d.defaultValue;return c},[n]),[r,a]=Xe(o);Ye(()=>{a(o)},[o]);let i=(c,d)=>{a(s=>({...s,[c]:d}))};return O("div",{className:"overflow-visible rounded-lg border border-[var(--ui-surface-border)]",children:[O("div",{className:"flex items-center justify-between rounded-t-lg border-b border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg-subtle)] px-3 py-1.5",children:[g("span",{className:"text-[11px] font-semibold uppercase tracking-wider text-[var(--ui-text-muted)]",children:"Playground"}),g("button",{type:"button",onClick:()=>a(o),className:"rounded px-2 py-0.5 text-[11px] text-[var(--ui-text-muted)] transition-colors hover:text-[var(--ui-text-secondary)]",children:"Reset"})]}),g("div",{className:"border-b border-[var(--ui-surface-border)] p-6",style:{backgroundColor:"var(--ui-surface-bg)"},children:g("div",{className:"min-w-0",children:t(r,i)})}),g("div",{className:"rounded-b-lg bg-[var(--ui-surface-bg-subtle)] p-3",children:g("div",{className:"grid gap-2.5",children:n.map(c=>O("div",{className:"flex items-center gap-3",children:[g("label",{className:"w-24 shrink-0 text-right font-mono text-[11px] font-medium text-[var(--ui-text-secondary)]",children:c.name}),g(gi,{control:c,value:r[c.name],onChange:d=>i(c.name,d)}),c.description?g("span",{className:"hidden text-[11px] text-[var(--color-n400)] lg:inline",children:c.description}):null]},c.name))})})]})}function vi({props:e}){return g("div",{className:"overflow-x-auto rounded-lg border border-[var(--ui-surface-border)]",children:O("table",{className:"w-full text-left text-sm",children:[g("thead",{children:O("tr",{className:"border-b border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg-subtle)]",children:[g("th",{className:"px-4 py-2 text-xs font-semibold text-[var(--ui-text-secondary)]",children:"Prop"}),g("th",{className:"px-4 py-2 text-xs font-semibold text-[var(--ui-text-secondary)]",children:"Type"}),g("th",{className:"px-4 py-2 text-xs font-semibold text-[var(--ui-text-secondary)]",children:"Default"}),g("th",{className:"px-4 py-2 text-xs font-semibold text-[var(--ui-text-secondary)]",children:"Description"})]})}),g("tbody",{children:e.map(t=>O("tr",{className:"border-b border-[var(--ui-surface-border)] last:border-b-0",children:[g("td",{className:"px-4 py-2 font-mono text-xs font-medium text-[var(--ui-text-primary)]",children:t.name}),g("td",{className:"px-4 py-2 font-mono text-xs text-[var(--ui-accent-bg)]",children:t.type}),g("td",{className:"px-4 py-2 font-mono text-xs text-[var(--ui-text-muted)]",children:t.default??"\u2014"}),g("td",{className:"px-4 py-2 text-xs text-[var(--ui-text-secondary)]",children:t.description??""})]},t.name))})]})})}function hi({activeGroup:e,activeComponent:t,theme:n,preset:o,setTheme:r,setPreset:a,children:i}){let c=ut(),d=`owoui-theme-${n}`,s=`owoui-preset-${o}`;return g("div",{"data-theme":n,"data-preset":o,className:sn(d,s,"min-h-dvh"),style:{backgroundColor:"var(--ui-canvas-bg)",color:"var(--ui-text-primary)"},children:O("div",{className:"flex h-dvh min-w-0",children:[g("a",{href:"#sb-main",className:"sr-only focus:not-sr-only focus:absolute focus:z-50 focus:rounded focus:bg-[var(--ui-surface-bg)] focus:px-4 focus:py-2 focus:text-sm focus:shadow",children:"Skip to main content"}),O("aside",{className:"flex w-72 shrink-0 flex-col border-r border-[var(--ui-surface-border)] bg-[var(--ui-surface-bg-subtle)]",children:[O("div",{className:"border-b border-[var(--ui-surface-border)] px-4 py-4",children:[O("div",{className:"flex items-center justify-between gap-3",children:[g("a",{href:"#/",className:"text-base font-semibold text-[var(--ui-text-primary)]",children:"owoui Storybook"}),g("span",{className:"rounded-full border border-[var(--ui-surface-border)] px-2 py-1 text-[11px] uppercase tracking-[0.16em] text-[var(--ui-text-muted)]",children:"Static"})]}),g("p",{className:"mt-2 text-sm text-[var(--ui-text-secondary)]",children:"Official standalone component gallery bundled with `@owodesign/owoui`."}),O("div",{className:"mt-4 grid gap-3",children:[O("div",{children:[g("label",{className:"mb-1.5 block text-[11px] font-semibold uppercase tracking-[0.16em] text-[var(--ui-text-muted)]",children:"Theme"}),g(Q,{value:n,onChange:l=>r(l),options:an.map(l=>({value:l,label:l})),size:"sm",ariaLabel:"Theme"})]}),O("div",{children:[g("label",{className:"mb-1.5 block text-[11px] font-semibold uppercase tracking-[0.16em] text-[var(--ui-text-muted)]",children:"Preset"}),g(Q,{value:o,onChange:l=>a(l),options:Bt.map(l=>({value:l,label:l})),size:"sm",ariaLabel:"Preset"})]})]})]}),g("nav",{className:"min-w-0 flex-1 overflow-y-auto overscroll-contain px-3 py-4",children:pt.map(l=>O("div",{className:"mb-5",children:[g("div",{className:"mb-2 px-2 text-xs font-semibold uppercase tracking-[0.14em] text-[var(--ui-text-muted)]",children:Ft[l]}),c[l].map(u=>{let p=u.group===e&&u.componentId===t;return g("a",{href:`#/${u.group}/${u.componentId}`,className:sn("block min-w-0 truncate rounded-md px-3 py-2 text-sm transition-colors",p?"bg-[color-mix(in_srgb,var(--ui-accent-bg)_10%,transparent)] font-medium text-[var(--ui-accent-bg)]":"text-[var(--ui-text-secondary)] hover:bg-[var(--ui-surface-bg-inset)] hover:text-[var(--ui-text-primary)]"),onClick:m=>{m.preventDefault(),bo(u.group,u.componentId)},title:u.componentName,children:u.componentName},u.componentId)})]},l))})]}),g("main",{id:"sb-main",className:"min-w-0 flex-1 overflow-y-auto px-8 py-8",children:g("div",{className:"mx-auto max-w-4xl",children:i})})]})})}function ln(){let e=di(),t=dt(()=>ut(),[]),n=dt(()=>{let l=pt[0],u=t[l]?.[0];return u?{group:u.group,component:u.componentId}:null},[t]),o=_t(e.group,e.component),r=o?.group??n?.group??e.group,a=o?.componentId??n?.component??e.component,[i,c]=Xe(()=>si()),[d,s]=Xe(()=>li());return Ye(()=>{window.localStorage.setItem(fo,i);let l=document.documentElement;l.dataset.theme=i,l.classList.remove(...an.map(u=>`owoui-theme-${u}`)),l.classList.add(`owoui-theme-${i}`)},[i]),Ye(()=>{window.localStorage.setItem(go,d);let l=document.documentElement;l.dataset.preset=d,l.classList.remove(...Bt.map(u=>`owoui-preset-${u}`)),l.classList.add(`owoui-preset-${d}`)},[d]),Ye(()=>{!o&&n&&bo(n.group,n.component)},[o,n]),g(hi,{activeGroup:r,activeComponent:a,theme:i,preset:d,setTheme:c,setPreset:s,children:o?g(Ct,{children:g(Nt,{children:O("div",{children:[O("div",{className:"mb-8",children:[g("h1",{className:"text-balance text-2xl font-semibold text-[var(--color-n900)]",children:o.componentName}),o.description?g("p",{className:"mt-2 text-pretty text-base text-[var(--ui-text-muted)]",children:o.description}):null]}),o.props&&o.props.length>0?O("div",{className:"mb-8",children:[g("h2",{className:"mb-3 text-lg font-semibold text-[var(--ui-text-primary)]",children:"Props"}),g(vi,{props:o.props})]}):null,o.renderPlayground&&o.props&&o.props.length>0?O("div",{className:"mb-8",children:[g("h2",{className:"mb-3 text-lg font-semibold text-[var(--ui-text-primary)]",children:"Playground"}),g(bi,{props:o.props,renderPlayground:o.renderPlayground},`${o.group}-${o.componentId}`)]}):null,g("div",{className:"space-y-8",children:o.stories.map(l=>O("section",{children:[O("div",{className:"mb-3",children:[g("h2",{className:"text-balance text-lg font-semibold text-[var(--ui-text-primary)]",children:l.title}),l.description?g("p",{className:"mt-1 text-pretty text-sm text-[var(--ui-text-muted)]",children:l.description}):null]}),g(ci,{story:l})]},l.id))})]})})}):g("div",{className:"py-12 text-center text-sm text-[var(--ui-text-muted)]",children:g("p",{children:"Component not found."})})})}import{jsx as vo}from"react/jsx-runtime";var ho=document.getElementById("root");if(!ho)throw new Error("Missing #root container for owoui storybook static app");var dn=Ot[0];window.location.hash.length<=1&&dn&&(window.location.hash=`#/${dn.group}/${dn.componentId}`);xi(ho).render(vo(yi,{children:vo(ln,{})}));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>owoui Storybook</title>
|
|
7
|
+
<meta name="color-scheme" content="light dark" />
|
|
8
|
+
<link rel="stylesheet" href="./app.css" />
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
<script type="module" src="./assets/main.js"></script>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
package/dist/tokens.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
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-muted", "--ui-surface-border-strong", "--ui-surface-shadow", "--ui-surface-shadow-strong", "--ui-surface-blur", "--ui-canvas-bg", "--ui-canvas-bg-subtle", "--ui-surface-container", "--ui-surface-container-high", "--ui-surface-container-highest", "--ui-text-primary", "--ui-text-secondary", "--ui-text-muted", "--ui-text-on-accent", "--ui-accent-bg", "--ui-accent-bg-hover", "--ui-accent-bg-muted", "--ui-accent-text", "--ui-accent-border", "--ui-success-bg", "--ui-success-border", "--ui-success-text", "--ui-warning-bg", "--ui-warning-border", "--ui-warning-text", "--ui-danger-bg", "--ui-danger-bg-emphasis", "--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-radius-xl", "--ui-control-radius-2xl", "--ui-control-border-width", "--ui-control-focus-ring", "--ui-control-focus-ring-offset", "--ui-font-heading", "--ui-motion-duration-fast", "--ui-motion-duration-default", "--ui-motion-ease-standard", "--ui-density-compact", "--ui-density-default", "--ui-density-comfortable"];
|
|
2
2
|
type SemanticTokenKey = (typeof semanticTokenKeys)[number];
|
|
3
|
+
declare const themeNames: readonly ["light", "dark"];
|
|
4
|
+
type OwoUiThemeName = (typeof themeNames)[number];
|
|
3
5
|
declare const tokenGroups: readonly [{
|
|
4
6
|
readonly id: "surface";
|
|
5
7
|
readonly label: "Surface";
|
|
@@ -29,8 +31,8 @@ declare const tokenGroups: readonly [{
|
|
|
29
31
|
readonly label: "Motion & Density";
|
|
30
32
|
readonly tokens: readonly ["--ui-motion-duration-fast", "--ui-motion-duration-default", "--ui-motion-ease-standard", "--ui-density-compact", "--ui-density-default", "--ui-density-comfortable"];
|
|
31
33
|
}];
|
|
32
|
-
declare const presetNames: readonly ["default", "
|
|
34
|
+
declare const presetNames: readonly ["default", "flat", "elevated", "glass"];
|
|
33
35
|
type OwoUiPresetName = (typeof presetNames)[number];
|
|
34
36
|
declare const tokenDescriptions: Record<SemanticTokenKey, string>;
|
|
35
37
|
|
|
36
|
-
export { type OwoUiPresetName, type SemanticTokenKey, presetNames, semanticTokenKeys, tokenDescriptions, tokenGroups };
|
|
38
|
+
export { type OwoUiPresetName, type OwoUiThemeName, type SemanticTokenKey, presetNames, semanticTokenKeys, themeNames, tokenDescriptions, tokenGroups };
|
package/dist/tokens.min.js
CHANGED
|
@@ -1 +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-muted","--ui-surface-border-strong","--ui-surface-shadow","--ui-surface-shadow-strong","--ui-surface-blur","--ui-canvas-bg","--ui-canvas-bg-subtle","--ui-surface-container","--ui-surface-container-high","--ui-surface-container-highest","--ui-text-primary","--ui-text-secondary","--ui-text-muted","--ui-text-on-accent","--ui-accent-bg","--ui-accent-bg-hover","--ui-accent-bg-muted","--ui-accent-text","--ui-accent-border","--ui-success-bg","--ui-success-border","--ui-success-text","--ui-warning-bg","--ui-warning-border","--ui-warning-text","--ui-danger-bg","--ui-danger-bg-emphasis","--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-radius-xl","--ui-control-radius-2xl","--ui-control-border-width","--ui-control-focus-ring","--ui-control-focus-ring-offset","--ui-font-heading","--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-muted","--ui-surface-border-strong","--ui-surface-shadow","--ui-surface-shadow-strong","--ui-surface-blur","--ui-canvas-bg","--ui-canvas-bg-subtle","--ui-surface-container","--ui-surface-container-high","--ui-surface-container-highest"]},{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-bg-muted","--ui-accent-text","--ui-accent-border"]},{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-bg-emphasis","--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-radius-xl","--ui-control-radius-2xl","--ui-control-border-width","--ui-control-focus-ring","--ui-control-focus-ring-offset"]},{id:"typography",label:"Typography",tokens:["--ui-font-heading"]},{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","
|
|
1
|
+
var e=["--ui-surface-bg","--ui-surface-bg-subtle","--ui-surface-bg-raised","--ui-surface-bg-inset","--ui-surface-border","--ui-surface-border-muted","--ui-surface-border-strong","--ui-surface-shadow","--ui-surface-shadow-strong","--ui-surface-blur","--ui-canvas-bg","--ui-canvas-bg-subtle","--ui-surface-container","--ui-surface-container-high","--ui-surface-container-highest","--ui-text-primary","--ui-text-secondary","--ui-text-muted","--ui-text-on-accent","--ui-accent-bg","--ui-accent-bg-hover","--ui-accent-bg-muted","--ui-accent-text","--ui-accent-border","--ui-success-bg","--ui-success-border","--ui-success-text","--ui-warning-bg","--ui-warning-border","--ui-warning-text","--ui-danger-bg","--ui-danger-bg-emphasis","--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-radius-xl","--ui-control-radius-2xl","--ui-control-border-width","--ui-control-focus-ring","--ui-control-focus-ring-offset","--ui-font-heading","--ui-motion-duration-fast","--ui-motion-duration-default","--ui-motion-ease-standard","--ui-density-compact","--ui-density-default","--ui-density-comfortable"],r=["light","dark"],t=[{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-muted","--ui-surface-border-strong","--ui-surface-shadow","--ui-surface-shadow-strong","--ui-surface-blur","--ui-canvas-bg","--ui-canvas-bg-subtle","--ui-surface-container","--ui-surface-container-high","--ui-surface-container-highest"]},{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-bg-muted","--ui-accent-text","--ui-accent-border"]},{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-bg-emphasis","--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-radius-xl","--ui-control-radius-2xl","--ui-control-border-width","--ui-control-focus-ring","--ui-control-focus-ring-offset"]},{id:"typography",label:"Typography",tokens:["--ui-font-heading"]},{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"],a={"--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-muted":"Lowest-emphasis border for subtle separators and dividers.","--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-canvas-bg":"Page-level canvas background, distinct from component surfaces.","--ui-canvas-bg-subtle":"Subtle canvas background for secondary page regions.","--ui-surface-container":"Container background for sidebars, panels, and layout regions.","--ui-surface-container-high":"Higher-emphasis container background for nested panels.","--ui-surface-container-highest":"Highest-emphasis container background for deeply nested panels.","--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-bg-muted":"Muted accent background for hover, selected, and highlighted states.","--ui-accent-text":"Readable text color used on accent backgrounds.","--ui-accent-border":"Accent-tinted border for active indicators and emphasis separators.","--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-bg-emphasis":"Stronger danger background for hover, active, or destructive emphasis.","--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-radius-xl":"Extra-large radius for drawers, dialogs, and large containers.","--ui-control-radius-2xl":"Double extra-large radius for sheets and full-page overlays.","--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-font-heading":"Heading font family stack.","--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,r as themeNames,a as tokenDescriptions,t as tokenGroups};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owodesign/owoui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Reusable React UI foundation components and theme presets.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.min.js",
|
|
@@ -38,37 +38,45 @@
|
|
|
38
38
|
},
|
|
39
39
|
"./storybook/catalog.json": "./dist/storybook/catalog.json",
|
|
40
40
|
"./style.css": "./src/style.css",
|
|
41
|
-
"./
|
|
42
|
-
"./
|
|
43
|
-
"./
|
|
44
|
-
"./
|
|
41
|
+
"./theme-light.css": "./src/theme-light.css",
|
|
42
|
+
"./theme-dark.css": "./src/theme-dark.css",
|
|
43
|
+
"./preset-default.css": "./src/preset-default.css",
|
|
44
|
+
"./preset-flat.css": "./src/preset-flat.css",
|
|
45
|
+
"./preset-elevated.css": "./src/preset-elevated.css",
|
|
46
|
+
"./preset-glass.css": "./src/preset-glass.css"
|
|
45
47
|
},
|
|
46
48
|
"files": [
|
|
47
49
|
"dist",
|
|
48
50
|
"src/style.css",
|
|
49
51
|
"src/tokens.css",
|
|
50
|
-
"src/
|
|
51
|
-
"src/
|
|
52
|
-
"src/
|
|
53
|
-
"src/
|
|
52
|
+
"src/theme-light.css",
|
|
53
|
+
"src/theme-dark.css",
|
|
54
|
+
"src/preset-default.css",
|
|
55
|
+
"src/preset-flat.css",
|
|
56
|
+
"src/preset-elevated.css",
|
|
57
|
+
"src/preset-glass.css",
|
|
54
58
|
"src/styles"
|
|
55
59
|
],
|
|
56
60
|
"sideEffects": [
|
|
57
61
|
"./src/style.css",
|
|
58
62
|
"./src/tokens.css",
|
|
59
|
-
"./src/
|
|
60
|
-
"./src/
|
|
61
|
-
"./src/
|
|
62
|
-
"./src/
|
|
63
|
+
"./src/theme-light.css",
|
|
64
|
+
"./src/theme-dark.css",
|
|
65
|
+
"./src/preset-default.css",
|
|
66
|
+
"./src/preset-flat.css",
|
|
67
|
+
"./src/preset-elevated.css",
|
|
68
|
+
"./src/preset-glass.css",
|
|
63
69
|
"./src/styles/**/*.css",
|
|
64
70
|
"./src/storybook/**/*.ts",
|
|
65
71
|
"./src/storybook/**/*.tsx"
|
|
66
72
|
],
|
|
67
73
|
"scripts": {
|
|
68
|
-
"build": "npm run build:lib && npm run build:storybook && npm run build:storybook:catalog",
|
|
74
|
+
"build": "npm run build:lib && npm run build:storybook && npm run build:storybook:catalog && npm run build:storybook:static",
|
|
69
75
|
"build:lib": "tsup",
|
|
70
76
|
"build:storybook": "tsup --config tsup.storybook.config.ts",
|
|
71
77
|
"build:storybook:catalog": "node scripts/build-storybook-catalog.mjs",
|
|
78
|
+
"build:storybook:static:bundle": "tsup --config tsup.storybook.static.config.ts",
|
|
79
|
+
"build:storybook:static": "npm run build:storybook:static:bundle && node scripts/build-storybook-static.mjs",
|
|
72
80
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
73
81
|
"consumer:smoke": "node examples/consumer-smoke.mjs",
|
|
74
82
|
"pack:inspect": "npm_config_cache=/tmp/owoui-npm-cache npm pack --dry-run --json .",
|
|
@@ -86,8 +94,10 @@
|
|
|
86
94
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
87
95
|
},
|
|
88
96
|
"devDependencies": {
|
|
97
|
+
"@tailwindcss/postcss": "^4.2.1",
|
|
89
98
|
"@types/react": "^19.0.0",
|
|
90
99
|
"@types/react-dom": "^19.0.0",
|
|
100
|
+
"postcss": "^8.5.6",
|
|
91
101
|
"tailwindcss": "^4.2.1",
|
|
92
102
|
"tsup": "^8.5.1"
|
|
93
103
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
@import "./tokens.css";
|
|
2
|
+
|
|
3
|
+
:root[data-preset="default"],
|
|
4
|
+
.owoui-preset-default {
|
|
5
|
+
--preset-surface-bg: var(--theme-surface-base);
|
|
6
|
+
--preset-surface-bg-subtle: var(--theme-surface-subtle);
|
|
7
|
+
--preset-surface-bg-raised: var(--theme-surface-raised);
|
|
8
|
+
--preset-surface-bg-inset: var(--theme-surface-inset);
|
|
9
|
+
--preset-surface-border: var(--theme-surface-border);
|
|
10
|
+
--preset-surface-border-muted: var(--theme-surface-border-muted);
|
|
11
|
+
--preset-surface-border-strong: var(--theme-surface-border-strong);
|
|
12
|
+
--preset-surface-shadow: var(--shadow-raised);
|
|
13
|
+
--preset-surface-shadow-strong: var(--shadow-popover);
|
|
14
|
+
--preset-surface-blur: 0px;
|
|
15
|
+
--preset-canvas-bg: var(--theme-surface-canvas);
|
|
16
|
+
--preset-canvas-bg-subtle: var(--theme-canvas-bg-subtle);
|
|
17
|
+
--preset-surface-container: var(--theme-surface-container);
|
|
18
|
+
--preset-surface-container-high: var(--theme-surface-container-high);
|
|
19
|
+
--preset-surface-container-highest: var(--theme-surface-container-highest);
|
|
20
|
+
--preset-control-radius-sm: 0.5rem;
|
|
21
|
+
--preset-control-radius-md: 0.75rem;
|
|
22
|
+
--preset-control-radius-lg: 1rem;
|
|
23
|
+
--preset-control-radius-xl: 1.5rem;
|
|
24
|
+
--preset-control-radius-2xl: 2rem;
|
|
25
|
+
--preset-control-border-width: 1px;
|
|
26
|
+
}
|
|
27
|
+
|