@ai-matrx/design-system 0.86.339 → 0.86.340

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/controls.css CHANGED
@@ -2463,3 +2463,169 @@
2463
2463
  color: var(--mac-label-secondary) !important;
2464
2464
  }
2465
2465
  }
2466
+
2467
+ /* ── THE WINDOW CHROME (2026-10-23) ───────────────────────────────────────────────────────────
2468
+ `WindowLights` / `WindowLight` / `WindowChromeButton` (controls/window-controls.tsx): a floating
2469
+ window's title bar at macOS's own geometry, never the 28px control (a light drawn as a Button was a
2470
+ 28px box with a 16px glyph in a 14px dot). Lights: 12px dots 8px apart, an 8px glyph revealed when
2471
+ the group is hovered or focused, each light's glyph in its own dark shade; disabled is a grey dot;
2472
+ an inactive window's lights are grey until the pointer reaches them. Chrome button: a 20px square,
2473
+ a 14px glyph, quiet until hovered. Colors are the --matrx-window-light-* tokens (tokens.css).
2474
+ Pinned by controls/window-controls-geometry.test.tsx. */
2475
+ @layer matrx-tap-lock {
2476
+ :root {
2477
+ --matrx-window-light-size: 0.75rem; /* 12px — the dot */
2478
+ --matrx-window-light-gap: 0.5rem; /* 8px between dots */
2479
+ --matrx-window-light-glyph-size: 0.5rem; /* 8px — the revealed glyph */
2480
+ --matrx-window-light-touch-size: 1.5rem; /* 24px — the phone header's dot */
2481
+ --matrx-window-light-touch-glyph-size: 0.625rem; /* 10px */
2482
+ --matrx-window-light-touch-gap: 0.75rem; /* 12px — the 44px hit areas barely meet */
2483
+ --matrx-window-chrome-button-size: 1.25rem; /* 20px — a title-bar action */
2484
+ --matrx-window-chrome-glyph: 0.875rem; /* 14px */
2485
+ }
2486
+ .matrx-window-lights {
2487
+ display: inline-flex !important;
2488
+ align-items: center !important;
2489
+ gap: var(--matrx-window-light-gap) !important;
2490
+ flex-shrink: 0 !important;
2491
+ cursor: default;
2492
+ }
2493
+ .matrx-window-light {
2494
+ position: relative;
2495
+ display: inline-flex !important;
2496
+ align-items: center !important;
2497
+ justify-content: center !important;
2498
+ flex-shrink: 0 !important;
2499
+ width: var(--matrx-window-light-size) !important;
2500
+ min-width: var(--matrx-window-light-size) !important;
2501
+ max-width: var(--matrx-window-light-size) !important;
2502
+ height: var(--matrx-window-light-size) !important;
2503
+ min-height: var(--matrx-window-light-size) !important;
2504
+ max-height: var(--matrx-window-light-size) !important;
2505
+ margin: 0 !important;
2506
+ padding: 0 !important;
2507
+ border: 0 !important;
2508
+ border-radius: 9999px !important;
2509
+ box-shadow: inset 0 0 0 0.5px hsl(var(--matrx-window-light-edge)) !important;
2510
+ cursor: pointer;
2511
+ -webkit-tap-highlight-color: transparent;
2512
+ transition: background-color 120ms ease, filter 120ms ease;
2513
+ }
2514
+ /* The hit area spans half the gap on every side, so the row of lights has no dead pixels between dots. */
2515
+ .matrx-window-light::after {
2516
+ content: "";
2517
+ position: absolute;
2518
+ inset: calc(var(--matrx-window-light-gap) / -2);
2519
+ border-radius: 9999px;
2520
+ }
2521
+ .matrx-window-light[data-matrx-window-light="close"] {
2522
+ background-color: hsl(var(--matrx-window-light-close)) !important;
2523
+ color: hsl(var(--matrx-window-light-close-glyph)) !important;
2524
+ }
2525
+ .matrx-window-light[data-matrx-window-light="minimize"] {
2526
+ background-color: hsl(var(--matrx-window-light-minimize)) !important;
2527
+ color: hsl(var(--matrx-window-light-minimize-glyph)) !important;
2528
+ }
2529
+ .matrx-window-light[data-matrx-window-light="maximize"] {
2530
+ background-color: hsl(var(--matrx-window-light-maximize)) !important;
2531
+ color: hsl(var(--matrx-window-light-maximize-glyph)) !important;
2532
+ }
2533
+ .matrx-window-light:active:not(:disabled) {
2534
+ filter: brightness(0.85);
2535
+ }
2536
+ .matrx-window-light svg {
2537
+ width: var(--matrx-window-light-glyph-size) !important;
2538
+ height: var(--matrx-window-light-glyph-size) !important;
2539
+ flex-shrink: 0 !important;
2540
+ stroke-width: 3.5 !important;
2541
+ opacity: 0;
2542
+ transition: opacity 100ms ease;
2543
+ pointer-events: none;
2544
+ }
2545
+ .matrx-window-lights:is(:hover, :focus-within) .matrx-window-light:not(:disabled) svg {
2546
+ opacity: 1;
2547
+ }
2548
+ /* Nothing hovers on touch: the glyphs are always shown. */
2549
+ @media (hover: none) {
2550
+ .matrx-window-light:not(:disabled) svg {
2551
+ opacity: 1;
2552
+ }
2553
+ }
2554
+ .matrx-window-light:focus-visible {
2555
+ outline: 2px solid hsl(var(--ring)) !important;
2556
+ outline-offset: 1px !important;
2557
+ }
2558
+ .matrx-window-light:disabled,
2559
+ .matrx-window-lights[data-inactive]:not(:hover):not(:focus-within) .matrx-window-light {
2560
+ background-color: hsl(var(--matrx-window-light-off)) !important;
2561
+ }
2562
+ .matrx-window-light:disabled {
2563
+ cursor: default;
2564
+ }
2565
+ .matrx-window-light:disabled svg {
2566
+ opacity: 0 !important;
2567
+ }
2568
+ /* The phone header's lights: bigger dots, glyphs always shown, a 44px hit area. */
2569
+ .matrx-window-lights[data-touch] {
2570
+ gap: var(--matrx-window-light-touch-gap) !important;
2571
+ }
2572
+ .matrx-window-lights[data-touch] .matrx-window-light {
2573
+ width: var(--matrx-window-light-touch-size) !important;
2574
+ min-width: var(--matrx-window-light-touch-size) !important;
2575
+ max-width: var(--matrx-window-light-touch-size) !important;
2576
+ height: var(--matrx-window-light-touch-size) !important;
2577
+ min-height: var(--matrx-window-light-touch-size) !important;
2578
+ max-height: var(--matrx-window-light-touch-size) !important;
2579
+ }
2580
+ .matrx-window-lights[data-touch] .matrx-window-light::after {
2581
+ inset: calc((var(--matrx-control-touch) - var(--matrx-window-light-touch-size)) / -2);
2582
+ }
2583
+ .matrx-window-lights[data-touch] .matrx-window-light svg {
2584
+ width: var(--matrx-window-light-touch-glyph-size) !important;
2585
+ height: var(--matrx-window-light-touch-glyph-size) !important;
2586
+ stroke-width: 3 !important;
2587
+ }
2588
+ .matrx-window-lights[data-touch] .matrx-window-light:not(:disabled) svg {
2589
+ opacity: 1;
2590
+ }
2591
+
2592
+ .matrx-window-chrome-button {
2593
+ position: relative;
2594
+ display: inline-flex !important;
2595
+ align-items: center !important;
2596
+ justify-content: center !important;
2597
+ flex-shrink: 0 !important;
2598
+ width: var(--matrx-window-chrome-button-size) !important;
2599
+ min-width: var(--matrx-window-chrome-button-size) !important;
2600
+ max-width: var(--matrx-window-chrome-button-size) !important;
2601
+ height: var(--matrx-window-chrome-button-size) !important;
2602
+ min-height: var(--matrx-window-chrome-button-size) !important;
2603
+ max-height: var(--matrx-window-chrome-button-size) !important;
2604
+ margin: 0 !important;
2605
+ padding: 0 !important;
2606
+ border: 0 !important;
2607
+ border-radius: 0.375rem !important;
2608
+ background-color: transparent !important;
2609
+ color: hsl(var(--muted-foreground)) !important;
2610
+ cursor: pointer;
2611
+ -webkit-tap-highlight-color: transparent;
2612
+ transition: background-color 120ms ease, color 120ms ease;
2613
+ }
2614
+ .matrx-window-chrome-button svg {
2615
+ width: var(--matrx-window-chrome-glyph) !important;
2616
+ height: var(--matrx-window-chrome-glyph) !important;
2617
+ flex-shrink: 0 !important;
2618
+ }
2619
+ .matrx-window-chrome-button:hover:not(:disabled) {
2620
+ background-color: hsl(var(--accent)) !important;
2621
+ color: hsl(var(--foreground)) !important;
2622
+ }
2623
+ .matrx-window-chrome-button:focus-visible {
2624
+ outline: 2px solid hsl(var(--ring)) !important;
2625
+ outline-offset: 1px !important;
2626
+ }
2627
+ .matrx-window-chrome-button:disabled {
2628
+ color: hsl(var(--disabled-foreground)) !important;
2629
+ cursor: default;
2630
+ }
2631
+ }
@@ -326,6 +326,54 @@ interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement
326
326
  */
