@blibliki/ui 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import{Slot as e}from"@radix-ui/react-slot";import{cva as t}from"class-variance-authority";import*as n from"react";import{forwardRef as r,useMemo as i,useRef as a,useState as o}from"react";import{clsx as s}from"clsx";import{twMerge as c}from"tailwind-merge";import{jsx as l,jsxs as u}from"react/jsx-runtime";import*as d from"@radix-ui/react-label";import*as f from"@radix-ui/react-select";import{throttle as p}from"@blibliki/utils";import*as m from"@radix-ui/react-dialog";import*as h from"@radix-ui/react-context-menu";import*as g from"@radix-ui/react-dropdown-menu";function _(...e){return c(s(e))}const v=t(`ui-button`,{variants:{variant:{contained:`ui-button--variant-contained`,outlined:`ui-button--variant-outlined`,text:`ui-button--variant-text`},color:{primary:`ui-button--color-primary`,neutral:`ui-button--color-neutral`,secondary:`ui-button--color-secondary`,error:`ui-button--color-error`,warning:`ui-button--color-warning`,info:`ui-button--color-info`,success:`ui-button--color-success`},size:{md:`ui-button--size-md`,sm:`ui-button--size-sm`,lg:`ui-button--size-lg`,icon:`ui-button--size-icon`}},defaultVariants:{variant:`contained`,color:`primary`,size:`md`}}),y=n.forwardRef(({className:t,variant:n,color:r,size:i,asChild:a=!1,type:o,...s},c)=>l(a?e:`button`,{ref:c,className:_(v({variant:n,color:r,size:i}),t),type:a?void 0:o??`button`,...s}));y.displayName=`Button`;const b=r(({className:e,...t},n)=>l(`div`,{ref:n,className:_(`ui-card`,e),...t}));b.displayName=`Card`;function x({className:e,...t}){return l(`div`,{className:_(`ui-card-header`,e),...t})}function S({className:e,...t}){return l(`div`,{className:_(`ui-card-title`,e),...t})}function C({className:e,...t}){return l(`div`,{className:_(`ui-card-description`,e),...t})}function w({className:e,...t}){return l(`div`,{className:_(`ui-card-action`,e),...t})}function T({className:e,...t}){return l(`div`,{className:_(`ui-card-content`,e),...t})}function E({className:e,...t}){return l(`div`,{className:_(`ui-card-footer`,e),...t})}const D=t(`ui-surface`,{variants:{tone:{canvas:`ui-surface--tone-canvas`,panel:`ui-surface--tone-panel`,raised:`ui-surface--tone-raised`,subtle:`ui-surface--tone-subtle`},border:{none:``,subtle:`ui-surface--border-subtle`},radius:{none:`ui-surface--radius-none`,sm:`ui-surface--radius-sm`,md:`ui-surface--radius-md`,lg:`ui-surface--radius-lg`},shadow:{none:``,sm:`ui-surface--shadow-sm`,md:`ui-surface--shadow-md`,lg:`ui-surface--shadow-lg`,xl:`ui-surface--shadow-xl`},intent:{neutral:``,success:`ui-surface--intent-success`,warning:`ui-surface--intent-warning`,error:`ui-surface--intent-error`,info:`ui-surface--intent-info`}},defaultVariants:{tone:`raised`,border:`none`,radius:`md`,shadow:`none`,intent:`neutral`}}),O=n.forwardRef(({className:t,tone:n,border:r,radius:i,shadow:a,intent:o,asChild:s=!1,...c},u)=>l(s?e:`div`,{ref:u,className:_(D({tone:n,border:r,radius:i,shadow:a,intent:o}),t),...c}));O.displayName=`Surface`;const k=t(`ui-stack`,{variants:{direction:{row:`ui-stack--row`,column:`ui-stack--column`},align:{start:`ui-stack--align-start`,center:`ui-stack--align-center`,end:`ui-stack--align-end`,stretch:`ui-stack--align-stretch`,baseline:`ui-stack--align-baseline`},justify:{start:`ui-stack--justify-start`,center:`ui-stack--justify-center`,end:`ui-stack--justify-end`,between:`ui-stack--justify-between`,around:`ui-stack--justify-around`,evenly:`ui-stack--justify-evenly`},gap:{0:`ui-stack--gap-0`,1:`ui-stack--gap-1`,2:`ui-stack--gap-2`,3:`ui-stack--gap-3`,4:`ui-stack--gap-4`,5:`ui-stack--gap-5`,6:`ui-stack--gap-6`},wrap:{true:`ui-stack--wrap`,false:``}},defaultVariants:{direction:`column`,align:`stretch`,justify:`start`,gap:2,wrap:!1}}),A=n.forwardRef(({className:t,direction:n,align:r,justify:i,gap:a,wrap:o,asChild:s=!1,...c},u)=>l(s?e:`div`,{ref:u,className:_(k({direction:n,align:r,justify:i,gap:a,wrap:o}),t),...c}));A.displayName=`Stack`;const j=t(`ui-divider`,{variants:{orientation:{horizontal:`ui-divider--horizontal`,vertical:`ui-divider--vertical`},tone:{subtle:`ui-divider--tone-subtle`,strong:`ui-divider--tone-strong`}},defaultVariants:{orientation:`horizontal`,tone:`subtle`}}),M=n.forwardRef(({className:e,orientation:t,tone:n,...r},i)=>l(`div`,{ref:i,role:`separator`,"aria-orientation":t??`horizontal`,className:_(j({orientation:t,tone:n}),e),...r}));M.displayName=`Divider`;const N={xs:`ui-icon-button--size-xs`,sm:`ui-icon-button--size-sm`,md:`ui-icon-button--size-md`},P=n.forwardRef(({icon:e,size:t=`md`,variant:n=`text`,color:r=`secondary`,className:i,...a},o)=>l(y,{ref:o,variant:n,color:r,size:`icon`,className:_(`ui-icon-button`,N[t],i),...a,children:e}));P.displayName=`IconButton`;const F=t(`ui-input`,{variants:{size:{sm:`ui-input--size-sm`,md:`ui-input--size-md`}},defaultVariants:{size:`md`}}),I=r(({className:e,type:t=`text`,size:n,...r},i)=>l(`input`,{ref:i,type:t,"data-size":n??`md`,className:_(F({size:n}),e),...r}));I.displayName=`Input`;const L=t(`ui-textarea`,{variants:{size:{sm:`ui-textarea--size-sm`,md:`ui-textarea--size-md`},resize:{none:`ui-textarea--resize-none`,vertical:`ui-textarea--resize-vertical`,both:`ui-textarea--resize-both`}},defaultVariants:{size:`md`,resize:`vertical`}}),R=r(({className:e,size:t,resize:n,...r},i)=>l(`textarea`,{ref:i,"data-size":t??`md`,className:_(L({size:t,resize:n}),e),...r}));R.displayName=`Textarea`;function z({className:e,...t}){return l(d.Root,{className:_(`ui-label`,e),...t})}const B=t(`ui-text`,{variants:{tone:{primary:`ui-text--tone-primary`,secondary:`ui-text--tone-secondary`,muted:`ui-text--tone-muted`,success:`ui-text--tone-success`,warning:`ui-text--tone-warning`,error:`ui-text--tone-error`,info:`ui-text--tone-info`},size:{xs:`ui-text--size-xs`,sm:`ui-text--size-sm`,md:`ui-text--size-md`,lg:`ui-text--size-lg`},weight:{regular:`ui-text--weight-regular`,medium:`ui-text--weight-medium`,semibold:`ui-text--weight-semibold`}},defaultVariants:{tone:`primary`,size:`sm`,weight:`regular`}}),V=r(({className:t,tone:n,size:r,weight:i,asChild:a=!1,...o},s)=>l(a?e:`p`,{ref:s,className:_(B({tone:n,size:r,weight:i}),t),...o}));V.displayName=`Text`;const H=t(`ui-badge`,{variants:{tone:{neutral:`ui-badge--tone-neutral`,primary:`ui-badge--tone-primary`,secondary:`ui-badge--tone-secondary`,success:`ui-badge--tone-success`,warning:`ui-badge--tone-warning`,error:`ui-badge--tone-error`,info:`ui-badge--tone-info`},variant:{soft:`ui-badge--variant-soft`,solid:`ui-badge--variant-solid`,outline:`ui-badge--variant-outline`},size:{sm:`ui-badge--size-sm`,md:`ui-badge--size-md`}},defaultVariants:{tone:`neutral`,variant:`soft`,size:`md`}}),U=r(({className:t,tone:n,variant:r,size:i,asChild:a=!1,...o},s)=>l(a?e:`span`,{ref:s,className:_(H({tone:n,variant:r,size:i}),t),...o}));U.displayName=`Badge`;const ee=t(`ui-switch`,{variants:{size:{sm:`ui-switch--size-sm`,md:`ui-switch--size-md`},color:{primary:`ui-switch--color-primary`,secondary:`ui-switch--color-secondary`,error:`ui-switch--color-error`,warning:`ui-switch--color-warning`,info:`ui-switch--color-info`,success:`ui-switch--color-success`}},defaultVariants:{size:`md`,color:`primary`}}),W=n.forwardRef(({checked:e=!1,onCheckedChange:t,className:n,size:r,color:i,type:a,onClick:o,...s},c)=>l(`button`,{ref:c,type:a??`button`,role:`switch`,"aria-checked":e,"data-state":e?`checked`:`unchecked`,className:_(ee({size:r,color:i}),n),onClick:n=>{o?.(n),n.defaultPrevented||t?.(!e)},...s,children:l(`span`,{"aria-hidden":!0,className:`ui-switch__thumb`})}));W.displayName=`Switch`;function G(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e,children:l(`path`,{d:`M4 6.5 8 10.5 12 6.5`,stroke:`currentColor`,strokeWidth:`1.6`,strokeLinecap:`round`,strokeLinejoin:`round`})})}function te(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e,children:l(`path`,{d:`M4 9.5 8 5.5 12 9.5`,stroke:`currentColor`,strokeWidth:`1.6`,strokeLinecap:`round`,strokeLinejoin:`round`})})}function ne(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e,children:l(`path`,{d:`M3.5 8.5 6.5 11.5 12.5 4.5`,stroke:`currentColor`,strokeWidth:`1.75`,strokeLinecap:`round`,strokeLinejoin:`round`})})}function K(e){return l(f.Root,{...e})}function q(e){return l(f.Group,{...e})}function J({className:e,...t}){return l(f.Value,{className:_(`ui-select-value`,e),...t})}function Y({className:e,size:t=`md`,children:n,...r}){return u(f.Trigger,{"data-size":t,className:_(`ui-select-trigger`,e),...r,children:[n,l(f.Icon,{asChild:!0,children:l(G,{className:`ui-select-chevron`})})]})}function X({className:e,children:t,position:n=`popper`,...r}){return l(f.Portal,{children:u(f.Content,{position:n,className:_(`ui-select-content`,n===`popper`&&`ui-select-content--popper`,e),...r,children:[l(oe,{}),l(f.Viewport,{className:_(`ui-select-viewport`,n===`popper`&&`ui-select-viewport--popper`),children:t}),l(se,{})]})})}function re({className:e,...t}){return l(f.Label,{className:_(`ui-select-label`,e),...t})}function ie({className:e,children:t,...n}){return u(f.Item,{className:_(`ui-select-item`,e),...n,children:[l(`span`,{className:`ui-select-indicator`,"aria-hidden":!0,children:l(f.ItemIndicator,{children:l(ne,{className:`ui-select-indicator-icon`})})}),l(f.ItemText,{className:`ui-select-item-text`,children:t})]})}function ae({className:e,...t}){return l(f.Separator,{className:_(`ui-select-separator`,e),...t})}function oe({className:e,...t}){return l(f.ScrollUpButton,{className:_(`ui-select-scroll-button`,e),...t,children:l(te,{className:`ui-select-scroll-icon`})})}function se({className:e,...t}){return l(f.ScrollDownButton,{className:_(`ui-select-scroll-button`,e),...t,children:l(G,{className:`ui-select-scroll-icon`})})}function ce(e){return!!(e&&typeof e==`object`&&`name`in e&&`value`in e&&(typeof e.value==`string`||typeof e.value==`number`))}function le(e){return!!(e&&typeof e==`object`&&`id`in e&&`name`in e&&typeof e.id==`string`)}function ue({value:e,options:t,label:n,contentClassName:r,triggerClassName:a,disabled:o=!1,onChange:s}){let c=i(()=>{if(!t.length)return[];let e=t[0];return typeof e==`string`||typeof e==`number`?t.map(e=>({name:e.toString(),value:e})):ce(e)?Array.from(t):le(e)?t.map(e=>({name:e.name,value:e.id})):[]},[t]),d=i(()=>c.length?typeof c[0]?.value==`number`?`number`:`string`:typeof e==`number`?`number`:`string`,[c,e]),f=e=>{if(d===`number`){s(Number(e));return}s(e)},p=e!==void 0&&e!==``?e.toString():void 0,m=n&&n.length>0?n:`Select...`,h=i(()=>{let e=c.reduce((e,t)=>{let n=t.name.length;return Math.max(e,n)},0);return Math.max(m.length,e)},[c,m]),g=Math.min(Math.max(h+6,18),40);return u(K,{value:p,onValueChange:f,disabled:o,children:[l(Y,{className:a,style:a?void 0:{width:`clamp(10rem, ${g}ch, 26rem)`,maxWidth:`100%`},children:l(J,{placeholder:m})}),l(X,{className:r,children:u(q,{children:[l(re,{children:`Select...`}),c.map(e=>l(ie,{value:e.value.toString(),children:e.name},e.value))]})})]})}const Z=(e,t,n,r)=>{if(r===void 0||r===1)return e;let i=n-t;return i===0?t:t+((e-t)/i)**+r*i},de=(e,t,n,r)=>{if(r===void 0||r===1)return e;let i=n-t;return i===0?t:t+((e-t)/i)**+(1/r)*i};function fe(e){return e===void 0?``:Number.isInteger(e)?`${e}`:e.toFixed(2)}const Q=(e,t,n)=>Math.min(n,Math.max(t,e));function pe(e){let{className:t,name:n,onChange:r,value:i,defaultValue:a,marks:o,hideMarks:s=!1,exp:c,min:d=0,orientation:f=`vertical`,max:m,step:h,...g}=e,v=o?.length??0,b=v>0,x=m??(b?v-1:1),S=h??(b?1:.01),C=i===void 0?void 0:Q(de(i,d,x,c),d,x),w=a===void 0?d:Q(a,d,x),T=p(e=>{let t=Q(Number(e.target.value),d,x);r(t,Z(t,d,x,c))},1e3),E=e=>()=>{let t=Q(e,d,x);r(t,Z(t,d,x,c))},D=e=>x===d?0:(Q(e,d,x)-d)/(x-d)*100,O=o?o.every(e=>e.value===0):!1,k=s||!o||O,A=C??w,j=o?.find(e=>e.value===A),M=i??Z(A,d,x,c),N=j?.label??fe(M),P=C===void 0?{defaultValue:w}:{value:C};return u(`div`,{className:_(`ui-fader nodrag`,f===`horizontal`&&`ui-fader--horizontal`,t),...g,children:[u(`div`,{className:_(`ui-fader__control`,f===`horizontal`?`ui-fader__control--horizontal`:`ui-fader__control--vertical`),children:[l(`input`,{type:`range`,min:d,max:x,...P,step:S,"aria-label":n,className:_(`ui-fader__range`,f===`horizontal`?`ui-fader__range--horizontal`:`ui-fader__range--vertical`),onChange:T}),k&&l(`div`,{className:_(`ui-fader__tooltip`,f===`horizontal`?`ui-fader__tooltip--horizontal`:`ui-fader__tooltip--vertical`),children:N}),o&&!s&&l(`div`,{className:_(`ui-fader__marks`,f===`horizontal`?`ui-fader__marks--horizontal`:`ui-fader__marks--vertical`,o.length===1&&`ui-fader__marks--single`),children:o.map((e,t)=>u(y,{size:`sm`,variant:`text`,color:`secondary`,className:_(`ui-fader__mark-button`,f===`horizontal`&&`ui-fader__mark-button--horizontal`,f===`horizontal`&&e.value<=d&&`ui-fader__mark-button--horizontal-start`,f===`horizontal`&&e.value>=x&&`ui-fader__mark-button--horizontal-end`),style:f===`horizontal`?{left:`${D(e.value)}%`}:void 0,onClick:E(e.value),children:[l(`span`,{className:`ui-fader__mark-dot`,"aria-hidden":!0}),e.label]},`${e.value}-${t}`))})]}),u(`div`,{className:`ui-fader__label-row`,children:[l(`span`,{className:`ui-fader__label-dot`,"aria-hidden":!0}),l(`span`,{className:`ui-fader__label`,children:n})]})]})}pe.displayName=`Fader`;const $=(e,t,n)=>Math.min(n,Math.max(t,e)),me=(e,t,n,r)=>{if(r===void 0||r===1)return e;let i=n-t;return i===0?t:t+((e-t)/i)**+(1/r)*i},he=(e,t,n,r)=>{if(r===void 0||r===1)return e;let i=n-t;return i===0?t:t+((e-t)/i)**+r*i},ge=e=>{let t=`${e}`,n=t.indexOf(`.`);return n===-1?0:t.length-n-1},_e=(e,t,n)=>{let r=ge(n),i=Math.round((e-t)/n)*n+t;return Number(i.toFixed(r))},ve=(e,t)=>{let n=Math.min(4,ge(t));return n===0?`${Math.round(e)}`:`${Number(e.toFixed(n))}`},ye=r(({className:e,style:t,name:n,onChange:r,value:i,defaultValue:s,max:c=1,min:d=0,step:f=.01,exp:p,size:m=`md`,disabled:h=!1,formatValue:g,onKeyDown:v,onPointerDown:y,onPointerMove:b,onPointerUp:x,onPointerCancel:S,onWheel:C,...w},T)=>{let[E,D]=o($(s??d,d,c)),O=a(null),k=$(i??E,d,c),A=$(me(k,d,c,p),d,c),j=c===d?0:(A-d)/(c-d),M=g?g(k):ve(k,f),N=e=>{let t=$(_e(e,d,f),d,c);t!==k&&(i===void 0&&D(t),r(t))},P=e=>{N(k+e*f)},F=e=>{if(v?.(e),!(e.defaultPrevented||h))switch(e.key){case`ArrowUp`:case`ArrowRight`:e.preventDefault(),P(1);return;case`ArrowDown`:case`ArrowLeft`:e.preventDefault(),P(-1);return;case`PageUp`:e.preventDefault(),P(10);return;case`PageDown`:e.preventDefault(),P(-10);return;case`Home`:e.preventDefault(),N(d);return;case`End`:e.preventDefault(),N(c);return;default:return}},I=e=>{y?.(e),!(e.defaultPrevented||h)&&(e.preventDefault(),e.currentTarget.focus(),e.currentTarget.setPointerCapture(e.pointerId),O.current={pointerId:e.pointerId,lastY:e.clientY,sliderValue:A})},L=e=>{if(b?.(e),e.defaultPrevented||h)return;let t=O.current;if(t?.pointerId!==e.pointerId)return;e.preventDefault();let n=80*(e.shiftKey?8:1),r=(t.lastY-e.clientY)*(c-d)/n,i=$(t.sliderValue+r,d,c),a=he(i,d,c,p);t.lastY=e.clientY,t.sliderValue=i,N(a)},R=e=>{O.current?.pointerId===e.pointerId&&(e.currentTarget.hasPointerCapture(e.pointerId)&&e.currentTarget.releasePointerCapture(e.pointerId),O.current=null)},z=e=>{x?.(e),!e.defaultPrevented&&R(e)},B=e=>{S?.(e),!e.defaultPrevented&&R(e)},V=e=>{C?.(e),!(e.defaultPrevented||h||e.deltaY===0)&&(e.preventDefault(),P(e.deltaY<0?1:-1))};return u(`div`,{ref:T,role:`slider`,tabIndex:h?-1:0,"aria-label":n,"aria-disabled":h,"aria-valuemin":d,"aria-valuemax":c,"aria-valuenow":k,"aria-valuetext":M,"data-size":m,className:_(`ui-encoder`,m===`sm`&&`ui-encoder--size-sm`,m===`md`&&`ui-encoder--size-md`,h&&`ui-encoder--disabled`,e),style:{...t,"--ui-encoder-angle":`${-135+j*270}deg`,"--ui-encoder-fill":`${j*270}deg`},onKeyDown:F,onPointerDown:I,onPointerMove:L,onPointerUp:z,onPointerCancel:B,onWheel:V,...w,children:[l(`div`,{className:`ui-encoder__dial`,children:l(`span`,{className:`ui-encoder__indicator`,"aria-hidden":!0})}),l(`span`,{className:`ui-encoder__value`,children:M})]})});ye.displayName=`Encoder`;function be(e){return l(m.Root,{...e})}function xe(e){return l(m.Trigger,{...e})}function Se(e){return l(m.Portal,{...e})}function Ce(e){return l(m.Close,{...e})}function we({className:e,...t}){return l(m.Overlay,{className:_(`ui-dialog-overlay`,e),...t})}function Te(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e,children:l(`path`,{d:`M3.5 3.5 12.5 12.5M12.5 3.5 3.5 12.5`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`})})}function Ee({className:e,children:t,hideCloseButton:n=!1,...r}){return u(Se,{children:[l(we,{}),u(m.Content,{className:_(`ui-dialog-content`,e),...r,children:[t,!n&&u(m.Close,{className:`ui-dialog-close`,children:[l(Te,{className:`ui-dialog-close-icon`}),l(`span`,{className:`ui-visually-hidden`,children:`Close`})]})]})]})}function De({className:e,...t}){return l(`div`,{className:_(`ui-dialog-header`,e),...t})}function Oe({className:e,...t}){return l(`div`,{className:_(`ui-dialog-footer`,e),...t})}function ke({className:e,...t}){return l(m.Title,{className:_(`ui-dialog-title`,e),...t})}function Ae({className:e,...t}){return l(m.Description,{className:_(`ui-dialog-description`,e),...t})}function je(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e,children:l(`path`,{d:`M3.5 8.5 6.5 11.5 12.5 4.5`,stroke:`currentColor`,strokeWidth:`1.75`,strokeLinecap:`round`,strokeLinejoin:`round`})})}function Me(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`currentColor`,"aria-hidden":!0,...e,children:l(`circle`,{cx:`8`,cy:`8`,r:`3`})})}function Ne(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e,children:l(`path`,{d:`M6 3.5 10.5 8 6 12.5`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`})})}function Pe(e){return l(h.Root,{...e})}function Fe(e){return l(h.Trigger,{...e})}function Ie(e){return l(h.Group,{...e})}function Le(e){return l(h.Portal,{...e})}function Re(e){return l(h.Sub,{...e})}function ze(e){return l(h.RadioGroup,{...e})}function Be({className:e,inset:t=!1,children:n,...r}){return u(h.SubTrigger,{"data-inset":t?`true`:void 0,className:_(`ui-dropdown-item ui-dropdown-sub-trigger`,e),...r,children:[n,l(Ne,{className:`ui-dropdown-chevron`})]})}function Ve({className:e,...t}){return l(h.SubContent,{className:_(`ui-dropdown-content ui-dropdown-sub-content ui-context-content ui-context-sub-content`,e),...t})}function He({className:e,...t}){return l(h.Portal,{children:l(h.Content,{className:_(`ui-dropdown-content ui-context-content`,e),...t})})}function Ue({className:e,inset:t=!1,variant:n=`default`,...r}){return l(h.Item,{"data-inset":t?`true`:void 0,"data-variant":n,className:_(`ui-dropdown-item`,e),...r})}function We({className:e,children:t,checked:n,...r}){return u(h.CheckboxItem,{checked:n,className:_(`ui-dropdown-item ui-dropdown-item--with-indicator`,e),...r,children:[l(`span`,{className:`ui-dropdown-indicator`,"aria-hidden":!0,children:l(h.ItemIndicator,{children:l(je,{className:`ui-dropdown-indicator-icon`})})}),t]})}function Ge({className:e,children:t,...n}){return u(h.RadioItem,{className:_(`ui-dropdown-item ui-dropdown-item--with-indicator`,e),...n,children:[l(`span`,{className:`ui-dropdown-indicator`,"aria-hidden":!0,children:l(h.ItemIndicator,{children:l(Me,{className:`ui-dropdown-indicator-icon`})})}),t]})}function Ke({className:e,inset:t=!1,...n}){return l(h.Label,{"data-inset":t?`true`:void 0,className:_(`ui-dropdown-label`,e),...n})}function qe({className:e,...t}){return l(h.Separator,{className:_(`ui-dropdown-separator`,e),...t})}function Je({className:e,...t}){return l(`span`,{className:_(`ui-dropdown-shortcut`,e),...t})}function Ye(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e,children:l(`path`,{d:`M3.5 8.5 6.5 11.5 12.5 4.5`,stroke:`currentColor`,strokeWidth:`1.75`,strokeLinecap:`round`,strokeLinejoin:`round`})})}function Xe(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`currentColor`,"aria-hidden":!0,...e,children:l(`circle`,{cx:`8`,cy:`8`,r:`3`})})}function Ze(e){return l(`svg`,{viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e,children:l(`path`,{d:`M6 3.5 10.5 8 6 12.5`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`})})}function Qe(e){return l(g.Root,{...e})}function $e(e){return l(g.Portal,{...e})}function et(e){return l(g.Trigger,{...e})}function tt({className:e,sideOffset:t=6,...n}){return l(g.Portal,{children:l(g.Content,{sideOffset:t,className:_(`ui-dropdown-content`,e),...n})})}function nt(e){return l(g.Group,{...e})}function rt({className:e,inset:t=!1,variant:n=`default`,...r}){return l(g.Item,{"data-inset":t?`true`:void 0,"data-variant":n,className:_(`ui-dropdown-item`,e),...r})}function it({className:e,children:t,checked:n,...r}){return u(g.CheckboxItem,{checked:n,className:_(`ui-dropdown-item ui-dropdown-item--with-indicator`,e),...r,children:[l(`span`,{className:`ui-dropdown-indicator`,"aria-hidden":!0,children:l(g.ItemIndicator,{children:l(Ye,{className:`ui-dropdown-indicator-icon`})})}),t]})}function at(e){return l(g.RadioGroup,{...e})}function ot({className:e,children:t,...n}){return u(g.RadioItem,{className:_(`ui-dropdown-item ui-dropdown-item--with-indicator`,e),...n,children:[l(`span`,{className:`ui-dropdown-indicator`,"aria-hidden":!0,children:l(g.ItemIndicator,{children:l(Xe,{className:`ui-dropdown-indicator-icon`})})}),t]})}function st({className:e,inset:t=!1,...n}){return l(g.Label,{"data-inset":t?`true`:void 0,className:_(`ui-dropdown-label`,e),...n})}function ct({className:e,...t}){return l(g.Separator,{className:_(`ui-dropdown-separator`,e),...t})}function lt({className:e,...t}){return l(`span`,{className:_(`ui-dropdown-shortcut`,e),...t})}function ut(e){return l(g.Sub,{...e})}function dt({className:e,inset:t=!1,children:n,...r}){return u(g.SubTrigger,{"data-inset":t?`true`:void 0,className:_(`ui-dropdown-item ui-dropdown-sub-trigger`,e),...r,children:[n,l(Ze,{className:`ui-dropdown-chevron`})]})}function ft({className:e,...t}){return l(g.SubContent,{className:_(`ui-dropdown-content ui-dropdown-sub-content`,e),...t})}const pt={surface0:`oklch(0.985 0.004 260)`,surfaceRaised:`oklch(0.996 0.002 260)`,surfaceRaisedHover:`oklch(1 0 0)`,surface1:`oklch(0.96 0.006 260)`,surface2:`oklch(0.92 0.008 260)`,borderSubtle:`oklch(0.84 0.01 260)`,textPrimary:`oklch(0.18 0.01 260)`,textSecondary:`oklch(0.33 0.01 260)`,textMuted:`oklch(0.48 0.01 260)`,primary500:`oklch(0.62 0.19 255)`,primary600:`oklch(0.55 0.2 255)`,primaryContrast:`oklch(0.98 0 0)`,secondary500:`oklch(0.62 0.2 300)`,secondary600:`oklch(0.55 0.21 300)`,secondaryContrast:`oklch(0.98 0 0)`,error500:`oklch(0.63 0.24 28)`,error600:`oklch(0.57 0.24 28)`,errorContrast:`oklch(0.98 0 0)`,warning500:`oklch(0.78 0.17 78)`,warning600:`oklch(0.72 0.17 78)`,warningContrast:`oklch(0.2 0.01 260)`,info500:`oklch(0.66 0.14 220)`,info600:`oklch(0.59 0.15 220)`,infoContrast:`oklch(0.98 0 0)`,success500:`oklch(0.66 0.17 150)`,success600:`oklch(0.59 0.18 150)`,successContrast:`oklch(0.98 0 0)`},mt={surface0:`oklch(0.12 0.01 260)`,surfaceRaised:`oklch(0.2 0.01 260)`,surfaceRaisedHover:`oklch(0.24 0.01 260)`,surface1:`oklch(0.16 0.01 260)`,surface2:`oklch(0.21 0.01 260)`,borderSubtle:`oklch(0.34 0.01 260)`,textPrimary:`oklch(0.96 0.01 260)`,textSecondary:`oklch(0.76 0.01 260)`,textMuted:`oklch(0.62 0.01 260)`,primary500:`oklch(0.67 0.19 255)`,primary600:`oklch(0.6 0.2 255)`,primaryContrast:`oklch(0.98 0 0)`,secondary500:`oklch(0.67 0.2 300)`,secondary600:`oklch(0.6 0.21 300)`,secondaryContrast:`oklch(0.98 0 0)`,error500:`oklch(0.67 0.22 28)`,error600:`oklch(0.6 0.23 28)`,errorContrast:`oklch(0.98 0 0)`,warning500:`oklch(0.79 0.15 78)`,warning600:`oklch(0.73 0.16 78)`,warningContrast:`oklch(0.2 0.01 260)`,info500:`oklch(0.69 0.13 220)`,info600:`oklch(0.62 0.14 220)`,infoContrast:`oklch(0.98 0 0)`,success500:`oklch(0.69 0.16 150)`,success600:`oklch(0.62 0.17 150)`,successContrast:`oklch(0.98 0 0)`},ht={sm:`4px`,md:`8px`,lg:`12px`},gt=(e={})=>({light:{...pt,...e.light},dark:{...mt,...e.dark},radius:{...ht,...e.radius}});function _t(e,t){let n=t===`dark`?e.dark:e.light;return{"--ui-color-surface-0":n.surface0,"--ui-color-surface-raised":n.surfaceRaised,"--ui-color-surface-raised-hover":n.surfaceRaisedHover,"--ui-color-surface-1":n.surface1,"--ui-color-surface-2":n.surface2,"--ui-color-border-subtle":n.borderSubtle,"--ui-color-text-primary":n.textPrimary,"--ui-color-text-secondary":n.textSecondary,"--ui-color-text-muted":n.textMuted,"--ui-color-primary-500":n.primary500,"--ui-color-primary-600":n.primary600,"--ui-color-primary-contrast":n.primaryContrast,"--ui-color-secondary-500":n.secondary500,"--ui-color-secondary-600":n.secondary600,"--ui-color-secondary-contrast":n.secondaryContrast,"--ui-color-error-500":n.error500,"--ui-color-error-600":n.error600,"--ui-color-error-contrast":n.errorContrast,"--ui-color-warning-500":n.warning500,"--ui-color-warning-600":n.warning600,"--ui-color-warning-contrast":n.warningContrast,"--ui-color-info-500":n.info500,"--ui-color-info-600":n.info600,"--ui-color-info-contrast":n.infoContrast,"--ui-color-success-500":n.success500,"--ui-color-success-600":n.success600,"--ui-color-success-contrast":n.successContrast,"--ui-radius-sm":e.radius.sm,"--ui-radius-md":e.radius.md,"--ui-radius-lg":e.radius.lg}}function vt({children:e,mode:t=`light`,theme:r,className:i}){let a=n.useMemo(()=>gt(r),[r]),o=n.useMemo(()=>_t(a,t),[a,t]);return l(`div`,{className:_(t===`dark`&&`dark`,i),"data-theme":t,style:o,children:e})}const yt={surface:{canvas:`var(--ui-color-surface-0)`,panel:`var(--ui-color-surface-1)`,raised:`var(--ui-color-surface-raised)`,subtle:`var(--ui-color-surface-2)`},text:{primary:`var(--ui-color-text-primary)`,secondary:`var(--ui-color-text-secondary)`,muted:`var(--ui-color-text-muted)`},border:{subtle:`var(--ui-color-border-subtle)`}},bt={primary:{500:`var(--ui-color-primary-500)`,600:`var(--ui-color-primary-600)`,contrast:`var(--ui-color-primary-contrast)`},secondary:{500:`var(--ui-color-secondary-500)`,600:`var(--ui-color-secondary-600)`,contrast:`var(--ui-color-secondary-contrast)`},success:{500:`var(--ui-color-success-500)`,600:`var(--ui-color-success-600)`,contrast:`var(--ui-color-success-contrast)`},warning:{500:`var(--ui-color-warning-500)`,600:`var(--ui-color-warning-600)`,contrast:`var(--ui-color-warning-contrast)`},error:{500:`var(--ui-color-error-500)`,600:`var(--ui-color-error-600)`,contrast:`var(--ui-color-error-contrast)`},info:{500:`var(--ui-color-info-500)`,600:`var(--ui-color-info-600)`,contrast:`var(--ui-color-info-contrast)`}};function xt(e,t=`500`){return bt[e][t]}function St(e,t,n){return`color-mix(in oklab, ${e}, ${t} ${n}%)`}const Ct=12;export{U as Badge,y as Button,b as Card,w as CardAction,T as CardContent,C as CardDescription,E as CardFooter,x as CardHeader,S as CardTitle,Pe as ContextMenu,We as ContextMenuCheckboxItem,He as ContextMenuContent,Ie as ContextMenuGroup,Ue as ContextMenuItem,Ke as ContextMenuLabel,Le as ContextMenuPortal,ze as ContextMenuRadioGroup,Ge as ContextMenuRadioItem,qe as ContextMenuSeparator,Je as ContextMenuShortcut,Re as ContextMenuSub,Ve as ContextMenuSubContent,Be as ContextMenuSubTrigger,Fe as ContextMenuTrigger,be as Dialog,Ce as DialogClose,Ee as DialogContent,Ae as DialogDescription,Oe as DialogFooter,De as DialogHeader,we as DialogOverlay,Se as DialogPortal,ke as DialogTitle,xe as DialogTrigger,M as Divider,Qe as DropdownMenu,it as DropdownMenuCheckboxItem,tt as DropdownMenuContent,nt as DropdownMenuGroup,rt as DropdownMenuItem,st as DropdownMenuLabel,$e as DropdownMenuPortal,at as DropdownMenuRadioGroup,ot as DropdownMenuRadioItem,ct as DropdownMenuSeparator,lt as DropdownMenuShortcut,ut as DropdownMenuSub,ft as DropdownMenuSubContent,dt as DropdownMenuSubTrigger,et as DropdownMenuTrigger,ye as Encoder,pe as Fader,P as IconButton,I as Input,z as Label,ue as OptionSelect,K as Select,X as SelectContent,q as SelectGroup,ie as SelectItem,re as SelectLabel,se as SelectScrollDownButton,oe as SelectScrollUpButton,ae as SelectSeparator,Y as SelectTrigger,J as SelectValue,A as Stack,O as Surface,W as Switch,V as Text,R as Textarea,vt as UIProvider,Ct as UI_MAX_TAILWIND_CLASSES,H as badgeVariants,v as buttonVariants,_ as cn,gt as createTheme,j as dividerVariants,F as inputVariants,k as stackVariants,D as surfaceVariants,B as textVariants,L as textareaVariants,_t as themeToCssVariables,St as uiColorMix,xt as uiTone,yt as uiVars};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["clamp","MenuCheckIcon","MenuDotIcon","MenuChevronRightIcon"],"sources":["../src/lib/cn.ts","../src/components/button.tsx","../src/components/card.tsx","../src/components/surface.tsx","../src/components/stack.tsx","../src/components/divider.tsx","../src/components/icon-button.tsx","../src/components/input.tsx","../src/components/textarea.tsx","../src/components/label.tsx","../src/components/text.tsx","../src/components/badge.tsx","../src/components/switch.tsx","../src/components/select.tsx","../src/components/fader.tsx","../src/components/encoder.tsx","../src/components/dialog.tsx","../src/components/context-menu.tsx","../src/components/dropdown-menu.tsx","../src/theme.ts","../src/UIProvider.tsx","../src/semantic.ts","../src/index.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst buttonVariants = cva(\"ui-button\", {\n variants: {\n variant: {\n contained: \"ui-button--variant-contained\",\n outlined: \"ui-button--variant-outlined\",\n text: \"ui-button--variant-text\",\n },\n color: {\n primary: \"ui-button--color-primary\",\n neutral: \"ui-button--color-neutral\",\n secondary: \"ui-button--color-secondary\",\n error: \"ui-button--color-error\",\n warning: \"ui-button--color-warning\",\n info: \"ui-button--color-info\",\n success: \"ui-button--color-success\",\n },\n size: {\n md: \"ui-button--size-md\",\n sm: \"ui-button--size-sm\",\n lg: \"ui-button--size-lg\",\n icon: \"ui-button--size-icon\",\n },\n },\n defaultVariants: {\n variant: \"contained\",\n color: \"primary\",\n size: \"md\",\n },\n});\n\ntype ButtonElement = HTMLButtonElement;\n\nexport interface ButtonProps\n extends\n Omit<React.ButtonHTMLAttributes<ButtonElement>, \"color\">,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = React.forwardRef<ButtonElement, ButtonProps>(\n (\n { className, variant, color, size, asChild = false, type, ...props },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"button\";\n\n return (\n <Comp\n ref={ref}\n className={cn(buttonVariants({ variant, color, size }), className)}\n type={asChild ? undefined : (type ?? \"button\")}\n {...props}\n />\n );\n },\n);\n\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","import { type ComponentProps, forwardRef } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst Card = forwardRef<HTMLDivElement, ComponentProps<\"div\">>(\n ({ className, ...props }, ref) => {\n return <div ref={ref} className={cn(\"ui-card\", className)} {...props} />;\n },\n);\n\nCard.displayName = \"Card\";\n\nfunction CardHeader({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={cn(\"ui-card-header\", className)} {...props} />;\n}\n\nfunction CardTitle({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={cn(\"ui-card-title\", className)} {...props} />;\n}\n\nfunction CardDescription({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={cn(\"ui-card-description\", className)} {...props} />;\n}\n\nfunction CardAction({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={cn(\"ui-card-action\", className)} {...props} />;\n}\n\nfunction CardContent({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={cn(\"ui-card-content\", className)} {...props} />;\n}\n\nfunction CardFooter({ className, ...props }: ComponentProps<\"div\">) {\n return <div className={cn(\"ui-card-footer\", className)} {...props} />;\n}\n\nexport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n};\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst surfaceVariants = cva(\"ui-surface\", {\n variants: {\n tone: {\n canvas: \"ui-surface--tone-canvas\",\n panel: \"ui-surface--tone-panel\",\n raised: \"ui-surface--tone-raised\",\n subtle: \"ui-surface--tone-subtle\",\n },\n border: {\n none: \"\",\n subtle: \"ui-surface--border-subtle\",\n },\n radius: {\n none: \"ui-surface--radius-none\",\n sm: \"ui-surface--radius-sm\",\n md: \"ui-surface--radius-md\",\n lg: \"ui-surface--radius-lg\",\n },\n shadow: {\n none: \"\",\n sm: \"ui-surface--shadow-sm\",\n md: \"ui-surface--shadow-md\",\n lg: \"ui-surface--shadow-lg\",\n xl: \"ui-surface--shadow-xl\",\n },\n intent: {\n neutral: \"\",\n success: \"ui-surface--intent-success\",\n warning: \"ui-surface--intent-warning\",\n error: \"ui-surface--intent-error\",\n info: \"ui-surface--intent-info\",\n },\n },\n defaultVariants: {\n tone: \"raised\",\n border: \"none\",\n radius: \"md\",\n shadow: \"none\",\n intent: \"neutral\",\n },\n});\n\ntype SurfaceElement = HTMLDivElement;\n\nexport interface SurfaceProps\n extends\n React.HTMLAttributes<SurfaceElement>,\n VariantProps<typeof surfaceVariants> {\n asChild?: boolean;\n}\n\nconst Surface = React.forwardRef<SurfaceElement, SurfaceProps>(\n (\n {\n className,\n tone,\n border,\n radius,\n shadow,\n intent,\n asChild = false,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"div\";\n\n return (\n <Comp\n ref={ref}\n className={cn(\n surfaceVariants({ tone, border, radius, shadow, intent }),\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nSurface.displayName = \"Surface\";\n\nexport { Surface, surfaceVariants };\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst stackVariants = cva(\"ui-stack\", {\n variants: {\n direction: {\n row: \"ui-stack--row\",\n column: \"ui-stack--column\",\n },\n align: {\n start: \"ui-stack--align-start\",\n center: \"ui-stack--align-center\",\n end: \"ui-stack--align-end\",\n stretch: \"ui-stack--align-stretch\",\n baseline: \"ui-stack--align-baseline\",\n },\n justify: {\n start: \"ui-stack--justify-start\",\n center: \"ui-stack--justify-center\",\n end: \"ui-stack--justify-end\",\n between: \"ui-stack--justify-between\",\n around: \"ui-stack--justify-around\",\n evenly: \"ui-stack--justify-evenly\",\n },\n gap: {\n 0: \"ui-stack--gap-0\",\n 1: \"ui-stack--gap-1\",\n 2: \"ui-stack--gap-2\",\n 3: \"ui-stack--gap-3\",\n 4: \"ui-stack--gap-4\",\n 5: \"ui-stack--gap-5\",\n 6: \"ui-stack--gap-6\",\n },\n wrap: {\n true: \"ui-stack--wrap\",\n false: \"\",\n },\n },\n defaultVariants: {\n direction: \"column\",\n align: \"stretch\",\n justify: \"start\",\n gap: 2,\n wrap: false,\n },\n});\n\ntype StackElement = HTMLDivElement;\n\nexport interface StackProps\n extends\n React.HTMLAttributes<StackElement>,\n VariantProps<typeof stackVariants> {\n asChild?: boolean;\n}\n\nconst Stack = React.forwardRef<StackElement, StackProps>(\n (\n {\n className,\n direction,\n align,\n justify,\n gap,\n wrap,\n asChild = false,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : \"div\";\n\n return (\n <Comp\n ref={ref}\n className={cn(\n stackVariants({ direction, align, justify, gap, wrap }),\n className,\n )}\n {...props}\n />\n );\n },\n);\n\nStack.displayName = \"Stack\";\n\nexport { Stack, stackVariants };\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst dividerVariants = cva(\"ui-divider\", {\n variants: {\n orientation: {\n horizontal: \"ui-divider--horizontal\",\n vertical: \"ui-divider--vertical\",\n },\n tone: {\n subtle: \"ui-divider--tone-subtle\",\n strong: \"ui-divider--tone-strong\",\n },\n },\n defaultVariants: {\n orientation: \"horizontal\",\n tone: \"subtle\",\n },\n});\n\ntype DividerElement = HTMLDivElement;\n\nexport interface DividerProps\n extends\n React.HTMLAttributes<DividerElement>,\n VariantProps<typeof dividerVariants> {}\n\nconst Divider = React.forwardRef<DividerElement, DividerProps>(\n ({ className, orientation, tone, ...props }, ref) => {\n return (\n <div\n ref={ref}\n role=\"separator\"\n aria-orientation={orientation ?? \"horizontal\"}\n className={cn(dividerVariants({ orientation, tone }), className)}\n {...props}\n />\n );\n },\n);\n\nDivider.displayName = \"Divider\";\n\nexport { Divider, dividerVariants };\n","import * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { Button, type ButtonProps } from \"./button\";\n\ntype IconButtonSize = \"xs\" | \"sm\" | \"md\";\n\nconst sizeClass: Record<IconButtonSize, string> = {\n xs: \"ui-icon-button--size-xs\",\n sm: \"ui-icon-button--size-sm\",\n md: \"ui-icon-button--size-md\",\n};\n\nexport interface IconButtonProps extends Omit<\n ButtonProps,\n \"children\" | \"size\" | \"asChild\"\n> {\n icon: React.ReactNode;\n size?: IconButtonSize;\n \"aria-label\": string;\n}\n\nconst IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n (\n {\n icon,\n size = \"md\",\n variant = \"text\",\n color = \"secondary\",\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <Button\n ref={ref}\n variant={variant}\n color={color}\n size=\"icon\"\n className={cn(\"ui-icon-button\", sizeClass[size], className)}\n {...props}\n >\n {icon}\n </Button>\n );\n },\n);\n\nIconButton.displayName = \"IconButton\";\n\nexport { IconButton };\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, type InputHTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst inputVariants = cva(\"ui-input\", {\n variants: {\n size: {\n sm: \"ui-input--size-sm\",\n md: \"ui-input--size-md\",\n },\n },\n defaultVariants: {\n size: \"md\",\n },\n});\n\nexport interface InputProps\n extends\n Omit<InputHTMLAttributes<HTMLInputElement>, \"size\">,\n VariantProps<typeof inputVariants> {}\n\nconst Input = forwardRef<HTMLInputElement, InputProps>(\n ({ className, type = \"text\", size, ...props }, ref) => {\n return (\n <input\n ref={ref}\n type={type}\n data-size={size ?? \"md\"}\n className={cn(inputVariants({ size }), className)}\n {...props}\n />\n );\n },\n);\n\nInput.displayName = \"Input\";\n\nexport { Input, inputVariants };\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, type TextareaHTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst textareaVariants = cva(\"ui-textarea\", {\n variants: {\n size: {\n sm: \"ui-textarea--size-sm\",\n md: \"ui-textarea--size-md\",\n },\n resize: {\n none: \"ui-textarea--resize-none\",\n vertical: \"ui-textarea--resize-vertical\",\n both: \"ui-textarea--resize-both\",\n },\n },\n defaultVariants: {\n size: \"md\",\n resize: \"vertical\",\n },\n});\n\nexport interface TextareaProps\n extends\n Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, \"size\">,\n VariantProps<typeof textareaVariants> {}\n\nconst Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, size, resize, ...props }, ref) => {\n return (\n <textarea\n ref={ref}\n data-size={size ?? \"md\"}\n className={cn(textareaVariants({ size, resize }), className)}\n {...props}\n />\n );\n },\n);\n\nTextarea.displayName = \"Textarea\";\n\nexport { Textarea, textareaVariants };\n","import * as LabelPrimitive from \"@radix-ui/react-label\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nfunction Label({\n className,\n ...props\n}: ComponentProps<typeof LabelPrimitive.Root>) {\n return (\n <LabelPrimitive.Root className={cn(\"ui-label\", className)} {...props} />\n );\n}\n\nexport { Label };\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, type HTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst textVariants = cva(\"ui-text\", {\n variants: {\n tone: {\n primary: \"ui-text--tone-primary\",\n secondary: \"ui-text--tone-secondary\",\n muted: \"ui-text--tone-muted\",\n success: \"ui-text--tone-success\",\n warning: \"ui-text--tone-warning\",\n error: \"ui-text--tone-error\",\n info: \"ui-text--tone-info\",\n },\n size: {\n xs: \"ui-text--size-xs\",\n sm: \"ui-text--size-sm\",\n md: \"ui-text--size-md\",\n lg: \"ui-text--size-lg\",\n },\n weight: {\n regular: \"ui-text--weight-regular\",\n medium: \"ui-text--weight-medium\",\n semibold: \"ui-text--weight-semibold\",\n },\n },\n defaultVariants: {\n tone: \"primary\",\n size: \"sm\",\n weight: \"regular\",\n },\n});\n\ntype TextElement = HTMLParagraphElement;\n\nexport interface TextProps\n extends HTMLAttributes<TextElement>, VariantProps<typeof textVariants> {\n asChild?: boolean;\n}\n\nconst Text = forwardRef<TextElement, TextProps>(\n ({ className, tone, size, weight, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"p\";\n\n return (\n <Comp\n ref={ref}\n className={cn(textVariants({ tone, size, weight }), className)}\n {...props}\n />\n );\n },\n);\n\nText.displayName = \"Text\";\n\nexport { Text, textVariants };\n","import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { forwardRef, type HTMLAttributes } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst badgeVariants = cva(\"ui-badge\", {\n variants: {\n tone: {\n neutral: \"ui-badge--tone-neutral\",\n primary: \"ui-badge--tone-primary\",\n secondary: \"ui-badge--tone-secondary\",\n success: \"ui-badge--tone-success\",\n warning: \"ui-badge--tone-warning\",\n error: \"ui-badge--tone-error\",\n info: \"ui-badge--tone-info\",\n },\n variant: {\n soft: \"ui-badge--variant-soft\",\n solid: \"ui-badge--variant-solid\",\n outline: \"ui-badge--variant-outline\",\n },\n size: {\n sm: \"ui-badge--size-sm\",\n md: \"ui-badge--size-md\",\n },\n },\n defaultVariants: {\n tone: \"neutral\",\n variant: \"soft\",\n size: \"md\",\n },\n});\n\ntype BadgeElement = HTMLSpanElement;\n\nexport interface BadgeProps\n extends HTMLAttributes<BadgeElement>, VariantProps<typeof badgeVariants> {\n asChild?: boolean;\n}\n\nconst Badge = forwardRef<BadgeElement, BadgeProps>(\n ({ className, tone, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : \"span\";\n\n return (\n <Comp\n ref={ref}\n className={cn(badgeVariants({ tone, variant, size }), className)}\n {...props}\n />\n );\n },\n);\n\nBadge.displayName = \"Badge\";\n\nexport { Badge, badgeVariants };\n","import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nconst switchVariants = cva(\"ui-switch\", {\n variants: {\n size: {\n sm: \"ui-switch--size-sm\",\n md: \"ui-switch--size-md\",\n },\n color: {\n primary: \"ui-switch--color-primary\",\n secondary: \"ui-switch--color-secondary\",\n error: \"ui-switch--color-error\",\n warning: \"ui-switch--color-warning\",\n info: \"ui-switch--color-info\",\n success: \"ui-switch--color-success\",\n },\n },\n defaultVariants: {\n size: \"md\",\n color: \"primary\",\n },\n});\n\nexport interface SwitchProps\n extends\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"color\" | \"onChange\">,\n VariantProps<typeof switchVariants> {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n}\n\nconst Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(\n (\n {\n checked = false,\n onCheckedChange,\n className,\n size,\n color,\n type,\n onClick,\n ...props\n },\n ref,\n ) => {\n return (\n <button\n ref={ref}\n type={type ?? \"button\"}\n role=\"switch\"\n aria-checked={checked}\n data-state={checked ? \"checked\" : \"unchecked\"}\n className={cn(switchVariants({ size, color }), className)}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) {\n onCheckedChange?.(!checked);\n }\n }}\n {...props}\n >\n <span aria-hidden className=\"ui-switch__thumb\" />\n </button>\n );\n },\n);\n\nSwitch.displayName = \"Switch\";\n\nexport { Switch };\n","import * as SelectPrimitive from \"@radix-ui/react-select\";\nimport type { ComponentProps } from \"react\";\nimport { useMemo } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nfunction SelectChevronDownIcon(props: ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden {...props}>\n <path\n d=\"M4 6.5 8 10.5 12 6.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nfunction SelectChevronUpIcon(props: ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden {...props}>\n <path\n d=\"M4 9.5 8 5.5 12 9.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nfunction SelectCheckIcon(props: ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden {...props}>\n <path\n d=\"M3.5 8.5 6.5 11.5 12.5 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nfunction Select(props: ComponentProps<typeof SelectPrimitive.Root>) {\n return <SelectPrimitive.Root {...props} />;\n}\n\nfunction SelectGroup(props: ComponentProps<typeof SelectPrimitive.Group>) {\n return <SelectPrimitive.Group {...props} />;\n}\n\nfunction SelectValue({\n className,\n ...props\n}: ComponentProps<typeof SelectPrimitive.Value>) {\n return (\n <SelectPrimitive.Value\n className={cn(\"ui-select-value\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectTrigger({\n className,\n size = \"md\",\n children,\n ...props\n}: ComponentProps<typeof SelectPrimitive.Trigger> & {\n size?: \"sm\" | \"md\";\n}) {\n return (\n <SelectPrimitive.Trigger\n data-size={size}\n className={cn(\"ui-select-trigger\", className)}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <SelectChevronDownIcon className=\"ui-select-chevron\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nfunction SelectContent({\n className,\n children,\n position = \"popper\",\n ...props\n}: ComponentProps<typeof SelectPrimitive.Content>) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n position={position}\n className={cn(\n \"ui-select-content\",\n position === \"popper\" && \"ui-select-content--popper\",\n className,\n )}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n \"ui-select-viewport\",\n position === \"popper\" && \"ui-select-viewport--popper\",\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nfunction SelectLabel({\n className,\n ...props\n}: ComponentProps<typeof SelectPrimitive.Label>) {\n return (\n <SelectPrimitive.Label\n className={cn(\"ui-select-label\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectItem({\n className,\n children,\n ...props\n}: ComponentProps<typeof SelectPrimitive.Item>) {\n return (\n <SelectPrimitive.Item\n className={cn(\"ui-select-item\", className)}\n {...props}\n >\n <span className=\"ui-select-indicator\" aria-hidden>\n <SelectPrimitive.ItemIndicator>\n <SelectCheckIcon className=\"ui-select-indicator-icon\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText className=\"ui-select-item-text\">\n {children}\n </SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n\nfunction SelectSeparator({\n className,\n ...props\n}: ComponentProps<typeof SelectPrimitive.Separator>) {\n return (\n <SelectPrimitive.Separator\n className={cn(\"ui-select-separator\", className)}\n {...props}\n />\n );\n}\n\nfunction SelectScrollUpButton({\n className,\n ...props\n}: ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n return (\n <SelectPrimitive.ScrollUpButton\n className={cn(\"ui-select-scroll-button\", className)}\n {...props}\n >\n <SelectChevronUpIcon className=\"ui-select-scroll-icon\" />\n </SelectPrimitive.ScrollUpButton>\n );\n}\n\nfunction SelectScrollDownButton({\n className,\n ...props\n}: ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n return (\n <SelectPrimitive.ScrollDownButton\n className={cn(\"ui-select-scroll-button\", className)}\n {...props}\n >\n <SelectChevronDownIcon className=\"ui-select-scroll-icon\" />\n </SelectPrimitive.ScrollDownButton>\n );\n}\n\ntype OptionSelectValue = string | number;\ntype OptionSelectValueOption = { name: string; value: OptionSelectValue };\ntype OptionSelectIdOption = { id: string; name: string };\ntype OptionSelectInput =\n | readonly string[]\n | readonly number[]\n | readonly OptionSelectValueOption[]\n | readonly OptionSelectIdOption[];\n\nexport interface OptionSelectProps<T extends OptionSelectValue | undefined> {\n value: T;\n options: OptionSelectInput;\n label?: string;\n contentClassName?: string;\n triggerClassName?: string;\n disabled?: boolean;\n onChange: (value: T) => void;\n}\n\nfunction isValueOption(value: unknown): value is OptionSelectValueOption {\n return Boolean(\n value &&\n typeof value === \"object\" &&\n \"name\" in value &&\n \"value\" in value &&\n (typeof (value as { value: unknown }).value === \"string\" ||\n typeof (value as { value: unknown }).value === \"number\"),\n );\n}\n\nfunction isIdOption(value: unknown): value is OptionSelectIdOption {\n return Boolean(\n value &&\n typeof value === \"object\" &&\n \"id\" in value &&\n \"name\" in value &&\n typeof (value as { id: unknown }).id === \"string\",\n );\n}\n\nfunction OptionSelect<T extends OptionSelectValue | undefined>({\n value,\n options,\n label,\n contentClassName,\n triggerClassName,\n disabled = false,\n onChange,\n}: OptionSelectProps<T>) {\n const normalizedOptions = useMemo(() => {\n if (!options.length) return [];\n\n const first = options[0];\n if (typeof first === \"string\" || typeof first === \"number\") {\n return (options as readonly OptionSelectValue[]).map((option) => ({\n name: option.toString(),\n value: option,\n }));\n }\n\n if (isValueOption(first)) {\n return Array.from(options as readonly OptionSelectValueOption[]);\n }\n\n if (isIdOption(first)) {\n return (options as readonly OptionSelectIdOption[]).map((option) => ({\n name: option.name,\n value: option.id,\n }));\n }\n\n return [];\n }, [options]);\n\n const valueKind = useMemo<\"number\" | \"string\">(() => {\n if (!normalizedOptions.length) {\n return typeof value === \"number\" ? \"number\" : \"string\";\n }\n return typeof normalizedOptions[0]?.value === \"number\"\n ? \"number\"\n : \"string\";\n }, [normalizedOptions, value]);\n\n const onValueChange = (newValue: string) => {\n if (valueKind === \"number\") {\n onChange(Number(newValue) as T);\n return;\n }\n onChange(newValue as T);\n };\n\n const selectedValue =\n value !== undefined && value !== \"\" ? value.toString() : undefined;\n const placeholder = label && label.length > 0 ? label : \"Select...\";\n const longestDisplayLength = useMemo(() => {\n const longestOption = normalizedOptions.reduce((maxLength, option) => {\n const length = option.name.length;\n return Math.max(maxLength, length);\n }, 0);\n\n return Math.max(placeholder.length, longestOption);\n }, [normalizedOptions, placeholder]);\n const autoWidthCh = Math.min(Math.max(longestDisplayLength + 6, 18), 40);\n\n const triggerStyle = triggerClassName\n ? undefined\n : ({\n width: `clamp(10rem, ${autoWidthCh}ch, 26rem)`,\n maxWidth: \"100%\",\n } as const);\n\n return (\n <Select\n value={selectedValue}\n onValueChange={onValueChange}\n disabled={disabled}\n >\n <SelectTrigger className={triggerClassName} style={triggerStyle}>\n <SelectValue placeholder={placeholder} />\n </SelectTrigger>\n <SelectContent className={contentClassName}>\n <SelectGroup>\n <SelectLabel>Select...</SelectLabel>\n {normalizedOptions.map((option) => (\n <SelectItem key={option.value} value={option.value.toString()}>\n {option.name}\n </SelectItem>\n ))}\n </SelectGroup>\n </SelectContent>\n </Select>\n );\n}\n\nexport {\n OptionSelect,\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n};\n","import { throttle } from \"@blibliki/utils\";\nimport { ChangeEvent } from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport { Button } from \"./button\";\n\nexport type TOrientation = \"vertical\" | \"horizontal\";\n\nexport type MarkProps = {\n value: number;\n label: string;\n};\n\nexport interface FaderProps extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n \"onChange\"\n> {\n name: string;\n onChange: (value: number, calculatedValue: number) => void;\n defaultValue?: number;\n value?: number;\n orientation?: TOrientation;\n marks?: readonly MarkProps[];\n hideMarks?: boolean;\n max?: number;\n min?: number;\n step?: number;\n exp?: number;\n}\n\nconst calcValue = (\n sliderValue: number,\n min: number,\n max: number,\n exp?: number,\n) => {\n if (exp === undefined || exp === 1) return sliderValue;\n\n const range = max - min;\n if (range === 0) return min;\n const normalizedSlider = (sliderValue - min) / range;\n const curved = Math.pow(normalizedSlider, exp);\n\n return min + curved * range;\n};\n\nconst revCalcValue = (\n actualValue: number,\n min: number,\n max: number,\n exp?: number,\n) => {\n if (exp === undefined || exp === 1) return actualValue;\n\n const range = max - min;\n if (range === 0) return min;\n const normalizedValue = (actualValue - min) / range;\n const inverseExp = 1 / exp;\n const sliderPosition = Math.pow(normalizedValue, inverseExp);\n\n return min + sliderPosition * range;\n};\n\nfunction formatTooltipValue(value?: number) {\n if (value === undefined) return \"\";\n if (Number.isInteger(value)) return `${value}`;\n return value.toFixed(2);\n}\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(max, Math.max(min, value));\n\nfunction Fader(props: FaderProps) {\n const {\n className,\n name,\n onChange,\n value,\n defaultValue,\n marks,\n hideMarks = false,\n exp,\n min = 0,\n orientation = \"vertical\",\n max: maxProp,\n step: stepProp,\n ...rest\n } = props;\n\n const marksCount = marks?.length ?? 0;\n const hasMarkedScale = marksCount > 0;\n const max = maxProp ?? (hasMarkedScale ? marksCount - 1 : 1);\n const step = stepProp ?? (hasMarkedScale ? 1 : 0.01);\n\n const sliderValue =\n value !== undefined\n ? clamp(revCalcValue(value, min, max, exp), min, max)\n : undefined;\n const sliderDefaultValue =\n defaultValue !== undefined ? clamp(defaultValue, min, max) : min;\n\n const onRangeChange = (event: ChangeEvent<HTMLInputElement>) => {\n const nextSliderValue = clamp(Number(event.target.value), min, max);\n onChange(nextSliderValue, calcValue(nextSliderValue, min, max, exp));\n };\n const debouncedOnChange = throttle(onRangeChange, 1000);\n\n const onMarkClick = (markValue: number) => () => {\n const nextSliderValue = clamp(markValue, min, max);\n onChange(nextSliderValue, calcValue(nextSliderValue, min, max, exp));\n };\n const getHorizontalMarkPosition = (markValue: number) => {\n if (max === min) return 0;\n return ((clamp(markValue, min, max) - min) / (max - min)) * 100;\n };\n\n const hasOnlyZeroMarks = marks\n ? marks.every((mark) => mark.value === 0)\n : false;\n const showTooltip = hideMarks || !marks || hasOnlyZeroMarks;\n const currentSliderValue = sliderValue ?? sliderDefaultValue;\n const activeMark = marks?.find((mark) => mark.value === currentSliderValue);\n const currentDisplayValue =\n value ?? calcValue(currentSliderValue, min, max, exp);\n const tooltipText =\n activeMark?.label ?? formatTooltipValue(currentDisplayValue);\n\n const rangeValueProps =\n sliderValue !== undefined\n ? ({ value: sliderValue } as const)\n : ({ defaultValue: sliderDefaultValue } as const);\n\n return (\n <div\n className={cn(\n \"ui-fader nodrag\",\n orientation === \"horizontal\" && \"ui-fader--horizontal\",\n className,\n )}\n {...rest}\n >\n <div\n className={cn(\n \"ui-fader__control\",\n orientation === \"horizontal\"\n ? \"ui-fader__control--horizontal\"\n : \"ui-fader__control--vertical\",\n )}\n >\n <input\n type=\"range\"\n min={min}\n max={max}\n {...rangeValueProps}\n step={step}\n aria-label={name}\n className={cn(\n \"ui-fader__range\",\n orientation === \"horizontal\"\n ? \"ui-fader__range--horizontal\"\n : \"ui-fader__range--vertical\",\n )}\n onChange={debouncedOnChange}\n />\n\n {showTooltip && (\n <div\n className={cn(\n \"ui-fader__tooltip\",\n orientation === \"horizontal\"\n ? \"ui-fader__tooltip--horizontal\"\n : \"ui-fader__tooltip--vertical\",\n )}\n >\n {tooltipText}\n </div>\n )}\n\n {marks && !hideMarks && (\n <div\n className={cn(\n \"ui-fader__marks\",\n orientation === \"horizontal\"\n ? \"ui-fader__marks--horizontal\"\n : \"ui-fader__marks--vertical\",\n marks.length === 1 && \"ui-fader__marks--single\",\n )}\n >\n {marks.map((mark, index) => (\n <Button\n key={`${mark.value}-${index}`}\n size=\"sm\"\n variant=\"text\"\n color=\"secondary\"\n className={cn(\n \"ui-fader__mark-button\",\n orientation === \"horizontal\" &&\n \"ui-fader__mark-button--horizontal\",\n orientation === \"horizontal\" &&\n mark.value <= min &&\n \"ui-fader__mark-button--horizontal-start\",\n orientation === \"horizontal\" &&\n mark.value >= max &&\n \"ui-fader__mark-button--horizontal-end\",\n )}\n style={\n orientation === \"horizontal\"\n ? { left: `${getHorizontalMarkPosition(mark.value)}%` }\n : undefined\n }\n onClick={onMarkClick(mark.value)}\n >\n <span className=\"ui-fader__mark-dot\" aria-hidden />\n {mark.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n\n <div className=\"ui-fader__label-row\">\n <span className=\"ui-fader__label-dot\" aria-hidden />\n <span className=\"ui-fader__label\">{name}</span>\n </div>\n </div>\n );\n}\n\nFader.displayName = \"Fader\";\n\nexport { Fader };\n","import {\n forwardRef,\n type CSSProperties,\n type HTMLAttributes,\n type KeyboardEvent,\n type PointerEvent,\n type WheelEvent,\n useRef,\n useState,\n} from \"react\";\nimport { cn } from \"@/lib/cn\";\n\ntype EncoderSize = \"sm\" | \"md\";\n\ntype DragState = {\n pointerId: number;\n lastY: number;\n sliderValue: number;\n};\n\nconst FULL_RANGE_DRAG_DISTANCE_PX = 80;\nconst FINE_DRAG_DISTANCE_MULTIPLIER = 8;\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(max, Math.max(min, value));\n\nconst calcSliderValue = (\n actualValue: number,\n min: number,\n max: number,\n exp?: number,\n) => {\n if (exp === undefined || exp === 1) return actualValue;\n\n const range = max - min;\n if (range === 0) return min;\n\n const normalizedValue = (actualValue - min) / range;\n const inverseExp = 1 / exp;\n\n return min + Math.pow(normalizedValue, inverseExp) * range;\n};\n\nconst calcActualValue = (\n sliderValue: number,\n min: number,\n max: number,\n exp?: number,\n) => {\n if (exp === undefined || exp === 1) return sliderValue;\n\n const range = max - min;\n if (range === 0) return min;\n\n const normalizedSlider = (sliderValue - min) / range;\n\n return min + Math.pow(normalizedSlider, exp) * range;\n};\n\nconst getStepPrecision = (step: number) => {\n const stepString = `${step}`;\n const decimalIndex = stepString.indexOf(\".\");\n\n return decimalIndex === -1 ? 0 : stepString.length - decimalIndex - 1;\n};\n\nconst roundToStep = (value: number, min: number, step: number) => {\n const precision = getStepPrecision(step);\n const nextValue = Math.round((value - min) / step) * step + min;\n\n return Number(nextValue.toFixed(precision));\n};\n\nconst formatDisplayValue = (value: number, step: number) => {\n const precision = Math.min(4, getStepPrecision(step));\n\n if (precision === 0) return `${Math.round(value)}`;\n\n return `${Number(value.toFixed(precision))}`;\n};\n\nexport interface EncoderProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"onChange\"\n> {\n name: string;\n onChange: (value: number) => void;\n defaultValue?: number;\n value?: number;\n max?: number;\n min?: number;\n step?: number;\n exp?: number;\n size?: EncoderSize;\n disabled?: boolean;\n formatValue?: (value: number) => string;\n}\n\nconst Encoder = forwardRef<HTMLDivElement, EncoderProps>(\n (\n {\n className,\n style,\n name,\n onChange,\n value,\n defaultValue,\n max = 1,\n min = 0,\n step = 0.01,\n exp,\n size = \"md\",\n disabled = false,\n formatValue,\n onKeyDown,\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n onWheel,\n ...rest\n },\n ref,\n ) => {\n const [uncontrolledValue, setUncontrolledValue] = useState(\n clamp(defaultValue ?? min, min, max),\n );\n const dragStateRef = useRef<DragState | null>(null);\n\n const currentValue = clamp(value ?? uncontrolledValue, min, max);\n const currentSliderValue = clamp(\n calcSliderValue(currentValue, min, max, exp),\n min,\n max,\n );\n\n const progress = max === min ? 0 : (currentSliderValue - min) / (max - min);\n\n const displayValue = formatValue\n ? formatValue(currentValue)\n : formatDisplayValue(currentValue, step);\n\n const commitValue = (nextRawValue: number) => {\n const nextValue = clamp(roundToStep(nextRawValue, min, step), min, max);\n\n if (nextValue === currentValue) return;\n\n if (value === undefined) {\n setUncontrolledValue(nextValue);\n }\n\n onChange(nextValue);\n };\n\n const changeBySteps = (stepDelta: number) => {\n commitValue(currentValue + stepDelta * step);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n\n if (event.defaultPrevented || disabled) return;\n\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowRight\":\n event.preventDefault();\n changeBySteps(1);\n return;\n case \"ArrowDown\":\n case \"ArrowLeft\":\n event.preventDefault();\n changeBySteps(-1);\n return;\n case \"PageUp\":\n event.preventDefault();\n changeBySteps(10);\n return;\n case \"PageDown\":\n event.preventDefault();\n changeBySteps(-10);\n return;\n case \"Home\":\n event.preventDefault();\n commitValue(min);\n return;\n case \"End\":\n event.preventDefault();\n commitValue(max);\n return;\n default:\n return;\n }\n };\n\n const handlePointerDown = (event: PointerEvent<HTMLDivElement>) => {\n onPointerDown?.(event);\n\n if (event.defaultPrevented || disabled) return;\n\n event.preventDefault();\n event.currentTarget.focus();\n event.currentTarget.setPointerCapture(event.pointerId);\n\n dragStateRef.current = {\n pointerId: event.pointerId,\n lastY: event.clientY,\n sliderValue: currentSliderValue,\n };\n };\n\n const handlePointerMove = (event: PointerEvent<HTMLDivElement>) => {\n onPointerMove?.(event);\n\n if (event.defaultPrevented || disabled) return;\n\n const dragState = dragStateRef.current;\n\n if (dragState?.pointerId !== event.pointerId) return;\n\n event.preventDefault();\n\n const dragDistance =\n FULL_RANGE_DRAG_DISTANCE_PX *\n (event.shiftKey ? FINE_DRAG_DISTANCE_MULTIPLIER : 1);\n const deltaSliderValue =\n ((dragState.lastY - event.clientY) * (max - min)) / dragDistance;\n const nextSliderValue = clamp(\n dragState.sliderValue + deltaSliderValue,\n min,\n max,\n );\n const nextValue = calcActualValue(nextSliderValue, min, max, exp);\n\n dragState.lastY = event.clientY;\n dragState.sliderValue = nextSliderValue;\n\n commitValue(nextValue);\n };\n\n const clearDragState = (event: PointerEvent<HTMLDivElement>) => {\n const dragState = dragStateRef.current;\n\n if (dragState?.pointerId !== event.pointerId) return;\n\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n\n dragStateRef.current = null;\n };\n\n const handlePointerUp = (event: PointerEvent<HTMLDivElement>) => {\n onPointerUp?.(event);\n\n if (event.defaultPrevented) return;\n\n clearDragState(event);\n };\n\n const handlePointerCancel = (event: PointerEvent<HTMLDivElement>) => {\n onPointerCancel?.(event);\n\n if (event.defaultPrevented) return;\n\n clearDragState(event);\n };\n\n const handleWheel = (event: WheelEvent<HTMLDivElement>) => {\n onWheel?.(event);\n\n if (event.defaultPrevented || disabled || event.deltaY === 0) return;\n\n event.preventDefault();\n changeBySteps(event.deltaY < 0 ? 1 : -1);\n };\n\n return (\n <div\n ref={ref}\n role=\"slider\"\n tabIndex={disabled ? -1 : 0}\n aria-label={name}\n aria-disabled={disabled}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={currentValue}\n aria-valuetext={displayValue}\n data-size={size}\n className={cn(\n \"ui-encoder\",\n size === \"sm\" && \"ui-encoder--size-sm\",\n size === \"md\" && \"ui-encoder--size-md\",\n disabled && \"ui-encoder--disabled\",\n className,\n )}\n style={\n {\n ...style,\n \"--ui-encoder-angle\": `${-135 + progress * 270}deg`,\n \"--ui-encoder-fill\": `${progress * 270}deg`,\n } as CSSProperties\n }\n onKeyDown={handleKeyDown}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerCancel}\n onWheel={handleWheel}\n {...rest}\n >\n <div className=\"ui-encoder__dial\">\n <span className=\"ui-encoder__indicator\" aria-hidden />\n </div>\n <span className=\"ui-encoder__value\">{displayValue}</span>\n </div>\n );\n },\n);\n\nEncoder.displayName = \"Encoder\";\n\nexport { Encoder };\n","import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nfunction Dialog(props: React.ComponentProps<typeof DialogPrimitive.Root>) {\n return <DialogPrimitive.Root {...props} />;\n}\n\nfunction DialogTrigger(\n props: React.ComponentProps<typeof DialogPrimitive.Trigger>,\n) {\n return <DialogPrimitive.Trigger {...props} />;\n}\n\nfunction DialogPortal(\n props: React.ComponentProps<typeof DialogPrimitive.Portal>,\n) {\n return <DialogPrimitive.Portal {...props} />;\n}\n\nfunction DialogClose(\n props: React.ComponentProps<typeof DialogPrimitive.Close>,\n) {\n return <DialogPrimitive.Close {...props} />;\n}\n\nfunction DialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {\n return (\n <DialogPrimitive.Overlay\n className={cn(\"ui-dialog-overlay\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogCloseIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden {...props}>\n <path\n d=\"M3.5 3.5 12.5 12.5M12.5 3.5 3.5 12.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\ninterface DialogContentProps extends React.ComponentProps<\n typeof DialogPrimitive.Content\n> {\n hideCloseButton?: boolean;\n}\n\nfunction DialogContent({\n className,\n children,\n hideCloseButton = false,\n ...props\n}: DialogContentProps) {\n return (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n className={cn(\"ui-dialog-content\", className)}\n {...props}\n >\n {children}\n {!hideCloseButton && (\n <DialogPrimitive.Close className=\"ui-dialog-close\">\n <DialogCloseIcon className=\"ui-dialog-close-icon\" />\n <span className=\"ui-visually-hidden\">Close</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nfunction DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={cn(\"ui-dialog-header\", className)} {...props} />;\n}\n\nfunction DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={cn(\"ui-dialog-footer\", className)} {...props} />;\n}\n\nfunction DialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return (\n <DialogPrimitive.Title\n className={cn(\"ui-dialog-title\", className)}\n {...props}\n />\n );\n}\n\nfunction DialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return (\n <DialogPrimitive.Description\n className={cn(\"ui-dialog-description\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogClose,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n type DialogContentProps,\n};\n","import * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\";\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nfunction MenuCheckIcon(props: ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden {...props}>\n <path\n d=\"M3.5 8.5 6.5 11.5 12.5 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nfunction MenuDotIcon(props: ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden {...props}>\n <circle cx=\"8\" cy=\"8\" r=\"3\" />\n </svg>\n );\n}\n\nfunction MenuChevronRightIcon(props: ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden {...props}>\n <path\n d=\"M6 3.5 10.5 8 6 12.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nfunction ContextMenu(props: ComponentProps<typeof ContextMenuPrimitive.Root>) {\n return <ContextMenuPrimitive.Root {...props} />;\n}\n\nfunction ContextMenuTrigger(\n props: ComponentProps<typeof ContextMenuPrimitive.Trigger>,\n) {\n return <ContextMenuPrimitive.Trigger {...props} />;\n}\n\nfunction ContextMenuGroup(\n props: ComponentProps<typeof ContextMenuPrimitive.Group>,\n) {\n return <ContextMenuPrimitive.Group {...props} />;\n}\n\nfunction ContextMenuPortal(\n props: ComponentProps<typeof ContextMenuPrimitive.Portal>,\n) {\n return <ContextMenuPrimitive.Portal {...props} />;\n}\n\nfunction ContextMenuSub(\n props: ComponentProps<typeof ContextMenuPrimitive.Sub>,\n) {\n return <ContextMenuPrimitive.Sub {...props} />;\n}\n\nfunction ContextMenuRadioGroup(\n props: ComponentProps<typeof ContextMenuPrimitive.RadioGroup>,\n) {\n return <ContextMenuPrimitive.RadioGroup {...props} />;\n}\n\nfunction ContextMenuSubTrigger({\n className,\n inset = false,\n children,\n ...props\n}: ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n}) {\n return (\n <ContextMenuPrimitive.SubTrigger\n data-inset={inset ? \"true\" : undefined}\n className={cn(\"ui-dropdown-item ui-dropdown-sub-trigger\", className)}\n {...props}\n >\n {children}\n <MenuChevronRightIcon className=\"ui-dropdown-chevron\" />\n </ContextMenuPrimitive.SubTrigger>\n );\n}\n\nfunction ContextMenuSubContent({\n className,\n ...props\n}: ComponentProps<typeof ContextMenuPrimitive.SubContent>) {\n return (\n <ContextMenuPrimitive.SubContent\n className={cn(\n \"ui-dropdown-content ui-dropdown-sub-content ui-context-content ui-context-sub-content\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction ContextMenuContent({\n className,\n ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Content>) {\n return (\n <ContextMenuPrimitive.Portal>\n <ContextMenuPrimitive.Content\n className={cn(\"ui-dropdown-content ui-context-content\", className)}\n {...props}\n />\n </ContextMenuPrimitive.Portal>\n );\n}\n\nfunction ContextMenuItem({\n className,\n inset = false,\n variant = \"default\",\n ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: \"default\" | \"destructive\";\n}) {\n return (\n <ContextMenuPrimitive.Item\n data-inset={inset ? \"true\" : undefined}\n data-variant={variant}\n className={cn(\"ui-dropdown-item\", className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) {\n return (\n <ContextMenuPrimitive.CheckboxItem\n checked={checked}\n className={cn(\n \"ui-dropdown-item ui-dropdown-item--with-indicator\",\n className,\n )}\n {...props}\n >\n <span className=\"ui-dropdown-indicator\" aria-hidden>\n <ContextMenuPrimitive.ItemIndicator>\n <MenuCheckIcon className=\"ui-dropdown-indicator-icon\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction ContextMenuRadioItem({\n className,\n children,\n ...props\n}: ComponentProps<typeof ContextMenuPrimitive.RadioItem>) {\n return (\n <ContextMenuPrimitive.RadioItem\n className={cn(\n \"ui-dropdown-item ui-dropdown-item--with-indicator\",\n className,\n )}\n {...props}\n >\n <span className=\"ui-dropdown-indicator\" aria-hidden>\n <ContextMenuPrimitive.ItemIndicator>\n <MenuDotIcon className=\"ui-dropdown-indicator-icon\" />\n </ContextMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </ContextMenuPrimitive.RadioItem>\n );\n}\n\nfunction ContextMenuLabel({\n className,\n inset = false,\n ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Label> & {\n inset?: boolean;\n}) {\n return (\n <ContextMenuPrimitive.Label\n data-inset={inset ? \"true\" : undefined}\n className={cn(\"ui-dropdown-label\", className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuSeparator({\n className,\n ...props\n}: ComponentProps<typeof ContextMenuPrimitive.Separator>) {\n return (\n <ContextMenuPrimitive.Separator\n className={cn(\"ui-dropdown-separator\", className)}\n {...props}\n />\n );\n}\n\nfunction ContextMenuShortcut({ className, ...props }: ComponentProps<\"span\">) {\n return <span className={cn(\"ui-dropdown-shortcut\", className)} {...props} />;\n}\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n};\n","import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\n\nfunction MenuCheckIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden {...props}>\n <path\n d=\"M3.5 8.5 6.5 11.5 12.5 4.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nfunction MenuDotIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden {...props}>\n <circle cx=\"8\" cy=\"8\" r=\"3\" />\n </svg>\n );\n}\n\nfunction MenuChevronRightIcon(props: React.ComponentProps<\"svg\">) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden {...props}>\n <path\n d=\"M6 3.5 10.5 8 6 12.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nfunction DropdownMenu(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Root>,\n) {\n return <DropdownMenuPrimitive.Root {...props} />;\n}\n\nfunction DropdownMenuPortal(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>,\n) {\n return <DropdownMenuPrimitive.Portal {...props} />;\n}\n\nfunction DropdownMenuTrigger(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>,\n) {\n return <DropdownMenuPrimitive.Trigger {...props} />;\n}\n\nfunction DropdownMenuContent({\n className,\n sideOffset = 6,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n sideOffset={sideOffset}\n className={cn(\"ui-dropdown-content\", className)}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nfunction DropdownMenuGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Group>,\n) {\n return <DropdownMenuPrimitive.Group {...props} />;\n}\n\nfunction DropdownMenuItem({\n className,\n inset = false,\n variant = \"default\",\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n variant?: \"default\" | \"destructive\";\n}) {\n return (\n <DropdownMenuPrimitive.Item\n data-inset={inset ? \"true\" : undefined}\n data-variant={variant}\n className={cn(\"ui-dropdown-item\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {\n return (\n <DropdownMenuPrimitive.CheckboxItem\n checked={checked}\n className={cn(\n \"ui-dropdown-item ui-dropdown-item--with-indicator\",\n className,\n )}\n {...props}\n >\n <span className=\"ui-dropdown-indicator\" aria-hidden>\n <DropdownMenuPrimitive.ItemIndicator>\n <MenuCheckIcon className=\"ui-dropdown-indicator-icon\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n}\n\nfunction DropdownMenuRadioGroup(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>,\n) {\n return <DropdownMenuPrimitive.RadioGroup {...props} />;\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {\n return (\n <DropdownMenuPrimitive.RadioItem\n className={cn(\n \"ui-dropdown-item ui-dropdown-item--with-indicator\",\n className,\n )}\n {...props}\n >\n <span className=\"ui-dropdown-indicator\" aria-hidden>\n <DropdownMenuPrimitive.ItemIndicator>\n <MenuDotIcon className=\"ui-dropdown-indicator-icon\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n );\n}\n\nfunction DropdownMenuLabel({\n className,\n inset = false,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.Label\n data-inset={inset ? \"true\" : undefined}\n className={cn(\"ui-dropdown-label\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n className={cn(\"ui-dropdown-separator\", className)}\n {...props}\n />\n );\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return <span className={cn(\"ui-dropdown-shortcut\", className)} {...props} />;\n}\n\nfunction DropdownMenuSub(\n props: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>,\n) {\n return <DropdownMenuPrimitive.Sub {...props} />;\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset = false,\n children,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n}) {\n return (\n <DropdownMenuPrimitive.SubTrigger\n data-inset={inset ? \"true\" : undefined}\n className={cn(\"ui-dropdown-item ui-dropdown-sub-trigger\", className)}\n {...props}\n >\n {children}\n <MenuChevronRightIcon className=\"ui-dropdown-chevron\" />\n </DropdownMenuPrimitive.SubTrigger>\n );\n}\n\nfunction DropdownMenuSubContent({\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {\n return (\n <DropdownMenuPrimitive.SubContent\n className={cn(\"ui-dropdown-content ui-dropdown-sub-content\", className)}\n {...props}\n />\n );\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n};\n","export type UIMode = \"light\" | \"dark\";\n\nexport interface UIColorTokens {\n surface0: string;\n surfaceRaised: string;\n surfaceRaisedHover: string;\n surface1: string;\n surface2: string;\n borderSubtle: string;\n textPrimary: string;\n textSecondary: string;\n textMuted: string;\n primary500: string;\n primary600: string;\n primaryContrast: string;\n secondary500: string;\n secondary600: string;\n secondaryContrast: string;\n error500: string;\n error600: string;\n errorContrast: string;\n warning500: string;\n warning600: string;\n warningContrast: string;\n info500: string;\n info600: string;\n infoContrast: string;\n success500: string;\n success600: string;\n successContrast: string;\n}\n\nexport interface UIRadiusTokens {\n sm: string;\n md: string;\n lg: string;\n}\n\nexport interface UITheme {\n light?: Partial<UIColorTokens>;\n dark?: Partial<UIColorTokens>;\n radius?: Partial<UIRadiusTokens>;\n}\n\nexport interface UIResolvedTheme {\n light: UIColorTokens;\n dark: UIColorTokens;\n radius: UIRadiusTokens;\n}\n\nconst defaultLight: UIColorTokens = {\n surface0: \"oklch(0.985 0.004 260)\",\n surfaceRaised: \"oklch(0.996 0.002 260)\",\n surfaceRaisedHover: \"oklch(1 0 0)\",\n surface1: \"oklch(0.96 0.006 260)\",\n surface2: \"oklch(0.92 0.008 260)\",\n borderSubtle: \"oklch(0.84 0.01 260)\",\n textPrimary: \"oklch(0.18 0.01 260)\",\n textSecondary: \"oklch(0.33 0.01 260)\",\n textMuted: \"oklch(0.48 0.01 260)\",\n primary500: \"oklch(0.62 0.19 255)\",\n primary600: \"oklch(0.55 0.2 255)\",\n primaryContrast: \"oklch(0.98 0 0)\",\n secondary500: \"oklch(0.62 0.2 300)\",\n secondary600: \"oklch(0.55 0.21 300)\",\n secondaryContrast: \"oklch(0.98 0 0)\",\n error500: \"oklch(0.63 0.24 28)\",\n error600: \"oklch(0.57 0.24 28)\",\n errorContrast: \"oklch(0.98 0 0)\",\n warning500: \"oklch(0.78 0.17 78)\",\n warning600: \"oklch(0.72 0.17 78)\",\n warningContrast: \"oklch(0.2 0.01 260)\",\n info500: \"oklch(0.66 0.14 220)\",\n info600: \"oklch(0.59 0.15 220)\",\n infoContrast: \"oklch(0.98 0 0)\",\n success500: \"oklch(0.66 0.17 150)\",\n success600: \"oklch(0.59 0.18 150)\",\n successContrast: \"oklch(0.98 0 0)\",\n};\n\nconst defaultDark: UIColorTokens = {\n surface0: \"oklch(0.12 0.01 260)\",\n surfaceRaised: \"oklch(0.2 0.01 260)\",\n surfaceRaisedHover: \"oklch(0.24 0.01 260)\",\n surface1: \"oklch(0.16 0.01 260)\",\n surface2: \"oklch(0.21 0.01 260)\",\n borderSubtle: \"oklch(0.34 0.01 260)\",\n textPrimary: \"oklch(0.96 0.01 260)\",\n textSecondary: \"oklch(0.76 0.01 260)\",\n textMuted: \"oklch(0.62 0.01 260)\",\n primary500: \"oklch(0.67 0.19 255)\",\n primary600: \"oklch(0.6 0.2 255)\",\n primaryContrast: \"oklch(0.98 0 0)\",\n secondary500: \"oklch(0.67 0.2 300)\",\n secondary600: \"oklch(0.6 0.21 300)\",\n secondaryContrast: \"oklch(0.98 0 0)\",\n error500: \"oklch(0.67 0.22 28)\",\n error600: \"oklch(0.6 0.23 28)\",\n errorContrast: \"oklch(0.98 0 0)\",\n warning500: \"oklch(0.79 0.15 78)\",\n warning600: \"oklch(0.73 0.16 78)\",\n warningContrast: \"oklch(0.2 0.01 260)\",\n info500: \"oklch(0.69 0.13 220)\",\n info600: \"oklch(0.62 0.14 220)\",\n infoContrast: \"oklch(0.98 0 0)\",\n success500: \"oklch(0.69 0.16 150)\",\n success600: \"oklch(0.62 0.17 150)\",\n successContrast: \"oklch(0.98 0 0)\",\n};\n\nconst defaultRadius: UIRadiusTokens = {\n sm: \"4px\",\n md: \"8px\",\n lg: \"12px\",\n};\n\nexport const createTheme = (theme: UITheme = {}): UIResolvedTheme => ({\n light: { ...defaultLight, ...theme.light },\n dark: { ...defaultDark, ...theme.dark },\n radius: { ...defaultRadius, ...theme.radius },\n});\n\nexport function themeToCssVariables(\n theme: UIResolvedTheme,\n mode: UIMode,\n): Record<string, string> {\n const colors = mode === \"dark\" ? theme.dark : theme.light;\n\n return {\n \"--ui-color-surface-0\": colors.surface0,\n \"--ui-color-surface-raised\": colors.surfaceRaised,\n \"--ui-color-surface-raised-hover\": colors.surfaceRaisedHover,\n \"--ui-color-surface-1\": colors.surface1,\n \"--ui-color-surface-2\": colors.surface2,\n \"--ui-color-border-subtle\": colors.borderSubtle,\n \"--ui-color-text-primary\": colors.textPrimary,\n \"--ui-color-text-secondary\": colors.textSecondary,\n \"--ui-color-text-muted\": colors.textMuted,\n \"--ui-color-primary-500\": colors.primary500,\n \"--ui-color-primary-600\": colors.primary600,\n \"--ui-color-primary-contrast\": colors.primaryContrast,\n \"--ui-color-secondary-500\": colors.secondary500,\n \"--ui-color-secondary-600\": colors.secondary600,\n \"--ui-color-secondary-contrast\": colors.secondaryContrast,\n \"--ui-color-error-500\": colors.error500,\n \"--ui-color-error-600\": colors.error600,\n \"--ui-color-error-contrast\": colors.errorContrast,\n \"--ui-color-warning-500\": colors.warning500,\n \"--ui-color-warning-600\": colors.warning600,\n \"--ui-color-warning-contrast\": colors.warningContrast,\n \"--ui-color-info-500\": colors.info500,\n \"--ui-color-info-600\": colors.info600,\n \"--ui-color-info-contrast\": colors.infoContrast,\n \"--ui-color-success-500\": colors.success500,\n \"--ui-color-success-600\": colors.success600,\n \"--ui-color-success-contrast\": colors.successContrast,\n \"--ui-radius-sm\": theme.radius.sm,\n \"--ui-radius-md\": theme.radius.md,\n \"--ui-radius-lg\": theme.radius.lg,\n };\n}\n","import * as React from \"react\";\nimport { cn } from \"@/lib/cn\";\nimport {\n createTheme,\n type UIMode,\n type UITheme,\n themeToCssVariables,\n} from \"@/theme\";\n\nexport interface UIProviderProps {\n children: React.ReactNode;\n mode?: UIMode;\n theme?: UITheme;\n className?: string;\n}\n\nexport function UIProvider({\n children,\n mode = \"light\",\n theme,\n className,\n}: UIProviderProps): React.JSX.Element {\n const resolvedTheme = React.useMemo(() => createTheme(theme), [theme]);\n const variables = React.useMemo(\n () => themeToCssVariables(resolvedTheme, mode),\n [resolvedTheme, mode],\n );\n\n return (\n <div\n className={cn(mode === \"dark\" && \"dark\", className)}\n data-theme={mode}\n style={variables}\n >\n {children}\n </div>\n );\n}\n","const uiVars = {\n surface: {\n canvas: \"var(--ui-color-surface-0)\",\n panel: \"var(--ui-color-surface-1)\",\n raised: \"var(--ui-color-surface-raised)\",\n subtle: \"var(--ui-color-surface-2)\",\n },\n text: {\n primary: \"var(--ui-color-text-primary)\",\n secondary: \"var(--ui-color-text-secondary)\",\n muted: \"var(--ui-color-text-muted)\",\n },\n border: {\n subtle: \"var(--ui-color-border-subtle)\",\n },\n} as const;\n\nconst toneVars = {\n primary: {\n \"500\": \"var(--ui-color-primary-500)\",\n \"600\": \"var(--ui-color-primary-600)\",\n contrast: \"var(--ui-color-primary-contrast)\",\n },\n secondary: {\n \"500\": \"var(--ui-color-secondary-500)\",\n \"600\": \"var(--ui-color-secondary-600)\",\n contrast: \"var(--ui-color-secondary-contrast)\",\n },\n success: {\n \"500\": \"var(--ui-color-success-500)\",\n \"600\": \"var(--ui-color-success-600)\",\n contrast: \"var(--ui-color-success-contrast)\",\n },\n warning: {\n \"500\": \"var(--ui-color-warning-500)\",\n \"600\": \"var(--ui-color-warning-600)\",\n contrast: \"var(--ui-color-warning-contrast)\",\n },\n error: {\n \"500\": \"var(--ui-color-error-500)\",\n \"600\": \"var(--ui-color-error-600)\",\n contrast: \"var(--ui-color-error-contrast)\",\n },\n info: {\n \"500\": \"var(--ui-color-info-500)\",\n \"600\": \"var(--ui-color-info-600)\",\n contrast: \"var(--ui-color-info-contrast)\",\n },\n} as const;\n\ntype UIIntentTone = keyof typeof toneVars;\ntype UIIntentToneLevel = keyof (typeof toneVars)[UIIntentTone];\n\nfunction uiTone(tone: UIIntentTone, level: UIIntentToneLevel = \"500\"): string {\n return toneVars[tone][level];\n}\n\nfunction uiColorMix(\n base: string,\n mixWith: string,\n mixWithPercent: number,\n): string {\n return `color-mix(in oklab, ${base}, ${mixWith} ${mixWithPercent}%)`;\n}\n\nexport {\n uiColorMix,\n uiTone,\n uiVars,\n type UIIntentTone,\n type UIIntentToneLevel,\n};\n","export { Button, buttonVariants, type ButtonProps } from \"./components/button\";\nexport {\n Card,\n CardAction,\n CardContent,\n CardDescription,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"./components/card\";\nexport {\n Surface,\n surfaceVariants,\n type SurfaceProps,\n} from \"./components/surface\";\nexport { Stack, stackVariants, type StackProps } from \"./components/stack\";\nexport {\n Divider,\n dividerVariants,\n type DividerProps,\n} from \"./components/divider\";\nexport { IconButton, type IconButtonProps } from \"./components/icon-button\";\nexport { Input, inputVariants, type InputProps } from \"./components/input\";\nexport {\n Textarea,\n textareaVariants,\n type TextareaProps,\n} from \"./components/textarea\";\nexport { Label } from \"./components/label\";\nexport { Text, textVariants, type TextProps } from \"./components/text\";\nexport { Badge, badgeVariants, type BadgeProps } from \"./components/badge\";\nexport { Switch, type SwitchProps } from \"./components/switch\";\nexport {\n OptionSelect,\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectScrollDownButton,\n SelectScrollUpButton,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n type OptionSelectProps,\n} from \"./components/select\";\nexport {\n Fader,\n type FaderProps,\n type MarkProps,\n type TOrientation,\n} from \"./components/fader\";\nexport { Encoder, type EncoderProps } from \"./components/encoder\";\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogClose,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n type DialogContentProps,\n} from \"./components/dialog\";\nexport {\n ContextMenu,\n ContextMenuPortal,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuGroup,\n ContextMenuLabel,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioGroup,\n ContextMenuRadioItem,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuSub,\n ContextMenuSubTrigger,\n ContextMenuSubContent,\n} from \"./components/context-menu\";\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n} from \"./components/dropdown-menu\";\nexport { UIProvider, type UIProviderProps } from \"./UIProvider\";\nexport { cn } from \"./lib/cn\";\nexport {\n uiColorMix,\n uiTone,\n uiVars,\n type UIIntentTone,\n type UIIntentToneLevel,\n} from \"./semantic\";\nexport {\n createTheme,\n themeToCssVariables,\n type UIMode,\n type UIResolvedTheme,\n type UITheme,\n type UIColorTokens,\n type UIRadiusTokens,\n} from \"./theme\";\n\nexport const UI_MAX_TAILWIND_CLASSES = 12;\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import uiGovernancePlugin from "./ui-governance-plugin.js";
2
+
3
+ export function createUIGovernanceConfig(options = {}) {
4
+ const maxClasses = options.maxClasses ?? 12;
5
+ const severity = options.severity ?? "error";
6
+
7
+ return {
8
+ plugins: {
9
+ "ui-governance": uiGovernancePlugin,
10
+ },
11
+ rules: {
12
+ "ui-governance/max-tailwind-classes": [severity, { max: maxClasses }],
13
+ "ui-governance/no-raw-color-values": severity,
14
+ },
15
+ };
16
+ }
17
+
18
+ export { uiGovernancePlugin };
@@ -0,0 +1,252 @@
1
+ const CLASSNAME_HELPER_NAMES = new Set(["cn", "clsx", "twMerge"]);
2
+
3
+ const COLOR_LITERAL_PATTERN =
4
+ /#(?:[\da-fA-F]{3,4}|[\da-fA-F]{6}|[\da-fA-F]{8})\b|(?:rgb|rgba|hsl|hsla|oklch)\(/;
5
+ const TAILWIND_ARBITRARY_COLOR_CLASS_PATTERN =
6
+ /^(?:bg|text|border|outline|ring|fill|stroke|from|via|to)-\[[^\]]+\]$/;
7
+
8
+ const STYLE_COLOR_PROPERTY_PATTERN =
9
+ /color|background|border|outline|stroke|fill|shadow/i;
10
+
11
+ function splitClassTokens(value) {
12
+ if (typeof value !== "string") {
13
+ return [];
14
+ }
15
+ return value.trim().split(/\s+/).filter(Boolean);
16
+ }
17
+
18
+ function collectClassTokens(node) {
19
+ if (!node) {
20
+ return [];
21
+ }
22
+
23
+ switch (node.type) {
24
+ case "Literal":
25
+ return typeof node.value === "string" ? splitClassTokens(node.value) : [];
26
+ case "TemplateLiteral":
27
+ return node.quasis.flatMap((part) =>
28
+ splitClassTokens(part.value.cooked ?? ""),
29
+ );
30
+ case "BinaryExpression":
31
+ return [
32
+ ...collectClassTokens(node.left),
33
+ ...collectClassTokens(node.right),
34
+ ];
35
+ case "ConditionalExpression":
36
+ return [
37
+ ...collectClassTokens(node.consequent),
38
+ ...collectClassTokens(node.alternate),
39
+ ];
40
+ case "LogicalExpression":
41
+ return [
42
+ ...collectClassTokens(node.left),
43
+ ...collectClassTokens(node.right),
44
+ ];
45
+ case "ArrayExpression":
46
+ return node.elements.flatMap((element) => collectClassTokens(element));
47
+ case "ObjectExpression":
48
+ return node.properties.flatMap((property) => {
49
+ if (
50
+ property?.type !== "Property" ||
51
+ property.computed ||
52
+ property.key.type !== "Literal" ||
53
+ typeof property.key.value !== "string"
54
+ ) {
55
+ return [];
56
+ }
57
+ return splitClassTokens(property.key.value);
58
+ });
59
+ case "CallExpression":
60
+ if (
61
+ node.callee.type === "Identifier" &&
62
+ CLASSNAME_HELPER_NAMES.has(node.callee.name)
63
+ ) {
64
+ return node.arguments.flatMap((arg) => collectClassTokens(arg));
65
+ }
66
+ return [];
67
+ case "JSXExpressionContainer":
68
+ return collectClassTokens(node.expression);
69
+ default:
70
+ return [];
71
+ }
72
+ }
73
+
74
+ function readStylePropertyName(property) {
75
+ if (
76
+ property.type !== "Property" ||
77
+ property.computed ||
78
+ (property.key.type !== "Identifier" && property.key.type !== "Literal")
79
+ ) {
80
+ return null;
81
+ }
82
+
83
+ if (property.key.type === "Identifier") {
84
+ return property.key.name;
85
+ }
86
+
87
+ return typeof property.key.value === "string" ? property.key.value : null;
88
+ }
89
+
90
+ function hasRawColorLiteral(node) {
91
+ if (!node) {
92
+ return false;
93
+ }
94
+
95
+ switch (node.type) {
96
+ case "Literal":
97
+ return (
98
+ typeof node.value === "string" && COLOR_LITERAL_PATTERN.test(node.value)
99
+ );
100
+ case "TemplateLiteral":
101
+ return node.quasis.some((part) =>
102
+ COLOR_LITERAL_PATTERN.test(part.value.cooked ?? ""),
103
+ );
104
+ case "CallExpression":
105
+ return node.arguments.some((argument) => hasRawColorLiteral(argument));
106
+ case "ConditionalExpression":
107
+ return (
108
+ hasRawColorLiteral(node.consequent) ||
109
+ hasRawColorLiteral(node.alternate)
110
+ );
111
+ case "LogicalExpression":
112
+ return hasRawColorLiteral(node.left) || hasRawColorLiteral(node.right);
113
+ default:
114
+ return false;
115
+ }
116
+ }
117
+
118
+ const maxTailwindClassesRule = {
119
+ meta: {
120
+ type: "suggestion",
121
+ docs: {
122
+ description:
123
+ "Warn when className contains too many utility classes. Prefer reusable UI primitives.",
124
+ },
125
+ schema: [
126
+ {
127
+ type: "object",
128
+ properties: {
129
+ max: {
130
+ type: "integer",
131
+ minimum: 1,
132
+ },
133
+ },
134
+ additionalProperties: false,
135
+ },
136
+ ],
137
+ messages: {
138
+ tooManyClasses:
139
+ "className has {{count}} utility classes (max: {{max}}). Extract a reusable component or compose with shared class helpers.",
140
+ },
141
+ },
142
+ create(context) {
143
+ const configuredMax = context.options[0]?.max ?? 12;
144
+
145
+ return {
146
+ JSXAttribute(node) {
147
+ if (
148
+ node.name.type !== "JSXIdentifier" ||
149
+ node.name.name !== "className"
150
+ ) {
151
+ return;
152
+ }
153
+
154
+ if (!node.value) {
155
+ return;
156
+ }
157
+
158
+ const tokens = collectClassTokens(node.value);
159
+ if (tokens.length > configuredMax) {
160
+ context.report({
161
+ node,
162
+ messageId: "tooManyClasses",
163
+ data: {
164
+ count: String(tokens.length),
165
+ max: String(configuredMax),
166
+ },
167
+ });
168
+ }
169
+ },
170
+ };
171
+ },
172
+ };
173
+
174
+ const noRawColorValuesRule = {
175
+ meta: {
176
+ type: "suggestion",
177
+ docs: {
178
+ description:
179
+ "Warn on raw color usage in JSX className/style. Prefer semantic palette tokens.",
180
+ },
181
+ schema: [],
182
+ messages: {
183
+ arbitraryColorClass:
184
+ "Avoid arbitrary Tailwind color class '{{className}}'. Use semantic palette tokens/components instead.",
185
+ rawInlineColor:
186
+ "Avoid raw inline color values in style prop. Use palette tokens/CSS variables.",
187
+ },
188
+ },
189
+ create(context) {
190
+ return {
191
+ JSXAttribute(node) {
192
+ if (node.name.type !== "JSXIdentifier" || !node.value) {
193
+ return;
194
+ }
195
+
196
+ if (node.name.name === "className") {
197
+ const tokens = collectClassTokens(node.value);
198
+ const arbitraryColorToken = tokens.find((token) =>
199
+ TAILWIND_ARBITRARY_COLOR_CLASS_PATTERN.test(token),
200
+ );
201
+
202
+ if (arbitraryColorToken) {
203
+ context.report({
204
+ node,
205
+ messageId: "arbitraryColorClass",
206
+ data: {
207
+ className: arbitraryColorToken,
208
+ },
209
+ });
210
+ }
211
+ }
212
+
213
+ if (
214
+ node.name.name === "style" &&
215
+ node.value.type === "JSXExpressionContainer" &&
216
+ node.value.expression.type === "ObjectExpression"
217
+ ) {
218
+ const colorProperty = node.value.expression.properties.find(
219
+ (property) => {
220
+ if (property.type !== "Property") {
221
+ return false;
222
+ }
223
+
224
+ const key = readStylePropertyName(property);
225
+ if (!key || !STYLE_COLOR_PROPERTY_PATTERN.test(key)) {
226
+ return false;
227
+ }
228
+
229
+ return hasRawColorLiteral(property.value);
230
+ },
231
+ );
232
+
233
+ if (colorProperty) {
234
+ context.report({
235
+ node: colorProperty,
236
+ messageId: "rawInlineColor",
237
+ });
238
+ }
239
+ }
240
+ },
241
+ };
242
+ },
243
+ };
244
+
245
+ const uiGovernancePlugin = {
246
+ rules: {
247
+ "max-tailwind-classes": maxTailwindClassesRule,
248
+ "no-raw-color-values": noRawColorValuesRule,
249
+ },
250
+ };
251
+
252
+ export default uiGovernancePlugin;
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@blibliki/ui",
3
+ "version": "0.9.2",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "import": "./dist/index.js"
9
+ },
10
+ "./styles.css": "./styles.css",
11
+ "./tokens.css": "./tokens.css",
12
+ "./eslint": "./eslint/index.js",
13
+ "./eslint/ui-governance-plugin": "./eslint/ui-governance-plugin.js",
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "README.md",
18
+ "src",
19
+ "dist",
20
+ "eslint",
21
+ "scripts",
22
+ "styles.css",
23
+ "tokens.css"
24
+ ],
25
+ "dependencies": {
26
+ "@radix-ui/react-context-menu": "2.3.1",
27
+ "@radix-ui/react-dialog": "1.1.17",
28
+ "@radix-ui/react-dropdown-menu": "2.1.18",
29
+ "@radix-ui/react-label": "2.1.10",
30
+ "@radix-ui/react-select": "2.3.1",
31
+ "@radix-ui/react-slot": "1.3.0",
32
+ "class-variance-authority": "^0.7.1",
33
+ "clsx": "^2.1.1",
34
+ "tailwind-merge": "3.6.0",
35
+ "@blibliki/utils": "^0.9.2"
36
+ },
37
+ "peerDependencies": {
38
+ "react": ">=19",
39
+ "react-dom": ">=19"
40
+ },
41
+ "devDependencies": {
42
+ "@types/react": "19.2.17",
43
+ "@types/react-dom": "19.2.3",
44
+ "react": "19.2.7",
45
+ "react-dom": "19.2.7"
46
+ },
47
+ "scripts": {
48
+ "build": "tsdown",
49
+ "clean:dist": "rm -rf ./dist",
50
+ "dev": "tsdown --watch --no-clean",
51
+ "lint:palette": "node scripts/check-css-palette.mjs",
52
+ "lint": "pnpm run lint:palette && eslint src",
53
+ "tsc": "tsc --noEmit",
54
+ "format": "prettier . --write",
55
+ "format:check": "prettier . --check",
56
+ "bump": "npm version patch",
57
+ "release": "pnpm run build && pnpm publish --access public"
58
+ }
59
+ }