lucent-ui 0.32.1 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Lucent UI
2
2
 
3
- [![CI](https://github.com/rozinashopify/lucent-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/rozinashopify/lucent-ui/actions/workflows/ci.yml)
3
+ [![CI](https://github.com/rozina-hudson/lucent-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/rozina-hudson/lucent-ui/actions/workflows/ci.yml)
4
4
  [![npm](https://img.shields.io/npm/v/lucent-ui)](https://www.npmjs.com/package/lucent-ui)
5
5
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
6
6
 
@@ -1997,7 +1997,7 @@ const sa = {
1997
1997
  // Text
1998
1998
  textPrimary: "#111827",
1999
1999
  textSecondary: "#6b7280",
2000
- textDisabled: "#9ca3af",
2000
+ textDisabled: "#d1d5db",
2001
2001
  textInverse: "#ffffff",
2002
2002
  // Accent (monochrome default — near-black for universal, high-contrast out of the box)
2003
2003
  // Use `brandTokens` to opt in to the gold palette.
@@ -2230,7 +2230,7 @@ function nt(e, t, s) {
2230
2230
  const r = La(t.bgBase, n);
2231
2231
  a.surface = r, "surfaceSecondary" in e || (a.surfaceSecondary = z(r, n ? -0.04 : 0.03)), "surfaceRaised" in e || (a.surfaceRaised = z(r, n ? 0 : 0.06)), "surfaceOverlay" in e || (a.surfaceOverlay = z(r, n ? 0 : 0.06));
2232
2232
  }
2233
- return "surface" in e && ("surfaceSecondary" in e || (a.surfaceSecondary = z(t.surface, n ? -0.04 : 0.03)), "surfaceRaised" in e || (a.surfaceRaised = z(t.surface, n ? 0 : 0.06)), "surfaceOverlay" in e || (a.surfaceOverlay = z(t.surface, n ? 0 : 0.06))), "textPrimary" in e && ("textSecondary" in e || (a.textSecondary = z(t.textPrimary, n ? 0.2 : -0.15)), "textDisabled" in e || (a.textDisabled = z(t.textPrimary, n ? 0.35 : -0.4))), "accentDefault" in e && ("accentHover" in e || (a.accentHover = z(t.accentDefault, n ? 0.05 : -0.07)), "accentSubtle" in e || (a.accentSubtle = z(t.accentDefault, n ? 0.85 : -0.6))), "successDefault" in e && ("successSubtle" in e || (a.successSubtle = ce(t.successDefault, n)), "successText" in e || (a.successText = ie(t.successDefault, n))), "warningDefault" in e && ("warningSubtle" in e || (a.warningSubtle = ce(t.warningDefault, n)), "warningText" in e || (a.warningText = ie(t.warningDefault, n))), "dangerDefault" in e && ("dangerHover" in e || (a.dangerHover = z(t.dangerDefault, n ? 0.05 : -0.07)), "dangerSubtle" in e || (a.dangerSubtle = ce(t.dangerDefault, n)), "dangerText" in e || (a.dangerText = ie(t.dangerDefault, n))), "infoDefault" in e && ("infoSubtle" in e || (a.infoSubtle = ce(t.infoDefault, n)), "infoText" in e || (a.infoText = ie(t.infoDefault, n))), a;
2233
+ return "surface" in e && ("surfaceSecondary" in e || (a.surfaceSecondary = z(t.surface, n ? -0.04 : 0.03)), "surfaceRaised" in e || (a.surfaceRaised = z(t.surface, n ? 0 : 0.06)), "surfaceOverlay" in e || (a.surfaceOverlay = z(t.surface, n ? 0 : 0.06))), "textPrimary" in e && ("textSecondary" in e || (a.textSecondary = z(t.textPrimary, n ? 0.2 : -0.15)), "textDisabled" in e || (a.textDisabled = z(t.textPrimary, n ? 0.58 : -0.62))), "accentDefault" in e && ("accentHover" in e || (a.accentHover = z(t.accentDefault, n ? 0.05 : -0.07)), "accentSubtle" in e || (a.accentSubtle = z(t.accentDefault, n ? 0.85 : -0.6))), "successDefault" in e && ("successSubtle" in e || (a.successSubtle = ce(t.successDefault, n)), "successText" in e || (a.successText = ie(t.successDefault, n))), "warningDefault" in e && ("warningSubtle" in e || (a.warningSubtle = ce(t.warningDefault, n)), "warningText" in e || (a.warningText = ie(t.warningDefault, n))), "dangerDefault" in e && ("dangerHover" in e || (a.dangerHover = z(t.dangerDefault, n ? 0.05 : -0.07)), "dangerSubtle" in e || (a.dangerSubtle = ce(t.dangerDefault, n)), "dangerText" in e || (a.dangerText = ie(t.dangerDefault, n))), "infoDefault" in e && ("infoSubtle" in e || (a.infoSubtle = ce(t.infoDefault, n)), "infoText" in e || (a.infoText = ie(t.infoDefault, n))), a;
2234
2234
  }
2235
2235
  function rt(e, t = "light") {
2236
2236
  const a = { ...t === "dark" ? tt : he, ...e }, n = nt(e, a, t), r = t === "light" ? z(a.accentDefault, -0.15) : z(a.accentDefault, 0.15);
@@ -102,8 +102,8 @@
102
102
  .lucent-cp-field::-webkit-outer-spin-button,
103
103
  .lucent-cp-field::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
104
104
  .lucent-cp-field { -moz-appearance: textfield; }
105
- `}),s&&!n&&l.jsx("label",{htmlFor:`${v}-swatch`,style:{fontSize:a==="sm"?"var(--lucent-font-size-xs)":"var(--lucent-font-size-sm)",fontWeight:"var(--lucent-font-weight-medium)",color:r?"var(--lucent-text-disabled)":"var(--lucent-text-primary)",fontFamily:"var(--lucent-font-family-base)"},children:s}),l.jsx(ne,{id:`${v}-swatch`,color:`rgba(${C.r},${C.g},${C.b},${h.a})`,shape:"square",showCheckerboard:!0,disabled:r,onClick:()=>S(c=>!c),"aria-expanded":p,"aria-haspopup":"dialog",style:{width:f,height:f,borderRadius:a==="sm"?"var(--lucent-radius-md)":"var(--lucent-radius-lg)",boxShadow:p?"inset 0 0 0 2px var(--lucent-accent-border), 0 0 0 3px var(--lucent-accent-subtle)":"inset 0 0 0 1px rgba(0,0,0,0.2)"}}),s&&n&&l.jsx("label",{htmlFor:`${v}-swatch`,style:{fontSize:a==="sm"?"var(--lucent-font-size-xs)":"var(--lucent-font-size-sm)",fontWeight:"var(--lucent-font-weight-medium)",color:r?"var(--lucent-text-disabled)":"var(--lucent-text-primary)",fontFamily:"var(--lucent-font-family-base)",cursor:"pointer"},children:s}),p&&Rt.createPortal(l.jsxs("div",{ref:H,role:"dialog","aria-label":"Color picker",style:{position:"fixed",top:Y.top,left:Y.left,zIndex:999999,background:"color-mix(in srgb, var(--lucent-surface-overlay) 85%, transparent)",backdropFilter:"blur(6px)",WebkitBackdropFilter:"blur(6px)",border:"1px solid color-mix(in srgb, var(--lucent-accent-default) 15%, var(--lucent-border-default))",borderRadius:"var(--lucent-radius-xl)",boxShadow:"0 0 24px -4px color-mix(in srgb, var(--lucent-accent-default) 12%, transparent), var(--lucent-shadow-md)",width:280,overflow:"hidden",display:"flex",flexDirection:"column"},children:[l.jsxs("div",{ref:E,style:{position:"relative",height:160,background:`hsl(${h.h}, 100%, 50%)`,cursor:"crosshair",userSelect:"none",flexShrink:0},onPointerDown:c=>{c.currentTarget.setPointerCapture(c.pointerId),W(c)},onPointerMove:c=>{c.buttons>0&&W(c)},children:[l.jsx("div",{style:{position:"absolute",inset:0,background:"linear-gradient(to right, #fff, transparent)"}}),l.jsx("div",{style:{position:"absolute",inset:0,background:"linear-gradient(to bottom, transparent, #000)"}}),l.jsx("div",{style:{position:"absolute",left:`${h.s}%`,top:`${100-h.v}%`,transform:"translate(-50%, -50%)",width:14,height:14,borderRadius:"50%",border:"2px solid #fff",boxShadow:"0 0 0 1px rgba(0,0,0,0.25), 0 2px 4px rgba(0,0,0,0.35)",pointerEvents:"none"}})]}),l.jsxs("div",{style:{padding:12,display:"flex",flexDirection:"column",gap:10},children:[l.jsxs("div",{style:{display:"flex",gap:10,alignItems:"center"},children:[l.jsx(ne,{color:`rgba(${C.r},${C.g},${C.b},${h.a})`,shape:"square",showCheckerboard:!0,style:{width:44,height:44,borderRadius:8}}),l.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:8},children:[l.jsx(Qe,{value:h.h,min:0,max:360,onChange:c=>B({...h,h:Math.round(c)}),trackStyle:{background:"linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%)"},formatTooltip:c=>`${Math.round(c)}°`}),l.jsxs("div",{style:{position:"relative",borderRadius:6,overflow:"hidden"},children:[l.jsx("div",{style:{position:"absolute",inset:0,backgroundImage:xa,backgroundSize:"8px 8px",backgroundPosition:"0 0, 0 4px, 4px -4px, -4px 0",backgroundColor:"#fff"}}),l.jsx("div",{style:{position:"absolute",inset:0,background:`linear-gradient(to right, transparent, ${ye})`}}),l.jsx(Qe,{value:h.a,min:0,max:1,onChange:c=>B({...h,a:Math.round(c*100)/100}),trackStyle:{background:"transparent",position:"relative",zIndex:1},formatTooltip:c=>`${Math.round(c*100)}%`})]})]})]}),l.jsx(Be,{size:"sm",value:M,onChange:c=>k(c),options:w.map(({id:c,label:m})=>({value:c,label:m}))}),M==="hex"&&l.jsxs("div",{style:{display:"flex",gap:6,alignItems:"center"},children:[l.jsx(ze,{variant:"secondary",size:"sm",onClick:U,disabled:!R,title:R?"Pick color from screen":"Not supported in this browser",leftIcon:l.jsx(ma,{}),style:{flexShrink:0,paddingLeft:8,paddingRight:8}}),l.jsx(K,{size:"sm",prefix:"#",value:$,onChange:c=>{const m=c.target.value.replace("#","");A(m.toUpperCase());const z=de(`#${m}`);if(z){const I=X(z);D(I),t==null||t(je(z))}},spellCheck:!1,placeholder:"000000",maxLength:8,style:{flex:1}}),l.jsx(K,{size:"sm",type:"number",suffix:"%",value:_,min:0,max:100,onChange:c=>{const m=+c.target.value;!isNaN(m)&&m>=0&&m<=100&&B({...h,a:m/100})},className:"lucent-cp-field",style:{width:68,flexShrink:0}})]}),M==="rgb"&&l.jsx("div",{style:{display:"flex",gap:6},children:[{label:"R",val:C.r,max:255,fn:c=>B(X({...C,r:c}))},{label:"G",val:C.g,max:255,fn:c=>B(X({...C,g:c}))},{label:"B",val:C.b,max:255,fn:c=>B(X({...C,b:c}))},{label:"A",val:_,max:100,fn:c=>B({...h,a:c/100})}].map(({label:c,val:m,max:z,fn:I})=>l.jsx(K,{size:"sm",type:"number",prefix:c,value:m,min:0,max:z,onChange:F=>{const P=+F.target.value;!isNaN(P)&&P>=0&&P<=z&&I(P)},className:"lucent-cp-field",style:{flex:1}},c))}),M==="hsl"&&l.jsx("div",{style:{display:"flex",gap:6},children:[{label:"H",val:O.h,max:360,fn:c=>{const{r:m,g:z,b:I}=ge(c,O.s,O.l);B(X({r:m,g:z,b:I,a:h.a}))}},{label:"S",val:O.s,max:100,fn:c=>{const{r:m,g:z,b:I}=ge(O.h,c,O.l);B(X({r:m,g:z,b:I,a:h.a}))}},{label:"L",val:O.l,max:100,fn:c=>{const{r:m,g:z,b:I}=ge(O.h,O.s,c);B(X({r:m,g:z,b:I,a:h.a}))}},{label:"A",val:_,max:100,fn:c=>B({...h,a:c/100})}].map(({label:c,val:m,max:z,fn:I})=>l.jsx(K,{size:"sm",type:"number",prefix:c,value:m,min:0,max:z,onChange:F=>{const P=+F.target.value;!isNaN(P)&&P>=0&&P<=z&&I(P)},className:"lucent-cp-field",style:{flex:1}},c))}),M==="hsb"&&l.jsx("div",{style:{display:"flex",gap:6},children:[{label:"H",val:h.h,max:360,fn:c=>B({...h,h:c})},{label:"S",val:h.s,max:100,fn:c=>B({...h,s:c})},{label:"B",val:h.v,max:100,fn:c=>B({...h,v:c})},{label:"A",val:_,max:100,fn:c=>B({...h,a:c/100})}].map(({label:c,val:m,max:z,fn:I})=>l.jsx(K,{size:"sm",type:"number",prefix:c,value:m,min:0,max:z,onChange:F=>{const P=+F.target.value;!isNaN(P)&&P>=0&&P<=z&&I(P)},className:"lucent-cp-field",style:{flex:1}},c))}),o.length>0&&l.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:8},children:[o.length>1&&l.jsx(Ie,{size:"sm",value:String(y),onChange:c=>x(Number(c.target.value)),options:o.map((c,m)=>({value:String(m),label:c.label}))}),o.length===1&&l.jsx("span",{style:{fontSize:"var(--lucent-font-size-xs)",fontWeight:"var(--lucent-font-weight-medium)",color:"var(--lucent-text-secondary)",fontFamily:"var(--lucent-font-family-base)"},children:(T=o[0])==null?void 0:T.label}),l.jsx("div",{style:{display:"flex",gap:6,flexWrap:"wrap"},children:(((L=o[y])==null?void 0:L.colors)??[]).map(c=>{const m=Re(c).toLowerCase()===ae.slice(0,7).toLowerCase();return l.jsx(ne,{color:c,selected:m,onClick:()=>B(X(rt(c)))},c)})})]})]})]}),i??document.body)]})}ot.displayName="ColorPicker";function ha({tabs:e,defaultValue:t,value:s,onChange:a,variant:n="underline",style:r}){var _;const o=s!==void 0,[i,d]=b.useState(t??((_=e[0])==null?void 0:_.value)??""),u=o?s:i,[f,g]=b.useState(null),v=b.useRef([]),[p,S]=b.useState(null),M=b.useRef(!1),k=n==="pills",y=b.useRef(null),x=b.useRef(null),h=b.useRef(null),[D,$]=b.useState(e.length),[A,N]=b.useState(!1),[E,H]=b.useState(!1),[Y,V]=b.useState(null),B=e.slice(0,D),W=e.slice(D),U=W.length>0,C=W.some(w=>w.value===u),O=()=>{if(C){S(null);return}const w=e.findIndex((T,L)=>L<D&&T.value===u),R=v.current[w];if(R){if(k){const T=R.querySelector("span");if(!T)return;S({left:T.offsetLeft+R.offsetLeft,width:T.offsetWidth,animate:M.current})}else S({left:R.offsetLeft,width:R.offsetWidth,animate:M.current});M.current=!0}};b.useLayoutEffect(()=>{O(),document.fonts.ready.then(O)},[u,D,k]),b.useEffect(()=>{const w=y.current;if(!w)return;const R=()=>{const m=w.clientWidth,z=70;let I=0,F=0;for(let P=0;P<e.length;P++){const Z=v.current[P];if(!Z){F++;continue}const J=Z.offsetWidth;if(P<e.length-1){if(I+J+z>m)break}else if(I+J>m)break;I+=J,F++}if(F>=e.length-1&&F<e.length){let P=0;for(let Z=0;Z<e.length;Z++){const J=v.current[Z];J&&(P+=J.offsetWidth)}P<=m&&(F=e.length)}$(F<1?1:F)};let T;(()=>{T=requestAnimationFrame(()=>{T=requestAnimationFrame(R)})})();const c=new ResizeObserver(R);return c.observe(w),()=>{c.disconnect(),cancelAnimationFrame(T)}},[e]),b.useEffect(()=>{if(!A)return;const w=R=>{h.current&&!h.current.contains(R.target)&&x.current&&!x.current.contains(R.target)&&(N(!1),V(null))};return document.addEventListener("mousedown",w),()=>document.removeEventListener("mousedown",w)},[A]);const ae=w=>{o||d(w),a==null||a(w)},ye=(w,R)=>{var m;const T=B.map((z,I)=>z.disabled?-1:I).filter(z=>z!==-1),L=T.indexOf(R);let c=-1;w.key==="ArrowRight"&&(c=T[(L+1)%T.length]??-1),w.key==="ArrowLeft"&&(c=T[(L-1+T.length)%T.length]??-1),w.key==="Home"&&(c=T[0]??-1),w.key==="End"&&(c=T[T.length-1]??-1),c!==-1&&(w.preventDefault(),(m=v.current[c])==null||m.focus(),ae(B[c].value))};return l.jsxs("div",{style:{display:"flex",flexDirection:"column",position:"relative",...r},children:[l.jsxs("div",{ref:y,role:"tablist",style:{position:"relative",display:"flex",overflow:"hidden",...k?{padding:"var(--lucent-space-1)"}:{borderBottom:"1px solid var(--lucent-border-default)"}},children:[e.map((w,R)=>{const T=R<D,L=w.value===u,c=w.disabled??!1;return l.jsxs("button",{ref:m=>{v.current[R]=m},role:"tab","aria-selected":L,"aria-controls":`lucent-tabpanel-${w.value}`,id:`lucent-tab-${w.value}`,disabled:c,tabIndex:L&&T?0:-1,onClick:()=>{c||ae(w.value)},onKeyDown:m=>ye(m,R),onMouseEnter:()=>{!c&&T&&g(R)},onMouseLeave:()=>g(null),style:{padding:k?"var(--lucent-space-1) var(--lucent-space-2)":"var(--lucent-space-1) var(--lucent-space-2) var(--lucent-space-3)",background:"none",border:"none",cursor:c?"not-allowed":"pointer",fontFamily:"var(--lucent-font-family-base)",fontSize:"var(--lucent-font-size-md)",fontWeight:L?"var(--lucent-font-weight-medium)":"var(--lucent-font-weight-regular)",color:c?"var(--lucent-text-disabled)":k&&L?"var(--lucent-accent-fg)":L?"var(--lucent-text-primary)":"var(--lucent-text-secondary)",transition:"color var(--lucent-duration-fast) var(--lucent-easing-default)",whiteSpace:"nowrap",outline:"none",position:T?"relative":"absolute",zIndex:L?1:0,...T?{}:{visibility:"hidden",pointerEvents:"none",left:-9999}},children:[l.jsx("span",{style:{display:"block",padding:"var(--lucent-space-1) var(--lucent-space-3)",borderRadius:"var(--lucent-radius-md)",background:!k&&f===R&&!L&&!c?"var(--lucent-surface-secondary)":"transparent",transition:"background var(--lucent-duration-fast) var(--lucent-easing-default)"},children:w.label}),k&&f===R&&!L&&!c&&T&&l.jsx("span",{"aria-hidden":!0,style:{position:"absolute",top:0,bottom:0,left:0,right:0,borderRadius:"var(--lucent-radius-md)",background:"var(--lucent-surface-secondary)",zIndex:-1,transition:"background var(--lucent-duration-fast) var(--lucent-easing-default)"}})]},w.value)}),U&&l.jsx("button",{ref:x,onClick:()=>N(w=>!w),onMouseEnter:()=>H(!0),onMouseLeave:()=>H(!1),style:{padding:k?"var(--lucent-space-1) var(--lucent-space-2)":"var(--lucent-space-1) var(--lucent-space-2) var(--lucent-space-3)",background:"none",border:"none",cursor:"pointer",fontFamily:"var(--lucent-font-family-base)",fontSize:"var(--lucent-font-size-md)",fontWeight:C?"var(--lucent-font-weight-medium)":"var(--lucent-font-weight-regular)",color:C?"var(--lucent-text-primary)":"var(--lucent-text-secondary)",whiteSpace:"nowrap",outline:"none",position:"relative",flexShrink:0},children:l.jsx("span",{style:{display:"block",padding:"var(--lucent-space-1) var(--lucent-space-3)",borderRadius:"var(--lucent-radius-md)",background:E?"var(--lucent-surface-secondary)":"transparent",transition:"background var(--lucent-duration-fast) var(--lucent-easing-default)"},children:"More…"})}),p!=null&&l.jsx("span",{"aria-hidden":!0,style:k?{position:"absolute",top:"var(--lucent-space-1)",bottom:"var(--lucent-space-1)",left:p.left,width:p.width,background:"var(--lucent-accent-default)",borderRadius:"var(--lucent-radius-md)",transition:p.animate?"left 220ms var(--lucent-easing-default), width 220ms var(--lucent-easing-default)":"none"}:{position:"absolute",bottom:0,left:p.left,width:p.width,height:2,background:"var(--lucent-accent-default)",borderRadius:"var(--lucent-radius-sm)",transition:p.animate?"left 220ms var(--lucent-easing-default), width 220ms var(--lucent-easing-default)":"none"}})]}),U&&A&&l.jsx("div",{ref:h,style:{position:"absolute",top:"100%",right:0,zIndex:50,marginTop:"var(--lucent-space-1)",background:"var(--lucent-surface-primary)",border:"1px solid var(--lucent-border-default)",borderRadius:"var(--lucent-radius-md)",boxShadow:"var(--lucent-shadow-md)",padding:"var(--lucent-space-1) 0",minWidth:140},children:W.map((w,R)=>{const T=w.value===u,L=w.disabled??!1,c=Y===R;return l.jsx("button",{disabled:L,onClick:()=>{L||(ae(w.value),N(!1))},onMouseEnter:()=>{L||V(R)},onMouseLeave:()=>V(null),style:{display:"block",width:"100%",padding:"var(--lucent-space-2) var(--lucent-space-4)",background:T||c?"var(--lucent-surface-secondary)":"none",border:"none",cursor:L?"not-allowed":"pointer",fontFamily:"var(--lucent-font-family-base)",fontSize:"var(--lucent-font-size-md)",fontWeight:T?"var(--lucent-font-weight-medium)":"var(--lucent-font-weight-regular)",color:L?"var(--lucent-text-disabled)":T||c?"var(--lucent-text-primary)":"var(--lucent-text-secondary)",textAlign:"left",outline:"none",transition:"background var(--lucent-duration-fast) var(--lucent-easing-default), color var(--lucent-duration-fast) var(--lucent-easing-default)"},children:w.label},w.value)})}),e.some(w=>w.content!=null)&&e.map(w=>l.jsx("div",{role:"tabpanel",id:`lucent-tabpanel-${w.value}`,"aria-labelledby":`lucent-tab-${w.value}`,hidden:w.value!==u,style:{padding:"var(--lucent-space-4) 0",outline:"none"},tabIndex:0,children:w.content},w.value))]})}const va={fontFamilyBase:'"DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',fontFamilyMono:'"DM Mono", "Fira Code", "Cascadia Code", monospace',fontFamilyDisplay:'"Georama", "DM Sans", sans-serif',fontSizeXs:"0.75rem",fontSizeSm:"0.875rem",fontSizeMd:"1rem",fontSizeLg:"1.125rem",fontSizeXl:"1.25rem",fontSize2xl:"1.5rem",fontSize3xl:"1.875rem",fontWeightRegular:"400",fontWeightMedium:"500",fontWeightSemibold:"600",fontWeightBold:"700",lineHeightTight:"1.25",lineHeightBase:"1.5",lineHeightRelaxed:"1.75",letterSpacingTight:"-0.02em",letterSpacingBase:"0em",letterSpacingWide:"0.04em"},ya={space0:"0px",space1:"0.25rem",space2:"0.5rem",space3:"0.75rem",space4:"1rem",space5:"1.25rem",space6:"1.5rem",space8:"2rem",space10:"2.5rem",space12:"3rem",space16:"4rem",space20:"5rem",space24:"6rem"},wa={radiusNone:"0px",radiusSm:"0.25rem",radiusMd:"0.375rem",radiusLg:"0.5rem",radiusXl:"0.75rem",radiusFull:"9999px"},Sa={durationFast:"100ms",durationBase:"200ms",durationSlow:"350ms",easingDefault:"cubic-bezier(0.4, 0, 0.2, 1)",easingEmphasized:"cubic-bezier(0.2, 0, 0, 1)",easingDecelerate:"cubic-bezier(0, 0, 0.2, 1)"},lt={shadowNone:"none",shadowSm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",shadowMd:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",shadowLg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",shadowXl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)"},ct={shadowNone:"none",shadowSm:"inset 0 1px 0 0 rgba(255, 255, 255, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.2)",shadowMd:"inset 0 1px 0 0 rgba(255, 255, 255, 0.06), 0 2px 4px -1px rgba(0, 0, 0, 0.25)",shadowLg:"inset 0 1px 0 0 rgba(255, 255, 255, 0.08), 0 4px 8px -2px rgba(0, 0, 0, 0.3)",shadowXl:"inset 0 1px 0 0 rgba(255, 255, 255, 0.1), 0 8px 16px -4px rgba(0, 0, 0, 0.35)"},re={...va,...ya,...wa,...Sa,...lt,bgBase:"#ffffff",bgSubtle:"#f9fafb",bgOverlay:"rgb(0 0 0 / 0.4)",surface:"#ffffff",surfaceSecondary:"#f3f4f6",surfaceRaised:"#ffffff",surfaceOverlay:"#ffffff",surfaceTint:"#f2f2f2",borderDefault:"#e5e7eb",borderSubtle:"#f3f4f6",borderStrong:"#9ca3af",controlTrack:"#d1d5db",textPrimary:"#111827",textSecondary:"#6b7280",textDisabled:"#9ca3af",textInverse:"#ffffff",accentDefault:"#111827",accentHover:"#1f2937",accentSubtle:"#f3f4f6",accentBorder:"#111827",accentFg:"#ffffff",successDefault:"#16a34a",successSubtle:"#f0fdf4",successText:"#15803d",warningDefault:"#d97706",warningSubtle:"#fffbeb",warningText:"#b45309",dangerDefault:"#dc2626",dangerHover:"#b91c1c",dangerSubtle:"#fef2f2",dangerText:"#b91c1c",infoDefault:"#2563eb",infoSubtle:"#eff6ff",infoText:"#1d4ed8"};function ka(e){const t=parseInt(e.slice(1,3),16),s=parseInt(e.slice(3,5),16),a=parseInt(e.slice(5,7),16);return{r:t,g:s,b:a}}function Da({r:e,g:t,b:s}){const a=n=>n.toString(16).padStart(2,"0");return`#${a(e)}${a(t)}${a(s)}`}function G(e){const{r:t,g:s,b:a}=ka(e),n=t/255,r=s/255,o=a/255,i=Math.max(n,r,o),d=Math.min(n,r,o);let u=0,f=0;const g=(i+d)/2;if(i!==d){const v=i-d;switch(f=g>.5?v/(2-i-d):v/(i+d),i){case n:u=(r-o)/v+(r<o?6:0);break;case r:u=(o-n)/v+2;break;case o:u=(n-r)/v+4;break}u/=6}return[u*360,f,g]}function q(e,t,s){e=(e%360+360)%360,t=Math.min(1,Math.max(0,t)),s=Math.min(1,Math.max(0,s));const a=(1-Math.abs(2*s-1))*t,n=a*(1-Math.abs(e/60%2-1)),r=s-a/2;let o=0,i=0,d=0;return e<60?(o=a,i=n):e<120?(o=n,i=a):e<180?(i=a,d=n):e<240?(i=n,d=a):e<300?(o=n,d=a):(o=a,d=n),Da({r:Math.round((o+r)*255),g:Math.round((i+r)*255),b:Math.round((d+r)*255)})}function j(e,t){const[s,a,n]=G(e);return q(s,a,Math.min(1,Math.max(0,n+t)))}const Ma=222,ja=.12;function it(e,t){return t<.04?[Ma,ja]:[e,t]}function Ta(e){const[t,s,a]=G(e),[n,r]=it(t,s);return q(n,r,Math.max(.04,Math.min(.2,.07+(1-a))))}function ke(e){const[t,s,a]=G(e),[n,r]=it(t,s);return q(n,r,Math.max(.06,Math.min(.5,(1-a)*.6+.06)))}function De(e){const[t,s,a]=G(e);return q(t,s,Math.max(.04,Math.min(.97,1-a+.04)))}function Me(e){const[t,s,a]=G(e);return q(t,s,Math.max(.02,Math.min(.98,1-a)))}function ut(e){const t=Ta(e.bgBase),[s,a,n]=G(t),r=o=>q(s,a,Math.min(.25,n+o));return{...e,...ct,bgBase:t,bgSubtle:r(.02),bgOverlay:"rgb(0 0 0 / 0.6)",surface:r(.02),surfaceSecondary:r(.05),surfaceRaised:r(.08),surfaceOverlay:r(.08),surfaceTint:r(.03),borderDefault:ke(e.borderDefault),borderSubtle:ke(e.borderSubtle),borderStrong:ke(e.borderStrong),controlTrack:r(.1),textPrimary:De(e.textPrimary),textSecondary:De(e.textSecondary),textDisabled:De(e.textDisabled),textInverse:t,accentDefault:Me(e.accentDefault),accentHover:Me(e.accentHover),accentSubtle:Me(e.accentSubtle),accentBorder:e.accentBorder,accentFg:e.accentFg,successDefault:j(e.successDefault,.1),successSubtle:j(e.successDefault,-.25),successText:j(e.successText,.15),warningDefault:j(e.warningDefault,.1),warningSubtle:j(e.warningDefault,-.25),warningText:j(e.warningText,.15),dangerDefault:j(e.dangerDefault,.1),dangerHover:j(e.dangerHover,.1),dangerSubtle:j(e.dangerDefault,-.25),dangerText:j(e.dangerText,.15),infoDefault:j(e.infoDefault,.1),infoSubtle:j(e.infoDefault,-.25),infoText:j(e.infoText,.15)}}const $e=ut(re);function dt(e){return"--lucent-"+e.replace(/([A-Z])/g,t=>`-${t.toLowerCase()}`).replace(/([a-z])(\d)/g,(t,s,a)=>`${s}-${a}`)}function ft(e,t=":root"){const s=Object.entries(e).map(([a,n])=>` ${dt(a)}: ${n};`).join(`
105
+ `}),s&&!n&&l.jsx("label",{htmlFor:`${v}-swatch`,style:{fontSize:a==="sm"?"var(--lucent-font-size-xs)":"var(--lucent-font-size-sm)",fontWeight:"var(--lucent-font-weight-medium)",color:r?"var(--lucent-text-disabled)":"var(--lucent-text-primary)",fontFamily:"var(--lucent-font-family-base)"},children:s}),l.jsx(ne,{id:`${v}-swatch`,color:`rgba(${C.r},${C.g},${C.b},${h.a})`,shape:"square",showCheckerboard:!0,disabled:r,onClick:()=>S(c=>!c),"aria-expanded":p,"aria-haspopup":"dialog",style:{width:f,height:f,borderRadius:a==="sm"?"var(--lucent-radius-md)":"var(--lucent-radius-lg)",boxShadow:p?"inset 0 0 0 2px var(--lucent-accent-border), 0 0 0 3px var(--lucent-accent-subtle)":"inset 0 0 0 1px rgba(0,0,0,0.2)"}}),s&&n&&l.jsx("label",{htmlFor:`${v}-swatch`,style:{fontSize:a==="sm"?"var(--lucent-font-size-xs)":"var(--lucent-font-size-sm)",fontWeight:"var(--lucent-font-weight-medium)",color:r?"var(--lucent-text-disabled)":"var(--lucent-text-primary)",fontFamily:"var(--lucent-font-family-base)",cursor:"pointer"},children:s}),p&&Rt.createPortal(l.jsxs("div",{ref:H,role:"dialog","aria-label":"Color picker",style:{position:"fixed",top:Y.top,left:Y.left,zIndex:999999,background:"color-mix(in srgb, var(--lucent-surface-overlay) 85%, transparent)",backdropFilter:"blur(6px)",WebkitBackdropFilter:"blur(6px)",border:"1px solid color-mix(in srgb, var(--lucent-accent-default) 15%, var(--lucent-border-default))",borderRadius:"var(--lucent-radius-xl)",boxShadow:"0 0 24px -4px color-mix(in srgb, var(--lucent-accent-default) 12%, transparent), var(--lucent-shadow-md)",width:280,overflow:"hidden",display:"flex",flexDirection:"column"},children:[l.jsxs("div",{ref:E,style:{position:"relative",height:160,background:`hsl(${h.h}, 100%, 50%)`,cursor:"crosshair",userSelect:"none",flexShrink:0},onPointerDown:c=>{c.currentTarget.setPointerCapture(c.pointerId),W(c)},onPointerMove:c=>{c.buttons>0&&W(c)},children:[l.jsx("div",{style:{position:"absolute",inset:0,background:"linear-gradient(to right, #fff, transparent)"}}),l.jsx("div",{style:{position:"absolute",inset:0,background:"linear-gradient(to bottom, transparent, #000)"}}),l.jsx("div",{style:{position:"absolute",left:`${h.s}%`,top:`${100-h.v}%`,transform:"translate(-50%, -50%)",width:14,height:14,borderRadius:"50%",border:"2px solid #fff",boxShadow:"0 0 0 1px rgba(0,0,0,0.25), 0 2px 4px rgba(0,0,0,0.35)",pointerEvents:"none"}})]}),l.jsxs("div",{style:{padding:12,display:"flex",flexDirection:"column",gap:10},children:[l.jsxs("div",{style:{display:"flex",gap:10,alignItems:"center"},children:[l.jsx(ne,{color:`rgba(${C.r},${C.g},${C.b},${h.a})`,shape:"square",showCheckerboard:!0,style:{width:44,height:44,borderRadius:8}}),l.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:8},children:[l.jsx(Qe,{value:h.h,min:0,max:360,onChange:c=>B({...h,h:Math.round(c)}),trackStyle:{background:"linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%)"},formatTooltip:c=>`${Math.round(c)}°`}),l.jsxs("div",{style:{position:"relative",borderRadius:6,overflow:"hidden"},children:[l.jsx("div",{style:{position:"absolute",inset:0,backgroundImage:xa,backgroundSize:"8px 8px",backgroundPosition:"0 0, 0 4px, 4px -4px, -4px 0",backgroundColor:"#fff"}}),l.jsx("div",{style:{position:"absolute",inset:0,background:`linear-gradient(to right, transparent, ${ye})`}}),l.jsx(Qe,{value:h.a,min:0,max:1,onChange:c=>B({...h,a:Math.round(c*100)/100}),trackStyle:{background:"transparent",position:"relative",zIndex:1},formatTooltip:c=>`${Math.round(c*100)}%`})]})]})]}),l.jsx(Be,{size:"sm",value:M,onChange:c=>k(c),options:w.map(({id:c,label:m})=>({value:c,label:m}))}),M==="hex"&&l.jsxs("div",{style:{display:"flex",gap:6,alignItems:"center"},children:[l.jsx(ze,{variant:"secondary",size:"sm",onClick:U,disabled:!R,title:R?"Pick color from screen":"Not supported in this browser",leftIcon:l.jsx(ma,{}),style:{flexShrink:0,paddingLeft:8,paddingRight:8}}),l.jsx(K,{size:"sm",prefix:"#",value:$,onChange:c=>{const m=c.target.value.replace("#","");A(m.toUpperCase());const z=de(`#${m}`);if(z){const I=X(z);D(I),t==null||t(je(z))}},spellCheck:!1,placeholder:"000000",maxLength:8,style:{flex:1}}),l.jsx(K,{size:"sm",type:"number",suffix:"%",value:_,min:0,max:100,onChange:c=>{const m=+c.target.value;!isNaN(m)&&m>=0&&m<=100&&B({...h,a:m/100})},className:"lucent-cp-field",style:{width:68,flexShrink:0}})]}),M==="rgb"&&l.jsx("div",{style:{display:"flex",gap:6},children:[{label:"R",val:C.r,max:255,fn:c=>B(X({...C,r:c}))},{label:"G",val:C.g,max:255,fn:c=>B(X({...C,g:c}))},{label:"B",val:C.b,max:255,fn:c=>B(X({...C,b:c}))},{label:"A",val:_,max:100,fn:c=>B({...h,a:c/100})}].map(({label:c,val:m,max:z,fn:I})=>l.jsx(K,{size:"sm",type:"number",prefix:c,value:m,min:0,max:z,onChange:F=>{const P=+F.target.value;!isNaN(P)&&P>=0&&P<=z&&I(P)},className:"lucent-cp-field",style:{flex:1}},c))}),M==="hsl"&&l.jsx("div",{style:{display:"flex",gap:6},children:[{label:"H",val:O.h,max:360,fn:c=>{const{r:m,g:z,b:I}=ge(c,O.s,O.l);B(X({r:m,g:z,b:I,a:h.a}))}},{label:"S",val:O.s,max:100,fn:c=>{const{r:m,g:z,b:I}=ge(O.h,c,O.l);B(X({r:m,g:z,b:I,a:h.a}))}},{label:"L",val:O.l,max:100,fn:c=>{const{r:m,g:z,b:I}=ge(O.h,O.s,c);B(X({r:m,g:z,b:I,a:h.a}))}},{label:"A",val:_,max:100,fn:c=>B({...h,a:c/100})}].map(({label:c,val:m,max:z,fn:I})=>l.jsx(K,{size:"sm",type:"number",prefix:c,value:m,min:0,max:z,onChange:F=>{const P=+F.target.value;!isNaN(P)&&P>=0&&P<=z&&I(P)},className:"lucent-cp-field",style:{flex:1}},c))}),M==="hsb"&&l.jsx("div",{style:{display:"flex",gap:6},children:[{label:"H",val:h.h,max:360,fn:c=>B({...h,h:c})},{label:"S",val:h.s,max:100,fn:c=>B({...h,s:c})},{label:"B",val:h.v,max:100,fn:c=>B({...h,v:c})},{label:"A",val:_,max:100,fn:c=>B({...h,a:c/100})}].map(({label:c,val:m,max:z,fn:I})=>l.jsx(K,{size:"sm",type:"number",prefix:c,value:m,min:0,max:z,onChange:F=>{const P=+F.target.value;!isNaN(P)&&P>=0&&P<=z&&I(P)},className:"lucent-cp-field",style:{flex:1}},c))}),o.length>0&&l.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:8},children:[o.length>1&&l.jsx(Ie,{size:"sm",value:String(y),onChange:c=>x(Number(c.target.value)),options:o.map((c,m)=>({value:String(m),label:c.label}))}),o.length===1&&l.jsx("span",{style:{fontSize:"var(--lucent-font-size-xs)",fontWeight:"var(--lucent-font-weight-medium)",color:"var(--lucent-text-secondary)",fontFamily:"var(--lucent-font-family-base)"},children:(T=o[0])==null?void 0:T.label}),l.jsx("div",{style:{display:"flex",gap:6,flexWrap:"wrap"},children:(((L=o[y])==null?void 0:L.colors)??[]).map(c=>{const m=Re(c).toLowerCase()===ae.slice(0,7).toLowerCase();return l.jsx(ne,{color:c,selected:m,onClick:()=>B(X(rt(c)))},c)})})]})]})]}),i??document.body)]})}ot.displayName="ColorPicker";function ha({tabs:e,defaultValue:t,value:s,onChange:a,variant:n="underline",style:r}){var _;const o=s!==void 0,[i,d]=b.useState(t??((_=e[0])==null?void 0:_.value)??""),u=o?s:i,[f,g]=b.useState(null),v=b.useRef([]),[p,S]=b.useState(null),M=b.useRef(!1),k=n==="pills",y=b.useRef(null),x=b.useRef(null),h=b.useRef(null),[D,$]=b.useState(e.length),[A,N]=b.useState(!1),[E,H]=b.useState(!1),[Y,V]=b.useState(null),B=e.slice(0,D),W=e.slice(D),U=W.length>0,C=W.some(w=>w.value===u),O=()=>{if(C){S(null);return}const w=e.findIndex((T,L)=>L<D&&T.value===u),R=v.current[w];if(R){if(k){const T=R.querySelector("span");if(!T)return;S({left:T.offsetLeft+R.offsetLeft,width:T.offsetWidth,animate:M.current})}else S({left:R.offsetLeft,width:R.offsetWidth,animate:M.current});M.current=!0}};b.useLayoutEffect(()=>{O(),document.fonts.ready.then(O)},[u,D,k]),b.useEffect(()=>{const w=y.current;if(!w)return;const R=()=>{const m=w.clientWidth,z=70;let I=0,F=0;for(let P=0;P<e.length;P++){const Z=v.current[P];if(!Z){F++;continue}const J=Z.offsetWidth;if(P<e.length-1){if(I+J+z>m)break}else if(I+J>m)break;I+=J,F++}if(F>=e.length-1&&F<e.length){let P=0;for(let Z=0;Z<e.length;Z++){const J=v.current[Z];J&&(P+=J.offsetWidth)}P<=m&&(F=e.length)}$(F<1?1:F)};let T;(()=>{T=requestAnimationFrame(()=>{T=requestAnimationFrame(R)})})();const c=new ResizeObserver(R);return c.observe(w),()=>{c.disconnect(),cancelAnimationFrame(T)}},[e]),b.useEffect(()=>{if(!A)return;const w=R=>{h.current&&!h.current.contains(R.target)&&x.current&&!x.current.contains(R.target)&&(N(!1),V(null))};return document.addEventListener("mousedown",w),()=>document.removeEventListener("mousedown",w)},[A]);const ae=w=>{o||d(w),a==null||a(w)},ye=(w,R)=>{var m;const T=B.map((z,I)=>z.disabled?-1:I).filter(z=>z!==-1),L=T.indexOf(R);let c=-1;w.key==="ArrowRight"&&(c=T[(L+1)%T.length]??-1),w.key==="ArrowLeft"&&(c=T[(L-1+T.length)%T.length]??-1),w.key==="Home"&&(c=T[0]??-1),w.key==="End"&&(c=T[T.length-1]??-1),c!==-1&&(w.preventDefault(),(m=v.current[c])==null||m.focus(),ae(B[c].value))};return l.jsxs("div",{style:{display:"flex",flexDirection:"column",position:"relative",...r},children:[l.jsxs("div",{ref:y,role:"tablist",style:{position:"relative",display:"flex",overflow:"hidden",...k?{padding:"var(--lucent-space-1)"}:{borderBottom:"1px solid var(--lucent-border-default)"}},children:[e.map((w,R)=>{const T=R<D,L=w.value===u,c=w.disabled??!1;return l.jsxs("button",{ref:m=>{v.current[R]=m},role:"tab","aria-selected":L,"aria-controls":`lucent-tabpanel-${w.value}`,id:`lucent-tab-${w.value}`,disabled:c,tabIndex:L&&T?0:-1,onClick:()=>{c||ae(w.value)},onKeyDown:m=>ye(m,R),onMouseEnter:()=>{!c&&T&&g(R)},onMouseLeave:()=>g(null),style:{padding:k?"var(--lucent-space-1) var(--lucent-space-2)":"var(--lucent-space-1) var(--lucent-space-2) var(--lucent-space-3)",background:"none",border:"none",cursor:c?"not-allowed":"pointer",fontFamily:"var(--lucent-font-family-base)",fontSize:"var(--lucent-font-size-md)",fontWeight:L?"var(--lucent-font-weight-medium)":"var(--lucent-font-weight-regular)",color:c?"var(--lucent-text-disabled)":k&&L?"var(--lucent-accent-fg)":L?"var(--lucent-text-primary)":"var(--lucent-text-secondary)",transition:"color var(--lucent-duration-fast) var(--lucent-easing-default)",whiteSpace:"nowrap",outline:"none",position:T?"relative":"absolute",zIndex:L?1:0,...T?{}:{visibility:"hidden",pointerEvents:"none",left:-9999}},children:[l.jsx("span",{style:{display:"block",padding:"var(--lucent-space-1) var(--lucent-space-3)",borderRadius:"var(--lucent-radius-md)",background:!k&&f===R&&!L&&!c?"var(--lucent-surface-secondary)":"transparent",transition:"background var(--lucent-duration-fast) var(--lucent-easing-default)"},children:w.label}),k&&f===R&&!L&&!c&&T&&l.jsx("span",{"aria-hidden":!0,style:{position:"absolute",top:0,bottom:0,left:0,right:0,borderRadius:"var(--lucent-radius-md)",background:"var(--lucent-surface-secondary)",zIndex:-1,transition:"background var(--lucent-duration-fast) var(--lucent-easing-default)"}})]},w.value)}),U&&l.jsx("button",{ref:x,onClick:()=>N(w=>!w),onMouseEnter:()=>H(!0),onMouseLeave:()=>H(!1),style:{padding:k?"var(--lucent-space-1) var(--lucent-space-2)":"var(--lucent-space-1) var(--lucent-space-2) var(--lucent-space-3)",background:"none",border:"none",cursor:"pointer",fontFamily:"var(--lucent-font-family-base)",fontSize:"var(--lucent-font-size-md)",fontWeight:C?"var(--lucent-font-weight-medium)":"var(--lucent-font-weight-regular)",color:C?"var(--lucent-text-primary)":"var(--lucent-text-secondary)",whiteSpace:"nowrap",outline:"none",position:"relative",flexShrink:0},children:l.jsx("span",{style:{display:"block",padding:"var(--lucent-space-1) var(--lucent-space-3)",borderRadius:"var(--lucent-radius-md)",background:E?"var(--lucent-surface-secondary)":"transparent",transition:"background var(--lucent-duration-fast) var(--lucent-easing-default)"},children:"More…"})}),p!=null&&l.jsx("span",{"aria-hidden":!0,style:k?{position:"absolute",top:"var(--lucent-space-1)",bottom:"var(--lucent-space-1)",left:p.left,width:p.width,background:"var(--lucent-accent-default)",borderRadius:"var(--lucent-radius-md)",transition:p.animate?"left 220ms var(--lucent-easing-default), width 220ms var(--lucent-easing-default)":"none"}:{position:"absolute",bottom:0,left:p.left,width:p.width,height:2,background:"var(--lucent-accent-default)",borderRadius:"var(--lucent-radius-sm)",transition:p.animate?"left 220ms var(--lucent-easing-default), width 220ms var(--lucent-easing-default)":"none"}})]}),U&&A&&l.jsx("div",{ref:h,style:{position:"absolute",top:"100%",right:0,zIndex:50,marginTop:"var(--lucent-space-1)",background:"var(--lucent-surface-primary)",border:"1px solid var(--lucent-border-default)",borderRadius:"var(--lucent-radius-md)",boxShadow:"var(--lucent-shadow-md)",padding:"var(--lucent-space-1) 0",minWidth:140},children:W.map((w,R)=>{const T=w.value===u,L=w.disabled??!1,c=Y===R;return l.jsx("button",{disabled:L,onClick:()=>{L||(ae(w.value),N(!1))},onMouseEnter:()=>{L||V(R)},onMouseLeave:()=>V(null),style:{display:"block",width:"100%",padding:"var(--lucent-space-2) var(--lucent-space-4)",background:T||c?"var(--lucent-surface-secondary)":"none",border:"none",cursor:L?"not-allowed":"pointer",fontFamily:"var(--lucent-font-family-base)",fontSize:"var(--lucent-font-size-md)",fontWeight:T?"var(--lucent-font-weight-medium)":"var(--lucent-font-weight-regular)",color:L?"var(--lucent-text-disabled)":T||c?"var(--lucent-text-primary)":"var(--lucent-text-secondary)",textAlign:"left",outline:"none",transition:"background var(--lucent-duration-fast) var(--lucent-easing-default), color var(--lucent-duration-fast) var(--lucent-easing-default)"},children:w.label},w.value)})}),e.some(w=>w.content!=null)&&e.map(w=>l.jsx("div",{role:"tabpanel",id:`lucent-tabpanel-${w.value}`,"aria-labelledby":`lucent-tab-${w.value}`,hidden:w.value!==u,style:{padding:"var(--lucent-space-4) 0",outline:"none"},tabIndex:0,children:w.content},w.value))]})}const va={fontFamilyBase:'"DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',fontFamilyMono:'"DM Mono", "Fira Code", "Cascadia Code", monospace',fontFamilyDisplay:'"Georama", "DM Sans", sans-serif',fontSizeXs:"0.75rem",fontSizeSm:"0.875rem",fontSizeMd:"1rem",fontSizeLg:"1.125rem",fontSizeXl:"1.25rem",fontSize2xl:"1.5rem",fontSize3xl:"1.875rem",fontWeightRegular:"400",fontWeightMedium:"500",fontWeightSemibold:"600",fontWeightBold:"700",lineHeightTight:"1.25",lineHeightBase:"1.5",lineHeightRelaxed:"1.75",letterSpacingTight:"-0.02em",letterSpacingBase:"0em",letterSpacingWide:"0.04em"},ya={space0:"0px",space1:"0.25rem",space2:"0.5rem",space3:"0.75rem",space4:"1rem",space5:"1.25rem",space6:"1.5rem",space8:"2rem",space10:"2.5rem",space12:"3rem",space16:"4rem",space20:"5rem",space24:"6rem"},wa={radiusNone:"0px",radiusSm:"0.25rem",radiusMd:"0.375rem",radiusLg:"0.5rem",radiusXl:"0.75rem",radiusFull:"9999px"},Sa={durationFast:"100ms",durationBase:"200ms",durationSlow:"350ms",easingDefault:"cubic-bezier(0.4, 0, 0.2, 1)",easingEmphasized:"cubic-bezier(0.2, 0, 0, 1)",easingDecelerate:"cubic-bezier(0, 0, 0.2, 1)"},lt={shadowNone:"none",shadowSm:"0 1px 2px 0 rgb(0 0 0 / 0.05)",shadowMd:"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",shadowLg:"0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",shadowXl:"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)"},ct={shadowNone:"none",shadowSm:"inset 0 1px 0 0 rgba(255, 255, 255, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.2)",shadowMd:"inset 0 1px 0 0 rgba(255, 255, 255, 0.06), 0 2px 4px -1px rgba(0, 0, 0, 0.25)",shadowLg:"inset 0 1px 0 0 rgba(255, 255, 255, 0.08), 0 4px 8px -2px rgba(0, 0, 0, 0.3)",shadowXl:"inset 0 1px 0 0 rgba(255, 255, 255, 0.1), 0 8px 16px -4px rgba(0, 0, 0, 0.35)"},re={...va,...ya,...wa,...Sa,...lt,bgBase:"#ffffff",bgSubtle:"#f9fafb",bgOverlay:"rgb(0 0 0 / 0.4)",surface:"#ffffff",surfaceSecondary:"#f3f4f6",surfaceRaised:"#ffffff",surfaceOverlay:"#ffffff",surfaceTint:"#f2f2f2",borderDefault:"#e5e7eb",borderSubtle:"#f3f4f6",borderStrong:"#9ca3af",controlTrack:"#d1d5db",textPrimary:"#111827",textSecondary:"#6b7280",textDisabled:"#d1d5db",textInverse:"#ffffff",accentDefault:"#111827",accentHover:"#1f2937",accentSubtle:"#f3f4f6",accentBorder:"#111827",accentFg:"#ffffff",successDefault:"#16a34a",successSubtle:"#f0fdf4",successText:"#15803d",warningDefault:"#d97706",warningSubtle:"#fffbeb",warningText:"#b45309",dangerDefault:"#dc2626",dangerHover:"#b91c1c",dangerSubtle:"#fef2f2",dangerText:"#b91c1c",infoDefault:"#2563eb",infoSubtle:"#eff6ff",infoText:"#1d4ed8"};function ka(e){const t=parseInt(e.slice(1,3),16),s=parseInt(e.slice(3,5),16),a=parseInt(e.slice(5,7),16);return{r:t,g:s,b:a}}function Da({r:e,g:t,b:s}){const a=n=>n.toString(16).padStart(2,"0");return`#${a(e)}${a(t)}${a(s)}`}function G(e){const{r:t,g:s,b:a}=ka(e),n=t/255,r=s/255,o=a/255,i=Math.max(n,r,o),d=Math.min(n,r,o);let u=0,f=0;const g=(i+d)/2;if(i!==d){const v=i-d;switch(f=g>.5?v/(2-i-d):v/(i+d),i){case n:u=(r-o)/v+(r<o?6:0);break;case r:u=(o-n)/v+2;break;case o:u=(n-r)/v+4;break}u/=6}return[u*360,f,g]}function q(e,t,s){e=(e%360+360)%360,t=Math.min(1,Math.max(0,t)),s=Math.min(1,Math.max(0,s));const a=(1-Math.abs(2*s-1))*t,n=a*(1-Math.abs(e/60%2-1)),r=s-a/2;let o=0,i=0,d=0;return e<60?(o=a,i=n):e<120?(o=n,i=a):e<180?(i=a,d=n):e<240?(i=n,d=a):e<300?(o=n,d=a):(o=a,d=n),Da({r:Math.round((o+r)*255),g:Math.round((i+r)*255),b:Math.round((d+r)*255)})}function j(e,t){const[s,a,n]=G(e);return q(s,a,Math.min(1,Math.max(0,n+t)))}const Ma=222,ja=.12;function it(e,t){return t<.04?[Ma,ja]:[e,t]}function Ta(e){const[t,s,a]=G(e),[n,r]=it(t,s);return q(n,r,Math.max(.04,Math.min(.2,.07+(1-a))))}function ke(e){const[t,s,a]=G(e),[n,r]=it(t,s);return q(n,r,Math.max(.06,Math.min(.5,(1-a)*.6+.06)))}function De(e){const[t,s,a]=G(e);return q(t,s,Math.max(.04,Math.min(.97,1-a+.04)))}function Me(e){const[t,s,a]=G(e);return q(t,s,Math.max(.02,Math.min(.98,1-a)))}function ut(e){const t=Ta(e.bgBase),[s,a,n]=G(t),r=o=>q(s,a,Math.min(.25,n+o));return{...e,...ct,bgBase:t,bgSubtle:r(.02),bgOverlay:"rgb(0 0 0 / 0.6)",surface:r(.02),surfaceSecondary:r(.05),surfaceRaised:r(.08),surfaceOverlay:r(.08),surfaceTint:r(.03),borderDefault:ke(e.borderDefault),borderSubtle:ke(e.borderSubtle),borderStrong:ke(e.borderStrong),controlTrack:r(.1),textPrimary:De(e.textPrimary),textSecondary:De(e.textSecondary),textDisabled:De(e.textDisabled),textInverse:t,accentDefault:Me(e.accentDefault),accentHover:Me(e.accentHover),accentSubtle:Me(e.accentSubtle),accentBorder:e.accentBorder,accentFg:e.accentFg,successDefault:j(e.successDefault,.1),successSubtle:j(e.successDefault,-.25),successText:j(e.successText,.15),warningDefault:j(e.warningDefault,.1),warningSubtle:j(e.warningDefault,-.25),warningText:j(e.warningText,.15),dangerDefault:j(e.dangerDefault,.1),dangerHover:j(e.dangerHover,.1),dangerSubtle:j(e.dangerDefault,-.25),dangerText:j(e.dangerText,.15),infoDefault:j(e.infoDefault,.1),infoSubtle:j(e.infoDefault,-.25),infoText:j(e.infoText,.15)}}const $e=ut(re);function dt(e){return"--lucent-"+e.replace(/([A-Z])/g,t=>`-${t.toLowerCase()}`).replace(/([a-z])(\d)/g,(t,s,a)=>`${s}-${a}`)}function ft(e,t=":root"){const s=Object.entries(e).map(([a,n])=>` ${dt(a)}: ${n};`).join(`
106
106
  `);return`${t} {
107
107
  ${s}
108
- }`}function za(e){const t=parseInt(e.slice(1,3),16)/255,s=parseInt(e.slice(3,5),16)/255,a=parseInt(e.slice(5,7),16)/255,n=r=>r<=.03928?r/12.92:Math.pow((r+.055)/1.055,2.4);return .2126*n(t)+.7152*n(s)+.0722*n(a)}const Ia=.2126729,Ba=.7151522,Ra=.072175,$a=.56,La=.57,Pa=.65,Ca=.62,et=.022,Fa=1.414,Ha=1.14,Wa=1.14,tt=.027,at=.027;function nt(e){const t=parseInt(e.slice(1,3),16)/255,s=parseInt(e.slice(3,5),16)/255,a=parseInt(e.slice(5,7),16)/255,n=Math.pow(t,2.4),r=Math.pow(s,2.4),o=Math.pow(a,2.4);let i=Ia*n+Ba*r+Ra*o;return i<0&&(i=0),i<et?i+Math.pow(et-i,Fa):i}function xe(e,t){const s=nt(e),a=nt(t);let n;if(s>a){const r=(Math.pow(s,$a)-Math.pow(a,La))*Ha;n=r<tt?0:r-tt}else{const r=(Math.pow(s,Pa)-Math.pow(a,Ca))*Wa;n=r>-at?0:r+at}return n*100}function pt(e){const t=Math.abs(xe(e,"#ffffff")),s=Math.abs(xe(e,"#000000"));return t>=s?"#ffffff":"#000000"}function Le(e){const t=parseInt(e.slice(1,3),16)/255,s=parseInt(e.slice(3,5),16)/255,a=parseInt(e.slice(5,7),16)/255,n=Math.max(t,s,a),r=Math.min(t,s,a);let o=0,i=0;if(n!==r){const u=n-r;i=(n+r)/2>.5?u/(2-n-r):u/(n+r),n===t?o=((s-a)/u+(s<a?6:0))/6:n===s?o=((a-t)/u+2)/6:o=((t-s)/u+4)/6}return pt(e)==="#000000"?Te(o,Math.min(i,.6),.12):Te(o,Math.min(i,.2),.95)}function gt(e,t,s=60){if(Math.abs(xe(e,t))>=s)return e;const a=parseInt(e.slice(1,3),16)/255,n=parseInt(e.slice(3,5),16)/255,r=parseInt(e.slice(5,7),16)/255,o=Math.max(a,n,r),i=Math.min(a,n,r);let d=0,u=0,f=(o+i)/2;if(o!==i){const p=o-i;u=f>.5?p/(2-o-i):p/(o+i),o===a?d=((n-r)/p+(n<r?6:0))/6:o===n?d=((r-a)/p+2)/6:d=((a-n)/p+4)/6}const v=za(t)>.5?-.005:.005;for(let p=0;p<100;p++){f=Math.min(1,Math.max(0,f+v));const S=Te(d,u,f);if(Math.abs(xe(S,t))>=s)return S}return e}function Te(e,t,s){const a=(d,u,f)=>(f<0&&(f+=1),f>1&&(f-=1),f<.16666666666666666?d+(u-d)*6*f:f<.5?u:f<.6666666666666666?d+(u-d)*(.6666666666666666-f)*6:d);let n,r,o;if(t===0)n=r=o=s;else{const d=s<.5?s*(1+t):s+t-s*t,u=2*s-d;n=a(u,d,e+1/3),r=a(u,d,e),o=a(u,d,e-1/3)}const i=d=>Math.round(d*255).toString(16).padStart(2,"0");return`#${i(n)}${i(r)}${i(o)}`}function Ea(e,t){const[s,a,n]=G(e);return t?q(s,a*.3,Math.min(1,n+(1-n)*.85)):q(s,a,Math.min(.25,n+.04))}const me={subtle:{light:.95,dark:.12},text:{light:.28,dark:.78}};function fe(e,t){const[s,a]=G(e);return q(s,a*.5,t?me.subtle.light:me.subtle.dark)}function pe(e,t){const[s,a]=G(e);return q(s,a,t?me.text.light:me.text.dark)}function Pe(e,t,s){const a={},n=s==="light";if("borderDefault"in e&&("borderSubtle"in e||(a.borderSubtle=j(t.borderDefault,n?.05:-.02)),"borderStrong"in e||(a.borderStrong=j(t.borderDefault,n?-.27:.19))),"bgBase"in e&&("bgSubtle"in e||(a.bgSubtle=j(t.bgBase,n?-.02:.02)),"surfaceTint"in e||(a.surfaceTint=j(t.bgBase,n?-.04:.03)),!("surface"in e))){const r=Ea(t.bgBase,n);a.surface=r,"surfaceSecondary"in e||(a.surfaceSecondary=j(r,n?-.04:.03)),"surfaceRaised"in e||(a.surfaceRaised=j(r,n?0:.06)),"surfaceOverlay"in e||(a.surfaceOverlay=j(r,n?0:.06))}return"surface"in e&&("surfaceSecondary"in e||(a.surfaceSecondary=j(t.surface,n?-.04:.03)),"surfaceRaised"in e||(a.surfaceRaised=j(t.surface,n?0:.06)),"surfaceOverlay"in e||(a.surfaceOverlay=j(t.surface,n?0:.06))),"textPrimary"in e&&("textSecondary"in e||(a.textSecondary=j(t.textPrimary,n?.2:-.15)),"textDisabled"in e||(a.textDisabled=j(t.textPrimary,n?.35:-.4))),"accentDefault"in e&&("accentHover"in e||(a.accentHover=j(t.accentDefault,n?.05:-.07)),"accentSubtle"in e||(a.accentSubtle=j(t.accentDefault,n?.85:-.6))),"successDefault"in e&&("successSubtle"in e||(a.successSubtle=fe(t.successDefault,n)),"successText"in e||(a.successText=pe(t.successDefault,n))),"warningDefault"in e&&("warningSubtle"in e||(a.warningSubtle=fe(t.warningDefault,n)),"warningText"in e||(a.warningText=pe(t.warningDefault,n))),"dangerDefault"in e&&("dangerHover"in e||(a.dangerHover=j(t.dangerDefault,n?.05:-.07)),"dangerSubtle"in e||(a.dangerSubtle=fe(t.dangerDefault,n)),"dangerText"in e||(a.dangerText=pe(t.dangerDefault,n))),"infoDefault"in e&&("infoSubtle"in e||(a.infoSubtle=fe(t.infoDefault,n)),"infoText"in e||(a.infoText=pe(t.infoDefault,n))),a}function Ce(e,t="light"){const a={...t==="dark"?$e:re,...e},n=Pe(e,a,t),r=t==="light"?j(a.accentDefault,-.15):j(a.accentDefault,.15);return{...a,...n,accentFg:Le(a.accentDefault),accentBorder:r}}const Fe={name:"default",light:{bgBase:"#ffffff",surface:"#ffffff",borderDefault:"#e5e7eb",accentDefault:"#111827",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#111318",surface:"#181a20",borderDefault:"#2e3039",accentDefault:"#f9fafb",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},bt={name:"brand",light:{bgBase:"#fffefb",surface:"#fffdf7",borderDefault:"#e8e3d6",accentDefault:"#e9c96b",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#151310",surface:"#1c1a15",borderDefault:"#33302a",accentDefault:"#e9c96b",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},se={name:"indigo",light:{bgBase:"#fdfcff",surface:"#faf9fe",borderDefault:"#e0dde9",accentDefault:"#6366f1",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#12111a",surface:"#191820",borderDefault:"#2e2d3a",accentDefault:"#818cf8",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},xt={name:"violet",light:{bgBase:"#fdfcfe",surface:"#faf8fd",borderDefault:"#e2dce9",accentDefault:"#8b5cf6",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#13111a",surface:"#1a1822",borderDefault:"#302d3b",accentDefault:"#a78bfa",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},He={name:"emerald",light:{bgBase:"#fbfefc",surface:"#f7fcf9",borderDefault:"#dbe8df",accentDefault:"#10b981",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#0f1512",surface:"#151c18",borderDefault:"#263330",accentDefault:"#34d399",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},Na={name:"teal",light:{bgBase:"#fbfefd",surface:"#f6fcfa",borderDefault:"#d4e5e0",accentDefault:"#0d9488",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#0f1514",surface:"#161d1c",borderDefault:"#283836",accentDefault:"#2dd4bf",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},We={name:"rose",light:{bgBase:"#fffcfd",surface:"#fef9fa",borderDefault:"#ecdde1",accentDefault:"#f43f5e",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#161012",surface:"#1d1518",borderDefault:"#3a282e",accentDefault:"#fb7185",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},mt={name:"coral",light:{bgBase:"#fffcfb",surface:"#fef9f7",borderDefault:"#e9ddd8",accentDefault:"#e8624a",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#b91c1c",infoDefault:"#2563eb"},dark:{bgBase:"#171210",surface:"#1e1816",borderDefault:"#3b312c",accentDefault:"#f38b76",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},Aa={name:"amber",light:{bgBase:"#fffefb",surface:"#fefcf6",borderDefault:"#e8e1d0",accentDefault:"#d97706",successDefault:"#16a34a",warningDefault:"#b45309",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#171310",surface:"#1e1a15",borderDefault:"#3a3329",accentDefault:"#f59e0b",successDefault:"#22c55e",warningDefault:"#d97706",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},Ee={name:"ocean",light:{bgBase:"#fbfdff",surface:"#f6fafd",borderDefault:"#d9e4ec",accentDefault:"#0ea5e9",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#0e1318",surface:"#141a20",borderDefault:"#243038",accentDefault:"#38bdf8",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},ht={name:"slate",light:{bgBase:"#fafbfc",surface:"#f7f8fa",borderDefault:"#dde1e6",accentDefault:"#475569",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#0f1116",surface:"#161920",borderDefault:"#2b3040",accentDefault:"#94a3b8",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},Oa={name:"sage",light:{bgBase:"#fbfcfb",surface:"#f5f7f5",borderDefault:"#d8ddd6",accentDefault:"#5f8c6e",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#101410",surface:"#171c17",borderDefault:"#2c372c",accentDefault:"#86b394",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},oe={name:"sharp",tokens:{radiusNone:"0px",radiusSm:"0.125rem",radiusMd:"0.1875rem",radiusLg:"0.25rem",radiusXl:"0.375rem",radiusFull:"9999px"}},ee={name:"rounded",tokens:{radiusNone:"0px",radiusSm:"0.25rem",radiusMd:"0.375rem",radiusLg:"0.5rem",radiusXl:"0.75rem",radiusFull:"9999px"}},le={name:"pill",tokens:{radiusNone:"0px",radiusSm:"0.5rem",radiusMd:"0.75rem",radiusLg:"1rem",radiusXl:"1.5rem",radiusFull:"9999px"}},ce={name:"compact",tokens:{space0:"0px",space1:"0.1rem",space2:"0.25rem",space3:"0.6rem",space4:"0.8rem",space5:"1rem",space6:"1.2rem",space8:"1.6rem",space10:"2rem",space12:"2.4rem",space16:"3.2rem",space20:"4rem",space24:"4.8rem"}},te={name:"default",tokens:{space0:"0px",space1:"0.25rem",space2:"0.5rem",space3:"0.75rem",space4:"1rem",space5:"1.25rem",space6:"1.5rem",space8:"2rem",space10:"2.5rem",space12:"3rem",space16:"4rem",space20:"5rem",space24:"6rem"}},ie={name:"spacious",tokens:{space0:"0px",space1:"0.375rem",space2:"0.75rem",space3:"1.125rem",space4:"1.25rem",space5:"1.5625rem",space6:"1.875rem",space8:"2.5rem",space10:"3.125rem",space12:"3.75rem",space16:"5rem",space20:"6.25rem",space24:"7.5rem"}},he={name:"flat",light:{shadowNone:"none",shadowSm:"none",shadowMd:"none",shadowLg:"none",shadowXl:"none"},dark:{shadowNone:"none",shadowSm:"none",shadowMd:"none",shadowLg:"none",shadowXl:"none"}},Ne={name:"subtle",light:{shadowNone:"none",shadowSm:"rgba(17, 17, 26, 0.04) 0px 2px 8px, rgba(17, 17, 26, 0.02) 0px 4px 16px",shadowMd:"rgba(17, 17, 26, 0.06) 0px 4px 16px, rgba(17, 17, 26, 0.03) 0px 8px 32px",shadowLg:"rgba(17, 17, 26, 0.06) 0px 8px 24px, rgba(17, 17, 26, 0.04) 0px 16px 48px",shadowXl:"rgba(17, 17, 26, 0.08) 0px 12px 32px, rgba(17, 17, 26, 0.05) 0px 24px 64px"},dark:{shadowNone:"none",shadowSm:"0 0 20px color-mix(in srgb, var(--lucent-accent-default) 5%, transparent)",shadowMd:"0 0 30px color-mix(in srgb, var(--lucent-accent-default) 7%, transparent), inset 0 1px 0 0 rgba(255, 255, 255, 0.04)",shadowLg:"0 0 40px color-mix(in srgb, var(--lucent-accent-default) 9%, transparent), inset 0 1px 0 0 rgba(255, 255, 255, 0.05)",shadowXl:"0 0 56px color-mix(in srgb, var(--lucent-accent-default) 12%, transparent), inset 0 1px 0 0 rgba(255, 255, 255, 0.06)"}},Ae={name:"elevated",light:{shadowNone:"none",shadowSm:"rgba(17, 17, 26, 0.05) 0px 2px 8px, rgba(17, 17, 26, 0.03) 0px 4px 16px",shadowMd:"rgba(17, 17, 26, 0.1) 0px 4px 16px, rgba(17, 17, 26, 0.05) 0px 8px 32px",shadowLg:"rgba(17, 17, 26, 0.1) 0px 8px 24px, rgba(17, 17, 26, 0.08) 0px 16px 48px",shadowXl:"rgba(17, 17, 26, 0.12) 0px 12px 32px, rgba(17, 17, 26, 0.1) 0px 24px 64px"},dark:{shadowNone:"none",shadowSm:"inset 0 1px 0 0 rgba(255, 255, 255, 0.06), inset 0 0 12px rgba(255, 255, 255, 0.02)",shadowMd:"inset 0 1px 0 0 rgba(255, 255, 255, 0.08), inset 0 0 20px rgba(255, 255, 255, 0.03), 0 0 1px rgba(255, 255, 255, 0.06)",shadowLg:"inset 0 1px 0 0 rgba(255, 255, 255, 0.1), inset 0 0 28px rgba(255, 255, 255, 0.04), 0 0 1px rgba(255, 255, 255, 0.08)",shadowXl:"inset 0 1px 0 0 rgba(255, 255, 255, 0.12), inset 0 0 36px rgba(255, 255, 255, 0.05), 0 0 1px rgba(255, 255, 255, 0.1)"}},Oe={name:"liquidGlass",light:{shadowNone:"none",shadowSm:"0 4px 30px rgba(0, 0, 0, 0.04)",shadowMd:"0 8px 50px rgba(0, 0, 0, 0.05), 0 2px 10px rgba(0, 0, 0, 0.02)",shadowLg:"0 12px 60px rgba(0, 0, 0, 0.06), 0 4px 20px rgba(0, 0, 0, 0.03)",shadowXl:"0 20px 80px rgba(0, 0, 0, 0.08), 0 8px 30px rgba(0, 0, 0, 0.04)"},dark:{shadowNone:"none",shadowSm:"inset 0 1px 0 0 rgba(255, 255, 255, 0.06), 0 0 30px rgba(255, 255, 255, 0.02)",shadowMd:"inset 0 1px 0 0 rgba(255, 255, 255, 0.08), inset 0 0 20px rgba(255, 255, 255, 0.02), 0 0 40px rgba(255, 255, 255, 0.03)",shadowLg:"inset 0 1px 0 0 rgba(255, 255, 255, 0.1), inset 0 0 30px rgba(255, 255, 255, 0.03), 0 0 50px rgba(255, 255, 255, 0.04)",shadowXl:"inset 0 1px 0 0 rgba(255, 255, 255, 0.12), inset 0 0 40px rgba(255, 255, 255, 0.04), 0 0 70px rgba(255, 255, 255, 0.05)"}},Xe={name:"brutalist",light:{shadowNone:"none",shadowSm:"0 0 0 2px var(--lucent-text-primary), 3px 3px 0 0 color-mix(in srgb, var(--lucent-accent-default) 50%, transparent)",shadowMd:"0 0 0 2px var(--lucent-text-primary), 5px 5px 0 0 color-mix(in srgb, var(--lucent-accent-default) 60%, transparent)",shadowLg:"0 0 0 3px var(--lucent-text-primary), 6px 6px 0 0 color-mix(in srgb, var(--lucent-accent-default) 70%, transparent)",shadowXl:"0 0 0 3px var(--lucent-text-primary), 8px 8px 0 0 color-mix(in srgb, var(--lucent-accent-default) 80%, transparent)"},dark:{shadowNone:"none",shadowSm:"0 0 0 2px color-mix(in srgb, var(--lucent-accent-default) 60%, transparent), 3px 3px 0 0 color-mix(in srgb, var(--lucent-accent-default) 30%, transparent)",shadowMd:"0 0 0 2px color-mix(in srgb, var(--lucent-accent-default) 65%, transparent), 5px 5px 0 0 color-mix(in srgb, var(--lucent-accent-default) 35%, transparent)",shadowLg:"0 0 0 3px color-mix(in srgb, var(--lucent-accent-default) 70%, transparent), 6px 6px 0 0 color-mix(in srgb, var(--lucent-accent-default) 40%, transparent)",shadowXl:"0 0 0 3px color-mix(in srgb, var(--lucent-accent-default) 75%, transparent), 8px 8px 0 0 color-mix(in srgb, var(--lucent-accent-default) 45%, transparent)"}},qe={name:"neumorphic",light:{shadowNone:"none",shadowSm:"3px 3px 8px #d1d5db, -3px -3px 8px #ffffff",shadowMd:"5px 5px 14px #d1d5db, -5px -5px 14px #ffffff",shadowLg:"8px 8px 20px #d1d5db, -8px -8px 20px #ffffff",shadowXl:"12px 12px 28px #d1d5db, -12px -12px 28px #ffffff"},dark:{shadowNone:"none",shadowSm:"3px 3px 10px color-mix(in srgb, var(--lucent-accent-default) 12%, transparent), -3px -3px 10px rgba(255, 255, 255, 0.03)",shadowMd:"5px 5px 16px color-mix(in srgb, var(--lucent-accent-default) 15%, transparent), -5px -5px 16px rgba(255, 255, 255, 0.04)",shadowLg:"8px 8px 24px color-mix(in srgb, var(--lucent-accent-default) 18%, transparent), -8px -8px 24px rgba(255, 255, 255, 0.05)",shadowXl:"12px 12px 32px color-mix(in srgb, var(--lucent-accent-default) 22%, transparent), -12px -12px 32px rgba(255, 255, 255, 0.06)"}},Ue={name:"natural",light:{shadowNone:"none",shadowSm:"0 1px 1px rgba(0, 0, 0, 0.06), 0 2px 4px rgba(0, 0, 0, 0.06)",shadowMd:"0 1px 2px rgba(0, 0, 0, 0.06), 0 2px 4px rgba(0, 0, 0, 0.06), 0 4px 8px rgba(0, 0, 0, 0.06)",shadowLg:"0 1px 2px rgba(0, 0, 0, 0.05), 0 2px 4px rgba(0, 0, 0, 0.05), 0 4px 8px rgba(0, 0, 0, 0.05), 0 8px 16px rgba(0, 0, 0, 0.05)",shadowXl:"0 1px 2px rgba(0, 0, 0, 0.04), 0 2px 4px rgba(0, 0, 0, 0.04), 0 4px 8px rgba(0, 0, 0, 0.04), 0 8px 16px rgba(0, 0, 0, 0.04), 0 16px 32px rgba(0, 0, 0, 0.04)"},dark:{shadowNone:"none",shadowSm:"inset 0 1px 0 0 rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.03)",shadowMd:"inset 0 1px 0 0 rgba(255, 255, 255, 0.07), inset 0 0 0 1px rgba(255, 255, 255, 0.04), 0 1px 3px rgba(0, 0, 0, 0.15)",shadowLg:"inset 0 1px 0 0 rgba(255, 255, 255, 0.09), inset 0 0 0 1px rgba(255, 255, 255, 0.05), inset 0 0 16px rgba(255, 255, 255, 0.02), 0 2px 6px rgba(0, 0, 0, 0.15)",shadowXl:"inset 0 1px 0 0 rgba(255, 255, 255, 0.12), inset 0 0 0 1px rgba(255, 255, 255, 0.06), inset 0 0 24px rgba(255, 255, 255, 0.03), 0 4px 10px rgba(0, 0, 0, 0.15)"}},ve={name:"glow",light:{shadowNone:"none",shadowSm:"0 1px 3px rgba(0, 0, 0, 0.06), 0 0 12px color-mix(in srgb, var(--lucent-accent-default) 12%, transparent)",shadowMd:"0 2px 6px rgba(0, 0, 0, 0.06), 0 0 20px color-mix(in srgb, var(--lucent-accent-default) 16%, transparent)",shadowLg:"0 4px 10px rgba(0, 0, 0, 0.06), 0 0 30px color-mix(in srgb, var(--lucent-accent-default) 20%, transparent)",shadowXl:"0 6px 14px rgba(0, 0, 0, 0.06), 0 0 44px color-mix(in srgb, var(--lucent-accent-default) 25%, transparent)"},dark:{shadowNone:"none",shadowSm:"0 0 16px color-mix(in srgb, var(--lucent-accent-default) 20%, transparent)",shadowMd:"0 0 24px color-mix(in srgb, var(--lucent-accent-default) 28%, transparent)",shadowLg:"0 0 36px color-mix(in srgb, var(--lucent-accent-default) 35%, transparent)",shadowXl:"0 0 50px color-mix(in srgb, var(--lucent-accent-default) 40%, transparent)"}},vt={name:"modern",palette:se,shape:ee,density:te,shadow:Ne},yt={name:"enterprise",palette:Fe,shape:oe,density:ce,shadow:he},wt={name:"playful",palette:We,shape:le,density:ie,shadow:Ae},St={name:"liquidGlass",palette:Ee,shape:le,density:ie,shadow:Oe},kt={name:"bento",palette:se,shape:ee,density:te,shadow:Ue},Dt={name:"brutalist",palette:mt,shape:oe,density:ce,shadow:Xe},Mt={name:"terminal",palette:He,shape:oe,density:ce,shadow:ve},jt={name:"softUI",palette:xt,shape:le,density:te,shadow:qe},Tt={name:"bloom",palette:se,shape:ee,density:ie,shadow:ve},zt={name:"minimal",palette:ht,shape:ee,density:te,shadow:he},Xa={default:Fe,brand:bt,indigo:se,violet:xt,emerald:He,teal:Na,rose:We,coral:mt,amber:Aa,ocean:Ee,slate:ht,sage:Oa},qa={sharp:oe,rounded:ee,pill:le},Ua={compact:ce,default:te,spacious:ie},Ga={flat:he,subtle:Ne,elevated:Ae,liquidGlass:Oe,brutalist:Xe,neumorphic:qe,natural:Ue,glow:ve},Va={modern:vt,enterprise:yt,playful:wt,liquidGlass:St,bento:kt,brutalist:Dt,terminal:Mt,softUI:jt,bloom:Tt,minimal:zt};function _a(e){return typeof e=="string"?Xa[e]:e}function Ka(e){return typeof e=="string"?qa[e]:e}function Ya(e){return typeof e=="string"?Ua[e]:e}function Za(e){return typeof e=="string"?Ga[e]:e}function It(e,t){let s,a,n,r;if(typeof e=="string"){const i=Va[e];if(!i)return{};s=i.palette,a=i.shape,n=i.density,r=i.shadow}else e.palette!==void 0&&(s=_a(e.palette)),e.shape!==void 0&&(a=Ka(e.shape)),e.density!==void 0&&(n=Ya(e.density)),e.shadow!==void 0&&(r=Za(e.shadow));const o={};if(s){const i=Ce(s[t],t);Object.assign(o,i)}return a&&Object.assign(o,a.tokens),n&&Object.assign(o,n.tokens),r&&Object.assign(o,r[t]),o}const Bt=b.createContext({theme:"light",tokens:re});function Ja({theme:e="light",preset:t,tokens:s,anchors:a,children:n}){const r=b.useId().replace(/:/g,""),o=t?It(t,e):void 0,i=(()=>{if(a){const k=Ce(a,e);if(o){const y={};for(const[x,h]of Object.entries(o))(x.startsWith("space")||x.startsWith("radius")||x.startsWith("shadow")||x.startsWith("duration")||x.startsWith("easing"))&&(y[x]=h);return{...k,...y}}return k}const u=e==="dark"?$e:re,f=o?{...o,...s}:s,g=f?{...u,...f}:u,v=f?Pe(f,g,e):{},p=(f==null?void 0:f.accentBorder)??(e==="light"?j(g.accentDefault,-.15):j(g.accentDefault,.15)),S=(f==null?void 0:f.accentFg)??Le(g.accentDefault),M=gt(g.accentDefault,S);return{...g,...v,accentDefault:M,accentFg:S,accentBorder:p}})(),d=`html { font-size: 14px; }
108
+ }`}function za(e){const t=parseInt(e.slice(1,3),16)/255,s=parseInt(e.slice(3,5),16)/255,a=parseInt(e.slice(5,7),16)/255,n=r=>r<=.03928?r/12.92:Math.pow((r+.055)/1.055,2.4);return .2126*n(t)+.7152*n(s)+.0722*n(a)}const Ia=.2126729,Ba=.7151522,Ra=.072175,$a=.56,La=.57,Pa=.65,Ca=.62,et=.022,Fa=1.414,Ha=1.14,Wa=1.14,tt=.027,at=.027;function nt(e){const t=parseInt(e.slice(1,3),16)/255,s=parseInt(e.slice(3,5),16)/255,a=parseInt(e.slice(5,7),16)/255,n=Math.pow(t,2.4),r=Math.pow(s,2.4),o=Math.pow(a,2.4);let i=Ia*n+Ba*r+Ra*o;return i<0&&(i=0),i<et?i+Math.pow(et-i,Fa):i}function xe(e,t){const s=nt(e),a=nt(t);let n;if(s>a){const r=(Math.pow(s,$a)-Math.pow(a,La))*Ha;n=r<tt?0:r-tt}else{const r=(Math.pow(s,Pa)-Math.pow(a,Ca))*Wa;n=r>-at?0:r+at}return n*100}function pt(e){const t=Math.abs(xe(e,"#ffffff")),s=Math.abs(xe(e,"#000000"));return t>=s?"#ffffff":"#000000"}function Le(e){const t=parseInt(e.slice(1,3),16)/255,s=parseInt(e.slice(3,5),16)/255,a=parseInt(e.slice(5,7),16)/255,n=Math.max(t,s,a),r=Math.min(t,s,a);let o=0,i=0;if(n!==r){const u=n-r;i=(n+r)/2>.5?u/(2-n-r):u/(n+r),n===t?o=((s-a)/u+(s<a?6:0))/6:n===s?o=((a-t)/u+2)/6:o=((t-s)/u+4)/6}return pt(e)==="#000000"?Te(o,Math.min(i,.6),.12):Te(o,Math.min(i,.2),.95)}function gt(e,t,s=60){if(Math.abs(xe(e,t))>=s)return e;const a=parseInt(e.slice(1,3),16)/255,n=parseInt(e.slice(3,5),16)/255,r=parseInt(e.slice(5,7),16)/255,o=Math.max(a,n,r),i=Math.min(a,n,r);let d=0,u=0,f=(o+i)/2;if(o!==i){const p=o-i;u=f>.5?p/(2-o-i):p/(o+i),o===a?d=((n-r)/p+(n<r?6:0))/6:o===n?d=((r-a)/p+2)/6:d=((a-n)/p+4)/6}const v=za(t)>.5?-.005:.005;for(let p=0;p<100;p++){f=Math.min(1,Math.max(0,f+v));const S=Te(d,u,f);if(Math.abs(xe(S,t))>=s)return S}return e}function Te(e,t,s){const a=(d,u,f)=>(f<0&&(f+=1),f>1&&(f-=1),f<.16666666666666666?d+(u-d)*6*f:f<.5?u:f<.6666666666666666?d+(u-d)*(.6666666666666666-f)*6:d);let n,r,o;if(t===0)n=r=o=s;else{const d=s<.5?s*(1+t):s+t-s*t,u=2*s-d;n=a(u,d,e+1/3),r=a(u,d,e),o=a(u,d,e-1/3)}const i=d=>Math.round(d*255).toString(16).padStart(2,"0");return`#${i(n)}${i(r)}${i(o)}`}function Ea(e,t){const[s,a,n]=G(e);return t?q(s,a*.3,Math.min(1,n+(1-n)*.85)):q(s,a,Math.min(.25,n+.04))}const me={subtle:{light:.95,dark:.12},text:{light:.28,dark:.78}};function fe(e,t){const[s,a]=G(e);return q(s,a*.5,t?me.subtle.light:me.subtle.dark)}function pe(e,t){const[s,a]=G(e);return q(s,a,t?me.text.light:me.text.dark)}function Pe(e,t,s){const a={},n=s==="light";if("borderDefault"in e&&("borderSubtle"in e||(a.borderSubtle=j(t.borderDefault,n?.05:-.02)),"borderStrong"in e||(a.borderStrong=j(t.borderDefault,n?-.27:.19))),"bgBase"in e&&("bgSubtle"in e||(a.bgSubtle=j(t.bgBase,n?-.02:.02)),"surfaceTint"in e||(a.surfaceTint=j(t.bgBase,n?-.04:.03)),!("surface"in e))){const r=Ea(t.bgBase,n);a.surface=r,"surfaceSecondary"in e||(a.surfaceSecondary=j(r,n?-.04:.03)),"surfaceRaised"in e||(a.surfaceRaised=j(r,n?0:.06)),"surfaceOverlay"in e||(a.surfaceOverlay=j(r,n?0:.06))}return"surface"in e&&("surfaceSecondary"in e||(a.surfaceSecondary=j(t.surface,n?-.04:.03)),"surfaceRaised"in e||(a.surfaceRaised=j(t.surface,n?0:.06)),"surfaceOverlay"in e||(a.surfaceOverlay=j(t.surface,n?0:.06))),"textPrimary"in e&&("textSecondary"in e||(a.textSecondary=j(t.textPrimary,n?.2:-.15)),"textDisabled"in e||(a.textDisabled=j(t.textPrimary,n?.58:-.62))),"accentDefault"in e&&("accentHover"in e||(a.accentHover=j(t.accentDefault,n?.05:-.07)),"accentSubtle"in e||(a.accentSubtle=j(t.accentDefault,n?.85:-.6))),"successDefault"in e&&("successSubtle"in e||(a.successSubtle=fe(t.successDefault,n)),"successText"in e||(a.successText=pe(t.successDefault,n))),"warningDefault"in e&&("warningSubtle"in e||(a.warningSubtle=fe(t.warningDefault,n)),"warningText"in e||(a.warningText=pe(t.warningDefault,n))),"dangerDefault"in e&&("dangerHover"in e||(a.dangerHover=j(t.dangerDefault,n?.05:-.07)),"dangerSubtle"in e||(a.dangerSubtle=fe(t.dangerDefault,n)),"dangerText"in e||(a.dangerText=pe(t.dangerDefault,n))),"infoDefault"in e&&("infoSubtle"in e||(a.infoSubtle=fe(t.infoDefault,n)),"infoText"in e||(a.infoText=pe(t.infoDefault,n))),a}function Ce(e,t="light"){const a={...t==="dark"?$e:re,...e},n=Pe(e,a,t),r=t==="light"?j(a.accentDefault,-.15):j(a.accentDefault,.15);return{...a,...n,accentFg:Le(a.accentDefault),accentBorder:r}}const Fe={name:"default",light:{bgBase:"#ffffff",surface:"#ffffff",borderDefault:"#e5e7eb",accentDefault:"#111827",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#111318",surface:"#181a20",borderDefault:"#2e3039",accentDefault:"#f9fafb",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},bt={name:"brand",light:{bgBase:"#fffefb",surface:"#fffdf7",borderDefault:"#e8e3d6",accentDefault:"#e9c96b",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#151310",surface:"#1c1a15",borderDefault:"#33302a",accentDefault:"#e9c96b",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},se={name:"indigo",light:{bgBase:"#fdfcff",surface:"#faf9fe",borderDefault:"#e0dde9",accentDefault:"#6366f1",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#12111a",surface:"#191820",borderDefault:"#2e2d3a",accentDefault:"#818cf8",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},xt={name:"violet",light:{bgBase:"#fdfcfe",surface:"#faf8fd",borderDefault:"#e2dce9",accentDefault:"#8b5cf6",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#13111a",surface:"#1a1822",borderDefault:"#302d3b",accentDefault:"#a78bfa",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},He={name:"emerald",light:{bgBase:"#fbfefc",surface:"#f7fcf9",borderDefault:"#dbe8df",accentDefault:"#10b981",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#0f1512",surface:"#151c18",borderDefault:"#263330",accentDefault:"#34d399",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},Na={name:"teal",light:{bgBase:"#fbfefd",surface:"#f6fcfa",borderDefault:"#d4e5e0",accentDefault:"#0d9488",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#0f1514",surface:"#161d1c",borderDefault:"#283836",accentDefault:"#2dd4bf",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},We={name:"rose",light:{bgBase:"#fffcfd",surface:"#fef9fa",borderDefault:"#ecdde1",accentDefault:"#f43f5e",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#161012",surface:"#1d1518",borderDefault:"#3a282e",accentDefault:"#fb7185",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},mt={name:"coral",light:{bgBase:"#fffcfb",surface:"#fef9f7",borderDefault:"#e9ddd8",accentDefault:"#e8624a",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#b91c1c",infoDefault:"#2563eb"},dark:{bgBase:"#171210",surface:"#1e1816",borderDefault:"#3b312c",accentDefault:"#f38b76",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},Aa={name:"amber",light:{bgBase:"#fffefb",surface:"#fefcf6",borderDefault:"#e8e1d0",accentDefault:"#d97706",successDefault:"#16a34a",warningDefault:"#b45309",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#171310",surface:"#1e1a15",borderDefault:"#3a3329",accentDefault:"#f59e0b",successDefault:"#22c55e",warningDefault:"#d97706",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},Ee={name:"ocean",light:{bgBase:"#fbfdff",surface:"#f6fafd",borderDefault:"#d9e4ec",accentDefault:"#0ea5e9",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#0e1318",surface:"#141a20",borderDefault:"#243038",accentDefault:"#38bdf8",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},ht={name:"slate",light:{bgBase:"#fafbfc",surface:"#f7f8fa",borderDefault:"#dde1e6",accentDefault:"#475569",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#0f1116",surface:"#161920",borderDefault:"#2b3040",accentDefault:"#94a3b8",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},Oa={name:"sage",light:{bgBase:"#fbfcfb",surface:"#f5f7f5",borderDefault:"#d8ddd6",accentDefault:"#5f8c6e",successDefault:"#16a34a",warningDefault:"#d97706",dangerDefault:"#dc2626",infoDefault:"#2563eb"},dark:{bgBase:"#101410",surface:"#171c17",borderDefault:"#2c372c",accentDefault:"#86b394",successDefault:"#22c55e",warningDefault:"#f59e0b",dangerDefault:"#ef4444",infoDefault:"#3b82f6"}},oe={name:"sharp",tokens:{radiusNone:"0px",radiusSm:"0.125rem",radiusMd:"0.1875rem",radiusLg:"0.25rem",radiusXl:"0.375rem",radiusFull:"9999px"}},ee={name:"rounded",tokens:{radiusNone:"0px",radiusSm:"0.25rem",radiusMd:"0.375rem",radiusLg:"0.5rem",radiusXl:"0.75rem",radiusFull:"9999px"}},le={name:"pill",tokens:{radiusNone:"0px",radiusSm:"0.5rem",radiusMd:"0.75rem",radiusLg:"1rem",radiusXl:"1.5rem",radiusFull:"9999px"}},ce={name:"compact",tokens:{space0:"0px",space1:"0.1rem",space2:"0.25rem",space3:"0.6rem",space4:"0.8rem",space5:"1rem",space6:"1.2rem",space8:"1.6rem",space10:"2rem",space12:"2.4rem",space16:"3.2rem",space20:"4rem",space24:"4.8rem"}},te={name:"default",tokens:{space0:"0px",space1:"0.25rem",space2:"0.5rem",space3:"0.75rem",space4:"1rem",space5:"1.25rem",space6:"1.5rem",space8:"2rem",space10:"2.5rem",space12:"3rem",space16:"4rem",space20:"5rem",space24:"6rem"}},ie={name:"spacious",tokens:{space0:"0px",space1:"0.375rem",space2:"0.75rem",space3:"1.125rem",space4:"1.25rem",space5:"1.5625rem",space6:"1.875rem",space8:"2.5rem",space10:"3.125rem",space12:"3.75rem",space16:"5rem",space20:"6.25rem",space24:"7.5rem"}},he={name:"flat",light:{shadowNone:"none",shadowSm:"none",shadowMd:"none",shadowLg:"none",shadowXl:"none"},dark:{shadowNone:"none",shadowSm:"none",shadowMd:"none",shadowLg:"none",shadowXl:"none"}},Ne={name:"subtle",light:{shadowNone:"none",shadowSm:"rgba(17, 17, 26, 0.04) 0px 2px 8px, rgba(17, 17, 26, 0.02) 0px 4px 16px",shadowMd:"rgba(17, 17, 26, 0.06) 0px 4px 16px, rgba(17, 17, 26, 0.03) 0px 8px 32px",shadowLg:"rgba(17, 17, 26, 0.06) 0px 8px 24px, rgba(17, 17, 26, 0.04) 0px 16px 48px",shadowXl:"rgba(17, 17, 26, 0.08) 0px 12px 32px, rgba(17, 17, 26, 0.05) 0px 24px 64px"},dark:{shadowNone:"none",shadowSm:"0 0 20px color-mix(in srgb, var(--lucent-accent-default) 5%, transparent)",shadowMd:"0 0 30px color-mix(in srgb, var(--lucent-accent-default) 7%, transparent), inset 0 1px 0 0 rgba(255, 255, 255, 0.04)",shadowLg:"0 0 40px color-mix(in srgb, var(--lucent-accent-default) 9%, transparent), inset 0 1px 0 0 rgba(255, 255, 255, 0.05)",shadowXl:"0 0 56px color-mix(in srgb, var(--lucent-accent-default) 12%, transparent), inset 0 1px 0 0 rgba(255, 255, 255, 0.06)"}},Ae={name:"elevated",light:{shadowNone:"none",shadowSm:"rgba(17, 17, 26, 0.05) 0px 2px 8px, rgba(17, 17, 26, 0.03) 0px 4px 16px",shadowMd:"rgba(17, 17, 26, 0.1) 0px 4px 16px, rgba(17, 17, 26, 0.05) 0px 8px 32px",shadowLg:"rgba(17, 17, 26, 0.1) 0px 8px 24px, rgba(17, 17, 26, 0.08) 0px 16px 48px",shadowXl:"rgba(17, 17, 26, 0.12) 0px 12px 32px, rgba(17, 17, 26, 0.1) 0px 24px 64px"},dark:{shadowNone:"none",shadowSm:"inset 0 1px 0 0 rgba(255, 255, 255, 0.06), inset 0 0 12px rgba(255, 255, 255, 0.02)",shadowMd:"inset 0 1px 0 0 rgba(255, 255, 255, 0.08), inset 0 0 20px rgba(255, 255, 255, 0.03), 0 0 1px rgba(255, 255, 255, 0.06)",shadowLg:"inset 0 1px 0 0 rgba(255, 255, 255, 0.1), inset 0 0 28px rgba(255, 255, 255, 0.04), 0 0 1px rgba(255, 255, 255, 0.08)",shadowXl:"inset 0 1px 0 0 rgba(255, 255, 255, 0.12), inset 0 0 36px rgba(255, 255, 255, 0.05), 0 0 1px rgba(255, 255, 255, 0.1)"}},Oe={name:"liquidGlass",light:{shadowNone:"none",shadowSm:"0 4px 30px rgba(0, 0, 0, 0.04)",shadowMd:"0 8px 50px rgba(0, 0, 0, 0.05), 0 2px 10px rgba(0, 0, 0, 0.02)",shadowLg:"0 12px 60px rgba(0, 0, 0, 0.06), 0 4px 20px rgba(0, 0, 0, 0.03)",shadowXl:"0 20px 80px rgba(0, 0, 0, 0.08), 0 8px 30px rgba(0, 0, 0, 0.04)"},dark:{shadowNone:"none",shadowSm:"inset 0 1px 0 0 rgba(255, 255, 255, 0.06), 0 0 30px rgba(255, 255, 255, 0.02)",shadowMd:"inset 0 1px 0 0 rgba(255, 255, 255, 0.08), inset 0 0 20px rgba(255, 255, 255, 0.02), 0 0 40px rgba(255, 255, 255, 0.03)",shadowLg:"inset 0 1px 0 0 rgba(255, 255, 255, 0.1), inset 0 0 30px rgba(255, 255, 255, 0.03), 0 0 50px rgba(255, 255, 255, 0.04)",shadowXl:"inset 0 1px 0 0 rgba(255, 255, 255, 0.12), inset 0 0 40px rgba(255, 255, 255, 0.04), 0 0 70px rgba(255, 255, 255, 0.05)"}},Xe={name:"brutalist",light:{shadowNone:"none",shadowSm:"0 0 0 2px var(--lucent-text-primary), 3px 3px 0 0 color-mix(in srgb, var(--lucent-accent-default) 50%, transparent)",shadowMd:"0 0 0 2px var(--lucent-text-primary), 5px 5px 0 0 color-mix(in srgb, var(--lucent-accent-default) 60%, transparent)",shadowLg:"0 0 0 3px var(--lucent-text-primary), 6px 6px 0 0 color-mix(in srgb, var(--lucent-accent-default) 70%, transparent)",shadowXl:"0 0 0 3px var(--lucent-text-primary), 8px 8px 0 0 color-mix(in srgb, var(--lucent-accent-default) 80%, transparent)"},dark:{shadowNone:"none",shadowSm:"0 0 0 2px color-mix(in srgb, var(--lucent-accent-default) 60%, transparent), 3px 3px 0 0 color-mix(in srgb, var(--lucent-accent-default) 30%, transparent)",shadowMd:"0 0 0 2px color-mix(in srgb, var(--lucent-accent-default) 65%, transparent), 5px 5px 0 0 color-mix(in srgb, var(--lucent-accent-default) 35%, transparent)",shadowLg:"0 0 0 3px color-mix(in srgb, var(--lucent-accent-default) 70%, transparent), 6px 6px 0 0 color-mix(in srgb, var(--lucent-accent-default) 40%, transparent)",shadowXl:"0 0 0 3px color-mix(in srgb, var(--lucent-accent-default) 75%, transparent), 8px 8px 0 0 color-mix(in srgb, var(--lucent-accent-default) 45%, transparent)"}},qe={name:"neumorphic",light:{shadowNone:"none",shadowSm:"3px 3px 8px #d1d5db, -3px -3px 8px #ffffff",shadowMd:"5px 5px 14px #d1d5db, -5px -5px 14px #ffffff",shadowLg:"8px 8px 20px #d1d5db, -8px -8px 20px #ffffff",shadowXl:"12px 12px 28px #d1d5db, -12px -12px 28px #ffffff"},dark:{shadowNone:"none",shadowSm:"3px 3px 10px color-mix(in srgb, var(--lucent-accent-default) 12%, transparent), -3px -3px 10px rgba(255, 255, 255, 0.03)",shadowMd:"5px 5px 16px color-mix(in srgb, var(--lucent-accent-default) 15%, transparent), -5px -5px 16px rgba(255, 255, 255, 0.04)",shadowLg:"8px 8px 24px color-mix(in srgb, var(--lucent-accent-default) 18%, transparent), -8px -8px 24px rgba(255, 255, 255, 0.05)",shadowXl:"12px 12px 32px color-mix(in srgb, var(--lucent-accent-default) 22%, transparent), -12px -12px 32px rgba(255, 255, 255, 0.06)"}},Ue={name:"natural",light:{shadowNone:"none",shadowSm:"0 1px 1px rgba(0, 0, 0, 0.06), 0 2px 4px rgba(0, 0, 0, 0.06)",shadowMd:"0 1px 2px rgba(0, 0, 0, 0.06), 0 2px 4px rgba(0, 0, 0, 0.06), 0 4px 8px rgba(0, 0, 0, 0.06)",shadowLg:"0 1px 2px rgba(0, 0, 0, 0.05), 0 2px 4px rgba(0, 0, 0, 0.05), 0 4px 8px rgba(0, 0, 0, 0.05), 0 8px 16px rgba(0, 0, 0, 0.05)",shadowXl:"0 1px 2px rgba(0, 0, 0, 0.04), 0 2px 4px rgba(0, 0, 0, 0.04), 0 4px 8px rgba(0, 0, 0, 0.04), 0 8px 16px rgba(0, 0, 0, 0.04), 0 16px 32px rgba(0, 0, 0, 0.04)"},dark:{shadowNone:"none",shadowSm:"inset 0 1px 0 0 rgba(255, 255, 255, 0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.03)",shadowMd:"inset 0 1px 0 0 rgba(255, 255, 255, 0.07), inset 0 0 0 1px rgba(255, 255, 255, 0.04), 0 1px 3px rgba(0, 0, 0, 0.15)",shadowLg:"inset 0 1px 0 0 rgba(255, 255, 255, 0.09), inset 0 0 0 1px rgba(255, 255, 255, 0.05), inset 0 0 16px rgba(255, 255, 255, 0.02), 0 2px 6px rgba(0, 0, 0, 0.15)",shadowXl:"inset 0 1px 0 0 rgba(255, 255, 255, 0.12), inset 0 0 0 1px rgba(255, 255, 255, 0.06), inset 0 0 24px rgba(255, 255, 255, 0.03), 0 4px 10px rgba(0, 0, 0, 0.15)"}},ve={name:"glow",light:{shadowNone:"none",shadowSm:"0 1px 3px rgba(0, 0, 0, 0.06), 0 0 12px color-mix(in srgb, var(--lucent-accent-default) 12%, transparent)",shadowMd:"0 2px 6px rgba(0, 0, 0, 0.06), 0 0 20px color-mix(in srgb, var(--lucent-accent-default) 16%, transparent)",shadowLg:"0 4px 10px rgba(0, 0, 0, 0.06), 0 0 30px color-mix(in srgb, var(--lucent-accent-default) 20%, transparent)",shadowXl:"0 6px 14px rgba(0, 0, 0, 0.06), 0 0 44px color-mix(in srgb, var(--lucent-accent-default) 25%, transparent)"},dark:{shadowNone:"none",shadowSm:"0 0 16px color-mix(in srgb, var(--lucent-accent-default) 20%, transparent)",shadowMd:"0 0 24px color-mix(in srgb, var(--lucent-accent-default) 28%, transparent)",shadowLg:"0 0 36px color-mix(in srgb, var(--lucent-accent-default) 35%, transparent)",shadowXl:"0 0 50px color-mix(in srgb, var(--lucent-accent-default) 40%, transparent)"}},vt={name:"modern",palette:se,shape:ee,density:te,shadow:Ne},yt={name:"enterprise",palette:Fe,shape:oe,density:ce,shadow:he},wt={name:"playful",palette:We,shape:le,density:ie,shadow:Ae},St={name:"liquidGlass",palette:Ee,shape:le,density:ie,shadow:Oe},kt={name:"bento",palette:se,shape:ee,density:te,shadow:Ue},Dt={name:"brutalist",palette:mt,shape:oe,density:ce,shadow:Xe},Mt={name:"terminal",palette:He,shape:oe,density:ce,shadow:ve},jt={name:"softUI",palette:xt,shape:le,density:te,shadow:qe},Tt={name:"bloom",palette:se,shape:ee,density:ie,shadow:ve},zt={name:"minimal",palette:ht,shape:ee,density:te,shadow:he},Xa={default:Fe,brand:bt,indigo:se,violet:xt,emerald:He,teal:Na,rose:We,coral:mt,amber:Aa,ocean:Ee,slate:ht,sage:Oa},qa={sharp:oe,rounded:ee,pill:le},Ua={compact:ce,default:te,spacious:ie},Ga={flat:he,subtle:Ne,elevated:Ae,liquidGlass:Oe,brutalist:Xe,neumorphic:qe,natural:Ue,glow:ve},Va={modern:vt,enterprise:yt,playful:wt,liquidGlass:St,bento:kt,brutalist:Dt,terminal:Mt,softUI:jt,bloom:Tt,minimal:zt};function _a(e){return typeof e=="string"?Xa[e]:e}function Ka(e){return typeof e=="string"?qa[e]:e}function Ya(e){return typeof e=="string"?Ua[e]:e}function Za(e){return typeof e=="string"?Ga[e]:e}function It(e,t){let s,a,n,r;if(typeof e=="string"){const i=Va[e];if(!i)return{};s=i.palette,a=i.shape,n=i.density,r=i.shadow}else e.palette!==void 0&&(s=_a(e.palette)),e.shape!==void 0&&(a=Ka(e.shape)),e.density!==void 0&&(n=Ya(e.density)),e.shadow!==void 0&&(r=Za(e.shadow));const o={};if(s){const i=Ce(s[t],t);Object.assign(o,i)}return a&&Object.assign(o,a.tokens),n&&Object.assign(o,n.tokens),r&&Object.assign(o,r[t]),o}const Bt=b.createContext({theme:"light",tokens:re});function Ja({theme:e="light",preset:t,tokens:s,anchors:a,children:n}){const r=b.useId().replace(/:/g,""),o=t?It(t,e):void 0,i=(()=>{if(a){const k=Ce(a,e);if(o){const y={};for(const[x,h]of Object.entries(o))(x.startsWith("space")||x.startsWith("radius")||x.startsWith("shadow")||x.startsWith("duration")||x.startsWith("easing"))&&(y[x]=h);return{...k,...y}}return k}const u=e==="dark"?$e:re,f=o?{...o,...s}:s,g=f?{...u,...f}:u,v=f?Pe(f,g,e):{},p=(f==null?void 0:f.accentBorder)??(e==="light"?j(g.accentDefault,-.15):j(g.accentDefault,.15)),S=(f==null?void 0:f.accentFg)??Le(g.accentDefault),M=gt(g.accentDefault,S);return{...g,...v,accentDefault:M,accentFg:S,accentBorder:p}})(),d=`html { font-size: 14px; }
109
109
  `+ft(i,":root");return b.useLayoutEffect(()=>{let u=document.getElementById(`lucent-tokens-${r}`);return u||(u=document.createElement("style"),u.id=`lucent-tokens-${r}`,document.head.appendChild(u)),u.textContent=d,()=>{var f;(f=document.getElementById(`lucent-tokens-${r}`))==null||f.remove()}},[r,d]),l.jsx(Bt.Provider,{value:{theme:e,tokens:i},children:n})}function Qa(){return b.useContext(Bt)}exports.Badge=Xt;exports.Button=ze;exports.ColorPicker=ot;exports.ColorSwatch=ne;exports.Input=K;exports.LucentProvider=Ja;exports.SegmentedControl=Be;exports.Select=Ie;exports.Slider=sa;exports.Tabs=ha;exports.Text=ta;exports.Toggle=Vt;exports.adjustLightness=j;exports.bentoPreset=kt;exports.bloomPreset=Tt;exports.brandPalette=bt;exports.brutalistPreset=Dt;exports.brutalistShadow=Xe;exports.compactDensity=ce;exports.createTheme=Ce;exports.darkShadowTokens=ct;exports.darkTokens=$e;exports.defaultDensity=te;exports.defaultPalette=Fe;exports.deriveDarkFromLight=ut;exports.deriveTokens=Pe;exports.elevatedShadow=Ae;exports.emeraldPalette=He;exports.ensureContrast=gt;exports.enterprisePreset=yt;exports.flatShadow=he;exports.getAccentFg=Le;exports.getContrastText=pt;exports.glowShadow=ve;exports.hexToHsl=G;exports.hslToHex=q;exports.indigoPalette=se;exports.lightShadowTokens=lt;exports.lightTokens=re;exports.liquidGlassPreset=St;exports.liquidGlassShadow=Oe;exports.makeLibraryCSS=ft;exports.minimalPreset=zt;exports.modernPreset=vt;exports.naturalShadow=Ue;exports.neumorphicShadow=qe;exports.oceanPalette=Ee;exports.pillShape=le;exports.playfulPreset=wt;exports.resolvePreset=It;exports.rosePalette=We;exports.roundedShape=ee;exports.sharpShape=oe;exports.softUIPreset=jt;exports.spaciousDensity=ie;exports.subtleShadow=Ne;exports.terminalPreset=Mt;exports.tokenToCssVar=dt;exports.useLucent=Qa;
package/dist/devtools.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),h=require("react"),ne=require("react-dom"),s=require("./LucentProvider-DQ46gmxN.cjs");function oe(){const{tokens:t}=s.useLucent(),[n,o]=h.useState({}),i=h.useRef(n);i.current=n;const c=h.useCallback((f,d)=>{document.documentElement.style.setProperty(s.tokenToCssVar(f),d),o(m=>({...m,[f]:d}))},[]),l=h.useCallback(f=>{document.documentElement.style.removeProperty(s.tokenToCssVar(f)),o(d=>{const m={...d};return delete m[f],m})},[]),u=h.useCallback(()=>{for(const f of Object.keys(i.current))document.documentElement.style.removeProperty(s.tokenToCssVar(f));o({})},[]);return{tokens:t,overrides:n,overrideCount:Object.keys(n).length,setOverride:c,removeOverride:l,resetAll:u}}function y(t){return{key:t,controlType:"color"}}function p(t,n,o,i,c){return{key:t,controlType:"slider",sliderConfig:{min:n,max:o,step:i,unit:c}}}function g(t){return{key:t,controlType:"text"}}const J=[{label:"Colors",defaultExpanded:!0,subgroups:[{label:"Background",tokens:[y("bgBase"),y("bgSubtle"),y("bgOverlay")]},{label:"Surface",tokens:[y("surface"),y("surfaceSecondary"),y("surfaceRaised"),y("surfaceOverlay"),y("surfaceTint")]},{label:"Border",tokens:[y("borderDefault"),y("borderSubtle"),y("borderStrong"),y("controlTrack")]},{label:"Text",tokens:[y("textPrimary"),y("textSecondary"),y("textDisabled"),y("textInverse")]},{label:"Accent",tokens:[y("accentDefault"),y("accentHover"),y("accentSubtle"),y("accentBorder"),y("accentFg")]},{label:"Success",tokens:[y("successDefault"),y("successSubtle"),y("successText")]},{label:"Warning",tokens:[y("warningDefault"),y("warningSubtle"),y("warningText")]},{label:"Danger",tokens:[y("dangerDefault"),y("dangerHover"),y("dangerSubtle"),y("dangerText")]},{label:"Info",tokens:[y("infoDefault"),y("infoSubtle"),y("infoText")]}]},{label:"Typography",tokens:[g("fontFamilyBase"),g("fontFamilyMono"),g("fontFamilyDisplay"),p("fontSizeXs",.5,2,.0625,"rem"),p("fontSizeSm",.5,2,.0625,"rem"),p("fontSizeMd",.5,2,.0625,"rem"),p("fontSizeLg",.5,3,.0625,"rem"),p("fontSizeXl",.5,3,.0625,"rem"),p("fontSize2xl",.5,4,.0625,"rem"),p("fontSize3xl",.5,4,.0625,"rem"),g("fontWeightRegular"),g("fontWeightMedium"),g("fontWeightSemibold"),g("fontWeightBold"),g("lineHeightTight"),g("lineHeightBase"),g("lineHeightRelaxed"),g("letterSpacingTight"),g("letterSpacingBase"),g("letterSpacingWide")]},{label:"Spacing",tokens:[p("space0",0,6,.125,"rem"),p("space1",0,6,.125,"rem"),p("space2",0,6,.125,"rem"),p("space3",0,6,.125,"rem"),p("space4",0,6,.125,"rem"),p("space5",0,6,.125,"rem"),p("space6",0,6,.125,"rem"),p("space8",0,6,.125,"rem"),p("space10",0,6,.125,"rem"),p("space12",0,8,.125,"rem"),p("space16",0,10,.125,"rem"),p("space20",0,12,.125,"rem"),p("space24",0,12,.125,"rem")]},{label:"Radius",tokens:[g("radiusNone"),p("radiusSm",0,2,.0625,"rem"),p("radiusMd",0,2,.0625,"rem"),p("radiusLg",0,2,.0625,"rem"),p("radiusXl",0,3,.0625,"rem"),g("radiusFull")]},{label:"Shadows",tokens:[g("shadowNone"),g("shadowSm"),g("shadowMd"),g("shadowLg"),g("shadowXl")]},{label:"Motion",tokens:[g("durationFast"),g("durationBase"),g("durationSlow"),g("easingDefault"),g("easingEmphasized"),g("easingDecelerate")]}];function re(t){return Object.keys(t).length===0?`<LucentProvider>
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),h=require("react"),ne=require("react-dom"),s=require("./LucentProvider-we0nRXn-.cjs");function oe(){const{tokens:t}=s.useLucent(),[n,o]=h.useState({}),i=h.useRef(n);i.current=n;const c=h.useCallback((f,d)=>{document.documentElement.style.setProperty(s.tokenToCssVar(f),d),o(m=>({...m,[f]:d}))},[]),l=h.useCallback(f=>{document.documentElement.style.removeProperty(s.tokenToCssVar(f)),o(d=>{const m={...d};return delete m[f],m})},[]),u=h.useCallback(()=>{for(const f of Object.keys(i.current))document.documentElement.style.removeProperty(s.tokenToCssVar(f));o({})},[]);return{tokens:t,overrides:n,overrideCount:Object.keys(n).length,setOverride:c,removeOverride:l,resetAll:u}}function y(t){return{key:t,controlType:"color"}}function p(t,n,o,i,c){return{key:t,controlType:"slider",sliderConfig:{min:n,max:o,step:i,unit:c}}}function g(t){return{key:t,controlType:"text"}}const J=[{label:"Colors",defaultExpanded:!0,subgroups:[{label:"Background",tokens:[y("bgBase"),y("bgSubtle"),y("bgOverlay")]},{label:"Surface",tokens:[y("surface"),y("surfaceSecondary"),y("surfaceRaised"),y("surfaceOverlay"),y("surfaceTint")]},{label:"Border",tokens:[y("borderDefault"),y("borderSubtle"),y("borderStrong"),y("controlTrack")]},{label:"Text",tokens:[y("textPrimary"),y("textSecondary"),y("textDisabled"),y("textInverse")]},{label:"Accent",tokens:[y("accentDefault"),y("accentHover"),y("accentSubtle"),y("accentBorder"),y("accentFg")]},{label:"Success",tokens:[y("successDefault"),y("successSubtle"),y("successText")]},{label:"Warning",tokens:[y("warningDefault"),y("warningSubtle"),y("warningText")]},{label:"Danger",tokens:[y("dangerDefault"),y("dangerHover"),y("dangerSubtle"),y("dangerText")]},{label:"Info",tokens:[y("infoDefault"),y("infoSubtle"),y("infoText")]}]},{label:"Typography",tokens:[g("fontFamilyBase"),g("fontFamilyMono"),g("fontFamilyDisplay"),p("fontSizeXs",.5,2,.0625,"rem"),p("fontSizeSm",.5,2,.0625,"rem"),p("fontSizeMd",.5,2,.0625,"rem"),p("fontSizeLg",.5,3,.0625,"rem"),p("fontSizeXl",.5,3,.0625,"rem"),p("fontSize2xl",.5,4,.0625,"rem"),p("fontSize3xl",.5,4,.0625,"rem"),g("fontWeightRegular"),g("fontWeightMedium"),g("fontWeightSemibold"),g("fontWeightBold"),g("lineHeightTight"),g("lineHeightBase"),g("lineHeightRelaxed"),g("letterSpacingTight"),g("letterSpacingBase"),g("letterSpacingWide")]},{label:"Spacing",tokens:[p("space0",0,6,.125,"rem"),p("space1",0,6,.125,"rem"),p("space2",0,6,.125,"rem"),p("space3",0,6,.125,"rem"),p("space4",0,6,.125,"rem"),p("space5",0,6,.125,"rem"),p("space6",0,6,.125,"rem"),p("space8",0,6,.125,"rem"),p("space10",0,6,.125,"rem"),p("space12",0,8,.125,"rem"),p("space16",0,10,.125,"rem"),p("space20",0,12,.125,"rem"),p("space24",0,12,.125,"rem")]},{label:"Radius",tokens:[g("radiusNone"),p("radiusSm",0,2,.0625,"rem"),p("radiusMd",0,2,.0625,"rem"),p("radiusLg",0,2,.0625,"rem"),p("radiusXl",0,3,.0625,"rem"),g("radiusFull")]},{label:"Shadows",tokens:[g("shadowNone"),g("shadowSm"),g("shadowMd"),g("shadowLg"),g("shadowXl")]},{label:"Motion",tokens:[g("durationFast"),g("durationBase"),g("durationSlow"),g("easingDefault"),g("easingEmphasized"),g("easingDecelerate")]}];function re(t){return Object.keys(t).length===0?`<LucentProvider>
2
2
  {children}
3
3
  </LucentProvider>`:`<LucentProvider tokens={{
4
4
  ${Object.entries(t).map(([o,i])=>` ${o}: '${i}'`).join(`,
package/dist/devtools.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsxs as c, jsx as t, Fragment as fe } from "react/jsx-runtime";
2
2
  import { useState as C, useRef as ue, useCallback as O, useEffect as N, useMemo as me, createContext as be } from "react";
3
3
  import { createPortal as ve } from "react-dom";
4
- import { _ as ye, $ as S, T as h, C as E, B as M, e as _, I as he, a0 as xe, a1 as Se, z as ke, K as we, M as Ce, m as ze, F as Be, u as Te, Y as Me, x as Fe, a as B, a2 as Re, a3 as ne, g as De, a4 as Oe, S as Le, d as oe, p as Pe, h as Ee, f as Ie, b as Ae } from "./LucentProvider-BAYI38i6.js";
4
+ import { _ as ye, $ as S, T as h, C as E, B as M, e as _, I as he, a0 as xe, a1 as Se, z as ke, K as we, M as Ce, m as ze, F as Be, u as Te, Y as Me, x as Fe, a as B, a2 as Re, a3 as ne, g as De, a4 as Oe, S as Le, d as oe, p as Pe, h as Ee, f as Ie, b as Ae } from "./LucentProvider-BoiXYqA4.js";
5
5
  function Ge() {
6
6
  const { tokens: e } = ye(), [n, o] = C({}), s = ue(n);
7
7
  s.current = n;
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),C=require("./LucentProvider-DQ46gmxN.cjs"),c=require("react"),J=require("react-dom"),wt={id:"button",name:"Button",tier:"atom",domain:"neutral",specVersion:"1.0",description:"A clickable control that triggers an action. The primary interactive primitive in Lucent UI.",designIntent:'Buttons communicate available actions. Variant conveys hierarchy: use "primary" for the single most important action in a view, "secondary" for supporting actions, "ghost" for low-emphasis actions in dense UIs, "outline" for bordered buttons with transparent background, and "danger" exclusively for destructive or irreversible operations. Use "danger-ghost" for low-emphasis destructive actions (red text, no fill) and "danger-outline" for bordered destructive buttons (also transparent background). Size should match surrounding content density — prefer "md" as the default, "sm" for toolbars or tables, "xs" for compact UIs like customizer panels, and "2xs" for ultra-dense inline controls (~22px height) such as table-inline actions or toolbar icon triggers. Icon-only buttons (leftIcon/rightIcon without children) automatically render as square with aspect-ratio: 1.',props:[{name:"variant",type:"enum",required:!1,default:"primary",description:'Visual style conveying action hierarchy. "primary" — filled accent for the single most important action. "secondary" — subtle accent-tinted fill for supporting actions. "outline" — bordered with no fill, for neutral secondary actions. "ghost" — transparent with no border, for low-emphasis or inline actions. "danger" — filled red for irreversible destructive actions (e.g. "Delete account"). "danger-outline" — red border + red text for destructive actions that need visual weight without a filled background. "danger-ghost" — red text only, for low-emphasis destructive actions (e.g. "Remove" in a list row).',enumValues:["primary","secondary","outline","ghost","danger","danger-outline","danger-ghost"]},{name:"size",type:"enum",required:!1,default:"md",description:'Controls height and padding. "lg" (48px) — hero sections, onboarding flows. "md" (42px) — default for most forms and dialogs. "sm" (34px) — toolbars, table headers, card actions. "xs" (26px) — compact UIs like customizer panels, inline controls. "2xs" (22px) — ultra-dense inline icon triggers, table-row actions, dashboard toolbar buttons.',enumValues:["2xs","xs","sm","md","lg"]},{name:"children",type:"ReactNode",required:!1,description:"Button label or content. Omit for icon-only buttons (provide leftIcon or rightIcon instead)."},{name:"disabled",type:"boolean",required:!1,default:"false",description:"Prevents interaction and applies disabled styling."},{name:"loading",type:"boolean",required:!1,default:"false",description:"Shows a spinner and prevents interaction while an async action is in progress."},{name:"fullWidth",type:"boolean",required:!1,default:"false",description:"Stretches the button to fill its container width."},{name:"bordered",type:"boolean",required:!1,default:"true",description:"When false removes the button border entirely, producing a flat look."},{name:"leftIcon",type:"ReactNode",required:!1,description:"Icon element rendered before the label."},{name:"rightIcon",type:"ReactNode",required:!1,description:"Icon element rendered after the label."},{name:"chevron",type:"boolean",required:!1,default:"false",description:"Appends a chevron-down icon after the label. Useful for dropdown triggers."},{name:"spread",type:"boolean",required:!1,default:"false",description:"Spaces content to the edges (justify-content: space-between). Useful with fullWidth + rightIcon/chevron."},{name:"onClick",type:"function",required:!1,description:"Called when the button is clicked and not disabled or loading."},{name:"type",type:"enum",required:!1,default:"button",description:"Native button type attribute.",enumValues:["button","submit","reset"]}],usageExamples:[{title:"Primary action",code:'<Button variant="primary" onClick={handleSave}>Save changes</Button>'},{title:"Destructive action",code:'<Button variant="danger" onClick={handleDelete}>Delete account</Button>'},{title:"Loading state",code:'<Button variant="primary" loading={isSaving}>Save changes</Button>'},{title:"With icon",code:'<Button variant="secondary" leftIcon={<PlusIcon />}>Add member</Button>'},{title:"Ghost in toolbar",code:'<Button variant="ghost" size="sm">Edit</Button>'},{title:"Full-width submit",code:'<Button variant="primary" type="submit" fullWidth>Sign in</Button>'},{title:"Outline with swatch",code:`<Button size="xs" variant="outline" leftIcon={<span style={{ width: 8, height: 8, borderRadius: '50%', background: '#6366f1' }} />}>Indigo</Button>`},{title:"Dropdown trigger",code:'<Button variant="outline" chevron>Options</Button>'},{title:"Bordered destructive action",code:'<Button variant="danger-outline" onClick={handleRevoke}>Revoke access</Button>'},{title:"Low-emphasis destructive action",code:'<Button variant="danger-ghost" onClick={handleRemove}>Remove</Button>'},{title:"Dense inline action",code:'<Button variant="ghost" size="2xs" leftIcon={<RefreshIcon />}>Retry</Button>'},{title:"Icon-only (square)",code:'<Button variant="outline" size="2xs" leftIcon={<CloseIcon />} aria-label="Close" />',description:"Omitting children auto-sizes the button as a square via aspect-ratio: 1."}],compositionGraph:[],accessibility:{role:"button",ariaAttributes:["aria-disabled","aria-busy"],keyboardInteractions:["Enter — activates the button","Space — activates the button"]}},kt={id:"input",name:"Input",tier:"atom",domain:"neutral",specVersion:"0.1",description:"A single-line text field with optional label, helper text, and error state.",designIntent:"Always pair with a visible label — never rely on placeholder text alone as it disappears on input and is inaccessible. Use errorText (not helperText) to surface validation failures; the component applies danger styling automatically. leftElement and rightElement accept icons or small controls (e.g. currency symbol, clear button).",props:[{name:"size",type:"enum",required:!1,default:"md",description:"Controls height, font size, and padding. Label and helper text scale accordingly.",enumValues:["sm","md","lg"]},{name:"type",type:"enum",required:!1,default:"text",description:"HTML input type.",enumValues:["text","number","password","email","tel","url","search","color"]},{name:"label",type:"string",required:!1,description:"Visible label rendered above the input."},{name:"helperText",type:"string",required:!1,description:"Supplementary hint shown below the input."},{name:"errorText",type:"string",required:!1,description:"Validation error message. When set, input renders in error state."},{name:"leftElement",type:"ReactNode",required:!1,description:"Icon or adornment rendered inside the left edge."},{name:"rightElement",type:"ReactNode",required:!1,description:"Icon or adornment rendered inside the right edge."},{name:"placeholder",type:"string",required:!1,description:"Placeholder text. Use as a hint, not a label."},{name:"prefix",type:"ReactNode",required:!1,description:'Inset label attached to the left of the field (e.g. "$", "https://").'},{name:"suffix",type:"ReactNode",required:!1,description:'Inset label attached to the right of the field (e.g. "kg", ".com").'},{name:"disabled",type:"boolean",required:!1,default:"false",description:"Disables the input."},{name:"value",type:"string",required:!1,description:"Controlled value."},{name:"onChange",type:"function",required:!1,description:"Change handler."}],usageExamples:[{title:"Basic",code:'<Input label="Email" type="email" placeholder="you@example.com" />'},{title:"With helper text",code:'<Input label="Username" helperText="3–20 characters, letters and numbers only" />'},{title:"Error state",code:'<Input label="Password" type="password" value={value} errorText="Must be at least 8 characters" />'},{title:"With icon",code:'<Input label="Search" leftElement={<SearchIcon />} placeholder="Search…" />'}],compositionGraph:[],accessibility:{role:"textbox",ariaAttributes:["aria-invalid","aria-describedby","aria-label"],keyboardInteractions:["Tab — focuses the input"]}},St={sm:"var(--lucent-font-size-sm)",md:"var(--lucent-font-size-md)",lg:"var(--lucent-font-size-md)"},Tt={sm:"var(--lucent-font-size-sm)",md:"var(--lucent-font-size-sm)",lg:"var(--lucent-font-size-md)"},Ct={sm:"var(--lucent-space-3)",md:"var(--lucent-space-4)",lg:"var(--lucent-space-4)"},nt=c.forwardRef(({label:t,helperText:r,errorText:n,autoResize:o=!1,maxLength:a,showCount:i=!1,size:l="md",id:s,value:d,onChange:f,disabled:m,style:p,...k},x)=>{const g=c.useRef(null),h=x??g,u=s??`lucent-textarea-${Math.random().toString(36).slice(2,7)}`,b=!!n,w=!!m,y=typeof d=="string"?d.length:0;c.useEffect(()=>{if(!o)return;const I=h.current;I&&(I.style.height="auto",I.style.height=`${I.scrollHeight}px`)},[d,o,h]);const S=w?"transparent":b?"var(--lucent-danger-default)":"var(--lucent-border-default)";return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"var(--lucent-space-1)",width:"100%"},children:[t&&e.jsx("label",{htmlFor:u,style:{fontSize:Tt[l],fontWeight:"var(--lucent-font-weight-medium)",color:w?"var(--lucent-text-disabled)":"var(--lucent-text-primary)",fontFamily:"var(--lucent-font-family-base)"},children:t}),e.jsx("textarea",{ref:h,id:u,maxLength:a,value:d,onChange:f,disabled:m,"aria-invalid":b,"aria-describedby":b?`${u}-error`:r?`${u}-helper`:void 0,style:{width:"100%",minHeight:"100px",padding:Ct[l],fontSize:St[l],fontFamily:"var(--lucent-font-family-base)",color:w?"var(--lucent-text-disabled)":"var(--lucent-text-primary)",background:w?"color-mix(in srgb, var(--lucent-text-primary) 6%, transparent)":"var(--lucent-surface)",border:`1px solid ${S}`,borderRadius:"var(--lucent-radius-lg)",outline:"none",resize:o?"none":"vertical",boxSizing:"border-box",lineHeight:"var(--lucent-line-height-base)",cursor:w?"not-allowed":void 0,transition:["border-color var(--lucent-duration-fast) var(--lucent-easing-default)","box-shadow var(--lucent-duration-fast) var(--lucent-easing-default)"].join(", "),...p},onMouseEnter:I=>{var v;!w&&I.currentTarget!==document.activeElement&&(I.currentTarget.style.borderColor=b?"var(--lucent-danger-default)":"var(--lucent-border-strong)"),(v=k.onMouseEnter)==null||v.call(k,I)},onMouseLeave:I=>{var v;!w&&I.currentTarget!==document.activeElement&&(I.currentTarget.style.borderColor=b?"var(--lucent-danger-default)":"var(--lucent-border-default)"),(v=k.onMouseLeave)==null||v.call(k,I)},onFocus:I=>{var v;w||(I.currentTarget.style.borderColor=b?"var(--lucent-danger-default)":"var(--lucent-accent-border)",I.currentTarget.style.boxShadow=`0 0 0 3px ${b?"var(--lucent-danger-subtle)":"var(--lucent-accent-subtle)"}`,(v=k.onFocus)==null||v.call(k,I))},onBlur:I=>{var v;w||(I.currentTarget.style.borderColor=b?"var(--lucent-danger-default)":"var(--lucent-border-default)",I.currentTarget.style.boxShadow="none",(v=k.onBlur)==null||v.call(k,I))},...k}),e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start"},children:[e.jsxs("div",{children:[b&&e.jsx("span",{id:`${u}-error`,role:"alert",style:{fontSize:"var(--lucent-font-size-sm)",color:"var(--lucent-danger-text)",fontFamily:"var(--lucent-font-family-base)"},children:n}),!b&&r&&e.jsx("span",{id:`${u}-helper`,style:{fontSize:"var(--lucent-font-size-sm)",color:"var(--lucent-text-secondary)",fontFamily:"var(--lucent-font-family-base)"},children:r})]}),(i||a)&&e.jsxs("span",{style:{fontSize:"var(--lucent-font-size-xs)",color:a&&y>=a?"var(--lucent-danger-text)":"var(--lucent-text-secondary)",fontFamily:"var(--lucent-font-family-mono)",flexShrink:0,marginLeft:"var(--lucent-space-2)"},children:[y,a?`/${a}`:""]})]})]})});nt.displayName="Textarea";const It={id:"textarea",name:"Textarea",tier:"atom",domain:"neutral",specVersion:"0.1",description:"A multi-line text input with optional auto-resize and character count.",designIntent:"Use autoResize for open-ended fields (bio, description) where content length is unpredictable. Use maxLength + showCount for fields with hard limits (tweet-style). Behaves identically to Input for label/helper/error patterns.",props:[{name:"label",type:"string",required:!1,description:"Visible label above the textarea."},{name:"helperText",type:"string",required:!1,description:"Hint text shown below."},{name:"errorText",type:"string",required:!1,description:"Validation error. Triggers error styling."},{name:"autoResize",type:"boolean",required:!1,default:"false",description:"Grows with content, disables manual resize handle."},{name:"maxLength",type:"number",required:!1,description:"Character limit. Displays counter when set."},{name:"showCount",type:"boolean",required:!1,default:"false",description:"Always show character counter even without maxLength."},{name:"value",type:"string",required:!1,description:"Controlled value."},{name:"onChange",type:"function",required:!1,description:"Change handler."},{name:"placeholder",type:"string",required:!1,description:"Placeholder text."},{name:"size",type:"enum",required:!1,default:"md",description:"Controls font size and padding.",enumValues:["sm","md","lg"]},{name:"disabled",type:"boolean",required:!1,default:"false",description:"Disables the textarea."}],usageExamples:[{title:"Basic",code:'<Textarea label="Bio" placeholder="Tell us about yourself…" />'},{title:"Auto-resize",code:'<Textarea label="Description" autoResize value={value} onChange={e => setValue(e.target.value)} />'},{title:"With character count",code:'<Textarea label="Tweet" maxLength={280} showCount value={value} onChange={e => setValue(e.target.value)} />'},{title:"Error state",code:'<Textarea label="Notes" errorText="Required" value="" />'}],compositionGraph:[],accessibility:{role:"textbox",ariaAttributes:["aria-multiline","aria-invalid","aria-describedby"],keyboardInteractions:["Tab — focuses the textarea"]}},jt={id:"badge",name:"Badge",tier:"atom",domain:"neutral",specVersion:"0.1",description:"A small inline label for status, count, or category.",designIntent:'Badges communicate status or category at a glance. Match variant to semantic meaning — never use "danger" for non-critical states or "success" for neutral counts. Use dot=true when a single colour indicator is enough context (e.g. online status). Keep badge text short: 1–3 words maximum.',props:[{name:"variant",type:"enum",required:!1,default:"neutral",description:"Colour scheme conveying semantic meaning.",enumValues:["neutral","success","warning","danger","info","accent"]},{name:"size",type:"enum",required:!1,default:"md",description:"Controls height and font size.",enumValues:["sm","md"]},{name:"dot",type:"boolean",required:!1,default:"false",description:"Prepends a coloured dot indicator."},{name:"children",type:"ReactNode",required:!0,description:"Badge label."}],usageExamples:[{title:"Status",code:'<Badge variant="success" dot>Active</Badge>'},{title:"Count",code:'<Badge variant="danger">12</Badge>'},{title:"Category",code:'<Badge variant="info">Beta</Badge>'},{title:"Neutral tag",code:"<Badge>Draft</Badge>"}],compositionGraph:[],accessibility:{role:"status",notes:"Use aria-label on the parent element when badge meaning depends on context."}},Mt={neutral:{bg:"var(--lucent-surface-secondary)",color:"var(--lucent-text-secondary)",border:"var(--lucent-border-default)",hoverBg:"var(--lucent-surface-hover, #e5e7eb)",hoverBorder:"var(--lucent-border-strong)"},accent:{bg:"var(--lucent-accent-default)",color:"var(--lucent-accent-fg)",border:"var(--lucent-accent-default)",hoverBg:"var(--lucent-accent-hover)",hoverBorder:"var(--lucent-accent-hover)"},success:{bg:"var(--lucent-success-subtle)",color:"var(--lucent-success-text)",border:"var(--lucent-success-subtle)",hoverBg:"color-mix(in srgb, var(--lucent-success-default) 15%, var(--lucent-success-subtle))",hoverBorder:"var(--lucent-success-default)"},warning:{bg:"var(--lucent-warning-subtle)",color:"var(--lucent-warning-text)",border:"var(--lucent-warning-subtle)",hoverBg:"color-mix(in srgb, var(--lucent-warning-default) 15%, var(--lucent-warning-subtle))",hoverBorder:"var(--lucent-warning-default)"},danger:{bg:"var(--lucent-danger-subtle)",color:"var(--lucent-danger-text)",border:"var(--lucent-danger-subtle)",hoverBg:"color-mix(in srgb, var(--lucent-danger-default) 15%, var(--lucent-danger-subtle))",hoverBorder:"var(--lucent-danger-default)"},info:{bg:"var(--lucent-info-subtle)",color:"var(--lucent-info-text)",border:"var(--lucent-info-subtle)",hoverBg:"color-mix(in srgb, var(--lucent-info-default) 15%, var(--lucent-info-subtle))",hoverBorder:"var(--lucent-info-default)"}},zt={sm:{fontSize:"var(--lucent-font-size-xs)",height:"calc(var(--lucent-space-5) * 0.5 + 10px)",padding:"var(--lucent-space-1) var(--lucent-space-2)",paddingDismiss:"var(--lucent-space-1) var(--lucent-space-1) var(--lucent-space-1) var(--lucent-space-2)",iconSize:12,dotSize:6,gap:"var(--lucent-space-1)"},md:{fontSize:"var(--lucent-font-size-sm)",height:"calc(var(--lucent-space-6) * 0.5 + 12px)",padding:"var(--lucent-space-1) var(--lucent-space-2)",paddingDismiss:"var(--lucent-space-1) var(--lucent-space-1) var(--lucent-space-1) var(--lucent-space-2)",iconSize:14,dotSize:7,gap:"var(--lucent-space-2)"},lg:{fontSize:"var(--lucent-font-size-md)",height:"calc(var(--lucent-space-8) * 0.5 + 14px)",padding:"var(--lucent-space-1) var(--lucent-space-3)",paddingDismiss:"var(--lucent-space-1) var(--lucent-space-2) var(--lucent-space-1) var(--lucent-space-3)",iconSize:16,dotSize:8,gap:"var(--lucent-space-2)"}},Et=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),C=require("./LucentProvider-we0nRXn-.cjs"),c=require("react"),J=require("react-dom"),wt={id:"button",name:"Button",tier:"atom",domain:"neutral",specVersion:"1.0",description:"A clickable control that triggers an action. The primary interactive primitive in Lucent UI.",designIntent:'Buttons communicate available actions. Variant conveys hierarchy: use "primary" for the single most important action in a view, "secondary" for supporting actions, "ghost" for low-emphasis actions in dense UIs, "outline" for bordered buttons with transparent background, and "danger" exclusively for destructive or irreversible operations. Use "danger-ghost" for low-emphasis destructive actions (red text, no fill) and "danger-outline" for bordered destructive buttons (also transparent background). Size should match surrounding content density — prefer "md" as the default, "sm" for toolbars or tables, "xs" for compact UIs like customizer panels, and "2xs" for ultra-dense inline controls (~22px height) such as table-inline actions or toolbar icon triggers. Icon-only buttons (leftIcon/rightIcon without children) automatically render as square with aspect-ratio: 1.',props:[{name:"variant",type:"enum",required:!1,default:"primary",description:'Visual style conveying action hierarchy. "primary" — filled accent for the single most important action. "secondary" — subtle accent-tinted fill for supporting actions. "outline" — bordered with no fill, for neutral secondary actions. "ghost" — transparent with no border, for low-emphasis or inline actions. "danger" — filled red for irreversible destructive actions (e.g. "Delete account"). "danger-outline" — red border + red text for destructive actions that need visual weight without a filled background. "danger-ghost" — red text only, for low-emphasis destructive actions (e.g. "Remove" in a list row).',enumValues:["primary","secondary","outline","ghost","danger","danger-outline","danger-ghost"]},{name:"size",type:"enum",required:!1,default:"md",description:'Controls height and padding. "lg" (48px) — hero sections, onboarding flows. "md" (42px) — default for most forms and dialogs. "sm" (34px) — toolbars, table headers, card actions. "xs" (26px) — compact UIs like customizer panels, inline controls. "2xs" (22px) — ultra-dense inline icon triggers, table-row actions, dashboard toolbar buttons.',enumValues:["2xs","xs","sm","md","lg"]},{name:"children",type:"ReactNode",required:!1,description:"Button label or content. Omit for icon-only buttons (provide leftIcon or rightIcon instead)."},{name:"disabled",type:"boolean",required:!1,default:"false",description:"Prevents interaction and applies disabled styling."},{name:"loading",type:"boolean",required:!1,default:"false",description:"Shows a spinner and prevents interaction while an async action is in progress."},{name:"fullWidth",type:"boolean",required:!1,default:"false",description:"Stretches the button to fill its container width."},{name:"bordered",type:"boolean",required:!1,default:"true",description:"When false removes the button border entirely, producing a flat look."},{name:"leftIcon",type:"ReactNode",required:!1,description:"Icon element rendered before the label."},{name:"rightIcon",type:"ReactNode",required:!1,description:"Icon element rendered after the label."},{name:"chevron",type:"boolean",required:!1,default:"false",description:"Appends a chevron-down icon after the label. Useful for dropdown triggers."},{name:"spread",type:"boolean",required:!1,default:"false",description:"Spaces content to the edges (justify-content: space-between). Useful with fullWidth + rightIcon/chevron."},{name:"onClick",type:"function",required:!1,description:"Called when the button is clicked and not disabled or loading."},{name:"type",type:"enum",required:!1,default:"button",description:"Native button type attribute.",enumValues:["button","submit","reset"]}],usageExamples:[{title:"Primary action",code:'<Button variant="primary" onClick={handleSave}>Save changes</Button>'},{title:"Destructive action",code:'<Button variant="danger" onClick={handleDelete}>Delete account</Button>'},{title:"Loading state",code:'<Button variant="primary" loading={isSaving}>Save changes</Button>'},{title:"With icon",code:'<Button variant="secondary" leftIcon={<PlusIcon />}>Add member</Button>'},{title:"Ghost in toolbar",code:'<Button variant="ghost" size="sm">Edit</Button>'},{title:"Full-width submit",code:'<Button variant="primary" type="submit" fullWidth>Sign in</Button>'},{title:"Outline with swatch",code:`<Button size="xs" variant="outline" leftIcon={<span style={{ width: 8, height: 8, borderRadius: '50%', background: '#6366f1' }} />}>Indigo</Button>`},{title:"Dropdown trigger",code:'<Button variant="outline" chevron>Options</Button>'},{title:"Bordered destructive action",code:'<Button variant="danger-outline" onClick={handleRevoke}>Revoke access</Button>'},{title:"Low-emphasis destructive action",code:'<Button variant="danger-ghost" onClick={handleRemove}>Remove</Button>'},{title:"Dense inline action",code:'<Button variant="ghost" size="2xs" leftIcon={<RefreshIcon />}>Retry</Button>'},{title:"Icon-only (square)",code:'<Button variant="outline" size="2xs" leftIcon={<CloseIcon />} aria-label="Close" />',description:"Omitting children auto-sizes the button as a square via aspect-ratio: 1."}],compositionGraph:[],accessibility:{role:"button",ariaAttributes:["aria-disabled","aria-busy"],keyboardInteractions:["Enter — activates the button","Space — activates the button"]}},kt={id:"input",name:"Input",tier:"atom",domain:"neutral",specVersion:"0.1",description:"A single-line text field with optional label, helper text, and error state.",designIntent:"Always pair with a visible label — never rely on placeholder text alone as it disappears on input and is inaccessible. Use errorText (not helperText) to surface validation failures; the component applies danger styling automatically. leftElement and rightElement accept icons or small controls (e.g. currency symbol, clear button).",props:[{name:"size",type:"enum",required:!1,default:"md",description:"Controls height, font size, and padding. Label and helper text scale accordingly.",enumValues:["sm","md","lg"]},{name:"type",type:"enum",required:!1,default:"text",description:"HTML input type.",enumValues:["text","number","password","email","tel","url","search","color"]},{name:"label",type:"string",required:!1,description:"Visible label rendered above the input."},{name:"helperText",type:"string",required:!1,description:"Supplementary hint shown below the input."},{name:"errorText",type:"string",required:!1,description:"Validation error message. When set, input renders in error state."},{name:"leftElement",type:"ReactNode",required:!1,description:"Icon or adornment rendered inside the left edge."},{name:"rightElement",type:"ReactNode",required:!1,description:"Icon or adornment rendered inside the right edge."},{name:"placeholder",type:"string",required:!1,description:"Placeholder text. Use as a hint, not a label."},{name:"prefix",type:"ReactNode",required:!1,description:'Inset label attached to the left of the field (e.g. "$", "https://").'},{name:"suffix",type:"ReactNode",required:!1,description:'Inset label attached to the right of the field (e.g. "kg", ".com").'},{name:"disabled",type:"boolean",required:!1,default:"false",description:"Disables the input."},{name:"value",type:"string",required:!1,description:"Controlled value."},{name:"onChange",type:"function",required:!1,description:"Change handler."}],usageExamples:[{title:"Basic",code:'<Input label="Email" type="email" placeholder="you@example.com" />'},{title:"With helper text",code:'<Input label="Username" helperText="3–20 characters, letters and numbers only" />'},{title:"Error state",code:'<Input label="Password" type="password" value={value} errorText="Must be at least 8 characters" />'},{title:"With icon",code:'<Input label="Search" leftElement={<SearchIcon />} placeholder="Search…" />'}],compositionGraph:[],accessibility:{role:"textbox",ariaAttributes:["aria-invalid","aria-describedby","aria-label"],keyboardInteractions:["Tab — focuses the input"]}},St={sm:"var(--lucent-font-size-sm)",md:"var(--lucent-font-size-md)",lg:"var(--lucent-font-size-md)"},Tt={sm:"var(--lucent-font-size-sm)",md:"var(--lucent-font-size-sm)",lg:"var(--lucent-font-size-md)"},Ct={sm:"var(--lucent-space-3)",md:"var(--lucent-space-4)",lg:"var(--lucent-space-4)"},nt=c.forwardRef(({label:t,helperText:r,errorText:n,autoResize:o=!1,maxLength:a,showCount:i=!1,size:l="md",id:s,value:d,onChange:f,disabled:m,style:p,...k},x)=>{const g=c.useRef(null),h=x??g,u=s??`lucent-textarea-${Math.random().toString(36).slice(2,7)}`,b=!!n,w=!!m,y=typeof d=="string"?d.length:0;c.useEffect(()=>{if(!o)return;const I=h.current;I&&(I.style.height="auto",I.style.height=`${I.scrollHeight}px`)},[d,o,h]);const S=w?"transparent":b?"var(--lucent-danger-default)":"var(--lucent-border-default)";return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"var(--lucent-space-1)",width:"100%"},children:[t&&e.jsx("label",{htmlFor:u,style:{fontSize:Tt[l],fontWeight:"var(--lucent-font-weight-medium)",color:w?"var(--lucent-text-disabled)":"var(--lucent-text-primary)",fontFamily:"var(--lucent-font-family-base)"},children:t}),e.jsx("textarea",{ref:h,id:u,maxLength:a,value:d,onChange:f,disabled:m,"aria-invalid":b,"aria-describedby":b?`${u}-error`:r?`${u}-helper`:void 0,style:{width:"100%",minHeight:"100px",padding:Ct[l],fontSize:St[l],fontFamily:"var(--lucent-font-family-base)",color:w?"var(--lucent-text-disabled)":"var(--lucent-text-primary)",background:w?"color-mix(in srgb, var(--lucent-text-primary) 6%, transparent)":"var(--lucent-surface)",border:`1px solid ${S}`,borderRadius:"var(--lucent-radius-lg)",outline:"none",resize:o?"none":"vertical",boxSizing:"border-box",lineHeight:"var(--lucent-line-height-base)",cursor:w?"not-allowed":void 0,transition:["border-color var(--lucent-duration-fast) var(--lucent-easing-default)","box-shadow var(--lucent-duration-fast) var(--lucent-easing-default)"].join(", "),...p},onMouseEnter:I=>{var v;!w&&I.currentTarget!==document.activeElement&&(I.currentTarget.style.borderColor=b?"var(--lucent-danger-default)":"var(--lucent-border-strong)"),(v=k.onMouseEnter)==null||v.call(k,I)},onMouseLeave:I=>{var v;!w&&I.currentTarget!==document.activeElement&&(I.currentTarget.style.borderColor=b?"var(--lucent-danger-default)":"var(--lucent-border-default)"),(v=k.onMouseLeave)==null||v.call(k,I)},onFocus:I=>{var v;w||(I.currentTarget.style.borderColor=b?"var(--lucent-danger-default)":"var(--lucent-accent-border)",I.currentTarget.style.boxShadow=`0 0 0 3px ${b?"var(--lucent-danger-subtle)":"var(--lucent-accent-subtle)"}`,(v=k.onFocus)==null||v.call(k,I))},onBlur:I=>{var v;w||(I.currentTarget.style.borderColor=b?"var(--lucent-danger-default)":"var(--lucent-border-default)",I.currentTarget.style.boxShadow="none",(v=k.onBlur)==null||v.call(k,I))},...k}),e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start"},children:[e.jsxs("div",{children:[b&&e.jsx("span",{id:`${u}-error`,role:"alert",style:{fontSize:"var(--lucent-font-size-sm)",color:"var(--lucent-danger-text)",fontFamily:"var(--lucent-font-family-base)"},children:n}),!b&&r&&e.jsx("span",{id:`${u}-helper`,style:{fontSize:"var(--lucent-font-size-sm)",color:"var(--lucent-text-secondary)",fontFamily:"var(--lucent-font-family-base)"},children:r})]}),(i||a)&&e.jsxs("span",{style:{fontSize:"var(--lucent-font-size-xs)",color:a&&y>=a?"var(--lucent-danger-text)":"var(--lucent-text-secondary)",fontFamily:"var(--lucent-font-family-mono)",flexShrink:0,marginLeft:"var(--lucent-space-2)"},children:[y,a?`/${a}`:""]})]})]})});nt.displayName="Textarea";const It={id:"textarea",name:"Textarea",tier:"atom",domain:"neutral",specVersion:"0.1",description:"A multi-line text input with optional auto-resize and character count.",designIntent:"Use autoResize for open-ended fields (bio, description) where content length is unpredictable. Use maxLength + showCount for fields with hard limits (tweet-style). Behaves identically to Input for label/helper/error patterns.",props:[{name:"label",type:"string",required:!1,description:"Visible label above the textarea."},{name:"helperText",type:"string",required:!1,description:"Hint text shown below."},{name:"errorText",type:"string",required:!1,description:"Validation error. Triggers error styling."},{name:"autoResize",type:"boolean",required:!1,default:"false",description:"Grows with content, disables manual resize handle."},{name:"maxLength",type:"number",required:!1,description:"Character limit. Displays counter when set."},{name:"showCount",type:"boolean",required:!1,default:"false",description:"Always show character counter even without maxLength."},{name:"value",type:"string",required:!1,description:"Controlled value."},{name:"onChange",type:"function",required:!1,description:"Change handler."},{name:"placeholder",type:"string",required:!1,description:"Placeholder text."},{name:"size",type:"enum",required:!1,default:"md",description:"Controls font size and padding.",enumValues:["sm","md","lg"]},{name:"disabled",type:"boolean",required:!1,default:"false",description:"Disables the textarea."}],usageExamples:[{title:"Basic",code:'<Textarea label="Bio" placeholder="Tell us about yourself…" />'},{title:"Auto-resize",code:'<Textarea label="Description" autoResize value={value} onChange={e => setValue(e.target.value)} />'},{title:"With character count",code:'<Textarea label="Tweet" maxLength={280} showCount value={value} onChange={e => setValue(e.target.value)} />'},{title:"Error state",code:'<Textarea label="Notes" errorText="Required" value="" />'}],compositionGraph:[],accessibility:{role:"textbox",ariaAttributes:["aria-multiline","aria-invalid","aria-describedby"],keyboardInteractions:["Tab — focuses the textarea"]}},jt={id:"badge",name:"Badge",tier:"atom",domain:"neutral",specVersion:"0.1",description:"A small inline label for status, count, or category.",designIntent:'Badges communicate status or category at a glance. Match variant to semantic meaning — never use "danger" for non-critical states or "success" for neutral counts. Use dot=true when a single colour indicator is enough context (e.g. online status). Keep badge text short: 1–3 words maximum.',props:[{name:"variant",type:"enum",required:!1,default:"neutral",description:"Colour scheme conveying semantic meaning.",enumValues:["neutral","success","warning","danger","info","accent"]},{name:"size",type:"enum",required:!1,default:"md",description:"Controls height and font size.",enumValues:["sm","md"]},{name:"dot",type:"boolean",required:!1,default:"false",description:"Prepends a coloured dot indicator."},{name:"children",type:"ReactNode",required:!0,description:"Badge label."}],usageExamples:[{title:"Status",code:'<Badge variant="success" dot>Active</Badge>'},{title:"Count",code:'<Badge variant="danger">12</Badge>'},{title:"Category",code:'<Badge variant="info">Beta</Badge>'},{title:"Neutral tag",code:"<Badge>Draft</Badge>"}],compositionGraph:[],accessibility:{role:"status",notes:"Use aria-label on the parent element when badge meaning depends on context."}},Mt={neutral:{bg:"var(--lucent-surface-secondary)",color:"var(--lucent-text-secondary)",border:"var(--lucent-border-default)",hoverBg:"var(--lucent-surface-hover, #e5e7eb)",hoverBorder:"var(--lucent-border-strong)"},accent:{bg:"var(--lucent-accent-default)",color:"var(--lucent-accent-fg)",border:"var(--lucent-accent-default)",hoverBg:"var(--lucent-accent-hover)",hoverBorder:"var(--lucent-accent-hover)"},success:{bg:"var(--lucent-success-subtle)",color:"var(--lucent-success-text)",border:"var(--lucent-success-subtle)",hoverBg:"color-mix(in srgb, var(--lucent-success-default) 15%, var(--lucent-success-subtle))",hoverBorder:"var(--lucent-success-default)"},warning:{bg:"var(--lucent-warning-subtle)",color:"var(--lucent-warning-text)",border:"var(--lucent-warning-subtle)",hoverBg:"color-mix(in srgb, var(--lucent-warning-default) 15%, var(--lucent-warning-subtle))",hoverBorder:"var(--lucent-warning-default)"},danger:{bg:"var(--lucent-danger-subtle)",color:"var(--lucent-danger-text)",border:"var(--lucent-danger-subtle)",hoverBg:"color-mix(in srgb, var(--lucent-danger-default) 15%, var(--lucent-danger-subtle))",hoverBorder:"var(--lucent-danger-default)"},info:{bg:"var(--lucent-info-subtle)",color:"var(--lucent-info-text)",border:"var(--lucent-info-subtle)",hoverBg:"color-mix(in srgb, var(--lucent-info-default) 15%, var(--lucent-info-subtle))",hoverBorder:"var(--lucent-info-default)"}},zt={sm:{fontSize:"var(--lucent-font-size-xs)",height:"calc(var(--lucent-space-5) * 0.5 + 10px)",padding:"var(--lucent-space-1) var(--lucent-space-2)",paddingDismiss:"var(--lucent-space-1) var(--lucent-space-1) var(--lucent-space-1) var(--lucent-space-2)",iconSize:12,dotSize:6,gap:"var(--lucent-space-1)"},md:{fontSize:"var(--lucent-font-size-sm)",height:"calc(var(--lucent-space-6) * 0.5 + 12px)",padding:"var(--lucent-space-1) var(--lucent-space-2)",paddingDismiss:"var(--lucent-space-1) var(--lucent-space-1) var(--lucent-space-1) var(--lucent-space-2)",iconSize:14,dotSize:7,gap:"var(--lucent-space-2)"},lg:{fontSize:"var(--lucent-font-size-md)",height:"calc(var(--lucent-space-8) * 0.5 + 14px)",padding:"var(--lucent-space-1) var(--lucent-space-3)",paddingDismiss:"var(--lucent-space-1) var(--lucent-space-2) var(--lucent-space-1) var(--lucent-space-3)",iconSize:16,dotSize:8,gap:"var(--lucent-space-2)"}},Et=`
2
2
  @keyframes lucent-chip-pulse {
3
3
  0% { transform: scale(1); opacity: 0.6; }
4
4
  100% { transform: scale(2.8); opacity: 0; }
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsxs as g, jsx as e, Fragment as Q } from "react/jsx-runtime";
2
- import { T as V, I as ut, B as ce, g as St, a as Me } from "./LucentProvider-BAYI38i6.js";
3
- import { b as gi, C as vi, c as bi, L as yi, S as xi, d as wi, e as ki, f as Si, h as Ti, i as Ci, j as Ii, k as Mi, l as zi, m as Ei, n as Ai, o as qi, p as Di, q as Bi, r as Ri, s as Li, t as Pi, u as Fi, v as Ni, w as $i, x as Wi, y as Oi, z as Vi, A as Hi, D as Gi, E as Ui, F as ji, G as _i, H as Yi, J as Ki, K as Xi, M as Ji, N as Zi, O as Qi, P as es, Q as ts, R as ns, U as rs, V as as, W as os, X as is, Y as ss, Z as ls, _ as cs } from "./LucentProvider-BAYI38i6.js";
2
+ import { T as V, I as ut, B as ce, g as St, a as Me } from "./LucentProvider-BoiXYqA4.js";
3
+ import { b as gi, C as vi, c as bi, L as yi, S as xi, d as wi, e as ki, f as Si, h as Ti, i as Ci, j as Ii, k as Mi, l as zi, m as Ei, n as Ai, o as qi, p as Di, q as Bi, r as Ri, s as Li, t as Pi, u as Fi, v as Ni, w as $i, x as Wi, y as Oi, z as Vi, A as Hi, D as Gi, E as Ui, F as ji, G as _i, H as Yi, J as Ki, K as Xi, M as Ji, N as Zi, O as Qi, P as es, Q as ts, R as ns, U as rs, V as as, W as os, X as is, Y as ss, Z as ls, _ as cs } from "./LucentProvider-BoiXYqA4.js";
4
4
  import { forwardRef as pt, useRef as $, useEffect as H, useState as z, useCallback as J, useContext as ee, createContext as fe, useLayoutEffect as te, useId as Pe, Children as Tt, isValidElement as Ct, cloneElement as It } from "react";
5
5
  import { createPortal as ae } from "react-dom";
6
6
  const Ra = {
@@ -0,0 +1,197 @@
1
+ // ─── Design Rules ────────────────────────────────────────────────────────────
2
+ // Structured layout guidance injected into the MCP system prompt so AI agents
3
+ // produce aesthetically consistent Lucent UI layouts, not just valid props.
4
+ export const DESIGN_RULES = [
5
+ {
6
+ id: 'spacing',
7
+ title: 'Spacing scale',
8
+ body: `
9
+ Use Stack and Row components for all layout — never raw flexbox.
10
+ Gap values map to the spacing token scale (default density, 14px base):
11
+
12
+ | Gap | Token | Rem | ~px | Use for |
13
+ |-----|----------|---------|-----|-----------------------------------------------------|
14
+ | 0 | space-0 | 0 | 0 | Stacked label + description (no visible gap) |
15
+ | 1 | space-1 | 0.25rem | 3.5 | Tight inline pairs: icon + label, badge + name |
16
+ | 2 | space-2 | 0.5rem | 7 | Related items in a row: chip gap, button-group gap |
17
+ | 3 | space-3 | 0.75rem | 10 | Label-to-control gap, rows in a settings list |
18
+ | 4 | space-4 | 1rem | 14 | Sections within a card, standard Stack gap (default) |
19
+ | 5 | space-5 | 1.25rem | 17 | Between content blocks inside a page section |
20
+ | 6 | space-6 | 1.5rem | 21 | Card-to-card gap, major section separation |
21
+ | 8 | space-8 | 2rem | 28 | Page-level section separation |
22
+ | 10+ | space-10+| 2.5rem+ | 35+ | Hero spacing, page margins (rare in components) |
23
+
24
+ Card padding sizes:
25
+ - sm: py=space-2, px=space-3 — compact lists, dense data
26
+ - md: py=space-4, px=space-5 — forms, standard content (default)
27
+ - lg: py=space-6, px=space-8 — hero content, featured cards
28
+ `.trim(),
29
+ },
30
+ {
31
+ id: 'typography',
32
+ title: 'Typography hierarchy',
33
+ body: `
34
+ Always use the Text component — never raw HTML tags with inline font styles.
35
+ Three font families: base (DM Sans), mono (DM Mono), display (Georama).
36
+ Use display family for large numeric values (stats, prices, counters).
37
+
38
+ | Role | Size | Weight | Color | Element | Family |
39
+ |--------------|------|----------|-----------|---------|---------|
40
+ | Page title | 2xl | bold | primary | h1 | base |
41
+ | Section head | lg | semibold | primary | h2 | base |
42
+ | Card title | md | semibold | primary | h3 | base |
43
+ | Body text | sm | regular | primary | p | base |
44
+ | Label | xs | medium | secondary | label | base |
45
+ | Caption | xs | regular | secondary | span | base |
46
+ | Stat value | 2xl | bold | primary | span | display |
47
+ | Code/mono | sm | regular | primary | code | mono |
48
+
49
+ Font size scale (14px base):
50
+ - xs: 0.75rem (10.5px) — labels, captions, metadata
51
+ - sm: 0.875rem (12.25px) — body text, descriptions
52
+ - md: 1rem (14px) — card titles, emphasized text
53
+ - lg: 1.125rem (15.75px) — section headings
54
+ - xl: 1.25rem (17.5px) — page subtitles
55
+ - 2xl: 1.5rem (21px) — page titles, stat values
56
+ - 3xl: 1.875rem (26.25px) — hero headings (rare)
57
+ `.trim(),
58
+ },
59
+ {
60
+ id: 'buttons',
61
+ title: 'Button pairing rules',
62
+ body: `
63
+ Button variants: primary, secondary (filled), outline (bordered), ghost, danger.
64
+
65
+ Pairing guidelines:
66
+ - Primary + Outline: balanced dual actions (Save / Cancel, Confirm / Back)
67
+ - Primary + Ghost: dominant + dismiss (Submit / Reset, Continue / Skip)
68
+ - Single Primary: sole call-to-action (Sign up, Follow, Add to cart)
69
+ - Outline only: equal-weight options in a row (Edit, Share, Export)
70
+ - Danger + Outline: destructive confirmation (Delete / Cancel)
71
+ - Never place two primary buttons in the same Row
72
+
73
+ Size pairing:
74
+ - Buttons in the same Row should use the same size
75
+ - Form action buttons: md (default)
76
+ - Card inline actions: sm
77
+ - Toolbar/compact actions: xs
78
+ - Button heights (border-box): sm=34px, md=42px, lg=48px — these align with input total heights
79
+
80
+ Icon usage:
81
+ - leftIcon for semantic context (+ Add, ↓ Download)
82
+ - rightIcon for directional flow (Next →)
83
+ - chevron prop for dropdown triggers (built-in chevron-down SVG)
84
+ `.trim(),
85
+ },
86
+ {
87
+ id: 'layout',
88
+ title: 'Common layout patterns',
89
+ body: `
90
+ Always use Stack (vertical) and Row (horizontal) — never raw div with flex styles.
91
+ Stack default gap: 4. Row default gap: 3.
92
+
93
+ Toggle / checkbox row:
94
+ Row gap="3" align="center"
95
+ ├── Toggle or Checkbox
96
+ └── Stack gap="0"
97
+ ├── Text size="sm" weight="medium" ← label
98
+ └── Text size="xs" color="secondary" ← description
99
+
100
+ Stats block:
101
+ Stack gap="0" align="center"
102
+ ├── Text size="2xl" weight="bold" family="display" ← value
103
+ └── Text size="xs" color="secondary" ← label
104
+
105
+ Form layout:
106
+ Stack gap="4"
107
+ └── FormField[] ← each field includes its own label + error
108
+
109
+ Action bar (form actions):
110
+ Row gap="2" justify="end"
111
+ ├── Button variant="outline" ← secondary action
112
+ └── Button variant="primary" ← primary action
113
+
114
+ Card content:
115
+ Card padding="md"
116
+ └── Stack gap="4"
117
+ ├── Text size="md" weight="semibold" ← card title
118
+ ├── Stack gap="3" ← card body
119
+ └── Row gap="2" justify="end" ← card actions
120
+
121
+ Page section:
122
+ Stack gap="5"
123
+ ├── Row justify="between" align="center"
124
+ │ ├── Text size="2xl" weight="bold" ← page title
125
+ │ └── Button variant="outline" ← page action
126
+ └── Stack gap="6" ← section content
127
+ `.trim(),
128
+ },
129
+ {
130
+ id: 'color',
131
+ title: 'Color usage',
132
+ body: `
133
+ Lucent uses CSS custom properties for all colors. Never use raw hex values.
134
+
135
+ Text colors (via Text color prop):
136
+ - primary: default text, headings, values
137
+ - secondary: labels, captions, metadata, descriptions
138
+ - disabled: disabled state text (neutral gray, never accent-tinted)
139
+ - inverse: text on dark backgrounds
140
+ - onAccent: text on accent-colored backgrounds (auto-computed for contrast)
141
+ - success / warning / danger / info: semantic status text
142
+
143
+ Surface usage:
144
+ - Card variant="elevated": raised cards with shadow
145
+ - Card variant="outline": bordered cards, lower emphasis
146
+ - Card variant="filled": subtle background fill, no border
147
+
148
+ Accent color:
149
+ - Applied automatically by LucentProvider to primary buttons, toggles, checkboxes, radio
150
+ - textOnAccent is auto-computed via APCA contrast algorithm
151
+ - Light mode default accent: near-black (#111827)
152
+ - Dark mode default accent: near-white (#f9fafb)
153
+ - 12 palette presets available: default, brand, indigo, violet, emerald, teal, rose, coral, amber, ocean, slate, sage
154
+
155
+ Status colors (Chip/Badge/Alert variants):
156
+ - success: positive trends, confirmations, online status
157
+ - warning: attention needed, approaching limits
158
+ - danger: errors, destructive actions, critical alerts
159
+ - info: neutral information, tips, updates
160
+
161
+ Disabled state:
162
+ - Always use neutral gray — never accent-tinted surfaces
163
+ - Applied via color-mix with neutral gray, not opacity
164
+ `.trim(),
165
+ },
166
+ {
167
+ id: 'density',
168
+ title: 'Density and responsive patterns',
169
+ body: `
170
+ Three density presets scale all spacing tokens proportionally:
171
+ - compact: tighter spacing (~80% of default) — data-dense dashboards, admin panels
172
+ - default: standard spacing — general purpose
173
+ - spacious: generous spacing (~125% of default) — marketing, onboarding, hero sections
174
+
175
+ Responsive wrapping:
176
+ - Use Row with wrap prop for responsive card grids
177
+ - Set minWidth on flex children (e.g. style={{ flex: 1, minWidth: 180 }})
178
+ - This creates equal-width cards that wrap gracefully without media queries
179
+
180
+ Card grids:
181
+ Row gap="4" wrap
182
+ └── Card[] style={{ flex: 1, minWidth: 240 }}
183
+
184
+ Compact list items:
185
+ Stack gap="2"
186
+ └── Row[] gap="3" align="center" (each row is an item)
187
+ `.trim(),
188
+ },
189
+ ];
190
+ /** Full design rules as a single markdown string for system prompt injection. */
191
+ export const DESIGN_RULES_TEXT = DESIGN_RULES.map((s) => `## ${s.title}\n\n${s.body}`).join('\n\n');
192
+ /** Compact summary for the system prompt (keeps token budget reasonable). */
193
+ export const DESIGN_RULES_SUMMARY = `# Lucent UI Design Rules
194
+
195
+ These rules ensure AI-generated layouts are aesthetically consistent, not just technically valid.
196
+
197
+ ${DESIGN_RULES_TEXT}`;
@@ -5,6 +5,7 @@ import { z } from 'zod';
5
5
  import { ALL_MANIFESTS } from './registry.js';
6
6
  import { ALL_PATTERNS } from './pattern-registry.js';
7
7
  import { PALETTES, SHAPES, DENSITIES, SHADOWS, COMBINED, generatePresetConfig } from './presets.js';
8
+ import { DESIGN_RULES, DESIGN_RULES_SUMMARY } from './design-rules.js';
8
9
  // ─── Auth stub ───────────────────────────────────────────────────────────────
9
10
  // LUCENT_API_KEY is reserved for the future paid tier.
10
11
  // When set, the server acknowledges it but does not yet enforce it.
@@ -65,6 +66,8 @@ function scorePattern(r, query) {
65
66
  const server = new McpServer({
66
67
  name: 'lucent-mcp',
67
68
  version: '0.1.0',
69
+ }, {
70
+ instructions: DESIGN_RULES_SUMMARY,
68
71
  });
69
72
  // Tool: list_components
70
73
  server.tool('list_components', 'Lists all available Lucent UI components with their name, tier (atom/molecule), and one-line description.', {}, async () => {
@@ -260,6 +263,51 @@ server.tool('get_preset_config', 'Returns the LucentProvider configuration code
260
263
  ],
261
264
  };
262
265
  });
266
+ // Tool: get_design_rules
267
+ server.tool('get_design_rules', 'Returns Lucent UI design rules for spacing, typography, button pairing, layout patterns, color usage, and density. These rules ensure AI-generated layouts are aesthetically consistent. Query a specific section or get all rules.', {
268
+ section: z
269
+ .string()
270
+ .optional()
271
+ .describe('Optional section id: "spacing", "typography", "buttons", "layout", "color", or "density". Omit to get all rules.'),
272
+ }, async ({ section }) => {
273
+ if (section) {
274
+ const s = section.trim().toLowerCase();
275
+ const rule = DESIGN_RULES.find((r) => r.id === s);
276
+ if (!rule) {
277
+ return {
278
+ content: [
279
+ {
280
+ type: 'text',
281
+ text: JSON.stringify({
282
+ error: `Section "${section}" not found.`,
283
+ availableSections: DESIGN_RULES.map((r) => ({
284
+ id: r.id,
285
+ title: r.title,
286
+ })),
287
+ }),
288
+ },
289
+ ],
290
+ isError: true,
291
+ };
292
+ }
293
+ return {
294
+ content: [
295
+ {
296
+ type: 'text',
297
+ text: `## ${rule.title}\n\n${rule.body}`,
298
+ },
299
+ ],
300
+ };
301
+ }
302
+ return {
303
+ content: [
304
+ {
305
+ type: 'text',
306
+ text: DESIGN_RULES_SUMMARY,
307
+ },
308
+ ],
309
+ };
310
+ });
263
311
  // ─── Start ────────────────────────────────────────────────────────────────────
264
312
  const transport = new StdioServerTransport();
265
313
  await server.connect(transport);
@@ -6,6 +6,10 @@ import { PATTERN as FormLayout } from '../src/manifest/patterns/form-layout.patt
6
6
  import { PATTERN as EmptyStateCard } from '../src/manifest/patterns/empty-state-card.pattern.js';
7
7
  import { PATTERN as CollapsibleCard } from '../src/manifest/patterns/collapsible-card.pattern.js';
8
8
  import { PATTERN as SearchFilterBar } from '../src/manifest/patterns/search-filter-bar.pattern.js';
9
+ import { PATTERN as ProductItemCard } from '../src/manifest/patterns/product-item-card.pattern.js';
10
+ import { PATTERN as NotificationCard } from '../src/manifest/patterns/notification-card.pattern.js';
11
+ import { PATTERN as ConfirmationDialog } from '../src/manifest/patterns/confirmation-dialog.pattern.js';
12
+ import { PATTERN as BulkActionBar } from '../src/manifest/patterns/bulk-action-bar.pattern.js';
9
13
  export const ALL_PATTERNS = [
10
14
  ProfileCard,
11
15
  SettingsPanel,
@@ -15,4 +19,8 @@ export const ALL_PATTERNS = [
15
19
  EmptyStateCard,
16
20
  CollapsibleCard,
17
21
  SearchFilterBar,
22
+ ProductItemCard,
23
+ NotificationCard,
24
+ ConfirmationDialog,
25
+ BulkActionBar,
18
26
  ];
@@ -0,0 +1,71 @@
1
+ export const PATTERN = {
2
+ id: 'bulk-action-bar',
3
+ name: 'Bulk Action Bar',
4
+ description: 'Sticky bar that appears when table rows are selected. Shows selection count, bulk action buttons, and a clear selection control.',
5
+ category: 'action',
6
+ components: ['checkbox', 'text', 'button', 'button-group', 'divider', 'row'],
7
+ structure: `
8
+ Row gap="3" align="center" (surface background, padding=md)
9
+ ├── Checkbox (indeterminate when partial)
10
+ ├── Text (sm, semibold) ← "3 selected"
11
+ ├── Divider (vertical)
12
+ ├── ButtonGroup
13
+ │ ├── Button (outline, sm) ← "Export"
14
+ │ ├── Button (outline, sm) ← "Archive"
15
+ │ └── Button (danger-outline, sm) ← "Delete"
16
+ └── Row flex=1 justify="end"
17
+ └── Button (ghost, sm) ← "Clear selection"
18
+ `.trim(),
19
+ code: `<Row gap="3" align="center" style={{ padding: 'var(--lucent-space-3) var(--lucent-space-4)', background: 'var(--lucent-surface)', borderRadius: 'var(--lucent-radius-lg)', border: '1px solid var(--lucent-border-default)' }}>
20
+ <Checkbox indeterminate checked onChange={() => {}} />
21
+ <Text size="sm" weight="semibold">3 selected</Text>
22
+ <Divider orientation="vertical" />
23
+ <ButtonGroup>
24
+ <Button variant="outline" size="sm">Export</Button>
25
+ <Button variant="outline" size="sm">Archive</Button>
26
+ <Button variant="danger-outline" size="sm">Delete</Button>
27
+ </ButtonGroup>
28
+ <Row style={{ flex: 1, justifyContent: 'flex-end' }}>
29
+ <Button variant="ghost" size="sm">Clear selection</Button>
30
+ </Row>
31
+ </Row>`,
32
+ variants: [
33
+ {
34
+ title: 'Minimal (single action)',
35
+ code: `<Row gap="3" align="center" style={{ padding: 'var(--lucent-space-3) var(--lucent-space-4)', background: 'var(--lucent-surface)', borderRadius: 'var(--lucent-radius-lg)', border: '1px solid var(--lucent-border-default)' }}>
36
+ <Checkbox checked onChange={() => {}} />
37
+ <Text size="sm" weight="semibold">12 selected</Text>
38
+ <Row style={{ flex: 1, justifyContent: 'flex-end' }}>
39
+ <Button variant="danger" size="sm">Delete selected</Button>
40
+ </Row>
41
+ </Row>`,
42
+ },
43
+ {
44
+ title: 'With count badge and secondary actions',
45
+ code: `<Row gap="3" align="center" style={{ padding: 'var(--lucent-space-3) var(--lucent-space-4)', background: 'var(--lucent-surface)', borderRadius: 'var(--lucent-radius-lg)', border: '1px solid var(--lucent-border-default)' }}>
46
+ <Checkbox indeterminate checked onChange={() => {}} />
47
+ <Row gap="2" align="center">
48
+ <Text size="sm" weight="semibold">5 of 24 selected</Text>
49
+ <Button variant="ghost" size="xs">Select all</Button>
50
+ </Row>
51
+ <Divider orientation="vertical" />
52
+ <Button variant="outline" size="sm">Assign label</Button>
53
+ <Button variant="outline" size="sm">Move to</Button>
54
+ <Button variant="danger-outline" size="sm">Delete</Button>
55
+ <Row style={{ flex: 1, justifyContent: 'flex-end' }}>
56
+ <Button variant="ghost" size="sm">Clear</Button>
57
+ </Row>
58
+ </Row>`,
59
+ },
60
+ ],
61
+ designNotes: 'The bar uses a Row with center alignment so all elements sit on the same ' +
62
+ 'horizontal baseline. The Checkbox reflects selection state — indeterminate ' +
63
+ 'when some rows are selected, checked when all are. A vertical Divider ' +
64
+ 'visually separates the selection count from the action buttons. ButtonGroup ' +
65
+ 'clusters related actions with shared border radius. The danger-outline ' +
66
+ 'variant on the Delete button signals destructive intent without the visual ' +
67
+ 'weight of a filled danger button. The clear selection Button is pushed to ' +
68
+ 'the far right via flex: 1 on its wrapper Row, keeping it accessible but ' +
69
+ 'visually subordinate. The minimal variant drops the ButtonGroup and Divider ' +
70
+ 'for a simpler single-action layout.',
71
+ };
@@ -0,0 +1,95 @@
1
+ export const PATTERN = {
2
+ id: 'confirmation-dialog',
3
+ name: 'Confirmation Dialog',
4
+ description: 'Centered modal-style card for destructive action confirmations with danger button pairing. For delete/remove/reset flows.',
5
+ category: 'action',
6
+ components: ['card', 'icon', 'text', 'button', 'input', 'stack', 'row'],
7
+ structure: `
8
+ Card (elevated, padding="lg", maxWidth=400)
9
+ └── Stack gap="8" align="center"
10
+ ├── Icon (lg, danger color) ← warning icon
11
+ ├── Stack gap="1" align="center"
12
+ │ ├── Text (lg, semibold, center) ← "Delete project?"
13
+ │ └── Text (sm, secondary, center) ← consequence description
14
+ └── Row gap="3"
15
+ ├── Button (outline, full width) ← "Cancel"
16
+ └── Button (danger, full width) ← "Delete"
17
+ `.trim(),
18
+ code: `<Card variant="elevated" padding="lg" style={{ maxWidth: 400 }}>
19
+ <Stack gap="8" align="center">
20
+ <Icon size="xl" color="var(--lucent-danger-text)">
21
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round">
22
+ <path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" />
23
+ <line x1={12} y1={9} x2={12} y2={13} />
24
+ <line x1={12} y1={17} x2={12.01} y2={17} />
25
+ </svg>
26
+ </Icon>
27
+ <Stack gap="1" align="center">
28
+ <Text size="lg" weight="semibold">Delete project?</Text>
29
+ <Text size="sm" color="secondary" align="center">This will permanently delete "Acme Corp" and all of its data. This action cannot be undone.</Text>
30
+ </Stack>
31
+ <Row gap="3" style={{ width: '100%' }}>
32
+ <Button variant="outline" style={{ flex: 1 }}>Cancel</Button>
33
+ <Button variant="danger" style={{ flex: 1 }}>Delete</Button>
34
+ </Row>
35
+ </Stack>
36
+ </Card>`,
37
+ variants: [
38
+ {
39
+ title: 'With typed confirmation',
40
+ code: `<Card variant="elevated" padding="lg" style={{ maxWidth: 400 }}>
41
+ <Stack gap="8" align="center">
42
+ <Icon size="xl" color="var(--lucent-danger-text)">
43
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round">
44
+ <path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" />
45
+ <line x1={12} y1={9} x2={12} y2={13} />
46
+ <line x1={12} y1={17} x2={12.01} y2={17} />
47
+ </svg>
48
+ </Icon>
49
+ <Stack gap="1" align="center">
50
+ <Text size="lg" weight="semibold">Delete your account?</Text>
51
+ <Text size="sm" color="secondary" align="center">All projects, data, and billing history will be permanently removed. Type DELETE to confirm.</Text>
52
+ </Stack>
53
+ <Input placeholder="Type DELETE to confirm" size="md" style={{ width: '100%' }} />
54
+ <Row gap="3" style={{ width: '100%' }}>
55
+ <Button variant="outline" style={{ flex: 1 }}>Cancel</Button>
56
+ <Button variant="danger" style={{ flex: 1 }} disabled>Delete account</Button>
57
+ </Row>
58
+ </Stack>
59
+ </Card>`,
60
+ },
61
+ {
62
+ title: 'Non-destructive confirmation',
63
+ code: `<Card variant="elevated" padding="lg" style={{ maxWidth: 400 }}>
64
+ <Stack gap="8" align="center">
65
+ <Icon size="xl" color="var(--lucent-info-text)">
66
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round">
67
+ <circle cx={12} cy={12} r={10} />
68
+ <line x1={12} y1={16} x2={12} y2={12} />
69
+ <line x1={12} y1={8} x2={12.01} y2={8} />
70
+ </svg>
71
+ </Icon>
72
+ <Stack gap="1" align="center">
73
+ <Text size="lg" weight="semibold">Publish changes?</Text>
74
+ <Text size="sm" color="secondary" align="center">This will make your draft visible to all team members. You can unpublish later from settings.</Text>
75
+ </Stack>
76
+ <Row gap="3" style={{ width: '100%' }}>
77
+ <Button variant="outline" style={{ flex: 1 }}>Keep as draft</Button>
78
+ <Button variant="primary" style={{ flex: 1 }}>Publish</Button>
79
+ </Row>
80
+ </Stack>
81
+ </Card>`,
82
+ },
83
+ ],
84
+ designNotes: 'The centered layout with align="center" creates a focused, modal-like feel ' +
85
+ 'even though this is a Card, not a true modal. The warning Icon at the top ' +
86
+ 'provides an immediate visual signal of severity. The text stack uses gap="1" ' +
87
+ 'to tightly couple the title and consequence description. Buttons use flex: 1 ' +
88
+ 'inside a full-width Row so they split evenly — Cancel (outline) on the left, ' +
89
+ 'destructive action (danger) on the right, following the convention of placing ' +
90
+ 'the primary action on the right. The typed confirmation variant adds an Input ' +
91
+ 'between the text and buttons with the danger Button disabled until the user ' +
92
+ 'types the confirmation text. The non-destructive variant swaps the danger ' +
93
+ 'Button for primary and the warning Icon for info, reusing the same centered ' +
94
+ 'layout for any "are you sure?" flow.',
95
+ };
@@ -0,0 +1,108 @@
1
+ export const PATTERN = {
2
+ id: 'announcement-card',
3
+ name: 'Announcement Card',
4
+ description: 'Rich announcement card with optional media slot, status icon, title, message, and action buttons. For in-page announcements, feature launches, promotions, or system notices.',
5
+ category: 'card',
6
+ components: ['card', 'icon', 'text', 'button', 'chip', 'stack', 'row'],
7
+ structure: `
8
+ Card (elevated, padding="lg", media=<img>)
9
+ └── Stack gap="4"
10
+ ├── Row gap="2" wrap ← optional badge row
11
+ │ └── Chip (accent/success, sm) ← category / "New"
12
+ ├── Stack gap="1"
13
+ │ ├── Text (md, semibold) ← title
14
+ │ └── Text (sm, secondary) ← message body
15
+ └── Row gap="2"
16
+ ├── Button (primary, sm) ← action
17
+ └── Button (ghost, sm) ← dismiss
18
+ `.trim(),
19
+ code: `<Card
20
+ variant="elevated"
21
+ padding="lg"
22
+ style={{ width: 380 }}
23
+ media={<img src="/announcements/feature-launch.jpg" alt="New dashboard" style={{ width: '100%', height: 160, objectFit: 'cover', display: 'block' }} />}
24
+ >
25
+ <Stack gap="4">
26
+ <Row gap="2">
27
+ <Chip variant="accent" size="sm">New Feature</Chip>
28
+ </Row>
29
+ <Stack gap="1">
30
+ <Text size="md" weight="semibold">Redesigned Analytics Dashboard</Text>
31
+ <Text size="sm" color="secondary">Track key metrics at a glance with our new real-time dashboard. Includes custom date ranges, export to CSV, and team sharing.</Text>
32
+ </Stack>
33
+ <Row gap="2">
34
+ <Button variant="primary" size="sm">Try it now</Button>
35
+ <Button variant="ghost" size="sm">Learn more</Button>
36
+ </Row>
37
+ </Stack>
38
+ </Card>`,
39
+ variants: [
40
+ {
41
+ title: 'System notice (no media, with status icon)',
42
+ code: `<Card variant="outline" padding="md" style={{ width: 400 }}>
43
+ <Row gap="3" align="start">
44
+ <Icon size="lg" color="var(--lucent-warning-text)">
45
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round">
46
+ <path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" />
47
+ <line x1={12} y1={9} x2={12} y2={13} />
48
+ <line x1={12} y1={17} x2={12.01} y2={17} />
49
+ </svg>
50
+ </Icon>
51
+ <Stack gap="2" style={{ flex: 1 }}>
52
+ <Text size="sm" weight="semibold">Storage almost full</Text>
53
+ <Text size="sm" color="secondary">You've used 92% of your storage. Upgrade your plan or delete unused files to free up space.</Text>
54
+ <Row gap="2">
55
+ <Button variant="primary" size="sm">Upgrade plan</Button>
56
+ <Button variant="ghost" size="sm">Manage storage</Button>
57
+ </Row>
58
+ </Stack>
59
+ </Row>
60
+ </Card>`,
61
+ },
62
+ {
63
+ title: 'Promotional banner with media',
64
+ code: `<Card variant="filled" padding="md" hoverable style={{ width: 380 }}>
65
+ <Row gap="5" align="center">
66
+ <div style={{ width: 80, height: 80, borderRadius: 'var(--lucent-radius-lg)', overflow: 'hidden', flexShrink: 0 }}>
67
+ <img src="/promo/spring-sale.jpg" alt="Spring sale" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
68
+ </div>
69
+ <Stack gap="2" style={{ flex: 1 }}>
70
+ <Row gap="2" align="center">
71
+ <Text size="md" weight="semibold">Spring Sale</Text>
72
+ <Chip variant="success" size="sm">-30%</Chip>
73
+ </Row>
74
+ <Text size="sm" color="secondary">All Pro plans are 30% off through April. Upgrade now and lock in the price for a year.</Text>
75
+ <Button variant="primary" size="sm" style={{ alignSelf: 'flex-start' }}>Claim offer</Button>
76
+ </Stack>
77
+ </Row>
78
+ </Card>`,
79
+ },
80
+ {
81
+ title: 'Success confirmation',
82
+ code: `<Card variant="outline" padding="md" style={{ width: 400, borderColor: 'var(--lucent-success-default)' }}>
83
+ <Row gap="3" align="start">
84
+ <Icon size="lg" color="var(--lucent-success-text)">
85
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round">
86
+ <path d="M22 11.08V12a10 10 0 11-5.93-9.14" />
87
+ <polyline points="22 4 12 14.01 9 11.01" />
88
+ </svg>
89
+ </Icon>
90
+ <Stack gap="1" style={{ flex: 1 }}>
91
+ <Text size="sm" weight="semibold">Payment received</Text>
92
+ <Text size="sm" color="secondary">Your invoice #1042 for $2,400.00 has been paid successfully.</Text>
93
+ </Stack>
94
+ <Button variant="ghost" size="sm">Dismiss</Button>
95
+ </Row>
96
+ </Card>`,
97
+ },
98
+ ],
99
+ designNotes: 'The default announcement card uses the Card media slot for a full-bleed hero ' +
100
+ 'image that grabs attention, followed by an optional Chip badge for categorization, ' +
101
+ 'then title + description + action buttons. This distinguishes it from the Alert ' +
102
+ 'molecule which is a lightweight status banner — the Announcement Card is richer, ' +
103
+ 'supports media, and drives the user toward an action. The system notice variant ' +
104
+ 'drops the media for a compact icon-led layout similar to Alert but with action ' +
105
+ 'buttons. The promotional variant uses an inline thumbnail (Row with rounded image) ' +
106
+ 'for a side-by-side layout that works well for offers and upsells. The success ' +
107
+ 'variant uses a tinted border to reinforce status at a glance.',
108
+ };
@@ -0,0 +1,110 @@
1
+ export const PATTERN = {
2
+ id: 'product-item-card',
3
+ name: 'Product/Item Card',
4
+ description: 'Versatile content card with media slot, title, tags, metadata, and CTA. Reusable for products, articles, team members, or any entity list.',
5
+ category: 'card',
6
+ components: ['card', 'avatar', 'icon', 'text', 'chip', 'button', 'stack', 'row'],
7
+ structure: `
8
+ Card (elevated, padding="lg", media=<img>)
9
+ └── Stack gap="4"
10
+ ├── Stack gap="1"
11
+ │ ├── Text (md, semibold) ← title
12
+ │ └── Text (sm, secondary) ← subtitle
13
+ ├── Row gap="2" wrap
14
+ │ └── Chip[] (neutral, sm) ← tags / categories
15
+ ├── Row gap="4" justify="between" align="baseline"
16
+ │ ├── Text (lg, bold, display) ← price / key metric
17
+ │ └── Text (xs, secondary) ← secondary info
18
+ └── Button (primary, full width) ← CTA
19
+ `.trim(),
20
+ code: `<Card
21
+ variant="elevated"
22
+ padding="lg"
23
+ style={{ width: 320 }}
24
+ media={<img src="/products/headphones.jpg" alt="Wireless Headphones" style={{ width: '100%', height: 180, objectFit: 'cover', display: 'block' }} />}
25
+ >
26
+ <Stack gap="4">
27
+ <Stack gap="1">
28
+ <Text size="md" weight="semibold">Wireless Headphones</Text>
29
+ <Text size="sm" color="secondary">Active noise cancelling, 40hr battery</Text>
30
+ </Stack>
31
+ <Row gap="2" wrap>
32
+ <Chip variant="neutral" size="sm">Audio</Chip>
33
+ <Chip variant="neutral" size="sm">Bluetooth</Chip>
34
+ <Chip variant="neutral" size="sm">ANC</Chip>
35
+ </Row>
36
+ <Row gap="4" justify="between" align="baseline">
37
+ <Text size="lg" weight="bold" family="display">$249.00</Text>
38
+ <Text size="xs" color="secondary">Free shipping</Text>
39
+ </Row>
40
+ <Button variant="primary" style={{ width: '100%' }}>Add to Cart</Button>
41
+ </Stack>
42
+ </Card>`,
43
+ variants: [
44
+ {
45
+ title: 'Article card',
46
+ code: `<Card variant="outline" padding="lg" hoverable style={{ width: 340 }}>
47
+ <Stack gap="4">
48
+ <Row gap="3" align="start">
49
+ <Icon size={20} color="var(--lucent-text-secondary)">
50
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5} strokeLinecap="round" strokeLinejoin="round">
51
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" />
52
+ <polyline points="14 2 14 8 20 8" />
53
+ <line x1={16} y1={13} x2={8} y2={13} />
54
+ <line x1={16} y1={17} x2={8} y2={17} />
55
+ </svg>
56
+ </Icon>
57
+ <Stack gap="1" style={{ flex: 1 }}>
58
+ <Text size="md" weight="semibold">Design Tokens at Scale</Text>
59
+ <Text size="xs" color="secondary">Published Mar 15, 2026</Text>
60
+ </Stack>
61
+ </Row>
62
+ <Text size="sm" color="secondary">
63
+ How we unified spacing, color, and typography across 12 product surfaces using a single token system.
64
+ </Text>
65
+ <Row gap="2" wrap>
66
+ <Chip variant="neutral" size="sm">Design Systems</Chip>
67
+ <Chip variant="neutral" size="sm">Tokens</Chip>
68
+ </Row>
69
+ <Row gap="4" justify="between" align="center">
70
+ <Text size="xs" color="secondary">8 min read</Text>
71
+ <Button variant="ghost" size="sm">Read more</Button>
72
+ </Row>
73
+ </Stack>
74
+ </Card>`,
75
+ },
76
+ {
77
+ title: 'Team member card',
78
+ code: `<Card variant="filled" padding="lg" style={{ width: 280 }}>
79
+ <Stack gap="4">
80
+ <Stack gap="3" align="center">
81
+ <Avatar src="/avatars/alex.jpg" alt="Alex Chen" size="lg" />
82
+ <Stack gap="0" align="center">
83
+ <Text size="md" weight="semibold">Alex Chen</Text>
84
+ <Text size="sm" color="secondary">Engineering Lead</Text>
85
+ </Stack>
86
+ </Stack>
87
+ <Row gap="2" wrap justify="center">
88
+ <Chip variant="neutral" size="sm">React</Chip>
89
+ <Chip variant="neutral" size="sm">Go</Chip>
90
+ <Chip variant="neutral" size="sm">Platform</Chip>
91
+ </Row>
92
+ <Row gap="3">
93
+ <Button variant="outline" style={{ flex: 1 }} size="sm">Profile</Button>
94
+ <Button variant="primary" style={{ flex: 1 }} size="sm">Message</Button>
95
+ </Row>
96
+ </Stack>
97
+ </Card>`,
98
+ },
99
+ ],
100
+ designNotes: 'The default product card uses the Card media slot for a full-bleed hero image ' +
101
+ 'at the top, keeping the content area clean with just title, tags, price, and CTA. ' +
102
+ 'Tags use neutral Chips at sm size for low visual weight — they inform without ' +
103
+ 'competing with the title. The price/metric row uses justify="between" with ' +
104
+ 'align="baseline" to anchor the large display-font value and the secondary caption ' +
105
+ 'to the same text baseline. A full-width primary Button as the sole CTA creates a ' +
106
+ 'clear action target. The article variant swaps the media slot for an inline Icon + ' +
107
+ 'text header and replaces the price row with read-time + ghost button, keeping the ' +
108
+ 'same vertical rhythm. The team member variant centers the content for a profile-style ' +
109
+ 'layout and uses a dual-button footer with flex: 1 for equal width.',
110
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucent-ui",
3
- "version": "0.32.1",
3
+ "version": "0.34.0",
4
4
  "description": "An AI-first React component library with machine-readable manifests.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",