327
327
  declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
328
328
 
329
+ /**
330
+ * THE WINDOW CHROME CONTROLS (2026-10-23) — the title bar of a floating window (summon's
331
+ * WindowPanel) drawn at macOS's own geometry, never the 28px control:
332
+ *
333
+ * WindowLights the traffic-light group: 12px dots 8px apart; hovering (or focusing) the
334
+ * group reveals every light's 8px glyph, as macOS does. `inactive` greys the
335
+ * lights of a window that is not in front until the pointer reaches them.
336
+ * `touch` is the phone header's lights: 24px dots, 10px glyphs always shown.
337
+ * WindowLight one light: `kind` close / minimize / maximize picks its color and glyph;
338
+ * `restores` swaps in the restore glyph (a minimized window's yellow, a
339
+ * maximized window's green). Disabled is a grey dot with no glyph.
340
+ * WindowChromeButton a title-bar icon action (the sidebar toggle, pop out): a 20px square with
341
+ * a 14px glyph, quiet until hovered.
342
+ *
343
+ * Geometry and color live in `controls.css` (THE WINDOW CHROME), locked in
344
+ * `@layer matrx-tap-lock` like every control, so `className` places them and never restyles them.
345
+ * Colors are the `--matrx-window-light-*` tokens in `tokens.css` (both themes). The contract is
346
+ * pinned by `window-controls-geometry.test.tsx`: moving a light back onto the 28px Button fails it.
347
+ */
348
+
349
+ type WindowLightKind = "close" | "minimize" | "maximize";
350
+ interface WindowLightsProps extends React.HTMLAttributes<HTMLDivElement> {
351
+ /** The window is not the one in front: the lights are grey until the pointer reaches them. */
352
+ inactive?: boolean;
353
+ /** The phone header's lights: 24px dots with their glyphs always shown (no hover on touch). */
354
+ touch?: boolean;
355
+ }
356
+ /** The traffic-light group. Its hover (or keyboard focus) reveals every light's glyph. */
357
+ declare const WindowLights: React.ForwardRefExoticComponent<WindowLightsProps & React.RefAttributes<HTMLDivElement>>;
358
+ interface WindowLightProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
359
+ /** Which light: close (red), minimize (yellow), maximize (green). */
360
+ kind: WindowLightKind;
361
+ /** The light undoes its window's state (restore a minimized or maximized window): the restore glyph. */
362
+ restores?: boolean;
363
+ /** A light must say what it does. */
364
+ "aria-label": string;
365
+ }
366
+ /** One traffic light. Place it inside `WindowLights`. */
367
+ declare const WindowLight: React.ForwardRefExoticComponent<WindowLightProps & React.RefAttributes<HTMLButtonElement>>;
368
+ interface WindowChromeButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
369
+ /** The 14px glyph. */
370
+ icon: React.ReactNode;
371
+ /** A title-bar action must say what it does (also its tooltip unless `title` is given). */
372
+ "aria-label": string;
373
+ }
374
+ /** A title-bar icon action (sidebar toggle, pop out): 20px, quiet until hovered. */
375
+ declare const WindowChromeButton: React.ForwardRefExoticComponent<WindowChromeButtonProps & React.RefAttributes<HTMLButtonElement>>;
376
+
329
377
  /**
330
378
  * DecisionControl — THE row decision: [Yes] [No] [Other] + the answer's value chip.
331
379
  *
@@ -2078,4 +2126,4 @@ interface TileCardGridProps {
2078
2126
  }
2079
2127
  declare function TileCardGrid({ title, description, cards, columns, className }: TileCardGridProps): React.JSX.Element;
2080
2128
 
2081
- export { ActionFeedbackButton, type ActionFeedbackButtonProps, AdvancedCollapsible, type AdvancedCollapsibleProps, type AnchorRect, AnchoredToolbar, type AnchoredToolbarProps, AspectRatioGlyph, AspectRatioSelect, type AspectRatioSelectProps, Badge, type BadgeProps, type BadgeTone, type BlockingCheck, Button, type ButtonProps$1 as ButtonProps, CHIP_TONES, CONFIGURATION_CHOICE_SIZE, CONTROLS_COLLAPSE_BELOW_REM, CONTROLS_CONTAINER_CLASS, CONTROLS_CONTAINER_NAME, CalloutBanner, type CalloutTone, type CardColor, type CardSize, Chip, type ChipHue, type ChipProps, ChipSet, type ChipSetProps, type ChipTone, CitationChip, type CitationChipProps, CitationPopoverBody, type CitationPopoverBodyProps, ClampedNumberInput, type ClampedNumberInputProps, CollapsibleText, CollapsibleTextGroupControls, type ColorSwatch, ColorSwatchRow, type ColorSwatchRowProps, type ConfigurationColumn, ConfigurationTable, ConfigurationTableRow, ConfigurationValueList, ConfirmDelete, type ConfirmDeleteProps, ControlRow, type ControlRowProps, ControlScope, type ControlVariant, type ControlWidth, DangerZone, DateField, type DateFieldMode, type DateFieldProps, DateTimeField, type DecisionAnswer, DecisionControl, type DecisionControlProps, DeleteButton, type DeleteButtonProps, DisclosureHeader, type DisclosureHeaderProps, type DisclosureHeaderVariant, EmptyState, EmptyStateCard, type EmptyStateCardProps, type EmptyStateProps, Field, FieldHelp, type FieldProps, GatedActionButton, type GatedActionButtonProps, type GlyphTone, HUE_TONE, HelpIcon, type HelpIconProps, HueCard, type HueCardProps, HueGrid, type HueGridProps, HueList, type HueListProps, HueRow, type HueRowProps, IconDropdownMenu, type IconDropdownMenuProps, type IconDropdownOption, IconSelect, type IconSelectItem, type IconSelectProps, type IndicatorItem, IndicatorStrip, type IndicatorStripProps, type IndicatorTone, InfoHint, type InfoHintProps, Input, type InputProps, IosWidget, type IosWidgetProps, KpiGrid, KpiTile, type KpiTileProps, type KpiTone, type KpiTrend, LabeledField, type LabeledFieldProps, LightSwitchToggle, type LightSwitchToggleProps, MiddleTruncate, MissingTag, NumberStepper, type NumberStepperProps, OpacitySlider, type OpacitySliderProps, OptionCombobox, type OptionComboboxGroup, type OptionComboboxProps, PageRangeInput, type PageRangeInputProps, type PageRangeIssue, type PageRangeIssueKind, type ParsedPageRanges, type ParsedRatio, PromoBanner, type PromoBannerProps, type PromoTone, PropertyRow, type PropertyRowProps, type RatioGroups, RegionSkeleton, type RegionSkeletonProps, RowGroup, type RowGroupProps, STATUS_TONES, SearchField, SearchInput, type SearchInputProps, type SegmentOption, SegmentedControl, type SegmentedControlProps, Select, type SelectOption, type SelectProps, SelectTrigger, type SelectTriggerProps, SettingRow, type SettingRowProps, Slider, type SliderProps, SplitButton, type StageState, type StageStep, StageSteps, type StageStepsProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, StatusToken, type StatusTone, StructuredSectionCard, type StructuredSectionCardProps, type StructuredSectionCardTitleTone, Switch, type SwitchProps, Tabs, TabsList, type TabsListProps, type TabsProps, TabsTrigger, type TabsVariant, TextArrayInput, type TextArrayInputProps, Textarea, type TextareaProps, Tile, TileCard, TileCardGrid, type TileCardGridProps, type TileCardProps, type TileLayout, type TileProps, TimeField, ToolRail, type ToolRailItem, type ToolRailProps, type WayOutItem, clampDraft, cleanUrl, firstBlockingReason, formatDay, formatPageRanges, formatTime, groupRatioOptions, humanizeRatioWord, indicatorText, isAspectRatioOptionSet, isCollectedValue, parsePageRanges, parseRatio, parseTypedDate, parseTypedTime, ratioShapeName, shownDraft, spansOf, splitForMiddleTruncate, stageStates, valueSummary };
2129
+ export { ActionFeedbackButton, type ActionFeedbackButtonProps, AdvancedCollapsible, type AdvancedCollapsibleProps, type AnchorRect, AnchoredToolbar, type AnchoredToolbarProps, AspectRatioGlyph, AspectRatioSelect, type AspectRatioSelectProps, Badge, type BadgeProps, type BadgeTone, type BlockingCheck, Button, type ButtonProps$1 as ButtonProps, CHIP_TONES, CONFIGURATION_CHOICE_SIZE, CONTROLS_COLLAPSE_BELOW_REM, CONTROLS_CONTAINER_CLASS, CONTROLS_CONTAINER_NAME, CalloutBanner, type CalloutTone, type CardColor, type CardSize, Chip, type ChipHue, type ChipProps, ChipSet, type ChipSetProps, type ChipTone, CitationChip, type CitationChipProps, CitationPopoverBody, type CitationPopoverBodyProps, ClampedNumberInput, type ClampedNumberInputProps, CollapsibleText, CollapsibleTextGroupControls, type ColorSwatch, ColorSwatchRow, type ColorSwatchRowProps, type ConfigurationColumn, ConfigurationTable, ConfigurationTableRow, ConfigurationValueList, ConfirmDelete, type ConfirmDeleteProps, ControlRow, type ControlRowProps, ControlScope, type ControlVariant, type ControlWidth, DangerZone, DateField, type DateFieldMode, type DateFieldProps, DateTimeField, type DecisionAnswer, DecisionControl, type DecisionControlProps, DeleteButton, type DeleteButtonProps, DisclosureHeader, type DisclosureHeaderProps, type DisclosureHeaderVariant, EmptyState, EmptyStateCard, type EmptyStateCardProps, type EmptyStateProps, Field, FieldHelp, type FieldProps, GatedActionButton, type GatedActionButtonProps, type GlyphTone, HUE_TONE, HelpIcon, type HelpIconProps, HueCard, type HueCardProps, HueGrid, type HueGridProps, HueList, type HueListProps, HueRow, type HueRowProps, IconDropdownMenu, type IconDropdownMenuProps, type IconDropdownOption, IconSelect, type IconSelectItem, type IconSelectProps, type IndicatorItem, IndicatorStrip, type IndicatorStripProps, type IndicatorTone, InfoHint, type InfoHintProps, Input, type InputProps, IosWidget, type IosWidgetProps, KpiGrid, KpiTile, type KpiTileProps, type KpiTone, type KpiTrend, LabeledField, type LabeledFieldProps, LightSwitchToggle, type LightSwitchToggleProps, MiddleTruncate, MissingTag, NumberStepper, type NumberStepperProps, OpacitySlider, type OpacitySliderProps, OptionCombobox, type OptionComboboxGroup, type OptionComboboxProps, PageRangeInput, type PageRangeInputProps, type PageRangeIssue, type PageRangeIssueKind, type ParsedPageRanges, type ParsedRatio, PromoBanner, type PromoBannerProps, type PromoTone, PropertyRow, type PropertyRowProps, type RatioGroups, RegionSkeleton, type RegionSkeletonProps, RowGroup, type RowGroupProps, STATUS_TONES, SearchField, SearchInput, type SearchInputProps, type SegmentOption, SegmentedControl, type SegmentedControlProps, Select, type SelectOption, type SelectProps, SelectTrigger, type SelectTriggerProps, SettingRow, type SettingRowProps, Slider, type SliderProps, SplitButton, type StageState, type StageStep, StageSteps, type StageStepsProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, StatusToken, type StatusTone, StructuredSectionCard, type StructuredSectionCardProps, type StructuredSectionCardTitleTone, Switch, type SwitchProps, Tabs, TabsList, type TabsListProps, type TabsProps, TabsTrigger, type TabsVariant, TextArrayInput, type TextArrayInputProps, Textarea, type TextareaProps, Tile, TileCard, TileCardGrid, type TileCardGridProps, type TileCardProps, type TileLayout, type TileProps, TimeField, ToolRail, type ToolRailItem, type ToolRailProps, type WayOutItem, WindowChromeButton, type WindowChromeButtonProps, WindowLight, type WindowLightKind, type WindowLightProps, WindowLights, type WindowLightsProps, clampDraft, cleanUrl, firstBlockingReason, formatDay, formatPageRanges, formatTime, groupRatioOptions, humanizeRatioWord, indicatorText, isAspectRatioOptionSet, isCollectedValue, parsePageRanges, parseRatio, parseTypedDate, parseTypedTime, ratioShapeName, shownDraft, spansOf, splitForMiddleTruncate, stageStates, valueSummary };
@@ -326,6 +326,54 @@ interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement
326
326
  */
