@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/README.md +91 -0
- package/dist/index.d.ts +542 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/eslint/index.js +18 -0
- package/eslint/ui-governance-plugin.js +252 -0
- package/package.json +59 -0
- package/scripts/check-css-palette.mjs +92 -0
- package/src/UIProvider.tsx +38 -0
- package/src/components/badge.tsx +57 -0
- package/src/components/button.tsx +65 -0
- package/src/components/card.tsx +44 -0
- package/src/components/context-menu.tsx +239 -0
- package/src/components/dialog.tsx +127 -0
- package/src/components/divider.tsx +45 -0
- package/src/components/dropdown-menu.tsx +243 -0
- package/src/components/encoder.tsx +323 -0
- package/src/components/fader.tsx +230 -0
- package/src/components/icon-button.tsx +51 -0
- package/src/components/input.tsx +38 -0
- package/src/components/label.tsx +14 -0
- package/src/components/select.tsx +342 -0
- package/src/components/stack.tsx +90 -0
- package/src/components/surface.tsx +88 -0
- package/src/components/switch.tsx +72 -0
- package/src/components/text.tsx +59 -0
- package/src/components/textarea.tsx +43 -0
- package/src/index.ts +120 -0
- package/src/lib/cn.ts +6 -0
- package/src/semantic.ts +72 -0
- package/src/theme.ts +161 -0
- package/styles.css +2041 -0
- package/tokens.css +90 -0
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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"}
|
package/eslint/index.js
ADDED
|
@@ -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
|
+
}
|