ui-lab-registry 0.3.48 → 0.3.49

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.
@@ -150,7 +150,6 @@ export const generatedAPI = {
150
150
  "name": "size",
151
151
  "type": "ButtonSize",
152
152
  "required": false,
153
- "defaultValue": "md",
154
153
  "description": "Size class appended to the root element. Accepts any string."
155
154
  },
156
155
  {
@@ -2361,6 +2360,12 @@ export const generatedAPI = {
2361
2360
  "required": false,
2362
2361
  "description": "Additional CSS class for the root wrapper"
2363
2362
  },
2363
+ {
2364
+ "name": "label",
2365
+ "type": "string",
2366
+ "required": false,
2367
+ "description": "Display text for the currently selected value — used for SSR/SSG to avoid\nflash of placeholder before items register. Provide alongside selectedKey or\ndefaultSelectedKey so the correct label renders on the first pass."
2368
+ },
2364
2369
  {
2365
2370
  "name": "styles",
2366
2371
  "type": "SelectStylesProp",
@@ -2419,12 +2424,6 @@ export const generatedAPI = {
2419
2424
  "required": false,
2420
2425
  "description": "Default selected keys for uncontrolled multi-select"
2421
2426
  },
2422
- {
2423
- "name": "valueLabel",
2424
- "type": "string",
2425
- "required": false,
2426
- "description": "Display text for the currently selected value — used for SSR/SSG to avoid\nflash of placeholder before items register. Provide alongside selectedKey or\ndefaultSelectedKey so the correct label renders on the first pass."
2427
- },
2428
2427
  {
2429
2428
  "name": "onSelectionChange",
2430
2429
  "type": "((value: any) => void)",
@@ -3715,7 +3714,7 @@ export const generatedAPI = {
3715
3714
  "description": "Default display text shown in the trigger when nothing is selected"
3716
3715
  },
3717
3716
  {
3718
- "name": "valueLabel",
3717
+ "name": "label",
3719
3718
  "type": "string",
3720
3719
  "required": false,
3721
3720
  "description": "Display text for the currently selected value — used for SSR/SSG to avoid\nflash of placeholder before items register. Provide alongside selectedKey or\ndefaultSelectedKey so the correct label renders on the first pass."
@@ -4845,7 +4844,7 @@ export const generatedAPI = {
4845
4844
  };
4846
4845
  export const generatedStyles = {
4847
4846
  "anchor": "@reference \"tailwindcss\";\n\n@layer components {\n .preview, .anchor {\n display: inline\n }\n\n .root {\n @apply inline-block relative cursor-pointer;\n display: inline-block;\n color: var(--foreground, currentColor);\n text-decoration: none;\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]) .underline {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible, var(--focus-ring));\n outline-offset: 2px;\n border-radius: 2px;\n }\n }\n\n .underline {\n @apply absolute left-0 right-0 bottom-0 h-px;\n background-color: var(--underline-background, var(--background-600));\n transform-origin: right;\n transform: scaleX(1);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n pointer-events: none;\n }\n\n .preview {\n }\n}\n",
4848
- "badge": "@reference \"tailwindcss\";\n\n@layer components {\n .badge {\n @apply inline-flex items-center justify-center gap-2 select-none whitespace-nowrap px-1.5;\n height: fit-content;\n width: fit-content;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--background-border, var(--background-600));\n border-radius: var(--radius-sm, 0.375rem);\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--text-xs, 0.75rem);\n line-height: var(--leading-tight, 1.25);\n }\n\n .badge.dismissible {\n @apply pr-0.5;\n }\n\n .pill {\n border-radius: 9999px;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n }\n\n .dismiss {\n @apply ml-1 flex shrink-0 items-center justify-center p-0 cursor-pointer;\n width: 1em;\n height: 1em;\n line-height: 1;\n border-radius: var(--radius-xs, 0.25rem);\n background-color: var(--dismiss-background, var(--background, transparent));\n color: var(--foreground, var(--foreground-400));\n border: none;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n outline: none;\n }\n\n .dismiss svg {\n width: 100%;\n height: 100%;\n }\n\n .dismiss[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover, var(--dismiss-background, transparent));\n }\n\n .dismiss[data-pressed=\"true\"] {\n background-color: var(\n --background-pressed,\n var(--background-hover, var(--dismiss-background, transparent))\n );\n transform: scale(0.95);\n }\n\n .dismiss[data-focus-visible=\"true\"] {\n box-shadow: 0 0 0 1.5px var(--focus-visible, var(--foreground));\n }\n}\n",
4847
+ "badge": "@reference \"tailwindcss\";\n\n@layer components {\n .badge {\n @apply inline-flex items-center justify-center gap-2 select-none whitespace-nowrap px-1.5;\n height: fit-content;\n width: fit-content;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--background-border, var(--background-600));\n border-radius: var(--radius-sm, 0.375rem);\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--text-xs, 0.75rem);\n line-height: var(--leading-tight, 1.25);\n }\n\n .badge.dismissible {\n @apply pr-0.5;\n }\n\n .pill {\n border-radius: 9999px;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n }\n\n .dismiss {\n @apply ml-1 flex shrink-0 items-center justify-center p-0 cursor-pointer;\n width: 1em;\n height: 1em;\n line-height: 1;\n border-radius: var(--radius-xs, 0.25rem);\n background-color: var(--dismiss-background, var(--background, transparent));\n color: var(--foreground, var(--foreground-400));\n border: none;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n outline: none;\n }\n\n .dismiss svg {\n width: 100%;\n height: 100%;\n }\n\n .dismiss[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover, var(--dismiss-background, transparent));\n }\n\n .dismiss[data-pressed=\"true\"] {\n background-color: var(\n --background-pressed,\n var(--background-hover, var(--dismiss-background, transparent))\n );\n transform: scale(0.95);\n }\n\n .dismiss[data-focus-visible=\"true\"] {\n box-shadow: 0 0 0 1.5px var(--focus-visible, var(--foreground));\n }\n}\n",
4849
4848
  "banner": "@reference \"tailwindcss\";\n\n@layer components {\n .banner {\n @apply flex w-full items-start gap-3 px-4 py-3;\n font-family: inherit;\n font-weight: var(--font-weight-medium, 500);\n line-height: var(--leading-normal, 1.5);\n background-color: var(--background, var(--background-900));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--border, var(--background-700));\n border-radius: var(--radius-sm, 0.375rem);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .banner:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover, var(--background));\n border-color: var(--border-hover, var(--border));\n }\n\n .banner[data-pressed=\"true\"] {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n border-color: var(--border-pressed, var(--border-hover, var(--border)));\n }\n\n .content {\n @apply min-w-0 flex flex-col gap-1;\n }\n\n .iconContainer {\n @apply flex shrink-0 items-start justify-center pt-0.5;\n }\n\n .icon {\n @apply h-5 w-5;\n color: var(--icon-color, currentColor);\n }\n\n .dismiss {\n @apply flex h-8 w-8 shrink-0 items-center justify-center p-0 cursor-pointer;\n background-color: transparent;\n color: currentColor;\n border: none;\n border-radius: var(--radius-sm, 0.375rem);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--dismiss-hover-background, transparent);\n }\n\n &[data-pressed=\"true\"] {\n background-color: var(--dismiss-pressed-background, transparent);\n }\n\n &:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n }\n }\n\n .title {\n font-weight: var(--font-weight-semibold, 600);\n font-size: inherit;\n line-height: var(--leading-tight, 1.25);\n @apply my-0;\n }\n\n .body {\n font-weight: var(--font-weight-medium, 500);\n font-size: inherit;\n line-height: var(--leading-normal, 1.5);\n @apply my-0;\n }\n}\n",
4850
4849
  "button": "@reference \"tailwindcss\";\n\n@layer components {\n .button {\n @apply inline-flex items-center justify-center gap-2 select-none cursor-pointer whitespace-nowrap;\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &:focus-visible {\n outline: none;\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n filter: grayscale(0.5);\n }\n }\n}\n",
4851
4850
  "card": "@reference \"tailwindcss\";\n\n@layer components {\n .card {\n @apply overflow-hidden;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, inherit);\n border: var(--border-width-base, 1px) solid var(--background-border, var(--border));\n border-radius: var(--radius-sm, 0.375rem);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .header {\n @apply p-4;\n color: var(--foreground, inherit);\n border-bottom: var(--border-width-base, 1px) solid var(--background-border, var(--border));\n }\n\n .body {\n @apply px-4 py-2;\n color: var(--foreground, inherit);\n }\n\n .footer {\n @apply px-2 py-2;\n color: var(--foreground, inherit);\n background-color: var(--background, var(--background-800));\n border-top: var(--border-width-base, 1px) solid var(--background-border, var(--border));\n }\n}\n",
@@ -4854,17 +4853,17 @@ export const generatedStyles = {
4854
4853
  "color": "@reference \"tailwindcss\";\n\n@layer components {\n .color {\n --background: color-mix(in srgb, var(--background-800) 30%, transparent);\n --background-border: var(--background-700);\n --focus-visible: var(--accent-500);\n\n display: flex;\n flex-direction: column;\n gap: 1rem;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n width: 260px;\n }\n\n .color[data-disabled=\"true\"] {\n opacity: 0.5;\n pointer-events: none;\n }\n\n .color[data-variant=\"popover\"] {\n background: transparent;\n border-color: transparent;\n border-radius: 0;\n }\n\n .color-provider {\n display: inline-flex;\n width: fit-content;\n }\n\n .color-provider .color-trigger {\n --trigger-background: color-mix(in srgb, var(--background-800) 35%, transparent);\n --trigger-background-hover: color-mix(in srgb, var(--background-700) 45%, transparent);\n --trigger-border: var(--background-700);\n --trigger-text: var(--foreground-200);\n --background-border: var(--background-700);\n --focus-visible: var(--accent-500);\n --checkerboard-dark: var(--background-700);\n --checkerboard-light: var(--background-800);\n\n display: inline-flex;\n align-items: center;\n gap: 0.625rem;\n min-width: 170px;\n height: 40px;\n padding: 0 0.75rem;\n border: var(--border-width-base, 1px) solid var(--trigger-border);\n border-radius: var(--radius-sm, 0.375rem);\n background: var(--trigger-background);\n color: var(--trigger-text);\n cursor: pointer;\n font: inherit;\n font-size: 0.875rem;\n line-height: 1;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .color-provider .color-trigger:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background: var(--trigger-background-hover);\n }\n\n .color-provider .color-trigger:focus-visible {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .color-provider .color-trigger[data-disabled=\"true\"] {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .color-provider .color-trigger[data-size=\"sm\"] {\n min-width: 150px;\n height: 34px;\n padding: 0 0.625rem;\n font-size: 0.8125rem;\n }\n\n .color-provider .color-trigger[data-size=\"lg\"] {\n min-width: 190px;\n height: 46px;\n padding: 0 0.875rem;\n font-size: 0.9375rem;\n }\n\n .color-provider .color-trigger-swatch {\n position: relative;\n width: 20px;\n height: 20px;\n flex: 0 0 auto;\n border-radius: var(--radius-xs, 0.25rem);\n border: var(--border-width-base, 1px) solid var(--background-border);\n overflow: hidden;\n }\n\n .color-provider .color-trigger-swatch::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: repeating-linear-gradient(\n 45deg,\n var(--checkerboard-dark),\n var(--checkerboard-dark) 4px,\n var(--checkerboard-light) 4px,\n var(--checkerboard-light) 8px\n );\n }\n\n .color-provider .color-trigger-swatch::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background-color: var(--preview-color, transparent);\n }\n\n .color-provider .color-trigger-value {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .color .controls {\n @apply pb-3 px-3 space-y-3;\n }\n\n .input-group {\n width: 100%;\n }\n\n .input-group > div:first-child {\n flex: 1;\n min-width: 0;\n }\n\n .input-group .input {\n width: 100%;\n }\n\n .input-group .format {\n flex-shrink: 0;\n width: 85px;\n }\n\n .color[data-size=\"sm\"] .format {\n width: 75px;\n }\n\n .canvas {\n position: relative;\n width: 96%;\n @apply mx-auto mt-2;\n cursor: crosshair;\n touch-action: none;\n display: flex;\n flex-direction: column;\n min-height: 160px;\n }\n\n .canvas[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .canvas .canvas-inner {\n position: relative;\n width: 100%;\n flex: 1;\n overflow: hidden;\n }\n\n .canvas .canvas-gradient-hue {\n position: absolute;\n inset: 0;\n overflow: hidden;\n }\n\n .canvas .canvas-gradient-saturation {\n position: absolute;\n inset: 0;\n background: linear-gradient(to right, rgb(255, 255, 255), transparent);\n }\n\n .canvas .canvas-gradient-brightness {\n position: absolute;\n inset: 0;\n background: linear-gradient(to top, rgb(0, 0, 0), transparent);\n }\n\n .canvas .canvas-pointer {\n --pointer-border: color-mix(in srgb, var(--foreground-200) 50%, transparent);\n\n position: absolute;\n width: 12px;\n height: 12px;\n border-radius: var(--radius-full);\n border: 2px solid var(--pointer-border);\n box-shadow: 0 0 0 1px rgb(0 0 0 / 0.3), 0 2px 4px rgb(0 0 0 / 0.3);\n pointer-events: none;\n transform: translate(-50%, -50%);\n z-index: 10;\n }\n\n .hue-slider {\n --slider-track-size: 16px;\n --slider-thumb-size: 12px;\n --slider-hit-size: 16px;\n --slider-track-radius: var(--radius-full);\n --slider-track-border: var(--border-width-base, 1px) solid var(--background-border);\n --slider-track-background: linear-gradient(\n to right,\n hsl(0, 100%, 50%),\n hsl(60, 100%, 50%),\n hsl(120, 100%, 50%),\n hsl(180, 100%, 50%),\n hsl(240, 100%, 50%),\n hsl(300, 100%, 50%),\n hsl(360, 100%, 50%)\n );\n --slider-range-display: none;\n --slider-thumb-scale-active: 1;\n\n width: 100%;\n min-height: 16px;\n border-radius: var(--radius-full);\n }\n\n .hue-slider .hue-track {\n position: relative;\n width: 100%;\n }\n\n .hue-slider .hue-thumb {\n --thumb-border: white;\n --thumb-background: white;\n --slider-thumb-background: var(--thumb-background);\n --slider-thumb-border: 2px solid var(--thumb-border);\n --slider-thumb-shadow: 0 2px 4px rgb(0 0 0 / 0.3);\n --slider-thumb-shadow-hover: 0 2px 6px rgb(0 0 0 / 0.4);\n --slider-thumb-shadow-active: 0 1px 3px rgb(0 0 0 / 0.3);\n\n border-radius: var(--radius-full);\n }\n\n .hue-slider .hue-thumb[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .hue-slider .hue-thumb[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n box-shadow: var(--slider-thumb-shadow-hover);\n }\n\n .hue-slider .hue-thumb[data-pressed=\"true\"] {\n box-shadow: var(--slider-thumb-shadow-active);\n }\n\n .opacity-slider {\n --slider-track-size: 12px;\n --slider-thumb-size: 10px;\n --slider-hit-size: 12px;\n --slider-track-radius: var(--radius-full);\n --slider-track-border: var(--border-width-base, 1px) solid var(--background-border);\n --slider-range-display: none;\n --slider-thumb-scale-active: 1;\n --checkerboard-dark: var(--background-800);\n --checkerboard-light: var(--background-700);\n --slider-track-background:\n linear-gradient(to right, transparent, var(--color-slider-opacity-color, rgb(0, 0, 0))),\n repeating-linear-gradient(\n 45deg,\n var(--checkerboard-dark),\n var(--checkerboard-dark) 10px,\n var(--checkerboard-light) 10px,\n var(--checkerboard-light) 20px\n );\n\n width: 100%;\n min-height: 12px;\n border-radius: var(--radius-full);\n }\n\n .opacity-slider .opacity-track {\n position: relative;\n width: 100%;\n overflow: hidden;\n }\n\n .opacity-slider .opacity-thumb {\n --thumb-border: white;\n --thumb-background: white;\n --slider-thumb-background: var(--thumb-background);\n --slider-thumb-border: 2px solid var(--thumb-border);\n --slider-thumb-shadow: 0 2px 4px rgb(0 0 0 / 0.3);\n --slider-thumb-shadow-hover: 0 2px 6px rgb(0 0 0 / 0.4);\n --slider-thumb-shadow-active: 0 1px 3px rgb(0 0 0 / 0.3);\n\n border-radius: var(--radius-full);\n }\n\n .opacity-slider .opacity-thumb[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .opacity-slider .opacity-thumb[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n box-shadow: var(--slider-thumb-shadow-hover);\n }\n\n .opacity-slider .opacity-thumb[data-pressed=\"true\"] {\n box-shadow: var(--slider-thumb-shadow-active);\n }\n\n .recent-colors {\n display: flex;\n gap: 0.5rem;\n overflow-x: auto;\n padding-bottom: 0.25rem;\n }\n\n .recent-colors .recent-color-swatch {\n flex-shrink: 0;\n width: 32px;\n height: 32px;\n border-radius: var(--radius-sm);\n border: var(--border-width-base, 1px) solid var(--background-border);\n cursor: pointer;\n background: none;\n padding: 0;\n outline: none;\n transition:\n box-shadow var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .recent-colors .recent-color-swatch:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n transform: scale(1.1);\n box-shadow: 0 0 0 2px var(--focus-visible);\n }\n\n .recent-colors .recent-color-swatch:active {\n transform: scale(0.95);\n }\n\n .recent-colors .recent-color-swatch:focus-visible {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n }\n\n .preview-swatch {\n --checkerboard-dark: var(--background-700);\n --checkerboard-light: var(--background-800);\n\n position: relative;\n width: 36px;\n height: 36px;\n border-radius: var(--radius-sm);\n border: var(--border-width-base, 1px) solid var(--background-border);\n box-shadow: 0 1px 3px rgb(0 0 0 / 0.1);\n overflow: hidden;\n flex-shrink: 0;\n }\n\n .preview-swatch::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: repeating-linear-gradient(\n 45deg,\n var(--checkerboard-dark),\n var(--checkerboard-dark) 6px,\n var(--checkerboard-light) 6px,\n var(--checkerboard-light) 12px\n );\n border-radius: var(--radius-sm);\n pointer-events: none;\n z-index: 1;\n }\n\n .preview-swatch::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background-color: var(--preview-color, transparent);\n border-radius: var(--radius-sm);\n pointer-events: none;\n z-index: 2;\n }\n\n .preview {\n --checkerboard-dark: var(--background-700);\n --checkerboard-light: var(--background-800);\n\n position: relative;\n width: 64px;\n height: 64px;\n border-radius: var(--radius-sm);\n border: var(--border-width-base, 1px) solid var(--background-border);\n box-shadow: 0 2px 8px rgb(0 0 0 / 0.2);\n overflow: hidden;\n }\n\n .preview::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: repeating-linear-gradient(\n 45deg,\n var(--checkerboard-dark),\n var(--checkerboard-dark) 10px,\n var(--checkerboard-light) 10px,\n var(--checkerboard-light) 20px\n );\n border-radius: var(--radius-sm);\n pointer-events: none;\n z-index: 1;\n }\n}\n",
4855
4854
  "command": "@reference \"tailwindcss\";\n\n@layer components {\n /* Overlay Container */\n .overlay {\n @apply fixed inset-0 flex items-start justify-center overflow-hidden;\n z-index: 999;\n padding-top: 20vh;\n /* Apply backdrop styles directly to avoid creating a containing block that disrupts sticky elements */\n background-color: var(--overlay);\n backdrop-filter: var(--overlay-backdrop);\n }\n\n /* Content */\n .content {\n @apply relative m-2 w-full max-w-[28rem];\n border-radius: var(--radius-sm);\n background: var(--background);\n margin-inline: 1rem;\n box-shadow: var(--shadow);\n animation: fade-in-zoom-in 0.2s ease-out;\n }\n\n .inner {\n border-radius: var(--radius-sm) var(--radius-sm) 0 0;\n border-top: var(--border-width-base) solid var(--border);\n @apply overflow-hidden;\n }\n\n /* Search Section */\n .search {\n @apply border-none flex p-1.5;\n --input-active-border-color: transparent;\n --input-active-box-shadow: none;\n }\n\n .input {\n border-color: transparent;\n background: transparent;\n box-shadow: none;\n\n &[data-active],\n &[data-focus-visible] {\n border-color: transparent;\n box-shadow: none;\n }\n }\n\n /* List Section */\n .list {\n @apply py-0.5 px-2 space-y-2;\n background-color: var(--background-list);\n }\n\n .list :global([role=\"listbox\"]) {\n @apply flex w-full flex-col;\n }\n\n .item {\n @apply flex items-center justify-between rounded-sm px-2 py-0.5 cursor-pointer;\n border-radius: 0.375rem;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n color: var(--foreground);\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item-content {\n @apply flex min-w-0 flex-1 items-center gap-2.5;\n flex: 1;\n }\n\n .item-icon {\n @apply flex h-6 w-6 shrink-0 items-center justify-center;\n color: var(--foreground);\n }\n\n .item-labels {\n flex: 1;\n @apply min-w-0;\n }\n\n .item-label {\n font-size: var(--text-sm);\n color: var(--foreground);\n font-weight: var(--font-weight-medium);\n @apply overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n color: var(--foreground-muted);\n font-size: 0.875rem;\n @apply overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .hint-wrapper {\n @apply flex items-center;\n }\n\n .category-header {\n @apply px-2 py-1.5 mt-2 first:mt-0;\n font-size: var(--text-sm);\n font-weight: var(--font-weight-semibold);\n color: var(--foreground-muted);\n }\n\n /* Empty State */\n .empty {\n padding: 1.5rem 1rem;\n text-align: center;\n font-size: 0.875rem;\n color: var(--foreground-muted);\n }\n\n /* Footer */\n .footer {\n @apply flex w-full items-center gap-2 px-1.5 py-2;\n background-color: var(--background-footer);\n border-top: 1px solid var(--border);\n justify-content: flex-between;\n }\n\n /* Animations */\n @keyframes fade-in-zoom-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }\n}\n",
4856
4855
  "confirm": "@reference \"tailwindcss\";\n\n@layer components {\n .confirm {\n --overlay-background: mix(var(--background-950) 50%, transparent);\n --header-foreground: var(--foreground-100);\n --description-foreground: var(--foreground-300);\n --error-foreground: var(--foreground-danger);\n --countdown-foreground: var(--foreground-400);\n --label-foreground: var(--foreground-300);\n --input-background: var(--background-800);\n --input-border-color: var(--background-700);\n --input-foreground: var(--foreground-100);\n --input-focus-visible: var(--accent-500);\n }\n\n .container {\n @apply flex flex-col;\n }\n\n .card {\n @apply max-w-[28rem];\n }\n\n .body {\n @apply flex flex-col gap-4;\n }\n\n .body-compact {\n @apply gap-3;\n }\n\n .dialog-overlay {\n @apply fixed inset-0 z-50 flex items-center justify-center;\n background-color: var(--overlay-background);\n }\n\n .dialog-card {\n @apply max-w-[28rem];\n margin: 0 1rem;\n }\n\n .header {\n @apply flex items-start gap-3;\n }\n\n .header-content {\n @apply flex-1;\n }\n\n .header-title {\n @apply font-semibold;\n color: var(--header-foreground);\n }\n\n .description {\n font-size: var(--text-sm);\n color: var(--description-foreground);\n }\n\n .error-message {\n font-size: var(--text-sm);\n color: var(--error-foreground);\n }\n\n .warning-box {\n @apply p-3 rounded-sm;\n border: var(--border-width-base, 1px) solid var(--warning-border-color);\n background-color: var(--warning-background);\n color: var(--warning-foreground);\n font-size: var(--text-sm);\n }\n\n .warning-box-low {\n --warning-background: var(--warning-background-low);\n --warning-border-color: var(--warning-border-color-low);\n --warning-foreground: var(--warning-foreground-low);\n }\n\n .warning-box-medium {\n --warning-background: var(--warning-background-medium);\n --warning-border-color: var(--warning-border-color-medium);\n --warning-foreground: var(--warning-foreground-medium);\n }\n\n .warning-box-high {\n --warning-background: var(--warning-background-high);\n --warning-border-color: var(--warning-border-color-high);\n --warning-foreground: var(--warning-foreground-high);\n }\n\n .warning-box-critical {\n --warning-background: var(--warning-background-critical);\n --warning-border-color: var(--warning-border-color-critical);\n --warning-foreground: var(--warning-foreground-critical);\n }\n\n .countdown-text {\n font-size: var(--text-sm);\n color: var(--countdown-foreground);\n }\n\n .input-label {\n font-size: var(--text-sm);\n margin-left: 0.25rem;\n color: var(--label-foreground);\n }\n\n .input {\n @apply w-full mt-2 px-3 py-2 rounded-sm transition-all duration-200;\n background-color: var(--input-background);\n border: var(--border-width-base, 1px) solid var(--input-border-color);\n color: var(--input-foreground);\n font-size: var(--text-sm);\n\n &:focus-visible {\n outline: 2px solid var(--input-focus-visible);\n outline-offset: 2px;\n }\n }\n\n .actions {\n @apply flex gap-2;\n }\n\n .actions-inline {\n @apply flex-row;\n }\n\n .actions-dialog {\n @apply flex-row justify-end;\n }\n}\n",
4857
- "date": "@reference \"tailwindcss\";\n\n@layer components {\n .calendar {\n --disabled-opacity: 0.5;\n\n @apply inline-flex p-1.5 flex-col overflow-hidden gap-0;\n border-radius: var(--radius-xs);\n background-color: var(--background);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-headers {\n @apply grid gap-2 px-4 pt-3 pb-1;\n grid-template-columns: repeat(7, 1fr);\n background: var(--background);\n border: var(--border-width-base) solid var(--border);\n border-bottom: none;\n border-radius: var(--radius-xs) var(--radius-xs) 0 0;\n }\n\n .day-header {\n @apply flex items-center justify-center;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-xs);\n color: var(--foreground);\n }\n\n .header {\n @apply flex items-center justify-between gap-4 pl-2 pr-1.5 py-1.5;\n color: var(--foreground);\n }\n\n .month-year {\n @apply ml-2;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n text-align: center;\n }\n\n .nav-button {\n @apply inline-flex min-h-8 min-w-8 items-center justify-center cursor-pointer;\n border-radius: var(--radius-xs);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 1px solid transparent;\n font-size: var(--text-sm);\n font-weight: 500;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .nav-button:focus-visible {\n outline: none;\n }\n\n .nav-button:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .grid {\n @apply grid gap-1 px-4 pb-4;\n grid-template-columns: repeat(7, 1fr); /* 7 days only */\n background: var(--background);\n border-radius: 0 0 var(--radius-xs) var(--radius-xs);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-cell {\n @apply flex min-h-8 items-center justify-center px-2.5 py-2 cursor-pointer;\n border-radius: var(--radius-base);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 2px solid transparent;\n font-size: var(--text-xs);\n font-weight: 400;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .day-cell:focus-visible {\n outline: none;\n }\n\n .week-header {\n display: none;\n }\n\n .week-number {\n display: none;\n }\n}\n\n/* Variant states - these are outside @layer */\n.day-cell[data-selected=\"true\"] {\n font-weight: 500;\n}\n\n.day-cell[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]),\n.day-cell:hover:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n}\n\n.day-cell[data-today=\"true\"] {\n border-color: transparent;\n}\n\n.day-cell[data-disabled=\"true\"],\n.day-cell[data-out-of-range=\"true\"] {\n opacity: var(--disabled-opacity);\n}\n\n.day-cell[data-disabled=\"true\"] { cursor: not-allowed; }\n",
4856
+ "date": "@reference \"tailwindcss\";\n\n@layer components {\n .calendar {\n --disabled-opacity: 0.5;\n\n @apply inline-flex p-1.5 flex-col overflow-hidden gap-0;\n border-radius: var(--radius-sm);\n background-color: var(--background);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-headers {\n @apply grid gap-2 px-4 pt-3 pb-1;\n grid-template-columns: repeat(7, 1fr);\n background: var(--background);\n border: var(--border-width-base) solid var(--border);\n border-bottom: none;\n border-radius: var(--radius-sm) var(--radius-sm) 0 0;\n }\n\n .day-header {\n @apply flex items-center justify-center;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n color: var(--foreground);\n }\n\n .header {\n @apply flex items-center justify-between gap-4 pl-2 pr-1.5 py-1.5;\n color: var(--foreground);\n }\n\n .month-year {\n @apply ml-2;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n text-align: center;\n }\n\n .nav-button {\n @apply inline-flex min-h-8 min-w-8 items-center justify-center cursor-pointer;\n border-radius: var(--radius-sm);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 1px solid transparent;\n font-size: var(--text-sm);\n font-weight: 500;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .nav-button:focus-visible {\n outline: none;\n }\n\n .nav-button:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .grid {\n @apply grid gap-1 px-4 pb-4;\n grid-template-columns: repeat(7, 1fr); /* 7 days only */\n background: var(--background);\n border-radius: 0 0 var(--radius-sm) var(--radius-sm);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-cell {\n @apply flex min-h-8 items-center justify-center px-2.5 py-2 cursor-pointer;\n border-radius: var(--radius-base);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 2px solid transparent;\n font-size: var(--text-sm);\n font-weight: 400;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .day-cell:focus-visible {\n outline: none;\n }\n\n .week-header {\n display: none;\n }\n\n .week-number {\n display: none;\n }\n}\n\n/* Variant states - these are outside @layer */\n.day-cell[data-selected=\"true\"] {\n font-weight: 500;\n}\n\n.day-cell[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]),\n.day-cell:hover:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n}\n\n.day-cell[data-today=\"true\"] {\n border-color: transparent;\n}\n\n.day-cell[data-disabled=\"true\"],\n.day-cell[data-out-of-range=\"true\"] {\n opacity: var(--disabled-opacity);\n}\n\n.day-cell[data-disabled=\"true\"] { cursor: not-allowed; }\n",
4858
4857
  "divider": "@reference \"tailwindcss\";\n\n@layer components {\n .divider {\n --divider-background: var(--group-divider-background, var(--background-border, var(--background)));\n }\n}\n",
4859
4858
  "expand": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n position: relative;\n display: block;\n width: 100%;\n }\n\n .expand {\n --expand-disabled-opacity: 0.6;\n --expand-trigger-padding-x: 0.75rem;\n --expand-trigger-padding-y: 0.5rem;\n\n @apply flex w-full flex-col;\n }\n\n .expand[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--expand-disabled-opacity);\n }\n\n .trigger {\n @apply flex w-full items-stretch justify-between border-0 p-0 text-left;\n\n appearance: none;\n color: var(--foreground);\n background-color: var(--background);\n cursor: pointer;\n border-radius: 0;\n font-size: var(--text-sm);\n line-height: var(--leading-snug);\n outline: none;\n box-shadow: none;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-smooth-settle, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-smooth-settle, ease-out));\n }\n\n .trigger:focus,\n .trigger:focus-visible {\n outline: none;\n box-shadow: none;\n }\n\n .trigger[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--expand-disabled-opacity);\n }\n\n .title {\n @apply flex min-w-0 flex-1 items-center overflow-hidden;\n\n padding: var(--expand-trigger-padding-y) 0 var(--expand-trigger-padding-y)\n var(--expand-trigger-padding-x);\n font-weight: var(--font-weight-medium);\n border-radius: 0;\n color: inherit;\n background-color: transparent;\n }\n\n .icon {\n @apply flex shrink-0 items-center justify-center;\n\n padding: var(--expand-trigger-padding-y) var(--expand-trigger-padding-x);\n color: inherit;\n background-color: transparent;\n border-radius: 0;\n }\n\n @media (hover: hover) {\n .trigger:not([data-disabled=\"true\"]):hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .trigger:not([data-disabled=\"true\"]) .icon:hover {\n border-radius: 0;\n }\n }\n\n .icon > * {\n transition: transform 250ms var(--ease-smooth-settle);\n }\n\n .icon[data-selected=\"true\"] > * {\n transform: rotate(180deg);\n }\n\n .expand:has(.content[data-from=\"above\"]) {\n flex-direction: column-reverse;\n }\n\n .expand:has(.content[data-from=\"above\"]) .icon > * {\n transform: rotate(180deg);\n }\n\n .expand:has(.content[data-from=\"above\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(0deg);\n }\n\n .expand:has(.content[data-from=\"left\"]) {\n @apply flex-row-reverse items-start;\n }\n\n .expand:has(.content[data-from=\"left\"]) .trigger {\n @apply w-auto flex-col;\n }\n\n .expand:has(.content[data-from=\"left\"]) .icon > * {\n transform: rotate(-90deg);\n }\n\n .expand:has(.content[data-from=\"left\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(90deg);\n }\n\n .expand:has(.content[data-from=\"right\"]) {\n @apply flex-row items-start;\n }\n\n .expand:has(.content[data-from=\"right\"]) .trigger {\n @apply w-auto flex-col;\n }\n\n .expand:has(.content[data-from=\"right\"]) .icon > * {\n transform: rotate(90deg);\n }\n\n .expand:has(.content[data-from=\"right\"]) .icon[data-selected=\"true\"] > * {\n transform: rotate(-90deg);\n }\n\n .content {\n display: grid;\n overflow: hidden;\n grid-template-rows: 0fr;\n transition: grid-template-rows 300ms var(--ease-smooth-settle);\n }\n\n .content[data-selected=\"true\"] {\n grid-template-rows: 1fr;\n }\n\n .content[data-from=\"left\"],\n .content[data-from=\"right\"] {\n grid-template-rows: 1fr;\n grid-template-columns: 0fr;\n transition: grid-template-columns 300ms var(--ease-smooth-settle);\n }\n\n .content[data-from=\"left\"][data-selected=\"true\"],\n .content[data-from=\"right\"][data-selected=\"true\"] {\n grid-template-columns: 1fr;\n }\n\n .content-inner {\n @apply min-h-0 overflow-hidden;\n\n min-width: 0;\n color: var(--foreground);\n background-color: var(--background);\n }\n\n .divider {\n margin: 0;\n }\n}\n",
4860
4859
  "flex": "@reference \"tailwindcss\";\n\n@layer components {\n .flex {\n --gap-scale: 0.5;\n\n @apply flex w-full;\n gap: calc(var(--spacing, 0.25rem) * var(--flex-gap-step, 4) * var(--gap-scale, 1));\n }\n\n /* Direction variants */\n .flex.row { flex-direction: row; }\n .flex.column { flex-direction: column; }\n\n /* Wrap variants */\n .flex.wrap { flex-wrap: wrap; }\n .flex.nowrap { flex-wrap: nowrap; }\n\n /* Justify-content variants */\n .flex.justify-start { justify-content: flex-start; }\n .flex.justify-end { justify-content: flex-end; }\n .flex.justify-center { justify-content: center; }\n .flex.justify-between { justify-content: space-between; }\n .flex.justify-around { justify-content: space-around; }\n .flex.justify-evenly { justify-content: space-evenly; }\n\n /* Align-items variants */\n .flex.align-start { align-items: flex-start; }\n .flex.align-end { align-items: flex-end; }\n .flex.align-center { align-items: center; }\n .flex.align-stretch { align-items: stretch; }\n .flex.align-baseline { align-items: baseline; }\n\n /* Container query parent - establishes containment context */\n .container-query-parent {\n container-type: inline-size;\n container-name: flex-parent;\n @apply w-full;\n }\n\n /* Container query responsive behavior - use .flex.container-responsive for specificity parity with base variants */\n @container flex-parent (width < 400px) {\n .flex.container-responsive {\n flex-direction: column;\n flex-wrap: wrap;\n justify-content: flex-start;\n --flex-gap-step: 2;\n }\n }\n\n @container flex-parent (400px <= width < 500px) {\n .flex.container-responsive {\n flex-wrap: wrap;\n --flex-gap-step: 2;\n }\n }\n\n @container flex-parent (500px <= width < 900px) {\n .flex.container-responsive {\n --flex-gap-step: 4;\n }\n }\n\n @container flex-parent (width >= 900px) {\n .flex.container-responsive {\n --flex-gap-step: 6;\n }\n }\n}\n",
4861
4860
  "frame": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n --frame-radius: var(--radius-sm, 24px);\n --frame-stroke-width: var(--border-width-base, 1px);\n }\n\n .shape {\n rx: var(--frame-radius);\n }\n\n .stroke {\n stroke-width: var(--frame-stroke-width);\n vector-effect: non-scaling-stroke;\n }\n\n}\n",
4862
4861
  "gallery": "@reference \"tailwindcss\";\n\n@layer components {\n .item-scope {\n @apply block min-w-0 h-full;\n }\n\n .item {\n --border-width: var(--border-width-base, 1px);\n --radius: var(--radius-sm, 0.375rem);\n --transition: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n --view-width: 200px;\n\n @apply flex flex-col overflow-hidden no-underline cursor-pointer w-full h-full;\n\n color: inherit;\n background: var(--background);\n border: var(--border-width) solid var(--background-border);\n border-radius: var(--radius);\n transition:\n border-color var(--transition),\n transform var(--transition),\n background-color var(--transition),\n box-shadow var(--transition);\n }\n\n .item:focus {\n outline: none;\n }\n\n .item[data-disabled=\"true\"] {\n @apply cursor-not-allowed;\n }\n\n .item[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n border-color: var(--background-hover-border);\n }\n\n .item[data-pressed=\"true\"] {\n border-color: var(--background-pressed-border, var(--background-hover-border));\n }\n\n .item[data-orientation=\"horizontal\"] {\n @apply flex-row;\n }\n\n .item[data-orientation=\"horizontal\"] .view {\n width: var(--view-width);\n }\n\n .view {\n --aspect-ratio: 16/9;\n --background: transparent;\n\n @apply relative overflow-hidden;\n\n aspect-ratio: var(--aspect-ratio);\n background: var(--background);\n }\n\n .view > img,\n .view > video {\n @apply w-full h-full object-cover;\n }\n\n .body {\n --gap: calc(var(--spacing, 0.25rem) * 1);\n --padding: calc(var(--spacing, 0.25rem) * 3);\n --title-color: var(--foreground);\n --description-color: var(--foreground-muted, var(--foreground));\n\n @apply flex flex-col self-start min-w-0;\n\n gap: var(--gap);\n padding: var(--padding);\n }\n\n .item[data-orientation=\"horizontal\"] .body {\n flex: 1;\n align-self: stretch;\n }\n\n .body > :first-child {\n color: var(--title-color);\n font-weight: var(--font-weight-medium, 500);\n }\n\n .body > :not(:first-child) {\n color: var(--description-color);\n font-size: var(--text-sm, 0.875rem);\n }\n}\n",
4863
4862
  "grid": "@reference \"tailwindcss\";\n\n@layer components {\n .grid {\n --gap-scale: 1;\n\n --background: transparent;\n --foreground: inherit;\n\n @apply grid w-full;\n background-color: var(--background);\n color: var(--foreground);\n grid-template-columns: var(--grid-tpl, repeat(3, 1fr));\n grid-template-rows: var(--grid-rows, auto);\n gap: calc(var(--spacing, 0.25rem) * var(--grid-gap-step, 4) * var(--gap-scale, 1));\n row-gap: calc(var(--spacing, 0.25rem) * var(--grid-row-gap-step, var(--grid-gap-step, 4)) * var(--gap-scale, 1));\n column-gap: calc(var(--spacing, 0.25rem) * var(--grid-col-gap-step, var(--grid-gap-step, 4)) * var(--gap-scale, 1));\n justify-items: var(--grid-ji, stretch);\n align-items: var(--grid-ai, stretch);\n justify-content: var(--grid-jc, start);\n align-content: var(--grid-ac, start);\n grid-auto-flow: var(--grid-flow, row);\n }\n\n .container {\n container-type: inline-size;\n container-name: grid-ctx;\n @apply w-full;\n }\n\n .grid.responsive-cols {\n grid-template-columns: var(--grid-tpl-sm, 1fr);\n }\n\n @media (min-width: 640px) {\n .grid.responsive-cols {\n grid-template-columns: var(--grid-tpl-md, var(--grid-tpl-sm, 1fr));\n }\n }\n\n @media (min-width: 1024px) {\n .grid.responsive-cols {\n grid-template-columns: var(--grid-tpl-lg, var(--grid-tpl-md, var(--grid-tpl-sm, 1fr)));\n }\n }\n\n @media (min-width: 1280px) {\n .grid.responsive-cols {\n grid-template-columns: var(--grid-tpl-xl, var(--grid-tpl-lg, var(--grid-tpl-md, var(--grid-tpl-sm, 1fr))));\n }\n }\n\n .grid.responsive-gap {\n --grid-gap-step: var(--grid-gap-step-sm, 2);\n }\n\n @media (min-width: 640px) {\n .grid.responsive-gap {\n --grid-gap-step: var(--grid-gap-step-md, var(--grid-gap-step-sm, 4));\n }\n }\n\n @media (min-width: 1024px) {\n .grid.responsive-gap {\n --grid-gap-step: var(--grid-gap-step-lg, var(--grid-gap-step-md, var(--grid-gap-step-sm, 4)));\n }\n }\n\n @media (min-width: 1280px) {\n .grid.responsive-gap {\n --grid-gap-step: var(--grid-gap-step-xl, var(--grid-gap-step-lg, var(--grid-gap-step-md, var(--grid-gap-step-sm, 4))));\n }\n }\n\n .grid.responsive-rows {\n grid-template-rows: var(--grid-rows-sm, auto);\n }\n\n @media (min-width: 640px) {\n .grid.responsive-rows {\n grid-template-rows: var(--grid-rows-md, var(--grid-rows-sm, auto));\n }\n }\n\n @media (min-width: 1024px) {\n .grid.responsive-rows {\n grid-template-rows: var(--grid-rows-lg, var(--grid-rows-md, var(--grid-rows-sm, auto)));\n }\n }\n\n @media (min-width: 1280px) {\n .grid.responsive-rows {\n grid-template-rows: var(--grid-rows-xl, var(--grid-rows-lg, var(--grid-rows-md, var(--grid-rows-sm, auto))));\n }\n }\n\n .grid.has-row-gap {\n row-gap: calc(var(--spacing, 0.25rem) * var(--grid-row-gap-step, var(--grid-gap-step, 4)) * var(--gap-scale, 1));\n }\n\n .grid.has-col-gap {\n column-gap: calc(var(--spacing, 0.25rem) * var(--grid-col-gap-step, var(--grid-gap-step, 4)) * var(--gap-scale, 1));\n }\n\n @container grid-ctx (width < 400px) {\n .container .grid {\n grid-template-columns: 1fr;\n --grid-gap-step: 2;\n }\n }\n}\n",
4864
- "group": "@reference \"tailwindcss\";\n\n@layer components {\n .group {\n --layout-radius-size: calc(var(--spacing) * 1.5);\n --layout-padding-size: var(--layout-radius-size);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-border-width: var(--border-width-base, 1px);\n --background-inner-radius: calc(var(--background-radius) - var(--background-border-width));\n --layout-text-height: calc(0.8em * var(--leading-tight, 1.25));\n --layout-vertical-spacing: calc(var(--spacing) * 4);\n --layout-border-height: calc(var(--background-border-width) * 2);\n --layout-padding-height: calc(var(--layout-padding-size) * 2);\n --layout-control-height: calc(\n var(--layout-text-height) +\n var(--layout-vertical-spacing) +\n var(--layout-border-height)\n );\n --item-height: max(\n calc(\n var(--layout-control-height) -\n var(--layout-padding-height) -\n var(--layout-border-height)\n ),\n 0px\n );\n\n @apply flex overflow-hidden shrink-0 box-border;\n color: var(--foreground, currentColor);\n background-color: var(--background, transparent);\n border: var(--background-border-width) solid var(--background-border, transparent);\n border-radius: var(--background-radius);\n padding: var(--layout-padding-size);\n\n &.horizontal {\n @apply flex-row items-stretch;\n height: var(--layout-control-height);\n\n .item.divider {\n margin-block: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n height: 100%;\n }\n }\n\n &.vertical {\n @apply flex-col;\n\n .item .button {\n @apply w-full;\n }\n\n .item.divider {\n margin-inline: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n width: 100%;\n }\n }\n\n &.none {\n --layout-padding-size: 0px;\n @apply gap-0;\n }\n\n &.xs {\n --layout-radius-size: calc(var(--spacing) * 0.875);\n @apply space-x-0.5;\n }\n\n &.sm {\n --layout-radius-size: calc(var(--spacing) * 1.25);\n @apply space-x-1;\n }\n\n }\n\n .item {\n @apply flex items-stretch;\n position: relative;\n isolation: isolate;\n border-radius: var(--group-item-radius, 0);\n overflow: visible;\n\n &.grow {\n flex: 1;\n }\n\n &.divider {\n @apply p-0 shrink-0 flex-none;\n\n > [role=\"separator\"] {\n flex: 0 0 auto;\n }\n }\n }\n\n :is(.button, .input, .select, .expand) {\n height: 100%;\n min-height: var(--item-height);\n position: relative;\n isolation: isolate;\n overflow: visible;\n }\n\n .button {\n @apply flex box-border;\n width: auto;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n &[data-selected=\"true\"] {\n @apply relative;\n background-color: var(--button-selected-background, var(--background-pressed, var(--background-hover, var(--background))));\n color: var(--button-selected-foreground, var(--foreground));\n }\n }\n\n .input {\n @apply flex flex-1 items-stretch overflow-visible;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n > [data-ring=\"true\"] {\n border-radius: inherit;\n }\n }\n\n .select {\n @apply flex items-stretch p-0 bg-transparent border-none;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand {\n @apply flex items-stretch;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand :global(.expand-scope),\n .expand :global(.expand) {\n @apply flex w-full h-full;\n }\n\n .expand :global(.expand) {\n @apply flex-col;\n border-radius: inherit;\n }\n\n .expand :global(.trigger) {\n @apply min-h-0;\n border-radius: inherit;\n }\n\n .trigger {}\n\n .group {\n .item :is(.button, .select) {\n border: none;\n }\n\n .input > [data-input-focus-surface=\"true\"] {\n border: none;\n }\n\n .button[data-selected=\"true\"] {\n font-weight: 500;\n }\n\n .item.divider > [role=\"separator\"] {\n --divider-background: var(--background);\n }\n\n &.none {\n .item:not(.divider) {\n overflow: hidden;\n }\n\n :is(.button, .trigger, .select) {\n border-radius: 0;\n --background-radius: 0;\n --background-inner-radius: 0;\n }\n\n .input {\n --radius-sm: 0;\n }\n\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .item:last-child {\n --group-item-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n }\n\n .item:only-child {\n --group-item-radius: var(--background-inner-radius);\n }\n\n &.horizontal {\n .item:first-child :is( .button, .trigger, .input > *, .select) {\n border-top-left-radius: var(--background-inner-radius);\n border-bottom-left-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is( .button, .trigger, .input > *, .select) {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child .trigger .icon-section {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n\n &.vertical {\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) var(--background-inner-radius) 0 0;\n }\n\n .item:last-child {\n --group-item-radius: 0 0 var(--background-inner-radius) var(--background-inner-radius);\n }\n\n .item:first-child :is(\n .button,\n .trigger,\n .input > *,\n .select\n ) {\n border-top-left-radius: var(--background-inner-radius);\n border-top-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is(\n .button,\n .trigger,\n .input > *,\n .select\n ) {\n border-bottom-left-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n }\n\n &:is(.xs, .sm) {\n .item {\n --group-item-radius: var(--background-inner-radius);\n }\n\n :is(.button, .trigger, .select) {\n border-radius: var(--background-inner-radius);\n }\n\n .input {\n --radius-sm: var(--background-inner-radius);\n }\n }\n }\n\n .group [data-ring=\"true\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n }\n\n .group :global(.focus-indicator) {\n display: none;\n }\n\n .group [data-focus-indicator=\"local\"] {\n display: none;\n }\n\n :is(.button[data-focus-visible=\"true\"], .trigger[data-focus-visible=\"true\"]) {\n @apply outline-none;\n box-shadow: none;\n }\n}\n",
4863
+ "group": "@reference \"tailwindcss\";\n\n@layer components {\n .group {\n --layout-radius-size: calc(var(--spacing) * 1.5);\n --layout-padding-size: var(--layout-radius-size);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-border-width: var(--border-width-base, 1px);\n --background-inner-radius: calc(var(--background-radius) - var(--background-border-width));\n --layout-text-height: calc(0.8em * var(--leading-tight, 1.25));\n --layout-vertical-spacing: calc(var(--spacing) * 4);\n --layout-border-height: calc(var(--background-border-width) * 2);\n --layout-padding-height: calc(var(--layout-padding-size) * 2);\n --layout-control-height: calc(\n var(--layout-text-height) +\n var(--layout-vertical-spacing) +\n var(--layout-border-height)\n );\n --item-height: max(\n calc(\n var(--layout-control-height) -\n var(--layout-padding-height) -\n var(--layout-border-height)\n ),\n 0px\n );\n\n @apply flex overflow-hidden shrink-0 box-border;\n color: var(--foreground, currentColor);\n background-color: var(--background, transparent);\n border: var(--background-border-width) solid var(--background-border, transparent);\n border-radius: var(--background-radius);\n padding: var(--layout-padding-size);\n\n &.horizontal {\n @apply flex-row items-stretch;\n height: var(--layout-control-height);\n\n .item.divider {\n margin-block: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n height: 100%;\n }\n }\n\n &.vertical {\n @apply flex-col;\n\n .item.divider {\n margin-inline: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n width: 100%;\n }\n }\n\n &.none {\n --layout-padding-size: 0px;\n @apply gap-0;\n }\n\n &.xs {\n --layout-radius-size: calc(var(--spacing) * 0.875);\n @apply space-x-0.5;\n }\n\n &.sm {\n --layout-radius-size: calc(var(--spacing) * 1.25);\n @apply space-x-1;\n }\n\n }\n\n .item {\n @apply flex items-stretch;\n position: relative;\n isolation: isolate;\n border-radius: var(--group-item-radius, 0);\n overflow: visible;\n\n &.grow {\n flex: 1;\n }\n\n &.divider {\n @apply p-0 shrink-0 flex-none;\n\n > [role=\"separator\"] {\n flex: 0 0 auto;\n }\n }\n }\n\n :is(.button, .input, .select, .expand) {\n height: 100%;\n min-height: var(--item-height);\n position: relative;\n isolation: isolate;\n overflow: visible;\n }\n\n .button {\n @apply flex box-border;\n width: auto;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n &[data-selected=\"true\"] {\n @apply relative;\n background-color: var(--button-selected-background, var(--background-pressed, var(--background-hover, var(--background))));\n color: var(--button-selected-foreground, var(--foreground));\n }\n }\n\n .horizontal .item.icon-button-item {\n @apply flex-1;\n }\n\n .item.icon-button-item > .button {\n @apply w-full;\n aspect-ratio: auto;\n }\n\n .item.icon-button-item > .button:global(.icon) {\n padding-inline: calc(var(--spacing) * 2);\n }\n\n .item.icon-button-item > .button:global(.icon):global(.sm) {\n padding-inline: calc(var(--spacing) * 1.5);\n }\n\n .item.icon-button-item > .button:global(.icon):global(.lg) {\n padding-inline: calc(var(--spacing) * 2.5);\n }\n\n .input {\n @apply flex flex-1 items-stretch overflow-visible;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n > [data-ring=\"true\"] {\n border-radius: inherit;\n }\n }\n\n .select {\n @apply flex items-stretch p-0 bg-transparent border-none;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand {\n @apply flex items-stretch;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand :global(.expand-scope),\n .expand :global(.expand) {\n @apply flex w-full h-full;\n }\n\n .expand :global(.expand) {\n @apply flex-col;\n border-radius: inherit;\n }\n\n .expand :global(.trigger) {\n @apply min-h-0;\n border-radius: inherit;\n }\n\n .trigger {}\n\n .group {\n .item :is(.button, .select) {\n border: none;\n }\n\n .input > [data-input-focus-surface=\"true\"] {\n border: none;\n }\n\n .button[data-selected=\"true\"] {\n font-weight: 500;\n }\n\n .item.divider > [role=\"separator\"] {\n --divider-background: var(--background);\n }\n\n &.none {\n .item:not(.divider) {\n overflow: hidden;\n }\n\n :is(.button, .trigger, .select) {\n border-radius: 0;\n --background-radius: 0;\n --background-inner-radius: 0;\n }\n\n .input {\n --radius-sm: 0;\n }\n\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .item:last-child {\n --group-item-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n }\n\n .item:only-child {\n --group-item-radius: var(--background-inner-radius);\n }\n\n &.horizontal {\n .item:first-child :is( .button, .trigger, .input > *, .select) {\n border-top-left-radius: var(--background-inner-radius);\n border-bottom-left-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is( .button, .trigger, .input > *, .select) {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child .trigger .icon-section {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n\n &.vertical {\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) var(--background-inner-radius) 0 0;\n }\n\n .item:last-child {\n --group-item-radius: 0 0 var(--background-inner-radius) var(--background-inner-radius);\n }\n\n .item:first-child :is(.button, .trigger, .input > *, .select) {\n border-top-left-radius: var(--background-inner-radius);\n border-top-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is(.button, .trigger, .input > *, .select) {\n border-bottom-left-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n }\n\n &:is(.xs, .sm) {\n .item {\n --group-item-radius: var(--background-inner-radius);\n }\n\n :is(.button, .trigger, .select) {\n border-radius: var(--background-inner-radius);\n }\n\n .input {\n --radius-sm: var(--background-inner-radius);\n }\n }\n }\n\n .group [data-ring=\"true\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n }\n\n .group :global(.focus-indicator) {\n display: none;\n }\n\n .group [data-focus-indicator=\"local\"] {\n display: none;\n }\n\n :is(.button[data-focus-visible=\"true\"], .trigger[data-focus-visible=\"true\"]) {\n @apply outline-none;\n box-shadow: none;\n }\n}\n",
4865
4864
  "input": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .input {\n height: fit-content;\n flex: 1;\n min-width: 0;\n @apply py-1.5 px-3;\n font-family: inherit;\n font-size: var(--text-xs);\n line-height: var(--leading-snug);\n color: var(--foreground);\n background-color: transparent;\n border: none;\n outline: none;\n box-sizing: border-box;\n\n &::placeholder {\n color: var(--placeholder);\n }\n\n &[data-disabled] {\n color: var(--disabled-foreground);\n cursor: not-allowed;\n }\n\n /* Hide default browser spinners for number inputs */\n &[type=\"number\"] {\n\n &::-webkit-outer-spin-button,\n &::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n display: none;\n }\n\n /* Firefox */\n &[type=\"number\"] {\n -moz-appearance: textfield;\n }\n }\n }\n\n .icon-wrapper {\n @apply z-10 flex items-center;\n pointer-events: none;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n color: var(--foreground, currentColor);\n }\n\n .icon-left {\n @apply relative;\n }\n\n .icon-right {\n @apply relative;\n }\n\n .container {\n --adornment-offset: calc(var(--spacing, 0.25rem) * 1.5);\n\n display: flex;\n align-items: center;\n width: 100%;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n box-sizing: border-box;\n overflow: hidden;\n\n &[data-disabled] {\n background-color: var(--disabled-background);\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n &[data-variant=\"ghost\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n\n background-color: transparent;\n border-color: transparent;\n }\n }\n\n .start-adornments,\n .end-adornments {\n @apply flex items-center gap-1;\n align-self: stretch;\n flex-shrink: 0;\n pointer-events: none;\n }\n\n .start-adornments {\n @apply pl-2.5;\n }\n\n .end-adornments {\n padding-right: var(--adornment-offset);\n\n &:has(.controls) {\n padding-right: 0;\n }\n\n &:has([data-hint]) {\n padding-right: 0;\n }\n }\n\n .actions {\n @apply flex items-center gap-1;\n pointer-events: auto;\n }\n\n .action {\n @apply flex items-center justify-center p-2;\n border-radius: 0.25rem;\n color: var(--action-foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--action-background-hover);\n color: var(--action-foreground-hover);\n }\n\n .hint {\n @apply inline-flex items-center justify-center whitespace-nowrap;\n flex-shrink: 0;\n margin-inline-start: calc(var(--spacing, 0.25rem) * 0.5);\n margin-inline-end: var(--adornment-offset);\n font-size: var(--text-sm);\n line-height: 1;\n color: var(--foreground);\n background-color: var(--background);\n pointer-events: auto;\n }\n\n .controls {\n @apply flex w-7.5 flex-col;\n align-self: stretch;\n min-height: 100%;\n border-left: var(--border-width-base, 1px) solid var(--background-border);\n pointer-events: auto;\n }\n\n .controls[data-disabled] {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .stepper {\n @apply flex w-full flex-1 items-center justify-center p-0 cursor-pointer;\n flex: 1;\n background-color: transparent;\n border: none;\n color: var(--foreground);\n --active-background: var(--background-700);\n --active-color: var(--foreground-100);\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &+.stepper {\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n &:hover:not(:disabled) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--hover-background);\n color: var(--hover-color);\n }\n\n &:active:not(:disabled) {\n background-color: var(--active-background);\n color: var(--active-color);\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n }\n}\n",
4866
- "label": "@reference \"tailwindcss\";\n\n@layer components {\n .label {\n --background: transparent;\n --foreground: var(--foreground-primary);\n --foreground-disabled: var(--foreground-secondary);\n --foreground-error: var(--danger-600);\n }\n\n .label > label {\n display: block;\n font-family: inherit;\n font-size: var(--text-sm);\n color: var(--foreground);\n transition: color 150ms ease;\n\n &[data-size=\"sm\"] { font-size: var(--text-sm); }\n &[data-size=\"lg\"] { font-size: var(--text-md); }\n\n &[data-disabled] {\n color: var(--foreground-disabled);\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n &[data-error] {\n color: var(--foreground-error);\n }\n }\n\n .label > .required-indicator {\n margin-left: 0.25rem;\n color: var(--required-color);\n }\n\n .label > .helper-text {\n --helper-foreground: var(--foreground-secondary);\n --helper-foreground-error: var(--danger-600);\n\n display: block;\n font-size: var(--text-sm);\n margin-top: 0.25rem;\n transition: color 150ms ease;\n color: var(--helper-foreground);\n\n &[data-error] {\n color: var(--helper-foreground-error);\n }\n }\n}\n",
4867
- "list": "@reference \"tailwindcss\";\n\n@layer components {\n .container {\n --gap-scale: 0.75;\n\n color: var(--foreground);\n @apply flex flex-col;\n gap: calc(var(--spacing, 0.25rem) * var(--list-gap-step, 0) * var(--gap-scale, 1));\n }\n\n .container[data-orientation=\"horizontal\"] {\n @apply flex-row flex-wrap;\n }\n\n .header {\n @apply flex items-center justify-between;\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n padding-top: 1rem;\n padding-bottom: 1rem;\n backdrop-filter: blur(12px);\n z-index: 10;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n }\n\n .header > :first-child {\n font-weight: var(--font-weight-semibold);\n font-size: 1.125rem;\n color: var(--header-title-foreground);\n }\n\n .header > :last-child {\n color: var(--header-subtitle-foreground);\n }\n\n .item {\n --background: transparent;\n\n @apply flex gap-3 px-2 py-1 cursor-pointer;\n background-color: var(--background);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .item[data-focus-visible=\"true\"] {\n box-shadow:\n inset 0 0 0 1px var(--item-focus-visible-background, var(--focus-visible-background)),\n 0 0 0 2px var(--item-focus-visible, var(--focus-visible));\n border-radius: var(--item-radius, var(--radius-sm, 0.375rem));\n outline: none;\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .container[data-keyboard-mode=\"true\"] .item[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.6);\n pointer-events: none;\n }\n\n .checkbox,\n .control,\n .media {\n @apply flex items-center justify-center flex-shrink-0;\n }\n\n .control {\n margin-left: auto;\n }\n\n .control[data-placement=\"start\"] {\n margin-left: 0;\n }\n\n .media {\n @apply h-8 w-8;\n }\n\n .title {\n font-size: var(--text-sm);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n @apply truncate;\n }\n\n .desc {\n font-size: var(--text-sm);\n color: var(--desc-foreground);\n @apply truncate;\n }\n\n .actionGroup {\n @apply flex items-center;\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n }\n\n .actionGroup[data-justify=\"between\"] { justify-content: space-between; }\n .actionGroup[data-justify=\"start\"] { justify-content: flex-start; }\n .actionGroup[data-justify=\"end\"] { justify-content: flex-end; }\n\n .actions {\n align-items: center;\n gap: 0.25rem;\n margin-left: auto;\n flex-shrink: 0;\n @apply flex p-1.5 opacity-70 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100;\n }\n\n .action {\n --background: transparent;\n\n @apply flex items-center justify-center;\n border-radius: 0.25rem;\n background-color: var(--background);\n color: var(--foreground);\n @apply p-2;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex p-6 pb-12;\n }\n\n .footer[data-align=\"center\"] { justify-content: center; }\n .footer[data-align=\"start\"] { justify-content: flex-start; }\n .footer[data-align=\"end\"] { justify-content: flex-end; }\n\n .container[data-spacing=\"sm\"] .footer {\n padding: 0.375rem 0.75rem;\n padding-bottom: 0.375rem;\n }\n}\n",
4865
+ "label": "@reference \"tailwindcss\";\n\n@layer components {\n .label {\n --background: transparent;\n --foreground: var(--foreground-primary);\n --disabled-foreground: var(--foreground-secondary);\n --error-foreground: var(--danger-600);\n --helper-color: var(--foreground-secondary);\n --helper-error-color: var(--danger-600);\n --required-color: var(--danger-600);\n }\n\n .text {\n display: block;\n font-family: inherit;\n font-size: var(--text-sm);\n color: var(--foreground);\n transition: color 150ms ease;\n\n &[data-disabled] {\n color: var(--disabled-foreground);\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n &[data-error] {\n color: var(--error-foreground);\n }\n }\n\n .required-indicator {\n margin-left: 0.25rem;\n color: var(--required-color);\n }\n\n .helper-text {\n display: block;\n font-size: var(--text-sm);\n margin-top: 0.25rem;\n transition: color 150ms ease;\n color: var(--helper-color);\n\n &[data-error] {\n color: var(--helper-error-color);\n }\n }\n}\n",
4866
+ "list": "@reference \"tailwindcss\";\n\n@layer components {\n .container {\n --gap-scale: 0.75;\n\n color: var(--foreground);\n @apply flex flex-col;\n gap: calc(var(--spacing, 0.25rem) * var(--list-gap-step, 0) * var(--gap-scale, 1));\n }\n\n .container[data-orientation=\"horizontal\"] {\n @apply flex-row flex-wrap;\n }\n\n .header {\n @apply flex items-center justify-between;\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n padding-top: 1rem;\n padding-bottom: 1rem;\n backdrop-filter: blur(12px);\n z-index: 10;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n }\n\n .header > :first-child {\n font-weight: var(--font-weight-semibold);\n font-size: 1.125rem;\n color: var(--header-title-foreground);\n }\n\n .header > :last-child {\n color: var(--header-subtitle-foreground);\n }\n\n .item {\n --background: transparent;\n\n @apply flex gap-3 px-2 py-1 cursor-pointer;\n background-color: var(--background);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .item[data-focus-visible=\"true\"] {\n box-shadow:\n inset 0 0 0 1px var(--item-focus-visible-background, var(--focus-visible-background)),\n 0 0 0 2px var(--item-focus-visible, var(--focus-visible));\n border-radius: var(--item-radius, var(--radius-sm, 0.375rem));\n outline: none;\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .container[data-keyboard-mode=\"true\"] .item[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.6);\n pointer-events: none;\n }\n\n .checkbox,\n .control,\n .media {\n @apply flex items-center justify-center flex-shrink-0;\n }\n\n .control {\n margin-left: auto;\n }\n\n .control[data-placement=\"start\"] {\n margin-left: 0;\n }\n\n .media {\n @apply h-8 w-8;\n }\n\n .title {\n font-size: var(--text-sm);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n @apply truncate;\n }\n\n .desc {\n font-size: var(--text-sm);\n color: var(--desc-foreground);\n @apply truncate;\n }\n\n .actionGroup {\n @apply flex items-center;\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n }\n\n .actionGroup[data-justify=\"between\"] { justify-content: space-between; }\n .actionGroup[data-justify=\"start\"] { justify-content: flex-start; }\n .actionGroup[data-justify=\"end\"] { justify-content: flex-end; }\n\n .actions {\n align-items: center;\n gap: 0.25rem;\n margin-left: auto;\n flex-shrink: 0;\n @apply flex p-1.5 opacity-70 transition-opacity;\n }\n\n .item:hover .actions,\n .item:focus-within .actions {\n opacity: 1;\n }\n\n .action {\n --background: transparent;\n\n @apply flex items-center justify-center;\n border-radius: 0.25rem;\n background-color: var(--background);\n color: var(--foreground);\n @apply p-2;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex p-6 pb-12;\n }\n\n .footer[data-align=\"center\"] { justify-content: center; }\n .footer[data-align=\"start\"] { justify-content: flex-start; }\n .footer[data-align=\"end\"] { justify-content: flex-end; }\n\n .container[data-spacing=\"sm\"] .footer {\n padding: 0.375rem 0.75rem;\n padding-bottom: 0.375rem;\n }\n}\n",
4868
4867
  "mask": "@reference \"tailwindcss\";\n\n@layer components {\n .mask {\n @apply relative h-full w-full;\n }\n}\n\n.mask[style*=\"mask-image\"],\n.mask[style*=\"-webkit-mask-image\"] {\n -webkit-mask-size: 100% 100%;\n mask-size: 100% 100%;\n}\n\n.mask[style*=\"--mask-clip-path\"] {\n clip-path: var(--mask-clip-path);\n}\n\n.mask-gradient {\n background: var(--mask-gradient);\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: transparent;\n color: transparent;\n}\n",
4869
4868
  "menu": "@reference \"tailwindcss\";\n\n@layer components {\n :global(.menu) {\n display: contents;\n\n .content,\n .sub-content {\n --content-padding: calc(var(--spacing) * 1.5);\n --content-radius: var(--radius-sm, 0.375rem);\n --content-inner-radius: calc(var(--content-radius) - var(--border-width-base, 1px));\n --open-animation: slide-in-from-top 0.15s var(--ease-snappy-pop);\n --closed-animation: slide-out-to-top 0.15s var(--ease-snappy-pop);\n --disabled-opacity: 0.5;\n\n @apply absolute min-w-40 max-w-80 overflow-hidden;\n z-index: 50000;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--content-radius);\n }\n\n .trigger {\n &[data-type=\"pop-over\"][data-pressed=\"true\"] {\n opacity: 1;\n background-color: var(--background-pressed);\n border-radius: var(--radius-sm, 0.375rem);\n }\n }\n\n .content[data-state=\"open\"],\n .sub-content[data-state=\"open\"] {\n animation: var(--open-animation);\n }\n\n .content[data-state=\"closed\"],\n .sub-content[data-state=\"closed\"] {\n animation: var(--closed-animation);\n }\n\n .list {\n @apply space-y-1;\n max-height: 24rem;\n overflow-y: auto;\n }\n\n .item {\n @apply flex min-w-0 items-center gap-2;\n padding: var(--item-padding, var(--content-padding));\n border-radius: var(--item-radius, var(--content-inner-radius));\n cursor: pointer;\n user-select: none;\n outline: none;\n color: var(--foreground);\n\n &[data-focused=\"true\"] {\n background-color: var(--background-focused, var(--background-hover));\n }\n\n &[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n pointer-events: none;\n }\n }\n\n .item {\n &[data-inset=\"true\"] {\n padding-left: calc(var(--item-padding, var(--content-padding)) * 2.67);\n }\n }\n\n .item-indicator {\n @apply ml-auto flex h-4 w-4 shrink-0 items-center justify-center;\n color: var(--foreground);\n }\n\n .sub-trigger[data-state=\"open\"]:not([data-focused=\"true\"]) {\n background-color: var(--background-focused, var(--background-hover));\n }\n\n .sub-trigger-chevron {\n @apply ml-auto h-4 w-4 shrink-0;\n color: var(--chevron-foreground, currentColor);\n }\n\n .label {\n padding: var(--content-padding);\n color: var(--foreground-muted);\n\n &[data-inset=\"true\"] {\n padding-left: calc(var(--content-padding) * 2.67);\n }\n }\n\n .separator {\n @apply -mx-1 my-1 h-px;\n background-color: var(--background-border);\n }\n\n .shortcut {\n margin-left: auto;\n color: var(--foreground-muted);\n }\n }\n\n @keyframes slide-in-from-top { from { opacity: 0; translate: 0 -2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-out-to-top { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 -2px; } }\n}\n",
4870
4869
  "modal": "@reference \"tailwindcss\";\n\n@layer components {\n .backdrop {\n @apply absolute inset-0 cursor-pointer;\n background-color: var(--backdrop-background);\n backdrop-filter: blur(4px);\n }\n\n .panel {\n @apply relative flex w-full flex-col overflow-hidden;\n z-index: 1;\n max-height: 90vh;\n margin: 1rem;\n color: var(--foreground);\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n pointer-events: auto;\n overflow: hidden;\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n box-shadow: 0 0 0 1.5px var(--focus-visible);\n }\n }\n\n .header {\n @apply flex shrink-0 items-center justify-between gap-2 px-6 py-4;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .title {\n @apply m-0;\n font-size: 1.125rem;\n font-weight: var(--font-weight-semibold);\n color: var(--title-foreground, var(--foreground));\n }\n\n .spacer {\n flex: 1;\n }\n\n .close {\n @apply ml-auto flex items-center justify-center cursor-pointer;\n background: none;\n border: none;\n color: var(--foreground);\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-pressed=\"true\"] {\n transform: scale(0.92);\n }\n\n &[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n border-radius: var(--radius-xs, 0.25rem);\n }\n }\n\n .close-icon {\n @apply h-5 w-5;\n }\n\n .content {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n color: var(--foreground);\n }\n\n .content::-webkit-scrollbar {\n width: 6px;\n }\n\n .content::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .content::-webkit-scrollbar-thumb {\n background-color: var(--background);\n border-radius: 3px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .content::-webkit-scrollbar-thumb:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex shrink-0 items-center justify-between gap-4 px-6 py-4;\n background-color: var(--footer-background, var(--background));\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n /* Size variants */\n .panel[data-size=\"fit\"] {\n width: fit-content;\n }\n\n .panel[data-size=\"auto\"] {\n max-width: min(90vw, 28rem);\n }\n\n /* Media queries for smaller screens */\n @media (max-width: 640px) {\n .panel {\n margin: 1rem;\n }\n\n .content {\n max-height: calc(100vh - 10rem);\n }\n }\n}\n",
@@ -4875,7 +4874,7 @@ export const generatedStyles = {
4875
4874
  "progress": "@reference \"tailwindcss\";\n\n@layer components {\n .bar {\n @apply relative w-full overflow-hidden;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--background);\n }\n\n .bar { height: 0.5rem; }\n\n .fill {\n @apply h-full;\n border-radius: var(--radius-full, 9999px);\n background-color: var(--background);\n transition: width 300ms var(--ease-snappy-pop);\n }\n\n .fill[data-animated=\"true\"] {\n animation: pulse 2s var(--ease-gentle-ease) infinite;\n }\n\n .fill[data-indeterminate=\"true\"] {\n width: 33.333%;\n animation: progress-indeterminate 1.5s var(--ease-gentle-ease) infinite;\n }\n\n .wrapper {\n @apply w-full;\n }\n\n .wrapper[data-has-label=\"true\"] {\n @apply space-y-1;\n }\n\n .label-row {\n @apply flex items-center justify-between;\n font-size: var(--text-sm);\n color: var(--foreground);\n }\n\n .label {\n user-select: none;\n }\n\n .value {\n font-variant-numeric: tabular-nums;\n }\n\n @keyframes pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n }\n\n @keyframes progress-indeterminate {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(400%); }\n }\n}\n",
4876
4875
  "radio": "@reference \"tailwindcss\";\n\n@layer components {\n .radio-items {\n @apply flex flex-col gap-3;\n }\n\n .radio-item {\n @apply flex items-start gap-3 cursor-pointer select-none;\n position: relative;\n overflow: visible;\n }\n\n .radio-surface {\n @apply inline-flex shrink-0;\n border-radius: 9999px;\n }\n\n .radio-input {\n @apply absolute inset-0 h-full w-full cursor-pointer opacity-0;\n }\n\n .radio {\n --disabled-opacity: 0.6;\n @apply relative flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center;\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: 9999px;\n background-color: var(--background);\n color: var(--foreground);\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n }\n }\n\n .radio-item:active .radio {\n transform: scale(0.92);\n }\n\n .dot {\n border-radius: 9999px;\n background-color: var(--background);\n transform: scale(0);\n }\n\n .radio[data-selected=\"true\"] .dot {\n transform: scale(1);\n }\n\n @media (hover: hover) {\n .radio-item:not([data-disabled=\"true\"]):hover .radio {\n opacity: 0.9;\n }\n }\n\n .radio-item[data-disabled=\"true\"] .radio {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n .radio-label {\n @apply cursor-pointer;\n color: var(--foreground);\n font-size: inherit;\n font-weight: var(--font-weight-medium, 500);\n line-height: inherit;\n user-select: none;\n\n &[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n }\n\n .radio-description {\n color: var(--foreground);\n font-size: var(--text-sm, 0.875rem);\n margin-top: 0.125rem;\n }\n\n .helper-text {\n color: var(--foreground);\n font-size: var(--text-sm, 0.875rem);\n margin-top: 0.5rem;\n margin-left: 2rem;\n }\n\n .radio.sm {\n @apply h-4 w-4;\n }\n\n .radio.sm .dot {\n width: 0.375rem;\n height: 0.375rem;\n }\n\n .radio.md {\n @apply h-5 w-5;\n }\n\n .radio.md .dot {\n width: 0.5rem;\n height: 0.5rem;\n }\n\n .radio.lg {\n @apply h-6 w-6;\n }\n\n .radio.lg .dot {\n width: 0.625rem;\n height: 0.625rem;\n }\n}\n",
4877
4876
  "scroll": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply relative;\n min-height: 0;\n }\n\n .vertical {\n --scrollbar-width: 12px;\n }\n\n .horizontal {\n --scrollbar-height: 12px;\n }\n\n .content {\n @apply h-full w-full;\n overflow: auto;\n }\n\n .vertical .content {\n overflow-y: auto;\n overflow-x: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .vertical[data-inline=\"true\"] .content {\n padding-right: 16px;\n }\n\n .horizontal .content {\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n\n .horizontal[data-inline=\"true\"] .content {\n padding-bottom: 16px;\n }\n\n .vertical .content::-webkit-scrollbar,\n .horizontal .content::-webkit-scrollbar { display: none; }\n\n .track {\n @apply absolute;\n z-index: 10;\n background-color: var(--background);\n }\n\n .track[data-hide=\"true\"] {\n transition-property: opacity;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .vertical .track {\n right: 4px;\n top: var(--scroll-padding-y, 0);\n width: 12px;\n height: calc(100% - 2 * var(--scroll-padding-y, 0));\n box-sizing: border-box;\n }\n\n .horizontal .track {\n bottom: 2px;\n left: 0;\n height: 12px;\n width: 100%;\n }\n\n .thumb {\n position: absolute;\n border-radius: calc(var(--radius-xs, 0.25rem) * 0.80);\n background-color: var(--background);\n transition-property: background-color, width, height;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .thumb:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .vertical .thumb {\n width: 6px;\n margin-left: 6px;\n transition-property: background-color, width, margin-left;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .vertical .thumb:hover,\n .vertical[data-pressed] .thumb {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n width: 8px;\n margin-left: 4px;\n }\n\n .horizontal .thumb {\n height: 6px;\n margin-top: 6px;\n transition-property: background-color, height, margin-top;\n transition-duration: var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms));\n transition-timing-function: var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .horizontal .thumb:hover,\n .horizontal[data-pressed] .thumb {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n height: 8px;\n margin-top: 4px;\n }\n}\n",
4878
- "select": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .select {\n --disabled-opacity: 0.5;\n --trigger-padding-inline: calc(var(--spacing) * 1.60);\n --trigger-padding-block: calc(var(--spacing) * 1.30);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n font-size: var(--foreground-size);\n height: fit-content;\n align-self: center;\n\n @apply p-0 gap-0 w-full flex-row items-center;\n position: relative;\n overflow: visible;\n\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n\n @apply select-none cursor-pointer;\n\n &[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n &[data-pressed=\"true\"]:not([data-disabled]) {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n }\n\n &[data-open=\"true\"] {\n background-color: var(--background-hover);\n }\n\n &:global(.group) {\n height: 100%;\n align-self: stretch;\n }\n }\n\n .trigger {\n @apply flex items-stretch flex-1 gap-0 w-full h-full min-h-0;\n\n background: transparent;\n\n @apply border-none cursor-pointer select-none;\n\n @media (hover: hover) {\n &:not([data-disabled]):hover .icon-section,\n &:not([data-disabled]):hover .value-section:not(:empty) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover);\n }\n }\n\n &[data-focus-visible=\"true\"] {\n @apply outline-none;\n }\n }\n\n .trigger-compact {\n @apply flex-none w-auto;\n }\n\n .select button.trigger { @apply p-0; }\n\n .value-section {\n @apply flex items-center flex-1 min-w-0 gap-0.5;\n\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n font-size: var(--foreground-size);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:only-child {\n border-radius: var(--background-inner-radius);\n justify-content: center;\n }\n &:empty {\n flex: 0;\n padding: 0;\n min-width: auto;\n }\n }\n\n .icon-section {\n @apply flex items-center justify-center shrink-0;\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .icon {\n @apply flex items-center justify-center w-4 h-4 opacity-70;\n }\n\n .select .trigger[data-open=\"true\"] .icon {\n transform: rotate(180deg);\n }\n\n .value {\n @apply flex items-center flex-1 min-w-0 gap-2 bg-transparent border-none;\n cursor: inherit;\n }\n\n .value-icon {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n color: var(--foreground);\n }\n\n .value-text {\n font-weight: var(--font-weight-medium);\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .content,\n .sub-content {\n --item-padding-inline: calc(var(--spacing) * 1.5);\n --item-padding-block: var(--spacing);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n overflow: hidden;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n }\n\n .content-root,\n .sub-content-root {\n position: absolute;\n }\n\n .content {\n &[data-state=\"open\"][data-placement=\"bottom\"] { animation: slide-in-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"open\"][data-placement=\"top\"] { animation: slide-in-from-bottom 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"bottom\"] { animation: slide-out-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"top\"] { animation: slide-out-from-bottom 0.15s var(--ease-snappy-pop); }\n }\n\n .list {\n @apply space-y-1;\n }\n\n .item,\n .sub-trigger {\n @apply flex items-center gap-2 outline-none cursor-default select-none;\n background-color: var(--background);\n border-radius: var(--background-inner-radius);\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-disabled] {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n }\n\n .item {\n --item-padding-inline: var(--trigger-padding-inline);\n --item-padding-block: calc(var(--trigger-padding-block) * 1.15);\n\n padding: var(--item-padding-block) var(--item-padding-inline);\n\n &[data-selected=\"true\"] {\n color: var(--foreground);\n }\n\n &[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .item-content {\n @apply flex flex-col flex-1 min-w-0;\n }\n\n .item-text {\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground-muted);\n @apply min-w-0 whitespace-normal break-words;\n }\n\n .item-icon, .item-indicator {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n }\n\n .item-icon { color: var(--icon-foreground); }\n .item-indicator { color: var(--indicator-foreground); margin-left: auto; }\n\n .item-with-description { @apply items-start py-2; }\n .item-icon-with-description, .item-indicator-with-description { @apply mt-0.5; }\n\n .separator {\n @apply my-1 -mx-1 h-px;\n background-color: var(--background-border);\n }\n\n .placeholder {\n color: var(--foreground-muted);\n }\n\n .icon-prefix {\n @apply inline-flex items-center shrink-0;\n }\n\n .select[data-mode=\"multiple\"] .item { gap: 0.5rem; }\n\n .search-trigger {\n @apply flex items-stretch relative bg-transparent cursor-text overflow-hidden;\n border-radius: var(--background-inner-radius);\n transition: box-shadow 150ms var(--ease-snappy-pop), border-color 150ms var(--ease-snappy-pop);\n\n &:focus-within {\n @apply outline-none;\n z-index: 1;\n }\n }\n\n .search-trigger :global(.focus-indicator) {\n display: none;\n }\n\n .search-value-section {\n @apply p-0;\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .input {\n padding-right: calc(var(--trigger-padding-inline) * 2 + 1rem);\n @apply border-none rounded-none shadow-none bg-transparent;\n\n &[data-focused], &[data-focus-visible] {\n @apply border-none shadow-none;\n }\n }\n\n .search-content-input {\n @apply border-none rounded-none bg-transparent;\n }\n\n .search-icon-section {\n @apply absolute right-0 top-0 bottom-0 flex items-center justify-center bg-transparent pointer-events-none;\n padding-inline: var(--trigger-padding-inline);\n }\n\n\n .search-wrapper {\n @apply overflow-hidden;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .empty-state {\n @apply px-3 py-2;\n color: var(--foreground-muted);\n }\n\n .content[data-placement=\"top\"] .search-wrapper {\n border-radius: 0;\n border-bottom: none;\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .sub-trigger {\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n\n &[data-highlighted=\"true\"],\n &[data-open=\"true\"]:not([data-highlighted=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .sub-trigger-chevron {\n @apply shrink-0 ml-auto w-4 h-4 opacity-60;\n }\n\n .sub-content {\n min-width: 160px;\n max-width: 320px;\n }\n\n @keyframes slide-in-from-top { from { opacity: 0; translate: 0 -2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-in-from-bottom { from { opacity: 0; translate: 0 2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-out-from-top { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 -2px; } }\n @keyframes slide-out-from-bottom { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 2px; } }\n}\n",
4877
+ "select": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .select {\n --disabled-opacity: 0.5;\n --trigger-padding-inline: calc(var(--spacing) * 1.60);\n --trigger-padding-block: calc(var(--spacing) * 1.30);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n font-size: var(--foreground-size);\n height: fit-content;\n align-self: center;\n\n @apply p-0 gap-0 w-full flex-row items-center;\n position: relative;\n overflow: visible;\n\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n\n @apply select-none cursor-pointer;\n\n &[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n &[data-pressed=\"true\"]:not([data-disabled]) {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n }\n\n &[data-open=\"true\"] {\n background-color: var(--background-hover);\n }\n\n &:global(.group) {\n height: 100%;\n align-self: stretch;\n }\n }\n\n .trigger {\n @apply flex items-stretch flex-1 gap-0 w-full h-full min-h-0;\n\n background: transparent;\n\n @apply border-none cursor-pointer select-none;\n\n @media (hover: hover) {\n &:not([data-disabled]):hover .icon-section,\n &:not([data-disabled]):hover .value-section:not(:empty) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover);\n }\n }\n\n &[data-focus-visible=\"true\"] {\n @apply outline-none;\n }\n }\n\n .trigger-compact {\n @apply flex-none w-auto;\n }\n\n .select button.trigger { @apply p-0; }\n\n .value-section {\n @apply flex items-center flex-1 min-w-0 gap-0.5;\n\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n font-size: var(--foreground-size);\n &:only-child {\n border-radius: var(--background-inner-radius);\n justify-content: center;\n }\n &:empty {\n flex: 0;\n padding: 0;\n min-width: auto;\n }\n }\n\n .icon-section {\n @apply flex items-center justify-center shrink-0;\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n }\n\n .icon {\n @apply flex items-center justify-center w-4 h-4 opacity-70;\n }\n\n.value {\n @apply flex items-center flex-1 min-w-0 gap-2 bg-transparent border-none;\n cursor: inherit;\n }\n\n .value-icon {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n color: var(--foreground);\n }\n\n .value-text {\n font-weight: var(--font-weight-medium);\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .content,\n .sub-content {\n --item-padding-inline: calc(var(--spacing) * 1.5);\n --item-padding-block: var(--spacing);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n overflow: hidden;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n }\n\n .content-root,\n .sub-content-root {\n position: absolute;\n }\n\n .content {}\n\n .list {\n @apply space-y-1;\n }\n\n .item,\n .sub-trigger {\n @apply flex items-center gap-2 outline-none cursor-default select-none;\n background-color: var(--background);\n border-radius: var(--background-inner-radius);\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n &[data-disabled] {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n }\n\n .item {\n --item-padding-inline: var(--trigger-padding-inline);\n --item-padding-block: calc(var(--trigger-padding-block) * 1.15);\n\n padding: var(--item-padding-block) var(--item-padding-inline);\n\n &[data-selected=\"true\"] {\n color: var(--foreground);\n }\n\n &[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .item-content {\n @apply flex flex-col flex-1 min-w-0;\n }\n\n .item-text {\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground-muted);\n @apply min-w-0 whitespace-normal break-words;\n }\n\n .item-icon, .item-indicator {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n }\n\n .item-icon { color: var(--icon-foreground); }\n .item-indicator { color: var(--indicator-foreground); margin-left: auto; }\n\n .item-with-description { @apply items-start py-2; }\n .item-icon-with-description, .item-indicator-with-description { @apply mt-0.5; }\n\n .separator {\n @apply my-1 -mx-1 h-px;\n background-color: var(--background-border);\n }\n\n .placeholder {\n color: var(--foreground-muted);\n }\n\n .icon-prefix {\n @apply inline-flex items-center shrink-0;\n }\n\n .select[data-mode=\"multiple\"] .item { gap: 0.5rem; }\n\n .search-trigger {\n @apply flex items-stretch relative bg-transparent cursor-text overflow-hidden;\n border-radius: var(--background-inner-radius);\n &:focus-within {\n @apply outline-none;\n z-index: 1;\n }\n }\n\n .search-trigger :global(.focus-indicator) {\n display: none;\n }\n\n .search-value-section {\n @apply p-0;\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .input {\n padding-right: calc(var(--trigger-padding-inline) * 2 + 1rem);\n @apply border-none rounded-none shadow-none bg-transparent;\n\n &[data-focused], &[data-focus-visible] {\n @apply border-none shadow-none;\n }\n }\n\n .search-content-input {\n @apply border-none rounded-none bg-transparent;\n }\n\n .search-icon-section {\n @apply absolute right-0 top-0 bottom-0 flex items-center justify-center bg-transparent pointer-events-none;\n padding-inline: var(--trigger-padding-inline);\n }\n\n\n .search-wrapper {\n @apply overflow-hidden;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .empty-state {\n @apply px-3 py-2;\n color: var(--foreground-muted);\n }\n\n .content[data-placement=\"top\"] .search-wrapper {\n border-radius: 0;\n border-bottom: none;\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .sub-trigger {\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n\n &[data-highlighted=\"true\"],\n &[data-open=\"true\"]:not([data-highlighted=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .sub-trigger-chevron {\n @apply shrink-0 ml-auto w-4 h-4 opacity-60;\n }\n\n .sub-content {\n min-width: 160px;\n max-width: 320px;\n }\n\n}\n",
4879
4878
  "slider": "@reference \"tailwindcss\";\n\n@layer components {\n .slider {\n --disabled-opacity: 0.6;\n --slider-track-size: 0.375rem;\n --slider-thumb-size: 1rem;\n\n @apply relative flex w-full items-center;\n min-inline-size: var(--slider-min-inline-size, 12rem);\n min-height: var(--slider-hit-size, 2rem);\n touch-action: none;\n user-select: none;\n }\n\n .track {\n @apply relative flex grow items-center;\n flex-grow: 1;\n height: var(--slider-track-size);\n overflow: visible;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n border: var(--slider-track-border, 0);\n background: var(\n --slider-track-background,\n var(--background, var(--background-800, transparent))\n );\n }\n\n .range {\n @apply absolute;\n display: var(--slider-range-display, block);\n pointer-events: none;\n border-radius: var(--slider-track-radius, var(--radius-xs, 0.25rem));\n background: var(--slider-range-background, var(--background));\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .thumb {\n @apply absolute block;\n top: 50%;\n width: var(--slider-thumb-size);\n height: var(--slider-thumb-size);\n transform: var(--slider-thumb-transform, translate(-50%, -50%));\n border-radius: var(--radius-full, 9999px);\n outline: none;\n background: var(--slider-thumb-background, var(--background));\n border: var(--slider-thumb-border, 1px solid var(--background-border));\n box-shadow: var(--slider-thumb-shadow, none);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n box-shadow var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .slider[data-orientation=\"horizontal\"] .range {\n top: 0;\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] {\n justify-content: center;\n min-inline-size: auto;\n width: fit-content;\n }\n\n .slider[data-orientation=\"vertical\"] .track {\n width: var(--slider-track-size);\n height: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .range {\n left: 0;\n width: 100%;\n }\n\n .slider[data-orientation=\"vertical\"] .thumb {\n left: 50%;\n top: auto;\n --slider-thumb-transform: translate(-50%, 50%);\n }\n\n .slider[data-disabled=\"true\"] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n .slider[data-disabled=\"true\"] .range {\n background: var(--slider-range-background-disabled, var(--background-disabled, var(--slider-range-background, var(--background))));\n }\n\n .thumb[data-disabled=\"true\"] {\n cursor: not-allowed;\n background: var(--slider-thumb-background-disabled, var(--background-disabled, var(--slider-thumb-background, var(--background))));\n }\n\n .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, -50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n\n .slider[data-orientation=\"vertical\"] .thumb[data-pressed=\"true\"] {\n transform: var(--slider-thumb-transform, translate(-50%, 50%)) scale(var(--slider-thumb-scale-active, 1.08));\n }\n}\n",
4880
4879
  "switch": "@reference \"tailwindcss\";\n\n@layer components {\n .switch {\n --radius: 9999px;\n --inner-radius: calc(var(--radius) - var(--border-width-base));\n\n --width: 2.75rem;\n --height: 1.5rem;\n --thumb-size: 1rem;\n --thumb-offset: 0.25rem;\n\n --disabled-opacity: 0.6;\n\n @apply relative inline-flex cursor-pointer items-center;\n user-select: none;\n border-radius: var(--radius);\n width: var(--width);\n height: var(--height);\n }\n\n .switch-track {\n @apply absolute inset-0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n background-color: var(--background);\n border: var(--border-width-base) solid var(--background-border);\n border-radius: var(--radius);\n }\n\n .switch:active:not([data-disabled]) .switch-track {\n transform: scale(0.98);\n }\n\n .switch-thumb {\n @apply absolute top-0 bottom-0 my-auto;\n left: var(--thumb-offset);\n width: var(--thumb-size);\n height: var(--thumb-size);\n transition: left 180ms var(--ease-snappy-pop), background-color 180ms var(--ease-snappy-pop);\n background-color: var(--foreground);\n border-radius: var(--inner-radius);\n z-index: 1;\n pointer-events: none;\n }\n\n .switch[data-selected] .switch-thumb {\n left: calc(var(--width) - var(--thumb-size) - var(--thumb-offset));\n }\n\n @media (hover: hover) {\n .switch[data-hovered=\"true\"]:not([data-disabled]) .switch-track {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .switch[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n\n .switch-sm {\n --width: 1.75rem;\n --height: 1rem;\n --thumb-size: 0.625rem;\n --thumb-offset: 0.1875rem;\n }\n}\n",
4881
4880
  "table": "@reference \"tailwindcss\";\n\n@layer components {\n .root {\n @apply w-full;\n }\n\n .container {\n @apply w-full overflow-x-auto rounded-sm;\n border: var(--border-width-base) solid var(--border, var(--background-border));\n background-color: var(--container-background, var(--background));\n }\n\n .container {\n display: block;\n max-width: none;\n }\n\n .table {\n @apply w-full;\n display: table;\n border-collapse: collapse;\n min-width: max-content;\n background-color: var(--background, transparent);\n color: var(--foreground);\n font-size: var(--text-xs);\n }\n\n .header {\n display: table-header-group;\n background-color: var(--background);\n }\n\n .body {\n display: table-row-group;\n background-color: var(--background);\n }\n\n .headerRow {\n display: table-row;\n background-color: var(--background);\n }\n\n .headerCell {\n @apply px-4 py-3 text-left;\n display: table-cell;\n background-color: var(--background);\n color: var(--foreground);\n font-weight: var(--header-font-weight, var(--font-weight-semibold));\n white-space: nowrap;\n border-bottom: var(--border-width-base) solid var(--border, var(--background-border));\n }\n\n .headerCell:first-child {\n border-top-left-radius: var(--radius-xs);\n }\n\n .headerCell:last-child {\n border-top-right-radius: var(--radius-xs);\n }\n\n .row {\n display: table-row;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .row[data-interactive=\"true\"] {\n @apply cursor-pointer;\n }\n\n .row:hover:not([data-disabled=\"true\"]) .cell {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .row[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.5);\n }\n\n .row:focus-visible {\n outline: 2px solid var(--focus-ring);\n outline-offset: -2px;\n }\n\n .interactive {\n @apply cursor-pointer;\n }\n\n .cell {\n @apply px-4 py-3 align-middle;\n display: table-cell;\n background-color: var(--background, transparent);\n color: var(--foreground);\n border-bottom: var(--border-width-base) solid var(--border, var(--background-border));\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .row:last-child .cell {\n border-bottom: none;\n }\n\n .row:last-child .cell:first-child {\n border-bottom-left-radius: var(--radius-xs);\n }\n\n .row:last-child .cell:last-child {\n border-bottom-right-radius: var(--radius-xs);\n }\n\n .emptyRow {\n border-bottom: none;\n }\n\n .emptyRow {\n display: table-row;\n }\n\n .emptyState {\n @apply px-4 py-8 text-center;\n background-color: var(--background);\n color: var(--foreground);\n }\n\n .emptyState {\n display: table-cell;\n }\n\n .filterBar {\n @apply mb-4 rounded-xs border p-4;\n border: var(--border-width-base) solid var(--background-border);\n background-color: var(--background);\n }\n\n .filterBar {\n display: block;\n }\n\n .filterGrid {\n @apply grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3;\n background-color: var(--background);\n }\n\n .filterGrid {\n display: grid;\n }\n\n .filterField {\n @apply min-w-0;\n }\n\n .filterLabel {\n @apply mb-2 block;\n color: var(--foreground);\n font-size: var(--filter-label-font-size, var(--text-xs));\n font-weight: var(--filter-label-font-weight, var(--font-weight-medium));\n }\n\n .filterLabel {\n display: block;\n }\n\n .filterInput {\n @apply w-full;\n }\n}\n",
@@ -4892,7 +4891,7 @@ export const generatedSourceCode = {
4892
4891
  },
4893
4892
  "badge": {
4894
4893
  "tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useButton } from \"@react-aria/button\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport css from \"./Badge.module.css\";\n\nimport { X } from \"lucide-react\";\n\ntype BadgeIconSlots = {\n left?: React.ReactNode;\n right?: React.ReactNode;\n};\n\ninterface BadgeIconStyles {\n left?: StyleValue;\n right?: StyleValue;\n}\n\nexport interface BadgeStyleSlots {\n root?: StyleValue;\n icon?: StyleValue | BadgeIconStyles;\n iconLeft?: StyleValue;\n iconRight?: StyleValue;\n dismiss?: StyleValue;\n}\n\nexport type BadgeStylesProp = StylesProp<BadgeStyleSlots>;\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Visual color style of the badge */\n variant?: string;\n /** Icon slots rendered before (left) or after (right) the badge label */\n icon?: React.ReactNode | BadgeIconSlots;\n /** Whether to show a dismiss button */\n dismissible?: boolean;\n /** Called when the dismiss button is clicked */\n onDismiss?: () => void;\n /** Whether to render with a fully rounded pill shape */\n pill?: boolean;\n /** Numeric count to display; replaces children when provided */\n count?: number;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: BadgeStylesProp;\n}\n\ninterface DismissButtonProps {\n onDismiss?: () => void;\n variant: string;\n className?: StyleValue;\n}\n\nfunction DismissButton({ onDismiss, variant, className }: DismissButtonProps) {\n const buttonRef = React.useRef<HTMLDivElement>(null);\n\n const { buttonProps, isPressed } = useButton(\n {\n \"aria-label\": \"Dismiss\",\n onPress: onDismiss,\n },\n buttonRef\n );\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing();\n const { hoverProps, isHovered } = useHover({});\n\n return (\n <div\n {...mergeProps(buttonProps, focusProps, hoverProps)}\n ref={buttonRef}\n role=\"button\"\n tabIndex={0}\n className={cn(\"badge\", variant, \"dismiss\", css.dismiss, className)}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n <X size={14} />\n </div>\n );\n}\n\nconst resolveBadgeBaseStyles = createStylesResolver(['root', 'icon', 'iconLeft', 'iconRight', 'dismiss'] as const);\n\nfunction resolveBadgeStyles(styles: BadgeStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveBadgeBaseStyles(styles);\n const { root, icon, iconLeft, iconRight, dismiss } = styles;\n if (!icon || typeof icon === \"string\" || Array.isArray(icon)) {\n return resolveBadgeBaseStyles({ root, icon: icon as StyleValue | undefined, iconLeft, iconRight, dismiss });\n }\n\n return resolveBadgeBaseStyles({\n root,\n iconLeft: icon.left ?? iconLeft,\n iconRight: icon.right ?? iconRight,\n dismiss,\n });\n}\n\nfunction isBadgeIconSlots(icon: BadgeProps[\"icon\"]): icon is BadgeIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && (\"left\" in icon || \"right\" in icon);\n}\n\nfunction resolveBadgeIcon(icon: BadgeProps[\"icon\"]) {\n if (!icon) {\n return undefined;\n }\n\n if (isBadgeIconSlots(icon)) {\n return icon;\n }\n\n return { left: icon };\n}\n\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n (\n {\n variant = \"default\",\n icon,\n dismissible = false,\n onDismiss,\n pill = false,\n count,\n children,\n className,\n styles,\n ...props\n },\n ref\n ) => {\n const resolved = resolveBadgeStyles(styles);\n const resolvedIcon = resolveBadgeIcon(icon);\n return (\n <span\n ref={ref}\n className={cn(\n \"badge\",\n variant,\n css.badge,\n pill && css.pill,\n dismissible && css.dismissible,\n className,\n resolved.root\n )}\n data-variant={variant}\n data-pill={pill ? \"true\" : undefined}\n data-dismissible={dismissible || undefined}\n {...props}\n >\n {resolvedIcon?.left && (\n <span className={cn(\"badge\", variant, \"icon\", css.icon, resolved.icon, resolved.iconLeft)} aria-hidden=\"true\">\n {resolvedIcon.left}\n </span>\n )}\n {count !== undefined ? count : children}\n {resolvedIcon?.right && (\n <span className={cn(\"badge\", variant, \"icon\", css.icon, resolved.icon, resolved.iconRight)} aria-hidden=\"true\">\n {resolvedIcon.right}\n </span>\n )}\n {dismissible && <DismissButton onDismiss={onDismiss} variant={variant} className={resolved.dismiss} />}\n </span>\n );\n }\n);\n\nBadge.displayName = \"Badge\";\n\nexport { Badge };\n",
4895
- "css": "@reference \"tailwindcss\";\n\n@layer components {\n .badge {\n @apply inline-flex items-center justify-center gap-2 select-none whitespace-nowrap px-1.5;\n height: fit-content;\n width: fit-content;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--background-border, var(--background-600));\n border-radius: var(--radius-sm, 0.375rem);\n font-weight: var(--font-weight-semibold, 600);\n font-size: var(--text-xs, 0.75rem);\n line-height: var(--leading-tight, 1.25);\n }\n\n .badge.dismissible {\n @apply pr-0.5;\n }\n\n .pill {\n border-radius: 9999px;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n }\n\n .dismiss {\n @apply ml-1 flex shrink-0 items-center justify-center p-0 cursor-pointer;\n width: 1em;\n height: 1em;\n line-height: 1;\n border-radius: var(--radius-xs, 0.25rem);\n background-color: var(--dismiss-background, var(--background, transparent));\n color: var(--foreground, var(--foreground-400));\n border: none;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n outline: none;\n }\n\n .dismiss svg {\n width: 100%;\n height: 100%;\n }\n\n .dismiss[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover, var(--dismiss-background, transparent));\n }\n\n .dismiss[data-pressed=\"true\"] {\n background-color: var(\n --background-pressed,\n var(--background-hover, var(--dismiss-background, transparent))\n );\n transform: scale(0.95);\n }\n\n .dismiss[data-focus-visible=\"true\"] {\n box-shadow: 0 0 0 1.5px var(--focus-visible, var(--foreground));\n }\n}\n",
4894
+ "css": "@reference \"tailwindcss\";\n\n@layer components {\n .badge {\n @apply inline-flex items-center justify-center gap-2 select-none whitespace-nowrap px-1.5;\n height: fit-content;\n width: fit-content;\n background-color: var(--background, var(--background-800));\n color: var(--foreground, var(--foreground-200));\n border: var(--border-width-base, 1px) solid var(--background-border, var(--background-600));\n border-radius: var(--radius-sm, 0.375rem);\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--text-xs, 0.75rem);\n line-height: var(--leading-tight, 1.25);\n }\n\n .badge.dismissible {\n @apply pr-0.5;\n }\n\n .pill {\n border-radius: 9999px;\n }\n\n .icon {\n @apply flex items-center shrink-0;\n }\n\n .dismiss {\n @apply ml-1 flex shrink-0 items-center justify-center p-0 cursor-pointer;\n width: 1em;\n height: 1em;\n line-height: 1;\n border-radius: var(--radius-xs, 0.25rem);\n background-color: var(--dismiss-background, var(--background, transparent));\n color: var(--foreground, var(--foreground-400));\n border: none;\n transition:\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n outline: none;\n }\n\n .dismiss svg {\n width: 100%;\n height: 100%;\n }\n\n .dismiss[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover, var(--dismiss-background, transparent));\n }\n\n .dismiss[data-pressed=\"true\"] {\n background-color: var(\n --background-pressed,\n var(--background-hover, var(--dismiss-background, transparent))\n );\n transform: scale(0.95);\n }\n\n .dismiss[data-focus-visible=\"true\"] {\n box-shadow: 0 0 0 1.5px var(--focus-visible, var(--foreground));\n }\n}\n",
4896
4895
  "cssTypes": "export interface Styles {\n badge: string;\n pill: string;\n dismissible: string;\n icon: string;\n dismiss: string;\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
4897
4896
  },
4898
4897
  "banner": {
@@ -4901,7 +4900,7 @@ export const generatedSourceCode = {
4901
4900
  "cssTypes": "declare const styles: {\n banner: string;\n content: string;\n dismiss: string;\n note: string;\n info: string;\n success: string;\n warning: string;\n danger: string;\n sm: string;\n md: string;\n lg: string;\n iconContainer: string;\n icon: string;\n title: string;\n body: string;\n};\n\nexport default styles;\n"
4902
4901
  },
4903
4902
  "button": {
4904
- "tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { useButton } from \"@react-aria/button\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport css from \"./Button.module.css\";\n\ntype ButtonSize = (string & {});\ntype ButtonIconSlots = {\n left?: React.ReactNode;\n right?: React.ReactNode;\n};\n\ninterface ButtonIconStyles {\n left?: StyleValue;\n right?: StyleValue;\n}\n\nexport interface ButtonStyleSlots {\n root?: StyleValue;\n icon?: StyleValue | ButtonIconStyles;\n}\n\nexport type ButtonStylesProp = StylesProp<ButtonStyleSlots>;\n\nconst resolveButtonBaseStyles = createStylesResolver(['root', 'iconLeft', 'iconRight'] as const);\n\nfunction resolveButtonStyles(styles: ButtonStylesProp | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveButtonBaseStyles(styles)\n const { root, icon } = styles;\n\n let iconLeft: StyleValue | undefined;\n let iconRight: StyleValue | undefined;\n\n if (icon) {\n if (typeof icon === 'string' || Array.isArray(icon)) {\n iconLeft = icon;\n iconRight = icon;\n } else {\n iconLeft = icon.left;\n iconRight = icon.right;\n }\n }\n\n return resolveButtonBaseStyles({ root, iconLeft, iconRight });\n}\n\nexport interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"href\" | \"target\"> {\n /** Variant class appended to the root element. Accepts any string. */\n variant?: string;\n /** Size class appended to the root element. Accepts any string. */\n size?: ButtonSize;\n /** Disables interaction and applies disabled styling */\n isDisabled?: boolean;\n /** React Aria press handler — preferred over onClick for accessibility */\n onPress?: (e: { target: EventTarget | null }) => void;\n /** Icon slots rendered before (left) or after (right) the button label */\n icon?: React.ReactNode | ButtonIconSlots;\n /** Renders the button as an anchor element when provided */\n href?: string;\n /** Browsing context for the anchor variant (e.g. \"_blank\") */\n target?: React.HTMLAttributeAnchorTarget;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ButtonStylesProp;\n}\n\nfunction isButtonIconSlots(icon: ButtonProps[\"icon\"]): icon is ButtonIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && ('left' in icon || 'right' in icon);\n}\n\nfunction resolveButtonIcon(icon: ButtonProps[\"icon\"]) {\n if (!icon) {\n return undefined;\n }\n\n if (isButtonIconSlots(icon)) {\n return icon;\n }\n\n return { left: icon };\n}\n\nfunction resolveButtonIconSizeClass(size: ButtonSize | undefined) {\n if (!size) {\n return undefined;\n }\n\n return (css as unknown as Record<string, string | undefined>)[`icon-${size}`];\n}\n\nconst Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(\n ({ className, styles, variant = \"default\", size = \"md\", children, onClick, onPress, isDisabled, disabled, icon, href, target, rel, ...props }, ref) => {\n const buttonRef = React.useRef<HTMLButtonElement | HTMLAnchorElement>(null);\n const mergedRef = useMergeRefs(ref, buttonRef);\n const isButtonDisabled = isDisabled ?? disabled ?? false;\n const [isPressed, setIsPressed] = React.useState(false);\n const isAnchor = !!href;\n\n const handlePress = React.useCallback((e: any) => {\n if (onPress) onPress({ target: e.target });\n if (onClick) onClick(e as unknown as React.MouseEvent<HTMLButtonElement>);\n }, [onPress, onClick]);\n\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n if (!isButtonDisabled) {\n setIsPressed(true);\n }\n props.onMouseDown?.(e as any);\n }, [isButtonDisabled, props]);\n\n const handleMouseUp = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n setIsPressed(false);\n props.onMouseUp?.(e as any);\n }, [props]);\n\n const handleMouseLeave = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n setIsPressed(false);\n props.onMouseLeave?.(e as any);\n }, [props]);\n\n const { buttonProps } = useButton({\n isDisabled: isButtonDisabled,\n onPress: handlePress,\n }, buttonRef as React.RefObject<HTMLButtonElement>);\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing({ autoFocus: props.autoFocus });\n const { hoverProps, isHovered } = useHover({ isDisabled: isButtonDisabled });\n\n const resolved = resolveButtonStyles(styles);\n const resolvedIcon = resolveButtonIcon(icon);\n const iconSizeClassName = resolveButtonIconSizeClass(size);\n const iconSlotClassName = size === \"icon\" ? \"icon\" : undefined;\n const buttonClassName = cn(\"button\", variant, size, css.button, className, resolved.root);\n\n const { targetProps } = useFocus({ mode: \"target\" });\n\n if (isAnchor) {\n return (\n <a\n {...mergeProps(focusProps, hoverProps, props as any)}\n {...targetProps}\n ref={mergedRef as unknown as React.RefObject<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={rel ?? (target === \"_blank\" ? \"noopener noreferrer\" : undefined)}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n className={buttonClassName}\n data-disabled={isButtonDisabled ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n {resolvedIcon?.left && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconLeft)}>{resolvedIcon.left}</span>}\n {children}\n {resolvedIcon?.right && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconRight)}>{resolvedIcon.right}</span>}\n </a>\n );\n }\n\n return (\n <button\n {...mergeProps(buttonProps, focusProps, hoverProps, props)}\n {...targetProps}\n disabled={isButtonDisabled}\n ref={mergedRef as unknown as React.RefObject<HTMLButtonElement>}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n className={buttonClassName}\n data-disabled={isButtonDisabled ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n {resolvedIcon?.left && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconLeft)}>{resolvedIcon.left}</span>}\n {children}\n {resolvedIcon?.right && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconRight)}>{resolvedIcon.right}</span>}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n\nexport { Button };\n",
4903
+ "tsx": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { useButton } from \"@react-aria/button\";\n\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport css from \"./Button.module.css\";\n\ntype ButtonSize = (string & {});\ntype ButtonIconSlots = {\n left?: React.ReactNode;\n right?: React.ReactNode;\n};\n\ninterface ButtonIconStyles {\n left?: StyleValue;\n right?: StyleValue;\n}\n\nexport interface ButtonStyleSlots {\n root?: StyleValue;\n icon?: StyleValue | ButtonIconStyles;\n}\n\nexport type ButtonStylesProp = StylesProp<ButtonStyleSlots>;\n\nconst resolveButtonBaseStyles = createStylesResolver(['root', 'iconLeft', 'iconRight'] as const);\n\nfunction resolveButtonStyles(styles: ButtonStylesProp | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveButtonBaseStyles(styles)\n const { root, icon } = styles;\n\n let iconLeft: StyleValue | undefined;\n let iconRight: StyleValue | undefined;\n\n if (icon) {\n if (typeof icon === 'string' || Array.isArray(icon)) {\n iconLeft = icon;\n iconRight = icon;\n } else {\n iconLeft = icon.left;\n iconRight = icon.right;\n }\n }\n\n return resolveButtonBaseStyles({ root, iconLeft, iconRight });\n}\n\nexport interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"href\" | \"target\"> {\n /** Variant class appended to the root element. Accepts any string. */\n variant?: string;\n /** Size class appended to the root element. Accepts any string. */\n size?: ButtonSize;\n /** Disables interaction and applies disabled styling */\n isDisabled?: boolean;\n /** React Aria press handler — preferred over onClick for accessibility */\n onPress?: (e: { target: EventTarget | null }) => void;\n /** Icon slots rendered before (left) or after (right) the button label */\n icon?: React.ReactNode | ButtonIconSlots;\n /** Renders the button as an anchor element when provided */\n href?: string;\n /** Browsing context for the anchor variant (e.g. \"_blank\") */\n target?: React.HTMLAttributeAnchorTarget;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ButtonStylesProp;\n}\n\nfunction isButtonIconSlots(icon: ButtonProps[\"icon\"]): icon is ButtonIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && ('left' in icon || 'right' in icon);\n}\n\nfunction resolveButtonIcon(icon: ButtonProps[\"icon\"]) {\n if (!icon) {\n return undefined;\n }\n\n if (isButtonIconSlots(icon)) {\n return icon;\n }\n\n return { left: icon };\n}\n\nfunction resolveButtonIconSizeClass(size: ButtonSize | undefined) {\n if (!size) {\n return undefined;\n }\n\n return (css as unknown as Record<string, string | undefined>)[`icon-${size}`];\n}\n\nconst Button = React.forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(\n ({ className, styles, variant = \"default\", size, children, onClick, onPress, isDisabled, disabled, icon, href, target, rel, ...props }, ref) => {\n const buttonRef = React.useRef<HTMLButtonElement | HTMLAnchorElement>(null);\n const mergedRef = useMergeRefs(ref, buttonRef);\n const isButtonDisabled = isDisabled ?? disabled ?? false;\n const [isPressed, setIsPressed] = React.useState(false);\n const isAnchor = !!href;\n\n const handlePress = React.useCallback((e: any) => {\n if (onPress) onPress({ target: e.target });\n if (onClick) onClick(e as unknown as React.MouseEvent<HTMLButtonElement>);\n }, [onPress, onClick]);\n\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n if (!isButtonDisabled) {\n setIsPressed(true);\n }\n props.onMouseDown?.(e as any);\n }, [isButtonDisabled, props]);\n\n const handleMouseUp = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n setIsPressed(false);\n props.onMouseUp?.(e as any);\n }, [props]);\n\n const handleMouseLeave = React.useCallback((e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {\n setIsPressed(false);\n props.onMouseLeave?.(e as any);\n }, [props]);\n\n const { buttonProps } = useButton({\n isDisabled: isButtonDisabled,\n onPress: handlePress,\n }, buttonRef as React.RefObject<HTMLButtonElement>);\n\n const { focusProps, isFocused, isFocusVisible } = useFocusRing({ autoFocus: props.autoFocus });\n const { hoverProps, isHovered } = useHover({ isDisabled: isButtonDisabled });\n\n const actualSize = size ?? \"md\";\n const isIconOnly = !children && !!icon;\n\n const resolved = resolveButtonStyles(styles);\n const resolvedIcon = resolveButtonIcon(icon);\n\n const iconSizeClassName = resolveButtonIconSizeClass(actualSize);\n const iconSlotClassName = isIconOnly ? \"icon\" : undefined;\n\n const buttonClassName = cn(\n \"button\",\n variant,\n actualSize,\n isIconOnly && \"icon\",\n css.button,\n className,\n resolved.root\n );\n\n const { targetProps } = useFocus({ mode: \"target\" });\n\n if (isAnchor) {\n return (\n <a\n {...mergeProps(focusProps, hoverProps, props as any)}\n {...targetProps}\n ref={mergedRef as unknown as React.RefObject<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={rel ?? (target === \"_blank\" ? \"noopener noreferrer\" : undefined)}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n className={buttonClassName}\n data-disabled={isButtonDisabled ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n {resolvedIcon?.left && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconLeft)}>{resolvedIcon.left}</span>}\n {children}\n {resolvedIcon?.right && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconRight)}>{resolvedIcon.right}</span>}\n </a>\n );\n }\n\n return (\n <button\n {...mergeProps(buttonProps, focusProps, hoverProps, props)}\n {...targetProps}\n disabled={isButtonDisabled}\n ref={mergedRef as unknown as React.RefObject<HTMLButtonElement>}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n className={buttonClassName}\n data-disabled={isButtonDisabled ? \"true\" : undefined}\n data-pressed={isPressed ? \"true\" : \"false\"}\n data-hovered={isHovered ? \"true\" : \"false\"}\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n >\n {resolvedIcon?.left && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconLeft)}>{resolvedIcon.left}</span>}\n {children}\n {resolvedIcon?.right && <span className={cn(iconSlotClassName, iconSizeClassName, resolved.iconRight)}>{resolvedIcon.right}</span>}\n </button>\n );\n }\n);\n\nButton.displayName = \"Button\";\n\nexport { Button };\n",
4905
4904
  "css": "@reference \"tailwindcss\";\n\n@layer components {\n .button {\n @apply inline-flex items-center justify-center gap-2 select-none cursor-pointer whitespace-nowrap;\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n\n font-weight: var(--font-weight-medium, 500);\n font-size: var(--text-sm, 0.875rem);\n line-height: var(--leading-tight, 1.25);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-hovered=\"true\"]:not([data-disabled=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &:focus-visible {\n outline: none;\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n filter: grayscale(0.5);\n }\n }\n}\n",
4906
4905
  "cssTypes": "export interface Styles {\n button: string;\n \"default\": string;\n \"primary\": string;\n \"secondary\": string;\n \"outline\": string;\n \"ghost\": string;\n \"danger\": string;\n \"sm\": string;\n \"md\": string;\n \"lg\": string;\n}\n\ndeclare const styles: Styles;\nexport default styles;\n"
4907
4906
  },
@@ -4937,7 +4936,7 @@ export const generatedSourceCode = {
4937
4936
  },
4938
4937
  "date": {
4939
4938
  "tsx": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\n\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\n\nimport { type StyleValue, cn } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { asElementProps } from \"@/lib/react-aria\"\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\n\nimport dateModuleStyles from \"./Date.module.css\"\n\n// Alias global Date to avoid shadowing by component name\nconst NativeDate = globalThis.Date;\n\ninterface DateStyleSlots {\n root?: StyleValue;\n header?: StyleValue;\n \"day-headers\"?: StyleValue;\n grid?: StyleValue;\n \"day-cell\"?: StyleValue; // individual date button\n}\n\ntype DateStylesProp = StylesProp<DateStyleSlots>;\n\nconst dateStyleSlotKeys = ['root', 'header', 'day-headers', 'grid', 'day-cell'] as const;\nconst resolveDateBaseStyles = createStylesResolver(dateStyleSlotKeys);\n\nfunction normalizeDateStyles(styles: DateStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) {\n return styles;\n }\n\n return {\n root: styles.root,\n header: styles.header,\n \"day-headers\": styles[\"day-headers\"],\n grid: styles.grid,\n \"day-cell\": styles[\"day-cell\"],\n };\n}\n\n/**\n * Context type for Calendar state management\n */\nexport interface DateContextValue {\n selectedDate: Date | null\n focusedDate: Date | null\n currentMonth: Date | null\n today: Date | null\n selectDate: (date: Date) => void\n focusDate: (date: Date) => void\n navigateMonth: (offset: number) => void\n isDateDisabled: (date: Date) => boolean\n isDateOutOfRange: (date: Date) => boolean\n}\n\nconst DateContext = React.createContext<DateContextValue | null>(null)\n\nfunction useDateContext() {\n const context = React.useContext(DateContext)\n if (!context) {\n throw new Error(\"Date component must be used within Date root\")\n }\n return context\n}\n\n/**\n * Props for Calendar component\n */\nexport interface DateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Controlled selected date */\n value?: Date | null\n /** Called when the user selects a date */\n onChange?: (date: Date) => void\n /** Function returning true for dates that should be unselectable */\n disabled?: (date: Date) => boolean\n /** Earliest selectable date */\n minDate?: Date\n /** Latest selectable date */\n maxDate?: Date\n /** Month shown initially when no date is selected */\n defaultMonth?: Date;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: DateStylesProp;\n}\n\n/**\n * Helper functions for date calculations\n */\nfunction getDaysInMonth(date: Date): number {\n return new NativeDate(date.getFullYear(), date.getMonth() + 1, 0).getDate()\n}\n\nfunction getFirstDayOfMonth(date: Date): number {\n return new NativeDate(date.getFullYear(), date.getMonth(), 1).getDay()\n}\n\nfunction isSameDay(date1: Date, date2: Date): boolean {\n return (\n date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n )\n}\n\nfunction isToday(date: Date, today: Date | null): boolean {\n if (!today) return false;\n return isSameDay(date, today)\n}\n\n/**\n * Calendar grid computation\n */\nfunction getCalendarGrid(currentMonth: Date | null): Date[][] {\n if (!currentMonth) return [];\n\n const daysInMonth = getDaysInMonth(currentMonth)\n const firstDay = getFirstDayOfMonth(currentMonth)\n\n const grid: Date[] = []\n\n // Handle previous month's days\n if (firstDay > 0) {\n const prevMonth = new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth(), 0)\n const daysInPrevMonth = getDaysInMonth(prevMonth)\n\n for (let i = firstDay - 1; i >= 0; i--) {\n const date = new NativeDate(prevMonth.getFullYear(), prevMonth.getMonth(), daysInPrevMonth - i)\n grid.push(date)\n }\n }\n\n // Current month days\n for (let i = 1; i <= daysInMonth; i++) {\n grid.push(new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth(), i))\n }\n\n // Pad with next month's days\n while (grid.length % 7 !== 0) {\n const nextDay = grid.length - firstDay - daysInMonth + 1\n const date = new NativeDate(currentMonth.getFullYear(), currentMonth.getMonth() + 1, nextDay)\n grid.push(date)\n }\n\n // Convert to rows\n const rows: Date[][] = []\n for (let i = 0; i < grid.length; i += 7) {\n rows.push(grid.slice(i, i + 7))\n }\n\n return rows\n}\n\nconst Date = React.forwardRef<HTMLDivElement, DateProps>(\n (\n {\n value: controlledValue,\n onChange,\n disabled: disabledProp = () => false,\n minDate,\n maxDate,\n defaultMonth,\n className,\n styles,\n ...props\n },\n ref\n ) => {\n const [uncontrolledValue, setUncontrolledValue] = React.useState<Date | null>(null)\n const [today, setToday] = React.useState<Date | null>(null)\n const [currentMonth, setCurrentMonth] = React.useState<Date | null>(null)\n const [focusedDate, setFocusedDate] = React.useState<Date | null>(null)\n\n const selectedDate = controlledValue !== undefined ? controlledValue : uncontrolledValue\n\n const resolved = resolveDateBaseStyles(normalizeDateStyles(styles));\n\n const isDateDisabled = React.useCallback(\n (date: Date): boolean => {\n if (disabledProp(date)) return true\n if (minDate && date < minDate) return true\n if (maxDate && date > maxDate) return true\n return false\n },\n [disabledProp, minDate, maxDate]\n )\n\n const isDateOutOfRange = React.useCallback(\n (date: Date): boolean => {\n if (!currentMonth) return false;\n return (\n date.getMonth() !== currentMonth.getMonth() ||\n date.getFullYear() !== currentMonth.getFullYear()\n )\n },\n [currentMonth]\n )\n\n const selectDate = React.useCallback(\n (date: Date) => {\n if (!isDateDisabled(date)) {\n if (controlledValue === undefined) {\n setUncontrolledValue(date)\n }\n onChange?.(date)\n setFocusedDate(null)\n }\n },\n [controlledValue, onChange, isDateDisabled]\n )\n\n const focusDate = React.useCallback((date: Date) => {\n setFocusedDate(date)\n }, [])\n\n const navigateMonth = React.useCallback((offset: number) => {\n setCurrentMonth(prev => {\n const baseDate = prev ?? new NativeDate(); // Handle null prev\n const newMonth = new NativeDate(baseDate.getFullYear(), baseDate.getMonth() + offset, 1)\n return newMonth\n })\n }, [])\n\n const calendarGrid = React.useMemo(\n () => currentMonth ? getCalendarGrid(currentMonth) : [],\n [currentMonth]\n )\n\n const contextValue: DateContextValue = React.useMemo(\n () => ({\n selectedDate,\n focusedDate,\n currentMonth,\n today,\n selectDate,\n focusDate,\n navigateMonth,\n isDateDisabled,\n isDateOutOfRange,\n }),\n [selectedDate, focusedDate, currentMonth, today, selectDate, focusDate, navigateMonth, isDateDisabled, isDateOutOfRange]\n )\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (!focusedDate) return\n\n let newFocusedDate: Date | null = null\n\n switch (e.key) {\n case \"ArrowUp\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() - 7)\n break\n case \"ArrowDown\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() + 7)\n break\n case \"ArrowLeft\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() - 1)\n break\n case \"ArrowRight\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), focusedDate.getDate() + 1)\n break\n case \"Home\":\n e.preventDefault()\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), 1)\n break\n case \"End\":\n e.preventDefault()\n const daysInMonth = getDaysInMonth(focusedDate)\n newFocusedDate = new NativeDate(focusedDate.getFullYear(), focusedDate.getMonth(), daysInMonth)\n break\n case \"PageUp\":\n e.preventDefault()\n navigateMonth(-1)\n return\n case \"PageDown\":\n e.preventDefault()\n navigateMonth(1)\n return\n case \"Enter\":\n case \" \":\n e.preventDefault()\n selectDate(focusedDate)\n return\n }\n\n if (newFocusedDate) {\n setFocusedDate(newFocusedDate)\n // Auto-navigate month if needed\n if (newFocusedDate.getMonth() !== currentMonth!.getMonth() || newFocusedDate.getFullYear() !== currentMonth!.getFullYear()) {\n setCurrentMonth(new NativeDate(newFocusedDate.getFullYear(), newFocusedDate.getMonth(), 1))\n }\n }\n },\n [focusedDate, currentMonth, selectDate, navigateMonth]\n )\n\n // Set initial focus, today, and current month on client mount\n React.useEffect(() => {\n const now = new NativeDate()\n setToday(now)\n\n if (currentMonth === null) { // Only set if not yet initialized\n setCurrentMonth(defaultMonth ?? now)\n }\n\n if (focusedDate === null) { // Only set if not yet initialized\n setFocusedDate(selectedDate ?? now)\n }\n }, [defaultMonth, currentMonth, focusedDate, selectedDate]) // Add relevant dependencies\n\n return (\n <DateContext.Provider value={contextValue}>\n <div\n ref={ref}\n className={cn(\"date\", dateModuleStyles.calendar, className, resolved.root)}\n role=\"application\"\n aria-label=\"Date picker calendar\"\n onKeyDown={handleKeyDown}\n {...props}\n >\n {currentMonth && (\n <>\n <DateHeader className={resolved.header} />\n <DateDayHeaders className={resolved[\"day-headers\"]} />\n <DateGrid grid={calendarGrid} className={resolved.grid} dayCellClassName={resolved[\"day-cell\"]} />\n </>\n )}\n </div>\n </DateContext.Provider>\n )\n }\n)\n\nDate.displayName = \"Date\"\n\n/**\n * Calendar Header component\n */\ninterface DateHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS class for the header */\n className?: string;\n}\n\n/** Navigation header with month/year display and prev/next controls */\nconst DateHeader = React.forwardRef<HTMLDivElement, DateHeaderProps>(\n ({ className, ...props }, ref) => {\n const { currentMonth, navigateMonth } = useDateContext()\n const { focusProps: prevFocusProps, isFocused: isPrevFocused, isFocusVisible: isPrevFocusVisible } = useFocusRing()\n const { focusProps: nextFocusProps, isFocused: isNextFocused, isFocusVisible: isNextFocusVisible } = useFocusRing()\n const { targetProps: prevTargetProps } = useFocus({ mode: \"target\" })\n const { targetProps: nextTargetProps } = useFocus({ mode: \"target\" })\n\n const monthYear = currentMonth\n ? currentMonth.toLocaleDateString(\"en-US\", {\n month: \"long\",\n year: \"numeric\",\n })\n : \"\"\n\n return (\n <div\n ref={ref}\n className={cn(\"header\", dateModuleStyles.header, className)}\n {...props}\n >\n <div className={cn(\"month-year\", dateModuleStyles[\"month-year\"])}>\n {monthYear}\n </div>\n <div>\n <button\n {...asElementProps<\"button\">(mergeProps(prevFocusProps, prevTargetProps))}\n onClick={() => navigateMonth(-1)}\n className={cn(\"nav-button\", \"prev-button\", dateModuleStyles[\"nav-button\"])}\n aria-label=\"Previous month\"\n data-focused={isPrevFocused ? \"true\" : undefined}\n data-focus-visible={isPrevFocusVisible ? \"true\" : undefined}\n >\n <ChevronLeft size={16} />\n </button>\n <button\n {...asElementProps<\"button\">(mergeProps(nextFocusProps, nextTargetProps))}\n onClick={() => navigateMonth(1)}\n className={cn(\"nav-button\", \"next-button\", dateModuleStyles[\"nav-button\"])}\n aria-label=\"Next month\"\n data-focused={isNextFocused ? \"true\" : undefined}\n data-focus-visible={isNextFocusVisible ? \"true\" : undefined}\n >\n <ChevronRight size={16} />\n </button>\n </div>\n </div>\n )\n }\n)\n\nDateHeader.displayName = \"Date.Header\"\n\n/**\n * Calendar Day Headers component\n */\ninterface DateDayHeadersProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS class for the day headers row */\n className?: string;\n}\n\n/** Row of weekday abbreviation labels above the calendar grid */\nconst DateDayHeaders = React.forwardRef<HTMLDivElement, DateDayHeadersProps>(\n ({ className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"day-headers\", dateModuleStyles[\"day-headers\"], className)}\n {...props}\n >\n {[\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"].map((day) => (\n <div\n key={day}\n className={cn(\"day-header\", dateModuleStyles[\"day-header\"])}\n >\n {day}\n </div>\n ))}\n </div>\n )\n }\n)\n\nDateDayHeaders.displayName = \"Date.DayHeaders\"\n\n/**\n * Calendar Grid component\n */\ninterface DateGridProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Calendar grid rows, each containing 7 Date objects */\n grid: Date[][]\n /** Classes applied to each individual date cell (DateDay component) */\n dayCellClassName?: string;\n}\n\n/** The 7-column calendar grid containing date cells */\nconst DateGrid = React.forwardRef<HTMLDivElement, DateGridProps>(\n ({ grid, className, dayCellClassName, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"grid\", dateModuleStyles.grid, className)}\n role=\"grid\"\n {...props}\n >\n {/* Week headers */}\n {[\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"].map((day) => (\n <div\n key={day}\n className={cn(\"day-header\", dateModuleStyles[\"week-header\"])}\n role=\"columnheader\"\n >\n {day}\n </div>\n ))}\n\n {/* Calendar rows */}\n {grid.map((week: Date[], weekIndex: number) => {\n return (\n <React.Fragment key={weekIndex}>\n {week.map((date: Date, dayIndex: number) => (\n <DateDay key={`${weekIndex}-${dayIndex}`} date={date} className={dayCellClassName} />\n ))}\n </React.Fragment>\n )\n })}\n </div>\n )\n }\n)\n\nDateGrid.displayName = \"Date.Grid\"\n\n/**\n * Calendar Day component\n */\ninterface DateDayProps extends React.HTMLAttributes<HTMLButtonElement> {\n /** The date this cell represents */\n date: Date\n}\n/**\n * Individual date cell in the calendar grid\n */\nconst DateDay = React.forwardRef<HTMLButtonElement, DateDayProps>(\n ({ date, className, onClick, ...props }, ref) => {\n const {\n selectedDate,\n focusedDate,\n today,\n selectDate,\n focusDate,\n isDateDisabled,\n isDateOutOfRange,\n } = useDateContext()\n\n const isDisabled = isDateDisabled(date)\n\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const mergedRef = useMergeRefs(ref, buttonRef)\n const { focusProps, isFocused: isFocusRingFocused, isFocusVisible } = useFocusRing()\n const { hoverProps, isHovered } = useHover({ isDisabled })\n const { targetProps } = useFocus({ mode: \"target\" })\n\n const isSelected = selectedDate ? isSameDay(date, selectedDate) : false\n const isFocused = focusedDate ? isSameDay(date, focusedDate) : false\n const isCurrentToday = isToday(date, today)\n const isOutOfRange = isDateOutOfRange(date)\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n selectDate(date)\n focusDate(date)\n onClick?.(e)\n },\n [date, selectDate, focusDate, onClick]\n )\n\n const handleFocus = React.useCallback(() => {\n focusDate(date)\n }, [date, focusDate])\n\n React.useEffect(() => {\n if (isFocused && buttonRef.current) {\n buttonRef.current.focus({ preventScroll: true })\n }\n }, [isFocused])\n\n return (\n <button\n ref={mergedRef}\n onClick={handleClick}\n className={cn(\"day\", dateModuleStyles[\"day-cell\"], className)}\n data-ring={targetProps[\"data-ring\"]}\n data-focus-indicator={targetProps[\"data-focus-indicator\"]}\n data-ring-inset={targetProps[\"data-ring-inset\"]}\n data-focused={isFocusRingFocused ? \"true\" : undefined}\n data-hovered={isHovered ? \"true\" : undefined}\n data-selected={isSelected ? \"true\" : undefined}\n data-today={isCurrentToday ? \"true\" : undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n data-out-of-range={isOutOfRange ? \"true\" : undefined}\n data-focus-visible={isFocusVisible && isFocused ? \"true\" : undefined}\n disabled={isDisabled}\n aria-selected={isSelected}\n aria-label={date.toLocaleDateString(\"en-US\", {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n })}\n {...mergeProps(focusProps, hoverProps, { onFocus: handleFocus }, props)}\n >\n {date.getDate()}\n </button>\n )\n }\n)\n\nDateDay.displayName = \"Date.Day\"\n\nexport { Date, DateHeader, DateGrid, DateDay }\n",
4940
- "css": "@reference \"tailwindcss\";\n\n@layer components {\n .calendar {\n --disabled-opacity: 0.5;\n\n @apply inline-flex p-1.5 flex-col overflow-hidden gap-0;\n border-radius: var(--radius-xs);\n background-color: var(--background);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-headers {\n @apply grid gap-2 px-4 pt-3 pb-1;\n grid-template-columns: repeat(7, 1fr);\n background: var(--background);\n border: var(--border-width-base) solid var(--border);\n border-bottom: none;\n border-radius: var(--radius-xs) var(--radius-xs) 0 0;\n }\n\n .day-header {\n @apply flex items-center justify-center;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-xs);\n color: var(--foreground);\n }\n\n .header {\n @apply flex items-center justify-between gap-4 pl-2 pr-1.5 py-1.5;\n color: var(--foreground);\n }\n\n .month-year {\n @apply ml-2;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n text-align: center;\n }\n\n .nav-button {\n @apply inline-flex min-h-8 min-w-8 items-center justify-center cursor-pointer;\n border-radius: var(--radius-xs);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 1px solid transparent;\n font-size: var(--text-sm);\n font-weight: 500;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .nav-button:focus-visible {\n outline: none;\n }\n\n .nav-button:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .grid {\n @apply grid gap-1 px-4 pb-4;\n grid-template-columns: repeat(7, 1fr); /* 7 days only */\n background: var(--background);\n border-radius: 0 0 var(--radius-xs) var(--radius-xs);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-cell {\n @apply flex min-h-8 items-center justify-center px-2.5 py-2 cursor-pointer;\n border-radius: var(--radius-base);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 2px solid transparent;\n font-size: var(--text-xs);\n font-weight: 400;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .day-cell:focus-visible {\n outline: none;\n }\n\n .week-header {\n display: none;\n }\n\n .week-number {\n display: none;\n }\n}\n\n/* Variant states - these are outside @layer */\n.day-cell[data-selected=\"true\"] {\n font-weight: 500;\n}\n\n.day-cell[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]),\n.day-cell:hover:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n}\n\n.day-cell[data-today=\"true\"] {\n border-color: transparent;\n}\n\n.day-cell[data-disabled=\"true\"],\n.day-cell[data-out-of-range=\"true\"] {\n opacity: var(--disabled-opacity);\n}\n\n.day-cell[data-disabled=\"true\"] { cursor: not-allowed; }\n",
4939
+ "css": "@reference \"tailwindcss\";\n\n@layer components {\n .calendar {\n --disabled-opacity: 0.5;\n\n @apply inline-flex p-1.5 flex-col overflow-hidden gap-0;\n border-radius: var(--radius-sm);\n background-color: var(--background);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-headers {\n @apply grid gap-2 px-4 pt-3 pb-1;\n grid-template-columns: repeat(7, 1fr);\n background: var(--background);\n border: var(--border-width-base) solid var(--border);\n border-bottom: none;\n border-radius: var(--radius-sm) var(--radius-sm) 0 0;\n }\n\n .day-header {\n @apply flex items-center justify-center;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n color: var(--foreground);\n }\n\n .header {\n @apply flex items-center justify-between gap-4 pl-2 pr-1.5 py-1.5;\n color: var(--foreground);\n }\n\n .month-year {\n @apply ml-2;\n font-weight: var(--font-weight-medium);\n font-size: var(--text-sm);\n text-align: center;\n }\n\n .nav-button {\n @apply inline-flex min-h-8 min-w-8 items-center justify-center cursor-pointer;\n border-radius: var(--radius-sm);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 1px solid transparent;\n font-size: var(--text-sm);\n font-weight: 500;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .nav-button:focus-visible {\n outline: none;\n }\n\n .nav-button:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .grid {\n @apply grid gap-1 px-4 pb-4;\n grid-template-columns: repeat(7, 1fr); /* 7 days only */\n background: var(--background);\n border-radius: 0 0 var(--radius-sm) var(--radius-sm);\n border: var(--border-width-base) solid var(--border);\n }\n\n .day-cell {\n @apply flex min-h-8 items-center justify-center px-2.5 py-2 cursor-pointer;\n border-radius: var(--radius-base);\n background-color: var(--background, transparent);\n color: var(--foreground);\n border: 2px solid transparent;\n font-size: var(--text-sm);\n font-weight: 400;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n border-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n opacity var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .day-cell:focus-visible {\n outline: none;\n }\n\n .week-header {\n display: none;\n }\n\n .week-number {\n display: none;\n }\n}\n\n/* Variant states - these are outside @layer */\n.day-cell[data-selected=\"true\"] {\n font-weight: 500;\n}\n\n.day-cell[data-hovered=\"true\"]:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]),\n.day-cell:hover:not([data-disabled=\"true\"]):not([data-out-of-range=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n}\n\n.day-cell[data-today=\"true\"] {\n border-color: transparent;\n}\n\n.day-cell[data-disabled=\"true\"],\n.day-cell[data-out-of-range=\"true\"] {\n opacity: var(--disabled-opacity);\n}\n\n.day-cell[data-disabled=\"true\"] { cursor: not-allowed; }\n",
4941
4940
  "cssTypes": "declare const styles: {\n calendar: string\n \"day-headers\": string\n \"day-header\": string\n header: string\n \"month-year\": string\n \"nav-button\": string\n grid: string\n \"day-cell\": string\n \"week-header\": string\n \"week-number\": string\n}\n\nexport default styles\n"
4942
4941
  },
4943
4942
  "divider": {
@@ -4971,9 +4970,9 @@ export const generatedSourceCode = {
4971
4970
  "cssTypes": "declare const styles: {\n readonly grid: string;\n readonly container: string;\n readonly \"responsive-cols\": string;\n readonly \"responsive-gap\": string;\n readonly \"responsive-rows\": string;\n readonly \"has-row-gap\": string;\n readonly \"has-col-gap\": string;\n};\n\nexport default styles;\n"
4972
4971
  },
4973
4972
  "group": {
4974
- "tsx": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn, type StyleValue } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\"\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\"\nimport { Button, type ButtonProps } from \"../Button\"\nimport { Expand, type ExpandProps } from \"../Expand\"\nimport { Input, type InputProps } from \"../Input\"\nimport { Select, type SelectProps } from \"../Select\"\nimport css from \"./Group.module.css\"\n\ntype Orientation = \"horizontal\" | \"vertical\"\ntype Spacing = \"none\" | \"xs\" | \"sm\"\n\ntype GroupItemStyles = {\n first?: StyleValue\n last?: StyleValue\n divider?: StyleValue\n grow?: StyleValue\n}\n\nexport interface GroupStyleSlots {\n root?: StyleValue;\n item?: StyleValue | GroupItemStyles;\n button?: StyleValue;\n input?: StyleValue;\n select?: StyleValue;\n expand?: StyleValue;\n}\n\nexport type GroupStylesProp = StylesProp<GroupStyleSlots>;\n\nexport interface GroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Variant class appended to the root and grouped slots. Accepts any string. */\n variant?: string\n /** Controls the axis that children are arranged along */\n orientation?: Orientation\n /** Controls the gap between group items */\n spacing?: Spacing\n /** Whether all items in the group are non-interactive */\n isDisabled?: boolean\n /** The currently active button value for toggle group behavior */\n value?: string\n /** Called when a button with a value prop is pressed */\n onChange?: (value: string) => void\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: GroupStylesProp\n}\n\ninterface GroupContextValue {\n isInGroup: boolean\n groupOrientation: Orientation\n groupSpacing: Spacing\n groupIsDisabled: boolean\n groupValue?: string\n groupOnChange?: (value: string) => void\n groupVariant?: string\n groupStyles: ReturnType<typeof resolveGroupStyles>\n registerInput?: (containerRef: React.RefObject<HTMLDivElement | null>, inputRef: React.RefObject<HTMLInputElement | null>) => void\n unregisterInput?: (containerRef: React.RefObject<HTMLDivElement | null>) => void\n activateInput?: () => boolean\n registerFocusableSurface?: (ref: React.RefObject<HTMLElement | null>) => void\n unregisterFocusableSurface?: (ref: React.RefObject<HTMLElement | null>) => void\n}\n\n// Context\nconst GroupContext = React.createContext<GroupContextValue | null>(null)\n\nfunction useGroupContext() {\n const context = React.useContext(GroupContext)\n if (!context) {\n throw new Error(\"Group sub-components must be used within Group\")\n }\n return context\n}\n\nconst resolveGroupBaseStyles = createStylesResolver([\n \"root\",\n \"item\",\n \"itemFirst\",\n \"itemLast\",\n \"itemDivider\",\n \"itemGrow\",\n \"button\",\n \"input\",\n \"select\",\n \"expand\",\n] as const)\n\nfunction resolveGroupStyles(styles: GroupStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveGroupBaseStyles(styles)\n const { root, item, button, input, select, expand } = styles\n\n let itemResolved: StyleValue | undefined\n let itemFirst: StyleValue | undefined\n let itemLast: StyleValue | undefined\n let itemDivider: StyleValue | undefined\n let itemGrow: StyleValue | undefined\n\n if (item) {\n if (typeof item === \"string\" || Array.isArray(item)) {\n itemResolved = item\n itemFirst = item\n itemLast = item\n itemDivider = item\n itemGrow = item\n } else {\n itemFirst = item.first\n itemLast = item.last\n itemDivider = item.divider\n itemGrow = item.grow\n }\n }\n\n return resolveGroupBaseStyles({\n root,\n item: itemResolved,\n itemFirst,\n itemLast,\n itemDivider,\n itemGrow,\n button,\n input,\n select,\n expand,\n })\n}\n\n// Orientation and spacing maps\nconst orientationMap: Record<Orientation, string> = {\n horizontal: css.horizontal,\n vertical: css.vertical,\n}\n\nconst spacingMap: Record<Spacing, string> = {\n none: css.none,\n xs: css.xs,\n sm: css.sm,\n}\n\n// Detect Divider elements by checking for separator role, orientation prop, or displayName\nfunction isDivider(child: React.ReactNode): boolean {\n if (!React.isValidElement(child)) return false\n const props = (child.props || {}) as Record<string, unknown>\n const type = child.type as any\n return props.role === \"separator\" || \"orientation\" in props || type?.displayName === \"Divider\"\n}\n\nfunction isHTMLElement(value: Element | null): value is HTMLElement {\n return value instanceof HTMLElement\n}\n\n// Root component\n/** Button group that groups related buttons together */\nconst GroupRoot = React.forwardRef<HTMLDivElement, GroupProps>(\n (\n {\n className,\n variant,\n orientation = \"horizontal\",\n spacing = \"none\",\n children,\n isDisabled = false,\n value,\n onChange,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const groupRef = React.useRef<HTMLDivElement>(null)\n const inputsRef = React.useRef<Map<React.RefObject<HTMLDivElement | null>, React.RefObject<HTMLInputElement | null>>>(new Map())\n const focusableSurfacesRef = React.useRef<React.RefObject<HTMLElement | null>[]>([])\n\n const childrenArray = React.Children.toArray(children).filter(\n (child) => child !== null && child !== undefined\n )\n\n const resolved = resolveGroupStyles(stylesProp)\n const mergedRef = useMergeRefs<HTMLDivElement>(ref, groupRef)\n\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef: groupRef,\n surfaceSelector: '[data-focus-surface=\"true\"]',\n radiusSource: \"item\",\n dependencies: [childrenArray.length, orientation, spacing],\n })\n\n const registerInput = React.useCallback((containerRef: React.RefObject<HTMLDivElement | null>, inputRef: React.RefObject<HTMLInputElement | null>) => {\n inputsRef.current.set(containerRef, inputRef)\n }, [])\n\n const unregisterInput = React.useCallback((containerRef: React.RefObject<HTMLDivElement | null>) => {\n inputsRef.current.delete(containerRef)\n }, [])\n\n const activateInput = React.useCallback(() => {\n const firstEntry = Array.from(inputsRef.current.entries())[0]\n if (firstEntry) {\n const [containerRef, inputRef] = firstEntry\n if (containerRef.current && inputRef.current) {\n // Focus the actual input for keyboard interaction\n inputRef.current.focus()\n\n // Force focus-visible state by finding the input container inside the wrapper\n // The Input component renders a container div with data-input-focus-surface\n const inputContainer = containerRef.current.querySelector('[data-input-focus-surface=\"true\"]') as HTMLElement\n if (inputContainer) {\n inputContainer.setAttribute('data-focus-visible', 'true')\n inputContainer.setAttribute('data-focused', 'true')\n }\n return true\n }\n }\n return false\n }, [])\n\n const registerFocusableSurface = React.useCallback((ref: React.RefObject<HTMLElement | null>) => {\n focusableSurfacesRef.current.push(ref)\n }, [])\n\n const unregisterFocusableSurface = React.useCallback((ref: React.RefObject<HTMLElement | null>) => {\n focusableSurfacesRef.current = focusableSurfacesRef.current.filter(r => r !== ref)\n }, [])\n\n\n const handleGroupKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== \"ArrowRight\" && e.key !== \"ArrowLeft\" && e.key !== \"ArrowDown\" && e.key !== \"ArrowUp\") {\n return\n }\n\n const focusedElement = document.activeElement\n if (!focusedElement || !groupRef.current?.contains(focusedElement as Node)) {\n return\n }\n\n const focusableElements = focusableSurfacesRef.current\n .map(ref => ref.current)\n .filter((el): el is HTMLElement => el !== null && !!groupRef.current?.contains(el))\n\n if (focusableElements.length === 0) {\n return\n }\n\n const currentIndex = focusableElements.findIndex(el => el.contains(focusedElement as Node))\n if (currentIndex === -1) {\n return\n }\n\n const isHorizontal = orientation === \"horizontal\"\n const isNavigatingInline = (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\") && isHorizontal\n const isNavigatingBlock = (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") && !isHorizontal\n\n if (!isNavigatingInline && !isNavigatingBlock) {\n return\n }\n\n e.preventDefault()\n\n let nextIndex = currentIndex\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n nextIndex = (currentIndex + 1) % focusableElements.length\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n nextIndex = currentIndex === 0 ? focusableElements.length - 1 : currentIndex - 1\n }\n\n const nextElement = focusableElements[nextIndex]\n if (nextElement) {\n // Try to focus an interactive element within the surface\n const focusableChild = nextElement.querySelector('button, input, [role=\"button\"]') as HTMLElement | null\n if (focusableChild) {\n focusableChild.focus()\n } else {\n nextElement.focus()\n }\n }\n }, [orientation])\n\n const contextValue: GroupContextValue = {\n isInGroup: true,\n groupOrientation: orientation,\n groupSpacing: spacing,\n groupIsDisabled: isDisabled,\n groupValue: value,\n groupOnChange: onChange,\n groupVariant: variant,\n groupStyles: resolved,\n registerInput,\n unregisterInput,\n activateInput,\n registerFocusableSurface,\n unregisterFocusableSurface,\n }\n\n return (\n <GroupContext.Provider value={contextValue}>\n <div ref={scopeRef} className={cn(\"group-scope\", scopeProps.className)}>\n <div {...indicatorProps} />\n <div\n ref={mergedRef}\n className={cn(\n 'group',\n variant,\n orientation,\n css.group,\n orientationMap[orientation],\n spacingMap[spacing],\n resolved.root,\n className\n )}\n role=\"group\"\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n onKeyDown={handleGroupKeyDown}\n {...props}\n >\n {childrenArray.map((child, index) => {\n const isFirst = index === 0\n const isLast = index === childrenArray.length - 1\n const isDividerChild = isDivider(child)\n\n // Extract layout-related classes from child to apply to the item wrapper\n const childProps = React.isValidElement(child) ? (child.props as any) : {}\n const childClassName = childProps.className || \"\"\n const shouldGrow = childClassName.includes('w-full') || childClassName.includes('flex-1')\n return (\n <div\n key={`item-${index}`}\n className={cn(\n 'item',\n variant,\n css.item,\n isFirst && resolved.itemFirst,\n isLast && resolved.itemLast,\n isDividerChild && css.divider,\n isDividerChild && resolved.itemDivider,\n shouldGrow && css.grow,\n shouldGrow && resolved.itemGrow,\n resolved.item,\n )}\n >\n {child}\n </div>\n )\n })}\n </div>\n </div>\n </GroupContext.Provider>\n )\n }\n)\nGroupRoot.displayName = \"Group\"\n\n// Group.Button component\ninterface GroupButtonProps extends ButtonProps {\n /** Whether this button is in an active/pressed state */\n active?: boolean\n /** Identifier used for toggle group behavior when Group has value/onChange */\n value?: string\n}\n\n/** Button styled to merge seamlessly with adjacent group items */\nconst GroupButton = React.forwardRef<HTMLButtonElement, GroupButtonProps>(\n ({ active, value, variant, className, onPress, onPointerDown, onMouseDown, ...restProps }, ref) => {\n const context = useGroupContext()\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const mergedRef = useMergeRefs(buttonRef, ref)\n\n // Merge disabled state from group context\n const isDisabled = restProps.isDisabled ?? context.groupIsDisabled\n\n // Derive active and onPress from toggle group context when value is provided\n const isActive = value !== undefined && context.groupValue !== undefined ? value === context.groupValue : active\n const baseHandlePress = value !== undefined && context.groupOnChange !== undefined ? () => context.groupOnChange!(value) : onPress\n\n const handlePress = React.useCallback((e: { target: EventTarget | null }) => {\n baseHandlePress?.(e)\n }, [baseHandlePress])\n\n // Activate input on pointer down to avoid focus ring flicker\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLButtonElement>) => {\n if (!isDisabled && e.pointerType !== \"mouse\") {\n // Pre-activate the input before button loses focus\n context.activateInput?.()\n }\n onPointerDown?.(e)\n }, [context, isDisabled, onPointerDown])\n\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {\n if (!isDisabled && context.activateInput?.()) {\n e.preventDefault()\n }\n onMouseDown?.(e)\n }, [context, isDisabled, onMouseDown])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(buttonRef)\n return () => {\n context.unregisterFocusableSurface?.(buttonRef)\n }\n }, [context])\n\n const buttonVariant = variant ?? context.groupVariant ?? \"ghost\"\n\n const buttonProps = {\n ...restProps,\n onPress: handlePress,\n onPointerDown: handlePointerDown,\n onMouseDown: handleMouseDown,\n variant: buttonVariant,\n isDisabled,\n \"data-focus-surface\": \"true\",\n \"data-selected\": isActive ? \"true\" : \"false\",\n className: cn(\n \"button\",\n buttonVariant,\n css.button,\n context.groupStyles.button,\n className\n ),\n }\n\n return <Button ref={mergedRef} {...buttonProps} />\n }\n)\nGroupButton.displayName = \"Group.Button\"\n\n// Group.Input component\ninterface GroupInputProps extends InputProps { }\n\n/** Input field integrated into the button group */\nconst GroupInput = React.forwardRef<HTMLInputElement, GroupInputProps>(\n ({ className, disabled, ...props }, ref) => {\n const context = useGroupContext()\n const inputRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(ref, inputRef)\n\n // Register and unregister the input ref with the group context\n React.useEffect(() => {\n context.registerInput?.(containerRef, inputRef)\n return () => {\n context.unregisterInput?.(containerRef)\n }\n }, [context])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(containerRef)\n return () => {\n context.unregisterFocusableSurface?.(containerRef)\n }\n }, [context])\n\n // Merge disabled state from group context\n const inputDisabled = disabled ?? context.groupIsDisabled\n\n return (\n <div\n ref={containerRef}\n className={cn(\"input\", context.groupVariant, css.input, context.groupStyles.input, className)}\n data-focus-surface=\"true\"\n >\n <Input\n ref={mergedRef}\n {...props}\n disabled={inputDisabled}\n className=\"h-full w-full px-2\"\n />\n </div>\n )\n }\n)\nGroupInput.displayName = \"Group.Input\"\n\n// Group.InputWrapper component - preserves Input styling (for use with ghost variant)\ninterface GroupInputWrapperProps extends InputProps { }\n\n/** Input variant that preserves Input styling within the group */\nconst GroupInputWrapper = React.forwardRef<HTMLInputElement, GroupInputWrapperProps>(\n ({ className, disabled, ...props }, ref) => {\n const context = useGroupContext()\n const inputRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(ref, inputRef)\n\n // Register and unregister the input ref with the group context\n React.useEffect(() => {\n context.registerInput?.(containerRef, inputRef)\n return () => {\n context.unregisterInput?.(containerRef)\n }\n }, [context])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(containerRef)\n return () => {\n context.unregisterFocusableSurface?.(containerRef)\n }\n }, [context])\n\n // Merge disabled state from group context\n const inputDisabled = disabled ?? context.groupIsDisabled\n\n return (\n <div\n ref={containerRef}\n className={cn(\"input\", context.groupVariant, css.input, context.groupStyles.input, className)}\n data-focus-surface=\"true\"\n >\n <Input\n ref={mergedRef}\n {...props}\n disabled={inputDisabled}\n className=\"h-full w-full px-2\"\n />\n </div>\n )\n }\n)\nGroupInputWrapper.displayName = \"Group.InputWrapper\"\n\n// Group.Select component\ninterface GroupSelectProps extends SelectProps<any> { }\n\n/** Select dropdown integrated into the button group */\nconst GroupSelect = React.forwardRef<HTMLDivElement, GroupSelectProps>(\n ({ className, isDisabled, ...props }, ref) => {\n const context = useGroupContext()\n const selectRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(selectRef, ref)\n\n // Merge disabled state from group context\n const disabled = isDisabled ?? context.groupIsDisabled\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(selectRef)\n return () => {\n context.unregisterFocusableSurface?.(selectRef)\n }\n }, [context])\n\n return (\n <Select\n ref={mergedRef}\n {...props}\n isDisabled={disabled}\n data-focus-surface=\"true\"\n className={cn(\"select\", context.groupVariant, css.select, context.groupStyles.select, className)}\n />\n )\n }\n)\nGroupSelect.displayName = \"Group.Select\"\n\n// Group.Expand component\ninterface GroupExpandProps extends ExpandProps { }\n\n/** Expand primitive integrated into the group */\nconst GroupExpand = React.forwardRef<HTMLDivElement, GroupExpandProps>(\n ({ className, isDisabled, styles: stylesProp, ...props }, ref) => {\n const context = useGroupContext()\n const surfaceRef = React.useRef<HTMLDivElement>(null)\n const disabled = isDisabled ?? context.groupIsDisabled\n const surfaceStyles = typeof stylesProp === \"string\" || Array.isArray(stylesProp) ? stylesProp : undefined\n const expandStyles = surfaceStyles ? undefined : stylesProp\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(surfaceRef)\n return () => {\n context.unregisterFocusableSurface?.(surfaceRef)\n }\n }, [context])\n\n return (\n <div\n ref={surfaceRef}\n data-focus-surface=\"true\"\n className={cn(\"expand\", context.groupVariant, css.expand, context.groupStyles.expand, surfaceStyles)}\n >\n <Expand\n ref={ref}\n {...props}\n className={className}\n styles={expandStyles}\n isDisabled={disabled}\n />\n </div>\n )\n }\n)\nGroupExpand.displayName = \"Group.Expand\"\n\n// Assemble compound component\nconst Group = Object.assign(GroupRoot, {\n Button: GroupButton,\n Input: GroupInput,\n InputWrapper: GroupInputWrapper,\n Select: GroupSelect,\n Expand: GroupExpand,\n})\n\nexport { Group, GroupContext }\n",
4975
- "css": "@reference \"tailwindcss\";\n\n@layer components {\n .group {\n --layout-radius-size: calc(var(--spacing) * 1.5);\n --layout-padding-size: var(--layout-radius-size);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-border-width: var(--border-width-base, 1px);\n --background-inner-radius: calc(var(--background-radius) - var(--background-border-width));\n --layout-text-height: calc(0.8em * var(--leading-tight, 1.25));\n --layout-vertical-spacing: calc(var(--spacing) * 4);\n --layout-border-height: calc(var(--background-border-width) * 2);\n --layout-padding-height: calc(var(--layout-padding-size) * 2);\n --layout-control-height: calc(\n var(--layout-text-height) +\n var(--layout-vertical-spacing) +\n var(--layout-border-height)\n );\n --item-height: max(\n calc(\n var(--layout-control-height) -\n var(--layout-padding-height) -\n var(--layout-border-height)\n ),\n 0px\n );\n\n @apply flex overflow-hidden shrink-0 box-border;\n color: var(--foreground, currentColor);\n background-color: var(--background, transparent);\n border: var(--background-border-width) solid var(--background-border, transparent);\n border-radius: var(--background-radius);\n padding: var(--layout-padding-size);\n\n &.horizontal {\n @apply flex-row items-stretch;\n height: var(--layout-control-height);\n\n .item.divider {\n margin-block: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n height: 100%;\n }\n }\n\n &.vertical {\n @apply flex-col;\n\n .item .button {\n @apply w-full;\n }\n\n .item.divider {\n margin-inline: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n width: 100%;\n }\n }\n\n &.none {\n --layout-padding-size: 0px;\n @apply gap-0;\n }\n\n &.xs {\n --layout-radius-size: calc(var(--spacing) * 0.875);\n @apply space-x-0.5;\n }\n\n &.sm {\n --layout-radius-size: calc(var(--spacing) * 1.25);\n @apply space-x-1;\n }\n\n }\n\n .item {\n @apply flex items-stretch;\n position: relative;\n isolation: isolate;\n border-radius: var(--group-item-radius, 0);\n overflow: visible;\n\n &.grow {\n flex: 1;\n }\n\n &.divider {\n @apply p-0 shrink-0 flex-none;\n\n > [role=\"separator\"] {\n flex: 0 0 auto;\n }\n }\n }\n\n :is(.button, .input, .select, .expand) {\n height: 100%;\n min-height: var(--item-height);\n position: relative;\n isolation: isolate;\n overflow: visible;\n }\n\n .button {\n @apply flex box-border;\n width: auto;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n &[data-selected=\"true\"] {\n @apply relative;\n background-color: var(--button-selected-background, var(--background-pressed, var(--background-hover, var(--background))));\n color: var(--button-selected-foreground, var(--foreground));\n }\n }\n\n .input {\n @apply flex flex-1 items-stretch overflow-visible;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n > [data-ring=\"true\"] {\n border-radius: inherit;\n }\n }\n\n .select {\n @apply flex items-stretch p-0 bg-transparent border-none;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand {\n @apply flex items-stretch;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand :global(.expand-scope),\n .expand :global(.expand) {\n @apply flex w-full h-full;\n }\n\n .expand :global(.expand) {\n @apply flex-col;\n border-radius: inherit;\n }\n\n .expand :global(.trigger) {\n @apply min-h-0;\n border-radius: inherit;\n }\n\n .trigger {}\n\n .group {\n .item :is(.button, .select) {\n border: none;\n }\n\n .input > [data-input-focus-surface=\"true\"] {\n border: none;\n }\n\n .button[data-selected=\"true\"] {\n font-weight: 500;\n }\n\n .item.divider > [role=\"separator\"] {\n --divider-background: var(--background);\n }\n\n &.none {\n .item:not(.divider) {\n overflow: hidden;\n }\n\n :is(.button, .trigger, .select) {\n border-radius: 0;\n --background-radius: 0;\n --background-inner-radius: 0;\n }\n\n .input {\n --radius-sm: 0;\n }\n\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .item:last-child {\n --group-item-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n }\n\n .item:only-child {\n --group-item-radius: var(--background-inner-radius);\n }\n\n &.horizontal {\n .item:first-child :is( .button, .trigger, .input > *, .select) {\n border-top-left-radius: var(--background-inner-radius);\n border-bottom-left-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is( .button, .trigger, .input > *, .select) {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child .trigger .icon-section {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n\n &.vertical {\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) var(--background-inner-radius) 0 0;\n }\n\n .item:last-child {\n --group-item-radius: 0 0 var(--background-inner-radius) var(--background-inner-radius);\n }\n\n .item:first-child :is(\n .button,\n .trigger,\n .input > *,\n .select\n ) {\n border-top-left-radius: var(--background-inner-radius);\n border-top-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is(\n .button,\n .trigger,\n .input > *,\n .select\n ) {\n border-bottom-left-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n }\n\n &:is(.xs, .sm) {\n .item {\n --group-item-radius: var(--background-inner-radius);\n }\n\n :is(.button, .trigger, .select) {\n border-radius: var(--background-inner-radius);\n }\n\n .input {\n --radius-sm: var(--background-inner-radius);\n }\n }\n }\n\n .group [data-ring=\"true\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n }\n\n .group :global(.focus-indicator) {\n display: none;\n }\n\n .group [data-focus-indicator=\"local\"] {\n display: none;\n }\n\n :is(.button[data-focus-visible=\"true\"], .trigger[data-focus-visible=\"true\"]) {\n @apply outline-none;\n box-shadow: none;\n }\n}\n",
4976
- "cssTypes": "declare const styles: {\n \"focus-scope\": string;\n \"focus-indicator\": string;\n group: string;\n horizontal: string;\n vertical: string;\n none: string;\n xs: string;\n sm: string;\n item: string;\n grow: string;\n divider: string;\n button: string;\n input: string;\n select: string;\n expand: string;\n trigger: string;\n};\n\nexport default styles;\n"
4973
+ "tsx": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn, type StyleValue } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\"\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\"\nimport { Button, type ButtonProps } from \"../Button\"\nimport { Expand, type ExpandProps } from \"../Expand\"\nimport { Input, type InputProps } from \"../Input\"\nimport { Select, type SelectProps } from \"../Select\"\nimport css from \"./Group.module.css\"\n\ntype Orientation = \"horizontal\" | \"vertical\"\ntype Spacing = \"none\" | \"xs\" | \"sm\"\n\ntype GroupItemStyles = {\n first?: StyleValue\n last?: StyleValue\n divider?: StyleValue\n grow?: StyleValue\n}\n\nexport interface GroupStyleSlots {\n root?: StyleValue;\n item?: StyleValue | GroupItemStyles;\n button?: StyleValue;\n input?: StyleValue;\n select?: StyleValue;\n expand?: StyleValue;\n}\n\nexport type GroupStylesProp = StylesProp<GroupStyleSlots>;\n\nexport interface GroupProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Variant class appended to the root and grouped slots. Accepts any string. */\n variant?: string\n /** Controls the axis that children are arranged along */\n orientation?: Orientation\n /** Controls the gap between group items */\n spacing?: Spacing\n /** Whether all items in the group are non-interactive */\n isDisabled?: boolean\n /** The currently active button value for toggle group behavior */\n value?: string\n /** Called when a button with a value prop is pressed */\n onChange?: (value: string) => void\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: GroupStylesProp\n}\n\ninterface GroupContextValue {\n isInGroup: boolean\n groupOrientation: Orientation\n groupSpacing: Spacing\n groupIsDisabled: boolean\n groupValue?: string\n groupOnChange?: (value: string) => void\n groupVariant?: string\n groupStyles: ReturnType<typeof resolveGroupStyles>\n registerInput?: (containerRef: React.RefObject<HTMLDivElement | null>, inputRef: React.RefObject<HTMLInputElement | null>) => void\n unregisterInput?: (containerRef: React.RefObject<HTMLDivElement | null>) => void\n activateInput?: () => boolean\n registerFocusableSurface?: (ref: React.RefObject<HTMLElement | null>) => void\n unregisterFocusableSurface?: (ref: React.RefObject<HTMLElement | null>) => void\n}\n\n// Context\nconst GroupContext = React.createContext<GroupContextValue | null>(null)\n\nfunction useGroupContext() {\n const context = React.useContext(GroupContext)\n if (!context) {\n throw new Error(\"Group sub-components must be used within Group\")\n }\n return context\n}\n\nconst resolveGroupBaseStyles = createStylesResolver([\n \"root\",\n \"item\",\n \"itemFirst\",\n \"itemLast\",\n \"itemDivider\",\n \"itemGrow\",\n \"button\",\n \"input\",\n \"select\",\n \"expand\",\n] as const)\n\nfunction resolveGroupStyles(styles: GroupStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveGroupBaseStyles(styles)\n const { root, item, button, input, select, expand } = styles\n\n let itemResolved: StyleValue | undefined\n let itemFirst: StyleValue | undefined\n let itemLast: StyleValue | undefined\n let itemDivider: StyleValue | undefined\n let itemGrow: StyleValue | undefined\n\n if (item) {\n if (typeof item === \"string\" || Array.isArray(item)) {\n itemResolved = item\n itemFirst = item\n itemLast = item\n itemDivider = item\n itemGrow = item\n } else {\n itemFirst = item.first\n itemLast = item.last\n itemDivider = item.divider\n itemGrow = item.grow\n }\n }\n\n return resolveGroupBaseStyles({\n root,\n item: itemResolved,\n itemFirst,\n itemLast,\n itemDivider,\n itemGrow,\n button,\n input,\n select,\n expand,\n })\n}\n\n// Orientation and spacing maps\nconst orientationMap: Record<Orientation, string> = {\n horizontal: css.horizontal,\n vertical: css.vertical,\n}\n\nconst spacingMap: Record<Spacing, string> = {\n none: css.none,\n xs: css.xs,\n sm: css.sm,\n}\n\n// Detect Divider elements by checking for separator role, orientation prop, or displayName\nfunction isDivider(child: React.ReactNode): boolean {\n if (!React.isValidElement(child)) return false\n const props = (child.props || {}) as Record<string, unknown>\n const type = child.type as any\n return props.role === \"separator\" || \"orientation\" in props || type?.displayName === \"Divider\"\n}\n\nfunction isHTMLElement(value: Element | null): value is HTMLElement {\n return value instanceof HTMLElement\n}\n\n// Root component\n/** Button group that groups related buttons together */\nconst GroupRoot = React.forwardRef<HTMLDivElement, GroupProps>(\n (\n {\n className,\n variant,\n orientation = \"horizontal\",\n spacing = \"none\",\n children,\n isDisabled = false,\n value,\n onChange,\n styles: stylesProp,\n ...props\n },\n ref\n ) => {\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const groupRef = React.useRef<HTMLDivElement>(null)\n const inputsRef = React.useRef<Map<React.RefObject<HTMLDivElement | null>, React.RefObject<HTMLInputElement | null>>>(new Map())\n const focusableSurfacesRef = React.useRef<React.RefObject<HTMLElement | null>[]>([])\n\n const childrenArray = React.Children.toArray(children).filter(\n (child) => child !== null && child !== undefined\n )\n\n const resolved = resolveGroupStyles(stylesProp)\n const mergedRef = useMergeRefs<HTMLDivElement>(ref, groupRef)\n\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef: groupRef,\n surfaceSelector: '[data-focus-surface=\"true\"]',\n radiusSource: \"item\",\n dependencies: [childrenArray.length, orientation, spacing],\n })\n\n const registerInput = React.useCallback((containerRef: React.RefObject<HTMLDivElement | null>, inputRef: React.RefObject<HTMLInputElement | null>) => {\n inputsRef.current.set(containerRef, inputRef)\n }, [])\n\n const unregisterInput = React.useCallback((containerRef: React.RefObject<HTMLDivElement | null>) => {\n inputsRef.current.delete(containerRef)\n }, [])\n\n const activateInput = React.useCallback(() => {\n const firstEntry = Array.from(inputsRef.current.entries())[0]\n if (firstEntry) {\n const [containerRef, inputRef] = firstEntry\n if (containerRef.current && inputRef.current) {\n // Focus the actual input for keyboard interaction\n inputRef.current.focus()\n\n // Force focus-visible state by finding the input container inside the wrapper\n // The Input component renders a container div with data-input-focus-surface\n const inputContainer = containerRef.current.querySelector('[data-input-focus-surface=\"true\"]') as HTMLElement\n if (inputContainer) {\n inputContainer.setAttribute('data-focus-visible', 'true')\n inputContainer.setAttribute('data-focused', 'true')\n }\n return true\n }\n }\n return false\n }, [])\n\n const registerFocusableSurface = React.useCallback((ref: React.RefObject<HTMLElement | null>) => {\n focusableSurfacesRef.current.push(ref)\n }, [])\n\n const unregisterFocusableSurface = React.useCallback((ref: React.RefObject<HTMLElement | null>) => {\n focusableSurfacesRef.current = focusableSurfacesRef.current.filter(r => r !== ref)\n }, [])\n\n\n const handleGroupKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== \"ArrowRight\" && e.key !== \"ArrowLeft\" && e.key !== \"ArrowDown\" && e.key !== \"ArrowUp\") {\n return\n }\n\n const focusedElement = document.activeElement\n if (!focusedElement || !groupRef.current?.contains(focusedElement as Node)) {\n return\n }\n\n const focusableElements = focusableSurfacesRef.current\n .map(ref => ref.current)\n .filter((el): el is HTMLElement => el !== null && !!groupRef.current?.contains(el))\n\n if (focusableElements.length === 0) {\n return\n }\n\n const currentIndex = focusableElements.findIndex(el => el.contains(focusedElement as Node))\n if (currentIndex === -1) {\n return\n }\n\n const isHorizontal = orientation === \"horizontal\"\n const isNavigatingInline = (e.key === \"ArrowRight\" || e.key === \"ArrowLeft\") && isHorizontal\n const isNavigatingBlock = (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") && !isHorizontal\n\n if (!isNavigatingInline && !isNavigatingBlock) {\n return\n }\n\n e.preventDefault()\n\n let nextIndex = currentIndex\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n nextIndex = (currentIndex + 1) % focusableElements.length\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n nextIndex = currentIndex === 0 ? focusableElements.length - 1 : currentIndex - 1\n }\n\n const nextElement = focusableElements[nextIndex]\n if (nextElement) {\n // Try to focus an interactive element within the surface\n const focusableChild = nextElement.querySelector('button, input, [role=\"button\"]') as HTMLElement | null\n if (focusableChild) {\n focusableChild.focus()\n } else {\n nextElement.focus()\n }\n }\n }, [orientation])\n\n const contextValue: GroupContextValue = {\n isInGroup: true,\n groupOrientation: orientation,\n groupSpacing: spacing,\n groupIsDisabled: isDisabled,\n groupValue: value,\n groupOnChange: onChange,\n groupVariant: variant,\n groupStyles: resolved,\n registerInput,\n unregisterInput,\n activateInput,\n registerFocusableSurface,\n unregisterFocusableSurface,\n }\n\n return (\n <GroupContext.Provider value={contextValue}>\n <div ref={scopeRef} className={cn(\"group-scope\", scopeProps.className)}>\n <div {...indicatorProps} />\n <div\n ref={mergedRef}\n className={cn(\n 'group',\n variant,\n orientation,\n css.group,\n orientationMap[orientation],\n spacingMap[spacing],\n resolved.root,\n className\n )}\n role=\"group\"\n aria-disabled={isDisabled || undefined}\n data-disabled={isDisabled ? \"true\" : undefined}\n onKeyDown={handleGroupKeyDown}\n {...props}\n >\n {childrenArray.map((child, index) => {\n const isFirst = index === 0\n const isLast = index === childrenArray.length - 1\n const isDividerChild = isDivider(child)\n\n // Extract layout-related classes from child to apply to the item wrapper\n const childProps = React.isValidElement(child) ? (child.props as any) : {}\n const childClassName = childProps.className || \"\"\n const shouldGrow = childClassName.includes('w-full') || childClassName.includes('flex-1')\n const childType = React.isValidElement(child) ? (child.type as any) : null\n const isIconGroupButton = childType?.displayName === \"Group.Button\" && childProps.size === \"icon\"\n return (\n <div\n key={`item-${index}`}\n className={cn(\n 'item',\n variant,\n css.item,\n isFirst && resolved.itemFirst,\n isLast && resolved.itemLast,\n isDividerChild && css.divider,\n isDividerChild && resolved.itemDivider,\n shouldGrow && css.grow,\n shouldGrow && resolved.itemGrow,\n isIconGroupButton && css[\"icon-button-item\"],\n resolved.item,\n )}\n >\n {child}\n </div>\n )\n })}\n </div>\n </div>\n </GroupContext.Provider>\n )\n }\n)\nGroupRoot.displayName = \"Group\"\n\n// Group.Button component\ninterface GroupButtonProps extends ButtonProps {\n /** Whether this button is in an active/pressed state */\n active?: boolean\n /** Identifier used for toggle group behavior when Group has value/onChange */\n value?: string\n}\n\n/** Button styled to merge seamlessly with adjacent group items */\nconst GroupButton = React.forwardRef<HTMLButtonElement, GroupButtonProps>(\n ({ active, value, variant, className, onPress, onPointerDown, onMouseDown, ...restProps }, ref) => {\n const context = useGroupContext()\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n const mergedRef = useMergeRefs(buttonRef, ref)\n\n // Merge disabled state from group context\n const isDisabled = restProps.isDisabled ?? context.groupIsDisabled\n\n // Derive active and onPress from toggle group context when value is provided\n const isActive = value !== undefined && context.groupValue !== undefined ? value === context.groupValue : active\n const baseHandlePress = value !== undefined && context.groupOnChange !== undefined ? () => context.groupOnChange!(value) : onPress\n\n const handlePress = React.useCallback((e: { target: EventTarget | null }) => {\n baseHandlePress?.(e)\n }, [baseHandlePress])\n\n // Activate input on pointer down to avoid focus ring flicker\n const handlePointerDown = React.useCallback((e: React.PointerEvent<HTMLButtonElement>) => {\n if (!isDisabled && e.pointerType !== \"mouse\") {\n // Pre-activate the input before button loses focus\n context.activateInput?.()\n }\n onPointerDown?.(e)\n }, [context, isDisabled, onPointerDown])\n\n const handleMouseDown = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {\n if (!isDisabled && context.activateInput?.()) {\n e.preventDefault()\n }\n onMouseDown?.(e)\n }, [context, isDisabled, onMouseDown])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(buttonRef)\n return () => {\n context.unregisterFocusableSurface?.(buttonRef)\n }\n }, [context])\n\n const buttonVariant = variant ?? context.groupVariant ?? \"ghost\"\n\n const buttonProps = {\n ...restProps,\n onPress: handlePress,\n onPointerDown: handlePointerDown,\n onMouseDown: handleMouseDown,\n variant: buttonVariant,\n isDisabled,\n \"data-focus-surface\": \"true\",\n \"data-selected\": isActive ? \"true\" : \"false\",\n className: cn(\n \"button\",\n buttonVariant,\n css.button,\n context.groupStyles.button,\n className\n ),\n }\n\n return <Button ref={mergedRef} {...buttonProps} />\n }\n)\nGroupButton.displayName = \"Group.Button\"\n\n// Group.Input component\ninterface GroupInputProps extends InputProps { }\n\n/** Input field integrated into the button group */\nconst GroupInput = React.forwardRef<HTMLInputElement, GroupInputProps>(\n ({ className, disabled, ...props }, ref) => {\n const context = useGroupContext()\n const inputRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(ref, inputRef)\n\n // Register and unregister the input ref with the group context\n React.useEffect(() => {\n context.registerInput?.(containerRef, inputRef)\n return () => {\n context.unregisterInput?.(containerRef)\n }\n }, [context])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(containerRef)\n return () => {\n context.unregisterFocusableSurface?.(containerRef)\n }\n }, [context])\n\n // Merge disabled state from group context\n const inputDisabled = disabled ?? context.groupIsDisabled\n\n return (\n <div\n ref={containerRef}\n className={cn(\"input\", context.groupVariant, css.input, context.groupStyles.input, className)}\n data-focus-surface=\"true\"\n >\n <Input\n ref={mergedRef}\n {...props}\n disabled={inputDisabled}\n className=\"h-full w-full px-2\"\n />\n </div>\n )\n }\n)\nGroupInput.displayName = \"Group.Input\"\n\n// Group.InputWrapper component - preserves Input styling (for use with ghost variant)\ninterface GroupInputWrapperProps extends InputProps { }\n\n/** Input variant that preserves Input styling within the group */\nconst GroupInputWrapper = React.forwardRef<HTMLInputElement, GroupInputWrapperProps>(\n ({ className, disabled, ...props }, ref) => {\n const context = useGroupContext()\n const inputRef = React.useRef<HTMLInputElement>(null)\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(ref, inputRef)\n\n // Register and unregister the input ref with the group context\n React.useEffect(() => {\n context.registerInput?.(containerRef, inputRef)\n return () => {\n context.unregisterInput?.(containerRef)\n }\n }, [context])\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(containerRef)\n return () => {\n context.unregisterFocusableSurface?.(containerRef)\n }\n }, [context])\n\n // Merge disabled state from group context\n const inputDisabled = disabled ?? context.groupIsDisabled\n\n return (\n <div\n ref={containerRef}\n className={cn(\"input\", context.groupVariant, css.input, context.groupStyles.input, className)}\n data-focus-surface=\"true\"\n >\n <Input\n ref={mergedRef}\n {...props}\n disabled={inputDisabled}\n className=\"h-full w-full px-2\"\n />\n </div>\n )\n }\n)\nGroupInputWrapper.displayName = \"Group.InputWrapper\"\n\n// Group.Select component\ninterface GroupSelectProps extends SelectProps<any> { }\n\n/** Select dropdown integrated into the button group */\nconst GroupSelect = React.forwardRef<HTMLDivElement, GroupSelectProps>(\n ({ className, isDisabled, ...props }, ref) => {\n const context = useGroupContext()\n const selectRef = React.useRef<HTMLDivElement>(null)\n const mergedRef = useMergeRefs(selectRef, ref)\n\n // Merge disabled state from group context\n const disabled = isDisabled ?? context.groupIsDisabled\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(selectRef)\n return () => {\n context.unregisterFocusableSurface?.(selectRef)\n }\n }, [context])\n\n return (\n <Select\n ref={mergedRef}\n {...props}\n isDisabled={disabled}\n data-focus-surface=\"true\"\n className={cn(\"select\", context.groupVariant, css.select, context.groupStyles.select, className)}\n />\n )\n }\n)\nGroupSelect.displayName = \"Group.Select\"\n\n// Group.Expand component\ninterface GroupExpandProps extends ExpandProps { }\n\n/** Expand primitive integrated into the group */\nconst GroupExpand = React.forwardRef<HTMLDivElement, GroupExpandProps>(\n ({ className, isDisabled, styles: stylesProp, ...props }, ref) => {\n const context = useGroupContext()\n const surfaceRef = React.useRef<HTMLDivElement>(null)\n const disabled = isDisabled ?? context.groupIsDisabled\n const surfaceStyles = typeof stylesProp === \"string\" || Array.isArray(stylesProp) ? stylesProp : undefined\n const expandStyles = surfaceStyles ? undefined : stylesProp\n\n React.useEffect(() => {\n context.registerFocusableSurface?.(surfaceRef)\n return () => {\n context.unregisterFocusableSurface?.(surfaceRef)\n }\n }, [context])\n\n return (\n <div\n ref={surfaceRef}\n data-focus-surface=\"true\"\n className={cn(\"expand\", context.groupVariant, css.expand, context.groupStyles.expand, surfaceStyles)}\n >\n <Expand\n ref={ref}\n {...props}\n className={className}\n styles={expandStyles}\n isDisabled={disabled}\n />\n </div>\n )\n }\n)\nGroupExpand.displayName = \"Group.Expand\"\n\n// Assemble compound component\nconst Group = Object.assign(GroupRoot, {\n Button: GroupButton,\n Input: GroupInput,\n InputWrapper: GroupInputWrapper,\n Select: GroupSelect,\n Expand: GroupExpand,\n})\n\nexport { Group, GroupContext }\n",
4974
+ "css": "@reference \"tailwindcss\";\n\n@layer components {\n .group {\n --layout-radius-size: calc(var(--spacing) * 1.5);\n --layout-padding-size: var(--layout-radius-size);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-border-width: var(--border-width-base, 1px);\n --background-inner-radius: calc(var(--background-radius) - var(--background-border-width));\n --layout-text-height: calc(0.8em * var(--leading-tight, 1.25));\n --layout-vertical-spacing: calc(var(--spacing) * 4);\n --layout-border-height: calc(var(--background-border-width) * 2);\n --layout-padding-height: calc(var(--layout-padding-size) * 2);\n --layout-control-height: calc(\n var(--layout-text-height) +\n var(--layout-vertical-spacing) +\n var(--layout-border-height)\n );\n --item-height: max(\n calc(\n var(--layout-control-height) -\n var(--layout-padding-height) -\n var(--layout-border-height)\n ),\n 0px\n );\n\n @apply flex overflow-hidden shrink-0 box-border;\n color: var(--foreground, currentColor);\n background-color: var(--background, transparent);\n border: var(--background-border-width) solid var(--background-border, transparent);\n border-radius: var(--background-radius);\n padding: var(--layout-padding-size);\n\n &.horizontal {\n @apply flex-row items-stretch;\n height: var(--layout-control-height);\n\n .item.divider {\n margin-block: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n height: 100%;\n }\n }\n\n &.vertical {\n @apply flex-col;\n\n .item.divider {\n margin-inline: calc(var(--layout-padding-size) * -1);\n }\n .item.divider > [role=\"separator\"] {\n width: 100%;\n }\n }\n\n &.none {\n --layout-padding-size: 0px;\n @apply gap-0;\n }\n\n &.xs {\n --layout-radius-size: calc(var(--spacing) * 0.875);\n @apply space-x-0.5;\n }\n\n &.sm {\n --layout-radius-size: calc(var(--spacing) * 1.25);\n @apply space-x-1;\n }\n\n }\n\n .item {\n @apply flex items-stretch;\n position: relative;\n isolation: isolate;\n border-radius: var(--group-item-radius, 0);\n overflow: visible;\n\n &.grow {\n flex: 1;\n }\n\n &.divider {\n @apply p-0 shrink-0 flex-none;\n\n > [role=\"separator\"] {\n flex: 0 0 auto;\n }\n }\n }\n\n :is(.button, .input, .select, .expand) {\n height: 100%;\n min-height: var(--item-height);\n position: relative;\n isolation: isolate;\n overflow: visible;\n }\n\n .button {\n @apply flex box-border;\n width: auto;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n &[data-selected=\"true\"] {\n @apply relative;\n background-color: var(--button-selected-background, var(--background-pressed, var(--background-hover, var(--background))));\n color: var(--button-selected-foreground, var(--foreground));\n }\n }\n\n .horizontal .item.icon-button-item {\n @apply flex-1;\n }\n\n .item.icon-button-item > .button {\n @apply w-full;\n aspect-ratio: auto;\n }\n\n .item.icon-button-item > .button:global(.icon) {\n padding-inline: calc(var(--spacing) * 2);\n }\n\n .item.icon-button-item > .button:global(.icon):global(.sm) {\n padding-inline: calc(var(--spacing) * 1.5);\n }\n\n .item.icon-button-item > .button:global(.icon):global(.lg) {\n padding-inline: calc(var(--spacing) * 2.5);\n }\n\n .input {\n @apply flex flex-1 items-stretch overflow-visible;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n\n > [data-ring=\"true\"] {\n border-radius: inherit;\n }\n }\n\n .select {\n @apply flex items-stretch p-0 bg-transparent border-none;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand {\n @apply flex items-stretch;\n border-radius: var(--group-item-radius, var(--background-inner-radius));\n }\n\n .expand :global(.expand-scope),\n .expand :global(.expand) {\n @apply flex w-full h-full;\n }\n\n .expand :global(.expand) {\n @apply flex-col;\n border-radius: inherit;\n }\n\n .expand :global(.trigger) {\n @apply min-h-0;\n border-radius: inherit;\n }\n\n .trigger {}\n\n .group {\n .item :is(.button, .select) {\n border: none;\n }\n\n .input > [data-input-focus-surface=\"true\"] {\n border: none;\n }\n\n .button[data-selected=\"true\"] {\n font-weight: 500;\n }\n\n .item.divider > [role=\"separator\"] {\n --divider-background: var(--background);\n }\n\n &.none {\n .item:not(.divider) {\n overflow: hidden;\n }\n\n :is(.button, .trigger, .select) {\n border-radius: 0;\n --background-radius: 0;\n --background-inner-radius: 0;\n }\n\n .input {\n --radius-sm: 0;\n }\n\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .item:last-child {\n --group-item-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n }\n\n .item:only-child {\n --group-item-radius: var(--background-inner-radius);\n }\n\n &.horizontal {\n .item:first-child :is( .button, .trigger, .input > *, .select) {\n border-top-left-radius: var(--background-inner-radius);\n border-bottom-left-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is( .button, .trigger, .input > *, .select) {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child .trigger .icon-section {\n border-top-right-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n\n &.vertical {\n .item:first-child {\n --group-item-radius: var(--background-inner-radius) var(--background-inner-radius) 0 0;\n }\n\n .item:last-child {\n --group-item-radius: 0 0 var(--background-inner-radius) var(--background-inner-radius);\n }\n\n .item:first-child :is(.button, .trigger, .input > *, .select) {\n border-top-left-radius: var(--background-inner-radius);\n border-top-right-radius: var(--background-inner-radius);\n }\n\n .item:last-child :is(.button, .trigger, .input > *, .select) {\n border-bottom-left-radius: var(--background-inner-radius);\n border-bottom-right-radius: var(--background-inner-radius);\n }\n }\n }\n\n &:is(.xs, .sm) {\n .item {\n --group-item-radius: var(--background-inner-radius);\n }\n\n :is(.button, .trigger, .select) {\n border-radius: var(--background-inner-radius);\n }\n\n .input {\n --radius-sm: var(--background-inner-radius);\n }\n }\n }\n\n .group [data-ring=\"true\"] {\n --ring-shadow: none;\n --ring-border: transparent;\n --ring-border-visible: transparent;\n }\n\n .group :global(.focus-indicator) {\n display: none;\n }\n\n .group [data-focus-indicator=\"local\"] {\n display: none;\n }\n\n :is(.button[data-focus-visible=\"true\"], .trigger[data-focus-visible=\"true\"]) {\n @apply outline-none;\n box-shadow: none;\n }\n}\n",
4975
+ "cssTypes": "declare const styles: {\n \"focus-scope\": string;\n \"focus-indicator\": string;\n group: string;\n horizontal: string;\n vertical: string;\n none: string;\n xs: string;\n sm: string;\n item: string;\n \"icon-button-item\": string;\n grow: string;\n divider: string;\n button: string;\n input: string;\n select: string;\n expand: string;\n trigger: string;\n};\n\nexport default styles;\n"
4977
4976
  },
4978
4977
  "input": {
4979
4978
  "tsx": "\"use client\";\n\nimport React, { forwardRef, type ComponentPropsWithoutRef } from \"react\";\n\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { mergeProps, } from \"@react-aria/utils\";\n\nimport { ChevronUp, ChevronDown } from \"lucide-react\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { Tooltip } from \"@/components/Tooltip\";\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport { GroupContext } from \"@/components/Group/Group\";\nimport css from \"./Input.module.css\";\n\ntype Variant = \"default\" | \"ghost\";\n\ntype InputIconStyles = {\n left?: StyleValue;\n right?: StyleValue;\n};\n\ntype InputStepperStyles = {\n up?: StyleValue;\n down?: StyleValue;\n};\n\nexport interface InputStyleSlots {\n root?: StyleValue;\n icon?: StyleValue | InputIconStyles;\n stepper?: StyleValue | InputStepperStyles;\n}\n\nexport type InputStylesProp = StylesProp<InputStyleSlots>;\n\nexport type InputAction = InputActionDef | React.ReactNode;\ntype InputIconSlots = {\n prefix?: React.ReactNode;\n suffix?: React.ReactNode;\n};\n\nexport type InputActionDef = {\n icon: React.ReactNode;\n title: string;\n onClick?: React.MouseEventHandler<HTMLButtonElement>;\n};\n\ntype InputActionSlots = {\n left?: InputAction[];\n right?: InputAction[];\n};\n\nconst resolveInputBaseStyles = createStylesResolver(['root', 'iconLeft', 'iconRight', 'stepperUp', 'stepperDown'] as const);\n\nfunction resolveInputStyles(styles: InputStylesProp | undefined) {\n if (!styles || typeof styles === 'string' || Array.isArray(styles)) return resolveInputBaseStyles(styles);\n const { root, icon, stepper } = styles;\n\n let iconLeft: StyleValue | undefined;\n let iconRight: StyleValue | undefined;\n let stepperUp: StyleValue | undefined;\n let stepperDown: StyleValue | undefined;\n\n if (icon) {\n if (typeof icon === 'string' || Array.isArray(icon)) {\n iconLeft = icon;\n iconRight = icon;\n } else {\n iconLeft = icon.left;\n iconRight = icon.right;\n }\n }\n\n if (stepper) {\n if (typeof stepper === 'string' || Array.isArray(stepper)) {\n stepperUp = stepper;\n stepperDown = stepper;\n } else {\n stepperUp = stepper.up;\n stepperDown = stepper.down;\n }\n }\n\n return resolveInputBaseStyles({ root, iconLeft, iconRight, stepperUp, stepperDown });\n}\n\nexport interface InputProps extends Omit<ComponentPropsWithoutRef<\"input\">, \"size\"> {\n /** Controls the visual style of the input */\n variant?: Variant;\n /** Whether the input is in an error state */\n error?: boolean;\n /** Icon displayed before the input value by default, or in named prefix/suffix slots */\n icon?: React.ReactNode | InputIconSlots;\n /** Inline actions rendered on the left or right side of the input. Passing an array keeps the existing right-side behavior. */\n actions?: InputAction[] | InputActionSlots;\n /** Hint content rendered inside a badge on the right side of the input, commonly used for keyboard shortcuts. */\n hint?: React.ReactNode;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: InputStylesProp;\n /** Hides the spinner controls for number inputs */\n \"hide-controls\"?: boolean;\n}\n\nfunction isInputIconSlots(icon: InputProps[\"icon\"]): icon is InputIconSlots {\n return typeof icon === \"object\" && icon !== null && !React.isValidElement(icon) && (\"prefix\" in icon || \"suffix\" in icon);\n}\n\nfunction resolveInputIcon(icon: InputProps[\"icon\"]) {\n if (!icon) {\n return undefined;\n }\n\n if (isInputIconSlots(icon)) {\n return icon;\n }\n\n return { prefix: icon };\n}\n\nfunction isInputActionSlots(actions: InputProps[\"actions\"]): actions is InputActionSlots {\n return typeof actions === \"object\" && actions !== null && !Array.isArray(actions) && !React.isValidElement(actions) && (\"left\" in actions || \"right\" in actions);\n}\n\nfunction resolveInputActions(actions: InputProps[\"actions\"]): InputActionSlots {\n if (!actions) {\n return {};\n }\n\n if (isInputActionSlots(actions)) {\n return actions;\n }\n\n return { right: actions };\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(\n (\n {\n className,\n variant = \"default\",\n error = false,\n disabled,\n icon,\n actions,\n hint,\n type = \"text\",\n onFocus,\n onBlur,\n styles: stylesProp,\n \"hide-controls\": hideControls = false,\n ...props\n },\n ref\n ) => {\n const groupContext = React.useContext(GroupContext);\n const resolvedActions = resolveInputActions(actions);\n const resolvedIcon = resolveInputIcon(icon);\n const leftActions = resolvedActions.left ?? [];\n const rightActions = resolvedActions.right ?? [];\n const hasPrefix = !!resolvedIcon?.prefix;\n const hasSuffix = !!resolvedIcon?.suffix;\n const hasLeftActions = leftActions.length > 0;\n const hasRightActions = rightActions.length > 0;\n const hasHint = hint !== undefined && hint !== null;\n const hasStartAdornment = hasPrefix || hasLeftActions;\n const isNumberType = type === \"number\";\n const [isFocused, setIsFocused] = React.useState(false);\n\n const inputRef = React.useRef<HTMLInputElement>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const scopeRef = React.useRef<HTMLDivElement>(null);\n const mergedRef = useMergeRefs(ref, inputRef);\n\n const { focusProps, isFocusVisible } = useFocusRing();\n const { scopeProps, indicatorProps } = useFocus({\n scopeRef,\n containerRef,\n surfaceSelector: '[data-input-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n });\n\n const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(true);\n onFocus?.(e);\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setIsFocused(false);\n onBlur?.(e);\n };\n\n const handleSpinClick = (direction: \"up\" | \"down\") => {\n if (!inputRef.current || disabled) return;\n\n const input = inputRef.current;\n\n if (direction === \"up\") {\n input.stepUp();\n } else {\n input.stepDown();\n }\n\n // Dispatch native input event to trigger React onChange handlers\n const event = new Event(\"input\", { bubbles: true });\n input.dispatchEvent(event);\n };\n\n const resolved = resolveInputStyles(stylesProp);\n const showControls = isNumberType && !hideControls;\n const hasEndAdornment = hasSuffix || hasRightActions || hasHint || showControls;\n const adornmentPadding = \"var(--adornment-offset)\";\n const inputPaddingStyle: React.CSSProperties = {\n ...(hasStartAdornment ? { paddingLeft: adornmentPadding } : {}),\n ...(hasEndAdornment ? { paddingRight: adornmentPadding } : {}),\n };\n\n const renderAction = (action: InputAction, index: number) => {\n const key = React.isValidElement(action) ? index : ((action as InputActionDef).title || index);\n\n return React.isValidElement(action) ? (\n <React.Fragment key={key}>{action}</React.Fragment>\n ) : (\n <Tooltip key={key} content={(action as InputActionDef).title} position=\"top\">\n <button\n type=\"button\"\n className={css.action}\n aria-label={(action as InputActionDef).title}\n onClick={(action as InputActionDef).onClick}\n >\n {(action as InputActionDef).icon}\n </button>\n </Tooltip>\n );\n };\n\n const inputRoot = (\n <div\n ref={containerRef}\n className={cn('input', css.container, resolved.root)}\n data-input-focus-surface=\"true\"\n data-focused={isFocused ? \"true\" : undefined}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-disabled={disabled || undefined}\n data-error={error ? \"true\" : undefined}\n data-variant={variant}\n >\n {hasStartAdornment && (\n <div className={css['start-adornments']} data-start-adornments>\n {hasPrefix && (\n <div className={cn('icon-wrapper', css['icon-wrapper'], resolved.iconLeft)}>\n <span className={css.icon}>\n {resolvedIcon?.prefix}\n </span>\n </div>\n )}\n {hasLeftActions && (\n <div className={css.actions} data-actions data-actions-position=\"left\">\n {leftActions.map(renderAction)}\n </div>\n )}\n </div>\n )}\n <input\n ref={mergedRef}\n type={type}\n disabled={disabled}\n data-focus-visible={isFocusVisible ? \"true\" : undefined}\n data-focused={isFocused ? \"true\" : undefined}\n data-disabled={disabled || undefined}\n data-error={error ? \"true\" : undefined}\n data-variant={variant}\n className={cn(css.input, className)}\n style={inputPaddingStyle}\n {...mergeProps(focusProps, {\n onFocus: handleFocus,\n onBlur: handleBlur,\n ...props,\n })}\n />\n {hasEndAdornment && (\n <div className={css['end-adornments']} data-end-adornments>\n {hasSuffix && (\n <div className={cn('icon-wrapper', css['icon-wrapper'], resolved.iconRight)}>\n <span className={css.icon}>\n {resolvedIcon?.suffix}\n </span>\n </div>\n )}\n {hasRightActions && (\n <div className={css.actions} data-actions data-actions-position=\"right\">\n {rightActions.map(renderAction)}\n </div>\n )}\n {hasHint && <span className={css.hint} data-hint>{hint}</span>}\n {showControls && (\n <div\n className={css.controls}\n data-disabled={disabled || undefined}\n >\n <button\n type=\"button\"\n className={cn('stepper', css.stepper, resolved.stepperUp)}\n onClick={() => handleSpinClick(\"up\")}\n disabled={disabled}\n tabIndex={-1}\n aria-label=\"Increment\"\n >\n <ChevronUp size={12} />\n </button>\n <button\n type=\"button\"\n className={cn('stepper', css.stepper, resolved.stepperDown)}\n onClick={() => handleSpinClick(\"down\")}\n disabled={disabled}\n tabIndex={-1}\n aria-label=\"Decrement\"\n >\n <ChevronDown size={12} />\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n );\n\n if (groupContext) {\n return inputRoot;\n }\n\n return (\n <div\n ref={scopeRef}\n className={cn(\"input-scope\", scopeProps.className, css.scope)}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n {inputRoot}\n </div>\n );\n }\n);\n\nInput.displayName = \"Input\";\n",
@@ -4981,13 +4980,13 @@ export const generatedSourceCode = {
4981
4980
  "cssTypes": "declare const styles: {\n scope: string;\n input: string;\n \"icon-wrapper\": string;\n icon: string;\n container: string;\n \"start-adornments\": string;\n \"end-adornments\": string;\n actions: string;\n action: string;\n hint: string;\n controls: string;\n stepper: string;\n};\n\nexport default styles;\n"
4982
4981
  },
4983
4982
  "label": {
4984
- "tsx": "import { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport css from \"./Label.module.css\";\n\ninterface LabelStyleSlots {\n root?: StyleValue;\n requiredIndicator?: StyleValue;\n helperText?: StyleValue;\n}\n\ntype LabelStylesProp = StylesProp<LabelStyleSlots>;\n\nconst resolveLabelBaseStyles = createStylesResolver(['root', 'requiredIndicator', 'helperText'] as const);\n\nexport interface LabelProps\n extends React.LabelHTMLAttributes<HTMLLabelElement> {\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: LabelStylesProp;\n /** Whether to show a required asterisk indicator */\n required?: boolean;\n /** Helper text shown below the label */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error */\n helperTextError?: boolean;\n /** Size of the label text */\n size?: \"sm\" | \"md\" | \"lg\" | null;\n /** Whether the label appears disabled */\n disabled?: boolean | null;\n /** Whether to apply error styling */\n error?: boolean | null;\n}\n\nconst Label = ({\n className,\n styles,\n size = \"md\",\n disabled,\n error,\n required,\n helperText,\n helperTextError,\n children,\n ...props\n}: LabelProps) => {\n const resolved = resolveLabelBaseStyles(styles);\n return (\n <div className={cn('label', css.label, 'w-full', className, resolved.root)}>\n <label\n data-size={size ?? 'md'}\n data-disabled={disabled || undefined}\n data-error={error || undefined}\n {...props}\n >\n {children}\n {required && (\n <span className={cn('required-indicator', css['required-indicator'], resolved.requiredIndicator)} aria-label=\"required\">\n *\n </span>\n )}\n </label>\n {helperText && (\n <p\n className={cn('helper-text', css['helper-text'], resolved.helperText)}\n data-error={helperTextError || undefined}\n >\n {helperText}\n </p>\n )}\n </div>\n );\n};\n\nLabel.displayName = \"Label\";\n\nexport { Label };\n",
4985
- "css": "@reference \"tailwindcss\";\n\n@layer components {\n .label {\n --background: transparent;\n --foreground: var(--foreground-primary);\n --foreground-disabled: var(--foreground-secondary);\n --foreground-error: var(--danger-600);\n }\n\n .label > label {\n display: block;\n font-family: inherit;\n font-size: var(--text-sm);\n color: var(--foreground);\n transition: color 150ms ease;\n\n &[data-size=\"sm\"] { font-size: var(--text-sm); }\n &[data-size=\"lg\"] { font-size: var(--text-md); }\n\n &[data-disabled] {\n color: var(--foreground-disabled);\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n &[data-error] {\n color: var(--foreground-error);\n }\n }\n\n .label > .required-indicator {\n margin-left: 0.25rem;\n color: var(--required-color);\n }\n\n .label > .helper-text {\n --helper-foreground: var(--foreground-secondary);\n --helper-foreground-error: var(--danger-600);\n\n display: block;\n font-size: var(--text-sm);\n margin-top: 0.25rem;\n transition: color 150ms ease;\n color: var(--helper-foreground);\n\n &[data-error] {\n color: var(--helper-foreground-error);\n }\n }\n}\n",
4986
- "cssTypes": "declare const styles: {\n label: string;\n \"required-indicator\": string;\n \"helper-text\": string;\n};\n\nexport default styles;\n"
4983
+ "tsx": "import { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport css from \"./Label.module.css\";\n\ninterface LabelStyleSlots {\n root?: StyleValue;\n text?: StyleValue;\n requiredIndicator?: StyleValue;\n helperText?: StyleValue;\n}\n\ntype LabelStylesProp = StylesProp<LabelStyleSlots>;\n\nconst resolveLabelBaseStyles = createStylesResolver([\"root\", \"text\", \"requiredIndicator\", \"helperText\"] as const);\n\nexport interface LabelProps\n extends React.LabelHTMLAttributes<HTMLLabelElement> {\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: LabelStylesProp;\n /** Whether to show a required asterisk indicator */\n required?: boolean;\n /** Helper text shown below the label */\n helperText?: React.ReactNode;\n /** Whether to style the helper text as an error */\n helperTextError?: boolean;\n /** Size of the label text */\n size?: \"sm\" | \"md\" | \"lg\" | null;\n /** Whether the label appears disabled */\n disabled?: boolean | null;\n /** Whether to apply error styling */\n error?: boolean | null;\n}\n\nconst Label = ({\n className,\n styles,\n size = \"md\",\n disabled,\n error,\n required,\n helperText,\n helperTextError,\n children,\n ...props\n}: LabelProps) => {\n const resolved = resolveLabelBaseStyles(styles);\n return (\n <div className={cn('label', css.label, 'w-full', className, resolved.root)}>\n <label\n className={cn(\"text\", css.text, resolved.text)}\n data-size={size ?? 'md'}\n data-disabled={disabled || undefined}\n data-error={error || undefined}\n {...props}\n >\n {children}\n {required && (\n <span className={cn(\"required-indicator\", css[\"required-indicator\"], resolved.requiredIndicator)} aria-label=\"required\">\n *\n </span>\n )}\n </label>\n {helperText && (\n <p\n className={cn(\"helper-text\", css[\"helper-text\"], resolved.helperText)}\n data-error={helperTextError || undefined}\n >\n {helperText}\n </p>\n )}\n </div>\n );\n};\n\nLabel.displayName = \"Label\";\n\nexport { Label };\n",
4984
+ "css": "@reference \"tailwindcss\";\n\n@layer components {\n .label {\n --background: transparent;\n --foreground: var(--foreground-primary);\n --disabled-foreground: var(--foreground-secondary);\n --error-foreground: var(--danger-600);\n --helper-color: var(--foreground-secondary);\n --helper-error-color: var(--danger-600);\n --required-color: var(--danger-600);\n }\n\n .text {\n display: block;\n font-family: inherit;\n font-size: var(--text-sm);\n color: var(--foreground);\n transition: color 150ms ease;\n\n &[data-disabled] {\n color: var(--disabled-foreground);\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n &[data-error] {\n color: var(--error-foreground);\n }\n }\n\n .required-indicator {\n margin-left: 0.25rem;\n color: var(--required-color);\n }\n\n .helper-text {\n display: block;\n font-size: var(--text-sm);\n margin-top: 0.25rem;\n transition: color 150ms ease;\n color: var(--helper-color);\n\n &[data-error] {\n color: var(--helper-error-color);\n }\n }\n}\n",
4985
+ "cssTypes": "declare const styles: {\n label: string;\n text: string;\n \"required-indicator\": string;\n \"helper-text\": string;\n};\n\nexport default styles;\n"
4987
4986
  },
4988
4987
  "list": {
4989
4988
  "tsx": "'use client';\n\nimport React from 'react';\nimport { cn } from \"./utils\";\nimport { createStylesResolver } from '@/lib/styles';\nimport { resolveGapStep, type GapSize } from '@/lib/gap';\nimport { Divider as FoldDivider } from '@/components/Divider';\nimport styles from './List.module.css';\nimport { ListContext, useListContext } from './list.context';\nimport {\n ListStyleSlot,\n ListContainerProps,\n ListHeaderProps,\n ListRef,\n ActionGroupComponentProps,\n FooterComponentProps,\n} from './list.types';\nimport { DividerProps } from '@/components/Divider';\nimport { scrollItemIntoView } from '@/utils/list-navigation';\n\nconst resolveListBaseStyles = createStylesResolver([\n 'root',\n 'header',\n 'item',\n 'checkbox',\n 'control',\n 'media',\n 'title',\n 'desc',\n 'actions',\n 'action',\n 'footer',\n] as const);\n\n// Ref container for keyboard navigation\nconst Container = React.forwardRef<ListRef, ListContainerProps>(\n (\n {\n items: _items = [],\n variant = 'default',\n orientation = 'vertical',\n gap,\n spacing = 'default',\n onNavigate,\n children,\n className,\n styles: stylesProp,\n style,\n ...props\n },\n ref\n ) => {\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const [focusedItem, setFocusedItemState] = React.useState<HTMLElement | null>(null);\n const [isFocusMode, setIsFocusMode] = React.useState(false);\n const shouldScrollFocusedItemRef = React.useRef(false);\n const resolvedStyles = resolveListBaseStyles(stylesProp) as Record<ListStyleSlot, string>;\n\n const getFocusableItems = React.useCallback(() => {\n if (!rootRef.current) return [];\n\n return Array.from(rootRef.current.querySelectorAll<HTMLElement>('[role=\"listitem\"]')).filter((item) => (\n item.isConnected &&\n item.tabIndex >= 0 &&\n item.getAttribute('aria-hidden') !== 'true' &&\n item.getAttribute('aria-disabled') !== 'true' &&\n item.getAttribute('data-disabled') !== 'true'\n ));\n }, []);\n\n const getFocusedIndex = React.useCallback(() => {\n if (!focusedItem || !isFocusMode) return null;\n const itemIndex = getFocusableItems().indexOf(focusedItem);\n return itemIndex >= 0 ? itemIndex : null;\n }, [focusedItem, getFocusableItems, isFocusMode]);\n\n const setFocusedItem = React.useCallback((\n item: HTMLElement | null,\n options: { enterFocusMode?: boolean; scroll?: boolean } = {},\n ) => {\n if (!item) {\n shouldScrollFocusedItemRef.current = false;\n setFocusedItemState(null);\n setIsFocusMode(false);\n return;\n }\n\n if (options.scroll) {\n shouldScrollFocusedItemRef.current = true;\n }\n\n setFocusedItemState(item);\n setIsFocusMode(options.enterFocusMode ?? true);\n }, []);\n\n const focusItemAtIndex = React.useCallback((index: number, scroll = true) => {\n const itemsInOrder = getFocusableItems();\n const target = itemsInOrder[index];\n if (!target) return false;\n\n shouldScrollFocusedItemRef.current = scroll;\n target.focus({ preventScroll: true });\n return true;\n }, [getFocusableItems]);\n\n const focusAdjacentItem = React.useCallback((currentItem: HTMLElement | null, direction: 1 | -1, scroll = true) => {\n const itemsInOrder = getFocusableItems();\n if (itemsInOrder.length === 0) return false;\n\n const currentIndex = currentItem ? itemsInOrder.indexOf(currentItem) : -1;\n const nextIndex = currentIndex === -1\n ? (direction === 1 ? 0 : itemsInOrder.length - 1)\n : Math.min(Math.max(currentIndex + direction, 0), itemsInOrder.length - 1);\n\n if (currentIndex !== -1 && nextIndex === currentIndex) {\n return false;\n }\n\n return focusItemAtIndex(nextIndex, scroll);\n }, [focusItemAtIndex, getFocusableItems]);\n\n const focusBoundaryItem = React.useCallback((position: 'first' | 'last', scroll = true) => {\n const itemsInOrder = getFocusableItems();\n if (itemsInOrder.length === 0) return false;\n\n return focusItemAtIndex(position === 'first' ? 0 : itemsInOrder.length - 1, scroll);\n }, [focusItemAtIndex, getFocusableItems]);\n\n // Expose ref methods for keyboard navigation\n React.useImperativeHandle(ref, () => ({\n focusNext: () => {\n focusAdjacentItem(focusedItem, 1);\n onNavigate?.down?.();\n },\n focusPrev: () => {\n focusAdjacentItem(focusedItem, -1);\n onNavigate?.up?.();\n },\n focusFirst: () => {\n focusBoundaryItem('first');\n onNavigate?.down?.();\n },\n focusLast: () => {\n focusBoundaryItem('last');\n onNavigate?.up?.();\n },\n selectHighlighted: () => {\n onNavigate?.enter?.();\n },\n clearHighlight: () => {\n setFocusedItem(null, { enterFocusMode: false });\n },\n getHighlightedIndex: () => getFocusedIndex(),\n }), [focusAdjacentItem, focusBoundaryItem, focusedItem, getFocusedIndex, onNavigate, setFocusedItem]);\n\n React.useEffect(() => {\n if (!isFocusMode || !focusedItem || !shouldScrollFocusedItemRef.current) return;\n shouldScrollFocusedItemRef.current = false;\n scrollItemIntoView(focusedItem);\n }, [focusedItem, isFocusMode]);\n\n React.useEffect(() => {\n if (!focusedItem) return;\n if (focusedItem.isConnected) return;\n setFocusedItem(null, { enterFocusMode: false });\n }, [focusedItem, setFocusedItem]);\n\n const contextValue = React.useMemo(\n () => ({\n focusedItem,\n isFocusMode,\n orientation,\n rootRef,\n styles: resolvedStyles,\n setFocusedItem,\n focusAdjacentItem,\n focusBoundaryItem,\n }),\n [focusAdjacentItem, focusBoundaryItem, focusedItem, isFocusMode, orientation, resolvedStyles, setFocusedItem]\n );\n\n return (\n <ListContext.Provider value={contextValue}>\n <div\n ref={rootRef}\n role=\"list\"\n className={cn(\n 'list',\n styles.container,\n className,\n resolvedStyles.root,\n )}\n style={{\n ...style,\n ...(gap ? { \"--list-gap-step\": resolveGapStep(gap as GapSize) } : null),\n } as React.CSSProperties}\n data-variant={variant}\n data-orientation={orientation}\n data-gap={gap}\n data-spacing={spacing}\n data-focus-mode={isFocusMode ? 'row' : undefined}\n data-keyboard-mode={isFocusMode ? 'true' : undefined}\n {...(props as React.HTMLAttributes<HTMLDivElement>)}\n >\n {children}\n </div>\n </ListContext.Provider>\n );\n }\n);\nContainer.displayName = 'List';\n\n/** Sticky heading row above a section of list items */\nconst Header = React.forwardRef<HTMLElement, ListHeaderProps>(\n ({ sticky, children, className, ...props }, ref) => {\n const { styles: listStyles } = useListContext();\n\n return (\n <header\n ref={ref}\n className={cn(styles.header, listStyles.header, sticky && styles.sticky, className)}\n {...props}\n >\n {children}\n </header>\n );\n }\n);\nHeader.displayName = 'List.Header';\n\n/** Row of action buttons aligned to the right of a list item */\nconst ActionGroup = React.forwardRef<HTMLDivElement, ActionGroupComponentProps>(\n ({ justify = 'start', children, className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(styles.actionGroup, className)}\n data-justify={justify}\n {...props}\n >\n {children}\n </div>\n )\n);\nActionGroup.displayName = 'List.ActionGroup';\n\n/** Horizontal separator between list sections */\nconst Divider = React.forwardRef<HTMLDivElement, DividerProps>(\n ({ className, ...props }, ref) => (\n <FoldDivider\n ref={ref}\n className={className}\n {...props}\n />\n )\n);\nDivider.displayName = 'List.Divider';\n\n/** Fixed bottom row beneath the list body */\nconst Footer = React.forwardRef<HTMLElement, FooterComponentProps>(\n ({ align = 'center', children, className, ...props }, ref) => {\n const { styles: listStyles } = useListContext();\n\n return (\n <footer\n ref={ref}\n className={cn(styles.footer, listStyles.footer, className)}\n data-align={align}\n {...props}\n >\n {children}\n </footer>\n );\n }\n);\nFooter.displayName = 'List.Footer';\n\n// Compound component\nconst List = Object.assign(Container, {\n Header,\n Item: null as any, // Set in index.ts\n Checkbox: null as any,\n CheckboxIndicator: null as any,\n Switch: null as any,\n Input: null as any,\n Select: null as any,\n Media: null as any,\n Desc: null as any,\n ActionGroup,\n Divider,\n Footer,\n});\n\nexport { Container, Header, ActionGroup, Divider, Footer };\n",
4990
- "css": "@reference \"tailwindcss\";\n\n@layer components {\n .container {\n --gap-scale: 0.75;\n\n color: var(--foreground);\n @apply flex flex-col;\n gap: calc(var(--spacing, 0.25rem) * var(--list-gap-step, 0) * var(--gap-scale, 1));\n }\n\n .container[data-orientation=\"horizontal\"] {\n @apply flex-row flex-wrap;\n }\n\n .header {\n @apply flex items-center justify-between;\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n padding-top: 1rem;\n padding-bottom: 1rem;\n backdrop-filter: blur(12px);\n z-index: 10;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n }\n\n .header > :first-child {\n font-weight: var(--font-weight-semibold);\n font-size: 1.125rem;\n color: var(--header-title-foreground);\n }\n\n .header > :last-child {\n color: var(--header-subtitle-foreground);\n }\n\n .item {\n --background: transparent;\n\n @apply flex gap-3 px-2 py-1 cursor-pointer;\n background-color: var(--background);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .item[data-focus-visible=\"true\"] {\n box-shadow:\n inset 0 0 0 1px var(--item-focus-visible-background, var(--focus-visible-background)),\n 0 0 0 2px var(--item-focus-visible, var(--focus-visible));\n border-radius: var(--item-radius, var(--radius-sm, 0.375rem));\n outline: none;\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .container[data-keyboard-mode=\"true\"] .item[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.6);\n pointer-events: none;\n }\n\n .checkbox,\n .control,\n .media {\n @apply flex items-center justify-center flex-shrink-0;\n }\n\n .control {\n margin-left: auto;\n }\n\n .control[data-placement=\"start\"] {\n margin-left: 0;\n }\n\n .media {\n @apply h-8 w-8;\n }\n\n .title {\n font-size: var(--text-sm);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n @apply truncate;\n }\n\n .desc {\n font-size: var(--text-sm);\n color: var(--desc-foreground);\n @apply truncate;\n }\n\n .actionGroup {\n @apply flex items-center;\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n }\n\n .actionGroup[data-justify=\"between\"] { justify-content: space-between; }\n .actionGroup[data-justify=\"start\"] { justify-content: flex-start; }\n .actionGroup[data-justify=\"end\"] { justify-content: flex-end; }\n\n .actions {\n align-items: center;\n gap: 0.25rem;\n margin-left: auto;\n flex-shrink: 0;\n @apply flex p-1.5 opacity-70 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100;\n }\n\n .action {\n --background: transparent;\n\n @apply flex items-center justify-center;\n border-radius: 0.25rem;\n background-color: var(--background);\n color: var(--foreground);\n @apply p-2;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex p-6 pb-12;\n }\n\n .footer[data-align=\"center\"] { justify-content: center; }\n .footer[data-align=\"start\"] { justify-content: flex-start; }\n .footer[data-align=\"end\"] { justify-content: flex-end; }\n\n .container[data-spacing=\"sm\"] .footer {\n padding: 0.375rem 0.75rem;\n padding-bottom: 0.375rem;\n }\n}\n",
4989
+ "css": "@reference \"tailwindcss\";\n\n@layer components {\n .container {\n --gap-scale: 0.75;\n\n color: var(--foreground);\n @apply flex flex-col;\n gap: calc(var(--spacing, 0.25rem) * var(--list-gap-step, 0) * var(--gap-scale, 1));\n }\n\n .container[data-orientation=\"horizontal\"] {\n @apply flex-row flex-wrap;\n }\n\n .header {\n @apply flex items-center justify-between;\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n padding-top: 1rem;\n padding-bottom: 1rem;\n backdrop-filter: blur(12px);\n z-index: 10;\n }\n\n .sticky {\n position: sticky;\n top: 0;\n }\n\n .header > :first-child {\n font-weight: var(--font-weight-semibold);\n font-size: 1.125rem;\n color: var(--header-title-foreground);\n }\n\n .header > :last-child {\n color: var(--header-subtitle-foreground);\n }\n\n .item {\n --background: transparent;\n\n @apply flex gap-3 px-2 py-1 cursor-pointer;\n background-color: var(--background);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .item[data-focus-visible=\"true\"] {\n box-shadow:\n inset 0 0 0 1px var(--item-focus-visible-background, var(--focus-visible-background)),\n 0 0 0 2px var(--item-focus-visible, var(--focus-visible));\n border-radius: var(--item-radius, var(--radius-sm, 0.375rem));\n outline: none;\n }\n\n .item:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .container[data-keyboard-mode=\"true\"] .item[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .item[data-disabled=\"true\"] {\n cursor: not-allowed;\n opacity: var(--disabled-opacity, 0.6);\n pointer-events: none;\n }\n\n .checkbox,\n .control,\n .media {\n @apply flex items-center justify-center flex-shrink-0;\n }\n\n .control {\n margin-left: auto;\n }\n\n .control[data-placement=\"start\"] {\n margin-left: 0;\n }\n\n .media {\n @apply h-8 w-8;\n }\n\n .title {\n font-size: var(--text-sm);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n @apply truncate;\n }\n\n .desc {\n font-size: var(--text-sm);\n color: var(--desc-foreground);\n @apply truncate;\n }\n\n .actionGroup {\n @apply flex items-center;\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n }\n\n .actionGroup[data-justify=\"between\"] { justify-content: space-between; }\n .actionGroup[data-justify=\"start\"] { justify-content: flex-start; }\n .actionGroup[data-justify=\"end\"] { justify-content: flex-end; }\n\n .actions {\n align-items: center;\n gap: 0.25rem;\n margin-left: auto;\n flex-shrink: 0;\n @apply flex p-1.5 opacity-70 transition-opacity;\n }\n\n .item:hover .actions,\n .item:focus-within .actions {\n opacity: 1;\n }\n\n .action {\n --background: transparent;\n\n @apply flex items-center justify-center;\n border-radius: 0.25rem;\n background-color: var(--background);\n color: var(--foreground);\n @apply p-2;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .action:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex p-6 pb-12;\n }\n\n .footer[data-align=\"center\"] { justify-content: center; }\n .footer[data-align=\"start\"] { justify-content: flex-start; }\n .footer[data-align=\"end\"] { justify-content: flex-end; }\n\n .container[data-spacing=\"sm\"] .footer {\n padding: 0.375rem 0.75rem;\n padding-bottom: 0.375rem;\n }\n}\n",
4991
4990
  "cssTypes": "declare const styles: {\n readonly container: string;\n readonly header: string;\n readonly sticky: string;\n readonly item: string;\n readonly actionGroup: string;\n readonly actions: string;\n readonly action: string;\n readonly checkbox: string;\n readonly control: string;\n readonly media: string;\n readonly title: string;\n readonly desc: string;\n readonly footer: string;\n};\n\nexport default styles;\n"
4992
4991
  },
4993
4992
  "mask": {
@@ -5001,7 +5000,7 @@ export const generatedSourceCode = {
5001
5000
  "cssTypes": "declare const styles: {\n trigger: string\n content: string\n list: string\n item: string\n 'item-indicator': string\n 'sub-trigger': string\n 'sub-trigger-chevron': string\n 'sub-content': string\n label: string\n separator: string\n shortcut: string\n}\n\nexport default styles\n"
5002
5001
  },
5003
5002
  "modal": {
5004
- "tsx": "\"use client\"\n\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useDialog } from \"react-aria\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useOverlayTriggerState } from \"react-stately\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { asElementProps } from \"@/lib/react-aria\";\nimport { X } from \"lucide-react\";\nimport css from \"./Modal.module.css\";\n\nconst useModalKeyboard = (\n ref: React.RefObject<HTMLDivElement | null>,\n isOpen: boolean,\n isDismissable: boolean,\n isKeyboardDismissDisabled: boolean,\n onClose: () => void\n) => {\n const onCloseRef = React.useRef(onClose);\n onCloseRef.current = onClose;\n\n React.useEffect(() => {\n if (!isOpen || !ref.current) return;\n\n ref.current.focus();\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && isDismissable && !isKeyboardDismissDisabled) {\n e.preventDefault();\n onCloseRef.current();\n }\n };\n\n ref.current.addEventListener(\"keydown\", handleKeyDown);\n return () => ref.current?.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isDismissable, isKeyboardDismissDisabled]);\n};\n\nexport interface ModalStyleSlots {\n root?: StyleValue;\n overlay?: StyleValue;\n backdrop?: StyleValue;\n header?: StyleValue;\n title?: StyleValue;\n spacer?: StyleValue;\n close?: StyleValue;\n closeIcon?: StyleValue;\n content?: StyleValue;\n footer?: StyleValue;\n}\n\nexport type ModalStylesProp = StylesProp<ModalStyleSlots>;\n\nconst resolveModalBaseStyles = createStylesResolver([\n 'root', 'overlay', 'backdrop', 'header', 'title', 'spacer', 'close', 'closeIcon', 'content', 'footer'\n] as const);\n\nfunction resolveModalStyles(styles: ModalStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveModalBaseStyles(styles);\n const { root, overlay, backdrop, header, title, spacer, close, closeIcon, content, footer } = styles;\n return resolveModalBaseStyles({ root, overlay, backdrop, header, title, spacer, close, closeIcon, content, footer });\n}\n\nexport interface ModalProps {\n /** Whether the modal is open */\n isOpen?: boolean;\n /** Callback when the open state changes */\n onOpenChange?: (isOpen: boolean) => void;\n /** Optional title rendered in the modal header bar */\n title?: React.ReactNode;\n /** Modal body content */\n children: React.ReactNode;\n /** Optional footer content rendered below the body */\n footer?: React.ReactNode;\n /** Whether to show the X close button in the header */\n close?: boolean;\n /** Controls modal width: \"fit\" adapts to content, \"auto\" uses default width */\n size?: \"fit\" | \"auto\";\n /** Whether clicking the backdrop dismisses the modal */\n isDismissable?: boolean;\n /** Prevents the Escape key from dismissing the modal */\n isKeyboardDismissDisabled?: boolean;\n /** Additional class for the modal panel */\n className?: string;\n /** Additional class for the inner content area */\n contentClassName?: string;\n /** Additional class for the backdrop overlay */\n overlayClassName?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ModalStylesProp;\n}\n\nfunction getModalChildDisplayName(child: React.ReactNode) {\n if (!React.isValidElement(child)) return null;\n const type = child.type as { displayName?: string };\n return type.displayName ?? null;\n}\n\n\n/**\n * Modal component that displays content in a centered dialog with a backdrop overlay.\n * Built with React Aria for full accessibility support including focus management,\n * keyboard handling, and screen reader announcements.\n */\nconst ModalBase = React.forwardRef<HTMLDivElement, ModalProps>(\n (\n {\n isOpen: controlledIsOpen,\n onOpenChange,\n title,\n children,\n footer,\n close = true,\n size = \"auto\",\n isDismissable = true,\n isKeyboardDismissDisabled = false,\n className,\n contentClassName,\n overlayClassName,\n styles,\n },\n ref\n ) => {\n const modalRef = React.useRef<HTMLDivElement>(null);\n const [mounted, setMounted] = React.useState(false);\n const [isClosePressed, setIsClosePressed] = React.useState(false);\n const [isCloseHovered, setIsCloseHovered] = React.useState(false);\n const [isCloseFocused, setIsCloseFocused] = React.useState(false);\n const [isCloseFocusVisible, setIsCloseFocusVisible] = React.useState(false);\n\n const resolved = resolveModalStyles(styles);\n\n // Use uncontrolled state management via useOverlayTriggerState\n const state = useOverlayTriggerState({\n isOpen: controlledIsOpen,\n onOpenChange: onOpenChange,\n });\n\n // Handle mount to prevent hydration issues\n React.useEffect(() => {\n setMounted(true);\n }, []);\n\n // Use forwardRef callback to expose modalRef\n React.useImperativeHandle(ref, () => modalRef.current as HTMLDivElement);\n\n // Handle keyboard events and auto-focus\n useModalKeyboard(\n modalRef,\n state.isOpen,\n isDismissable,\n isKeyboardDismissDisabled,\n () => state.close()\n );\n\n // useDialog hook provides accessibility attributes and title handling\n const { dialogProps, titleProps } = useDialog({}, modalRef);\n const { focusProps: modalFocusProps, isFocused: isModalFocused, isFocusVisible: isModalFocusVisible } = useFocusRing();\n\n const handleClose = () => state.close();\n\n if (!mounted || !state.isOpen) return null;\n\n const handleCloseMouseDown = () => setIsClosePressed(true);\n const handleCloseMouseUp = () => setIsClosePressed(false);\n const handleCloseMouseLeave = () => {\n setIsClosePressed(false);\n setIsCloseHovered(false);\n };\n const handleCloseMouseEnter = () => setIsCloseHovered(true);\n const handleCloseFocus = (event: React.FocusEvent<HTMLButtonElement>) => {\n setIsCloseFocused(true);\n setIsCloseFocusVisible(event.currentTarget.matches(\":focus-visible\"));\n };\n const handleCloseBlur = () => {\n setIsCloseFocused(false);\n setIsCloseFocusVisible(false);\n };\n\n const childArray = React.Children.toArray(children);\n const slottedHeader: React.ReactNode[] = [];\n const slottedBody: React.ReactNode[] = [];\n const slottedFooter: React.ReactNode[] = [];\n const unslottedChildren: React.ReactNode[] = [];\n\n childArray.forEach((child) => {\n switch (getModalChildDisplayName(child)) {\n case \"Modal.Header\":\n slottedHeader.push(child);\n break;\n case \"Modal.Body\":\n slottedBody.push(child);\n break;\n case \"Modal.Footer\":\n slottedFooter.push(child);\n break;\n default:\n unslottedChildren.push(child);\n }\n });\n\n const headerContent =\n slottedHeader.length > 0 ? (\n slottedHeader\n ) : (\n (title || close) && (\n <div className={cn(\"header\", css.header, resolved.header)}>\n {title && (\n <h4 {...asElementProps<\"h4\">(titleProps)} className={cn(\"title\", css.title, resolved.title)}>\n {title}\n </h4>\n )}\n {!title && close && <div className={cn(\"spacer\", css.spacer, resolved.spacer)} />}\n {close && (\n <button\n onClick={handleClose}\n onMouseDown={handleCloseMouseDown}\n onMouseEnter={handleCloseMouseEnter}\n onMouseUp={handleCloseMouseUp}\n onMouseLeave={handleCloseMouseLeave}\n onFocus={handleCloseFocus}\n onBlur={handleCloseBlur}\n className={cn(\"close\", css.close, resolved.close)}\n aria-label=\"Close modal\"\n type=\"button\"\n data-pressed={isClosePressed ? \"true\" : \"false\"}\n data-hovered={isCloseHovered ? \"true\" : \"false\"}\n data-focused={isCloseFocused ? \"true\" : \"false\"}\n data-focus-visible={isCloseFocusVisible ? \"true\" : \"false\"}\n >\n <X className={cn(\"close-icon\", css[\"close-icon\"], resolved.closeIcon)} />\n </button>\n )}\n </div>\n )\n );\n\n const bodyContent =\n slottedBody.length > 0 ? (\n slottedBody\n ) : (\n <div className={cn(\"content\", css.content, contentClassName, resolved.content)}>\n {unslottedChildren}\n </div>\n );\n\n return createPortal(\n <div\n className={cn(\n \"modal\",\n \"fixed inset-0 z-9999 flex items-center justify-center\",\n overlayClassName,\n resolved.overlay\n )}\n >\n {/* Backdrop overlay - click outside to dismiss */}\n <div\n className={cn(\"backdrop\", css.backdrop, resolved.backdrop)}\n onMouseDown={() => { if (isDismissable) state.close(); }}\n />\n\n {/* Modal content */}\n <div\n {...asElementProps<\"div\">(mergeProps(dialogProps, modalFocusProps))}\n aria-modal=\"true\"\n ref={modalRef}\n className={cn(\n \"panel\",\n css.panel,\n className,\n resolved.root\n )}\n onClick={(e) => e.stopPropagation()}\n tabIndex={-1}\n data-open={state.isOpen || undefined}\n data-size={size}\n data-focused={isModalFocused ? \"true\" : \"false\"}\n data-focus-visible={isModalFocusVisible ? \"true\" : \"false\"}\n >\n {/* Header */}\n {headerContent}\n\n {/* Body */}\n {bodyContent}\n\n {/* Footer */}\n {slottedFooter.length > 0 && slottedFooter}\n {!slottedFooter.length && footer && (\n <div className={cn(\"footer\", css.footer, resolved.footer)}>\n {footer}\n </div>\n )}\n </div>\n </div>,\n document.body\n );\n }\n);\n\nModalBase.displayName = \"Modal\";\n\n/**\n * ModalHeader component for use with compound Modal pattern\n */\nconst ModalHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"header\", css.header, className)} {...props}>\n {children}\n </div>\n));\n\nModalHeader.displayName = \"Modal.Header\";\n\n/**\n * ModalBody component for use with compound Modal pattern\n */\nconst ModalBody = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"content\", css.content, className)} {...props}>\n {children}\n </div>\n));\n\nModalBody.displayName = \"Modal.Body\";\n\n/**\n * ModalFooter component for use with compound Modal pattern\n */\nconst ModalFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"footer\", css.footer, className)} {...props}>\n {children}\n </div>\n));\n\nModalFooter.displayName = \"Modal.Footer\";\n\nconst Modal = Object.assign(ModalBase, {\n Header: ModalHeader,\n Body: ModalBody,\n Footer: ModalFooter,\n});\n\nexport { Modal, ModalHeader, ModalBody, ModalFooter };\n",
5003
+ "tsx": "\"use client\"\n\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useDialog } from \"react-aria\";\nimport { useFocusRing } from \"@react-aria/focus\";\nimport { mergeProps } from \"@react-aria/utils\";\nimport { useOverlayTriggerState } from \"react-stately\";\nimport { cn, type StyleValue } from \"./utils\";\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\";\nimport { asElementProps } from \"@/lib/react-aria\";\nimport { X } from \"lucide-react\";\nimport { useScrollLock } from \"../../hooks/useScrollLock\";\nimport css from \"./Modal.module.css\";\n\nconst useModalKeyboard = (\n ref: React.RefObject<HTMLDivElement | null>,\n isOpen: boolean,\n isDismissable: boolean,\n isKeyboardDismissDisabled: boolean,\n onClose: () => void\n) => {\n const onCloseRef = React.useRef(onClose);\n onCloseRef.current = onClose;\n\n React.useEffect(() => {\n if (!isOpen || !ref.current) return;\n\n ref.current.focus();\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && isDismissable && !isKeyboardDismissDisabled) {\n e.preventDefault();\n onCloseRef.current();\n }\n };\n\n ref.current.addEventListener(\"keydown\", handleKeyDown);\n return () => ref.current?.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isDismissable, isKeyboardDismissDisabled]);\n};\n\nexport interface ModalStyleSlots {\n root?: StyleValue;\n overlay?: StyleValue;\n backdrop?: StyleValue;\n header?: StyleValue;\n title?: StyleValue;\n spacer?: StyleValue;\n close?: StyleValue;\n closeIcon?: StyleValue;\n content?: StyleValue;\n footer?: StyleValue;\n}\n\nexport type ModalStylesProp = StylesProp<ModalStyleSlots>;\n\nconst resolveModalBaseStyles = createStylesResolver([\n 'root', 'overlay', 'backdrop', 'header', 'title', 'spacer', 'close', 'closeIcon', 'content', 'footer'\n] as const);\n\nfunction resolveModalStyles(styles: ModalStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveModalBaseStyles(styles);\n const { root, overlay, backdrop, header, title, spacer, close, closeIcon, content, footer } = styles;\n return resolveModalBaseStyles({ root, overlay, backdrop, header, title, spacer, close, closeIcon, content, footer });\n}\n\nexport interface ModalProps {\n /** Whether the modal is open */\n isOpen?: boolean;\n /** Callback when the open state changes */\n onOpenChange?: (isOpen: boolean) => void;\n /** Optional title rendered in the modal header bar */\n title?: React.ReactNode;\n /** Modal body content */\n children: React.ReactNode;\n /** Optional footer content rendered below the body */\n footer?: React.ReactNode;\n /** Whether to show the X close button in the header */\n close?: boolean;\n /** Controls modal width: \"fit\" adapts to content, \"auto\" uses default width */\n size?: \"fit\" | \"auto\";\n /** Whether clicking the backdrop dismisses the modal */\n isDismissable?: boolean;\n /** Prevents the Escape key from dismissing the modal */\n isKeyboardDismissDisabled?: boolean;\n /** Additional class for the modal panel */\n className?: string;\n /** Additional class for the inner content area */\n contentClassName?: string;\n /** Additional class for the backdrop overlay */\n overlayClassName?: string;\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: ModalStylesProp;\n}\n\nfunction getModalChildDisplayName(child: React.ReactNode) {\n if (!React.isValidElement(child)) return null;\n const type = child.type as { displayName?: string };\n return type.displayName ?? null;\n}\n\n\n/**\n * Modal component that displays content in a centered dialog with a backdrop overlay.\n * Built with React Aria for full accessibility support including focus management,\n * keyboard handling, and screen reader announcements.\n */\nconst ModalBase = React.forwardRef<HTMLDivElement, ModalProps>(\n (\n {\n isOpen: controlledIsOpen,\n onOpenChange,\n title,\n children,\n footer,\n close = true,\n size = \"auto\",\n isDismissable = true,\n isKeyboardDismissDisabled = false,\n className,\n contentClassName,\n overlayClassName,\n styles,\n },\n ref\n ) => {\n const modalRef = React.useRef<HTMLDivElement>(null);\n const [panelElement, setPanelElement] = React.useState<HTMLDivElement | null>(null);\n const setPanelRef = React.useCallback((el: HTMLDivElement | null) => {\n modalRef.current = el;\n setPanelElement(el);\n }, []);\n const [mounted, setMounted] = React.useState(false);\n const [isClosePressed, setIsClosePressed] = React.useState(false);\n const [isCloseHovered, setIsCloseHovered] = React.useState(false);\n const [isCloseFocused, setIsCloseFocused] = React.useState(false);\n const [isCloseFocusVisible, setIsCloseFocusVisible] = React.useState(false);\n\n const resolved = resolveModalStyles(styles);\n\n // Use uncontrolled state management via useOverlayTriggerState\n const state = useOverlayTriggerState({\n isOpen: controlledIsOpen,\n onOpenChange: onOpenChange,\n });\n\n // Handle mount to prevent hydration issues\n React.useEffect(() => {\n setMounted(true);\n }, []);\n\n // Use forwardRef callback to expose modalRef\n React.useImperativeHandle(ref, () => modalRef.current as HTMLDivElement);\n\n // Handle keyboard events and auto-focus\n useModalKeyboard(\n modalRef,\n state.isOpen,\n isDismissable,\n isKeyboardDismissDisabled,\n () => state.close()\n );\n\n // useDialog hook provides accessibility attributes and title handling\n const { dialogProps, titleProps } = useDialog({}, modalRef);\n const { focusProps: modalFocusProps, isFocused: isModalFocused, isFocusVisible: isModalFocusVisible } = useFocusRing();\n\n const handleClose = () => state.close();\n\n useScrollLock(state.isOpen, panelElement);\n\n if (!mounted || !state.isOpen) return null;\n\n const handleCloseMouseDown = () => setIsClosePressed(true);\n const handleCloseMouseUp = () => setIsClosePressed(false);\n const handleCloseMouseLeave = () => {\n setIsClosePressed(false);\n setIsCloseHovered(false);\n };\n const handleCloseMouseEnter = () => setIsCloseHovered(true);\n const handleCloseFocus = (event: React.FocusEvent<HTMLButtonElement>) => {\n setIsCloseFocused(true);\n setIsCloseFocusVisible(event.currentTarget.matches(\":focus-visible\"));\n };\n const handleCloseBlur = () => {\n setIsCloseFocused(false);\n setIsCloseFocusVisible(false);\n };\n\n const childArray = React.Children.toArray(children);\n const slottedHeader: React.ReactNode[] = [];\n const slottedBody: React.ReactNode[] = [];\n const slottedFooter: React.ReactNode[] = [];\n const unslottedChildren: React.ReactNode[] = [];\n\n childArray.forEach((child) => {\n switch (getModalChildDisplayName(child)) {\n case \"Modal.Header\":\n slottedHeader.push(child);\n break;\n case \"Modal.Body\":\n slottedBody.push(child);\n break;\n case \"Modal.Footer\":\n slottedFooter.push(child);\n break;\n default:\n unslottedChildren.push(child);\n }\n });\n\n const headerContent =\n slottedHeader.length > 0 ? (\n slottedHeader\n ) : (\n (title || close) && (\n <div className={cn(\"header\", css.header, resolved.header)}>\n {title && (\n <h4 {...asElementProps<\"h4\">(titleProps)} className={cn(\"title\", css.title, resolved.title)}>\n {title}\n </h4>\n )}\n {!title && close && <div className={cn(\"spacer\", css.spacer, resolved.spacer)} />}\n {close && (\n <button\n onClick={handleClose}\n onMouseDown={handleCloseMouseDown}\n onMouseEnter={handleCloseMouseEnter}\n onMouseUp={handleCloseMouseUp}\n onMouseLeave={handleCloseMouseLeave}\n onFocus={handleCloseFocus}\n onBlur={handleCloseBlur}\n className={cn(\"close\", css.close, resolved.close)}\n aria-label=\"Close modal\"\n type=\"button\"\n data-pressed={isClosePressed ? \"true\" : \"false\"}\n data-hovered={isCloseHovered ? \"true\" : \"false\"}\n data-focused={isCloseFocused ? \"true\" : \"false\"}\n data-focus-visible={isCloseFocusVisible ? \"true\" : \"false\"}\n >\n <X className={cn(\"close-icon\", css[\"close-icon\"], resolved.closeIcon)} />\n </button>\n )}\n </div>\n )\n );\n\n const bodyContent =\n slottedBody.length > 0 ? (\n slottedBody\n ) : (\n <div className={cn(\"content\", css.content, contentClassName, resolved.content)}>\n {unslottedChildren}\n </div>\n );\n\n return createPortal(\n <div\n className={cn(\n \"modal\",\n \"fixed inset-0 z-9999 flex items-center justify-center\",\n overlayClassName,\n resolved.overlay\n )}\n >\n {/* Backdrop overlay - click outside to dismiss */}\n <div\n className={cn(\"backdrop\", css.backdrop, resolved.backdrop)}\n onMouseDown={() => { if (isDismissable) state.close(); }}\n />\n\n {/* Modal content */}\n <div\n {...asElementProps<\"div\">(mergeProps(dialogProps, modalFocusProps))}\n aria-modal=\"true\"\n ref={setPanelRef}\n className={cn(\n \"panel\",\n css.panel,\n className,\n resolved.root\n )}\n onClick={(e) => e.stopPropagation()}\n tabIndex={-1}\n data-open={state.isOpen || undefined}\n data-size={size}\n data-focused={isModalFocused ? \"true\" : \"false\"}\n data-focus-visible={isModalFocusVisible ? \"true\" : \"false\"}\n >\n {/* Header */}\n {headerContent}\n\n {/* Body */}\n {bodyContent}\n\n {/* Footer */}\n {slottedFooter.length > 0 && slottedFooter}\n {!slottedFooter.length && footer && (\n <div className={cn(\"footer\", css.footer, resolved.footer)}>\n {footer}\n </div>\n )}\n </div>\n </div>,\n document.body\n );\n }\n);\n\nModalBase.displayName = \"Modal\";\n\n/**\n * ModalHeader component for use with compound Modal pattern\n */\nconst ModalHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"header\", css.header, className)} {...props}>\n {children}\n </div>\n));\n\nModalHeader.displayName = \"Modal.Header\";\n\n/**\n * ModalBody component for use with compound Modal pattern\n */\nconst ModalBody = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"content\", css.content, className)} {...props}>\n {children}\n </div>\n));\n\nModalBody.displayName = \"Modal.Body\";\n\n/**\n * ModalFooter component for use with compound Modal pattern\n */\nconst ModalFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & { children?: React.ReactNode }\n>(({ children, className, ...props }, ref) => (\n <div ref={ref} className={cn(\"footer\", css.footer, className)} {...props}>\n {children}\n </div>\n));\n\nModalFooter.displayName = \"Modal.Footer\";\n\nconst Modal = Object.assign(ModalBase, {\n Header: ModalHeader,\n Body: ModalBody,\n Footer: ModalFooter,\n});\n\nexport { Modal, ModalHeader, ModalBody, ModalFooter };\n",
5005
5004
  "css": "@reference \"tailwindcss\";\n\n@layer components {\n .backdrop {\n @apply absolute inset-0 cursor-pointer;\n background-color: var(--backdrop-background);\n backdrop-filter: blur(4px);\n }\n\n .panel {\n @apply relative flex w-full flex-col overflow-hidden;\n z-index: 1;\n max-height: 90vh;\n margin: 1rem;\n color: var(--foreground);\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--radius-sm, 0.375rem);\n pointer-events: auto;\n overflow: hidden;\n\n &[data-focus-visible=\"true\"] {\n outline: none;\n box-shadow: 0 0 0 1.5px var(--focus-visible);\n }\n }\n\n .header {\n @apply flex shrink-0 items-center justify-between gap-2 px-6 py-4;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .title {\n @apply m-0;\n font-size: 1.125rem;\n font-weight: var(--font-weight-semibold);\n color: var(--title-foreground, var(--foreground));\n }\n\n .spacer {\n flex: 1;\n }\n\n .close {\n @apply ml-auto flex items-center justify-center cursor-pointer;\n background: none;\n border: none;\n color: var(--foreground);\n transition:\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n transform var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-hovered=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n &[data-pressed=\"true\"] {\n transform: scale(0.92);\n }\n\n &[data-focus-visible=\"true\"] {\n outline: 2px solid var(--focus-visible);\n outline-offset: 2px;\n border-radius: var(--radius-xs, 0.25rem);\n }\n }\n\n .close-icon {\n @apply h-5 w-5;\n }\n\n .content {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n color: var(--foreground);\n }\n\n .content::-webkit-scrollbar {\n width: 6px;\n }\n\n .content::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .content::-webkit-scrollbar-thumb {\n background-color: var(--background);\n border-radius: 3px;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .content::-webkit-scrollbar-thumb:hover {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n\n .footer {\n @apply flex shrink-0 items-center justify-between gap-4 px-6 py-4;\n background-color: var(--footer-background, var(--background));\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n /* Size variants */\n .panel[data-size=\"fit\"] {\n width: fit-content;\n }\n\n .panel[data-size=\"auto\"] {\n max-width: min(90vw, 28rem);\n }\n\n /* Media queries for smaller screens */\n @media (max-width: 640px) {\n .panel {\n margin: 1rem;\n }\n\n .content {\n max-height: calc(100vh - 10rem);\n }\n }\n}\n",
5006
5005
  "cssTypes": "declare const styles: {\n backdrop: string;\n panel: string;\n header: string;\n title: string;\n spacer: string;\n close: string;\n \"close-icon\": string;\n content: string;\n footer: string;\n};\n\nexport default styles;\n"
5007
5006
  },
@@ -5041,8 +5040,8 @@ export const generatedSourceCode = {
5041
5040
  "cssTypes": "export const root: string;\nexport const vertical: string;\nexport const horizontal: string;\nexport const content: string;\nexport const track: string;\nexport const thumb: string;\n\ndeclare const styles: {\n root: string;\n vertical: string;\n horizontal: string;\n content: string;\n track: string;\n thumb: string;\n};\n\nexport default styles;\n"
5042
5041
  },
5043
5042
  "select": {
5044
- "tsx": "import * as React from \"react\"\nimport { Key } from \"@react-types/shared\";\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { useButton } from \"@react-aria/button\";\n\nimport { cn, type StyleValue } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport styles from \"./Select.module.css\"\nimport { useListNavigation, handleListKeyDown, focusAdjacentTabStop, type ItemData } from \"./Select.shared\"\n\nexport type SelectItemData = ItemData\n\nexport type SelectTriggerMode = \"click\" | \"hover\"\nexport type SelectMode = \"single\" | \"multiple\"\n\nexport interface SelectStyleSlots {\n root?: StyleValue;\n}\n\nexport type SelectStylesProp = StylesProp<SelectStyleSlots>;\n\nexport interface SelectContextValue {\n isOpen: boolean\n setIsOpen: React.Dispatch<React.SetStateAction<boolean>>\n contentPlacement: \"top\" | \"bottom\"\n setContentPlacement: React.Dispatch<React.SetStateAction<\"top\" | \"bottom\">>\n triggerType: \"button\" | \"input\"\n mode: SelectMode\n selectedKey: Key | null\n selectedKeys?: Set<Key>\n selectedTextValue: string\n onSelect: (key: Key) => void\n onToggle?: (key: Key) => void\n triggerRef: React.MutableRefObject<HTMLElement | null>\n wrapperRef: React.MutableRefObject<HTMLElement | null>\n contentRef: React.MutableRefObject<HTMLElement | null>\n triggerProps: any\n isFocused: boolean\n isFocusVisible: boolean\n isPressed: boolean\n isHovered: boolean\n isDisabled: boolean\n items: SelectItemData[]\n registerItem: (key: Key, textValue: string, isDisabled?: boolean, onSelect?: () => void, isSubmenuTrigger?: boolean) => void\n unregisterItem: (key: Key) => void\n searchValue: string\n setSearchValue: React.Dispatch<React.SetStateAction<string>>\n filteredItems: SelectItemData[]\n visibleKeys: Set<Key>\n focusedKey: Key | null\n setFocusedKey: React.Dispatch<React.SetStateAction<Key | null>>\n navigateToNextItem: () => void\n navigateToPrevItem: () => void\n selectFocusedItem: () => void\n isFocusedItemSubmenu: () => boolean\n maxItems: number\n triggerMode: SelectTriggerMode\n handleHoverIntent: (isHovering: boolean) => void\n mouseMoveDetectedRef: React.MutableRefObject<boolean>\n keyboardScrollIntentRef: React.MutableRefObject<boolean>\n markKeyboardNavigation: () => void\n moveFocusFromTrigger: (direction: 1 | -1) => boolean\n filter?: (item: any) => boolean\n contentId: string\n hasExternalValue: boolean\n restoreFocus: (target?: \"auto\" | \"trigger\" | \"row\") => void\n}\n\nconst SelectContext = React.createContext<SelectContextValue | null>(null)\n\nexport function useSelectContext() {\n const context = React.useContext(SelectContext)\n if (!context) {\n throw new Error(\"Select component must be used within Select root\")\n }\n return context\n}\n\nexport interface SelectProps<T = any> extends React.HTMLAttributes<HTMLDivElement> {\n /** Selection mode: \"single\" for one item, \"multiple\" for multi-item selection */\n mode?: SelectMode\n /** External items array — used when items are provided as data rather than JSX */\n items?: Array<T>\n /** Controlled selected key for single-select mode */\n selectedKey?: Key | null\n /** Default selected key for uncontrolled single-select */\n defaultSelectedKey?: Key | null\n /** Controlled selected keys for multi-select mode */\n selectedKeys?: Key[]\n /** Default selected keys for uncontrolled multi-select */\n defaultSelectedKeys?: Key[]\n /** Default display text shown in the trigger when nothing is selected */\n defaultValue?: string\n /** Display text for the currently selected value — used for SSR/SSG to avoid\n * flash of placeholder before items register. Provide alongside selectedKey or\n * defaultSelectedKey so the correct label renders on the first pass. */\n valueLabel?: string\n /** Called when selection changes; receives a single key (single) or key array (multiple) */\n onSelectionChange?: (value: any) => void\n /** Disables the entire select and prevents interaction */\n isDisabled?: boolean\n /** Focuses the trigger automatically on mount */\n autoFocus?: boolean\n /** Maximum number of items visible before the dropdown scrolls */\n maxItems?: number\n /** Additional CSS class for the root wrapper */\n className?: string\n /** How the dropdown opens: \"click\" (default) or \"hover\" */\n trigger?: SelectTriggerMode\n /** Custom filter predicate applied to the items array */\n filter?: (item: T) => boolean\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: SelectStylesProp;\n}\n\nconst resolveSelectBaseStyles = createStylesResolver(['root'] as const);\n\nfunction resolveSelectStyles(styles: SelectStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveSelectBaseStyles(styles)\n const { root } = styles\n return resolveSelectBaseStyles({ root })\n}\n\nconst Select = React.forwardRef<HTMLDivElement, SelectProps<any>>(\n (\n {\n mode = \"single\",\n items: propItems = [],\n selectedKey: controlledSelectedKey,\n defaultSelectedKey,\n selectedKeys: controlledSelectedKeys,\n defaultSelectedKeys = [],\n defaultValue,\n valueLabel,\n onSelectionChange,\n isDisabled = false,\n autoFocus = false,\n maxItems = 6,\n children,\n className,\n trigger: triggerMode = \"click\",\n filter,\n styles: stylesProp,\n ...domProps\n },\n ref\n ) => {\n const triggerRef = React.useRef<HTMLElement>(null)\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const wrapperRef = React.useRef<HTMLDivElement>(null)\n const contentRef = React.useRef<HTMLElement>(null)\n const mouseMoveDetectedRef = React.useRef(true)\n const itemExtrasRef = React.useRef<Map<Key, { onSelect?: () => void; isSubmenuTrigger?: boolean }>>(new Map())\n const [isOpen, setIsOpen] = React.useState(false)\n const [contentPlacement, setContentPlacement] = React.useState<\"top\" | \"bottom\">(\"bottom\")\n const contentId = React.useId()\n const hoverTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n const keyboardScrollIntentRef = React.useRef(false)\n\n const handleHoverIntent = React.useCallback((isHovering: boolean) => {\n if (triggerMode !== \"hover\" || isDisabled) return\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current)\n hoverTimeoutRef.current = null\n }\n\n if (isHovering) {\n setIsOpen(true)\n } else {\n hoverTimeoutRef.current = setTimeout(() => {\n setIsOpen(false)\n }, 100)\n }\n }, [triggerMode, isDisabled])\n\n React.useEffect(() => {\n if (!isOpen || triggerMode !== \"hover\" || isDisabled) return\n\n const handleMouseMove = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n const isOver = wrapperRef.current?.contains(target) ||\n contentRef.current?.contains(target)\n\n if (!isOver) {\n handleHoverIntent(false)\n } else {\n handleHoverIntent(true)\n }\n }\n\n window.addEventListener(\"mousemove\", handleMouseMove)\n return () => window.removeEventListener(\"mousemove\", handleMouseMove)\n }, [isOpen, triggerMode, isDisabled, handleHoverIntent])\n\n React.useEffect(() => {\n return () => {\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current)\n }\n }\n }, [])\n\n const [uncontrolledSelectedKey, setUncontrolledSelectedKey] = React.useState<Key | null>(\n defaultSelectedKey ?? null\n )\n const [uncontrolledSelectedKeys, setUncontrolledSelectedKeys] = React.useState<Set<Key>>(\n new Set(defaultSelectedKeys)\n )\n const [selectedTextValue, setSelectedTextValue] = React.useState(valueLabel ?? defaultValue ?? \"\")\n const selectedKey = controlledSelectedKey !== undefined ? controlledSelectedKey : uncontrolledSelectedKey\n const selectedKeys = controlledSelectedKeys !== undefined ? new Set(controlledSelectedKeys) : uncontrolledSelectedKeys\n\n const nav = useListNavigation({\n isOpen,\n externalItems: propItems.length > 0 ? propItems : undefined,\n filter: filter ? (item: any) => filter({ ...item, label: item.textValue } as any) : undefined\n })\n\n const registerItem = React.useCallback((key: Key, textValue: string, isDisabled?: boolean, onSelect?: () => void, isSubmenuTrigger?: boolean) => {\n nav.registerItem(key, textValue, isDisabled)\n itemExtrasRef.current.set(key, { onSelect, isSubmenuTrigger })\n }, [nav.registerItem])\n\n const unregisterItem = React.useCallback((key: Key) => {\n nav.unregisterItem(key)\n itemExtrasRef.current.delete(key)\n }, [nav.unregisterItem])\n\n const isFocusedItemSubmenu = React.useCallback(() => {\n if (nav.focusedKey === null) return false\n return itemExtrasRef.current.get(nav.focusedKey)?.isSubmenuTrigger ?? false\n }, [nav.focusedKey])\n\n const markKeyboardNavigation = React.useCallback(() => {\n mouseMoveDetectedRef.current = false\n keyboardScrollIntentRef.current = true\n }, [])\n\n const moveFocusFromTrigger = React.useCallback((direction: 1 | -1) => {\n const triggerElement = triggerRef.current\n if (!triggerElement) return false\n return focusAdjacentTabStop(triggerElement, direction, wrapperRef.current)\n }, [])\n\n const restoreFocus = React.useCallback((target: \"auto\" | \"trigger\" | \"row\" = \"auto\") => {\n const triggerElement = triggerRef.current\n if (!triggerElement) return\n\n const ownerRow = triggerElement.closest<HTMLElement>('[data-list-focus-owner=\"true\"]')\n const focusTarget = target === \"row\"\n ? ownerRow\n : target === \"trigger\"\n ? triggerElement\n : ownerRow ?? triggerElement\n\n focusTarget?.focus({ preventScroll: true })\n }, [])\n\n const onSelect = React.useCallback((key: Key) => {\n const item = nav.items.find(i => i.key === key)\n if (item) {\n setSelectedTextValue(item.textValue)\n }\n if (controlledSelectedKey === undefined) {\n setUncontrolledSelectedKey(key)\n }\n onSelectionChange?.(key)\n setIsOpen(false)\n nav.setSearchValue(\"\")\n restoreFocus()\n }, [controlledSelectedKey, onSelectionChange, nav.items, restoreFocus])\n\n const onToggle = React.useCallback((key: Key) => {\n const newKeys = new Set(selectedKeys)\n if (newKeys.has(key)) {\n newKeys.delete(key)\n } else {\n newKeys.add(key)\n }\n if (controlledSelectedKeys === undefined) {\n setUncontrolledSelectedKeys(newKeys)\n }\n onSelectionChange?.(Array.from(newKeys))\n }, [selectedKeys, controlledSelectedKeys, onSelectionChange])\n\n const selectFocusedItem = React.useCallback(() => {\n if (nav.focusedKey !== null) {\n const item = nav.enabledFilteredItems.find(item => item.key === nav.focusedKey)\n if (item && !item.isDisabled) {\n const extras = itemExtrasRef.current.get(nav.focusedKey)\n if (extras?.onSelect) {\n extras.onSelect()\n } else if (mode === \"multiple\") {\n onToggle(nav.focusedKey)\n } else {\n onSelect(nav.focusedKey)\n }\n }\n }\n }, [nav.focusedKey, nav.enabledFilteredItems, onSelect, onToggle, mode])\n\n React.useEffect(() => {\n if (isOpen) {\n // Only initialize focusedKey if it's not already valid\n if (nav.focusedKey !== null && nav.visibleKeys.has(nav.focusedKey)) {\n const item = nav.filteredItems.find(item => item.key === nav.focusedKey)\n if (item && !item.isDisabled) {\n return // Keep current keyboard focus, don't reset it\n }\n }\n\n const focusKey = mode === \"multiple\" && selectedKeys.size > 0\n ? Array.from(selectedKeys)[0]\n : selectedKey\n\n if (focusKey !== null && nav.visibleKeys.has(focusKey)) {\n const item = nav.filteredItems.find(item => item.key === focusKey)\n if (item && !item.isDisabled) {\n nav.setFocusedKey(focusKey)\n return\n }\n }\n if (nav.enabledFilteredItems.length > 0) {\n nav.setFocusedKey(nav.enabledFilteredItems[0].key)\n } else {\n nav.setFocusedKey(null)\n }\n }\n }, [isOpen, selectedKey, selectedKeys, nav.visibleKeys, nav.enabledFilteredItems, nav.filteredItems, mode, nav.focusedKey])\n\n const { buttonProps, isPressed } = useButton({\n isDisabled,\n onPress: (e) => {\n if (isDisabled) return\n // Keyboard interactions are handled by onKeyDown to prevent conflicts\n if (e.pointerType !== 'keyboard') {\n setIsOpen(prev => !prev)\n }\n },\n }, triggerRef)\n const { focusProps, isFocused, isFocusVisible } = useFocusRing()\n const { hoverProps, isHovered } = useHover({\n isDisabled,\n onHoverStart: () => handleHoverIntent(true),\n onHoverEnd: () => handleHoverIntent(false),\n })\n\n const triggerProps = mergeProps(buttonProps, focusProps, hoverProps, {\n 'aria-haspopup': 'listbox' as const,\n 'aria-expanded': isOpen,\n 'aria-controls': isOpen ? contentId : undefined,\n 'aria-disabled': isDisabled || undefined,\n onKeyDown: (e: React.KeyboardEvent) => {\n if (!isOpen) {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || (e.key === ' ' && !isDisabled)) {\n e.preventDefault()\n setIsOpen(true)\n }\n return\n }\n\n if (e.key === 'Tab') {\n e.preventDefault()\n const direction = e.shiftKey ? -1 : 1\n setIsOpen(false)\n nav.setSearchValue(\"\")\n moveFocusFromTrigger(direction as 1 | -1)\n return\n }\n\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {\n markKeyboardNavigation()\n }\n\n handleListKeyDown(e, {\n navigateNext: nav.navigateToNextItem,\n navigatePrev: nav.navigateToPrevItem,\n confirm: selectFocusedItem,\n close: () => {\n setIsOpen(false)\n nav.setSearchValue(\"\")\n restoreFocus()\n },\n filteredItems: nav.filteredItems,\n setFocusedKey: nav.setFocusedKey,\n })\n },\n })\n\n React.useEffect(() => {\n if (autoFocus && triggerRef.current) {\n triggerRef.current.focus({ preventScroll: true })\n }\n }, [autoFocus])\n\n React.useEffect(() => {\n if (mode === \"single\") {\n if (selectedKey === null) {\n setSelectedTextValue(\"\")\n } else {\n const selectedItem = nav.items.find(item => item.key === selectedKey)\n if (selectedItem) {\n setSelectedTextValue(selectedItem.textValue)\n } else if (valueLabel !== undefined) {\n setSelectedTextValue(valueLabel)\n } else if (defaultValue !== undefined && defaultValue !== null) {\n setSelectedTextValue(defaultValue)\n }\n }\n }\n }, [selectedKey, nav.items, mode, defaultValue, valueLabel])\n\n const childrenArray = React.Children.toArray(children)\n const trigger = childrenArray.find(child => React.isValidElement(child) && (\n (child.type as any)?.displayName === 'SelectTrigger' ||\n (child.type as any)?.displayName === 'SearchableTrigger'\n ))\n const contentItems = childrenArray.filter(child => React.isValidElement(child) && ((child.type as any)?.displayName === 'SelectContent' || (child.type as any)?.displayName === 'SearchableContent'))\n const otherContent = childrenArray.filter(child => !React.isValidElement(child) || (\n (child.type as any)?.displayName !== 'SelectTrigger' &&\n (child.type as any)?.displayName !== 'SearchableTrigger' &&\n (child.type as any)?.displayName !== 'SelectContent' &&\n (child.type as any)?.displayName !== 'SearchableContent'\n ))\n const hasExternalValue = otherContent.some(child => (\n React.isValidElement(child) && (child.type as any)?.displayName === 'SelectValue'\n ))\n const triggerType = React.isValidElement(trigger) && (trigger.type as any)?.displayName === 'SearchableTrigger'\n ? 'input'\n : 'button'\n\n const resolvedStyles = resolveSelectStyles(stylesProp);\n const mergedRootRef = useMergeRefs<HTMLDivElement>(scopeRef, wrapperRef, ref)\n const { indicatorProps } = useFocus({\n scopeRef,\n containerRef: wrapperRef,\n surfaceSelector: '[data-select-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"self\",\n dependencies: [mode],\n });\n\n return (\n <SelectContext.Provider\n value={{\n isOpen,\n setIsOpen,\n contentPlacement,\n setContentPlacement,\n triggerType,\n mode,\n selectedKey,\n selectedKeys: mode === \"multiple\" ? selectedKeys : undefined,\n selectedTextValue,\n onSelect,\n onToggle: mode === \"multiple\" ? onToggle : undefined,\n triggerRef,\n wrapperRef,\n contentRef,\n triggerProps,\n isFocused,\n isFocusVisible,\n isPressed,\n isHovered,\n isDisabled,\n items: nav.items,\n registerItem,\n unregisterItem,\n searchValue: nav.searchValue,\n setSearchValue: nav.setSearchValue,\n filteredItems: nav.filteredItems,\n visibleKeys: nav.visibleKeys,\n focusedKey: nav.focusedKey,\n setFocusedKey: nav.setFocusedKey,\n navigateToNextItem: nav.navigateToNextItem,\n navigateToPrevItem: nav.navigateToPrevItem,\n selectFocusedItem,\n isFocusedItemSubmenu,\n maxItems,\n triggerMode,\n handleHoverIntent,\n mouseMoveDetectedRef,\n keyboardScrollIntentRef,\n markKeyboardNavigation,\n moveFocusFromTrigger,\n filter,\n contentId,\n hasExternalValue,\n restoreFocus,\n }}\n >\n <div\n ref={mergedRootRef}\n className={cn('select', styles.select, className, resolvedStyles.root)}\n data-mode={mode}\n data-select-focus-surface=\"true\"\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n {...domProps}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n {otherContent}\n {trigger}\n {contentItems}\n </div>\n </SelectContext.Provider>\n )\n }\n)\nSelect.displayName = \"Select\"\n\nexport { Select, SelectContext }\n",
5045
- "css": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .select {\n --disabled-opacity: 0.5;\n --trigger-padding-inline: calc(var(--spacing) * 1.60);\n --trigger-padding-block: calc(var(--spacing) * 1.30);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n font-size: var(--foreground-size);\n height: fit-content;\n align-self: center;\n\n @apply p-0 gap-0 w-full flex-row items-center;\n position: relative;\n overflow: visible;\n\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n\n @apply select-none cursor-pointer;\n\n &[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n &[data-pressed=\"true\"]:not([data-disabled]) {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n }\n\n &[data-open=\"true\"] {\n background-color: var(--background-hover);\n }\n\n &:global(.group) {\n height: 100%;\n align-self: stretch;\n }\n }\n\n .trigger {\n @apply flex items-stretch flex-1 gap-0 w-full h-full min-h-0;\n\n background: transparent;\n\n @apply border-none cursor-pointer select-none;\n\n @media (hover: hover) {\n &:not([data-disabled]):hover .icon-section,\n &:not([data-disabled]):hover .value-section:not(:empty) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover);\n }\n }\n\n &[data-focus-visible=\"true\"] {\n @apply outline-none;\n }\n }\n\n .trigger-compact {\n @apply flex-none w-auto;\n }\n\n .select button.trigger { @apply p-0; }\n\n .value-section {\n @apply flex items-center flex-1 min-w-0 gap-0.5;\n\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n font-size: var(--foreground-size);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &:only-child {\n border-radius: var(--background-inner-radius);\n justify-content: center;\n }\n &:empty {\n flex: 0;\n padding: 0;\n min-width: auto;\n }\n }\n\n .icon-section {\n @apply flex items-center justify-center shrink-0;\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n }\n\n .icon {\n @apply flex items-center justify-center w-4 h-4 opacity-70;\n }\n\n .select .trigger[data-open=\"true\"] .icon {\n transform: rotate(180deg);\n }\n\n .value {\n @apply flex items-center flex-1 min-w-0 gap-2 bg-transparent border-none;\n cursor: inherit;\n }\n\n .value-icon {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n color: var(--foreground);\n }\n\n .value-text {\n font-weight: var(--font-weight-medium);\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .content,\n .sub-content {\n --item-padding-inline: calc(var(--spacing) * 1.5);\n --item-padding-block: var(--spacing);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n overflow: hidden;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n }\n\n .content-root,\n .sub-content-root {\n position: absolute;\n }\n\n .content {\n &[data-state=\"open\"][data-placement=\"bottom\"] { animation: slide-in-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"open\"][data-placement=\"top\"] { animation: slide-in-from-bottom 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"bottom\"] { animation: slide-out-from-top 0.15s var(--ease-snappy-pop); }\n &[data-state=\"closed\"][data-placement=\"top\"] { animation: slide-out-from-bottom 0.15s var(--ease-snappy-pop); }\n }\n\n .list {\n @apply space-y-1;\n }\n\n .item,\n .sub-trigger {\n @apply flex items-center gap-2 outline-none cursor-default select-none;\n background-color: var(--background);\n border-radius: var(--background-inner-radius);\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n transition:\n background-color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out)),\n color var(--hover-transition-duration, var(--hover-transition-leave-duration, 300ms)) var(--hover-transition-timing-function, var(--ease-snappy-pop, ease-out));\n\n &[data-disabled] {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n }\n\n .item {\n --item-padding-inline: var(--trigger-padding-inline);\n --item-padding-block: calc(var(--trigger-padding-block) * 1.15);\n\n padding: var(--item-padding-block) var(--item-padding-inline);\n\n &[data-selected=\"true\"] {\n color: var(--foreground);\n }\n\n &[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .item-content {\n @apply flex flex-col flex-1 min-w-0;\n }\n\n .item-text {\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground-muted);\n @apply min-w-0 whitespace-normal break-words;\n }\n\n .item-icon, .item-indicator {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n }\n\n .item-icon { color: var(--icon-foreground); }\n .item-indicator { color: var(--indicator-foreground); margin-left: auto; }\n\n .item-with-description { @apply items-start py-2; }\n .item-icon-with-description, .item-indicator-with-description { @apply mt-0.5; }\n\n .separator {\n @apply my-1 -mx-1 h-px;\n background-color: var(--background-border);\n }\n\n .placeholder {\n color: var(--foreground-muted);\n }\n\n .icon-prefix {\n @apply inline-flex items-center shrink-0;\n }\n\n .select[data-mode=\"multiple\"] .item { gap: 0.5rem; }\n\n .search-trigger {\n @apply flex items-stretch relative bg-transparent cursor-text overflow-hidden;\n border-radius: var(--background-inner-radius);\n transition: box-shadow 150ms var(--ease-snappy-pop), border-color 150ms var(--ease-snappy-pop);\n\n &:focus-within {\n @apply outline-none;\n z-index: 1;\n }\n }\n\n .search-trigger :global(.focus-indicator) {\n display: none;\n }\n\n .search-value-section {\n @apply p-0;\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .input {\n padding-right: calc(var(--trigger-padding-inline) * 2 + 1rem);\n @apply border-none rounded-none shadow-none bg-transparent;\n\n &[data-focused], &[data-focus-visible] {\n @apply border-none shadow-none;\n }\n }\n\n .search-content-input {\n @apply border-none rounded-none bg-transparent;\n }\n\n .search-icon-section {\n @apply absolute right-0 top-0 bottom-0 flex items-center justify-center bg-transparent pointer-events-none;\n padding-inline: var(--trigger-padding-inline);\n }\n\n\n .search-wrapper {\n @apply overflow-hidden;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .empty-state {\n @apply px-3 py-2;\n color: var(--foreground-muted);\n }\n\n .content[data-placement=\"top\"] .search-wrapper {\n border-radius: 0;\n border-bottom: none;\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .sub-trigger {\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n\n &[data-highlighted=\"true\"],\n &[data-open=\"true\"]:not([data-highlighted=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .sub-trigger-chevron {\n @apply shrink-0 ml-auto w-4 h-4 opacity-60;\n }\n\n .sub-content {\n min-width: 160px;\n max-width: 320px;\n }\n\n @keyframes slide-in-from-top { from { opacity: 0; translate: 0 -2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-in-from-bottom { from { opacity: 0; translate: 0 2px; } to { opacity: 1; translate: 0 0; } }\n @keyframes slide-out-from-top { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 -2px; } }\n @keyframes slide-out-from-bottom { from { opacity: 1; translate: 0 0; } to { opacity: 0; translate: 0 2px; } }\n}\n",
5043
+ "tsx": "import * as React from \"react\"\nimport { Key } from \"@react-types/shared\";\n\nimport { mergeProps, } from \"@react-aria/utils\";\nimport { useHover } from \"@react-aria/interactions\";\nimport { useFocusRing } from \"@react-aria/focus\"\nimport { useButton } from \"@react-aria/button\";\n\nimport { cn, type StyleValue } from \"./utils\"\nimport { type StylesProp, createStylesResolver } from \"@/lib/styles\"\nimport { useFocus } from \"@/hooks/useFocus\";\nimport { useMergeRefs } from \"@/hooks/useMergeRefs\";\nimport styles from \"./Select.module.css\"\nimport { useListNavigation, handleListKeyDown, focusAdjacentTabStop, type ItemData } from \"./Select.shared\"\nimport { registerSelectCloseCallback, unregisterSelectCloseCallback, closeOtherSelects, clearSelectRegistry } from \"./Select.registry\"\n\nexport type SelectItemData = ItemData\n\nexport type SelectTriggerMode = \"click\" | \"hover\"\nexport type SelectMode = \"single\" | \"multiple\"\n\nexport interface SelectStyleSlots {\n root?: StyleValue;\n}\n\nexport type SelectStylesProp = StylesProp<SelectStyleSlots>;\n\nexport interface SelectContextValue {\n isOpen: boolean\n setIsOpen: React.Dispatch<React.SetStateAction<boolean>>\n contentPlacement: \"top\" | \"bottom\"\n setContentPlacement: React.Dispatch<React.SetStateAction<\"top\" | \"bottom\">>\n triggerType: \"button\" | \"input\"\n mode: SelectMode\n selectedKey: Key | null\n selectedKeys?: Set<Key>\n selectedTextValue: string\n onSelect: (key: Key) => void\n onToggle?: (key: Key) => void\n triggerRef: React.MutableRefObject<HTMLElement | null>\n wrapperRef: React.MutableRefObject<HTMLElement | null>\n contentRef: React.MutableRefObject<HTMLElement | null>\n triggerProps: any\n isFocused: boolean\n isFocusVisible: boolean\n isPressed: boolean\n isHovered: boolean\n isDisabled: boolean\n items: SelectItemData[]\n registerItem: (key: Key, textValue: string, isDisabled?: boolean, onSelect?: () => void, isSubmenuTrigger?: boolean) => void\n unregisterItem: (key: Key) => void\n searchValue: string\n setSearchValue: React.Dispatch<React.SetStateAction<string>>\n filteredItems: SelectItemData[]\n visibleKeys: Set<Key>\n focusedKey: Key | null\n setFocusedKey: React.Dispatch<React.SetStateAction<Key | null>>\n navigateToNextItem: () => void\n navigateToPrevItem: () => void\n selectFocusedItem: () => void\n isFocusedItemSubmenu: () => boolean\n maxItems: number\n triggerMode: SelectTriggerMode\n handleHoverIntent: (isHovering: boolean) => void\n mouseMoveDetectedRef: React.MutableRefObject<boolean>\n keyboardScrollIntentRef: React.MutableRefObject<boolean>\n markKeyboardNavigation: () => void\n moveFocusFromTrigger: (direction: 1 | -1) => boolean\n filter?: (item: any) => boolean\n contentId: string\n hasExternalValue: boolean\n restoreFocus: (target?: \"auto\" | \"trigger\" | \"row\") => void\n}\n\nconst SelectContext = React.createContext<SelectContextValue | null>(null)\n\nexport function useSelectContext() {\n const context = React.useContext(SelectContext)\n if (!context) {\n throw new Error(\"Select component must be used within Select root\")\n }\n return context\n}\n\nexport interface SelectProps<T = any> extends React.HTMLAttributes<HTMLDivElement> {\n /** Selection mode: \"single\" for one item, \"multiple\" for multi-item selection */\n mode?: SelectMode\n /** External items array — used when items are provided as data rather than JSX */\n items?: Array<T>\n /** Controlled selected key for single-select mode */\n selectedKey?: Key | null\n /** Default selected key for uncontrolled single-select */\n defaultSelectedKey?: Key | null\n /** Controlled selected keys for multi-select mode */\n selectedKeys?: Key[]\n /** Default selected keys for uncontrolled multi-select */\n defaultSelectedKeys?: Key[]\n /** Default display text shown in the trigger when nothing is selected */\n defaultValue?: string\n /** Display text for the currently selected value — used for SSR/SSG to avoid\n * flash of placeholder before items register. Provide alongside selectedKey or\n * defaultSelectedKey so the correct label renders on the first pass. */\n label?: string\n /** Called when selection changes; receives a single key (single) or key array (multiple) */\n onSelectionChange?: (value: any) => void\n /** Disables the entire select and prevents interaction */\n isDisabled?: boolean\n /** Focuses the trigger automatically on mount */\n autoFocus?: boolean\n /** Maximum number of items visible before the dropdown scrolls */\n maxItems?: number\n /** Additional CSS class for the root wrapper */\n className?: string\n /** How the dropdown opens: \"click\" (default) or \"hover\" */\n trigger?: SelectTriggerMode\n /** Custom filter predicate applied to the items array */\n filter?: (item: T) => boolean\n /** Classes applied to the root or named slots. Accepts a string, cn()-compatible array, slot object, or array of any of those. */\n styles?: SelectStylesProp;\n}\n\nconst resolveSelectBaseStyles = createStylesResolver(['root'] as const);\n\nfunction resolveSelectStyles(styles: SelectStylesProp | undefined) {\n if (!styles || typeof styles === \"string\" || Array.isArray(styles)) return resolveSelectBaseStyles(styles)\n const { root } = styles\n return resolveSelectBaseStyles({ root })\n}\n\nconst Select = React.forwardRef<HTMLDivElement, SelectProps<any>>(\n (\n {\n mode = \"single\",\n items: propItems = [],\n selectedKey: controlledSelectedKey,\n defaultSelectedKey,\n selectedKeys: controlledSelectedKeys,\n defaultSelectedKeys = [],\n defaultValue,\n label,\n onSelectionChange,\n isDisabled = false,\n autoFocus = false,\n maxItems = 6,\n children,\n className,\n trigger: triggerMode = \"click\",\n filter,\n styles: stylesProp,\n ...domProps\n },\n ref\n ) => {\n const triggerRef = React.useRef<HTMLElement>(null)\n const scopeRef = React.useRef<HTMLDivElement>(null)\n const wrapperRef = React.useRef<HTMLDivElement>(null)\n const contentRef = React.useRef<HTMLElement>(null)\n const mouseMoveDetectedRef = React.useRef(true)\n const itemExtrasRef = React.useRef<Map<Key, { onSelect?: () => void; isSubmenuTrigger?: boolean }>>(new Map())\n const [isOpen, setIsOpen] = React.useState(false)\n const [contentPlacement, setContentPlacement] = React.useState<\"top\" | \"bottom\">(\"bottom\")\n const contentId = React.useId()\n const selectId = React.useId()\n const hoverTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)\n const keyboardScrollIntentRef = React.useRef(false)\n\n const handleHoverIntent = React.useCallback((isHovering: boolean) => {\n if (triggerMode !== \"hover\" || isDisabled) return\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current)\n hoverTimeoutRef.current = null\n }\n\n if (isHovering) {\n setIsOpen(true)\n } else {\n hoverTimeoutRef.current = setTimeout(() => {\n setIsOpen(false)\n }, 100)\n }\n }, [triggerMode, isDisabled])\n\n React.useEffect(() => {\n if (!isOpen || triggerMode !== \"hover\" || isDisabled) return\n\n const handleMouseMove = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n const isOver = wrapperRef.current?.contains(target) ||\n contentRef.current?.contains(target)\n\n if (!isOver) {\n handleHoverIntent(false)\n } else {\n handleHoverIntent(true)\n }\n }\n\n window.addEventListener(\"mousemove\", handleMouseMove)\n return () => window.removeEventListener(\"mousemove\", handleMouseMove)\n }, [isOpen, triggerMode, isDisabled, handleHoverIntent])\n\n React.useEffect(() => {\n return () => {\n if (hoverTimeoutRef.current) {\n clearTimeout(hoverTimeoutRef.current)\n }\n }\n }, [])\n\n React.useEffect(() => {\n registerSelectCloseCallback(selectId, (shouldClose) => {\n if (shouldClose) {\n setIsOpen(false)\n }\n })\n return () => {\n unregisterSelectCloseCallback(selectId)\n clearSelectRegistry(selectId)\n }\n }, [selectId])\n\n React.useEffect(() => {\n if (isOpen) {\n closeOtherSelects(selectId)\n }\n }, [isOpen, selectId])\n\n const [uncontrolledSelectedKey, setUncontrolledSelectedKey] = React.useState<Key | null>(\n defaultSelectedKey ?? null\n )\n const [uncontrolledSelectedKeys, setUncontrolledSelectedKeys] = React.useState<Set<Key>>(\n new Set(defaultSelectedKeys)\n )\n const [selectedTextValue, setSelectedTextValue] = React.useState(label ?? defaultValue ?? \"\")\n const selectedKey = controlledSelectedKey !== undefined ? controlledSelectedKey : uncontrolledSelectedKey\n const selectedKeys = controlledSelectedKeys !== undefined ? new Set(controlledSelectedKeys) : uncontrolledSelectedKeys\n\n const nav = useListNavigation({\n isOpen,\n externalItems: propItems.length > 0 ? propItems : undefined,\n filter: filter ? (item: any) => filter({ ...item, label: item.textValue } as any) : undefined\n })\n\n const registerItem = React.useCallback((key: Key, textValue: string, isDisabled?: boolean, onSelect?: () => void, isSubmenuTrigger?: boolean) => {\n nav.registerItem(key, textValue, isDisabled)\n itemExtrasRef.current.set(key, { onSelect, isSubmenuTrigger })\n }, [nav.registerItem])\n\n const unregisterItem = React.useCallback((key: Key) => {\n nav.unregisterItem(key)\n itemExtrasRef.current.delete(key)\n }, [nav.unregisterItem])\n\n const isFocusedItemSubmenu = React.useCallback(() => {\n if (nav.focusedKey === null) return false\n return itemExtrasRef.current.get(nav.focusedKey)?.isSubmenuTrigger ?? false\n }, [nav.focusedKey])\n\n const markKeyboardNavigation = React.useCallback(() => {\n mouseMoveDetectedRef.current = false\n keyboardScrollIntentRef.current = true\n }, [])\n\n const moveFocusFromTrigger = React.useCallback((direction: 1 | -1) => {\n const triggerElement = triggerRef.current\n if (!triggerElement) return false\n return focusAdjacentTabStop(triggerElement, direction, wrapperRef.current)\n }, [])\n\n const restoreFocus = React.useCallback((target: \"auto\" | \"trigger\" | \"row\" = \"auto\") => {\n const triggerElement = triggerRef.current\n if (!triggerElement) return\n\n const ownerRow = triggerElement.closest<HTMLElement>('[data-list-focus-owner=\"true\"]')\n const focusTarget = target === \"row\"\n ? ownerRow\n : target === \"trigger\"\n ? triggerElement\n : ownerRow ?? triggerElement\n\n focusTarget?.focus({ preventScroll: true })\n }, [])\n\n const onSelect = React.useCallback((key: Key) => {\n const item = nav.items.find(i => i.key === key)\n if (item) {\n setSelectedTextValue(item.textValue)\n }\n if (controlledSelectedKey === undefined) {\n setUncontrolledSelectedKey(key)\n }\n onSelectionChange?.(key)\n setIsOpen(false)\n nav.setSearchValue(\"\")\n restoreFocus()\n }, [controlledSelectedKey, onSelectionChange, nav.items, restoreFocus])\n\n const onToggle = React.useCallback((key: Key) => {\n const newKeys = new Set(selectedKeys)\n if (newKeys.has(key)) {\n newKeys.delete(key)\n } else {\n newKeys.add(key)\n }\n if (controlledSelectedKeys === undefined) {\n setUncontrolledSelectedKeys(newKeys)\n }\n onSelectionChange?.(Array.from(newKeys))\n }, [selectedKeys, controlledSelectedKeys, onSelectionChange])\n\n const selectFocusedItem = React.useCallback(() => {\n if (nav.focusedKey !== null) {\n const item = nav.enabledFilteredItems.find(item => item.key === nav.focusedKey)\n if (item && !item.isDisabled) {\n const extras = itemExtrasRef.current.get(nav.focusedKey)\n if (extras?.onSelect) {\n extras.onSelect()\n } else if (mode === \"multiple\") {\n onToggle(nav.focusedKey)\n } else {\n onSelect(nav.focusedKey)\n }\n }\n }\n }, [nav.focusedKey, nav.enabledFilteredItems, onSelect, onToggle, mode])\n\n React.useEffect(() => {\n if (isOpen) {\n // Only initialize focusedKey if it's not already valid\n if (nav.focusedKey !== null && nav.visibleKeys.has(nav.focusedKey)) {\n const item = nav.filteredItems.find(item => item.key === nav.focusedKey)\n if (item && !item.isDisabled) {\n return // Keep current keyboard focus, don't reset it\n }\n }\n\n const focusKey = mode === \"multiple\" && selectedKeys.size > 0\n ? Array.from(selectedKeys)[0]\n : selectedKey\n\n if (focusKey !== null && nav.visibleKeys.has(focusKey)) {\n const item = nav.filteredItems.find(item => item.key === focusKey)\n if (item && !item.isDisabled) {\n nav.setFocusedKey(focusKey)\n return\n }\n }\n if (nav.enabledFilteredItems.length > 0) {\n nav.setFocusedKey(nav.enabledFilteredItems[0].key)\n } else {\n nav.setFocusedKey(null)\n }\n }\n }, [isOpen, selectedKey, selectedKeys, nav.visibleKeys, nav.enabledFilteredItems, nav.filteredItems, mode, nav.focusedKey])\n\n const { buttonProps, isPressed } = useButton({\n isDisabled,\n onPress: (e) => {\n if (isDisabled) return\n // Keyboard interactions are handled by onKeyDown to prevent conflicts\n if (e.pointerType !== 'keyboard') {\n setIsOpen(prev => !prev)\n }\n },\n }, triggerRef)\n const { focusProps, isFocused, isFocusVisible } = useFocusRing()\n const { hoverProps, isHovered } = useHover({\n isDisabled,\n onHoverStart: () => handleHoverIntent(true),\n onHoverEnd: () => handleHoverIntent(false),\n })\n\n const triggerProps = mergeProps(buttonProps, focusProps, hoverProps, {\n 'aria-haspopup': 'listbox' as const,\n 'aria-expanded': isOpen,\n 'aria-controls': isOpen ? contentId : undefined,\n 'aria-disabled': isDisabled || undefined,\n onKeyDown: (e: React.KeyboardEvent) => {\n if (!isOpen) {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter' || (e.key === ' ' && !isDisabled)) {\n e.preventDefault()\n setIsOpen(true)\n }\n return\n }\n\n if (e.key === 'Tab') {\n e.preventDefault()\n const direction = e.shiftKey ? -1 : 1\n setIsOpen(false)\n nav.setSearchValue(\"\")\n moveFocusFromTrigger(direction as 1 | -1)\n return\n }\n\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Home' || e.key === 'End') {\n markKeyboardNavigation()\n }\n\n handleListKeyDown(e, {\n navigateNext: nav.navigateToNextItem,\n navigatePrev: nav.navigateToPrevItem,\n confirm: selectFocusedItem,\n close: () => {\n setIsOpen(false)\n nav.setSearchValue(\"\")\n restoreFocus()\n },\n filteredItems: nav.filteredItems,\n setFocusedKey: nav.setFocusedKey,\n })\n },\n })\n\n React.useEffect(() => {\n if (autoFocus && triggerRef.current) {\n triggerRef.current.focus({ preventScroll: true })\n }\n }, [autoFocus])\n\n React.useEffect(() => {\n if (mode === \"single\") {\n if (selectedKey === null) {\n setSelectedTextValue(\"\")\n } else {\n const selectedItem = nav.items.find(item => item.key === selectedKey)\n if (selectedItem) {\n setSelectedTextValue(selectedItem.textValue)\n } else if (label !== undefined) {\n setSelectedTextValue(label)\n } else if (defaultValue !== undefined && defaultValue !== null) {\n setSelectedTextValue(defaultValue)\n }\n }\n }\n }, [selectedKey, nav.items, mode, defaultValue, label])\n\n const childrenArray = React.Children.toArray(children)\n const trigger = childrenArray.find(child => React.isValidElement(child) && (\n (child.type as any)?.displayName === 'SelectTrigger' ||\n (child.type as any)?.displayName === 'SearchableTrigger'\n ))\n const contentItems = childrenArray.filter(child => React.isValidElement(child) && ((child.type as any)?.displayName === 'SelectContent' || (child.type as any)?.displayName === 'SearchableContent'))\n const otherContent = childrenArray.filter(child => !React.isValidElement(child) || (\n (child.type as any)?.displayName !== 'SelectTrigger' &&\n (child.type as any)?.displayName !== 'SearchableTrigger' &&\n (child.type as any)?.displayName !== 'SelectContent' &&\n (child.type as any)?.displayName !== 'SearchableContent'\n ))\n const hasExternalValue = otherContent.some(child => (\n React.isValidElement(child) && (child.type as any)?.displayName === 'SelectValue'\n ))\n const triggerType = React.isValidElement(trigger) && (trigger.type as any)?.displayName === 'SearchableTrigger'\n ? 'input'\n : 'button'\n\n const resolvedStyles = resolveSelectStyles(stylesProp);\n const mergedRootRef = useMergeRefs<HTMLDivElement>(scopeRef, wrapperRef, ref)\n const { indicatorProps } = useFocus({\n scopeRef,\n containerRef: wrapperRef,\n surfaceSelector: '[data-select-focus-surface=\"true\"]',\n radiusSource: \"surface\",\n mode: \"self\",\n dependencies: [mode],\n });\n\n return (\n <SelectContext.Provider\n value={{\n isOpen,\n setIsOpen,\n contentPlacement,\n setContentPlacement,\n triggerType,\n mode,\n selectedKey,\n selectedKeys: mode === \"multiple\" ? selectedKeys : undefined,\n selectedTextValue,\n onSelect,\n onToggle: mode === \"multiple\" ? onToggle : undefined,\n triggerRef,\n wrapperRef,\n contentRef,\n triggerProps,\n isFocused,\n isFocusVisible,\n isPressed,\n isHovered,\n isDisabled,\n items: nav.items,\n registerItem,\n unregisterItem,\n searchValue: nav.searchValue,\n setSearchValue: nav.setSearchValue,\n filteredItems: nav.filteredItems,\n visibleKeys: nav.visibleKeys,\n focusedKey: nav.focusedKey,\n setFocusedKey: nav.setFocusedKey,\n navigateToNextItem: nav.navigateToNextItem,\n navigateToPrevItem: nav.navigateToPrevItem,\n selectFocusedItem,\n isFocusedItemSubmenu,\n maxItems,\n triggerMode,\n handleHoverIntent,\n mouseMoveDetectedRef,\n keyboardScrollIntentRef,\n markKeyboardNavigation,\n moveFocusFromTrigger,\n filter,\n contentId,\n hasExternalValue,\n restoreFocus,\n }}\n >\n <div\n ref={mergedRootRef}\n className={cn('select', styles.select, className, resolvedStyles.root)}\n data-mode={mode}\n data-select-focus-surface=\"true\"\n data-focused={isFocused ? \"true\" : \"false\"}\n data-focus-visible={isFocusVisible ? \"true\" : \"false\"}\n {...domProps}\n >\n <div {...indicatorProps} data-focus-indicator=\"local\" />\n {otherContent}\n {trigger}\n {contentItems}\n </div>\n </SelectContext.Provider>\n )\n }\n)\nSelect.displayName = \"Select\"\n\nexport { Select, SelectContext }\n",
5044
+ "css": "@reference \"tailwindcss\";\n\n@layer components {\n .scope {\n @apply flex w-full;\n position: relative;\n overflow: visible;\n }\n\n .select {\n --disabled-opacity: 0.5;\n --trigger-padding-inline: calc(var(--spacing) * 1.60);\n --trigger-padding-block: calc(var(--spacing) * 1.30);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n font-size: var(--foreground-size);\n height: fit-content;\n align-self: center;\n\n @apply p-0 gap-0 w-full flex-row items-center;\n position: relative;\n overflow: visible;\n\n background-color: var(--background);\n color: var(--foreground);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n\n @apply select-none cursor-pointer;\n\n &[data-disabled] {\n opacity: var(--disabled-opacity);\n cursor: not-allowed;\n }\n\n &[data-pressed=\"true\"]:not([data-disabled]) {\n background-color: var(--background-pressed, var(--background-hover, var(--background)));\n }\n\n &[data-open=\"true\"] {\n background-color: var(--background-hover);\n }\n\n &:global(.group) {\n height: 100%;\n align-self: stretch;\n }\n }\n\n .trigger {\n @apply flex items-stretch flex-1 gap-0 w-full h-full min-h-0;\n\n background: transparent;\n\n @apply border-none cursor-pointer select-none;\n\n @media (hover: hover) {\n &:not([data-disabled]):hover .icon-section,\n &:not([data-disabled]):hover .value-section:not(:empty) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n background-color: var(--background-hover);\n }\n }\n\n &[data-focus-visible=\"true\"] {\n @apply outline-none;\n }\n }\n\n .trigger-compact {\n @apply flex-none w-auto;\n }\n\n .select button.trigger { @apply p-0; }\n\n .value-section {\n @apply flex items-center flex-1 min-w-0 gap-0.5;\n\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n font-size: var(--foreground-size);\n &:only-child {\n border-radius: var(--background-inner-radius);\n justify-content: center;\n }\n &:empty {\n flex: 0;\n padding: 0;\n min-width: auto;\n }\n }\n\n .icon-section {\n @apply flex items-center justify-center shrink-0;\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n border-radius: 0 var(--background-inner-radius) var(--background-inner-radius) 0;\n }\n\n .icon {\n @apply flex items-center justify-center w-4 h-4 opacity-70;\n }\n\n.value {\n @apply flex items-center flex-1 min-w-0 gap-2 bg-transparent border-none;\n cursor: inherit;\n }\n\n .value-icon {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n color: var(--foreground);\n }\n\n .value-text {\n font-weight: var(--font-weight-medium);\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .content,\n .sub-content {\n --item-padding-inline: calc(var(--spacing) * 1.5);\n --item-padding-block: var(--spacing);\n --background-radius: var(--radius-sm, 0.375rem);\n --background-inner-radius: calc(var(--background-radius) - var(--border-width-base, 1px));\n overflow: hidden;\n background-color: var(--background);\n border: var(--border-width-base, 1px) solid var(--background-border);\n border-radius: var(--background-radius);\n }\n\n .content-root,\n .sub-content-root {\n position: absolute;\n }\n\n .content {}\n\n .list {\n @apply space-y-1;\n }\n\n .item,\n .sub-trigger {\n @apply flex items-center gap-2 outline-none cursor-default select-none;\n background-color: var(--background);\n border-radius: var(--background-inner-radius);\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground);\n &[data-disabled] {\n opacity: var(--disabled-opacity, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n }\n\n .item {\n --item-padding-inline: var(--trigger-padding-inline);\n --item-padding-block: calc(var(--trigger-padding-block) * 1.15);\n\n padding: var(--item-padding-block) var(--item-padding-inline);\n\n &[data-selected=\"true\"] {\n color: var(--foreground);\n }\n\n &[data-highlighted=\"true\"] {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .item-content {\n @apply flex flex-col flex-1 min-w-0;\n }\n\n .item-text {\n @apply min-w-0 overflow-hidden text-ellipsis whitespace-nowrap;\n }\n\n .item-description {\n font-size: var(--foreground-size);\n font-weight: var(--font-weight-medium);\n color: var(--foreground-muted);\n @apply min-w-0 whitespace-normal break-words;\n }\n\n .item-icon, .item-indicator {\n @apply flex items-center justify-center shrink-0 w-4 h-4;\n }\n\n .item-icon { color: var(--icon-foreground); }\n .item-indicator { color: var(--indicator-foreground); margin-left: auto; }\n\n .item-with-description { @apply items-start py-2; }\n .item-icon-with-description, .item-indicator-with-description { @apply mt-0.5; }\n\n .separator {\n @apply my-1 -mx-1 h-px;\n background-color: var(--background-border);\n }\n\n .placeholder {\n color: var(--foreground-muted);\n }\n\n .icon-prefix {\n @apply inline-flex items-center shrink-0;\n }\n\n .select[data-mode=\"multiple\"] .item { gap: 0.5rem; }\n\n .search-trigger {\n @apply flex items-stretch relative bg-transparent cursor-text overflow-hidden;\n border-radius: var(--background-inner-radius);\n &:focus-within {\n @apply outline-none;\n z-index: 1;\n }\n }\n\n .search-trigger :global(.focus-indicator) {\n display: none;\n }\n\n .search-value-section {\n @apply p-0;\n border-radius: var(--background-inner-radius) 0 0 var(--background-inner-radius);\n }\n\n .input {\n padding-right: calc(var(--trigger-padding-inline) * 2 + 1rem);\n @apply border-none rounded-none shadow-none bg-transparent;\n\n &[data-focused], &[data-focus-visible] {\n @apply border-none shadow-none;\n }\n }\n\n .search-content-input {\n @apply border-none rounded-none bg-transparent;\n }\n\n .search-icon-section {\n @apply absolute right-0 top-0 bottom-0 flex items-center justify-center bg-transparent pointer-events-none;\n padding-inline: var(--trigger-padding-inline);\n }\n\n\n .search-wrapper {\n @apply overflow-hidden;\n border-bottom: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .empty-state {\n @apply px-3 py-2;\n color: var(--foreground-muted);\n }\n\n .content[data-placement=\"top\"] .search-wrapper {\n border-radius: 0;\n border-bottom: none;\n border-top: var(--border-width-base, 1px) solid var(--background-border);\n }\n\n .sub-trigger {\n padding: var(--trigger-padding-block) var(--trigger-padding-inline);\n\n &[data-highlighted=\"true\"],\n &[data-open=\"true\"]:not([data-highlighted=\"true\"]) {\n --hover-transition-duration: var(--hover-transition-enter-duration, 0ms);\n }\n }\n\n .sub-trigger-chevron {\n @apply shrink-0 ml-auto w-4 h-4 opacity-60;\n }\n\n .sub-content {\n min-width: 160px;\n max-width: 320px;\n }\n\n}\n",
5046
5045
  "cssTypes": "declare const styles: {\n scope: string;\n select: string;\n \"select-split\": string;\n trigger: string;\n \"trigger-compact\": string;\n input: string;\n \"search-trigger\": string;\n \"search-value-section\": string;\n \"search-content-input\": string;\n \"search-icon-section\": string;\n \"search-wrapper\": string;\n \"empty-state\": string;\n \"value-section\": string;\n \"icon-section\": string;\n icon: string;\n value: string;\n \"value-icon\": string;\n \"value-text\": string;\n \"value-chevron\": string;\n \"content-root\": string;\n content: string;\n viewport: string;\n list: string;\n item: string;\n \"item-icon\": string;\n \"item-indicator\": string;\n \"item-text\": string;\n \"item-content\": string;\n \"item-description\": string;\n \"item-with-description\": string;\n \"item-icon-with-description\": string;\n \"item-indicator-with-description\": string;\n separator: string;\n \"scroll-button\": string;\n placeholder: string;\n \"icon-prefix\": string;\n \"sub-trigger\": string;\n \"sub-trigger-chevron\": string;\n \"sub-content-root\": string;\n \"sub-content\": string;\n};\n\nexport default styles;\n"
5047
5046
  },
5048
5047
  "slider": {
@@ -5313,6 +5312,6 @@ export const generatedCorePeerDependencies = [
5313
5312
  "react-dom"
5314
5313
  ];
5315
5314
  export const packageMetadata = {
5316
- "version": "0.3.48"
5315
+ "version": "0.3.49"
5317
5316
  };
5318
5317
  //# sourceMappingURL=generated-data.js.map