327
327
  declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
328
328
 
329
+ /**
330
+ * THE WINDOW CHROME CONTROLS (2026-10-23) — the title bar of a floating window (summon's
331
+ * WindowPanel) drawn at macOS's own geometry, never the 28px control:
332
+ *
333
+ * WindowLights the traffic-light group: 12px dots 8px apart; hovering (or focusing) the
334
+ * group reveals every light's 8px glyph, as macOS does. `inactive` greys the
335
+ * lights of a window that is not in front until the pointer reaches them.
336
+ * `touch` is the phone header's lights: 24px dots, 10px glyphs always shown.
337
+ * WindowLight one light: `kind` close / minimize / maximize picks its color and glyph;
338
+ * `restores` swaps in the restore glyph (a minimized window's yellow, a
339
+ * maximized window's green). Disabled is a grey dot with no glyph.
340
+ * WindowChromeButton a title-bar icon action (the sidebar toggle, pop out): a 20px square with
341
+ * a 14px glyph, quiet until hovered.
342
+ *
343
+ * Geometry and color live in `controls.css` (THE WINDOW CHROME), locked in
344
+ * `@layer matrx-tap-lock` like every control, so `className` places them and never restyles them.
345
+ * Colors are the `--matrx-window-light-*` tokens in `tokens.css` (both themes). The contract is
346
+ * pinned by `window-controls-geometry.test.tsx`: moving a light back onto the 28px Button fails it.
347
+ */
348
+
349
+ type WindowLightKind = "close" | "minimize" | "maximize";
350
+ interface WindowLightsProps extends React.HTMLAttributes<HTMLDivElement> {
351
+ /** The window is not the one in front: the lights are grey until the pointer reaches them. */
352
+ inactive?: boolean;
353
+ /** The phone header's lights: 24px dots with their glyphs always shown (no hover on touch). */
354
+ touch?: boolean;
355
+ }
356
+ /** The traffic-light group. Its hover (or keyboard focus) reveals every light's glyph. */
357
+ declare const WindowLights: React.ForwardRefExoticComponent<WindowLightsProps & React.RefAttributes<HTMLDivElement>>;
358
+ interface WindowLightProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
359
+ /** Which light: close (red), minimize (yellow), maximize (green). */
360
+ kind: WindowLightKind;
361
+ /** The light undoes its window's state (restore a minimized or maximized window): the restore glyph. */
362
+ restores?: boolean;
363
+ /** A light must say what it does. */
364
+ "aria-label": string;
365
+ }
366
+ /** One traffic light. Place it inside `WindowLights`. */
367
+ declare const WindowLight: React.ForwardRefExoticComponent<WindowLightProps & React.RefAttributes<HTMLButtonElement>>;
368
+ interface WindowChromeButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
369
+ /** The 14px glyph. */
370
+ icon: React.ReactNode;
371
+ /** A title-bar action must say what it does (also its tooltip unless `title` is given). */
372
+ "aria-label": string;
373
+ }
374
+ /** A title-bar icon action (sidebar toggle, pop out): 20px, quiet until hovered. */
375
+ declare const WindowChromeButton: React.ForwardRefExoticComponent<WindowChromeButtonProps & React.RefAttributes<HTMLButtonElement>>;
376
+
329
377
  /**
330
378
  * DecisionControl — THE row decision: [Yes] [No] [Other] + the answer's value chip.
331
379
  *
@@ -2078,4 +2126,4 @@ interface TileCardGridProps {
2078
2126
  }
2079
2127
  declare function TileCardGrid({ title, description, cards, columns, className }: TileCardGridProps): React.JSX.Element;
2080
2128
 
2081
- export { ActionFeedbackButton, type ActionFeedbackButtonProps, AdvancedCollapsible, type AdvancedCollapsibleProps, type AnchorRect, AnchoredToolbar, type AnchoredToolbarProps, AspectRatioGlyph, AspectRatioSelect, type AspectRatioSelectProps, Badge, type BadgeProps, type BadgeTone, type BlockingCheck, Button, type ButtonProps$1 as ButtonProps, CHIP_TONES, CONFIGURATION_CHOICE_SIZE, CONTROLS_COLLAPSE_BELOW_REM, CONTROLS_CONTAINER_CLASS, CONTROLS_CONTAINER_NAME, CalloutBanner, type CalloutTone, type CardColor, type CardSize, Chip, type ChipHue, type ChipProps, ChipSet, type ChipSetProps, type ChipTone, CitationChip, type CitationChipProps, CitationPopoverBody, type CitationPopoverBodyProps, ClampedNumberInput, type ClampedNumberInputProps, CollapsibleText, CollapsibleTextGroupControls, type ColorSwatch, ColorSwatchRow, type ColorSwatchRowProps, type ConfigurationColumn, ConfigurationTable, ConfigurationTableRow, ConfigurationValueList, ConfirmDelete, type ConfirmDeleteProps, ControlRow, type ControlRowProps, ControlScope, type ControlVariant, type ControlWidth, DangerZone, DateField, type DateFieldMode, type DateFieldProps, DateTimeField, type DecisionAnswer, DecisionControl, type DecisionControlProps, DeleteButton, type DeleteButtonProps, DisclosureHeader, type DisclosureHeaderProps, type DisclosureHeaderVariant, EmptyState, EmptyStateCard, type EmptyStateCardProps, type EmptyStateProps, Field, FieldHelp, type FieldProps, GatedActionButton, type GatedActionButtonProps, type GlyphTone, HUE_TONE, HelpIcon, type HelpIconProps, HueCard, type HueCardProps, HueGrid, type HueGridProps, HueList, type HueListProps, HueRow, type HueRowProps, IconDropdownMenu, type IconDropdownMenuProps, type IconDropdownOption, IconSelect, type IconSelectItem, type IconSelectProps, type IndicatorItem, IndicatorStrip, type IndicatorStripProps, type IndicatorTone, InfoHint, type InfoHintProps, Input, type InputProps, IosWidget, type IosWidgetProps, KpiGrid, KpiTile, type KpiTileProps, type KpiTone, type KpiTrend, LabeledField, type LabeledFieldProps, LightSwitchToggle, type LightSwitchToggleProps, MiddleTruncate, MissingTag, NumberStepper, type NumberStepperProps, OpacitySlider, type OpacitySliderProps, OptionCombobox, type OptionComboboxGroup, type OptionComboboxProps, PageRangeInput, type PageRangeInputProps, type PageRangeIssue, type PageRangeIssueKind, type ParsedPageRanges, type ParsedRatio, PromoBanner, type PromoBannerProps, type PromoTone, PropertyRow, type PropertyRowProps, type RatioGroups, RegionSkeleton, type RegionSkeletonProps, RowGroup, type RowGroupProps, STATUS_TONES, SearchField, SearchInput, type SearchInputProps, type SegmentOption, SegmentedControl, type SegmentedControlProps, Select, type SelectOption, type SelectProps, SelectTrigger, type SelectTriggerProps, SettingRow, type SettingRowProps, Slider, type SliderProps, SplitButton, type StageState, type StageStep, StageSteps, type StageStepsProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, StatusToken, type StatusTone, StructuredSectionCard, type StructuredSectionCardProps, type StructuredSectionCardTitleTone, Switch, type SwitchProps, Tabs, TabsList, type TabsListProps, type TabsProps, TabsTrigger, type TabsVariant, TextArrayInput, type TextArrayInputProps, Textarea, type TextareaProps, Tile, TileCard, TileCardGrid, type TileCardGridProps, type TileCardProps, type TileLayout, type TileProps, TimeField, ToolRail, type ToolRailItem, type ToolRailProps, type WayOutItem, clampDraft, cleanUrl, firstBlockingReason, formatDay, formatPageRanges, formatTime, groupRatioOptions, humanizeRatioWord, indicatorText, isAspectRatioOptionSet, isCollectedValue, parsePageRanges, parseRatio, parseTypedDate, parseTypedTime, ratioShapeName, shownDraft, spansOf, splitForMiddleTruncate, stageStates, valueSummary };
2129
+ export { ActionFeedbackButton, type ActionFeedbackButtonProps, AdvancedCollapsible, type AdvancedCollapsibleProps, type AnchorRect, AnchoredToolbar, type AnchoredToolbarProps, AspectRatioGlyph, AspectRatioSelect, type AspectRatioSelectProps, Badge, type BadgeProps, type BadgeTone, type BlockingCheck, Button, type ButtonProps$1 as ButtonProps, CHIP_TONES, CONFIGURATION_CHOICE_SIZE, CONTROLS_COLLAPSE_BELOW_REM, CONTROLS_CONTAINER_CLASS, CONTROLS_CONTAINER_NAME, CalloutBanner, type CalloutTone, type CardColor, type CardSize, Chip, type ChipHue, type ChipProps, ChipSet, type ChipSetProps, type ChipTone, CitationChip, type CitationChipProps, CitationPopoverBody, type CitationPopoverBodyProps, ClampedNumberInput, type ClampedNumberInputProps, CollapsibleText, CollapsibleTextGroupControls, type ColorSwatch, ColorSwatchRow, type ColorSwatchRowProps, type ConfigurationColumn, ConfigurationTable, ConfigurationTableRow, ConfigurationValueList, ConfirmDelete, type ConfirmDeleteProps, ControlRow, type ControlRowProps, ControlScope, type ControlVariant, type ControlWidth, DangerZone, DateField, type DateFieldMode, type DateFieldProps, DateTimeField, type DecisionAnswer, DecisionControl, type DecisionControlProps, DeleteButton, type DeleteButtonProps, DisclosureHeader, type DisclosureHeaderProps, type DisclosureHeaderVariant, EmptyState, EmptyStateCard, type EmptyStateCardProps, type EmptyStateProps, Field, FieldHelp, type FieldProps, GatedActionButton, type GatedActionButtonProps, type GlyphTone, HUE_TONE, HelpIcon, type HelpIconProps, HueCard, type HueCardProps, HueGrid, type HueGridProps, HueList, type HueListProps, HueRow, type HueRowProps, IconDropdownMenu, type IconDropdownMenuProps, type IconDropdownOption, IconSelect, type IconSelectItem, type IconSelectProps, type IndicatorItem, IndicatorStrip, type IndicatorStripProps, type IndicatorTone, InfoHint, type InfoHintProps, Input, type InputProps, IosWidget, type IosWidgetProps, KpiGrid, KpiTile, type KpiTileProps, type KpiTone, type KpiTrend, LabeledField, type LabeledFieldProps, LightSwitchToggle, type LightSwitchToggleProps, MiddleTruncate, MissingTag, NumberStepper, type NumberStepperProps, OpacitySlider, type OpacitySliderProps, OptionCombobox, type OptionComboboxGroup, type OptionComboboxProps, PageRangeInput, type PageRangeInputProps, type PageRangeIssue, type PageRangeIssueKind, type ParsedPageRanges, type ParsedRatio, PromoBanner, type PromoBannerProps, type PromoTone, PropertyRow, type PropertyRowProps, type RatioGroups, RegionSkeleton, type RegionSkeletonProps, RowGroup, type RowGroupProps, STATUS_TONES, SearchField, SearchInput, type SearchInputProps, type SegmentOption, SegmentedControl, type SegmentedControlProps, Select, type SelectOption, type SelectProps, SelectTrigger, type SelectTriggerProps, SettingRow, type SettingRowProps, Slider, type SliderProps, SplitButton, type StageState, type StageStep, StageSteps, type StageStepsProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, StatusToken, type StatusTone, StructuredSectionCard, type StructuredSectionCardProps, type StructuredSectionCardTitleTone, Switch, type SwitchProps, Tabs, TabsList, type TabsListProps, type TabsProps, TabsTrigger, type TabsVariant, TextArrayInput, type TextArrayInputProps, Textarea, type TextareaProps, Tile, TileCard, TileCardGrid, type TileCardGridProps, type TileCardProps, type TileLayout, type TileProps, TimeField, ToolRail, type ToolRailItem, type ToolRailProps, type WayOutItem, WindowChromeButton, type WindowChromeButtonProps, WindowLight, type WindowLightKind, type WindowLightProps, WindowLights, type WindowLightsProps, clampDraft, cleanUrl, firstBlockingReason, formatDay, formatPageRanges, formatTime, groupRatioOptions, humanizeRatioWord, indicatorText, isAspectRatioOptionSet, isCollectedValue, parsePageRanges, parseRatio, parseTypedDate, parseTypedTime, ratioShapeName, shownDraft, spansOf, splitForMiddleTruncate, stageStates, valueSummary };
package/dist/controls.js CHANGED
@@ -47,6 +47,9 @@ import {
47
47
  TileCardGrid,
48
48
  TimeField,
49
49
  ToolRail,
50
+ WindowChromeButton,
51
+ WindowLight,
52
+ WindowLights,
50
53
  clampDraft,
51
54
  cleanUrl,
52
55
  firstBlockingReason,
@@ -66,7 +69,7 @@ import {
66
69
  spansOf,
67
70
  splitForMiddleTruncate,
68
71
  stageStates
69
- } from "./chunk-T4IJELSS.js";
72
+ } from "./chunk-KYH42WEX.js";
70
73
  import "./chunk-6NOLVA4E.js";
71
74
  import {
72
75
  Input,
@@ -239,6 +242,9 @@ export {
239
242
  TileCardGrid,
240
243
  TimeField,
241
244
  ToolRail,
245
+ WindowChromeButton,
246
+ WindowLight,
247
+ WindowLights,
242
248
  clampDraft,
243
249
  cleanUrl,
244
250
  firstBlockingReason,
package/dist/index.cjs CHANGED
@@ -4272,6 +4272,7 @@ __export(src_exports, {
4272
4272
  ArchivedDisclosure: () => ArchivedDisclosure,
4273
4273
  AssistPeekCard: () => AssistPeekCard,
4274
4274
  AssistPeekHover: () => AssistPeekHover,
4275
+ AssistTray: () => AssistTray,
4275
4276
  AuthGateDialog: () => AuthGateDialog2,
4276
4277
  Avatar: () => Avatar,
4277
4278
  AvatarFallback: () => AvatarFallback,
@@ -14447,7 +14448,7 @@ function ValueShell({ kind, glyph: Glyph, text, copy, state, record, peek, wrap
14447
14448
  const off = state !== "ok";
14448
14449
  const value = /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: cn("min-w-0", wrap ? "whitespace-pre-line break-words" : "truncate", off ? "text-muted-foreground line-through" : "text-foreground"), children: text });
14449
14450
  const body = /* @__PURE__ */ (0, import_jsx_runtime92.jsxs)(import_jsx_runtime92.Fragment, { children: [
14450
- /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Glyph, { className: cn("size-[1em] shrink-0", off ? "text-muted-foreground" : "text-muted-foreground") }),
14451
+ Glyph ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(Glyph, { className: "size-[1em] shrink-0 text-muted-foreground" }) : null,
14451
14452
  value,
14452
14453
  off ? /* @__PURE__ */ (0, import_jsx_runtime92.jsx)("span", { className: "shrink-0 text-muted-foreground no-underline", children: `\xB7 ${CONTACT_STATE_LABEL[state]}` }) : null
14453
14454
  ] });
