@viax.io/uxm 4.37.0 → 4.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [4.38.0](https://gitlab.viax.tech/services-viax/uxm/compare/v4.37.1...v4.38.0) (2026-09-08)
2
+
3
+
4
+ ### Features
5
+
6
+ * **tokens:** gate tokens.css against themeTokens; deprecate the Tailwind-only palette aliases ([9e90585](https://gitlab.viax.tech/services-viax/uxm/commit/9e9058535a447e384a2cb8558ff5b97371f8e57c))
7
+
8
+ ## [4.37.1](https://gitlab.viax.tech/services-viax/uxm/compare/v4.37.0...v4.37.1) (2026-09-08)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **ui:** theme-aware toast close hover and date-input popover shadow ([d860886](https://gitlab.viax.tech/services-viax/uxm/commit/d8608863351c27408eb02617ae80bd54da3f7cdf))
14
+
1
15
  # [4.37.0](https://gitlab.viax.tech/services-viax/uxm/compare/v4.36.0...v4.37.0) (2026-09-07)
2
16
 
3
17
 
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.3.1 | MIT License | https://tailwindcss.com */
2
- @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:var(--font-inter);--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-xs:.125rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--shadow-xs:0 1px 2px 0 #0000000d;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--shadow-md:0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;--shadow-lg:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--shadow-xl:0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a;--shadow-2xl:0 25px 50px -12px #00000040;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-inter);--default-mono-font-family:var(--font-mono);--color-surface:var(--color-surface);--color-surface-alt:var(--color-surface-alt);--color-card:var(--color-card);--color-text:var(--color-text);--color-text-strong:var(--color-text-strong);--color-text-muted:var(--color-text-muted);--color-text-subtle:var(--color-text-subtle);--color-text-inverse:var(--color-text-inverse);--color-border:var(--color-border);--color-accent-subtle:var(--color-accent-subtle);--color-accent-light:var(--color-accent-light);--color-accent:var(--color-accent);--color-accent-bold:var(--color-accent-bold);--color-highlight-warm:var(--color-highlight-warm);--color-highlight-cool:var(--color-highlight-cool);--color-on-highlight-warm:var(--color-on-highlight-warm);--color-on-highlight-cool:var(--color-on-highlight-cool);--color-category-composite:var(--color-category-composite);--color-category-diagram:var(--color-category-diagram);--color-danger-text:var(--color-danger-text);--color-success-bg:var(--color-success-bg);--color-success-text:var(--color-success-text);--color-success-border:var(--color-success-border);--color-info-bg:var(--color-info-bg);--color-info-text:var(--color-info-text);--color-info-border:var(--color-info-border);--color-warning-bg:var(--color-warning-bg);--color-warning-text:var(--color-warning-text);--color-warning-border:var(--color-warning-border);--color-danger-bg:var(--color-danger-bg);--color-danger-border:var(--color-danger-border)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.\@container{container-type:inline-size}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.z-10{z-index:10}.z-20{z-index:20}.z-\[9999\]{z-index:9999}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-mx-5{margin-inline:calc(var(--spacing) * -5)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.-ml-3{margin-left:calc(var(--spacing) * -3)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.list-item{display:list-item}.table{display:table}.table-column{display:table-column}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-8{height:calc(var(--spacing) * 8)}.h-full{height:100%}.max-h-\[280px\]{max-height:280px}.min-h-0{min-height:0}.min-h-\[120px\]{min-height:120px}.min-h-full{min-height:100%}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-8{width:calc(var(--spacing) * 8)}.w-44{width:calc(var(--spacing) * 44)}.w-\[58px\]{width:58px}.w-\[220px\]{width:220px}.w-auto{width:auto}.w-full{width:100%}.min-w-0{min-width:0}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-col-resize{cursor:col-resize}.cursor-pointer{cursor:pointer}.cursor-row-resize{cursor:row-resize}.resize{resize:both}.\[grid-template-columns\:repeat\(auto-fit\,minmax\(220px\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-6{column-gap:calc(var(--spacing) * 6)}.gap-y-4{row-gap:calc(var(--spacing) * 4)}.self-center{align-self:center}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-l-\[4px\]{border-top-left-radius:4px;border-bottom-left-radius:4px}.rounded-r-\[4px\]{border-top-right-radius:4px;border-bottom-right-radius:4px}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent-bold\/30{border-color:var(--color-accent-bold)}@supports (color:color-mix(in lab, red, red)){.border-accent-bold\/30{border-color:color-mix(in oklab, var(--color-accent-bold) 30%, transparent)}}.border-border,.border-border\/60{border-color:var(--color-border)}@supports (color:color-mix(in lab, red, red)){.border-border\/60{border-color:color-mix(in oklab, var(--color-border) 60%, transparent)}}.border-text\/20{border-color:var(--color-text)}@supports (color:color-mix(in lab, red, red)){.border-text\/20{border-color:color-mix(in oklab, var(--color-text) 20%, transparent)}}.bg-accent-subtle,.bg-accent-subtle\/40{background-color:var(--color-accent-subtle)}@supports (color:color-mix(in lab, red, red)){.bg-accent-subtle\/40{background-color:color-mix(in oklab, var(--color-accent-subtle) 40%, transparent)}}.bg-accent-subtle\/50{background-color:var(--color-accent-subtle)}@supports (color:color-mix(in lab, red, red)){.bg-accent-subtle\/50{background-color:color-mix(in oklab, var(--color-accent-subtle) 50%, transparent)}}.bg-card{background-color:var(--color-card)}.bg-surface{background-color:var(--color-surface)}.bg-surface-alt{background-color:var(--color-surface-alt)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.object-contain{object-fit:contain}.p-3{padding:calc(var(--spacing) * 3)}.p-6{padding:calc(var(--spacing) * 6)}.p-12{padding:calc(var(--spacing) * 12)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-1{padding-right:var(--spacing)}.pr-5{padding-right:calc(var(--spacing) * 5)}.pb-1{padding-bottom:var(--spacing)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-\[66px\]{padding-left:66px}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[38px\]{font-size:38px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[-0\.06em\]{--tw-tracking:-.06em;letter-spacing:-.06em}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-accent-bold{color:var(--color-accent-bold)}.text-text{color:var(--color-text)}.text-text-muted{color:var(--color-text-muted)}.text-text-strong{color:var(--color-text-strong)}.text-text-subtle{color:var(--color-text-subtle)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow{--tw-drop-shadow-size:drop-shadow(0 1px 2px var(--tw-drop-shadow-color,#0000001a)) drop-shadow(0 1px 1px var(--tw-drop-shadow-color,#0000000f));--tw-drop-shadow:drop-shadow(0 1px 2px #0000001a) drop-shadow(0 1px 1px #0000000f);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.invert{--tw-invert:invert(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.\[file\:line\]{file:line}@media (hover:hover){.group-hover\:bg-accent\/30:is(:where(.group):hover *){background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.group-hover\:bg-accent\/30:is(:where(.group):hover *){background-color:color-mix(in oklab, var(--color-accent) 30%, transparent)}}}.group-active\:bg-accent\/50:is(:where(.group):active *){background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.group-active\:bg-accent\/50:is(:where(.group):active *){background-color:color-mix(in oklab, var(--color-accent) 50%, transparent)}}@media (hover:hover){.hover\:border-accent\/40:hover{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.hover\:border-accent\/40:hover{border-color:color-mix(in oklab, var(--color-accent) 40%, transparent)}}.hover\:bg-surface-alt:hover{background-color:var(--color-surface-alt)}.hover\:text-text-strong:hover{color:var(--color-text-strong)}}.focus\:border-accent:focus{border-color:var(--color-accent)}@container (min-width:480px){.\@\[480px\]\:inline{display:inline}}@container (min-width:640px){.\@\[640px\]\:block{display:block}}}:root{--color-surface:#f8f7f6;--color-surface-alt:#f2f1f0;--color-card:#fff;--color-text:#1e1e1e;--color-text-strong:#4a4a4a;--color-text-muted:#9ca3af;--color-text-subtle:#cbd5e1;--color-text-inverse:#fff;--color-border:#ebebea;--color-accent-subtle:#e6ffd1;--color-accent-light:#90e9b8;--color-accent:#3ecc87;--color-accent-bold:#1e7150;--color-drop-target:var(--color-accent);--color-highlight-warm:#fcd0a1;--color-highlight-cool:#c3bef7;--color-on-highlight-warm:#7c6b3e;--color-on-highlight-cool:#5b54a0;--color-category-composite:#f472b6;--color-category-diagram:#6366f1;--color-success-bg:#f0fdf4;--color-success-text:#166534;--color-success-border:#bbf7d0;--color-info-bg:#eff6ff;--color-info-text:#1e40af;--color-info-border:#bfdbfe;--color-warning-bg:#fffbeb;--color-warning-text:#92400e;--color-warning-border:#fde68a;--color-danger-bg:#fef2f2;--color-danger-text:#991b1b;--color-danger-border:#fecaca;--color-canvas-dot:#e0e0e0;--color-preview-bg-light:#fff;--color-preview-bg-dark:#232220;--color-preview-border-light:#ebebea;--color-preview-border-dark:#444240;--shadow-xs:0 1px 2px #0000000f;--shadow-sm:0 1px 3px #0000001a;--shadow-md:0 4px 12px #0000000f, 0 1px 3px #0000000a;--shadow-lg:0 6px 20px #0000001a;--shadow-xl:0 8px 24px #0000001f;--shadow-2xl:0 24px 48px #0000002e;--shadow-card:0 1px 2px #0000000a, 0 4px 12px #0000000a;--shadow-modal:var(--shadow-2xl);--font-inter:"Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif}[data-theme=dark]{--color-surface:#232220;--color-surface-alt:#2a2927;--color-card:#1b1a18;--color-text:#f5f5f5;--color-text-strong:#c8c8c8;--color-text-muted:#a3a3a3;--color-text-subtle:#6e6e6e;--color-text-inverse:#1b1a18;--color-border:#444240;--color-accent-subtle:#1a4a2c;--color-accent-light:#3aa36a;--color-accent:#4fd99a;--color-accent-bold:#8ae6b4;--color-highlight-warm:#8a5a2b;--color-highlight-cool:#4d4a7f;--color-on-highlight-warm:#fcd0a1;--color-on-highlight-cool:#c3bef7;--color-category-composite:#f9a8d4;--color-category-diagram:#818cf8;--color-success-bg:#1a3924;--color-success-text:#86efac;--color-success-border:#2f6040;--color-info-bg:#1a2e4c;--color-info-text:#93c5fd;--color-info-border:#31507f;--color-warning-bg:#3a2d1b;--color-warning-text:#fcd34d;--color-warning-border:#5e4d30;--color-danger-bg:#3a2022;--color-danger-text:#fca5a5;--color-danger-border:#5e3034;--color-canvas-dot:#383634;--shadow-xs:0 1px 2px #0000004d;--shadow-sm:0 1px 3px #0006;--shadow-md:0 4px 12px #00000059, 0 1px 3px #00000040;--shadow-lg:0 6px 20px #00000073;--shadow-xl:0 8px 24px #00000080;--shadow-2xl:0 24px 48px #0000008c;--shadow-card:0 1px 2px #0000004d, 0 4px 12px #00000040}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:var(--font-inter);--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--leading-relaxed:1.625;--radius-xs:.125rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--shadow-xs:0 1px 2px 0 #0000000d;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--shadow-md:0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;--shadow-lg:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--shadow-xl:0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a;--shadow-2xl:0 25px 50px -12px #00000040;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-inter);--default-mono-font-family:var(--font-mono);--color-surface:var(--color-surface);--color-surface-alt:var(--color-surface-alt);--color-card:var(--color-card);--color-text:var(--color-text);--color-text-strong:var(--color-text-strong);--color-text-muted:var(--color-text-muted);--color-text-subtle:var(--color-text-subtle);--color-text-inverse:var(--color-text-inverse);--color-border:var(--color-border);--color-accent-subtle:var(--color-accent-subtle);--color-accent-light:var(--color-accent-light);--color-accent:var(--color-accent);--color-accent-bold:var(--color-accent-bold);--color-highlight-warm:var(--color-highlight-warm);--color-highlight-cool:var(--color-highlight-cool);--color-on-highlight-warm:var(--color-on-highlight-warm);--color-on-highlight-cool:var(--color-on-highlight-cool);--color-category-composite:var(--color-category-composite);--color-category-diagram:var(--color-category-diagram);--color-danger-text:var(--color-danger-text);--color-success-bg:var(--color-success-bg);--color-success-text:var(--color-success-text);--color-success-border:var(--color-success-border);--color-info-bg:var(--color-info-bg);--color-info-text:var(--color-info-text);--color-info-border:var(--color-info-border);--color-warning-bg:var(--color-warning-bg);--color-warning-text:var(--color-warning-text);--color-warning-border:var(--color-warning-border);--color-danger-bg:var(--color-danger-bg);--color-danger-border:var(--color-danger-border);--color-cream:var(--color-surface);--color-warm-gray:var(--color-surface-alt);--color-ink:var(--color-text);--color-green:var(--color-accent);--color-mint:var(--color-accent-light);--color-forest:var(--color-accent-bold);--color-peach:var(--color-highlight-warm);--color-lavender:var(--color-highlight-cool);--color-lime:var(--color-accent-subtle)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.\@container{container-type:inline-size}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.top-0{top:0}.right-0{right:0}.bottom-0{bottom:0}.left-0{left:0}.z-10{z-index:10}.z-20{z-index:20}.z-\[9999\]{z-index:9999}.col-span-2{grid-column:span 2/span 2}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.-mx-5{margin-inline:calc(var(--spacing) * -5)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.-ml-3{margin-left:calc(var(--spacing) * -3)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.inline-grid{display:inline-grid}.list-item{display:list-item}.table{display:table}.table-column{display:table-column}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-8{height:calc(var(--spacing) * 8)}.h-full{height:100%}.max-h-\[280px\]{max-height:280px}.min-h-0{min-height:0}.min-h-\[120px\]{min-height:120px}.min-h-full{min-height:100%}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-8{width:calc(var(--spacing) * 8)}.w-44{width:calc(var(--spacing) * 44)}.w-\[58px\]{width:58px}.w-\[220px\]{width:220px}.w-auto{width:auto}.w-full{width:100%}.min-w-0{min-width:0}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-col-resize{cursor:col-resize}.cursor-pointer{cursor:pointer}.cursor-row-resize{cursor:row-resize}.resize{resize:both}.\[grid-template-columns\:repeat\(auto-fit\,minmax\(220px\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-6{column-gap:calc(var(--spacing) * 6)}.gap-y-4{row-gap:calc(var(--spacing) * 4)}.self-center{align-self:center}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-l-\[4px\]{border-top-left-radius:4px;border-bottom-left-radius:4px}.rounded-r-\[4px\]{border-top-right-radius:4px;border-bottom-right-radius:4px}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-0{border-left-style:var(--tw-border-style);border-left-width:0}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent-bold\/30{border-color:var(--color-accent-bold)}@supports (color:color-mix(in lab, red, red)){.border-accent-bold\/30{border-color:color-mix(in oklab, var(--color-accent-bold) 30%, transparent)}}.border-border,.border-border\/60{border-color:var(--color-border)}@supports (color:color-mix(in lab, red, red)){.border-border\/60{border-color:color-mix(in oklab, var(--color-border) 60%, transparent)}}.border-text\/20{border-color:var(--color-text)}@supports (color:color-mix(in lab, red, red)){.border-text\/20{border-color:color-mix(in oklab, var(--color-text) 20%, transparent)}}.bg-accent-subtle,.bg-accent-subtle\/40{background-color:var(--color-accent-subtle)}@supports (color:color-mix(in lab, red, red)){.bg-accent-subtle\/40{background-color:color-mix(in oklab, var(--color-accent-subtle) 40%, transparent)}}.bg-accent-subtle\/50{background-color:var(--color-accent-subtle)}@supports (color:color-mix(in lab, red, red)){.bg-accent-subtle\/50{background-color:color-mix(in oklab, var(--color-accent-subtle) 50%, transparent)}}.bg-card{background-color:var(--color-card)}.bg-cream,.bg-surface{background-color:var(--color-surface)}.bg-surface-alt{background-color:var(--color-surface-alt)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.object-contain{object-fit:contain}.p-3{padding:calc(var(--spacing) * 3)}.p-6{padding:calc(var(--spacing) * 6)}.p-12{padding:calc(var(--spacing) * 12)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-1{padding-right:var(--spacing)}.pr-5{padding-right:calc(var(--spacing) * 5)}.pb-1{padding-bottom:var(--spacing)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-\[66px\]{padding-left:66px}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-\[38px\]{font-size:38px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[-0\.06em\]{--tw-tracking:-.06em;letter-spacing:-.06em}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-accent-bold{color:var(--color-accent-bold)}.text-ink,.text-text{color:var(--color-text)}.text-text-muted{color:var(--color-text-muted)}.text-text-strong{color:var(--color-text-strong)}.text-text-subtle{color:var(--color-text-subtle)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow{--tw-drop-shadow-size:drop-shadow(0 1px 2px var(--tw-drop-shadow-color,#0000001a)) drop-shadow(0 1px 1px var(--tw-drop-shadow-color,#0000000f));--tw-drop-shadow:drop-shadow(0 1px 2px #0000001a) drop-shadow(0 1px 1px #0000000f);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.invert{--tw-invert:invert(100%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-all{-webkit-user-select:all;user-select:all}.\[file\:line\]{file:line}@media (hover:hover){.group-hover\:bg-accent\/30:is(:where(.group):hover *){background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.group-hover\:bg-accent\/30:is(:where(.group):hover *){background-color:color-mix(in oklab, var(--color-accent) 30%, transparent)}}}.group-active\:bg-accent\/50:is(:where(.group):active *){background-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.group-active\:bg-accent\/50:is(:where(.group):active *){background-color:color-mix(in oklab, var(--color-accent) 50%, transparent)}}@media (hover:hover){.hover\:border-accent\/40:hover{border-color:var(--color-accent)}@supports (color:color-mix(in lab, red, red)){.hover\:border-accent\/40:hover{border-color:color-mix(in oklab, var(--color-accent) 40%, transparent)}}.hover\:bg-surface-alt:hover{background-color:var(--color-surface-alt)}.hover\:text-text-strong:hover{color:var(--color-text-strong)}}.focus\:border-accent:focus{border-color:var(--color-accent)}@container (min-width:480px){.\@\[480px\]\:inline{display:inline}}@container (min-width:640px){.\@\[640px\]\:block{display:block}}}:root{--color-surface:#f8f7f6;--color-surface-alt:#f2f1f0;--color-card:#fff;--color-text:#1e1e1e;--color-text-strong:#4a4a4a;--color-text-muted:#9ca3af;--color-text-subtle:#cbd5e1;--color-text-inverse:#fff;--color-border:#ebebea;--color-accent-subtle:#e6ffd1;--color-accent-light:#90e9b8;--color-accent:#3ecc87;--color-accent-bold:#1e7150;--color-drop-target:var(--color-accent);--color-highlight-warm:#fcd0a1;--color-highlight-cool:#c3bef7;--color-on-highlight-warm:#7c6b3e;--color-on-highlight-cool:#5b54a0;--color-category-composite:#f472b6;--color-category-diagram:#6366f1;--color-success-bg:#f0fdf4;--color-success-text:#166534;--color-success-border:#bbf7d0;--color-info-bg:#eff6ff;--color-info-text:#1e40af;--color-info-border:#bfdbfe;--color-warning-bg:#fffbeb;--color-warning-text:#92400e;--color-warning-border:#fde68a;--color-danger-bg:#fef2f2;--color-danger-text:#991b1b;--color-danger-border:#fecaca;--color-canvas-dot:#e0e0e0;--color-preview-bg-light:#fff;--color-preview-bg-dark:#232220;--color-preview-border-light:#ebebea;--color-preview-border-dark:#444240;--shadow-xs:0 1px 2px #0000000f;--shadow-sm:0 1px 3px #0000001a;--shadow-md:0 4px 12px #0000000f, 0 1px 3px #0000000a;--shadow-lg:0 6px 20px #0000001a;--shadow-xl:0 8px 24px #0000001f;--shadow-2xl:0 24px 48px #0000002e;--shadow-card:0 1px 2px #0000000a, 0 4px 12px #0000000a;--shadow-modal:var(--shadow-2xl);--font-inter:"Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif}[data-theme=dark]{--color-surface:#232220;--color-surface-alt:#2a2927;--color-card:#1b1a18;--color-text:#f5f5f5;--color-text-strong:#c8c8c8;--color-text-muted:#a3a3a3;--color-text-subtle:#6e6e6e;--color-text-inverse:#1b1a18;--color-border:#444240;--color-accent-subtle:#1a4a2c;--color-accent-light:#3aa36a;--color-accent:#4fd99a;--color-accent-bold:#8ae6b4;--color-highlight-warm:#8a5a2b;--color-highlight-cool:#4d4a7f;--color-on-highlight-warm:#fcd0a1;--color-on-highlight-cool:#c3bef7;--color-category-composite:#f9a8d4;--color-category-diagram:#818cf8;--color-success-bg:#1a3924;--color-success-text:#86efac;--color-success-border:#2f6040;--color-info-bg:#1a2e4c;--color-info-text:#93c5fd;--color-info-border:#31507f;--color-warning-bg:#3a2d1b;--color-warning-text:#fcd34d;--color-warning-border:#5e4d30;--color-danger-bg:#3a2022;--color-danger-text:#fca5a5;--color-danger-border:#5e3034;--color-canvas-dot:#383634;--shadow-xs:0 1px 2px #0000004d;--shadow-sm:0 1px 3px #0006;--shadow-md:0 4px 12px #00000059, 0 1px 3px #00000040;--shadow-lg:0 6px 20px #00000073;--shadow-xl:0 8px 24px #00000080;--shadow-2xl:0 24px 48px #0000008c;--shadow-card:0 1px 2px #0000004d, 0 4px 12px #00000040}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
@@ -216,7 +216,12 @@
216
216
  --color-danger-border: var(--color-danger-border);
217
217
  --font-sans: var(--font-inter);
218
218
 
219
- /* semantic aliases used by component classes */
219
+ /* @deprecated legacy palette names, scheduled for removal in the next major.
220
+ They exist ONLY here, inside the Tailwind `@theme inline` block: browsers
221
+ drop unknown at-rules, so a plain-CSS host never had them, and no atom or
222
+ studio utility reads them (audit 07-09-2026). Use the token each one
223
+ points at. `scripts/check-token-parity.mjs` lists them as
224
+ DEPRECATED_ALIASES — remove this block and that list together. */
220
225
  --color-cream: var(--color-surface);
221
226
  --color-warm-gray: var(--color-surface-alt);
222
227
  --color-ink: var(--color-text);
@@ -16,6 +16,9 @@
16
16
  border-radius: var(--uxm-bulk-action-bar-border-radius, 12px);
17
17
  padding: var(--uxm-bulk-action-bar-padding-y, 8px) var(--uxm-bulk-action-bar-padding-x, 12px);
18
18
  font-size: calc(var(--uxm-bulk-action-bar-font-size, 14px) * var(--type-scale, 1));
19
+ /* Composed from the Color / Blur / Offset Y knobs (same pattern as Card,
20
+ Calendar, Menu, Listbox). The colour fallback is a literal because the
21
+ knob is a COLOUR and the `--shadow-*` tokens are whole box-shadows. */
19
22
  box-shadow: 0 var(--uxm-bulk-action-bar-shadow-offset-y, 10px) var(--uxm-bulk-action-bar-shadow-blur, 28px) var(--uxm-bulk-action-bar-shadow-color, rgba(0, 0, 0, 0.16));
20
23
  }
21
24
 
@@ -3,7 +3,8 @@
3
3
  /* Soft elevation so the calendar reads as a floating surface in its popover
4
4
  usages (DateInput / TimeInput / EditableCell date). On by default via the
5
5
  `shadow` prop; the shadow itself is tunable through the
6
- `--uxm-calendar-shadow-*` vars. */
6
+ `--uxm-calendar-shadow-*` vars. The colour fallback is a literal because
7
+ the knob is a COLOUR and the `--shadow-*` tokens are whole box-shadows. */
7
8
  .uxm-calendar--shadow {
8
9
  box-shadow: 0 var(--uxm-calendar-shadow-offset-y, 6px) var(--uxm-calendar-shadow-blur, 20px) var(--uxm-calendar-shadow-color, rgba(0, 0, 0, 0.12));
9
10
  }
@@ -43,7 +43,7 @@
43
43
  /* Calendar inside owns its own bg / border / radius / padding, so the
44
44
  popover wrapper just needs positioning + a drop shadow. Using a filter
45
45
  drop-shadow follows the Calendar's rounded outline cleanly. */
46
- filter: drop-shadow(0 10px 28px rgba(0, 0, 0, 0.18));
46
+ filter: drop-shadow(var(--uxm-date-input-popover-shadow, var(--shadow-xl)));
47
47
  left: 0;
48
48
  position: absolute;
49
49
  top: calc(100% + 4px);
@@ -364,8 +364,10 @@ function SelectSingle({
364
364
  {
365
365
  glyph: "chevron-down",
366
366
  size: 14,
367
- className: "uxm-select-dropdown__trigger-chevron",
368
- style: { transform: open ? "rotate(180deg)" : "none" }
367
+ className: (0, import_helpers.cn)(
368
+ "uxm-select-dropdown__trigger-chevron",
369
+ open && "uxm-select-dropdown__trigger-chevron--open"
370
+ )
369
371
  }
370
372
  )
371
373
  ]
@@ -490,8 +492,10 @@ function SelectMulti({
490
492
  {
491
493
  glyph: "chevron-down",
492
494
  size: 14,
493
- className: "uxm-select-dropdown__trigger-chevron",
494
- style: { transform: open ? "rotate(180deg)" : "none" }
495
+ className: (0, import_helpers.cn)(
496
+ "uxm-select-dropdown__trigger-chevron",
497
+ open && "uxm-select-dropdown__trigger-chevron--open"
498
+ )
495
499
  }
496
500
  )
497
501
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/input/input.tsx"],"sourcesContent":["import {\n Children,\n isValidElement,\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n type SelectHTMLAttributes,\n type TextareaHTMLAttributes,\n} from 'react';\n\nimport { cn, mergeDescribedBy, mergeRefs } from '@/helpers';\n\nimport { ButtonGhost } from '../button';\nimport { FieldError } from '../field-error';\nimport { Icon } from '../icon';\nimport { IconButton } from '../icon-button';\nimport { DEFAULT_MULTI_REQUIRED_MESSAGE, Listbox, MultiListbox } from '../listbox';\n\nimport { clearFieldValue } from './clear-field-value';\n\nexport interface TextInputProps extends InputHTMLAttributes<HTMLInputElement> {\n /**\n * When set to a non-empty string, the field renders in its error state:\n * red border (`.uxm-input-text--error`), `aria-invalid`, and the message\n * rendered below the input. Omit (or pass an empty string) for the normal\n * state. The atom owns the message so it works standalone — search bars,\n * inline edits, custom layouts — without requiring a `FormField` wrapper.\n */\n error?: string;\n /**\n * Show a clear (✕) button at the trailing edge when the input has content.\n * **Defaults to `true`** — a free-text field is always safe to clear (you\n * can type/delete anyway), so the affordance is on by default; pass\n * `clearable={false}` to opt out. The ✕ self-clears (resets the field and\n * fires `onChange` with \"\"), so no `onClear` is needed — any controlled\n * `value` + `onChange` usage gets it for free.\n */\n clearable?: boolean;\n /**\n * Optional override for the clear action. By default the field clears\n * itself (and notifies via `onChange`); pass `onClear` only when you need\n * custom reset logic beyond emptying the value.\n */\n onClear?: () => void;\n /** Accessible name for the clear button. Default `\"Clear\"`. */\n clearLabel?: string;\n /**\n * Handle to the underlying `<input>` element, merged with the atom's own\n * internal ref (the self-clear keeps working). Use this to focus, select,\n * measure, or insert text at the caret from a consumer. A plain React `ref`\n * on `<TextInput>` does NOT reach the element — it's consumed by `{...rest}`\n * and overridden by the managed ref — so pass `inputRef` instead.\n */\n inputRef?: Ref<HTMLInputElement>;\n}\n\n\nexport function TextInput({\n className,\n type = 'text',\n error,\n clearable = true,\n onClear,\n clearLabel = 'Clear',\n value,\n defaultValue,\n onChange,\n disabled,\n inputRef,\n ...rest\n}: TextInputProps) {\n const errorId = useId();\n const innerRef = useRef<HTMLInputElement>(null);\n const isControlled = value !== undefined;\n const [hasTextUncontrolled, setHasTextUncontrolled] = useState(\n () => typeof defaultValue === 'string' && defaultValue.length > 0,\n );\n const hasValue = isControlled ? String(value).length > 0 : hasTextUncontrolled;\n const showClear = !!clearable && hasValue && !disabled;\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setHasTextUncontrolled(e.target.value.length > 0);\n onChange?.(e);\n };\n const handleClear = () => {\n // Self-clear path (clearFieldValue) already refocuses the field; only the\n // onClear-override path needs an explicit focus. Avoids a double focus().\n if (onClear) {\n onClear();\n innerRef.current?.focus();\n } else {\n clearFieldValue(innerRef.current);\n }\n if (!isControlled) setHasTextUncontrolled(false);\n };\n\n // Merge the consumer's `inputRef` with the atom's `innerRef` (the self-clear\n // relies on `innerRef`), so both get the element. Memoised on `inputRef` so\n // the callback identity is stable and React doesn't detach/reattach.\n const setInputRef = useMemo(() => mergeRefs(innerRef, inputRef), [inputRef]);\n\n const input = (\n // `{...rest}` is spread FIRST so the managed props below always win — a raw\n // consumer `ref` can't clobber the merged ref (which the self-clear relies\n // on); the sanctioned handle is `inputRef`, merged in via `setInputRef`.\n // `defaultValue` is only forwarded when uncontrolled, so value+defaultValue\n // are never both set.\n <input\n {...rest}\n ref={setInputRef}\n type={type}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n disabled={disabled}\n className={cn(\n 'uxm-input-text',\n error && 'uxm-input-text--error',\n clearable && 'uxm-input-text--clearable',\n className,\n )}\n aria-invalid={error ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], error ? errorId : undefined)}\n />\n );\n\n return (\n <>\n {clearable ? (\n // Layout-only wrapper so the clear button can sit absolutely at the\n // trailing edge. The visible chrome stays on `.uxm-input-text` (the\n // input itself), so save-emitted `--uxm-input-text-*` vars still land.\n <div className=\"uxm-input-text__wrap\">\n {input}\n {showClear && (\n <IconButton\n onClick={handleClear}\n className=\"uxm-field-clear uxm-input-text__clear\"\n aria-label={clearLabel}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n </div>\n ) : (\n input\n )}\n {error && (\n <FieldError id={errorId} className=\"uxm-input-text__error-message\">\n {error}\n </FieldError>\n )}\n </>\n );\n}\n// Static marker so FormField only forwards its `error` prop into children\n// that accept one (avoids React unknown-prop warnings on non-input children).\nTextInput.hasError = true;\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** See `TextInputProps.error`. */\n error?: string;\n /** See `TextInputProps.clearable`. Defaults to `true`; ✕ sits at the top-right corner. */\n clearable?: boolean;\n /** See `TextInputProps.onClear` — optional override; the field self-clears otherwise. */\n onClear?: () => void;\n /** See `TextInputProps.clearLabel`. Default `\"Clear\"`. */\n clearLabel?: string;\n /**\n * Handle to the underlying `<textarea>` element, merged with the atom's own\n * internal ref (the self-clear keeps working). Use it to focus, select, or\n * insert text at the caret (e.g. drop-a-variable-into-a-formula). A plain\n * React `ref` on `<Textarea>` does NOT reach the element — pass\n * `textareaRef` instead.\n */\n textareaRef?: Ref<HTMLTextAreaElement>;\n}\n\nexport function Textarea({\n className,\n error,\n clearable = true,\n onClear,\n clearLabel = 'Clear',\n value,\n defaultValue,\n onChange,\n disabled,\n textareaRef,\n ...rest\n}: TextareaProps) {\n const errorId = useId();\n const innerRef = useRef<HTMLTextAreaElement>(null);\n const isControlled = value !== undefined;\n const [hasTextUncontrolled, setHasTextUncontrolled] = useState(\n () => typeof defaultValue === 'string' && defaultValue.length > 0,\n );\n const hasValue = isControlled ? String(value).length > 0 : hasTextUncontrolled;\n const showClear = !!clearable && hasValue && !disabled;\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setHasTextUncontrolled(e.target.value.length > 0);\n onChange?.(e);\n };\n const handleClear = () => {\n // See TextInput: clearFieldValue refocuses; only onClear needs explicit focus.\n if (onClear) {\n onClear();\n innerRef.current?.focus();\n } else {\n clearFieldValue(innerRef.current);\n }\n if (!isControlled) setHasTextUncontrolled(false);\n };\n\n // Merge the consumer's `textareaRef` with the atom's `innerRef` — see TextInput.\n const setTextareaRef = useMemo(() => mergeRefs(innerRef, textareaRef), [textareaRef]);\n\n const textarea = (\n // `{...rest}` first so managed props win; the sanctioned element handle is\n // `textareaRef`, merged in via `setTextareaRef`. `defaultValue` only when\n // uncontrolled — never both value+defaultValue.\n <textarea\n {...rest}\n ref={setTextareaRef}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n disabled={disabled}\n className={cn(\n 'uxm-textarea',\n error && 'uxm-textarea--error',\n clearable && 'uxm-textarea--clearable',\n className,\n )}\n aria-invalid={error ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], error ? errorId : undefined)}\n />\n );\n\n return (\n <>\n {clearable ? (\n <div className=\"uxm-textarea__wrap\">\n {textarea}\n {showClear && (\n <IconButton\n onClick={handleClear}\n className=\"uxm-field-clear uxm-textarea__clear\"\n aria-label={clearLabel}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n </div>\n ) : (\n textarea\n )}\n {error && (\n <FieldError id={errorId} className=\"uxm-textarea__error-message\">\n {error}\n </FieldError>\n )}\n </>\n );\n}\nTextarea.hasError = true;\n\n/**\n * Native `<select>` attributes the atom still accepts verbatim. The five\n * omitted keys are the ones `mode` re-shapes: `value` / `defaultValue` /\n * `onChange` differ per mode, `required` gains its own message prop, and\n * `multiple` is replaced by `mode=\"multi\"`. Keeping this base means existing\n * `<Select onBlur={…} autoFocus data-testid={…}>` call sites — and any\n * `Omit<SelectProps, …>` in consumer code — keep compiling.\n */\ntype SelectNativeProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n 'value' | 'defaultValue' | 'onChange' | 'required' | 'multiple'\n>;\n\n/** Props shared by both single- and multi-select modes. */\ninterface SelectCommonProps extends SelectNativeProps {\n /** `<option>` children — parsed into items (and a placeholder from `<option value=\"\" disabled>`). */\n children?: ReactNode;\n /**\n * When set to a non-empty string, the trigger renders in its error\n * state: red border (`.uxm-select-dropdown--error`), `aria-invalid` on\n * the combobox, and the message below the trigger. Omit (or pass an\n * empty string) for the normal state.\n */\n error?: string;\n /**\n * Whether the dropdown panel includes a search box. Forwarded to the\n * internal Listbox: `true`/`false` force it, `\"auto\"` (the default)\n * shows it only once the option count crosses the shared threshold —\n * short lists stay a plain picker, long ones become filterable, with no\n * change to the trigger. (For a search-first combobox with its own\n * trigger chrome — icon glyphs, dial codes — use SearchDropdown.)\n */\n searchable?: boolean | 'auto';\n /**\n * Require a selection. Clearing to empty is still allowed (input-family,\n * live model) but flags the error immediately. An explicit `error` prop\n * takes precedence. Single mode is only clearable with a placeholder\n * option; multi mode uses `clearable`.\n */\n required?: boolean;\n /**\n * Override the default required message. Defaults are per-mode:\n * single → `\"Select an option\"`, multi → `\"Select at least one option\"`\n * (the shared `DEFAULT_MULTI_REQUIRED_MESSAGE`).\n */\n requiredMessage?: string;\n /**\n * Accessible name for the trigger's clear button. Defaults are per-mode:\n * single → `\"Clear selection\"`, multi → `\"Clear all selections\"`.\n */\n clearLabel?: string;\n}\n\nexport interface SelectSingleProps extends SelectCommonProps {\n /** Single-choice (default) — one value, cleared only when a placeholder option exists. */\n mode?: 'single';\n value?: string;\n defaultValue?: string;\n /** Fires a synthesized `ChangeEvent` (native-`<select>`-compatible) so `e.target.value` works. */\n onChange?: (event: ChangeEvent<HTMLSelectElement>) => void;\n}\n\nexport interface SelectMultiProps extends SelectCommonProps {\n /** Multi-choice — an array value with a \"N selected\" trigger, live commit, checkbox rows. */\n mode: 'multi';\n value?: string[];\n defaultValue?: string[];\n /** Fires the full selected-value array on every toggle (live). */\n onChange?: (next: string[]) => void;\n /** Show a clear-all ✕ on the trigger AND a \"Clear all\" in the panel. */\n clearable?: boolean;\n}\n\nexport type SelectProps = SelectSingleProps | SelectMultiProps;\n\ninterface SelectItem {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n/**\n * Parse `<option>` children into Listbox-friendly items. HTML semantics:\n * - `<option value=\"x\">Label</option>` → value \"x\", label \"Label\"\n * - `<option>Label</option>` → value \"Label\", label \"Label\" (label IS the value)\n * - `<option value=\"\" disabled>Placeholder</option>` → reserved as the\n * trigger placeholder text, not added to items (matches the common\n * React Select pattern).\n */\nfunction parseSelectOptions(children: ReactNode): {\n items: SelectItem[];\n placeholder: string | undefined;\n} {\n const items: SelectItem[] = [];\n let placeholder: string | undefined;\n\n Children.forEach(children, (child) => {\n if (\n !isValidElement<{\n value?: string | number;\n children?: ReactNode;\n disabled?: boolean;\n }>(child)\n ) {\n return;\n }\n if (child.type !== 'option') return;\n\n const text = String(child.props.children ?? '');\n const val = child.props.value !== undefined ? String(child.props.value) : text;\n const label = text || val;\n const disabled = child.props.disabled ?? false;\n\n if (val === '' && disabled && placeholder === undefined) {\n placeholder = label;\n return;\n }\n items.push({ value: val, label, disabled });\n });\n\n return { items, placeholder };\n}\n\n/**\n * Select Dropdown — internally a Listbox-backed picker. Its public\n * API stays compatible with the previous native-`<select>` shape:\n * pass `<option>` children, controlled (`value`) or uncontrolled\n * (`defaultValue`) state, and an `onChange(e)` handler that reads\n * `e.target.value`.\n *\n * The visible trigger keeps the same `.uxm-select-dropdown` class\n * (and all its registry-tuned visual chrome — bg, border, radius,\n * padding, font, per-state colors). The OPEN-state UI swaps from the\n * browser's native dropdown to a `<Listbox>` panel so it looks\n * identical across browsers and inherits the shared panel theming\n * from the `listbox` registry entry.\n *\n * `onChange` receives a synthetic `ChangeEvent` shape — most React\n * callers only read `e.target.value`, which is set correctly. For\n * new code, consider using `<Listbox>` directly with its native\n * `(item: T | null) => void` callback.\n */\nfunction SelectSingle({\n className,\n children,\n value,\n defaultValue,\n onChange,\n disabled,\n style,\n name,\n id,\n error,\n searchable = 'auto',\n required = false,\n requiredMessage,\n clearLabel = 'Clear selection',\n 'aria-label': ariaLabel,\n ...rest\n}: SelectSingleProps) {\n const errorId = useId();\n // Required is flagged (not blocked) on clear — input-family live model.\n // An explicit `error` prop wins over the internal required one.\n const [reqError, setReqError] = useState<string | null>(null);\n const shownError = error ?? reqError ?? undefined;\n // Uncontrolled state — only used when `value` is not provided. Matches\n // the native `<select>`'s controlled/uncontrolled duality.\n const [internal, setInternal] = useState<string>(() => String(defaultValue ?? ''));\n const isControlled = value !== undefined;\n const current = String(isControlled ? value : internal);\n\n const { items, placeholder } = useMemo(() => parseSelectOptions(children), [children]);\n const selected = useMemo(() => items.find((o) => o.value === current) ?? null, [items, current]);\n\n const commit = useCallback(\n (nextValue: string) => {\n if (!isControlled) setInternal(nextValue);\n if (required) setReqError(nextValue === '' ? (requiredMessage ?? 'Select an option') : null);\n if (onChange) {\n // Synthesize a ChangeEvent so callers using\n // `onChange={(e) => set(e.target.value)}` keep working. Listbox\n // doesn't fire native events; we fabricate the minimum surface\n // most React callers actually read (`target.value`,\n // `currentTarget.value`, `type`, `name`).\n const target = { value: nextValue, name } as unknown as EventTarget & HTMLSelectElement;\n const event = {\n target,\n currentTarget: target,\n type: 'change',\n bubbles: true,\n cancelable: false,\n defaultPrevented: false,\n preventDefault() {},\n stopPropagation() {},\n isDefaultPrevented: () => false,\n isPropagationStopped: () => false,\n persist() {},\n timeStamp: 0,\n nativeEvent: {} as Event,\n } as unknown as ChangeEvent<HTMLSelectElement>;\n onChange(event);\n }\n },\n [isControlled, onChange, name, required, requiredMessage],\n );\n\n return (\n <>\n <Listbox<SelectItem>\n items={items}\n getKey={(o) => o.value}\n getLabel={(o) => o.label}\n value={selected}\n onChange={(next) => {\n // Listbox's onChange is `(T | null) => void` to support\n // consumer-driven clearing. Select doesn't expose a clear\n // affordance — defensive ignore if null arrives.\n if (next) commit(next.value);\n }}\n isItemDisabled={(o) => o.disabled}\n disabled={disabled}\n searchable={searchable}\n aria-label={ariaLabel}\n // Clear inside the panel (input-family convention: clear on the trigger\n // AND in the dropdown). Shown when a value is picked and the field can be\n // empty (has a placeholder option). Mirrors the trailing ✕ on the trigger.\n footer={selected && placeholder !== undefined && !disabled\n ? ({ close }: { close: () => void }) => (\n <ButtonGhost\n className=\"uxm-listbox__footer-clear-option\"\n onClick={() => { commit(''); close(); }}\n >\n <Icon glyph=\"close\" size={12} />\n Clear\n </ButtonGhost>\n )\n : undefined}\n renderTrigger={({ open, triggerProps }) => (\n // Trigger uses `<div role=\"combobox\">` — gives us a focusable\n // surface that can carry the same `.uxm-select-dropdown` chrome\n // the native `<select>` had. `aria-disabled` drives the disabled\n // visual (CSS targets the attribute since `<div>` doesn't honor\n // `:disabled`).\n // `rest` = the leftover native-select attributes (`onBlur`, `autoFocus`,\n // `form`, `data-*`, …). It goes FIRST so `triggerProps` and the atom's\n // own props always win; the cast only bridges the element generic —\n // the trigger is a `<div>`, not a `<select>`.\n // eslint-disable-next-line jsx-a11y/role-has-required-aria-props -- aria-expanded (always) and aria-controls (while open) arrive via the triggerProps spread; the rule can't see through it\n <div role=\"combobox\"\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...triggerProps}\n tabIndex={disabled ? -1 : 0}\n // The trigger is what lands in the tab order, so it needs the name.\n // `aria-label` is destructured out of `rest` above and forwarded to\n // the Listbox, which puts it on the popup panel — naming the popup,\n // not the control. A `<div role=\"combobox\">` also can't be named by a\n // wrapping `<label>` (a div isn't labelable), so without this the\n // control announces as an unnamed combobox.\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={shownError ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], shownError ? errorId : undefined)}\n id={id}\n style={style}\n className={cn(\n 'uxm-select-dropdown',\n open && 'uxm-select-dropdown--open',\n shownError && 'uxm-select-dropdown--error',\n className,\n )}\n >\n <span\n className={cn(\n 'uxm-select-dropdown__trigger-label',\n !selected && 'uxm-select-dropdown__trigger-label--empty',\n )}\n >\n {selected ? selected.label : (placeholder ?? '')}\n </span>\n {/* Clear ✕ shows only when the field CAN be empty — i.e. it has a\n placeholder option (`<option value=\"\" disabled>`), which stands\n for the \"no selection\" state. A select without a placeholder is\n mandatory (a value is always picked, native-<select> style), so\n clearing to empty makes no sense and no ✕ is rendered. */}\n {selected && !disabled && placeholder !== undefined && (\n <IconButton\n aria-label={clearLabel}\n onClick={(e) => {\n // Stop click from bubbling to the trigger div (which\n // would toggle the popover back open).\n e.stopPropagation();\n commit('');\n }}\n onMouseDown={(e) => {\n // Stop mousedown too — the atom's Popover wires its\n // click-outside detection to mousedown.\n e.stopPropagation();\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.stopPropagation();\n }\n }}\n className=\"uxm-field-clear uxm-select-dropdown__trigger-clear\"\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n <Icon\n glyph=\"chevron-down\"\n size={14}\n className=\"uxm-select-dropdown__trigger-chevron\"\n style={{ transform: open ? 'rotate(180deg)' : 'none' }}\n />\n </div>\n )}\n renderItem={(o) => o.label}\n />\n {shownError && (\n <FieldError id={errorId} className=\"uxm-select-dropdown__error-message\">\n {shownError}\n </FieldError>\n )}\n </>\n );\n}\n\n/**\n * Multi-select mode — same `.uxm-select-dropdown` trigger chrome as single,\n * but backed by MultiListbox: an array value, a \"N selected\" trigger, checkbox\n * rows, live commit, and (input-family) a clear ✕ on the trigger AND in the\n * panel. Required flags an empty selection without blocking.\n */\nfunction SelectMulti({\n className,\n children,\n value,\n defaultValue,\n onChange,\n disabled,\n style,\n id,\n error,\n searchable = 'auto',\n required = false,\n requiredMessage,\n clearable = false,\n clearLabel = 'Clear all selections',\n 'aria-label': ariaLabel,\n ...rest\n}: SelectMultiProps) {\n const errorId = useId();\n const [reqError, setReqError] = useState<string | null>(null);\n const shownError = error ?? reqError ?? undefined;\n const [internal, setInternal] = useState<string[]>(() => defaultValue ?? []);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const { items, placeholder } = useMemo(() => parseSelectOptions(children), [children]);\n const selectedItems = useMemo(\n () => items.filter((o) => current.includes(o.value)),\n [items, current],\n );\n\n const commit = useCallback(\n (next: string[]) => {\n if (!isControlled) setInternal(next);\n if (required) {\n setReqError(next.length === 0 ? (requiredMessage ?? DEFAULT_MULTI_REQUIRED_MESSAGE) : null);\n }\n onChange?.(next);\n },\n [isControlled, onChange, required, requiredMessage],\n );\n\n return (\n <>\n <MultiListbox<SelectItem>\n items={items}\n getKey={(o) => o.value}\n getLabel={(o) => o.label}\n value={selectedItems}\n onChange={(next) => commit(next.map((o) => o.value))}\n // Relies on MultiListbox's default `commitMode=\"change\"` — the\n // \"N selected\" count has to track each toggle.\n isItemDisabled={(o) => o.disabled}\n disabled={disabled}\n searchable={searchable}\n aria-label={ariaLabel}\n footer={clearable\n ? ({ clear, selected }) =>\n selected.length > 0 ? (\n <ButtonGhost className=\"uxm-listbox__footer-clear-option\" onClick={clear}>\n <Icon glyph=\"close\" size={12} />\n Clear all\n </ButtonGhost>\n ) : null\n : undefined}\n renderTrigger={({ open, triggerProps }) => (\n // `rest` (leftover native-select attributes) goes first so\n // `triggerProps` and the atom's own props win — see SelectSingle.\n // eslint-disable-next-line jsx-a11y/role-has-required-aria-props -- aria-expanded/controls arrive via the triggerProps spread\n <div role=\"combobox\"\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...triggerProps}\n tabIndex={disabled ? -1 : 0}\n // Names the control itself, not just the popup — see SelectSingle.\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={shownError ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], shownError ? errorId : undefined)}\n id={id}\n style={style}\n className={cn(\n 'uxm-select-dropdown',\n open && 'uxm-select-dropdown--open',\n shownError && 'uxm-select-dropdown--error',\n className,\n )}\n >\n <span\n className={cn(\n 'uxm-select-dropdown__trigger-label',\n current.length === 0 && 'uxm-select-dropdown__trigger-label--empty',\n )}\n >\n {current.length === 0 ? (placeholder ?? '') : `${current.length} selected`}\n </span>\n {clearable && current.length > 0 && !disabled && (\n <IconButton\n aria-label={clearLabel}\n className=\"uxm-field-clear uxm-select-dropdown__trigger-clear\"\n onClick={(e) => { e.stopPropagation(); commit([]); }}\n onMouseDown={(e) => e.stopPropagation()}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') e.stopPropagation(); }}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n <Icon\n glyph=\"chevron-down\"\n size={14}\n className=\"uxm-select-dropdown__trigger-chevron\"\n style={{ transform: open ? 'rotate(180deg)' : 'none' }}\n />\n </div>\n )}\n renderItem={(o) => o.label}\n />\n {shownError && (\n <FieldError id={errorId} className=\"uxm-select-dropdown__error-message\">\n {shownError}\n </FieldError>\n )}\n </>\n );\n}\n\n/**\n * Select dropdown atom. `mode=\"single\"` (default) picks one value;\n * `mode=\"multi\"` picks an array. Both share the same trigger chrome and\n * `<option>` children API — only the value/onChange shape differs.\n */\nexport function Select(props: SelectProps) {\n return props.mode === 'multi' ? <SelectMulti {...props} /> : <SelectSingle {...props} />;\n}\nSelect.hasError = true;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/input/input.tsx"],"sourcesContent":["import {\n Children,\n isValidElement,\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n type SelectHTMLAttributes,\n type TextareaHTMLAttributes,\n} from 'react';\n\nimport { cn, mergeDescribedBy, mergeRefs } from '@/helpers';\n\nimport { ButtonGhost } from '../button';\nimport { FieldError } from '../field-error';\nimport { Icon } from '../icon';\nimport { IconButton } from '../icon-button';\nimport { DEFAULT_MULTI_REQUIRED_MESSAGE, Listbox, MultiListbox } from '../listbox';\n\nimport { clearFieldValue } from './clear-field-value';\n\nexport interface TextInputProps extends InputHTMLAttributes<HTMLInputElement> {\n /**\n * When set to a non-empty string, the field renders in its error state:\n * red border (`.uxm-input-text--error`), `aria-invalid`, and the message\n * rendered below the input. Omit (or pass an empty string) for the normal\n * state. The atom owns the message so it works standalone — search bars,\n * inline edits, custom layouts — without requiring a `FormField` wrapper.\n */\n error?: string;\n /**\n * Show a clear (✕) button at the trailing edge when the input has content.\n * **Defaults to `true`** — a free-text field is always safe to clear (you\n * can type/delete anyway), so the affordance is on by default; pass\n * `clearable={false}` to opt out. The ✕ self-clears (resets the field and\n * fires `onChange` with \"\"), so no `onClear` is needed — any controlled\n * `value` + `onChange` usage gets it for free.\n */\n clearable?: boolean;\n /**\n * Optional override for the clear action. By default the field clears\n * itself (and notifies via `onChange`); pass `onClear` only when you need\n * custom reset logic beyond emptying the value.\n */\n onClear?: () => void;\n /** Accessible name for the clear button. Default `\"Clear\"`. */\n clearLabel?: string;\n /**\n * Handle to the underlying `<input>` element, merged with the atom's own\n * internal ref (the self-clear keeps working). Use this to focus, select,\n * measure, or insert text at the caret from a consumer. A plain React `ref`\n * on `<TextInput>` does NOT reach the element — it's consumed by `{...rest}`\n * and overridden by the managed ref — so pass `inputRef` instead.\n */\n inputRef?: Ref<HTMLInputElement>;\n}\n\n\nexport function TextInput({\n className,\n type = 'text',\n error,\n clearable = true,\n onClear,\n clearLabel = 'Clear',\n value,\n defaultValue,\n onChange,\n disabled,\n inputRef,\n ...rest\n}: TextInputProps) {\n const errorId = useId();\n const innerRef = useRef<HTMLInputElement>(null);\n const isControlled = value !== undefined;\n const [hasTextUncontrolled, setHasTextUncontrolled] = useState(\n () => typeof defaultValue === 'string' && defaultValue.length > 0,\n );\n const hasValue = isControlled ? String(value).length > 0 : hasTextUncontrolled;\n const showClear = !!clearable && hasValue && !disabled;\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setHasTextUncontrolled(e.target.value.length > 0);\n onChange?.(e);\n };\n const handleClear = () => {\n // Self-clear path (clearFieldValue) already refocuses the field; only the\n // onClear-override path needs an explicit focus. Avoids a double focus().\n if (onClear) {\n onClear();\n innerRef.current?.focus();\n } else {\n clearFieldValue(innerRef.current);\n }\n if (!isControlled) setHasTextUncontrolled(false);\n };\n\n // Merge the consumer's `inputRef` with the atom's `innerRef` (the self-clear\n // relies on `innerRef`), so both get the element. Memoised on `inputRef` so\n // the callback identity is stable and React doesn't detach/reattach.\n const setInputRef = useMemo(() => mergeRefs(innerRef, inputRef), [inputRef]);\n\n const input = (\n // `{...rest}` is spread FIRST so the managed props below always win — a raw\n // consumer `ref` can't clobber the merged ref (which the self-clear relies\n // on); the sanctioned handle is `inputRef`, merged in via `setInputRef`.\n // `defaultValue` is only forwarded when uncontrolled, so value+defaultValue\n // are never both set.\n <input\n {...rest}\n ref={setInputRef}\n type={type}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n disabled={disabled}\n className={cn(\n 'uxm-input-text',\n error && 'uxm-input-text--error',\n clearable && 'uxm-input-text--clearable',\n className,\n )}\n aria-invalid={error ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], error ? errorId : undefined)}\n />\n );\n\n return (\n <>\n {clearable ? (\n // Layout-only wrapper so the clear button can sit absolutely at the\n // trailing edge. The visible chrome stays on `.uxm-input-text` (the\n // input itself), so save-emitted `--uxm-input-text-*` vars still land.\n <div className=\"uxm-input-text__wrap\">\n {input}\n {showClear && (\n <IconButton\n onClick={handleClear}\n className=\"uxm-field-clear uxm-input-text__clear\"\n aria-label={clearLabel}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n </div>\n ) : (\n input\n )}\n {error && (\n <FieldError id={errorId} className=\"uxm-input-text__error-message\">\n {error}\n </FieldError>\n )}\n </>\n );\n}\n// Static marker so FormField only forwards its `error` prop into children\n// that accept one (avoids React unknown-prop warnings on non-input children).\nTextInput.hasError = true;\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** See `TextInputProps.error`. */\n error?: string;\n /** See `TextInputProps.clearable`. Defaults to `true`; ✕ sits at the top-right corner. */\n clearable?: boolean;\n /** See `TextInputProps.onClear` — optional override; the field self-clears otherwise. */\n onClear?: () => void;\n /** See `TextInputProps.clearLabel`. Default `\"Clear\"`. */\n clearLabel?: string;\n /**\n * Handle to the underlying `<textarea>` element, merged with the atom's own\n * internal ref (the self-clear keeps working). Use it to focus, select, or\n * insert text at the caret (e.g. drop-a-variable-into-a-formula). A plain\n * React `ref` on `<Textarea>` does NOT reach the element — pass\n * `textareaRef` instead.\n */\n textareaRef?: Ref<HTMLTextAreaElement>;\n}\n\nexport function Textarea({\n className,\n error,\n clearable = true,\n onClear,\n clearLabel = 'Clear',\n value,\n defaultValue,\n onChange,\n disabled,\n textareaRef,\n ...rest\n}: TextareaProps) {\n const errorId = useId();\n const innerRef = useRef<HTMLTextAreaElement>(null);\n const isControlled = value !== undefined;\n const [hasTextUncontrolled, setHasTextUncontrolled] = useState(\n () => typeof defaultValue === 'string' && defaultValue.length > 0,\n );\n const hasValue = isControlled ? String(value).length > 0 : hasTextUncontrolled;\n const showClear = !!clearable && hasValue && !disabled;\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setHasTextUncontrolled(e.target.value.length > 0);\n onChange?.(e);\n };\n const handleClear = () => {\n // See TextInput: clearFieldValue refocuses; only onClear needs explicit focus.\n if (onClear) {\n onClear();\n innerRef.current?.focus();\n } else {\n clearFieldValue(innerRef.current);\n }\n if (!isControlled) setHasTextUncontrolled(false);\n };\n\n // Merge the consumer's `textareaRef` with the atom's `innerRef` — see TextInput.\n const setTextareaRef = useMemo(() => mergeRefs(innerRef, textareaRef), [textareaRef]);\n\n const textarea = (\n // `{...rest}` first so managed props win; the sanctioned element handle is\n // `textareaRef`, merged in via `setTextareaRef`. `defaultValue` only when\n // uncontrolled — never both value+defaultValue.\n <textarea\n {...rest}\n ref={setTextareaRef}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n disabled={disabled}\n className={cn(\n 'uxm-textarea',\n error && 'uxm-textarea--error',\n clearable && 'uxm-textarea--clearable',\n className,\n )}\n aria-invalid={error ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], error ? errorId : undefined)}\n />\n );\n\n return (\n <>\n {clearable ? (\n <div className=\"uxm-textarea__wrap\">\n {textarea}\n {showClear && (\n <IconButton\n onClick={handleClear}\n className=\"uxm-field-clear uxm-textarea__clear\"\n aria-label={clearLabel}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n </div>\n ) : (\n textarea\n )}\n {error && (\n <FieldError id={errorId} className=\"uxm-textarea__error-message\">\n {error}\n </FieldError>\n )}\n </>\n );\n}\nTextarea.hasError = true;\n\n/**\n * Native `<select>` attributes the atom still accepts verbatim. The five\n * omitted keys are the ones `mode` re-shapes: `value` / `defaultValue` /\n * `onChange` differ per mode, `required` gains its own message prop, and\n * `multiple` is replaced by `mode=\"multi\"`. Keeping this base means existing\n * `<Select onBlur={…} autoFocus data-testid={…}>` call sites — and any\n * `Omit<SelectProps, …>` in consumer code — keep compiling.\n */\ntype SelectNativeProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n 'value' | 'defaultValue' | 'onChange' | 'required' | 'multiple'\n>;\n\n/** Props shared by both single- and multi-select modes. */\ninterface SelectCommonProps extends SelectNativeProps {\n /** `<option>` children — parsed into items (and a placeholder from `<option value=\"\" disabled>`). */\n children?: ReactNode;\n /**\n * When set to a non-empty string, the trigger renders in its error\n * state: red border (`.uxm-select-dropdown--error`), `aria-invalid` on\n * the combobox, and the message below the trigger. Omit (or pass an\n * empty string) for the normal state.\n */\n error?: string;\n /**\n * Whether the dropdown panel includes a search box. Forwarded to the\n * internal Listbox: `true`/`false` force it, `\"auto\"` (the default)\n * shows it only once the option count crosses the shared threshold —\n * short lists stay a plain picker, long ones become filterable, with no\n * change to the trigger. (For a search-first combobox with its own\n * trigger chrome — icon glyphs, dial codes — use SearchDropdown.)\n */\n searchable?: boolean | 'auto';\n /**\n * Require a selection. Clearing to empty is still allowed (input-family,\n * live model) but flags the error immediately. An explicit `error` prop\n * takes precedence. Single mode is only clearable with a placeholder\n * option; multi mode uses `clearable`.\n */\n required?: boolean;\n /**\n * Override the default required message. Defaults are per-mode:\n * single → `\"Select an option\"`, multi → `\"Select at least one option\"`\n * (the shared `DEFAULT_MULTI_REQUIRED_MESSAGE`).\n */\n requiredMessage?: string;\n /**\n * Accessible name for the trigger's clear button. Defaults are per-mode:\n * single → `\"Clear selection\"`, multi → `\"Clear all selections\"`.\n */\n clearLabel?: string;\n}\n\nexport interface SelectSingleProps extends SelectCommonProps {\n /** Single-choice (default) — one value, cleared only when a placeholder option exists. */\n mode?: 'single';\n value?: string;\n defaultValue?: string;\n /** Fires a synthesized `ChangeEvent` (native-`<select>`-compatible) so `e.target.value` works. */\n onChange?: (event: ChangeEvent<HTMLSelectElement>) => void;\n}\n\nexport interface SelectMultiProps extends SelectCommonProps {\n /** Multi-choice — an array value with a \"N selected\" trigger, live commit, checkbox rows. */\n mode: 'multi';\n value?: string[];\n defaultValue?: string[];\n /** Fires the full selected-value array on every toggle (live). */\n onChange?: (next: string[]) => void;\n /** Show a clear-all ✕ on the trigger AND a \"Clear all\" in the panel. */\n clearable?: boolean;\n}\n\nexport type SelectProps = SelectSingleProps | SelectMultiProps;\n\ninterface SelectItem {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n/**\n * Parse `<option>` children into Listbox-friendly items. HTML semantics:\n * - `<option value=\"x\">Label</option>` → value \"x\", label \"Label\"\n * - `<option>Label</option>` → value \"Label\", label \"Label\" (label IS the value)\n * - `<option value=\"\" disabled>Placeholder</option>` → reserved as the\n * trigger placeholder text, not added to items (matches the common\n * React Select pattern).\n */\nfunction parseSelectOptions(children: ReactNode): {\n items: SelectItem[];\n placeholder: string | undefined;\n} {\n const items: SelectItem[] = [];\n let placeholder: string | undefined;\n\n Children.forEach(children, (child) => {\n if (\n !isValidElement<{\n value?: string | number;\n children?: ReactNode;\n disabled?: boolean;\n }>(child)\n ) {\n return;\n }\n if (child.type !== 'option') return;\n\n const text = String(child.props.children ?? '');\n const val = child.props.value !== undefined ? String(child.props.value) : text;\n const label = text || val;\n const disabled = child.props.disabled ?? false;\n\n if (val === '' && disabled && placeholder === undefined) {\n placeholder = label;\n return;\n }\n items.push({ value: val, label, disabled });\n });\n\n return { items, placeholder };\n}\n\n/**\n * Select Dropdown — internally a Listbox-backed picker. Its public\n * API stays compatible with the previous native-`<select>` shape:\n * pass `<option>` children, controlled (`value`) or uncontrolled\n * (`defaultValue`) state, and an `onChange(e)` handler that reads\n * `e.target.value`.\n *\n * The visible trigger keeps the same `.uxm-select-dropdown` class\n * (and all its registry-tuned visual chrome — bg, border, radius,\n * padding, font, per-state colors). The OPEN-state UI swaps from the\n * browser's native dropdown to a `<Listbox>` panel so it looks\n * identical across browsers and inherits the shared panel theming\n * from the `listbox` registry entry.\n *\n * `onChange` receives a synthetic `ChangeEvent` shape — most React\n * callers only read `e.target.value`, which is set correctly. For\n * new code, consider using `<Listbox>` directly with its native\n * `(item: T | null) => void` callback.\n */\nfunction SelectSingle({\n className,\n children,\n value,\n defaultValue,\n onChange,\n disabled,\n style,\n name,\n id,\n error,\n searchable = 'auto',\n required = false,\n requiredMessage,\n clearLabel = 'Clear selection',\n 'aria-label': ariaLabel,\n ...rest\n}: SelectSingleProps) {\n const errorId = useId();\n // Required is flagged (not blocked) on clear — input-family live model.\n // An explicit `error` prop wins over the internal required one.\n const [reqError, setReqError] = useState<string | null>(null);\n const shownError = error ?? reqError ?? undefined;\n // Uncontrolled state — only used when `value` is not provided. Matches\n // the native `<select>`'s controlled/uncontrolled duality.\n const [internal, setInternal] = useState<string>(() => String(defaultValue ?? ''));\n const isControlled = value !== undefined;\n const current = String(isControlled ? value : internal);\n\n const { items, placeholder } = useMemo(() => parseSelectOptions(children), [children]);\n const selected = useMemo(() => items.find((o) => o.value === current) ?? null, [items, current]);\n\n const commit = useCallback(\n (nextValue: string) => {\n if (!isControlled) setInternal(nextValue);\n if (required) setReqError(nextValue === '' ? (requiredMessage ?? 'Select an option') : null);\n if (onChange) {\n // Synthesize a ChangeEvent so callers using\n // `onChange={(e) => set(e.target.value)}` keep working. Listbox\n // doesn't fire native events; we fabricate the minimum surface\n // most React callers actually read (`target.value`,\n // `currentTarget.value`, `type`, `name`).\n const target = { value: nextValue, name } as unknown as EventTarget & HTMLSelectElement;\n const event = {\n target,\n currentTarget: target,\n type: 'change',\n bubbles: true,\n cancelable: false,\n defaultPrevented: false,\n preventDefault() {},\n stopPropagation() {},\n isDefaultPrevented: () => false,\n isPropagationStopped: () => false,\n persist() {},\n timeStamp: 0,\n nativeEvent: {} as Event,\n } as unknown as ChangeEvent<HTMLSelectElement>;\n onChange(event);\n }\n },\n [isControlled, onChange, name, required, requiredMessage],\n );\n\n return (\n <>\n <Listbox<SelectItem>\n items={items}\n getKey={(o) => o.value}\n getLabel={(o) => o.label}\n value={selected}\n onChange={(next) => {\n // Listbox's onChange is `(T | null) => void` to support\n // consumer-driven clearing. Select doesn't expose a clear\n // affordance — defensive ignore if null arrives.\n if (next) commit(next.value);\n }}\n isItemDisabled={(o) => o.disabled}\n disabled={disabled}\n searchable={searchable}\n aria-label={ariaLabel}\n // Clear inside the panel (input-family convention: clear on the trigger\n // AND in the dropdown). Shown when a value is picked and the field can be\n // empty (has a placeholder option). Mirrors the trailing ✕ on the trigger.\n footer={selected && placeholder !== undefined && !disabled\n ? ({ close }: { close: () => void }) => (\n <ButtonGhost\n className=\"uxm-listbox__footer-clear-option\"\n onClick={() => { commit(''); close(); }}\n >\n <Icon glyph=\"close\" size={12} />\n Clear\n </ButtonGhost>\n )\n : undefined}\n renderTrigger={({ open, triggerProps }) => (\n // Trigger uses `<div role=\"combobox\">` — gives us a focusable\n // surface that can carry the same `.uxm-select-dropdown` chrome\n // the native `<select>` had. `aria-disabled` drives the disabled\n // visual (CSS targets the attribute since `<div>` doesn't honor\n // `:disabled`).\n // `rest` = the leftover native-select attributes (`onBlur`, `autoFocus`,\n // `form`, `data-*`, …). It goes FIRST so `triggerProps` and the atom's\n // own props always win; the cast only bridges the element generic —\n // the trigger is a `<div>`, not a `<select>`.\n // eslint-disable-next-line jsx-a11y/role-has-required-aria-props -- aria-expanded (always) and aria-controls (while open) arrive via the triggerProps spread; the rule can't see through it\n <div role=\"combobox\"\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...triggerProps}\n tabIndex={disabled ? -1 : 0}\n // The trigger is what lands in the tab order, so it needs the name.\n // `aria-label` is destructured out of `rest` above and forwarded to\n // the Listbox, which puts it on the popup panel — naming the popup,\n // not the control. A `<div role=\"combobox\">` also can't be named by a\n // wrapping `<label>` (a div isn't labelable), so without this the\n // control announces as an unnamed combobox.\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={shownError ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], shownError ? errorId : undefined)}\n id={id}\n style={style}\n className={cn(\n 'uxm-select-dropdown',\n open && 'uxm-select-dropdown--open',\n shownError && 'uxm-select-dropdown--error',\n className,\n )}\n >\n <span\n className={cn(\n 'uxm-select-dropdown__trigger-label',\n !selected && 'uxm-select-dropdown__trigger-label--empty',\n )}\n >\n {selected ? selected.label : (placeholder ?? '')}\n </span>\n {/* Clear ✕ shows only when the field CAN be empty — i.e. it has a\n placeholder option (`<option value=\"\" disabled>`), which stands\n for the \"no selection\" state. A select without a placeholder is\n mandatory (a value is always picked, native-<select> style), so\n clearing to empty makes no sense and no ✕ is rendered. */}\n {selected && !disabled && placeholder !== undefined && (\n <IconButton\n aria-label={clearLabel}\n onClick={(e) => {\n // Stop click from bubbling to the trigger div (which\n // would toggle the popover back open).\n e.stopPropagation();\n commit('');\n }}\n onMouseDown={(e) => {\n // Stop mousedown too — the atom's Popover wires its\n // click-outside detection to mousedown.\n e.stopPropagation();\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.stopPropagation();\n }\n }}\n className=\"uxm-field-clear uxm-select-dropdown__trigger-clear\"\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n <Icon\n glyph=\"chevron-down\"\n size={14}\n className={cn(\n 'uxm-select-dropdown__trigger-chevron',\n open && 'uxm-select-dropdown__trigger-chevron--open',\n )}\n />\n </div>\n )}\n renderItem={(o) => o.label}\n />\n {shownError && (\n <FieldError id={errorId} className=\"uxm-select-dropdown__error-message\">\n {shownError}\n </FieldError>\n )}\n </>\n );\n}\n\n/**\n * Multi-select mode — same `.uxm-select-dropdown` trigger chrome as single,\n * but backed by MultiListbox: an array value, a \"N selected\" trigger, checkbox\n * rows, live commit, and (input-family) a clear ✕ on the trigger AND in the\n * panel. Required flags an empty selection without blocking.\n */\nfunction SelectMulti({\n className,\n children,\n value,\n defaultValue,\n onChange,\n disabled,\n style,\n id,\n error,\n searchable = 'auto',\n required = false,\n requiredMessage,\n clearable = false,\n clearLabel = 'Clear all selections',\n 'aria-label': ariaLabel,\n ...rest\n}: SelectMultiProps) {\n const errorId = useId();\n const [reqError, setReqError] = useState<string | null>(null);\n const shownError = error ?? reqError ?? undefined;\n const [internal, setInternal] = useState<string[]>(() => defaultValue ?? []);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const { items, placeholder } = useMemo(() => parseSelectOptions(children), [children]);\n const selectedItems = useMemo(\n () => items.filter((o) => current.includes(o.value)),\n [items, current],\n );\n\n const commit = useCallback(\n (next: string[]) => {\n if (!isControlled) setInternal(next);\n if (required) {\n setReqError(next.length === 0 ? (requiredMessage ?? DEFAULT_MULTI_REQUIRED_MESSAGE) : null);\n }\n onChange?.(next);\n },\n [isControlled, onChange, required, requiredMessage],\n );\n\n return (\n <>\n <MultiListbox<SelectItem>\n items={items}\n getKey={(o) => o.value}\n getLabel={(o) => o.label}\n value={selectedItems}\n onChange={(next) => commit(next.map((o) => o.value))}\n // Relies on MultiListbox's default `commitMode=\"change\"` — the\n // \"N selected\" count has to track each toggle.\n isItemDisabled={(o) => o.disabled}\n disabled={disabled}\n searchable={searchable}\n aria-label={ariaLabel}\n footer={clearable\n ? ({ clear, selected }) =>\n selected.length > 0 ? (\n <ButtonGhost className=\"uxm-listbox__footer-clear-option\" onClick={clear}>\n <Icon glyph=\"close\" size={12} />\n Clear all\n </ButtonGhost>\n ) : null\n : undefined}\n renderTrigger={({ open, triggerProps }) => (\n // `rest` (leftover native-select attributes) goes first so\n // `triggerProps` and the atom's own props win — see SelectSingle.\n // eslint-disable-next-line jsx-a11y/role-has-required-aria-props -- aria-expanded/controls arrive via the triggerProps spread\n <div role=\"combobox\"\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...triggerProps}\n tabIndex={disabled ? -1 : 0}\n // Names the control itself, not just the popup — see SelectSingle.\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={shownError ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], shownError ? errorId : undefined)}\n id={id}\n style={style}\n className={cn(\n 'uxm-select-dropdown',\n open && 'uxm-select-dropdown--open',\n shownError && 'uxm-select-dropdown--error',\n className,\n )}\n >\n <span\n className={cn(\n 'uxm-select-dropdown__trigger-label',\n current.length === 0 && 'uxm-select-dropdown__trigger-label--empty',\n )}\n >\n {current.length === 0 ? (placeholder ?? '') : `${current.length} selected`}\n </span>\n {clearable && current.length > 0 && !disabled && (\n <IconButton\n aria-label={clearLabel}\n className=\"uxm-field-clear uxm-select-dropdown__trigger-clear\"\n onClick={(e) => { e.stopPropagation(); commit([]); }}\n onMouseDown={(e) => e.stopPropagation()}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') e.stopPropagation(); }}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n <Icon\n glyph=\"chevron-down\"\n size={14}\n className={cn(\n 'uxm-select-dropdown__trigger-chevron',\n open && 'uxm-select-dropdown__trigger-chevron--open',\n )}\n />\n </div>\n )}\n renderItem={(o) => o.label}\n />\n {shownError && (\n <FieldError id={errorId} className=\"uxm-select-dropdown__error-message\">\n {shownError}\n </FieldError>\n )}\n </>\n );\n}\n\n/**\n * Select dropdown atom. `mode=\"single\"` (default) picks one value;\n * `mode=\"multi\"` picks an array. Both share the same trigger chrome and\n * `<option>` children API — only the value/onChange shape differs.\n */\nexport function Select(props: SelectProps) {\n return props.mode === 'multi' ? <SelectMulti {...props} /> : <SelectSingle {...props} />;\n}\nSelect.hasError = true;\n"],"mappings":"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","names":[]}
@@ -171,6 +171,10 @@
171
171
  transition: transform 0.15s;
172
172
  }
173
173
 
174
+ .uxm-select-dropdown__trigger-chevron--open {
175
+ transform: rotate(180deg);
176
+ }
177
+
174
178
  /* Clear ✕ inside the trigger — rendered when a value is selected AND the
175
179
  field can be empty (it has a placeholder option). Mandatory selects (no
176
180
  placeholder, a value is always picked) don't render it. Shared chrome
@@ -1 +1 @@
1
- {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/ui/input/input.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../src/ui/input/input.tsx"],"names":[],"mappings":"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"}
@@ -347,8 +347,10 @@ function SelectSingle({
347
347
  {
348
348
  glyph: "chevron-down",
349
349
  size: 14,
350
- className: "uxm-select-dropdown__trigger-chevron",
351
- style: { transform: open ? "rotate(180deg)" : "none" }
350
+ className: cn(
351
+ "uxm-select-dropdown__trigger-chevron",
352
+ open && "uxm-select-dropdown__trigger-chevron--open"
353
+ )
352
354
  }
353
355
  )
354
356
  ]
@@ -473,8 +475,10 @@ function SelectMulti({
473
475
  {
474
476
  glyph: "chevron-down",
475
477
  size: 14,
476
- className: "uxm-select-dropdown__trigger-chevron",
477
- style: { transform: open ? "rotate(180deg)" : "none" }
478
+ className: cn(
479
+ "uxm-select-dropdown__trigger-chevron",
480
+ open && "uxm-select-dropdown__trigger-chevron--open"
481
+ )
478
482
  }
479
483
  )
480
484
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/input/input.tsx"],"sourcesContent":["import {\n Children,\n isValidElement,\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n type SelectHTMLAttributes,\n type TextareaHTMLAttributes,\n} from 'react';\n\nimport { cn, mergeDescribedBy, mergeRefs } from '@/helpers';\n\nimport { ButtonGhost } from '../button';\nimport { FieldError } from '../field-error';\nimport { Icon } from '../icon';\nimport { IconButton } from '../icon-button';\nimport { DEFAULT_MULTI_REQUIRED_MESSAGE, Listbox, MultiListbox } from '../listbox';\n\nimport { clearFieldValue } from './clear-field-value';\n\nexport interface TextInputProps extends InputHTMLAttributes<HTMLInputElement> {\n /**\n * When set to a non-empty string, the field renders in its error state:\n * red border (`.uxm-input-text--error`), `aria-invalid`, and the message\n * rendered below the input. Omit (or pass an empty string) for the normal\n * state. The atom owns the message so it works standalone — search bars,\n * inline edits, custom layouts — without requiring a `FormField` wrapper.\n */\n error?: string;\n /**\n * Show a clear (✕) button at the trailing edge when the input has content.\n * **Defaults to `true`** — a free-text field is always safe to clear (you\n * can type/delete anyway), so the affordance is on by default; pass\n * `clearable={false}` to opt out. The ✕ self-clears (resets the field and\n * fires `onChange` with \"\"), so no `onClear` is needed — any controlled\n * `value` + `onChange` usage gets it for free.\n */\n clearable?: boolean;\n /**\n * Optional override for the clear action. By default the field clears\n * itself (and notifies via `onChange`); pass `onClear` only when you need\n * custom reset logic beyond emptying the value.\n */\n onClear?: () => void;\n /** Accessible name for the clear button. Default `\"Clear\"`. */\n clearLabel?: string;\n /**\n * Handle to the underlying `<input>` element, merged with the atom's own\n * internal ref (the self-clear keeps working). Use this to focus, select,\n * measure, or insert text at the caret from a consumer. A plain React `ref`\n * on `<TextInput>` does NOT reach the element — it's consumed by `{...rest}`\n * and overridden by the managed ref — so pass `inputRef` instead.\n */\n inputRef?: Ref<HTMLInputElement>;\n}\n\n\nexport function TextInput({\n className,\n type = 'text',\n error,\n clearable = true,\n onClear,\n clearLabel = 'Clear',\n value,\n defaultValue,\n onChange,\n disabled,\n inputRef,\n ...rest\n}: TextInputProps) {\n const errorId = useId();\n const innerRef = useRef<HTMLInputElement>(null);\n const isControlled = value !== undefined;\n const [hasTextUncontrolled, setHasTextUncontrolled] = useState(\n () => typeof defaultValue === 'string' && defaultValue.length > 0,\n );\n const hasValue = isControlled ? String(value).length > 0 : hasTextUncontrolled;\n const showClear = !!clearable && hasValue && !disabled;\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setHasTextUncontrolled(e.target.value.length > 0);\n onChange?.(e);\n };\n const handleClear = () => {\n // Self-clear path (clearFieldValue) already refocuses the field; only the\n // onClear-override path needs an explicit focus. Avoids a double focus().\n if (onClear) {\n onClear();\n innerRef.current?.focus();\n } else {\n clearFieldValue(innerRef.current);\n }\n if (!isControlled) setHasTextUncontrolled(false);\n };\n\n // Merge the consumer's `inputRef` with the atom's `innerRef` (the self-clear\n // relies on `innerRef`), so both get the element. Memoised on `inputRef` so\n // the callback identity is stable and React doesn't detach/reattach.\n const setInputRef = useMemo(() => mergeRefs(innerRef, inputRef), [inputRef]);\n\n const input = (\n // `{...rest}` is spread FIRST so the managed props below always win — a raw\n // consumer `ref` can't clobber the merged ref (which the self-clear relies\n // on); the sanctioned handle is `inputRef`, merged in via `setInputRef`.\n // `defaultValue` is only forwarded when uncontrolled, so value+defaultValue\n // are never both set.\n <input\n {...rest}\n ref={setInputRef}\n type={type}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n disabled={disabled}\n className={cn(\n 'uxm-input-text',\n error && 'uxm-input-text--error',\n clearable && 'uxm-input-text--clearable',\n className,\n )}\n aria-invalid={error ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], error ? errorId : undefined)}\n />\n );\n\n return (\n <>\n {clearable ? (\n // Layout-only wrapper so the clear button can sit absolutely at the\n // trailing edge. The visible chrome stays on `.uxm-input-text` (the\n // input itself), so save-emitted `--uxm-input-text-*` vars still land.\n <div className=\"uxm-input-text__wrap\">\n {input}\n {showClear && (\n <IconButton\n onClick={handleClear}\n className=\"uxm-field-clear uxm-input-text__clear\"\n aria-label={clearLabel}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n </div>\n ) : (\n input\n )}\n {error && (\n <FieldError id={errorId} className=\"uxm-input-text__error-message\">\n {error}\n </FieldError>\n )}\n </>\n );\n}\n// Static marker so FormField only forwards its `error` prop into children\n// that accept one (avoids React unknown-prop warnings on non-input children).\nTextInput.hasError = true;\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** See `TextInputProps.error`. */\n error?: string;\n /** See `TextInputProps.clearable`. Defaults to `true`; ✕ sits at the top-right corner. */\n clearable?: boolean;\n /** See `TextInputProps.onClear` — optional override; the field self-clears otherwise. */\n onClear?: () => void;\n /** See `TextInputProps.clearLabel`. Default `\"Clear\"`. */\n clearLabel?: string;\n /**\n * Handle to the underlying `<textarea>` element, merged with the atom's own\n * internal ref (the self-clear keeps working). Use it to focus, select, or\n * insert text at the caret (e.g. drop-a-variable-into-a-formula). A plain\n * React `ref` on `<Textarea>` does NOT reach the element — pass\n * `textareaRef` instead.\n */\n textareaRef?: Ref<HTMLTextAreaElement>;\n}\n\nexport function Textarea({\n className,\n error,\n clearable = true,\n onClear,\n clearLabel = 'Clear',\n value,\n defaultValue,\n onChange,\n disabled,\n textareaRef,\n ...rest\n}: TextareaProps) {\n const errorId = useId();\n const innerRef = useRef<HTMLTextAreaElement>(null);\n const isControlled = value !== undefined;\n const [hasTextUncontrolled, setHasTextUncontrolled] = useState(\n () => typeof defaultValue === 'string' && defaultValue.length > 0,\n );\n const hasValue = isControlled ? String(value).length > 0 : hasTextUncontrolled;\n const showClear = !!clearable && hasValue && !disabled;\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setHasTextUncontrolled(e.target.value.length > 0);\n onChange?.(e);\n };\n const handleClear = () => {\n // See TextInput: clearFieldValue refocuses; only onClear needs explicit focus.\n if (onClear) {\n onClear();\n innerRef.current?.focus();\n } else {\n clearFieldValue(innerRef.current);\n }\n if (!isControlled) setHasTextUncontrolled(false);\n };\n\n // Merge the consumer's `textareaRef` with the atom's `innerRef` — see TextInput.\n const setTextareaRef = useMemo(() => mergeRefs(innerRef, textareaRef), [textareaRef]);\n\n const textarea = (\n // `{...rest}` first so managed props win; the sanctioned element handle is\n // `textareaRef`, merged in via `setTextareaRef`. `defaultValue` only when\n // uncontrolled — never both value+defaultValue.\n <textarea\n {...rest}\n ref={setTextareaRef}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n disabled={disabled}\n className={cn(\n 'uxm-textarea',\n error && 'uxm-textarea--error',\n clearable && 'uxm-textarea--clearable',\n className,\n )}\n aria-invalid={error ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], error ? errorId : undefined)}\n />\n );\n\n return (\n <>\n {clearable ? (\n <div className=\"uxm-textarea__wrap\">\n {textarea}\n {showClear && (\n <IconButton\n onClick={handleClear}\n className=\"uxm-field-clear uxm-textarea__clear\"\n aria-label={clearLabel}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n </div>\n ) : (\n textarea\n )}\n {error && (\n <FieldError id={errorId} className=\"uxm-textarea__error-message\">\n {error}\n </FieldError>\n )}\n </>\n );\n}\nTextarea.hasError = true;\n\n/**\n * Native `<select>` attributes the atom still accepts verbatim. The five\n * omitted keys are the ones `mode` re-shapes: `value` / `defaultValue` /\n * `onChange` differ per mode, `required` gains its own message prop, and\n * `multiple` is replaced by `mode=\"multi\"`. Keeping this base means existing\n * `<Select onBlur={…} autoFocus data-testid={…}>` call sites — and any\n * `Omit<SelectProps, …>` in consumer code — keep compiling.\n */\ntype SelectNativeProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n 'value' | 'defaultValue' | 'onChange' | 'required' | 'multiple'\n>;\n\n/** Props shared by both single- and multi-select modes. */\ninterface SelectCommonProps extends SelectNativeProps {\n /** `<option>` children — parsed into items (and a placeholder from `<option value=\"\" disabled>`). */\n children?: ReactNode;\n /**\n * When set to a non-empty string, the trigger renders in its error\n * state: red border (`.uxm-select-dropdown--error`), `aria-invalid` on\n * the combobox, and the message below the trigger. Omit (or pass an\n * empty string) for the normal state.\n */\n error?: string;\n /**\n * Whether the dropdown panel includes a search box. Forwarded to the\n * internal Listbox: `true`/`false` force it, `\"auto\"` (the default)\n * shows it only once the option count crosses the shared threshold —\n * short lists stay a plain picker, long ones become filterable, with no\n * change to the trigger. (For a search-first combobox with its own\n * trigger chrome — icon glyphs, dial codes — use SearchDropdown.)\n */\n searchable?: boolean | 'auto';\n /**\n * Require a selection. Clearing to empty is still allowed (input-family,\n * live model) but flags the error immediately. An explicit `error` prop\n * takes precedence. Single mode is only clearable with a placeholder\n * option; multi mode uses `clearable`.\n */\n required?: boolean;\n /**\n * Override the default required message. Defaults are per-mode:\n * single → `\"Select an option\"`, multi → `\"Select at least one option\"`\n * (the shared `DEFAULT_MULTI_REQUIRED_MESSAGE`).\n */\n requiredMessage?: string;\n /**\n * Accessible name for the trigger's clear button. Defaults are per-mode:\n * single → `\"Clear selection\"`, multi → `\"Clear all selections\"`.\n */\n clearLabel?: string;\n}\n\nexport interface SelectSingleProps extends SelectCommonProps {\n /** Single-choice (default) — one value, cleared only when a placeholder option exists. */\n mode?: 'single';\n value?: string;\n defaultValue?: string;\n /** Fires a synthesized `ChangeEvent` (native-`<select>`-compatible) so `e.target.value` works. */\n onChange?: (event: ChangeEvent<HTMLSelectElement>) => void;\n}\n\nexport interface SelectMultiProps extends SelectCommonProps {\n /** Multi-choice — an array value with a \"N selected\" trigger, live commit, checkbox rows. */\n mode: 'multi';\n value?: string[];\n defaultValue?: string[];\n /** Fires the full selected-value array on every toggle (live). */\n onChange?: (next: string[]) => void;\n /** Show a clear-all ✕ on the trigger AND a \"Clear all\" in the panel. */\n clearable?: boolean;\n}\n\nexport type SelectProps = SelectSingleProps | SelectMultiProps;\n\ninterface SelectItem {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n/**\n * Parse `<option>` children into Listbox-friendly items. HTML semantics:\n * - `<option value=\"x\">Label</option>` → value \"x\", label \"Label\"\n * - `<option>Label</option>` → value \"Label\", label \"Label\" (label IS the value)\n * - `<option value=\"\" disabled>Placeholder</option>` → reserved as the\n * trigger placeholder text, not added to items (matches the common\n * React Select pattern).\n */\nfunction parseSelectOptions(children: ReactNode): {\n items: SelectItem[];\n placeholder: string | undefined;\n} {\n const items: SelectItem[] = [];\n let placeholder: string | undefined;\n\n Children.forEach(children, (child) => {\n if (\n !isValidElement<{\n value?: string | number;\n children?: ReactNode;\n disabled?: boolean;\n }>(child)\n ) {\n return;\n }\n if (child.type !== 'option') return;\n\n const text = String(child.props.children ?? '');\n const val = child.props.value !== undefined ? String(child.props.value) : text;\n const label = text || val;\n const disabled = child.props.disabled ?? false;\n\n if (val === '' && disabled && placeholder === undefined) {\n placeholder = label;\n return;\n }\n items.push({ value: val, label, disabled });\n });\n\n return { items, placeholder };\n}\n\n/**\n * Select Dropdown — internally a Listbox-backed picker. Its public\n * API stays compatible with the previous native-`<select>` shape:\n * pass `<option>` children, controlled (`value`) or uncontrolled\n * (`defaultValue`) state, and an `onChange(e)` handler that reads\n * `e.target.value`.\n *\n * The visible trigger keeps the same `.uxm-select-dropdown` class\n * (and all its registry-tuned visual chrome — bg, border, radius,\n * padding, font, per-state colors). The OPEN-state UI swaps from the\n * browser's native dropdown to a `<Listbox>` panel so it looks\n * identical across browsers and inherits the shared panel theming\n * from the `listbox` registry entry.\n *\n * `onChange` receives a synthetic `ChangeEvent` shape — most React\n * callers only read `e.target.value`, which is set correctly. For\n * new code, consider using `<Listbox>` directly with its native\n * `(item: T | null) => void` callback.\n */\nfunction SelectSingle({\n className,\n children,\n value,\n defaultValue,\n onChange,\n disabled,\n style,\n name,\n id,\n error,\n searchable = 'auto',\n required = false,\n requiredMessage,\n clearLabel = 'Clear selection',\n 'aria-label': ariaLabel,\n ...rest\n}: SelectSingleProps) {\n const errorId = useId();\n // Required is flagged (not blocked) on clear — input-family live model.\n // An explicit `error` prop wins over the internal required one.\n const [reqError, setReqError] = useState<string | null>(null);\n const shownError = error ?? reqError ?? undefined;\n // Uncontrolled state — only used when `value` is not provided. Matches\n // the native `<select>`'s controlled/uncontrolled duality.\n const [internal, setInternal] = useState<string>(() => String(defaultValue ?? ''));\n const isControlled = value !== undefined;\n const current = String(isControlled ? value : internal);\n\n const { items, placeholder } = useMemo(() => parseSelectOptions(children), [children]);\n const selected = useMemo(() => items.find((o) => o.value === current) ?? null, [items, current]);\n\n const commit = useCallback(\n (nextValue: string) => {\n if (!isControlled) setInternal(nextValue);\n if (required) setReqError(nextValue === '' ? (requiredMessage ?? 'Select an option') : null);\n if (onChange) {\n // Synthesize a ChangeEvent so callers using\n // `onChange={(e) => set(e.target.value)}` keep working. Listbox\n // doesn't fire native events; we fabricate the minimum surface\n // most React callers actually read (`target.value`,\n // `currentTarget.value`, `type`, `name`).\n const target = { value: nextValue, name } as unknown as EventTarget & HTMLSelectElement;\n const event = {\n target,\n currentTarget: target,\n type: 'change',\n bubbles: true,\n cancelable: false,\n defaultPrevented: false,\n preventDefault() {},\n stopPropagation() {},\n isDefaultPrevented: () => false,\n isPropagationStopped: () => false,\n persist() {},\n timeStamp: 0,\n nativeEvent: {} as Event,\n } as unknown as ChangeEvent<HTMLSelectElement>;\n onChange(event);\n }\n },\n [isControlled, onChange, name, required, requiredMessage],\n );\n\n return (\n <>\n <Listbox<SelectItem>\n items={items}\n getKey={(o) => o.value}\n getLabel={(o) => o.label}\n value={selected}\n onChange={(next) => {\n // Listbox's onChange is `(T | null) => void` to support\n // consumer-driven clearing. Select doesn't expose a clear\n // affordance — defensive ignore if null arrives.\n if (next) commit(next.value);\n }}\n isItemDisabled={(o) => o.disabled}\n disabled={disabled}\n searchable={searchable}\n aria-label={ariaLabel}\n // Clear inside the panel (input-family convention: clear on the trigger\n // AND in the dropdown). Shown when a value is picked and the field can be\n // empty (has a placeholder option). Mirrors the trailing ✕ on the trigger.\n footer={selected && placeholder !== undefined && !disabled\n ? ({ close }: { close: () => void }) => (\n <ButtonGhost\n className=\"uxm-listbox__footer-clear-option\"\n onClick={() => { commit(''); close(); }}\n >\n <Icon glyph=\"close\" size={12} />\n Clear\n </ButtonGhost>\n )\n : undefined}\n renderTrigger={({ open, triggerProps }) => (\n // Trigger uses `<div role=\"combobox\">` — gives us a focusable\n // surface that can carry the same `.uxm-select-dropdown` chrome\n // the native `<select>` had. `aria-disabled` drives the disabled\n // visual (CSS targets the attribute since `<div>` doesn't honor\n // `:disabled`).\n // `rest` = the leftover native-select attributes (`onBlur`, `autoFocus`,\n // `form`, `data-*`, …). It goes FIRST so `triggerProps` and the atom's\n // own props always win; the cast only bridges the element generic —\n // the trigger is a `<div>`, not a `<select>`.\n // eslint-disable-next-line jsx-a11y/role-has-required-aria-props -- aria-expanded (always) and aria-controls (while open) arrive via the triggerProps spread; the rule can't see through it\n <div role=\"combobox\"\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...triggerProps}\n tabIndex={disabled ? -1 : 0}\n // The trigger is what lands in the tab order, so it needs the name.\n // `aria-label` is destructured out of `rest` above and forwarded to\n // the Listbox, which puts it on the popup panel — naming the popup,\n // not the control. A `<div role=\"combobox\">` also can't be named by a\n // wrapping `<label>` (a div isn't labelable), so without this the\n // control announces as an unnamed combobox.\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={shownError ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], shownError ? errorId : undefined)}\n id={id}\n style={style}\n className={cn(\n 'uxm-select-dropdown',\n open && 'uxm-select-dropdown--open',\n shownError && 'uxm-select-dropdown--error',\n className,\n )}\n >\n <span\n className={cn(\n 'uxm-select-dropdown__trigger-label',\n !selected && 'uxm-select-dropdown__trigger-label--empty',\n )}\n >\n {selected ? selected.label : (placeholder ?? '')}\n </span>\n {/* Clear ✕ shows only when the field CAN be empty — i.e. it has a\n placeholder option (`<option value=\"\" disabled>`), which stands\n for the \"no selection\" state. A select without a placeholder is\n mandatory (a value is always picked, native-<select> style), so\n clearing to empty makes no sense and no ✕ is rendered. */}\n {selected && !disabled && placeholder !== undefined && (\n <IconButton\n aria-label={clearLabel}\n onClick={(e) => {\n // Stop click from bubbling to the trigger div (which\n // would toggle the popover back open).\n e.stopPropagation();\n commit('');\n }}\n onMouseDown={(e) => {\n // Stop mousedown too — the atom's Popover wires its\n // click-outside detection to mousedown.\n e.stopPropagation();\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.stopPropagation();\n }\n }}\n className=\"uxm-field-clear uxm-select-dropdown__trigger-clear\"\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n <Icon\n glyph=\"chevron-down\"\n size={14}\n className=\"uxm-select-dropdown__trigger-chevron\"\n style={{ transform: open ? 'rotate(180deg)' : 'none' }}\n />\n </div>\n )}\n renderItem={(o) => o.label}\n />\n {shownError && (\n <FieldError id={errorId} className=\"uxm-select-dropdown__error-message\">\n {shownError}\n </FieldError>\n )}\n </>\n );\n}\n\n/**\n * Multi-select mode — same `.uxm-select-dropdown` trigger chrome as single,\n * but backed by MultiListbox: an array value, a \"N selected\" trigger, checkbox\n * rows, live commit, and (input-family) a clear ✕ on the trigger AND in the\n * panel. Required flags an empty selection without blocking.\n */\nfunction SelectMulti({\n className,\n children,\n value,\n defaultValue,\n onChange,\n disabled,\n style,\n id,\n error,\n searchable = 'auto',\n required = false,\n requiredMessage,\n clearable = false,\n clearLabel = 'Clear all selections',\n 'aria-label': ariaLabel,\n ...rest\n}: SelectMultiProps) {\n const errorId = useId();\n const [reqError, setReqError] = useState<string | null>(null);\n const shownError = error ?? reqError ?? undefined;\n const [internal, setInternal] = useState<string[]>(() => defaultValue ?? []);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const { items, placeholder } = useMemo(() => parseSelectOptions(children), [children]);\n const selectedItems = useMemo(\n () => items.filter((o) => current.includes(o.value)),\n [items, current],\n );\n\n const commit = useCallback(\n (next: string[]) => {\n if (!isControlled) setInternal(next);\n if (required) {\n setReqError(next.length === 0 ? (requiredMessage ?? DEFAULT_MULTI_REQUIRED_MESSAGE) : null);\n }\n onChange?.(next);\n },\n [isControlled, onChange, required, requiredMessage],\n );\n\n return (\n <>\n <MultiListbox<SelectItem>\n items={items}\n getKey={(o) => o.value}\n getLabel={(o) => o.label}\n value={selectedItems}\n onChange={(next) => commit(next.map((o) => o.value))}\n // Relies on MultiListbox's default `commitMode=\"change\"` — the\n // \"N selected\" count has to track each toggle.\n isItemDisabled={(o) => o.disabled}\n disabled={disabled}\n searchable={searchable}\n aria-label={ariaLabel}\n footer={clearable\n ? ({ clear, selected }) =>\n selected.length > 0 ? (\n <ButtonGhost className=\"uxm-listbox__footer-clear-option\" onClick={clear}>\n <Icon glyph=\"close\" size={12} />\n Clear all\n </ButtonGhost>\n ) : null\n : undefined}\n renderTrigger={({ open, triggerProps }) => (\n // `rest` (leftover native-select attributes) goes first so\n // `triggerProps` and the atom's own props win — see SelectSingle.\n // eslint-disable-next-line jsx-a11y/role-has-required-aria-props -- aria-expanded/controls arrive via the triggerProps spread\n <div role=\"combobox\"\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...triggerProps}\n tabIndex={disabled ? -1 : 0}\n // Names the control itself, not just the popup — see SelectSingle.\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={shownError ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], shownError ? errorId : undefined)}\n id={id}\n style={style}\n className={cn(\n 'uxm-select-dropdown',\n open && 'uxm-select-dropdown--open',\n shownError && 'uxm-select-dropdown--error',\n className,\n )}\n >\n <span\n className={cn(\n 'uxm-select-dropdown__trigger-label',\n current.length === 0 && 'uxm-select-dropdown__trigger-label--empty',\n )}\n >\n {current.length === 0 ? (placeholder ?? '') : `${current.length} selected`}\n </span>\n {clearable && current.length > 0 && !disabled && (\n <IconButton\n aria-label={clearLabel}\n className=\"uxm-field-clear uxm-select-dropdown__trigger-clear\"\n onClick={(e) => { e.stopPropagation(); commit([]); }}\n onMouseDown={(e) => e.stopPropagation()}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') e.stopPropagation(); }}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n <Icon\n glyph=\"chevron-down\"\n size={14}\n className=\"uxm-select-dropdown__trigger-chevron\"\n style={{ transform: open ? 'rotate(180deg)' : 'none' }}\n />\n </div>\n )}\n renderItem={(o) => o.label}\n />\n {shownError && (\n <FieldError id={errorId} className=\"uxm-select-dropdown__error-message\">\n {shownError}\n </FieldError>\n )}\n </>\n );\n}\n\n/**\n * Select dropdown atom. `mode=\"single\"` (default) picks one value;\n * `mode=\"multi\"` picks an array. Both share the same trigger chrome and\n * `<option>` children API — only the value/onChange shape differs.\n */\nexport function Select(props: SelectProps) {\n return props.mode === 'multi' ? <SelectMulti {...props} /> : <SelectSingle {...props} />;\n}\nSelect.hasError = true;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/input/input.tsx"],"sourcesContent":["import {\n Children,\n isValidElement,\n useCallback,\n useId,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type HTMLAttributes,\n type InputHTMLAttributes,\n type ReactNode,\n type Ref,\n type SelectHTMLAttributes,\n type TextareaHTMLAttributes,\n} from 'react';\n\nimport { cn, mergeDescribedBy, mergeRefs } from '@/helpers';\n\nimport { ButtonGhost } from '../button';\nimport { FieldError } from '../field-error';\nimport { Icon } from '../icon';\nimport { IconButton } from '../icon-button';\nimport { DEFAULT_MULTI_REQUIRED_MESSAGE, Listbox, MultiListbox } from '../listbox';\n\nimport { clearFieldValue } from './clear-field-value';\n\nexport interface TextInputProps extends InputHTMLAttributes<HTMLInputElement> {\n /**\n * When set to a non-empty string, the field renders in its error state:\n * red border (`.uxm-input-text--error`), `aria-invalid`, and the message\n * rendered below the input. Omit (or pass an empty string) for the normal\n * state. The atom owns the message so it works standalone — search bars,\n * inline edits, custom layouts — without requiring a `FormField` wrapper.\n */\n error?: string;\n /**\n * Show a clear (✕) button at the trailing edge when the input has content.\n * **Defaults to `true`** — a free-text field is always safe to clear (you\n * can type/delete anyway), so the affordance is on by default; pass\n * `clearable={false}` to opt out. The ✕ self-clears (resets the field and\n * fires `onChange` with \"\"), so no `onClear` is needed — any controlled\n * `value` + `onChange` usage gets it for free.\n */\n clearable?: boolean;\n /**\n * Optional override for the clear action. By default the field clears\n * itself (and notifies via `onChange`); pass `onClear` only when you need\n * custom reset logic beyond emptying the value.\n */\n onClear?: () => void;\n /** Accessible name for the clear button. Default `\"Clear\"`. */\n clearLabel?: string;\n /**\n * Handle to the underlying `<input>` element, merged with the atom's own\n * internal ref (the self-clear keeps working). Use this to focus, select,\n * measure, or insert text at the caret from a consumer. A plain React `ref`\n * on `<TextInput>` does NOT reach the element — it's consumed by `{...rest}`\n * and overridden by the managed ref — so pass `inputRef` instead.\n */\n inputRef?: Ref<HTMLInputElement>;\n}\n\n\nexport function TextInput({\n className,\n type = 'text',\n error,\n clearable = true,\n onClear,\n clearLabel = 'Clear',\n value,\n defaultValue,\n onChange,\n disabled,\n inputRef,\n ...rest\n}: TextInputProps) {\n const errorId = useId();\n const innerRef = useRef<HTMLInputElement>(null);\n const isControlled = value !== undefined;\n const [hasTextUncontrolled, setHasTextUncontrolled] = useState(\n () => typeof defaultValue === 'string' && defaultValue.length > 0,\n );\n const hasValue = isControlled ? String(value).length > 0 : hasTextUncontrolled;\n const showClear = !!clearable && hasValue && !disabled;\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n if (!isControlled) setHasTextUncontrolled(e.target.value.length > 0);\n onChange?.(e);\n };\n const handleClear = () => {\n // Self-clear path (clearFieldValue) already refocuses the field; only the\n // onClear-override path needs an explicit focus. Avoids a double focus().\n if (onClear) {\n onClear();\n innerRef.current?.focus();\n } else {\n clearFieldValue(innerRef.current);\n }\n if (!isControlled) setHasTextUncontrolled(false);\n };\n\n // Merge the consumer's `inputRef` with the atom's `innerRef` (the self-clear\n // relies on `innerRef`), so both get the element. Memoised on `inputRef` so\n // the callback identity is stable and React doesn't detach/reattach.\n const setInputRef = useMemo(() => mergeRefs(innerRef, inputRef), [inputRef]);\n\n const input = (\n // `{...rest}` is spread FIRST so the managed props below always win — a raw\n // consumer `ref` can't clobber the merged ref (which the self-clear relies\n // on); the sanctioned handle is `inputRef`, merged in via `setInputRef`.\n // `defaultValue` is only forwarded when uncontrolled, so value+defaultValue\n // are never both set.\n <input\n {...rest}\n ref={setInputRef}\n type={type}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n disabled={disabled}\n className={cn(\n 'uxm-input-text',\n error && 'uxm-input-text--error',\n clearable && 'uxm-input-text--clearable',\n className,\n )}\n aria-invalid={error ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], error ? errorId : undefined)}\n />\n );\n\n return (\n <>\n {clearable ? (\n // Layout-only wrapper so the clear button can sit absolutely at the\n // trailing edge. The visible chrome stays on `.uxm-input-text` (the\n // input itself), so save-emitted `--uxm-input-text-*` vars still land.\n <div className=\"uxm-input-text__wrap\">\n {input}\n {showClear && (\n <IconButton\n onClick={handleClear}\n className=\"uxm-field-clear uxm-input-text__clear\"\n aria-label={clearLabel}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n </div>\n ) : (\n input\n )}\n {error && (\n <FieldError id={errorId} className=\"uxm-input-text__error-message\">\n {error}\n </FieldError>\n )}\n </>\n );\n}\n// Static marker so FormField only forwards its `error` prop into children\n// that accept one (avoids React unknown-prop warnings on non-input children).\nTextInput.hasError = true;\n\nexport interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** See `TextInputProps.error`. */\n error?: string;\n /** See `TextInputProps.clearable`. Defaults to `true`; ✕ sits at the top-right corner. */\n clearable?: boolean;\n /** See `TextInputProps.onClear` — optional override; the field self-clears otherwise. */\n onClear?: () => void;\n /** See `TextInputProps.clearLabel`. Default `\"Clear\"`. */\n clearLabel?: string;\n /**\n * Handle to the underlying `<textarea>` element, merged with the atom's own\n * internal ref (the self-clear keeps working). Use it to focus, select, or\n * insert text at the caret (e.g. drop-a-variable-into-a-formula). A plain\n * React `ref` on `<Textarea>` does NOT reach the element — pass\n * `textareaRef` instead.\n */\n textareaRef?: Ref<HTMLTextAreaElement>;\n}\n\nexport function Textarea({\n className,\n error,\n clearable = true,\n onClear,\n clearLabel = 'Clear',\n value,\n defaultValue,\n onChange,\n disabled,\n textareaRef,\n ...rest\n}: TextareaProps) {\n const errorId = useId();\n const innerRef = useRef<HTMLTextAreaElement>(null);\n const isControlled = value !== undefined;\n const [hasTextUncontrolled, setHasTextUncontrolled] = useState(\n () => typeof defaultValue === 'string' && defaultValue.length > 0,\n );\n const hasValue = isControlled ? String(value).length > 0 : hasTextUncontrolled;\n const showClear = !!clearable && hasValue && !disabled;\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setHasTextUncontrolled(e.target.value.length > 0);\n onChange?.(e);\n };\n const handleClear = () => {\n // See TextInput: clearFieldValue refocuses; only onClear needs explicit focus.\n if (onClear) {\n onClear();\n innerRef.current?.focus();\n } else {\n clearFieldValue(innerRef.current);\n }\n if (!isControlled) setHasTextUncontrolled(false);\n };\n\n // Merge the consumer's `textareaRef` with the atom's `innerRef` — see TextInput.\n const setTextareaRef = useMemo(() => mergeRefs(innerRef, textareaRef), [textareaRef]);\n\n const textarea = (\n // `{...rest}` first so managed props win; the sanctioned element handle is\n // `textareaRef`, merged in via `setTextareaRef`. `defaultValue` only when\n // uncontrolled — never both value+defaultValue.\n <textarea\n {...rest}\n ref={setTextareaRef}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n onChange={handleChange}\n disabled={disabled}\n className={cn(\n 'uxm-textarea',\n error && 'uxm-textarea--error',\n clearable && 'uxm-textarea--clearable',\n className,\n )}\n aria-invalid={error ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], error ? errorId : undefined)}\n />\n );\n\n return (\n <>\n {clearable ? (\n <div className=\"uxm-textarea__wrap\">\n {textarea}\n {showClear && (\n <IconButton\n onClick={handleClear}\n className=\"uxm-field-clear uxm-textarea__clear\"\n aria-label={clearLabel}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n </div>\n ) : (\n textarea\n )}\n {error && (\n <FieldError id={errorId} className=\"uxm-textarea__error-message\">\n {error}\n </FieldError>\n )}\n </>\n );\n}\nTextarea.hasError = true;\n\n/**\n * Native `<select>` attributes the atom still accepts verbatim. The five\n * omitted keys are the ones `mode` re-shapes: `value` / `defaultValue` /\n * `onChange` differ per mode, `required` gains its own message prop, and\n * `multiple` is replaced by `mode=\"multi\"`. Keeping this base means existing\n * `<Select onBlur={…} autoFocus data-testid={…}>` call sites — and any\n * `Omit<SelectProps, …>` in consumer code — keep compiling.\n */\ntype SelectNativeProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n 'value' | 'defaultValue' | 'onChange' | 'required' | 'multiple'\n>;\n\n/** Props shared by both single- and multi-select modes. */\ninterface SelectCommonProps extends SelectNativeProps {\n /** `<option>` children — parsed into items (and a placeholder from `<option value=\"\" disabled>`). */\n children?: ReactNode;\n /**\n * When set to a non-empty string, the trigger renders in its error\n * state: red border (`.uxm-select-dropdown--error`), `aria-invalid` on\n * the combobox, and the message below the trigger. Omit (or pass an\n * empty string) for the normal state.\n */\n error?: string;\n /**\n * Whether the dropdown panel includes a search box. Forwarded to the\n * internal Listbox: `true`/`false` force it, `\"auto\"` (the default)\n * shows it only once the option count crosses the shared threshold —\n * short lists stay a plain picker, long ones become filterable, with no\n * change to the trigger. (For a search-first combobox with its own\n * trigger chrome — icon glyphs, dial codes — use SearchDropdown.)\n */\n searchable?: boolean | 'auto';\n /**\n * Require a selection. Clearing to empty is still allowed (input-family,\n * live model) but flags the error immediately. An explicit `error` prop\n * takes precedence. Single mode is only clearable with a placeholder\n * option; multi mode uses `clearable`.\n */\n required?: boolean;\n /**\n * Override the default required message. Defaults are per-mode:\n * single → `\"Select an option\"`, multi → `\"Select at least one option\"`\n * (the shared `DEFAULT_MULTI_REQUIRED_MESSAGE`).\n */\n requiredMessage?: string;\n /**\n * Accessible name for the trigger's clear button. Defaults are per-mode:\n * single → `\"Clear selection\"`, multi → `\"Clear all selections\"`.\n */\n clearLabel?: string;\n}\n\nexport interface SelectSingleProps extends SelectCommonProps {\n /** Single-choice (default) — one value, cleared only when a placeholder option exists. */\n mode?: 'single';\n value?: string;\n defaultValue?: string;\n /** Fires a synthesized `ChangeEvent` (native-`<select>`-compatible) so `e.target.value` works. */\n onChange?: (event: ChangeEvent<HTMLSelectElement>) => void;\n}\n\nexport interface SelectMultiProps extends SelectCommonProps {\n /** Multi-choice — an array value with a \"N selected\" trigger, live commit, checkbox rows. */\n mode: 'multi';\n value?: string[];\n defaultValue?: string[];\n /** Fires the full selected-value array on every toggle (live). */\n onChange?: (next: string[]) => void;\n /** Show a clear-all ✕ on the trigger AND a \"Clear all\" in the panel. */\n clearable?: boolean;\n}\n\nexport type SelectProps = SelectSingleProps | SelectMultiProps;\n\ninterface SelectItem {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n/**\n * Parse `<option>` children into Listbox-friendly items. HTML semantics:\n * - `<option value=\"x\">Label</option>` → value \"x\", label \"Label\"\n * - `<option>Label</option>` → value \"Label\", label \"Label\" (label IS the value)\n * - `<option value=\"\" disabled>Placeholder</option>` → reserved as the\n * trigger placeholder text, not added to items (matches the common\n * React Select pattern).\n */\nfunction parseSelectOptions(children: ReactNode): {\n items: SelectItem[];\n placeholder: string | undefined;\n} {\n const items: SelectItem[] = [];\n let placeholder: string | undefined;\n\n Children.forEach(children, (child) => {\n if (\n !isValidElement<{\n value?: string | number;\n children?: ReactNode;\n disabled?: boolean;\n }>(child)\n ) {\n return;\n }\n if (child.type !== 'option') return;\n\n const text = String(child.props.children ?? '');\n const val = child.props.value !== undefined ? String(child.props.value) : text;\n const label = text || val;\n const disabled = child.props.disabled ?? false;\n\n if (val === '' && disabled && placeholder === undefined) {\n placeholder = label;\n return;\n }\n items.push({ value: val, label, disabled });\n });\n\n return { items, placeholder };\n}\n\n/**\n * Select Dropdown — internally a Listbox-backed picker. Its public\n * API stays compatible with the previous native-`<select>` shape:\n * pass `<option>` children, controlled (`value`) or uncontrolled\n * (`defaultValue`) state, and an `onChange(e)` handler that reads\n * `e.target.value`.\n *\n * The visible trigger keeps the same `.uxm-select-dropdown` class\n * (and all its registry-tuned visual chrome — bg, border, radius,\n * padding, font, per-state colors). The OPEN-state UI swaps from the\n * browser's native dropdown to a `<Listbox>` panel so it looks\n * identical across browsers and inherits the shared panel theming\n * from the `listbox` registry entry.\n *\n * `onChange` receives a synthetic `ChangeEvent` shape — most React\n * callers only read `e.target.value`, which is set correctly. For\n * new code, consider using `<Listbox>` directly with its native\n * `(item: T | null) => void` callback.\n */\nfunction SelectSingle({\n className,\n children,\n value,\n defaultValue,\n onChange,\n disabled,\n style,\n name,\n id,\n error,\n searchable = 'auto',\n required = false,\n requiredMessage,\n clearLabel = 'Clear selection',\n 'aria-label': ariaLabel,\n ...rest\n}: SelectSingleProps) {\n const errorId = useId();\n // Required is flagged (not blocked) on clear — input-family live model.\n // An explicit `error` prop wins over the internal required one.\n const [reqError, setReqError] = useState<string | null>(null);\n const shownError = error ?? reqError ?? undefined;\n // Uncontrolled state — only used when `value` is not provided. Matches\n // the native `<select>`'s controlled/uncontrolled duality.\n const [internal, setInternal] = useState<string>(() => String(defaultValue ?? ''));\n const isControlled = value !== undefined;\n const current = String(isControlled ? value : internal);\n\n const { items, placeholder } = useMemo(() => parseSelectOptions(children), [children]);\n const selected = useMemo(() => items.find((o) => o.value === current) ?? null, [items, current]);\n\n const commit = useCallback(\n (nextValue: string) => {\n if (!isControlled) setInternal(nextValue);\n if (required) setReqError(nextValue === '' ? (requiredMessage ?? 'Select an option') : null);\n if (onChange) {\n // Synthesize a ChangeEvent so callers using\n // `onChange={(e) => set(e.target.value)}` keep working. Listbox\n // doesn't fire native events; we fabricate the minimum surface\n // most React callers actually read (`target.value`,\n // `currentTarget.value`, `type`, `name`).\n const target = { value: nextValue, name } as unknown as EventTarget & HTMLSelectElement;\n const event = {\n target,\n currentTarget: target,\n type: 'change',\n bubbles: true,\n cancelable: false,\n defaultPrevented: false,\n preventDefault() {},\n stopPropagation() {},\n isDefaultPrevented: () => false,\n isPropagationStopped: () => false,\n persist() {},\n timeStamp: 0,\n nativeEvent: {} as Event,\n } as unknown as ChangeEvent<HTMLSelectElement>;\n onChange(event);\n }\n },\n [isControlled, onChange, name, required, requiredMessage],\n );\n\n return (\n <>\n <Listbox<SelectItem>\n items={items}\n getKey={(o) => o.value}\n getLabel={(o) => o.label}\n value={selected}\n onChange={(next) => {\n // Listbox's onChange is `(T | null) => void` to support\n // consumer-driven clearing. Select doesn't expose a clear\n // affordance — defensive ignore if null arrives.\n if (next) commit(next.value);\n }}\n isItemDisabled={(o) => o.disabled}\n disabled={disabled}\n searchable={searchable}\n aria-label={ariaLabel}\n // Clear inside the panel (input-family convention: clear on the trigger\n // AND in the dropdown). Shown when a value is picked and the field can be\n // empty (has a placeholder option). Mirrors the trailing ✕ on the trigger.\n footer={selected && placeholder !== undefined && !disabled\n ? ({ close }: { close: () => void }) => (\n <ButtonGhost\n className=\"uxm-listbox__footer-clear-option\"\n onClick={() => { commit(''); close(); }}\n >\n <Icon glyph=\"close\" size={12} />\n Clear\n </ButtonGhost>\n )\n : undefined}\n renderTrigger={({ open, triggerProps }) => (\n // Trigger uses `<div role=\"combobox\">` — gives us a focusable\n // surface that can carry the same `.uxm-select-dropdown` chrome\n // the native `<select>` had. `aria-disabled` drives the disabled\n // visual (CSS targets the attribute since `<div>` doesn't honor\n // `:disabled`).\n // `rest` = the leftover native-select attributes (`onBlur`, `autoFocus`,\n // `form`, `data-*`, …). It goes FIRST so `triggerProps` and the atom's\n // own props always win; the cast only bridges the element generic —\n // the trigger is a `<div>`, not a `<select>`.\n // eslint-disable-next-line jsx-a11y/role-has-required-aria-props -- aria-expanded (always) and aria-controls (while open) arrive via the triggerProps spread; the rule can't see through it\n <div role=\"combobox\"\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...triggerProps}\n tabIndex={disabled ? -1 : 0}\n // The trigger is what lands in the tab order, so it needs the name.\n // `aria-label` is destructured out of `rest` above and forwarded to\n // the Listbox, which puts it on the popup panel — naming the popup,\n // not the control. A `<div role=\"combobox\">` also can't be named by a\n // wrapping `<label>` (a div isn't labelable), so without this the\n // control announces as an unnamed combobox.\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={shownError ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], shownError ? errorId : undefined)}\n id={id}\n style={style}\n className={cn(\n 'uxm-select-dropdown',\n open && 'uxm-select-dropdown--open',\n shownError && 'uxm-select-dropdown--error',\n className,\n )}\n >\n <span\n className={cn(\n 'uxm-select-dropdown__trigger-label',\n !selected && 'uxm-select-dropdown__trigger-label--empty',\n )}\n >\n {selected ? selected.label : (placeholder ?? '')}\n </span>\n {/* Clear ✕ shows only when the field CAN be empty — i.e. it has a\n placeholder option (`<option value=\"\" disabled>`), which stands\n for the \"no selection\" state. A select without a placeholder is\n mandatory (a value is always picked, native-<select> style), so\n clearing to empty makes no sense and no ✕ is rendered. */}\n {selected && !disabled && placeholder !== undefined && (\n <IconButton\n aria-label={clearLabel}\n onClick={(e) => {\n // Stop click from bubbling to the trigger div (which\n // would toggle the popover back open).\n e.stopPropagation();\n commit('');\n }}\n onMouseDown={(e) => {\n // Stop mousedown too — the atom's Popover wires its\n // click-outside detection to mousedown.\n e.stopPropagation();\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.stopPropagation();\n }\n }}\n className=\"uxm-field-clear uxm-select-dropdown__trigger-clear\"\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n <Icon\n glyph=\"chevron-down\"\n size={14}\n className={cn(\n 'uxm-select-dropdown__trigger-chevron',\n open && 'uxm-select-dropdown__trigger-chevron--open',\n )}\n />\n </div>\n )}\n renderItem={(o) => o.label}\n />\n {shownError && (\n <FieldError id={errorId} className=\"uxm-select-dropdown__error-message\">\n {shownError}\n </FieldError>\n )}\n </>\n );\n}\n\n/**\n * Multi-select mode — same `.uxm-select-dropdown` trigger chrome as single,\n * but backed by MultiListbox: an array value, a \"N selected\" trigger, checkbox\n * rows, live commit, and (input-family) a clear ✕ on the trigger AND in the\n * panel. Required flags an empty selection without blocking.\n */\nfunction SelectMulti({\n className,\n children,\n value,\n defaultValue,\n onChange,\n disabled,\n style,\n id,\n error,\n searchable = 'auto',\n required = false,\n requiredMessage,\n clearable = false,\n clearLabel = 'Clear all selections',\n 'aria-label': ariaLabel,\n ...rest\n}: SelectMultiProps) {\n const errorId = useId();\n const [reqError, setReqError] = useState<string | null>(null);\n const shownError = error ?? reqError ?? undefined;\n const [internal, setInternal] = useState<string[]>(() => defaultValue ?? []);\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const { items, placeholder } = useMemo(() => parseSelectOptions(children), [children]);\n const selectedItems = useMemo(\n () => items.filter((o) => current.includes(o.value)),\n [items, current],\n );\n\n const commit = useCallback(\n (next: string[]) => {\n if (!isControlled) setInternal(next);\n if (required) {\n setReqError(next.length === 0 ? (requiredMessage ?? DEFAULT_MULTI_REQUIRED_MESSAGE) : null);\n }\n onChange?.(next);\n },\n [isControlled, onChange, required, requiredMessage],\n );\n\n return (\n <>\n <MultiListbox<SelectItem>\n items={items}\n getKey={(o) => o.value}\n getLabel={(o) => o.label}\n value={selectedItems}\n onChange={(next) => commit(next.map((o) => o.value))}\n // Relies on MultiListbox's default `commitMode=\"change\"` — the\n // \"N selected\" count has to track each toggle.\n isItemDisabled={(o) => o.disabled}\n disabled={disabled}\n searchable={searchable}\n aria-label={ariaLabel}\n footer={clearable\n ? ({ clear, selected }) =>\n selected.length > 0 ? (\n <ButtonGhost className=\"uxm-listbox__footer-clear-option\" onClick={clear}>\n <Icon glyph=\"close\" size={12} />\n Clear all\n </ButtonGhost>\n ) : null\n : undefined}\n renderTrigger={({ open, triggerProps }) => (\n // `rest` (leftover native-select attributes) goes first so\n // `triggerProps` and the atom's own props win — see SelectSingle.\n // eslint-disable-next-line jsx-a11y/role-has-required-aria-props -- aria-expanded/controls arrive via the triggerProps spread\n <div role=\"combobox\"\n {...(rest as HTMLAttributes<HTMLDivElement>)}\n {...triggerProps}\n tabIndex={disabled ? -1 : 0}\n // Names the control itself, not just the popup — see SelectSingle.\n aria-label={ariaLabel}\n aria-disabled={disabled || undefined}\n aria-required={required || undefined}\n aria-invalid={shownError ? true : undefined}\n aria-describedby={mergeDescribedBy(rest['aria-describedby'], shownError ? errorId : undefined)}\n id={id}\n style={style}\n className={cn(\n 'uxm-select-dropdown',\n open && 'uxm-select-dropdown--open',\n shownError && 'uxm-select-dropdown--error',\n className,\n )}\n >\n <span\n className={cn(\n 'uxm-select-dropdown__trigger-label',\n current.length === 0 && 'uxm-select-dropdown__trigger-label--empty',\n )}\n >\n {current.length === 0 ? (placeholder ?? '') : `${current.length} selected`}\n </span>\n {clearable && current.length > 0 && !disabled && (\n <IconButton\n aria-label={clearLabel}\n className=\"uxm-field-clear uxm-select-dropdown__trigger-clear\"\n onClick={(e) => { e.stopPropagation(); commit([]); }}\n onMouseDown={(e) => e.stopPropagation()}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') e.stopPropagation(); }}\n >\n <Icon glyph=\"close\" />\n </IconButton>\n )}\n <Icon\n glyph=\"chevron-down\"\n size={14}\n className={cn(\n 'uxm-select-dropdown__trigger-chevron',\n open && 'uxm-select-dropdown__trigger-chevron--open',\n )}\n />\n </div>\n )}\n renderItem={(o) => o.label}\n />\n {shownError && (\n <FieldError id={errorId} className=\"uxm-select-dropdown__error-message\">\n {shownError}\n </FieldError>\n )}\n </>\n );\n}\n\n/**\n * Select dropdown atom. `mode=\"single\"` (default) picks one value;\n * `mode=\"multi\"` picks an array. Both share the same trigger chrome and\n * `<option>` children API — only the value/onChange shape differs.\n */\nexport function Select(props: SelectProps) {\n return props.mode === 'multi' ? <SelectMulti {...props} /> : <SelectSingle {...props} />;\n}\nSelect.hasError = true;\n"],"mappings":"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","names":[]}
@@ -50,7 +50,7 @@ function StatCard({
50
50
  glyph: "arrow-up",
51
51
  size: 12,
52
52
  strokeWidth: 2.5,
53
- style: { transform: trendDirection === "down" ? "rotate(180deg)" : void 0 }
53
+ className: "uxm-stat-card__trend-icon"
54
54
  }
55
55
  ),
56
56
  trend
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/stat-card/stat-card.tsx"],"sourcesContent":["import { cn } from '@/helpers';\nimport { Icon } from '@/ui/icon';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type StatCardTrend = 'up' | 'down' | 'neutral';\n\nexport interface StatCardProps extends HTMLAttributes<HTMLDivElement> {\n label: ReactNode;\n value: ReactNode;\n trend?: ReactNode;\n trendDirection?: StatCardTrend;\n}\n\nexport function StatCard({\n label,\n value,\n trend,\n trendDirection = 'neutral',\n className,\n ...rest\n}: StatCardProps) {\n return (\n <div className={cn('uxm-stat-card', className)} {...rest}>\n <p className=\"uxm-stat-card__label\">{label}</p>\n <div className=\"uxm-stat-card__row\">\n <span className=\"uxm-stat-card__value\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'uxm-stat-card__trend',\n `uxm-stat-card__trend--${trendDirection}`,\n )}\n >\n {trendDirection !== 'neutral' && (\n <Icon\n glyph=\"arrow-up\"\n size={12}\n strokeWidth={2.5}\n style={{ transform: trendDirection === 'down' ? 'rotate(180deg)' : undefined }}\n />\n )}\n {trend}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBM;AAxBN,qBAAmB;AACnB,kBAAqB;AAad,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,SACE,6CAAC,SAAI,eAAW,mBAAG,iBAAiB,SAAS,GAAI,GAAG,MAClD;AAAA,gDAAC,OAAE,WAAU,wBAAwB,iBAAM;AAAA,IAC3C,6CAAC,SAAI,WAAU,sBACb;AAAA,kDAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,MAC7C,SACC;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,YACT;AAAA,YACA,yBAAyB,cAAc;AAAA,UACzC;AAAA,UAEC;AAAA,+BAAmB,aAClB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,OAAO,EAAE,WAAW,mBAAmB,SAAS,mBAAmB,OAAU;AAAA;AAAA,YAC/E;AAAA,YAED;AAAA;AAAA;AAAA,MACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/stat-card/stat-card.tsx"],"sourcesContent":["import { cn } from '@/helpers';\nimport { Icon } from '@/ui/icon';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type StatCardTrend = 'up' | 'down' | 'neutral';\n\nexport interface StatCardProps extends HTMLAttributes<HTMLDivElement> {\n label: ReactNode;\n value: ReactNode;\n trend?: ReactNode;\n trendDirection?: StatCardTrend;\n}\n\nexport function StatCard({\n label,\n value,\n trend,\n trendDirection = 'neutral',\n className,\n ...rest\n}: StatCardProps) {\n return (\n <div className={cn('uxm-stat-card', className)} {...rest}>\n <p className=\"uxm-stat-card__label\">{label}</p>\n <div className=\"uxm-stat-card__row\">\n <span className=\"uxm-stat-card__value\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'uxm-stat-card__trend',\n `uxm-stat-card__trend--${trendDirection}`,\n )}\n >\n {trendDirection !== 'neutral' && (\n <Icon\n glyph=\"arrow-up\"\n size={12}\n strokeWidth={2.5}\n className=\"uxm-stat-card__trend-icon\"\n />\n )}\n {trend}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBM;AAxBN,qBAAmB;AACnB,kBAAqB;AAad,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,SACE,6CAAC,SAAI,eAAW,mBAAG,iBAAiB,SAAS,GAAI,GAAG,MAClD;AAAA,gDAAC,OAAE,WAAU,wBAAwB,iBAAM;AAAA,IAC3C,6CAAC,SAAI,WAAU,sBACb;AAAA,kDAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,MAC7C,SACC;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,YACT;AAAA,YACA,yBAAyB,cAAc;AAAA,UACzC;AAAA,UAEC;AAAA,+BAAmB,aAClB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,WAAU;AAAA;AAAA,YACZ;AAAA,YAED;AAAA;AAAA;AAAA,MACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -41,6 +41,10 @@
41
41
  }
42
42
  .uxm-stat-card__trend--down {
43
43
  color: var(--uxm-stat-card-trend-down-color, var(--color-danger-text));
44
+ /* One `arrow-up` glyph serves both directions — flip it for `down`. */
45
+ }
46
+ .uxm-stat-card__trend--down .uxm-stat-card__trend-icon {
47
+ transform: rotate(180deg);
44
48
  }
45
49
  .uxm-stat-card__trend--neutral {
46
50
  color: var(--color-text-muted);
@@ -27,7 +27,7 @@ function StatCard({
27
27
  glyph: "arrow-up",
28
28
  size: 12,
29
29
  strokeWidth: 2.5,
30
- style: { transform: trendDirection === "down" ? "rotate(180deg)" : void 0 }
30
+ className: "uxm-stat-card__trend-icon"
31
31
  }
32
32
  ),
33
33
  trend
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/stat-card/stat-card.tsx"],"sourcesContent":["import { cn } from '@/helpers';\nimport { Icon } from '@/ui/icon';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type StatCardTrend = 'up' | 'down' | 'neutral';\n\nexport interface StatCardProps extends HTMLAttributes<HTMLDivElement> {\n label: ReactNode;\n value: ReactNode;\n trend?: ReactNode;\n trendDirection?: StatCardTrend;\n}\n\nexport function StatCard({\n label,\n value,\n trend,\n trendDirection = 'neutral',\n className,\n ...rest\n}: StatCardProps) {\n return (\n <div className={cn('uxm-stat-card', className)} {...rest}>\n <p className=\"uxm-stat-card__label\">{label}</p>\n <div className=\"uxm-stat-card__row\">\n <span className=\"uxm-stat-card__value\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'uxm-stat-card__trend',\n `uxm-stat-card__trend--${trendDirection}`,\n )}\n >\n {trendDirection !== 'neutral' && (\n <Icon\n glyph=\"arrow-up\"\n size={12}\n strokeWidth={2.5}\n style={{ transform: trendDirection === 'down' ? 'rotate(180deg)' : undefined }}\n />\n )}\n {trend}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"AAwBM,cAII,YAJJ;AAxBN,SAAS,UAAU;AACnB,SAAS,YAAY;AAad,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,SACE,qBAAC,SAAI,WAAW,GAAG,iBAAiB,SAAS,GAAI,GAAG,MAClD;AAAA,wBAAC,OAAE,WAAU,wBAAwB,iBAAM;AAAA,IAC3C,qBAAC,SAAI,WAAU,sBACb;AAAA,0BAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,MAC7C,SACC;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,yBAAyB,cAAc;AAAA,UACzC;AAAA,UAEC;AAAA,+BAAmB,aAClB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,OAAO,EAAE,WAAW,mBAAmB,SAAS,mBAAmB,OAAU;AAAA;AAAA,YAC/E;AAAA,YAED;AAAA;AAAA;AAAA,MACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/stat-card/stat-card.tsx"],"sourcesContent":["import { cn } from '@/helpers';\nimport { Icon } from '@/ui/icon';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type StatCardTrend = 'up' | 'down' | 'neutral';\n\nexport interface StatCardProps extends HTMLAttributes<HTMLDivElement> {\n label: ReactNode;\n value: ReactNode;\n trend?: ReactNode;\n trendDirection?: StatCardTrend;\n}\n\nexport function StatCard({\n label,\n value,\n trend,\n trendDirection = 'neutral',\n className,\n ...rest\n}: StatCardProps) {\n return (\n <div className={cn('uxm-stat-card', className)} {...rest}>\n <p className=\"uxm-stat-card__label\">{label}</p>\n <div className=\"uxm-stat-card__row\">\n <span className=\"uxm-stat-card__value\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'uxm-stat-card__trend',\n `uxm-stat-card__trend--${trendDirection}`,\n )}\n >\n {trendDirection !== 'neutral' && (\n <Icon\n glyph=\"arrow-up\"\n size={12}\n strokeWidth={2.5}\n className=\"uxm-stat-card__trend-icon\"\n />\n )}\n {trend}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"AAwBM,cAII,YAJJ;AAxBN,SAAS,UAAU;AACnB,SAAS,YAAY;AAad,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,SACE,qBAAC,SAAI,WAAW,GAAG,iBAAiB,SAAS,GAAI,GAAG,MAClD;AAAA,wBAAC,OAAE,WAAU,wBAAwB,iBAAM;AAAA,IAC3C,qBAAC,SAAI,WAAU,sBACb;AAAA,0BAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,MAC7C,SACC;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,yBAAyB,cAAc;AAAA,UACzC;AAAA,UAEC;AAAA,+BAAmB,aAClB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,WAAU;AAAA;AAAA,YACZ;AAAA,YAED;AAAA;AAAA;AAAA,MACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -163,7 +163,9 @@
163
163
  }
164
164
  .uxm-toast__close:hover {
165
165
  opacity: 1;
166
- background-color: rgba(0, 0, 0, 0.06);
166
+ /* Tint from the toast's own text colour so the fill reads on every
167
+ variant and in both themes (a black literal vanished on dark). */
168
+ background-color: var(--uxm-toast-close-hover-background-color, color-mix(in srgb, currentColor 10%, transparent));
167
169
  }
168
170
  .uxm-toast__close:focus-visible {
169
171
  opacity: 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viax.io/uxm",
3
- "version": "4.37.0",
3
+ "version": "4.38.0",
4
4
  "description": "Viax UXM — React 19 UI primitives and design tokens.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -61,12 +61,13 @@
61
61
  "typecheck": "tsc --noEmit && tsc --noEmit -p portal/tsconfig.json",
62
62
  "lint": "eslint .",
63
63
  "lint:fix": "eslint . --fix",
64
- "check:drift": "node scripts/check-state-var-drift.mjs && npm run check:type-scale",
64
+ "check:drift": "node scripts/check-state-var-drift.mjs && npm run check:type-scale && npm run check:tokens",
65
65
  "test:ci": "echo 'no tests yet' && exit 0",
66
66
  "test:coverage": "echo 'no coverage yet' && exit 0",
67
67
  "commit": "cz",
68
68
  "prepublishOnly": "npm run build",
69
69
  "check:type-scale": "node scripts/sweep-type-scale.mjs --check",
70
+ "check:tokens": "node scripts/check-token-parity.mjs",
70
71
  "verify:type-scale": "node scripts/verify-type-scale.mjs origin/master"
71
72
  },
72
73
  "config": {