@@ -14648,7 +14649,7 @@ function SocialHandleValue(props) {
14648
14649
  }
14649
14650
  );
14650
14651
  }
14651
- function UrlValue({ url, title, owner, state = "ok", peek = true }) {
14652
+ function UrlValue({ url, title, owner, state = "ok", peek = true, icon = true }) {
14652
14653
  const parsed = parseUrl(url);
14653
14654
  const ok = state === "ok" && Boolean(parsed.href);
14654
14655
  const record = {
@@ -14668,9 +14669,9 @@ function UrlValue({ url, title, owner, state = "ok", peek = true }) {
14668
14669
  ...ok ? { primary: { label: "Open", onSelect: () => (0, import_outbound2.openOutbound)(parsed.href) } } : {},
14669
14670
  copyData: { url: parsed.href ?? url, domain: parsed.domain, ...title ? { title } : {} }
14670
14671
  };
14671
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(ValueShell, { kind: "link", glyph: GlobeIcon, text: parsed.display, copy: parsed.href ?? url, state, record, peek });
14672
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(ValueShell, { kind: "link", ...icon ? { glyph: GlobeIcon } : {}, text: parsed.display, copy: parsed.href ?? url, state, record, peek });
14672
14673
  }
14673
- function ContactValue({ type, value, platform, followers, title, ...common }) {
14674
+ function ContactValue({ type, value, platform, followers, title, icon, ...common }) {
14674
14675
  switch (type) {
14675
14676
  case "email":
14676
14677
  return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(EmailValue, { email: value, ...common });
@@ -14681,7 +14682,7 @@ function ContactValue({ type, value, platform, followers, title, ...common }) {
14681
14682
  case "social":
14682
14683
  return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(SocialHandleValue, { value, ...platform !== void 0 ? { platform } : {}, ...followers !== void 0 ? { followers } : {}, ...common });
14683
14684
  case "url":
14684
- return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(UrlValue, { url: value, ...title !== void 0 ? { title } : {}, ...common });
14685
+ return /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(UrlValue, { url: value, ...title !== void 0 ? { title } : {}, ...icon !== void 0 ? { icon } : {}, ...common });
14685
14686
  }
14686
14687
  }
14687
14688
 
@@ -14871,6 +14872,7 @@ var React64 = __toESM(require("react"), 1);
14871
14872
  var import_react_slot7 = require("@radix-ui/react-slot");
14872
14873
  init_controls();
14873
14874
  init_icons();
14875
+ init_dropdown_menu();
14874
14876
  init_use_is_mobile();
14875
14877
  var import_jsx_runtime95 = require("react/jsx-runtime");
14876
14878
  function AssistPeekCard({
@@ -14887,8 +14889,10 @@ function AssistPeekCard({
14887
14889
  stopShowing,
14888
14890
  deciding = false,
14889
14891
  onNotNow,
14892
+ closeAs = "not-now",
14890
14893
  step
14891
14894
  }) {
14895
+ const closeLabel = closeAs === "dismiss" ? "Dismiss" : "Not now";
14892
14896
  const laterDoor = later?.length ? { kind: "action", id: "later", label: "Later", icon: ClockIcon, menu: later, busy: deciding } : null;
14893
14897
  const stopDoor = stopShowing?.length ? { kind: "action", id: "stop", label: "Stop showing", icon: BellOffIcon, menu: stopShowing, busy: deciding } : null;
14894
14898
  const doors = laterDoor && stopDoor ? [laterDoor, stopDoor] : laterDoor ? [laterDoor] : stopDoor ? [stopDoor] : [];
@@ -14899,7 +14903,7 @@ function AssistPeekCard({
14899
14903
  title,
14900
14904
  leading: Icon3 ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(Icon3, {}) : void 0,
14901
14905
  subtitle,
14902
- trailing: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(Button2, { type: "button", variant: "quiet", "aria-label": "Not now", title: "Not now", icon: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(XIcon, {}), disabled: Boolean(primary.busy) || deciding, onClick: onNotNow })
14906
+ trailing: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(Button2, { type: "button", variant: "quiet", "aria-label": closeLabel, title: closeLabel, icon: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(XIcon, {}), disabled: Boolean(primary.busy) || deciding, onClick: onNotNow })
14903
14907
  }
14904
14908
  ),
14905
14909
  /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(PeekCardBody, { children: [
@@ -15000,6 +15004,131 @@ function AssistPeekHover({ trigger, label, side = "top", align = "end", presenta
15000
15004
  }
15001
15005
  );
15002
15006
  }
15007
+ var TRAY_CLOSE_MS = 300;
15008
+ var TRAY_OPEN_MS = 500;
15009
+ function AssistTray({ count, children, quickQuiet, menu, allAssists, onHandlePointerDown, reminderAttributes, open: openProp, onOpenChange }) {
15010
+ const [hovered, setHovered] = React64.useState(false);
15011
+ const [keptOwn, setKept] = React64.useState(false);
15012
+ const kept = openProp ?? keptOwn;
15013
+ const open = kept || hovered;
15014
+ const box = React64.useRef(null);
15015
+ const timer = React64.useRef(null);
15016
+ const clear = () => {
15017
+ if (timer.current) clearTimeout(timer.current);
15018
+ timer.current = null;
15019
+ };
15020
+ React64.useEffect(() => clear, []);
15021
+ const setKeep = React64.useCallback(
15022
+ (next) => {
15023
+ setKept(next);
15024
+ onOpenChange?.(next);
15025
+ if (!next) setHovered(false);
15026
+ },
15027
+ [onOpenChange]
15028
+ );
15029
+ const enter = () => {
15030
+ clear();
15031
+ if (!open) timer.current = setTimeout(() => setHovered(true), TRAY_OPEN_MS);
15032
+ };
15033
+ const leave = () => {
15034
+ clear();
15035
+ timer.current = setTimeout(() => {
15036
+ if (document.querySelector("[data-radix-menu-content]")) return;
15037
+ setHovered(false);
15038
+ }, TRAY_CLOSE_MS);
15039
+ };
15040
+ React64.useEffect(() => {
15041
+ if (!kept) return;
15042
+ const onPress = (event) => {
15043
+ if (box.current?.contains(event.target) || inCardMenu(event.target)) return;
15044
+ setKeep(false);
15045
+ };
15046
+ const onKey = (event) => {
15047
+ if (event.key !== "Escape" || document.querySelector("[data-radix-menu-content]")) return;
15048
+ setKeep(false);
15049
+ };
15050
+ document.addEventListener("pointerdown", onPress, true);
15051
+ document.addEventListener("keydown", onKey);
15052
+ return () => {
15053
+ document.removeEventListener("pointerdown", onPress, true);
15054
+ document.removeEventListener("keydown", onKey);
15055
+ };
15056
+ }, [kept, setKeep]);
15057
+ if (count <= 0) return null;
15058
+ const label = `${count} assist${count === 1 ? "" : "s"}`;
15059
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
15060
+ "div",
15061
+ {
15062
+ ref: box,
15063
+ "data-matrx-assist-tray": "",
15064
+ "data-open": open ? "" : void 0,
15065
+ className: "pointer-events-none flex flex-col items-end gap-2 [:root[data-assist-dock-slot=header]_&]:flex-col-reverse",
15066
+ onMouseEnter: enter,
15067
+ onMouseLeave: leave,
15068
+ onPointerDownCapture: (event) => {
15069
+ if (event.target.closest("[data-matrx-assist-peek]")) setKeep(true);
15070
+ },
15071
+ children: [
15072
+ open ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { "data-matrx-assist-tray-stack": "", className: "matrx-peek-scroll pointer-events-auto flex max-h-[min(70dvh,640px)] flex-col items-end gap-2 overflow-y-auto", children: [
15073
+ React64.Children.map(children, (child) => child ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)("div", { className: "shrink-0", children: child }) : null),
15074
+ allAssists || menu?.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)("div", { className: "flex shrink-0 items-center rounded-md border border-border bg-popover shadow-md", children: [
15075
+ allAssists,
15076
+ menu?.length ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(TrayMenu, { menu }) : null
15077
+ ] }) : null
15078
+ ] }) : null,
15079
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(
15080
+ "div",
15081
+ {
15082
+ "data-matrx-assist-tray-reminder": "",
15083
+ ...reminderAttributes,
15084
+ className: "group pointer-events-auto flex items-center rounded-md border border-border bg-popover shadow-md transition-opacity data-[assist-dock-pending]:invisible data-[assist-dock-yield]:pointer-events-none data-[assist-dock-yield]:opacity-30",
15085
+ onPointerDown: onHandlePointerDown,
15086
+ children: [
15087
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
15088
+ Button2,
15089
+ {
15090
+ type: "button",
15091
+ variant: "quiet",
15092
+ icon: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(LightbulbIcon, {}),
15093
+ glyphTone: "primary",
15094
+ "aria-label": open ? `Hide ${label}` : `Show ${label}`,
15095
+ "aria-expanded": open,
15096
+ title: label,
15097
+ onClick: () => setKeep(!kept),
15098
+ children: String(count)
15099
+ }
15100
+ ),
15101
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(
15102
+ Button2,
15103
+ {
15104
+ type: "button",
15105
+ variant: "quiet",
15106
+ removes: true,
15107
+ icon: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(XIcon, {}),
15108
+ "aria-label": quickQuiet.label,
15109
+ title: quickQuiet.label,
15110
+ onClick: () => {
15111
+ setKeep(false);
15112
+ quickQuiet.onQuiet();
15113
+ }
15114
+ }
15115
+ )
15116
+ ]
15117
+ }
15118
+ )
15119
+ ]
15120
+ }
15121
+ );
15122
+ }
15123
+ function TrayMenu({ menu }) {
15124
+ return /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(DropdownMenu, { modal: false, children: [
15125
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(Button2, { type: "button", variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(BellOffIcon, {}), children: "Quiet" }) }),
15126
+ /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(DropdownMenuContent, { align: "end", children: menu.map((group, i) => /* @__PURE__ */ (0, import_jsx_runtime95.jsxs)(React64.Fragment, { children: [
15127
+ group.label ? /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(DropdownMenuLabel, { children: group.label }) : null,
15128
+ group.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime95.jsx)(DropdownMenuItem, { ...item.tone ? { tone: item.tone } : {}, onSelect: () => item.onSelect(), children: item.label }, item.key))
15129
+ ] }, `${group.label ?? ""}-${i}`)) })
15130
+ ] });
15131
+ }
15003
15132
 
15004
15133
  // src/radio-group.tsx
15005
15134
  var RadioGroupPrimitive = __toESM(require("@radix-ui/react-radio-group"), 1);