@wow-two-beta/ui-vue 0.0.3 → 0.0.5
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/chunks/{BackToTopButton.vue_vue_type_script_setup_true_lang-CkxLllEO.js → BackToTopButton.vue_vue_type_script_setup_true_lang-iLYlhK05.js} +11 -5
- package/dist/chunks/BackToTopButton.vue_vue_type_script_setup_true_lang-iLYlhK05.js.map +1 -0
- package/dist/chunks/{Backdrop.vue_vue_type_script_setup_true_lang-DZUhGY9p.js → Backdrop.vue_vue_type_script_setup_true_lang-CKG--_g8.js} +2 -2
- package/dist/chunks/{Backdrop.vue_vue_type_script_setup_true_lang-DZUhGY9p.js.map → Backdrop.vue_vue_type_script_setup_true_lang-CKG--_g8.js.map} +1 -1
- package/dist/chunks/{BottomSheet.vue_vue_type_script_setup_true_lang-CmNoI4BE.js → BottomSheet.vue_vue_type_script_setup_true_lang-CmNaGird.js} +8 -8
- package/dist/chunks/{BottomSheet.vue_vue_type_script_setup_true_lang-CmNoI4BE.js.map → BottomSheet.vue_vue_type_script_setup_true_lang-CmNaGird.js.map} +1 -1
- package/dist/chunks/{ChatComposer.vue_vue_type_script_setup_true_lang-lNcRhKIv.js → ChatComposer.vue_vue_type_script_setup_true_lang-DfeVsj9h.js} +1024 -579
- package/dist/chunks/ChatComposer.vue_vue_type_script_setup_true_lang-DfeVsj9h.js.map +1 -0
- package/dist/chunks/{DateExtensions-QahSUlRy.js → DateExtensions-C6a-h8ji.js} +12 -22
- package/dist/chunks/{DateExtensions-QahSUlRy.js.map → DateExtensions-C6a-h8ji.js.map} +1 -1
- package/dist/chunks/{DismissableLayer.vue_vue_type_script_setup_true_lang-6nRnzsJW.js → DismissableLayer.vue_vue_type_script_setup_true_lang-ptH1ttBL.js} +3 -3
- package/dist/chunks/DismissableLayer.vue_vue_type_script_setup_true_lang-ptH1ttBL.js.map +1 -0
- package/dist/chunks/{DrawerContent.vue_vue_type_script_setup_true_lang-DvvrJdF0.js → DrawerContent.vue_vue_type_script_setup_true_lang-4n5w3lg2.js} +5 -5
- package/dist/chunks/{DrawerContent.vue_vue_type_script_setup_true_lang-DvvrJdF0.js.map → DrawerContent.vue_vue_type_script_setup_true_lang-4n5w3lg2.js.map} +1 -1
- package/dist/chunks/{ModalContent.vue_vue_type_script_setup_true_lang-CLACSqKg.js → ModalContent.vue_vue_type_script_setup_true_lang-Co5jaeXk.js} +5 -5
- package/dist/chunks/{ModalContent.vue_vue_type_script_setup_true_lang-CLACSqKg.js.map → ModalContent.vue_vue_type_script_setup_true_lang-Co5jaeXk.js.map} +1 -1
- package/dist/chunks/{Navbar.vue_vue_type_script_setup_true_lang-Cl2ejukE.js → Navbar.vue_vue_type_script_setup_true_lang-Cy0zvm5d.js} +7 -7
- package/dist/chunks/Navbar.vue_vue_type_script_setup_true_lang-Cy0zvm5d.js.map +1 -0
- package/dist/chunks/{NotificationItem.vue_vue_type_script_setup_true_lang-KC5Iusce.js → NotificationItem.vue_vue_type_script_setup_true_lang-DySfo3fD.js} +5 -5
- package/dist/chunks/{NotificationItem.vue_vue_type_script_setup_true_lang-KC5Iusce.js.map → NotificationItem.vue_vue_type_script_setup_true_lang-DySfo3fD.js.map} +1 -1
- package/dist/chunks/{OptionTileGroup.vue_vue_type_script_setup_true_lang-BGSmXM_u.js → OptionTileGroup.vue_vue_type_script_setup_true_lang-CKSVGCby.js} +51 -30
- package/dist/chunks/OptionTileGroup.vue_vue_type_script_setup_true_lang-CKSVGCby.js.map +1 -0
- package/dist/chunks/{PopoverContent.vue_vue_type_script_setup_true_lang-D-OiGICS.js → PopoverContent.vue_vue_type_script_setup_true_lang-DYd617X5.js} +4 -4
- package/dist/chunks/{PopoverContent.vue_vue_type_script_setup_true_lang-D-OiGICS.js.map → PopoverContent.vue_vue_type_script_setup_true_lang-DYd617X5.js.map} +1 -1
- package/dist/chunks/{Presence-C7IJvh_P.js → Presence-DE4MlrJz.js} +45 -27
- package/dist/chunks/Presence-DE4MlrJz.js.map +1 -0
- package/dist/chunks/{SortableHandle.vue_vue_type_script_setup_true_lang-CWCXGjZG.js → SortableHandle.vue_vue_type_script_setup_true_lang-8WPwGZ5e.js} +141 -130
- package/dist/chunks/SortableHandle.vue_vue_type_script_setup_true_lang-8WPwGZ5e.js.map +1 -0
- package/dist/chunks/{SurfaceStyles-ChdpGRBO.js → SurfaceStyles-B6W7zdMi.js} +2 -2
- package/dist/chunks/{SurfaceStyles-ChdpGRBO.js.map → SurfaceStyles-B6W7zdMi.js.map} +1 -1
- package/dist/chunks/{TableOfContents.vue_vue_type_script_setup_true_lang-HVL4lg_f.js → TableOfContents.vue_vue_type_script_setup_true_lang-C9eM0AoG.js} +18 -20
- package/dist/chunks/TableOfContents.vue_vue_type_script_setup_true_lang-C9eM0AoG.js.map +1 -0
- package/dist/chunks/{Tones-CI65uuq9.js → Tones-WKBNZ_u2.js} +39 -17
- package/dist/chunks/Tones-WKBNZ_u2.js.map +1 -0
- package/dist/chunks/{index-BD7H9CkO.js → index-CEoYQiWL.js} +3 -3
- package/dist/chunks/{index-BD7H9CkO.js.map → index-CEoYQiWL.js.map} +1 -1
- package/dist/chunks/{index-Cbydgcdk.js → index-op-kbVUk.js} +3 -3
- package/dist/chunks/{index-Cbydgcdk.js.map → index-op-kbVUk.js.map} +1 -1
- package/dist/foundation/primitives/index.js +3 -3
- package/dist/foundation/primitives/presence/Presence.d.ts +4 -0
- package/dist/foundation/utils/index.js +3 -3
- package/dist/index.js +111 -109
- package/dist/presentation/actions/index.js +2 -2
- package/dist/presentation/actions/speedDial/SpeedDialAction.vue.d.ts +6 -5
- package/dist/presentation/actions/speedDial/index.d.ts +3 -5
- package/dist/presentation/display/audioWaveform/AudioWaveform.vue.d.ts +1 -0
- package/dist/presentation/display/diffViewer/DiffViewer.vue.d.ts +2 -0
- package/dist/presentation/display/eventCalendar/EventCalendar.vue.d.ts +1 -0
- package/dist/presentation/display/frameGlyph/FrameGlyph.vue.d.ts +2 -0
- package/dist/presentation/display/gantt/Gantt.vue.d.ts +1 -0
- package/dist/presentation/display/heatmapCalendar/HeatmapCalendar.vue.d.ts +1 -0
- package/dist/presentation/display/index.js +98 -96
- package/dist/presentation/display/list/ListContext.d.ts +16 -0
- package/dist/presentation/display/list/ListItem.vue.d.ts +7 -1
- package/dist/presentation/display/list/index.d.ts +1 -0
- package/dist/presentation/display/metricChip/MetricChip.vue.d.ts +1 -1
- package/dist/presentation/display/moduleGlyphs/CellsGlyph.vue.d.ts +1 -0
- package/dist/presentation/display/radiusGlyph/RadiusGlyph.vue.d.ts +1 -0
- package/dist/presentation/display/reactionBar/ReactionBar.vue.d.ts +1 -0
- package/dist/presentation/feedback/index.js +1 -1
- package/dist/presentation/feedback/tour/Tour.vue.d.ts +1 -0
- package/dist/presentation/forms/TimeColumns.vue.d.ts +22 -0
- package/dist/presentation/forms/dateField/DateField.vue.d.ts +12 -0
- package/dist/presentation/forms/dateTimeField/DateTimeField.vue.d.ts +17 -0
- package/dist/presentation/forms/index.js +2 -2
- package/dist/presentation/forms/multiSelect/MultiSelect.vue.d.ts +8 -0
- package/dist/presentation/forms/multiSelect/MultiSelectContext.d.ts +9 -0
- package/dist/presentation/forms/multiSelect/MultiSelectTags.vue.d.ts +10 -0
- package/dist/presentation/forms/multiSelect/MultiSelectTrigger.vue.d.ts +5 -0
- package/dist/presentation/forms/timeField/TimeField.vue.d.ts +20 -5
- package/dist/presentation/forms/timePicker/TimePicker.vue.d.ts +5 -5
- package/dist/presentation/layout/index.js +1 -1
- package/dist/presentation/nav/index.js +1 -1
- package/dist/presentation/overlays/index.js +5 -5
- package/package.json +3 -2
- package/dist/chunks/BackToTopButton.vue_vue_type_script_setup_true_lang-CkxLllEO.js.map +0 -1
- package/dist/chunks/ChatComposer.vue_vue_type_script_setup_true_lang-lNcRhKIv.js.map +0 -1
- package/dist/chunks/DismissableLayer.vue_vue_type_script_setup_true_lang-6nRnzsJW.js.map +0 -1
- package/dist/chunks/Navbar.vue_vue_type_script_setup_true_lang-Cl2ejukE.js.map +0 -1
- package/dist/chunks/OptionTileGroup.vue_vue_type_script_setup_true_lang-BGSmXM_u.js.map +0 -1
- package/dist/chunks/Presence-C7IJvh_P.js.map +0 -1
- package/dist/chunks/SortableHandle.vue_vue_type_script_setup_true_lang-CWCXGjZG.js.map +0 -1
- package/dist/chunks/TableOfContents.vue_vue_type_script_setup_true_lang-HVL4lg_f.js.map +0 -1
- package/dist/chunks/Tones-CI65uuq9.js.map +0 -1
|
@@ -4,7 +4,7 @@ import { u as useControlled } from "./useControlled-B6M4kTLn.js";
|
|
|
4
4
|
import { c as cn } from "./cn-CzDCF-Ah.js";
|
|
5
5
|
import { u as useFormControl } from "./FormControlContext-B71MFW26.js";
|
|
6
6
|
import { _ as _sfc_main$6 } from "./Spinner.vue_vue_type_script_setup_true_lang-BAepBy2n.js";
|
|
7
|
-
import { T as Tones } from "./Tones-
|
|
7
|
+
import { T as Tones } from "./Tones-WKBNZ_u2.js";
|
|
8
8
|
import { tv } from "tailwind-variants";
|
|
9
9
|
import { P as PressExtensions } from "./PressExtensions-DXqhjlR2.js";
|
|
10
10
|
import { B as ButtonType, H as HtmlElement } from "./HtmlExtensions-jlKY5f9C.js";
|
|
@@ -125,39 +125,53 @@ const buttonVariants = tv({
|
|
|
125
125
|
{ variant: "soft", tone: "danger", class: "bg-destructive-soft text-destructive-soft-foreground hover:bg-destructive-soft/80 active:bg-destructive-soft/85" },
|
|
126
126
|
{ variant: "soft", tone: "success", class: "bg-success-soft text-success-soft-foreground hover:bg-success-soft/80 active:bg-success-soft/85" },
|
|
127
127
|
{ variant: "soft", tone: "warning", class: "bg-warning-soft text-warning-soft-foreground hover:bg-warning-soft/80 active:bg-warning-soft/85" },
|
|
128
|
+
/*
|
|
129
|
+
* `text-{tone}-soft-foreground`, not `text-{tone}`, everywhere the fill is transparent or
|
|
130
|
+
* a light tint (surface · outline · ghost · reveal · link below).
|
|
131
|
+
*
|
|
132
|
+
* `text-{tone}` is the SOLID-fill accent: it is picked to carry the tone at full strength
|
|
133
|
+
* against its own opaque background, and on a light surface it is simply too light —
|
|
134
|
+
* `outline/warning` measured 1.85:1 and `surface/warning` 1.72:1 on this file's own
|
|
135
|
+
* `theme-smart-qr` card. `--color-{tone}-soft-foreground` is the token minted for exactly
|
|
136
|
+
* this pairing, and the `soft` rows below have always used it; these rows were the ones
|
|
137
|
+
* that were missed. Borders stay full-strength `{tone}` so the tone still reads.
|
|
138
|
+
* Matches `foundation/utils/Tones.ts`, which routes `soft` + `outline` the same way.
|
|
139
|
+
*/
|
|
128
140
|
// === SURFACE × tone (subtle tinted bg + visible tone-colored border) ===
|
|
129
|
-
{ variant: "surface", tone: "primary", class: "bg-primary/5 border-primary/40 text-primary hover:bg-primary/10 active:bg-primary/15" },
|
|
141
|
+
{ variant: "surface", tone: "primary", class: "bg-primary/5 border-primary/40 text-primary-soft-foreground hover:bg-primary/10 active:bg-primary/15" },
|
|
130
142
|
{ variant: "surface", tone: "neutral", class: "bg-muted/30 border-border-strong text-foreground hover:bg-muted/50 active:bg-muted/70" },
|
|
131
|
-
{ variant: "surface", tone: "danger", class: "bg-destructive/5 border-destructive/40 text-destructive hover:bg-destructive/10 active:bg-destructive/15" },
|
|
132
|
-
{ variant: "surface", tone: "success", class: "bg-success/5 border-success/40 text-success hover:bg-success/10 active:bg-success/15" },
|
|
133
|
-
{ variant: "surface", tone: "warning", class: "bg-warning/10 border-warning/40 text-warning hover:bg-warning/15 active:bg-warning/20" },
|
|
143
|
+
{ variant: "surface", tone: "danger", class: "bg-destructive/5 border-destructive/40 text-destructive-soft-foreground hover:bg-destructive/10 active:bg-destructive/15" },
|
|
144
|
+
{ variant: "surface", tone: "success", class: "bg-success/5 border-success/40 text-success-soft-foreground hover:bg-success/10 active:bg-success/15" },
|
|
145
|
+
{ variant: "surface", tone: "warning", class: "bg-warning/10 border-warning/40 text-warning-soft-foreground hover:bg-warning/15 active:bg-warning/20" },
|
|
134
146
|
// === OUTLINE × tone ===
|
|
135
|
-
{ variant: "outline", tone: "primary", class: "border-primary/50 text-primary hover:bg-primary/10 active:bg-primary/15" },
|
|
147
|
+
{ variant: "outline", tone: "primary", class: "border-primary/50 text-primary-soft-foreground hover:bg-primary/10 active:bg-primary/15" },
|
|
136
148
|
{ variant: "outline", tone: "neutral", class: "border-border-strong text-foreground hover:bg-muted/50 active:bg-muted/70" },
|
|
137
|
-
{ variant: "outline", tone: "danger", class: "border-destructive/50 text-destructive hover:bg-destructive/10 active:bg-destructive/15" },
|
|
138
|
-
{ variant: "outline", tone: "success", class: "border-success/50 text-success hover:bg-success/10 active:bg-success/15" },
|
|
139
|
-
{ variant: "outline", tone: "warning", class: "border-warning/60 text-warning hover:bg-warning/10 active:bg-warning/15" },
|
|
149
|
+
{ variant: "outline", tone: "danger", class: "border-destructive/50 text-destructive-soft-foreground hover:bg-destructive/10 active:bg-destructive/15" },
|
|
150
|
+
{ variant: "outline", tone: "success", class: "border-success/50 text-success-soft-foreground hover:bg-success/10 active:bg-success/15" },
|
|
151
|
+
{ variant: "outline", tone: "warning", class: "border-warning/60 text-warning-soft-foreground hover:bg-warning/10 active:bg-warning/15" },
|
|
140
152
|
// === GHOST × tone ===
|
|
141
|
-
{ variant: "ghost", tone: "primary", class: "text-primary hover:bg-primary/10 active:bg-primary/15" },
|
|
153
|
+
{ variant: "ghost", tone: "primary", class: "text-primary-soft-foreground hover:bg-primary/10 active:bg-primary/15" },
|
|
142
154
|
{ variant: "ghost", tone: "neutral", class: "text-foreground hover:bg-foreground/10 active:bg-foreground/15" },
|
|
143
|
-
{ variant: "ghost", tone: "danger", class: "text-destructive hover:bg-destructive/10 active:bg-destructive/15" },
|
|
144
|
-
{ variant: "ghost", tone: "success", class: "text-success hover:bg-success/10 active:bg-success/15" },
|
|
145
|
-
{ variant: "ghost", tone: "warning", class: "text-warning hover:bg-warning/10 active:bg-warning/15" },
|
|
155
|
+
{ variant: "ghost", tone: "danger", class: "text-destructive-soft-foreground hover:bg-destructive/10 active:bg-destructive/15" },
|
|
156
|
+
{ variant: "ghost", tone: "success", class: "text-success-soft-foreground hover:bg-success/10 active:bg-success/15" },
|
|
157
|
+
{ variant: "ghost", tone: "warning", class: "text-warning-soft-foreground hover:bg-warning/10 active:bg-warning/15" },
|
|
146
158
|
// === REVEAL × tone (idle: muted transparent · hover/focus-visible: bordered chip revealed) ===
|
|
147
159
|
// Idle text sits at reduced emphasis (muted-foreground / tone-tinted); hover & focus-visible
|
|
148
160
|
// resolve the border + a surface background + full-emphasis foreground so a bordered chip
|
|
149
161
|
// "appears". neutral is the common case (borderless icon affordance).
|
|
150
|
-
|
|
162
|
+
/* The `/70` idle alpha is the intended de-emphasis and is kept; only the token under it
|
|
163
|
+
changes, which is what lifts idle `warning` off 1.56:1. */
|
|
164
|
+
{ variant: "reveal", tone: "primary", class: "text-primary-soft-foreground/70 hover:border-border hover:bg-background hover:text-primary-soft-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-primary-soft-foreground active:bg-muted/70" },
|
|
151
165
|
{ variant: "reveal", tone: "neutral", class: "text-muted-foreground hover:border-border hover:bg-background hover:text-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-foreground active:bg-muted/70" },
|
|
152
|
-
{ variant: "reveal", tone: "danger", class: "text-destructive/70 hover:border-border hover:bg-background hover:text-destructive focus-visible:border-border focus-visible:bg-background focus-visible:text-destructive active:bg-muted/70" },
|
|
153
|
-
{ variant: "reveal", tone: "success", class: "text-success/70 hover:border-border hover:bg-background hover:text-success focus-visible:border-border focus-visible:bg-background focus-visible:text-success active:bg-muted/70" },
|
|
154
|
-
{ variant: "reveal", tone: "warning", class: "text-warning/70 hover:border-border hover:bg-background hover:text-warning focus-visible:border-border focus-visible:bg-background focus-visible:text-warning active:bg-muted/70" },
|
|
166
|
+
{ variant: "reveal", tone: "danger", class: "text-destructive-soft-foreground/70 hover:border-border hover:bg-background hover:text-destructive-soft-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-destructive-soft-foreground active:bg-muted/70" },
|
|
167
|
+
{ variant: "reveal", tone: "success", class: "text-success-soft-foreground/70 hover:border-border hover:bg-background hover:text-success-soft-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-success-soft-foreground active:bg-muted/70" },
|
|
168
|
+
{ variant: "reveal", tone: "warning", class: "text-warning-soft-foreground/70 hover:border-border hover:bg-background hover:text-warning-soft-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-warning-soft-foreground active:bg-muted/70" },
|
|
155
169
|
// === LINK × tone (h/padding/radius cleared by variant) ===
|
|
156
|
-
{ variant: "link", tone: "primary", class: "text-primary" },
|
|
170
|
+
{ variant: "link", tone: "primary", class: "text-primary-soft-foreground" },
|
|
157
171
|
{ variant: "link", tone: "neutral", class: "text-foreground" },
|
|
158
|
-
{ variant: "link", tone: "danger", class: "text-destructive" },
|
|
159
|
-
{ variant: "link", tone: "success", class: "text-success" },
|
|
160
|
-
{ variant: "link", tone: "warning", class: "text-warning" },
|
|
172
|
+
{ variant: "link", tone: "danger", class: "text-destructive-soft-foreground" },
|
|
173
|
+
{ variant: "link", tone: "success", class: "text-success-soft-foreground" },
|
|
174
|
+
{ variant: "link", tone: "warning", class: "text-warning-soft-foreground" },
|
|
161
175
|
// === GLASS / GLASS-SURFACE × tone ===
|
|
162
176
|
// neutral = the image-overlay default: fixed dark wash + light text (reads over any imagery).
|
|
163
177
|
{ variant: ["glass", "glass-surface"], tone: "neutral", class: "bg-black/45 text-white/70 hover:bg-black/65 hover:text-white active:bg-black/75" },
|
|
@@ -561,12 +575,19 @@ const toggleButtonVariants = tv({
|
|
|
561
575
|
}
|
|
562
576
|
},
|
|
563
577
|
compoundVariants: [
|
|
578
|
+
/*
|
|
579
|
+
* Pressed text is `-soft-foreground`, not `{tone}`, for `ghost` and `outline`: both keep a
|
|
580
|
+
* transparent fill, so the pressed label lands on the host surface where the full-strength
|
|
581
|
+
* accent is too light — `ghost/warning` measured 1.85:1 pressed. The `soft` rows below
|
|
582
|
+
* already resolved it this way; these two were missed. Same fix as `Button.variants.ts`
|
|
583
|
+
* and `foundation/utils/Tones.ts`. Borders keep full-strength `{tone}`.
|
|
584
|
+
*/
|
|
564
585
|
// === GHOST × tone — text color only, transparent bg ===
|
|
565
|
-
{ variant: "ghost", tone: "primary", class: "text-foreground/50 data-[pressed=true]:text-primary" },
|
|
586
|
+
{ variant: "ghost", tone: "primary", class: "text-foreground/50 data-[pressed=true]:text-primary-soft-foreground" },
|
|
566
587
|
{ variant: "ghost", tone: "neutral", class: "text-foreground/50 data-[pressed=true]:text-foreground" },
|
|
567
|
-
{ variant: "ghost", tone: "danger", class: "text-foreground/50 data-[pressed=true]:text-destructive" },
|
|
568
|
-
{ variant: "ghost", tone: "success", class: "text-foreground/50 data-[pressed=true]:text-success" },
|
|
569
|
-
{ variant: "ghost", tone: "warning", class: "text-foreground/50 data-[pressed=true]:text-warning" },
|
|
588
|
+
{ variant: "ghost", tone: "danger", class: "text-foreground/50 data-[pressed=true]:text-destructive-soft-foreground" },
|
|
589
|
+
{ variant: "ghost", tone: "success", class: "text-foreground/50 data-[pressed=true]:text-success-soft-foreground" },
|
|
590
|
+
{ variant: "ghost", tone: "warning", class: "text-foreground/50 data-[pressed=true]:text-warning-soft-foreground" },
|
|
570
591
|
// === SOFT × tone — pressed gets tone-soft bg ===
|
|
571
592
|
{ variant: "soft", tone: "primary", class: "text-foreground/70 data-[pressed=true]:bg-primary-soft data-[pressed=true]:text-primary-soft-foreground" },
|
|
572
593
|
{ variant: "soft", tone: "neutral", class: "text-foreground/70 data-[pressed=true]:bg-muted data-[pressed=true]:text-foreground" },
|
|
@@ -574,11 +595,11 @@ const toggleButtonVariants = tv({
|
|
|
574
595
|
{ variant: "soft", tone: "success", class: "text-foreground/70 data-[pressed=true]:bg-success-soft data-[pressed=true]:text-success-soft-foreground" },
|
|
575
596
|
{ variant: "soft", tone: "warning", class: "text-foreground/70 data-[pressed=true]:bg-warning-soft data-[pressed=true]:text-warning-soft-foreground" },
|
|
576
597
|
// === OUTLINE × tone — pressed swaps to tone border + tone text ===
|
|
577
|
-
{ variant: "outline", tone: "primary", class: "border-input text-foreground/70 data-[pressed=true]:border-primary data-[pressed=true]:text-primary" },
|
|
598
|
+
{ variant: "outline", tone: "primary", class: "border-input text-foreground/70 data-[pressed=true]:border-primary data-[pressed=true]:text-primary-soft-foreground" },
|
|
578
599
|
{ variant: "outline", tone: "neutral", class: "border-input text-foreground/70 data-[pressed=true]:border-foreground data-[pressed=true]:text-foreground" },
|
|
579
|
-
{ variant: "outline", tone: "danger", class: "border-input text-foreground/70 data-[pressed=true]:border-destructive data-[pressed=true]:text-destructive" },
|
|
580
|
-
{ variant: "outline", tone: "success", class: "border-input text-foreground/70 data-[pressed=true]:border-success data-[pressed=true]:text-success" },
|
|
581
|
-
{ variant: "outline", tone: "warning", class: "border-input text-foreground/70 data-[pressed=true]:border-warning data-[pressed=true]:text-warning" },
|
|
600
|
+
{ variant: "outline", tone: "danger", class: "border-input text-foreground/70 data-[pressed=true]:border-destructive data-[pressed=true]:text-destructive-soft-foreground" },
|
|
601
|
+
{ variant: "outline", tone: "success", class: "border-input text-foreground/70 data-[pressed=true]:border-success data-[pressed=true]:text-success-soft-foreground" },
|
|
602
|
+
{ variant: "outline", tone: "warning", class: "border-input text-foreground/70 data-[pressed=true]:border-warning data-[pressed=true]:text-warning-soft-foreground" },
|
|
582
603
|
// === SOLID × tone — pressed fills with tone ===
|
|
583
604
|
{ variant: "solid", tone: "primary", class: "border-input bg-background text-foreground/70 data-[pressed=true]:bg-primary data-[pressed=true]:border-primary data-[pressed=true]:text-primary-foreground" },
|
|
584
605
|
{ variant: "solid", tone: "neutral", class: "border-input bg-background text-foreground/70 data-[pressed=true]:bg-foreground data-[pressed=true]:border-foreground data-[pressed=true]:text-background" },
|
|
@@ -940,4 +961,4 @@ export {
|
|
|
940
961
|
optionTileGroupVariants as o,
|
|
941
962
|
toggleButtonVariants as t
|
|
942
963
|
};
|
|
943
|
-
//# sourceMappingURL=OptionTileGroup.vue_vue_type_script_setup_true_lang-
|
|
964
|
+
//# sourceMappingURL=OptionTileGroup.vue_vue_type_script_setup_true_lang-CKSVGCby.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OptionTileGroup.vue_vue_type_script_setup_true_lang-CKSVGCby.js","sources":["../../src/presentation/actions/button/Button.variants.ts","../../src/presentation/actions/button/Button.vue","../../src/presentation/actions/toggleButtonGroup/ToggleButtonGroupContext.ts","../../src/presentation/actions/toggleButtonGroup/ToggleButtonGroup.variants.ts","../../src/presentation/actions/toggleButton/ToggleButton.variants.ts","../../src/presentation/actions/toggleButton/ToggleButton.vue","../../src/presentation/actions/toggleButtonGroup/ToggleButtonGroup.vue","../../src/presentation/actions/optionTile/OptionTile.variants.ts","../../src/presentation/actions/optionTile/OptionTile.vue","../../src/presentation/forms/fieldset/Fieldset.vue","../../src/presentation/actions/optionTileGroup/OptionTileGroup.variants.ts","../../src/presentation/actions/optionTileGroup/OptionTileGroup.vue"],"sourcesContent":["import { tv, Tones, ColorTone, type VariantProps } from '../../../foundation/utils';\n\n/** Defines the Button visual surface style. */\nexport const ButtonVariant = {\n /** Refers to an opaque, filled surface. */\n Solid: 'solid',\n /** Refers to a muted/tinted fill. */\n Soft: 'soft',\n /** Refers to a subtle tinted fill + tone-colored border. */\n Surface: 'surface',\n /** Refers to a transparent fill + tone border. */\n Outline: 'outline',\n /** Refers to a borderless, transparent-at-rest button. */\n Ghost: 'ghost',\n /** Refers to a borderless button that reveals a bordered chip on hover/focus. */\n Reveal: 'reveal',\n /** Refers to an inline text link. */\n Link: 'link',\n /** Refers to a translucent glass wash + blur. */\n Glass: 'glass',\n /** Refers to a glass surface with a hairline border. */\n GlassSurface: 'glass-surface',\n} as const;\n\nexport type ButtonVariant = (typeof ButtonVariant)[keyof typeof ButtonVariant];\n\n/** Defines the Button silhouette. */\nexport const ButtonShape = {\n /** Refers to the default (text-width) shape. */\n Default: 'default',\n /** Refers to a square (1:1) icon shape. */\n Square: 'square',\n /** Refers to a circular icon shape. */\n Circle: 'circle',\n} as const;\n\nexport type ButtonShape = (typeof ButtonShape)[keyof typeof ButtonShape];\n\n/** Button visual surface — see Button.standard.md + Button.spec.md. */\nexport const buttonVariants = tv({\n base: [\n // layout\n 'group inline-flex items-center justify-center gap-2',\n // typography\n 'font-medium align-middle',\n // borders (forced-colors fallback)\n 'border border-transparent',\n 'forced-colors:border-[ButtonBorder]',\n // transitions (color only)\n 'transition-colors duration-150 ease-out',\n 'motion-reduce:transition-none',\n // focus\n 'outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',\n // disabled (native attr handles click-blocking; pointer-events-none would\n // suppress the cursor visual, so we don't add it here)\n 'disabled:opacity-50 disabled:cursor-not-allowed',\n // skeleton state — wins over everything\n 'data-[state=skeleton]:!bg-muted data-[state=skeleton]:!text-transparent data-[state=skeleton]:!border-transparent data-[state=skeleton]:!cursor-default data-[state=skeleton]:!pointer-events-none data-[state=skeleton]:animate-pulse',\n 'data-[state=skeleton]:[&>*]:!invisible',\n ],\n variants: {\n variant: {\n solid: '',\n soft: '',\n surface: '',\n outline: 'bg-transparent',\n ghost: 'bg-transparent',\n // Borderless + transparent at rest; on hover / focus-visible a bordered chip is\n // revealed (border + bg + foreground text). Per-tone reveal target set via\n // compoundVariants below. Pairs with `hoverSlot` for the icon-swap affordance.\n reveal: 'bg-transparent border-transparent',\n link: 'bg-transparent !h-auto !p-0 !rounded-none underline-offset-4 hover:underline focus-visible:ring-offset-0',\n // Base = neutral/default tone: dark image-overlay wash + blur. Non-neutral tones resolve\n // through the shared `Tones.glass` palette via compoundVariants below (so tone + color\n // overrides apply). `backdrop-blur-md` stays here for every tone.\n glass: 'backdrop-blur-md',\n 'glass-surface': 'backdrop-blur-md border-white/10',\n },\n tone: {\n primary: '',\n neutral: '',\n danger: '',\n success: '',\n warning: '',\n },\n size: {\n // min-h/min-w floor keeps the hit-target ≥ 24×24 (WCAG 2.2 SC 2.5.8) even when\n // --ui-density-scale < 1 would otherwise shrink it below the floor. Applies to\n // square/circle xs too (the min-h sets the box height; min-w the width).\n xs: 'h-[calc(1.5rem*var(--ui-density-scale,1))] min-h-6 min-w-6 px-[calc(0.5rem*var(--ui-density-scale,1))] text-xs rounded-sm gap-1',\n sm: 'h-[calc(2rem*var(--ui-density-scale,1))] px-[calc(0.75rem*var(--ui-density-scale,1))] text-sm rounded-md gap-1.5',\n md: 'h-[calc(2.5rem*var(--ui-density-scale,1))] px-[calc(1rem*var(--ui-density-scale,1))] text-sm rounded-md gap-2',\n lg: 'h-[calc(3rem*var(--ui-density-scale,1))] px-[calc(1.5rem*var(--ui-density-scale,1))] text-base rounded-lg gap-2',\n xl: 'h-[calc(3.5rem*var(--ui-density-scale,1))] px-[calc(2rem*var(--ui-density-scale,1))] text-base rounded-lg gap-2.5',\n },\n shape: {\n default: '',\n square: 'aspect-square !px-0',\n circle: 'aspect-square !px-0 !rounded-full',\n },\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n wrap: {\n true: 'whitespace-normal text-left',\n false: 'whitespace-nowrap text-ellipsis overflow-hidden',\n },\n },\n compoundVariants: [\n // === SOLID × tone ===\n { variant: 'solid', tone: 'primary', class: 'bg-primary text-primary-foreground hover:bg-primary/90 active:bg-primary/95' },\n { variant: 'solid', tone: 'neutral', class: 'bg-muted text-foreground hover:bg-muted/80 active:bg-muted/85' },\n { variant: 'solid', tone: 'danger', class: 'bg-destructive text-destructive-foreground hover:bg-destructive/90 active:bg-destructive/95' },\n { variant: 'solid', tone: 'success', class: 'bg-success text-success-foreground hover:bg-success/90 active:bg-success/95' },\n { variant: 'solid', tone: 'warning', class: 'bg-warning text-warning-foreground hover:bg-warning/90 active:bg-warning/95' },\n\n // === SOFT × tone ===\n { variant: 'soft', tone: 'primary', class: 'bg-primary-soft text-primary-soft-foreground hover:bg-primary-soft/80 active:bg-primary-soft/85' },\n { variant: 'soft', tone: 'neutral', class: 'bg-muted/60 text-foreground hover:bg-muted/80 active:bg-muted/85' },\n { variant: 'soft', tone: 'danger', class: 'bg-destructive-soft text-destructive-soft-foreground hover:bg-destructive-soft/80 active:bg-destructive-soft/85' },\n { variant: 'soft', tone: 'success', class: 'bg-success-soft text-success-soft-foreground hover:bg-success-soft/80 active:bg-success-soft/85' },\n { variant: 'soft', tone: 'warning', class: 'bg-warning-soft text-warning-soft-foreground hover:bg-warning-soft/80 active:bg-warning-soft/85' },\n\n /*\n * `text-{tone}-soft-foreground`, not `text-{tone}`, everywhere the fill is transparent or\n * a light tint (surface · outline · ghost · reveal · link below).\n *\n * `text-{tone}` is the SOLID-fill accent: it is picked to carry the tone at full strength\n * against its own opaque background, and on a light surface it is simply too light —\n * `outline/warning` measured 1.85:1 and `surface/warning` 1.72:1 on this file's own\n * `theme-smart-qr` card. `--color-{tone}-soft-foreground` is the token minted for exactly\n * this pairing, and the `soft` rows below have always used it; these rows were the ones\n * that were missed. Borders stay full-strength `{tone}` so the tone still reads.\n * Matches `foundation/utils/Tones.ts`, which routes `soft` + `outline` the same way.\n */\n // === SURFACE × tone (subtle tinted bg + visible tone-colored border) ===\n { variant: 'surface', tone: 'primary', class: 'bg-primary/5 border-primary/40 text-primary-soft-foreground hover:bg-primary/10 active:bg-primary/15' },\n { variant: 'surface', tone: 'neutral', class: 'bg-muted/30 border-border-strong text-foreground hover:bg-muted/50 active:bg-muted/70' },\n { variant: 'surface', tone: 'danger', class: 'bg-destructive/5 border-destructive/40 text-destructive-soft-foreground hover:bg-destructive/10 active:bg-destructive/15' },\n { variant: 'surface', tone: 'success', class: 'bg-success/5 border-success/40 text-success-soft-foreground hover:bg-success/10 active:bg-success/15' },\n { variant: 'surface', tone: 'warning', class: 'bg-warning/10 border-warning/40 text-warning-soft-foreground hover:bg-warning/15 active:bg-warning/20' },\n\n // === OUTLINE × tone ===\n { variant: 'outline', tone: 'primary', class: 'border-primary/50 text-primary-soft-foreground hover:bg-primary/10 active:bg-primary/15' },\n { variant: 'outline', tone: 'neutral', class: 'border-border-strong text-foreground hover:bg-muted/50 active:bg-muted/70' },\n { variant: 'outline', tone: 'danger', class: 'border-destructive/50 text-destructive-soft-foreground hover:bg-destructive/10 active:bg-destructive/15' },\n { variant: 'outline', tone: 'success', class: 'border-success/50 text-success-soft-foreground hover:bg-success/10 active:bg-success/15' },\n { variant: 'outline', tone: 'warning', class: 'border-warning/60 text-warning-soft-foreground hover:bg-warning/10 active:bg-warning/15' },\n\n // === GHOST × tone ===\n { variant: 'ghost', tone: 'primary', class: 'text-primary-soft-foreground hover:bg-primary/10 active:bg-primary/15' },\n { variant: 'ghost', tone: 'neutral', class: 'text-foreground hover:bg-foreground/10 active:bg-foreground/15' },\n { variant: 'ghost', tone: 'danger', class: 'text-destructive-soft-foreground hover:bg-destructive/10 active:bg-destructive/15' },\n { variant: 'ghost', tone: 'success', class: 'text-success-soft-foreground hover:bg-success/10 active:bg-success/15' },\n { variant: 'ghost', tone: 'warning', class: 'text-warning-soft-foreground hover:bg-warning/10 active:bg-warning/15' },\n\n // === REVEAL × tone (idle: muted transparent · hover/focus-visible: bordered chip revealed) ===\n // Idle text sits at reduced emphasis (muted-foreground / tone-tinted); hover & focus-visible\n // resolve the border + a surface background + full-emphasis foreground so a bordered chip\n // \"appears\". neutral is the common case (borderless icon affordance).\n /* The `/70` idle alpha is the intended de-emphasis and is kept; only the token under it\n changes, which is what lifts idle `warning` off 1.56:1. */\n { variant: 'reveal', tone: 'primary', class: 'text-primary-soft-foreground/70 hover:border-border hover:bg-background hover:text-primary-soft-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-primary-soft-foreground active:bg-muted/70' },\n { variant: 'reveal', tone: 'neutral', class: 'text-muted-foreground hover:border-border hover:bg-background hover:text-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-foreground active:bg-muted/70' },\n { variant: 'reveal', tone: 'danger', class: 'text-destructive-soft-foreground/70 hover:border-border hover:bg-background hover:text-destructive-soft-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-destructive-soft-foreground active:bg-muted/70' },\n { variant: 'reveal', tone: 'success', class: 'text-success-soft-foreground/70 hover:border-border hover:bg-background hover:text-success-soft-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-success-soft-foreground active:bg-muted/70' },\n { variant: 'reveal', tone: 'warning', class: 'text-warning-soft-foreground/70 hover:border-border hover:bg-background hover:text-warning-soft-foreground focus-visible:border-border focus-visible:bg-background focus-visible:text-warning-soft-foreground active:bg-muted/70' },\n\n // === LINK × tone (h/padding/radius cleared by variant) ===\n { variant: 'link', tone: 'primary', class: 'text-primary-soft-foreground' },\n { variant: 'link', tone: 'neutral', class: 'text-foreground' },\n { variant: 'link', tone: 'danger', class: 'text-destructive-soft-foreground' },\n { variant: 'link', tone: 'success', class: 'text-success-soft-foreground' },\n { variant: 'link', tone: 'warning', class: 'text-warning-soft-foreground' },\n\n // === GLASS / GLASS-SURFACE × tone ===\n // neutral = the image-overlay default: fixed dark wash + light text (reads over any imagery).\n { variant: ['glass', 'glass-surface'], tone: 'neutral', class: 'bg-black/45 text-white/70 hover:bg-black/65 hover:text-white active:bg-black/75' },\n // Every other tone resolves through the shared `Tones.glass` palette (`bg-{tone}/30 text-{tone}-foreground`)\n // so `tone=\"success\"` etc. AND per-instance `color` overrides actually apply, plus a tone-matched hover/active wash.\n { variant: ['glass', 'glass-surface'], tone: 'primary', class: `${Tones.glass.primary} hover:bg-primary/45 active:bg-primary/55` },\n { variant: ['glass', 'glass-surface'], tone: 'danger', class: `${Tones.glass.danger} hover:bg-destructive/45 active:bg-destructive/55` },\n { variant: ['glass', 'glass-surface'], tone: 'success', class: `${Tones.glass.success} hover:bg-success/45 active:bg-success/55` },\n { variant: ['glass', 'glass-surface'], tone: 'warning', class: `${Tones.glass.warning} hover:bg-warning/45 active:bg-warning/55` },\n // glass-surface non-neutral tones swap the white hairline for a tone-accent border (50% alpha).\n { variant: 'glass-surface', tone: 'primary', class: 'border-primary/50' },\n { variant: 'glass-surface', tone: 'danger', class: 'border-destructive/50' },\n { variant: 'glass-surface', tone: 'success', class: 'border-success/50' },\n { variant: 'glass-surface', tone: 'warning', class: 'border-warning/50' },\n ],\n defaultVariants: {\n variant: 'solid',\n tone: 'primary',\n size: 'md',\n shape: 'default',\n fullWidth: false,\n wrap: false,\n },\n});\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>;\n\n/* Compile-time lock: enum values ≡ tv variant/tone/shape value-sets (drift = type error). */\ntype AssertExact<A, B> = [A] extends [B] ? ([B] extends [A] ? true : never) : never;\nconst _assertButtonVariant: AssertExact<\n ButtonVariant,\n NonNullable<VariantProps<typeof buttonVariants>['variant']>\n> = true;\nconst _assertButtonTone: AssertExact<\n ColorTone,\n NonNullable<VariantProps<typeof buttonVariants>['tone']>\n> = true;\nconst _assertButtonShape: AssertExact<\n ButtonShape,\n NonNullable<VariantProps<typeof buttonVariants>['shape']>\n> = true;\nvoid _assertButtonVariant;\nvoid _assertButtonTone;\nvoid _assertButtonShape;\n","<script lang=\"ts\">\nimport type { ButtonHTMLAttributes, VNodeChild } from 'vue';\nimport type {\n ColorProp,\n ColorTone,\n PaddingProp,\n RadiusProp,\n SizePreset,\n SizeUnion,\n SizeValue,\n} from '../../../foundation/utils';\nimport type { ButtonVariant, ButtonShape, ButtonVariants } from './Button.variants';\n\n/* Named size presets — used for variant lookup. Any other string/number/object flows to box-overrides. Subset of the canonical `SizePreset` vocabulary. */\ntype ButtonSizePreset = Extract<SizePreset, 'xs' | 'sm' | 'md' | 'lg' | 'xl'>;\n\n/* `size`: preset (variant class) | number/string (square inline dims) | `{width,height,minWidth,minHeight,boxSize}`.\n Raw/object forms set inline dims only — pair with `padding` if text-bearing. */\nexport type ButtonSize = SizeUnion<ButtonSizePreset>;\n\n/* Both heritage types are `@vue-ignore`d: they contribute to the *type* surface exactly as in the\n React original, but must not become runtime props. Native button attributes belong in attribute\n fallthrough, and `ButtonVariants` resolves through `typeof buttonVariants`, which the SFC prop\n compiler cannot walk. */\nexport interface ButtonProps\n extends /* @vue-ignore */ Omit<\n ButtonHTMLAttributes,\n 'type' | 'disabled' | 'color' | 'onClick'\n >,\n /* @vue-ignore */ Omit<ButtonVariants, 'size' | 'variant' | 'tone' | 'shape'> {\n /** The visual surface style. */\n variant?: ButtonVariant;\n\n /** The semantic tone palette. */\n tone?: ColorTone;\n\n /** The button silhouette (default · square · circle). */\n shape?: ButtonShape;\n\n /** The size — preset name OR raw value OR explicit dim object; see `ButtonSize` for details. */\n size?: ButtonSize;\n\n /** The per-instance color override for the active `tone`. String → all slots derived; object → per-slot (bg/text/soft/softText/ring). Sets local CSS vars that `bg-{tone}` etc. pick up. */\n color?: ColorProp;\n\n /** The slot before children (logical start). Prefer the `leading` named slot; this prop stays for parity with the React API. */\n leadingSlot?: VNodeChild;\n\n /** The slot after children (logical end). Prefer the `trailing` named slot; this prop stays for parity with the React API. */\n trailingSlot?: VNodeChild;\n\n /** The content shown in place of children on hover / focus-visible (CSS-only swap — no JS hover state).\n Idle → children visible; hover/focus-visible → `hoverSlot` visible. Pairs with `variant=\"reveal\"`\n for a reveal-on-hover icon swap. When undefined (and no `hover` slot), children render normally. */\n hoverSlot?: VNodeChild;\n\n /** The indicator shown in place of the built-in `<Spinner/>` when `isLoading` is true. Prefer the `loading` named slot. */\n loadingSlot?: VNodeChild;\n\n /** The action-loading state — replaces leading w/ spinner, sets aria-busy, blocks clicks. */\n isLoading?: boolean;\n\n /** The text that replaces children when loading. No default — consumer supplies (i18n). */\n loadingText?: string;\n\n /** The content-loading state — hides content (preserves dimensions) + shimmer. Mutually exclusive with `isLoading`. */\n isSkeleton?: boolean;\n\n /** The disabled state — removes from focus order, blocks clicks. Forwards to native `disabled`. Inherited from an enclosing `Field` when omitted. */\n isDisabled?: boolean;\n\n /** The full-width state — stretches to fill container width. */\n isFullWidth?: boolean;\n\n /** The multi-line state — allows label wrap; default truncates to single line. */\n isMultiline?: boolean;\n\n /** The as-child flag — renders as the single child element via `Primitive`'s `asChild` merge. */\n asChild?: boolean;\n\n /** The independent padding override (preset token or `{x, y}` object). */\n padding?: PaddingProp;\n\n /** The independent radius override (preset token or raw value). */\n radius?: RadiusProp;\n\n /** The explicit width override. Number = px; string = any CSS unit. */\n width?: SizeValue;\n\n /** The explicit height override. Number = px; string = any CSS unit. */\n height?: SizeValue;\n\n /** The min width reserved so the button doesn't reflow when its label morphs. */\n minWidth?: SizeValue;\n\n /** The min height reserved — symmetric with `minWidth`. */\n minHeight?: SizeValue;\n\n /** The square-size shorthand — applied as fallback for both `width` and `height`. Explicit `width`/`height` win when both are set. Pairs with `shape=\"square\"` / `shape=\"circle\"` for icon buttons. */\n boxSize?: SizeValue;\n\n /** The button type. Default `ButtonType.Button` — NOT browser-default `'submit'`. */\n type?: ButtonType;\n\n /** The long-press duration (ms). Default 500. Out-of-range values trigger a dev warning. */\n longPressDelay?: number;\n\n /** The click-throttle window (ms) — first wins; subsequent swallowed via `preventDefault()`. */\n debounceMs?: number;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n computed,\n defineComponent,\n getCurrentInstance,\n normalizeStyle,\n onBeforeUnmount,\n useAttrs,\n useSlots,\n useTemplateRef,\n watchEffect,\n type ComponentPublicInstance,\n type StyleValue,\n} from 'vue';\nimport type { ClassValue } from 'clsx';\nimport {\n cn,\n ColorExtensions,\n composeEventHandlers,\n ButtonType,\n CssExtensions,\n HtmlElement,\n IS_DEV,\n Key,\n OptionalExtensions,\n PressExtensions,\n type BoxSizeOverrides,\n type PressEvent,\n} from '../../../foundation/utils';\nimport { Primitive } from '../../../foundation/primitives';\nimport { useFormControl } from '../../../foundation/primitives/formControlContext/FormControlContext';\nimport { Spinner } from '../../../foundation/icons';\nimport { useDebounceHandler } from '../../../foundation/hooks';\nimport { buttonVariants } from './Button.variants';\n\nconst COMPONENT_NAME = 'Button';\n\nconst BUTTON_SIZE_PRESETS: ReadonlySet<string> = new Set<ButtonSizePreset>([\n 'xs',\n 'sm',\n 'md',\n 'lg',\n 'xl',\n]);\n\n/* Observable state surfaced via the `data-state` DOM attribute. */\nconst ButtonDataState = {\n Loading: 'loading',\n Skeleton: 'skeleton',\n Disabled: 'disabled',\n} as const;\ntype ButtonDataState = (typeof ButtonDataState)[keyof typeof ButtonDataState];\n\n/* `inheritAttrs: false` because three attrs are *owned*, not forwarded: `class` and `style` fold\n into the component's own `cn()` / style resolution so consumer values still win last (plain\n fallthrough would append outside `cn()`, losing tailwind-merge conflict resolution), and\n `onClick` is intercepted so loading / skeleton / long-press / the debounce window can swallow a\n click before the consumer's handler sees it. Everything else passes straight through. */\n/* The name is spelled out, not `COMPONENT_NAME`: `defineOptions()` is hoisted out of `setup()`,\n so it cannot reference a locally declared const. */\ndefineOptions({ name: 'Button', inheritAttrs: false });\n\nconst props = withDefaults(defineProps<ButtonProps>(), {\n type: ButtonType.Button,\n longPressDelay: PressExtensions.longPressDelay.default,\n /* Explicit `undefined` defaults keep Vue's boolean casting from turning an absent prop into\n `false` — `isDisabled` must stay undefined to inherit from an enclosing `Field`. */\n isDisabled: undefined,\n isLoading: undefined,\n isSkeleton: undefined,\n isFullWidth: undefined,\n isMultiline: undefined,\n asChild: false,\n /* `VNodeChild` includes `boolean`, so Vue's boolean casting turns an absent node-valued prop\n into `false` rather than `undefined` — which reads as \"supplied\" at every `!== undefined`\n check. An explicit `undefined` default suppresses the cast. */\n leadingSlot: undefined,\n trailingSlot: undefined,\n hoverSlot: undefined,\n loadingSlot: undefined,\n});\n\nconst emit = defineEmits<{\n /** Fires when the press begins — pointer-down OR Space/Enter keydown (first event in a gesture). */\n 'press-start': [event: PressEvent<HTMLButtonElement>];\n\n /** Fires when the press ends — pointer-up/cancel OR Space/Enter keyup. */\n 'press-end': [event: PressEvent<HTMLButtonElement>];\n\n /** Fires when the pointer is held for `longPressDelay` ms. Suppresses the next click. */\n 'long-press': [event: PressEvent<HTMLButtonElement>];\n}>();\n\nconst attrs = useAttrs();\nconst slots = useSlots();\n\n/* Stable render-only wrappers for the node-valued props, so each can render as the fallback of its\n named-slot twin. Stable identity (created once) keeps them from remounting on every render. */\nconst nodeProp = (read: () => VNodeChild) => defineComponent({ render: read });\nconst LeadingSlotProp = nodeProp(() => props.leadingSlot);\nconst TrailingSlotProp = nodeProp(() => props.trailingSlot);\nconst HoverSlotProp = nodeProp(() => props.hoverSlot);\nconst LoadingSlotProp = nodeProp(() => props.loadingSlot);\n\n/* Inherit disabled-state from an enclosing `Field` when the local prop is omitted; standalone when\n no context. Bound to the object, never destructured — every field on it is a live getter. */\nconst formControl = useFormControl();\nconst resolvedDisabled = computed(() => props.isDisabled ?? formControl?.isDisabled ?? false);\n\nconst skeletonActive = computed(() => !!props.isSkeleton);\nconst loadingActive = computed(() => !skeletonActive.value && !!props.isLoading);\nconst isInactive = computed(\n () => loadingActive.value || skeletonActive.value || resolvedDisabled.value,\n);\n\nconst dataState = computed<ButtonDataState | undefined>(() =>\n skeletonActive.value\n ? ButtonDataState.Skeleton\n : loadingActive.value\n ? ButtonDataState.Loading\n : resolvedDisabled.value\n ? ButtonDataState.Disabled\n : undefined,\n);\n\nconst safeLongPressDelay = computed(() =>\n props.longPressDelay < PressExtensions.longPressDelay.min ||\n props.longPressDelay > PressExtensions.longPressDelay.max\n ? PressExtensions.longPressDelay.default\n : props.longPressDelay,\n);\n\nwatchEffect(() => {\n if (!IS_DEV) return;\n if (props.isLoading && props.isSkeleton) {\n console.warn(\n `[${COMPONENT_NAME}] \\`isLoading\\` and \\`isSkeleton\\` are mutually exclusive — \\`isSkeleton\\` takes precedence.`,\n );\n }\n if (safeLongPressDelay.value !== props.longPressDelay) {\n console.warn(\n `[${COMPONENT_NAME}] longPressDelay=${props.longPressDelay}ms is outside reasonable range (${PressExtensions.longPressDelay.min}–${PressExtensions.longPressDelay.max}ms). Falling back to ${PressExtensions.longPressDelay.default}ms.`,\n );\n }\n if (\n slots.default === undefined &&\n attrs['aria-label'] === undefined &&\n attrs['aria-labelledby'] === undefined\n ) {\n console.warn(\n `[${COMPONENT_NAME}] icon-only button (no text children) is missing an accessible name — pass \\`aria-label\\` or \\`aria-labelledby\\` (Button.standard.md rule 12).`,\n );\n }\n});\n\n/* Parse the union-typed `size` prop into preset (for variant lookup) + box overrides (for inline dims). */\nconst parsedSize = computed(() =>\n CssExtensions.parseSizeUnion<ButtonSizePreset>(props.size, BUTTON_SIZE_PRESETS),\n);\n\nconst rootClass = computed(() =>\n cn(\n buttonVariants({\n variant: props.variant,\n tone: props.tone,\n size: parsedSize.value.preset,\n shape: props.shape,\n fullWidth: props.isFullWidth,\n wrap: props.isMultiline,\n }),\n attrs.class as ClassValue,\n ),\n);\n\nconst overrideStyle = computed<StyleValue | undefined>(() => {\n const padStyle = CssExtensions.resolvePadding(props.padding);\n const radStyle = CssExtensions.resolveRadius(props.radius);\n /* Box overrides — `size` (object form or raw value) is the base; flat width/height/minWidth/minHeight/boxSize props win when both are set. */\n const composedBox: BoxSizeOverrides = {\n ...(parsedSize.value.box ?? {}),\n ...(props.width !== undefined ? { width: props.width } : {}),\n ...(props.height !== undefined ? { height: props.height } : {}),\n ...(props.minWidth !== undefined ? { minWidth: props.minWidth } : {}),\n ...(props.minHeight !== undefined ? { minHeight: props.minHeight } : {}),\n ...(props.boxSize !== undefined ? { boxSize: props.boxSize } : {}),\n };\n const boxStyle = CssExtensions.resolveBoxSize(composedBox);\n /* Per-instance color override → sets CSS vars on element, scoped locally. */\n const colorStyle = ColorExtensions.toneColorOverride(props.color, props.tone);\n const consumerStyle = attrs.style as StyleValue | undefined;\n if (!padStyle && !radStyle && !boxStyle && !colorStyle && !consumerStyle) return undefined;\n return normalizeStyle([colorStyle, padStyle, radStyle, boxStyle, consumerStyle]);\n});\n\n// ---------------------------------------------------------------------------\n// Press / long-press / debounce wiring.\n// ---------------------------------------------------------------------------\n\nlet isPressing = false;\nlet longPressTimer: ReturnType<typeof setTimeout> | undefined;\nlet longPressFired = false;\n\nconst instance = getCurrentInstance();\n\n/* React armed the long-press timer only when an `onLongPress` prop was passed. A declared emit has\n no such signal — `emit()` on an unlistened event is a silent no-op, but the fired flag would\n still swallow the following click on every long hold. The listener is read off the incoming\n vnode props at event time (declared-emit listeners are stripped from `attrs`), so an unlistened\n button never arms the timer at all. */\nfunction hasLongPressListener(): boolean {\n return instance?.vnode.props?.onLongPress !== undefined;\n}\n\nonBeforeUnmount(() => {\n if (longPressTimer !== undefined) clearTimeout(longPressTimer);\n});\n\nfunction cancelLongPress(): void {\n if (longPressTimer !== undefined) {\n clearTimeout(longPressTimer);\n longPressTimer = undefined;\n }\n}\n\nfunction endPress(event: PressEvent<HTMLButtonElement>): void {\n if (isPressing) {\n isPressing = false;\n emit('press-end', event);\n }\n}\n\nfunction handlePointerDown(event: PointerEvent): void {\n if (isInactive.value) return;\n // Cancel any pending timer, then arm only on the first pointer of a gesture — a second\n // pointer-down must not stack a second long-press timer.\n cancelLongPress();\n if (!isPressing) {\n const pressEvent = event as PressEvent<HTMLButtonElement>;\n isPressing = true;\n longPressFired = false;\n emit('press-start', pressEvent);\n if (hasLongPressListener()) {\n longPressTimer = setTimeout(() => {\n longPressFired = true;\n emit('long-press', pressEvent);\n longPressTimer = undefined;\n }, safeLongPressDelay.value);\n }\n }\n}\n\nfunction handlePointerUp(event: PointerEvent): void {\n cancelLongPress();\n endPress(event as PressEvent<HTMLButtonElement>);\n}\n\nfunction handlePointerCancel(event: PointerEvent): void {\n cancelLongPress();\n endPress(event as PressEvent<HTMLButtonElement>);\n}\n\nfunction handlePointerLeave(): void {\n // Pointer leaving cancels a pending long-press but does NOT end the press itself —\n // pointer-up/cancel handlers do that. Matches React Aria.\n cancelLongPress();\n}\n\nconst isActivationKey = (event: KeyboardEvent) =>\n event.key === Key.Space || event.key === Key.Enter;\n\nfunction handleKeyDown(event: KeyboardEvent): void {\n if (isInactive.value) return;\n if (isActivationKey(event) && !event.repeat && !isPressing) {\n isPressing = true;\n longPressFired = false;\n emit('press-start', event as PressEvent<HTMLButtonElement>);\n }\n}\n\nfunction handleKeyUp(event: KeyboardEvent): void {\n if (isActivationKey(event) && isPressing) {\n isPressing = false;\n emit('press-end', event as PressEvent<HTMLButtonElement>);\n }\n}\n\n/**\n * The consumer's listener for one attr, normalised. Vue merges several listeners for the same\n * event into an array (a wrapper component that binds `@click` on top of a forwarded `onClick`\n * produces exactly that), so the raw attr is not always callable.\n */\nfunction toHandler<E extends Event>(value: unknown): ((event: E) => void) | undefined {\n if (typeof value === 'function') return value as (event: E) => void;\n if (!Array.isArray(value)) return undefined;\n const handlers = value.filter(\n (entry): entry is (event: E) => void => typeof entry === 'function',\n );\n if (handlers.length === 0) return undefined;\n return (event) => {\n for (const handler of handlers) handler(event);\n };\n}\n\n// Long-press suppression happens BEFORE this — a suppressed click does NOT advance the throttle window.\nconst debouncedOnClick = useDebounceHandler(\n (event: MouseEvent) => toHandler<MouseEvent>(attrs.onClick)?.(event),\n () => props.debounceMs,\n);\n\nfunction handleClick(event: MouseEvent): void {\n if (loadingActive.value || skeletonActive.value) {\n // Block native activation too — e.g. `type=\"submit\"` must not submit while loading.\n event.preventDefault();\n return;\n }\n if (longPressFired) {\n longPressFired = false;\n event.preventDefault();\n return;\n }\n debouncedOnClick(event);\n}\n\n/* The attrs the component owns rather than forwards — see the `inheritAttrs: false` note above.\n Event names carry the single casing Vue's runtime understands (`on` + the event name with only\n its first letter capitalised); `onPointerDown` would bind a `pointer-down` listener. */\nconst OWNED_ATTRS: ReadonlySet<string> = new Set([\n 'class',\n 'style',\n 'onClick',\n 'onPointerdown',\n 'onPointerup',\n 'onPointercancel',\n 'onPointerleave',\n 'onKeydown',\n 'onKeyup',\n]);\n\nconst passthroughAttrs = computed(() =>\n Object.fromEntries(Object.entries(attrs).filter(([key]) => !OWNED_ATTRS.has(key))),\n);\n\n/** The consumer's own listener for an owned event, so it can be chained ahead of the component's. */\nfunction consumerHandler<E extends Event>(name: string): ((event: E) => void) | undefined {\n return toHandler<E>(attrs[name]);\n}\n\n/* Assembled in the React original's spread order: the component's own attributes first, its event\n chain next, consumer attrs last so they still win. */\nconst rootProps = computed(() => ({\n type: props.asChild ? undefined : props.type,\n class: rootClass.value,\n style: overrideStyle.value,\n disabled: OptionalExtensions.from(resolvedDisabled.value, true),\n 'aria-busy': OptionalExtensions.from(loadingActive.value || skeletonActive.value, true),\n 'aria-disabled': OptionalExtensions.from(loadingActive.value || skeletonActive.value, true),\n tabindex: OptionalExtensions.from(skeletonActive.value, -1),\n 'data-state': dataState.value,\n onClick: handleClick,\n onPointerdown: composeEventHandlers(consumerHandler<PointerEvent>('onPointerdown'), handlePointerDown),\n onPointerup: composeEventHandlers(consumerHandler<PointerEvent>('onPointerup'), handlePointerUp),\n onPointercancel: composeEventHandlers(\n consumerHandler<PointerEvent>('onPointercancel'),\n handlePointerCancel,\n ),\n onPointerleave: composeEventHandlers(\n consumerHandler<PointerEvent>('onPointerleave'),\n handlePointerLeave,\n ),\n onKeydown: composeEventHandlers(consumerHandler<KeyboardEvent>('onKeydown'), handleKeyDown),\n onKeyup: composeEventHandlers(consumerHandler<KeyboardEvent>('onKeyup'), handleKeyUp),\n ...passthroughAttrs.value,\n}));\n\nconst root = useTemplateRef<ComponentPublicInstance>('root');\n\n/** The rendered element — the Vue stand-in for the React original's forwarded ref. */\nconst el = computed<HTMLElement | null>(() => {\n const node = root.value?.$el;\n return node instanceof HTMLElement ? node : null;\n});\n\ndefineExpose({ el });\n</script>\n\n<template>\n <!-- Renders an action button — for text and/or icon content. -->\n <Primitive ref=\"root\" :as=\"HtmlElement.Button\" :as-child=\"asChild\" v-bind=\"rootProps\">\n <!-- asChild → the merge target owns its children; leading/trailing/loading chrome is not rendered. -->\n <slot v-if=\"asChild\" />\n\n <template v-else-if=\"loadingActive\">\n <slot name=\"loading\">\n <LoadingSlotProp v-if=\"loadingSlot !== undefined\" />\n <Spinner v-else />\n </slot>\n <span v-if=\"loadingText !== undefined\">{{ loadingText }}</span>\n <!-- No loadingText: keep children in sr-only so the accessible name survives (Spinner is aria-hidden). -->\n <span v-else class=\"sr-only\"><slot /></span>\n </template>\n\n <template v-else-if=\"hoverSlot !== undefined || $slots.hover\">\n <slot name=\"leading\"><LeadingSlotProp v-if=\"leadingSlot !== undefined\" /></slot>\n <!-- CSS-only hover/focus-visible swap: children occupy the box and reserve its size;\n the hover content overlays it centered. Toggle via `group-hover`/`group-focus-visible`\n on the root `group` — no JS hover state. `aria-hidden` on the hidden layer so AT\n reads one label. -->\n <span class=\"relative inline-flex items-center justify-center\">\n <span\n class=\"inline-flex items-center justify-center group-hover:invisible group-focus-visible:invisible\"\n >\n <slot />\n </span>\n <span\n aria-hidden=\"true\"\n class=\"invisible absolute inset-0 inline-flex items-center justify-center group-hover:visible group-focus-visible:visible\"\n >\n <slot name=\"hover\"><HoverSlotProp v-if=\"hoverSlot !== undefined\" /></slot>\n </span>\n </span>\n <slot name=\"trailing\"><TrailingSlotProp v-if=\"trailingSlot !== undefined\" /></slot>\n </template>\n\n <template v-else>\n <slot name=\"leading\"><LeadingSlotProp v-if=\"leadingSlot !== undefined\" /></slot>\n <slot />\n <slot name=\"trailing\"><TrailingSlotProp v-if=\"trailingSlot !== undefined\" /></slot>\n </template>\n </Primitive>\n</template>\n","import type { InjectionKey } from 'vue';\nimport type { ToggleItemRole } from './ToggleButtonGroup.variants';\n\n/**\n * The seam between `ToggleButtonGroup` and its `ToggleButton` children.\n *\n * The React original reached into its children with `Children.map` +\n * `cloneElement`, injecting `isPressed` / `onPressedChange` (and the tablist\n * roles) onto each one. Vue has no equivalent — a parent cannot rewrite a\n * child's props — so the same coordination runs through provide/inject: the\n * group publishes the selection, each item reads its own slice off its `value`.\n *\n * Semantics are preserved exactly: an item with no `value` is inert, an item\n * with an explicit `isPressed` prop still wins over the group, and the item's\n * own `pressed-change` fires before the group's toggle.\n */\nexport interface ToggleButtonGroupContextValue {\n /** True while the item carrying `value` is active. Always false for a valueless item. */\n isPressed: (value: string | undefined) => boolean;\n\n /** Flips the item carrying `value` — clears the selection in single mode, adds/removes in multi. No-op for a valueless item. */\n toggle: (value: string | undefined) => void;\n\n /** The ARIA role wiring the group applies to each item. Live getter — read it, don't destructure it. */\n readonly itemRole: ToggleItemRole;\n}\n\nexport const ToggleButtonGroupKey: InjectionKey<ToggleButtonGroupContextValue> = Symbol(\n 'wow-two.toggleButtonGroup',\n);\n","/**\n * ToggleButtonGroup value-set enums.\n *\n * The group composes appearance with `cn()` (no `tv()`), so these are plain\n * prop-type vocabularies — no `VariantProps` assert. `Orientation` is the\n * shared registry enum (imported at the prop site, not re-minted here).\n */\n\n/** Defines the ToggleButtonGroup visual style. */\nexport const ToggleButtonGroupVariant = {\n /** Refers to a standard button row/column (borders + attached radii). */\n Default: 'default',\n /** Refers to an iOS-style connected pill row on a muted track (active segment lifts). */\n Segmented: 'segmented',\n /** Refers to individually-separated rounded pills (each item its own detached chip). */\n Pill: 'pill',\n} as const;\n\nexport type ToggleButtonGroupVariant =\n (typeof ToggleButtonGroupVariant)[keyof typeof ToggleButtonGroupVariant];\n\n/** Defines the ToggleButtonGroup selection cardinality (the `type` discriminant). */\nexport const ToggleMode = {\n /** Refers to at-most-one active item; toggling the active one clears it. */\n Single: 'single',\n /** Refers to any number of independently-active items. */\n Multi: 'multi',\n} as const;\n\nexport type ToggleMode = (typeof ToggleMode)[keyof typeof ToggleMode];\n\n/** Defines the ARIA role wiring for the group and its items. */\nexport const ToggleItemRole = {\n /** Refers to the default `role=\"group\"` of independent toggle buttons. */\n Group: 'group',\n /** Refers to `role=\"tablist\"` on the root + `role=\"tab\"` (+ `aria-selected`) on items. */\n Tab: 'tab',\n} as const;\n\nexport type ToggleItemRole = (typeof ToggleItemRole)[keyof typeof ToggleItemRole];\n","import { tv, ColorTone, type VariantProps } from '../../../foundation/utils';\n\n/** Defines the ToggleButton's press-state surface style. */\nexport const ToggleButtonVariant = {\n /** Refers to a borderless, transparent surface (text-color only). */\n Ghost: 'ghost',\n /** Refers to a muted/tinted fill on press. */\n Soft: 'soft',\n /** Refers to a bordered surface that swaps to a tone border on press. */\n Outline: 'outline',\n /** Refers to a bordered surface that fills with the tone on press. */\n Solid: 'solid',\n /** Refers to a translucent glass wash + blur. */\n Glass: 'glass',\n /** Refers to a glass surface with a hairline border. */\n GlassSurface: 'glass-surface',\n} as const;\n\nexport type ToggleButtonVariant = (typeof ToggleButtonVariant)[keyof typeof ToggleButtonVariant];\n\n/** Defines the element ToggleButton renders as. Diverges from the shared `ElementTag` (which omits `button`), so it stays a local enum. */\nexport const ToggleButtonElement = {\n /** Refers to a native `<button>`. */\n Button: 'button',\n /** Refers to a `<div>` with `role=\"button\"` + Space/Enter keyboard — lets you nest interactive children without invalid button-in-button markup. */\n Div: 'div',\n} as const;\n\nexport type ToggleButtonElement = (typeof ToggleButtonElement)[keyof typeof ToggleButtonElement];\n\n/* Variant × tone matrix for ToggleButton's press-state appearance. Applied on top of Button (variant='ghost' tone='neutral' baseline). Press state is keyed off `data-pressed=\"true\"` — distinct from Button's `data-state` (loading/skeleton/disabled). */\nexport const toggleButtonVariants = tv({\n base: '',\n variants: {\n variant: {\n ghost: '',\n soft: '',\n outline: 'border',\n solid: 'border',\n glass: 'border border-transparent backdrop-blur-md',\n 'glass-surface': 'border backdrop-blur-md',\n },\n tone: {\n primary: '',\n neutral: '',\n danger: '',\n success: '',\n warning: '',\n },\n },\n compoundVariants: [\n /*\n * Pressed text is `-soft-foreground`, not `{tone}`, for `ghost` and `outline`: both keep a\n * transparent fill, so the pressed label lands on the host surface where the full-strength\n * accent is too light — `ghost/warning` measured 1.85:1 pressed. The `soft` rows below\n * already resolved it this way; these two were missed. Same fix as `Button.variants.ts`\n * and `foundation/utils/Tones.ts`. Borders keep full-strength `{tone}`.\n */\n // === GHOST × tone — text color only, transparent bg ===\n { variant: 'ghost', tone: 'primary', class: 'text-foreground/50 data-[pressed=true]:text-primary-soft-foreground' },\n { variant: 'ghost', tone: 'neutral', class: 'text-foreground/50 data-[pressed=true]:text-foreground' },\n { variant: 'ghost', tone: 'danger', class: 'text-foreground/50 data-[pressed=true]:text-destructive-soft-foreground' },\n { variant: 'ghost', tone: 'success', class: 'text-foreground/50 data-[pressed=true]:text-success-soft-foreground' },\n { variant: 'ghost', tone: 'warning', class: 'text-foreground/50 data-[pressed=true]:text-warning-soft-foreground' },\n\n // === SOFT × tone — pressed gets tone-soft bg ===\n { variant: 'soft', tone: 'primary', class: 'text-foreground/70 data-[pressed=true]:bg-primary-soft data-[pressed=true]:text-primary-soft-foreground' },\n { variant: 'soft', tone: 'neutral', class: 'text-foreground/70 data-[pressed=true]:bg-muted data-[pressed=true]:text-foreground' },\n { variant: 'soft', tone: 'danger', class: 'text-foreground/70 data-[pressed=true]:bg-destructive-soft data-[pressed=true]:text-destructive-soft-foreground' },\n { variant: 'soft', tone: 'success', class: 'text-foreground/70 data-[pressed=true]:bg-success-soft data-[pressed=true]:text-success-soft-foreground' },\n { variant: 'soft', tone: 'warning', class: 'text-foreground/70 data-[pressed=true]:bg-warning-soft data-[pressed=true]:text-warning-soft-foreground' },\n\n // === OUTLINE × tone — pressed swaps to tone border + tone text ===\n { variant: 'outline', tone: 'primary', class: 'border-input text-foreground/70 data-[pressed=true]:border-primary data-[pressed=true]:text-primary-soft-foreground' },\n { variant: 'outline', tone: 'neutral', class: 'border-input text-foreground/70 data-[pressed=true]:border-foreground data-[pressed=true]:text-foreground' },\n { variant: 'outline', tone: 'danger', class: 'border-input text-foreground/70 data-[pressed=true]:border-destructive data-[pressed=true]:text-destructive-soft-foreground' },\n { variant: 'outline', tone: 'success', class: 'border-input text-foreground/70 data-[pressed=true]:border-success data-[pressed=true]:text-success-soft-foreground' },\n { variant: 'outline', tone: 'warning', class: 'border-input text-foreground/70 data-[pressed=true]:border-warning data-[pressed=true]:text-warning-soft-foreground' },\n\n // === SOLID × tone — pressed fills with tone ===\n { variant: 'solid', tone: 'primary', class: 'border-input bg-background text-foreground/70 data-[pressed=true]:bg-primary data-[pressed=true]:border-primary data-[pressed=true]:text-primary-foreground' },\n { variant: 'solid', tone: 'neutral', class: 'border-input bg-background text-foreground/70 data-[pressed=true]:bg-foreground data-[pressed=true]:border-foreground data-[pressed=true]:text-background' },\n { variant: 'solid', tone: 'danger', class: 'border-input bg-background text-foreground/70 data-[pressed=true]:bg-destructive data-[pressed=true]:border-destructive data-[pressed=true]:text-destructive-foreground' },\n { variant: 'solid', tone: 'success', class: 'border-input bg-background text-foreground/70 data-[pressed=true]:bg-success data-[pressed=true]:border-success data-[pressed=true]:text-success-foreground' },\n { variant: 'solid', tone: 'warning', class: 'border-input bg-background text-foreground/70 data-[pressed=true]:bg-warning data-[pressed=true]:border-warning data-[pressed=true]:text-warning-foreground' },\n\n // === GLASS × tone — dark glass; pressed darkens slightly + tone-tinted text on tone variants ===\n { variant: 'glass', tone: 'primary', class: 'bg-black/45 text-white/60 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-white' },\n { variant: 'glass', tone: 'neutral', class: 'bg-black/45 text-white/60 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-white' },\n { variant: 'glass', tone: 'danger', class: 'bg-black/45 text-white/60 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-destructive' },\n { variant: 'glass', tone: 'success', class: 'bg-black/45 text-white/60 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-success' },\n { variant: 'glass', tone: 'warning', class: 'bg-black/45 text-white/60 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-warning' },\n\n // === GLASS-SURFACE × tone — same as glass + visible border emphasis on press ===\n { variant: 'glass-surface', tone: 'primary', class: 'bg-black/45 text-white/60 border-white/10 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-white data-[pressed=true]:border-white/40' },\n { variant: 'glass-surface', tone: 'neutral', class: 'bg-black/45 text-white/60 border-white/10 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-white data-[pressed=true]:border-white/40' },\n { variant: 'glass-surface', tone: 'danger', class: 'bg-black/45 text-white/60 border-white/10 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-destructive data-[pressed=true]:border-destructive/60' },\n { variant: 'glass-surface', tone: 'success', class: 'bg-black/45 text-white/60 border-white/10 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-success data-[pressed=true]:border-success/60' },\n { variant: 'glass-surface', tone: 'warning', class: 'bg-black/45 text-white/60 border-white/10 data-[pressed=true]:bg-black/65 data-[pressed=true]:text-warning data-[pressed=true]:border-warning/60' },\n ],\n defaultVariants: {\n variant: 'ghost',\n tone: 'primary',\n },\n});\n\nexport type ToggleButtonVariants = VariantProps<typeof toggleButtonVariants>;\n\n/* Compile-time lock: enum values ≡ tv axis keys (drift = type error). */\ntype AssertExact<A, B> = [A] extends [B] ? ([B] extends [A] ? true : never) : never;\nconst _assertToggleButtonVariant: AssertExact<\n ToggleButtonVariant,\n NonNullable<ToggleButtonVariants['variant']>\n> = true;\nconst _assertToggleButtonTone: AssertExact<ColorTone, NonNullable<ToggleButtonVariants['tone']>> =\n true;\nvoid _assertToggleButtonVariant;\nvoid _assertToggleButtonTone;\n","<script lang=\"ts\">\nimport type { VNodeChild } from 'vue';\nimport type { ColorProp, ColorTone } from '../../../foundation/utils';\nimport type { ButtonProps } from '../button';\nimport type { ToggleButtonElement, ToggleButtonVariant, ToggleButtonVariants } from './ToggleButton.variants';\n\n/* Fn signature for state-aware string props. */\ntype PressedFn<T> = (args: { pressed: boolean }) => T;\ntype StateAware<T> = T | PressedFn<T>;\n\n/* `ButtonProps` and `ToggleButtonVariants` are `@vue-ignore`d: everything not declared below\n flows to the underlying `Button` through attribute fallthrough (the counterpart of the\n original's `{...buttonProps}` spread), and `ToggleButtonVariants` resolves through\n `typeof toggleButtonVariants`, which the SFC prop compiler cannot walk. */\n/* The state-aware accessible label rides on the ignored heritage rather than the body — a declared\n `'aria-label'` would be camelized to `props.ariaLabel` and never reach the DOM. */\ntype ToggleButtonAttributes = Omit<\n ButtonProps,\n 'variant' | 'tone' | 'children' | 'title' | 'aria-label' | 'color'\n> & { 'aria-label'?: StateAware<string> };\n\nexport interface ToggleButtonProps\n extends /* @vue-ignore */ ToggleButtonAttributes,\n /* @vue-ignore */ Omit<ToggleButtonVariants, 'variant' | 'tone'> {\n /** The press-state surface style. */\n variant?: ToggleButtonVariant;\n\n /** The semantic tone palette. */\n tone?: ColorTone;\n\n /** The controlled pressed state. */\n isPressed?: boolean;\n\n /** The uncontrolled initial state. Ignored if `isPressed` is set. */\n defaultPressed?: boolean;\n\n /** The item's identity inside a `ToggleButtonGroup` — the group keys its selection off this. Also rendered as the native `value` attribute. */\n value?: string;\n\n /** The tooltip text — string OR fn receiving `{ pressed }`. State-aware form keeps consumer-supplied strings (i18n discipline). */\n title?: StateAware<string>;\n\n /** The per-instance color override — applies to the active `tone`'s theme tokens. See `ColorProp`. */\n color?: ColorProp;\n\n /** The optional rich tooltip shown on hover/focus — use for icon-only toggles. Until `presentation/display` ports, a string value degrades to the native `title` attribute (when `title` itself is unset) and a node value is ignored. */\n tooltip?: VNodeChild;\n\n /** The render element. `'div'` (role=button + Space/Enter keyboard) lets you nest INTERACTIVE children (a color picker, a link) inside a segment without invalid button-in-button markup. Default `'button'`. */\n as?: ToggleButtonElement;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, inject, useAttrs } from 'vue';\nimport type { ClassValue } from 'clsx';\nimport { cn, ColorTone as ColorToneValue, Key } from '../../../foundation/utils';\nimport { useControlled } from '../../../foundation/hooks';\nimport Button from '../button/Button.vue';\nimport { ButtonVariant } from '../button';\nimport { ToggleButtonGroupKey } from '../toggleButtonGroup/ToggleButtonGroupContext';\nimport { ToggleItemRole } from '../toggleButtonGroup/ToggleButtonGroup.variants';\nimport {\n toggleButtonVariants,\n ToggleButtonElement as ToggleButtonElementValue,\n ToggleButtonVariant as ToggleButtonVariantValue,\n} from './ToggleButton.variants';\n\n/* `inheritAttrs: false` so `class` folds into the component's own `cn()` call; everything else is\n forwarded onto `Button` by hand, which is where the original's `{...buttonProps}` landed. */\ndefineOptions({ name: 'ToggleButton', inheritAttrs: false });\n\nconst props = withDefaults(defineProps<ToggleButtonProps>(), {\n variant: ToggleButtonVariantValue.Ghost,\n tone: ColorToneValue.Primary,\n as: ToggleButtonElementValue.Button,\n /* Explicit `undefined` keeps Vue's boolean casting from collapsing an absent `isPressed` to\n `false`, which would pin the toggle to the controlled branch permanently. */\n isPressed: undefined,\n defaultPressed: undefined,\n /* `VNodeChild` includes `boolean`, so Vue's boolean casting turns an absent node-valued prop\n into `false` rather than `undefined` — which reads as \"supplied\" at every `!== undefined`\n check. An explicit `undefined` default suppresses the cast. */\n tooltip: undefined,\n});\n\nconst emit = defineEmits<{\n /** Emits the pressed state whenever it changes. */\n 'pressed-change': [pressed: boolean];\n}>();\n\nconst attrs = useAttrs();\n\n/* Present only inside a `ToggleButtonGroup`; standalone toggles own their state. */\nconst group = inject(ToggleButtonGroupKey, null);\n\nconst { value: pressed, setValue: setPressed } = useControlled<boolean>({\n /* Inside a group the selection lives on the group, which makes the item controlled — the same\n state the original produced by cloning `isPressed` onto each child. An explicit `isPressed`\n prop still wins over the group. */\n controlled: () => props.isPressed ?? group?.isPressed(props.value),\n default: props.defaultPressed ?? false,\n onChange: (pressed) => emit('pressed-change', pressed),\n});\n\n/* `aria-label` is read off `attrs`, not `props`: Vue camelizes declared prop keys, so a declared\n `'aria-label'` would arrive as `props.ariaLabel` and never render. It is stripped here and\n re-bound onto `Button` below, so the state-resolved value is the one that lands. */\nconst OWNED_ATTRS: ReadonlySet<string> = new Set(['class', 'aria-label']);\nconst passthroughAttrs = computed(() =>\n Object.fromEntries(Object.entries(attrs).filter(([key]) => !OWNED_ATTRS.has(key))),\n);\n\nconst isDiv = computed(() => props.as === ToggleButtonElementValue.Div);\n\n/* Resolve state-aware string props to plain strings for the underlying Button. */\nconst resolvedTitle = computed(() => {\n const title =\n typeof props.title === 'function' ? props.title({ pressed: pressed.value }) : props.title;\n /* `presentation/display` has not ported yet, so a string `tooltip` degrades to the native\n attribute rather than silently vanishing. An explicit `title` always wins. */\n return title ?? (typeof props.tooltip === 'string' ? props.tooltip : undefined);\n});\n\nconst resolvedAriaLabel = computed(() => {\n const label = attrs['aria-label'] as StateAware<string> | undefined;\n return typeof label === 'function' ? label({ pressed: pressed.value }) : label;\n});\n\nconst rootClass = computed(() =>\n cn(\n toggleButtonVariants({ variant: props.variant, tone: props.tone }),\n attrs.class as ClassValue,\n ),\n);\n\n/* Tablist wiring is layered by the group, exactly as the original's `cloneElement` did. */\nconst itemRole = computed(() =>\n group?.itemRole === ToggleItemRole.Tab ? ('tab' as const) : undefined,\n);\nconst ariaSelected = computed(() => (itemRole.value === 'tab' ? pressed.value : undefined));\n\nfunction toggle(): void {\n setPressed(!pressed.value);\n group?.toggle(props.value);\n}\n\n/* Chained after the consumer's own click (attribute fallthrough puts theirs first) and skipped\n when they called `preventDefault()` — the original's `onClick?.(e); if (!e.defaultPrevented)`. */\nfunction handleClick(event: MouseEvent): void {\n if (event.defaultPrevented) return;\n toggle();\n}\n\nfunction handleDivKeyDown(event: KeyboardEvent): void {\n if (event.key === Key.Space || event.key === Key.Enter) {\n event.preventDefault();\n toggle();\n }\n}\n</script>\n\n<template>\n <!-- Two-state action button (on/off) — sets `aria-pressed` + `data-pressed=\"true|false\"`. Wraps\n Button to inherit the size union, shape, asChild, loading, padding/radius. Press appearance\n lives in `toggleButtonVariants` (variant × tone matrix); ToggleButton's own appearance\n overrides Button's neutral-ghost baseline via class order. -->\n <Button\n :variant=\"ButtonVariant.Ghost\"\n :tone=\"tone ?? undefined\"\n :color=\"color\"\n :as-child=\"isDiv\"\n :value=\"value\"\n :aria-pressed=\"pressed\"\n :aria-label=\"resolvedAriaLabel\"\n :data-pressed=\"pressed ? 'true' : 'false'\"\n :title=\"resolvedTitle\"\n :role=\"itemRole\"\n :aria-selected=\"ariaSelected\"\n :class=\"rootClass\"\n v-bind=\"passthroughAttrs\"\n @click=\"handleClick\"\n >\n <!-- `as=\"div\"` → render through the asChild merge onto a real <div> so consumers may nest\n interactive children (button-in-button is invalid markup). Keyboard parity added here. -->\n <div v-if=\"isDiv\" role=\"button\" :tabindex=\"0\" @keydown=\"handleDivKeyDown\">\n <slot :pressed=\"pressed\" />\n </div>\n <slot v-else :pressed=\"pressed\" />\n </Button>\n</template>\n","<script lang=\"ts\">\nimport type { HTMLAttributes } from 'vue';\nimport type { Orientation } from '../../../foundation/utils';\nimport type {\n ToggleButtonGroupVariant,\n ToggleItemRole,\n ToggleMode,\n} from './ToggleButtonGroup.variants';\n\n/**\n * Props for the group, generic over the value type `T`.\n *\n * `T` defaults to `string`, so untyped usage keeps the historical `string | null`\n * shape. Pass a string-literal union or string enum\n * (`<ToggleButtonGroup<GradientType> …>`) to have `value` / `@value-change` emit\n * that narrowed type instead — no cast needed at the call site.\n *\n * Divergence from the React original: there, `type` discriminated a `SingleProps<T>`\n * / `MultiProps` union, so single mode saw `T | null` and multi mode `readonly\n * string[]`. Vue's prop compiler flattens a union type into one merged prop set, so\n * `value` / `defaultValue` carry both shapes and the mode still decides which is\n * live at runtime.\n */\nexport interface ToggleButtonGroupProps<T extends string = string>\n extends /* @vue-ignore */ Omit<HTMLAttributes, 'defaultValue' | 'onChange'> {\n /** The selection cardinality — omit or `ToggleMode.Single` for at-most-one, `ToggleMode.Multi` for any-number-active. */\n type?: ToggleMode;\n\n /** The controlled value — `T | null` in single mode, a string array in multi mode. */\n value?: T | null | ReadonlyArray<string>;\n\n /** The uncontrolled initial value. Ignored once `value` is set. */\n defaultValue?: T | null | ReadonlyArray<string>;\n\n /** The layout axis of the button row/column. @default Orientation.Horizontal */\n orientation?: Orientation;\n\n /** The attached state — collapses inner radii into a connected row/column. @default true */\n isAttached?: boolean;\n\n /**\n * The visual style.\n * - `default` — standard button row/column (borders + attached radii).\n * - `segmented` — iOS-style connected pill row on a muted track; the active\n * segment lifts to a `background` surface. Forces `isAttached`.\n * - `pill` — individually-separated rounded pills (each item its own detached\n * chip). Forces detached (never attaches).\n */\n variant?: ToggleButtonGroupVariant;\n\n /**\n * The ARIA role wiring.\n * - `group` (default) — `role=\"group\"` of independent toggle buttons.\n * - `tab` — opt into tablist semantics: root renders `role=\"tablist\"` and each\n * item `role=\"tab\"` + `aria-selected`. Pairs naturally with single-select.\n * @default ToggleItemRole.Group\n */\n itemRole?: ToggleItemRole;\n\n /**\n * The equal-width state — lays items out as equal-width tiles (each `flex-1 basis-0`)\n * for an icon category strip where every cell should share the row width. Additive;\n * the default keeps intrinsic item widths.\n * @default false\n */\n equalWidth?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\" generic=\"T extends string = string\">\nimport { computed, provide, useAttrs, useTemplateRef } from 'vue';\nimport type { ClassValue } from 'clsx';\nimport { cn, Orientation as OrientationValue } from '../../../foundation/utils';\nimport { useControlled } from '../../../foundation/hooks';\nimport { ToggleButtonGroupKey } from './ToggleButtonGroupContext';\nimport {\n ToggleButtonGroupVariant as ToggleButtonGroupVariantValue,\n ToggleItemRole as ToggleItemRoleValue,\n ToggleMode as ToggleModeValue,\n} from './ToggleButtonGroup.variants';\n\n/* `inheritAttrs: false` so `class` folds into the component's own `cn()` call — plain fallthrough\n appends outside it and loses tailwind-merge conflict resolution. */\ndefineOptions({ name: 'ToggleButtonGroup', inheritAttrs: false });\n\nconst props = withDefaults(defineProps<ToggleButtonGroupProps<T>>(), {\n orientation: OrientationValue.Horizontal,\n isAttached: true,\n variant: ToggleButtonGroupVariantValue.Default,\n itemRole: ToggleItemRoleValue.Group,\n equalWidth: false,\n type: undefined,\n value: undefined,\n defaultValue: undefined,\n});\n\nconst emit = defineEmits<{\n /** Emits the selection whenever it changes — `T | null` in single mode, the full array in multi mode. */\n 'value-change': [value: T | null | ReadonlyArray<string>];\n}>();\n\nconst attrs = useAttrs();\n\nconst mode = computed(() =>\n props.type === ToggleModeValue.Multi ? ToggleModeValue.Multi : ToggleModeValue.Single,\n);\nconst isSegmented = computed(() => props.variant === ToggleButtonGroupVariantValue.Segmented);\nconst isPill = computed(() => props.variant === ToggleButtonGroupVariantValue.Pill);\nconst isTablist = computed(() => props.itemRole === ToggleItemRoleValue.Tab);\nconst isHorizontal = computed(() => props.orientation === OrientationValue.Horizontal);\n// Segmented is inherently an attached pill row — the muted track only reads as one control when its\n// segments touch. Pill is the inverse — always detached chips, never attached.\nconst attached = computed(() =>\n isPill.value ? false : isSegmented.value || props.isAttached,\n);\n\nconst { value: singleValue, setValue: setSingleValue } = useControlled<string | null>({\n controlled: () =>\n mode.value === ToggleModeValue.Single ? (props.value as string | null | undefined) : undefined,\n default:\n props.type !== ToggleModeValue.Multi\n ? ((props.defaultValue as string | null | undefined) ?? null)\n : null,\n onChange: (next) => {\n if (mode.value === ToggleModeValue.Single) emit('value-change', next as T | null);\n },\n});\n\nconst { value: multiValue, setValue: setMultiValue } = useControlled<ReadonlyArray<string>>({\n controlled: () =>\n mode.value === ToggleModeValue.Multi\n ? (props.value as ReadonlyArray<string> | undefined)\n : undefined,\n default:\n props.type === ToggleModeValue.Multi\n ? ((props.defaultValue as ReadonlyArray<string> | undefined) ?? [])\n : [],\n onChange: (next) => {\n if (mode.value === ToggleModeValue.Multi) emit('value-change', next);\n },\n});\n\nfunction isPressed(childValue: string | undefined): boolean {\n if (childValue === undefined) return false;\n return mode.value === ToggleModeValue.Single\n ? singleValue.value === childValue\n : multiValue.value.includes(childValue);\n}\n\nfunction togglePressed(childValue: string | undefined): void {\n if (childValue === undefined) return;\n if (mode.value === ToggleModeValue.Single) {\n setSingleValue(singleValue.value === childValue ? null : childValue);\n } else {\n setMultiValue(\n multiValue.value.includes(childValue)\n ? multiValue.value.filter((entry) => entry !== childValue)\n : [...multiValue.value, childValue],\n );\n }\n}\n\n/* Each `ToggleButton` child reads its own slice off this — the provide/inject replacement for the\n original's `Children.map` + `cloneElement`. `itemRole` is a live getter, not a snapshot. */\nprovide(ToggleButtonGroupKey, {\n isPressed,\n toggle: togglePressed,\n get itemRole() {\n return props.itemRole;\n },\n});\n\nconst OWNED_ATTRS: ReadonlySet<string> = new Set(['class']);\nconst passthroughAttrs = computed(() =>\n Object.fromEntries(Object.entries(attrs).filter(([key]) => !OWNED_ATTRS.has(key))),\n);\n\nconst rootClass = computed(() =>\n cn(\n 'inline-flex',\n isHorizontal.value ? 'flex-row' : 'flex-col',\n attached.value\n ? isHorizontal.value\n ? '[&>*]:rounded-none [&>*:first-child]:rounded-l-md [&>*:last-child]:rounded-r-md [&>*:not(:first-child)]:-ml-px'\n : '[&>*]:rounded-none [&>*:first-child]:rounded-t-md [&>*:last-child]:rounded-b-md [&>*:not(:first-child)]:-mt-px'\n : 'gap-2',\n // Segmented: muted track + reset segment chrome; active segment lifts to a `background` surface.\n isSegmented.value && [\n 'rounded-md bg-muted p-1',\n '[&>*]:!rounded-md [&>*]:!ml-0 [&>*]:!border-transparent [&>*]:!bg-transparent',\n '[&>*[data-pressed=true]]:!bg-background [&>*[data-pressed=true]]:!text-foreground [&>*[data-pressed=true]]:shadow-sm',\n ],\n // Pill: fully-rounded detached chips (gap already applied via the non-attached branch above).\n isPill.value && '[&>*]:!rounded-full',\n // Equal-width tiles: every item shares the row/column extent (icon category strip).\n props.equalWidth && '[&>*]:flex-1 [&>*]:basis-0',\n attrs.class as ClassValue,\n ),\n);\n\nconst root = useTemplateRef<HTMLDivElement>('root');\n\n/** The rendered element — the Vue stand-in for the React original's forwarded ref. */\ndefineExpose({ el: root });\n</script>\n\n<template>\n <!-- Coordinates a row/column of ToggleButton children — `type=\"single\" | \"multi\"`. -->\n <div\n ref=\"root\"\n :role=\"isTablist ? 'tablist' : 'group'\"\n :aria-orientation=\"isTablist ? orientation : undefined\"\n :data-orientation=\"orientation\"\n :class=\"rootClass\"\n v-bind=\"passthroughAttrs\"\n >\n <slot />\n </div>\n</template>\n","import { tv, type VariantProps } from '../../../foundation/utils';\n\n/**\n * Adds `OptionTile`'s pressed wash on top of the underlying `ToggleButton`\n * outline treatment. The tint is a semantic token (`primary`), not a\n * hard-coded color — it layers after `toggleButtonVariants` via class order.\n */\nexport const optionTileVariants = tv({\n base: 'data-[pressed=true]:bg-primary/10',\n});\n\nexport type OptionTileVariants = VariantProps<typeof optionTileVariants>;\n","<script lang=\"ts\">\nimport type { ColorTone } from '../../../foundation/utils';\nimport type { ButtonSize } from '../button/Button.vue';\nimport type { ToggleButtonProps } from '../toggleButton';\n\n/** Defines props for a single-select preset tile. */\nexport interface OptionTileProps\n extends /* @vue-ignore */ Omit<\n ToggleButtonProps,\n | 'isPressed'\n | 'defaultPressed'\n | 'onPressedChange'\n | 'children'\n | 'aria-label'\n | 'title'\n | 'variant'\n | 'shape'\n > {\n /** The active-selection state of this tile. */\n selected: boolean;\n\n /** The accessible label + native tooltip — the tile is icon-only, so this is its name. */\n label: string;\n\n /* Re-declared from `ToggleButtonProps` (identical types) purely so the SFC compiler sees them:\n defaults can only be attached to props it actually generates, and the heritage is ignored. */\n\n /** The semantic tone palette. Default `primary`. */\n tone?: ColorTone;\n\n /** The tile size. Default `sm`. */\n size?: ButtonSize;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport type { ClassValue } from 'clsx';\nimport { cn, ColorTone as ColorToneValue } from '../../../foundation/utils';\nimport ToggleButton from '../toggleButton/ToggleButton.vue';\nimport { ToggleButtonVariant } from '../toggleButton';\nimport { ButtonShape } from '../button';\nimport { optionTileVariants } from './OptionTile.variants';\n\n/* `inheritAttrs: false` so `class` folds into the component's own `cn()` call; everything else is\n forwarded onto `ToggleButton` by hand. */\ndefineOptions({ name: 'OptionTile', inheritAttrs: false });\n\n/* `onSelect` became the `select` emit; the React prop was required, which an emit cannot express.\n `children` has no prop counterpart — the tile's icon, glyph, or swatch is the default slot. */\nwithDefaults(defineProps<OptionTileProps>(), {\n size: 'sm',\n tone: ColorToneValue.Primary,\n});\n\nconst emit = defineEmits<{\n /** Fires when this tile is selected. Single-select — the parent owns the value, so re-selecting the active tile is a harmless no-op. */\n select: [];\n}>();\n\nconst attrs = useAttrs();\n\nconst OWNED_ATTRS: ReadonlySet<string> = new Set(['class']);\nconst passthroughAttrs = computed(() =>\n Object.fromEntries(Object.entries(attrs).filter(([key]) => !OWNED_ATTRS.has(key))),\n);\n\nconst rootClass = computed(() => cn(optionTileVariants(), attrs.class as ClassValue));\n</script>\n\n<template>\n <!--\n Renders a square, single-select tile for preset grids (fill types, module /\n finder shapes, gradient presets) — an icon-only `ToggleButton` (`shape=\"square\"`)\n with a soft pressed wash. Compose several in a grid; the parent owns the active\n value. Disable a whole grid by wrapping it in a native `<fieldset disabled>`.\n -->\n <ToggleButton\n :shape=\"ButtonShape.Square\"\n :variant=\"ToggleButtonVariant.Outline\"\n :tone=\"tone\"\n :size=\"size\"\n :is-pressed=\"selected\"\n :aria-label=\"label\"\n :title=\"label\"\n :class=\"rootClass\"\n v-bind=\"passthroughAttrs\"\n @pressed-change=\"emit('select')\"\n >\n <slot />\n </ToggleButton>\n</template>\n","<script lang=\"ts\">\n/**\n * Defines props for a `Fieldset`.\n *\n * React's `FieldsetHTMLAttributes<HTMLFieldSetElement>` has no Vue counterpart —\n * every native attribute (`disabled`, `form`, `name`) is a fallthrough attr and\n * lands on the `<fieldset>` unchanged. The name is kept so consumers importing\n * `FieldsetProps` still resolve.\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface FieldsetProps {}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useAttrs, useTemplateRef } from 'vue';\nimport type { ClassValue } from 'clsx';\nimport { cn } from '../../../foundation/utils';\n\n/**\n * Semantic `<fieldset>` for grouping related controls. Pair with `Legend`\n * for the group label.\n */\n/* `inheritAttrs: false` so `class` folds into the component's own `cn()` call — plain fallthrough\n appends outside it and loses tailwind-merge conflict resolution. */\ndefineOptions({ name: 'Fieldset', inheritAttrs: false });\n\nconst attrs = useAttrs();\n\nconst OWNED_ATTRS: ReadonlySet<string> = new Set(['class']);\nconst passthroughAttrs = computed(() =>\n Object.fromEntries(Object.entries(attrs).filter(([key]) => !OWNED_ATTRS.has(key))),\n);\n\nconst rootClass = computed(() => cn('m-0 min-w-0 border-0 p-0', attrs.class as ClassValue));\n\nconst root = useTemplateRef<HTMLFieldSetElement>('root');\n\n/** The rendered element — the Vue stand-in for the React original's forwarded ref. */\ndefineExpose({ el: root });\n</script>\n\n<template>\n <fieldset ref=\"root\" :class=\"rootClass\" v-bind=\"passthroughAttrs\">\n <slot />\n </fieldset>\n</template>\n","import { tv, Align, type VariantProps } from '../../../foundation/utils';\n\n/** Provides the tile-row layout for `OptionTileGroup` on top of the reset `Fieldset` — flex row, gap, optional wrap + main-axis alignment. */\nexport const optionTileGroupVariants = tv({\n base: 'flex items-center gap-2',\n variants: {\n wrap: {\n true: 'flex-wrap',\n false: '',\n },\n align: {\n start: 'justify-start',\n center: 'justify-center',\n end: 'justify-end',\n },\n },\n defaultVariants: {\n wrap: false,\n align: 'start',\n },\n});\n\nexport type OptionTileGroupVariants = VariantProps<typeof optionTileGroupVariants>;\n\n/* Compile-time lock: shared `Align` values ≡ tv `align` keys (drift = type error). */\ntype AssertExact<A, B> = [A] extends [B] ? ([B] extends [A] ? true : never) : never;\nconst _assertOptionTileGroupAlign: AssertExact<\n Align,\n NonNullable<OptionTileGroupVariants['align']>\n> = true;\nvoid _assertOptionTileGroupAlign;\n","<script lang=\"ts\">\nimport type { Align } from '../../../foundation/utils';\n\n/** Defines props for a group of option tiles. */\nexport interface OptionTileGroupProps {\n /** The group's accessible name. */\n readonly label: string;\n\n /** The disabled state — greys + blocks every tile via a native `<fieldset disabled>`. */\n readonly disabled?: boolean;\n\n /** The wrap state — tiles flow onto multiple rows. Default `false` (single row). */\n readonly wrap?: boolean;\n\n /** The main-axis alignment of the tiles. Default `start`. */\n readonly align?: Align;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useAttrs, useTemplateRef } from 'vue';\nimport type { ClassValue } from 'clsx';\nimport { cn } from '../../../foundation/utils';\nimport { Fieldset } from '../../forms/fieldset';\nimport { optionTileGroupVariants } from './OptionTileGroup.variants';\n\n/* `inheritAttrs: false` so `class` folds into the component's own `cn()` call — plain fallthrough\n appends outside it and loses tailwind-merge conflict resolution. */\ndefineOptions({ name: 'OptionTileGroup', inheritAttrs: false });\n\n/* `children` has no prop counterpart — the `OptionTile` children are the default slot — and the\n React `className` prop is Vue's `class` fallthrough attr. */\n/* Explicit `undefined` defaults keep Vue's boolean casting from turning an absent prop into\n `false` — `wrap` must stay undefined so the variants config's own default decides. */\nconst props = withDefaults(defineProps<OptionTileGroupProps>(), {\n disabled: undefined,\n wrap: undefined,\n});\n\nconst attrs = useAttrs();\n\nconst OWNED_ATTRS: ReadonlySet<string> = new Set(['class']);\nconst passthroughAttrs = computed(() =>\n Object.fromEntries(Object.entries(attrs).filter(([key]) => !OWNED_ATTRS.has(key))),\n);\n\n/* `Fieldset` owns the `m-0 min-w-0 border-0 p-0` reset, so only the layout variants are\n composed here — the same split the React original had. */\nconst rootClass = computed(() =>\n cn(optionTileGroupVariants({ wrap: props.wrap, align: props.align }), attrs.class as ClassValue),\n);\n\nconst root = useTemplateRef<{ el: HTMLFieldSetElement | null }>('root');\n\n/** The rendered element — the Vue stand-in for the React original's forwarded ref. */\ndefineExpose({ el: computed(() => root.value?.el ?? null) });\n</script>\n\n<template>\n <!--\n Renders a labelled group of `OptionTile`s — a reset `<fieldset>` (native\n `disabled` greys + blocks the whole group) laid out as a tile row, with the\n group's accessible name on `aria-label`.\n -->\n <Fieldset\n ref=\"root\"\n :disabled=\"disabled\"\n :aria-label=\"label\"\n :class=\"rootClass\"\n v-bind=\"passthroughAttrs\"\n >\n <slot />\n </Fieldset>\n</template>\n"],"names":["_openBlock","_createBlock","_unref","_mergeProps","_renderSlot","_createElementBlock","_Fragment","Spinner","$slots","_createElementVNode","pressed","ToggleButtonElementValue","Button","ToggleModeValue","ToggleButtonGroupVariantValue","ToggleItemRoleValue","OrientationValue","ToggleButton"],"mappings":"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"}
|
|
@@ -2,11 +2,11 @@ import { defineComponent, shallowRef, provide, computed, renderSlot, inject, use
|
|
|
2
2
|
import { P as Primitive } from "./Primitive-Cm3ECaVw.js";
|
|
3
3
|
import { u as useControlled } from "./useControlled-B6M4kTLn.js";
|
|
4
4
|
import { c as cn } from "./cn-CzDCF-Ah.js";
|
|
5
|
-
import { s as surfaceVariants } from "./SurfaceStyles-
|
|
5
|
+
import { s as surfaceVariants } from "./SurfaceStyles-B6W7zdMi.js";
|
|
6
6
|
import { _ as _sfc_main$3 } from "./Portal.vue_vue_type_script_setup_true_lang-CF3R0VCZ.js";
|
|
7
|
-
import { P as Presence } from "./Presence-
|
|
7
|
+
import { P as Presence } from "./Presence-DE4MlrJz.js";
|
|
8
8
|
import { _ as _sfc_main$4 } from "./AnchoredPositioner.vue_vue_type_script_setup_true_lang-BpBVI2Cu.js";
|
|
9
|
-
import { _ as _sfc_main$5, a as _sfc_main$6 } from "./DismissableLayer.vue_vue_type_script_setup_true_lang-
|
|
9
|
+
import { _ as _sfc_main$5, a as _sfc_main$6 } from "./DismissableLayer.vue_vue_type_script_setup_true_lang-ptH1ttBL.js";
|
|
10
10
|
function toHtmlElement(value) {
|
|
11
11
|
if (typeof HTMLElement === "undefined") return null;
|
|
12
12
|
return value instanceof HTMLElement ? value : null;
|
|
@@ -209,4 +209,4 @@ export {
|
|
|
209
209
|
_sfc_main$1 as b,
|
|
210
210
|
toHtmlElement as t
|
|
211
211
|
};
|
|
212
|
-
//# sourceMappingURL=PopoverContent.vue_vue_type_script_setup_true_lang-
|
|
212
|
+
//# sourceMappingURL=PopoverContent.vue_vue_type_script_setup_true_lang-DYd617X5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PopoverContent.vue_vue_type_script_setup_true_lang-D-OiGICS.js","sources":["../../src/presentation/overlays/OverlayHelpers.ts","../../src/presentation/overlays/popover/Popover.vue","../../src/presentation/overlays/popover/PopoverTrigger.vue","../../src/presentation/overlays/popover/PopoverContent.vue"],"sourcesContent":["// Domain-internal helpers for `overlays/`. Not exported from the group barrel —\n// the \"internal\" signal is absence from `index.ts`, not the file name.\n\n/**\n * The DOM node behind a template ref, or `null`.\n *\n * The `typeof` guard is load-bearing rather than defensive. Every overlay seeds\n * its trigger element from a `watch(..., { immediate: true, flush: 'post' })`,\n * and Vue runs an *immediate* watcher once during SSR — where `HTMLElement` is\n * not a global, so a bare `value instanceof HTMLElement` throws `ReferenceError`\n * and takes the whole server render down. Returning `null` on the server is\n * correct as well as safe: there is no element to anchor to until hydration.\n */\nexport function toHtmlElement(value: unknown): HTMLElement | null {\n if (typeof HTMLElement === 'undefined') return null;\n return value instanceof HTMLElement ? value : null;\n}\n","<script lang=\"ts\">\nimport { inject, type ComputedRef, type InjectionKey, type Ref, type ShallowRef } from 'vue';\nimport type { Placement } from '@floating-ui/vue';\n\n/**\n * The value shared with `PopoverTrigger` / `PopoverContent`.\n *\n * React carried the trigger twice — a ref for imperative focus and a state copy\n * so an initially-open popover re-rendered anchored. A `shallowRef` is already\n * reactive, so one field covers both here.\n */\nexport interface PopoverContextValue {\n /** The resolved open state. Writable — an assignment routes through `setOpen`. */\n open: Ref<boolean>;\n setOpen: (open: boolean) => void;\n /** The trigger element — the positioning anchor and the focus-return target. */\n triggerEl: ShallowRef<HTMLElement | null>;\n placement: ComputedRef<Placement>;\n offset: ComputedRef<number>;\n dismissOnOutsideClick: ComputedRef<boolean>;\n dismissOnEscape: ComputedRef<boolean>;\n}\n\nexport const popoverContextKey: InjectionKey<PopoverContextValue> = Symbol('wow-two.popover');\n\nexport function usePopoverContext(): PopoverContextValue {\n const context = inject(popoverContextKey, null);\n if (!context) throw new Error('Popover.* must be used inside <Popover>');\n return context;\n}\n\n/**\n * The prop surface of `Popover`.\n *\n * `open` and `isOpen` are the same controlled state under two names: `open` is\n * the `v-model:open` binding target, `isOpen` the house boolean spelling that\n * mirrors the rest of the port. `open` wins when both are set. React's\n * `onOpenChange` is the `open-change` emit; `update:open` fires alongside it so\n * `v-model:open` works.\n */\nexport interface PopoverProps {\n /** The open state, controlled. The `v-model:open` binding target. */\n open?: boolean;\n\n /** The open state, controlled — the house spelling of `open`; `open` wins when both are set. */\n isOpen?: boolean;\n\n /** The initial open state when uncontrolled. Default `false`. */\n defaultOpen?: boolean;\n\n /** The Floating UI placement. Default `bottom`. */\n placement?: Placement;\n\n /** The distance between anchor and panel in px. Default 8. */\n offset?: number;\n\n /** The outside-click dismissal toggle. Default `true`. */\n dismissOnOutsideClick?: boolean;\n\n /** The Escape dismissal toggle. Default `true`. */\n dismissOnEscape?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, provide, shallowRef } from 'vue';\nimport { useControlled } from '../../../foundation/hooks';\n\n/**\n * State owner for a Popover tree. Renders only its slot — React returned a bare\n * context Provider, which has no element of its own.\n */\ndefineOptions({ name: 'Popover', inheritAttrs: false });\n\n/** The Popover tree — `PopoverTrigger` and `PopoverContent`. React's `children`. */\ndefineSlots<{ default(): unknown }>();\n\n/** `open` / `isOpen` default to `undefined` so an absent prop cannot read as an explicit `false`. */\nconst props = withDefaults(defineProps<PopoverProps>(), {\n open: undefined,\n isOpen: undefined,\n defaultOpen: false,\n placement: 'bottom',\n offset: 8,\n dismissOnOutsideClick: true,\n dismissOnEscape: true,\n});\n\nconst emit = defineEmits<{\n /** The `v-model:open` half. */\n 'update:open': [open: boolean];\n /** Replaces React's `onOpenChange`. */\n 'open-change': [open: boolean];\n}>();\n\nconst controlled = useControlled<boolean>({\n controlled: () => (props.open !== undefined ? props.open : props.isOpen),\n default: () => props.defaultOpen,\n onChange: (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n});\n\nconst triggerEl = shallowRef<HTMLElement | null>(null);\n\nprovide(popoverContextKey, {\n open: controlled.value,\n setOpen: controlled.setValue,\n triggerEl,\n placement: computed(() => props.placement),\n offset: computed(() => props.offset),\n dismissOnOutsideClick: computed(() => props.dismissOnOutsideClick),\n dismissOnEscape: computed(() => props.dismissOnEscape),\n});\n</script>\n\n<template>\n <slot />\n</template>\n","<script lang=\"ts\">\n/**\n * The prop surface of `PopoverTrigger`.\n *\n * React declared `extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'>`;\n * attributes reach the root through `useAttrs` here, so only `asChild` remains.\n */\nexport interface PopoverTriggerProps {\n /** Merge onto the single slot child instead of rendering a `<button>`. */\n asChild?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useAttrs, useTemplateRef, watch, type ComponentPublicInstance } from 'vue';\nimport { toHtmlElement } from '../OverlayHelpers';\nimport { Primitive } from '../../../foundation/primitives';\nimport { usePopoverContext } from './Popover.vue';\n\n/* Toggles the enclosing `Popover` and doubles as its positioning anchor. */\ndefineOptions({ name: 'PopoverTrigger', inheritAttrs: false });\n\n/** The trigger content — React's `children`. */\ndefineSlots<{ default(): unknown }>();\n\nconst props = withDefaults(defineProps<PopoverTriggerProps>(), { asChild: false });\n\nconst attrs = useAttrs();\nconst context = usePopoverContext();\nconst inner = useTemplateRef<ComponentPublicInstance>('inner');\n\n/* Lifted to a setup const so the template auto-unwraps it (a plain injected object does not). */\nconst isOpen = context.open;\n\n/* React memoized a composed callback ref to keep the anchor node from thrashing; a post-flush watch is the equivalent. */\nwatch(\n inner,\n (instance) => {\n context.triggerEl.value = toHtmlElement(instance?.$el);\n },\n { immediate: true, flush: 'post' },\n);\n\n/**\n * `@click` is declared after `v-bind=\"attrs\"`, so Vue chains the caller's own\n * handler first and this one second — React's `onClick?.(e)` order, which is\n * what makes the `defaultPrevented` opt-out work.\n */\nfunction handleClick(event: MouseEvent): void {\n if (event.defaultPrevented) return;\n context.setOpen(!context.open.value);\n}\n\n/** `Primitive` renders the real element, so its `$el` is this component's root. */\nconst el = computed(() => (inner.value?.$el ?? null) as HTMLElement | null);\n\ndefineExpose({ el });\n</script>\n\n<template>\n <Primitive\n ref=\"inner\"\n as=\"button\"\n :as-child=\"props.asChild\"\n type=\"button\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n v-bind=\"attrs\"\n @click=\"handleClick\"\n >\n <slot />\n </Primitive>\n</template>\n","<script lang=\"ts\">\nimport type {\n SurfaceElevation,\n SurfacePadding,\n SurfaceRadius,\n SurfaceTone,\n SurfaceVariant,\n} from '../../../foundation/utils';\n\n/**\n * Represents the prop surface of `PopoverContent`.\n *\n * React declared the surface axes by `extends SurfaceVariants`; they are\n * spelled out here because the SFC compiler's type resolver cannot follow a\n * `VariantProps<typeof …>` base and fails the build on it. The aliases below\n * are the canonical ones from `foundation/utils`, already locked against the\n * `surfaceVariants` config there, so the two cannot drift.\n */\nexport interface PopoverContentProps {\n /** The bare toggle — skips the surface chrome (bg/border/shadow); keeps only z-index + animation. */\n isBare?: boolean;\n\n /** The visual recipe. */\n variant?: SurfaceVariant;\n\n /** The color tone the recipe is tinted with. */\n tone?: SurfaceTone;\n\n /** The corner rounding. */\n radius?: SurfaceRadius;\n\n /** The inner spacing step. Defaults to `lg` with chrome on, `none` when bare. */\n padding?: SurfacePadding;\n\n /** The shadow depth. */\n elevation?: SurfaceElevation;\n}\n\n/** Contains the default chrome width that preserves the historical look. */\nconst DEFAULT_WIDTH = 'w-72';\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport { cn, surfaceVariants } from '../../../foundation/utils';\nimport {\n AnchoredPositioner,\n DismissableLayer,\n FocusScope,\n Portal,\n Presence,\n} from '../../../foundation/primitives';\nimport { usePopoverContext } from './Popover.vue';\n\n/* The anchored, dismissable popover panel. */\ndefineOptions({ name: 'PopoverContent', inheritAttrs: false });\n\n/** The panel content — React's `children`. */\ndefineSlots<{ default(): unknown }>();\n\nconst props = defineProps<PopoverContentProps>();\n\nconst attrs = useAttrs();\nconst context = usePopoverContext();\n\n/* Refs lifted to setup consts so the template auto-unwraps them (a plain injected object does not). */\nconst isOpen = context.open;\nconst placement = context.placement;\nconst offset = context.offset;\nconst dismissOnEscape = context.dismissOnEscape;\nconst dismissOnOutsideClick = context.dismissOnOutsideClick;\n\nconst anchor = computed(() => context.triggerEl.value);\n\n/** Default to `lg` padding when chrome is on (matches the old `p-4`); the caller can override. */\nconst resolvedPadding = computed(() => props.padding ?? (props.isBare ? 'none' : 'lg'));\n\nconst classes = computed(() =>\n cn(\n /* pop (fade+scale) gated on the portal-root data-state + motion-safe\n so reduced-motion users get no movement. */\n 'outline-none',\n 'motion-safe:group-data-[state=open]:animate-(--animate-pop-in)',\n 'motion-safe:group-data-[state=closed]:animate-(--animate-pop-out) motion-reduce:animate-none',\n !props.isBare &&\n cn(\n DEFAULT_WIDTH,\n surfaceVariants({\n variant: props.variant,\n tone: props.tone,\n radius: props.radius,\n padding: resolvedPadding.value,\n elevation: props.elevation,\n }),\n ),\n attrs.class as string | undefined,\n ),\n);\n\n/** Everything but `class`, which is re-applied through `cn` above. */\nconst rest = computed(() => {\n const { class: _class, ...others } = attrs;\n return others;\n});\n\nfunction handleEscape(): void {\n context.setOpen(false);\n requestAnimationFrame(() => context.triggerEl.value?.focus());\n}\n\nfunction handleOutsidePointerDown(event: PointerEvent): void {\n if (context.triggerEl.value?.contains(event.target as Node)) return;\n context.setOpen(false);\n}\n</script>\n\n<template>\n <!--\n React portalled from *inside* the Presence-cloned root; Vue resolves a cloned\n `ref` through `$el` and a Teleport has no element, so `Portal` is hoisted and\n the `contents` root stays the Presence node — which is what carries\n `data-state` for the panel's `group-data-[state=*]` pop.\n -->\n <Portal>\n <Presence :is-present=\"isOpen\">\n <!--\n `Presence`-clonable root: accepts `data-state` + `ref`, marked `group` so\n the panel animates off it, and holds no layout of its own\n (`display: contents`) so anchored positioning is unaffected.\n -->\n <div class=\"group contents\">\n <!-- z-popover (80) on the SC root (transform makes the stacking context) so a\n popover from a Modal (z-modal, 70) paints above it — both portal to body. -->\n <AnchoredPositioner\n :anchor=\"anchor\"\n :placement=\"placement\"\n :offset=\"offset\"\n class=\"z-popover\"\n >\n <!--\n `FocusScope as-child` merges into `DismissableLayer`, whose own root div\n *is* the panel — React kept a layer div around a separate panel div. The\n two share a box, and collapsing them puts `role`, the surface classes and\n the outside-click boundary on one node.\n -->\n <FocusScope as-child trapped loop>\n <DismissableLayer\n :is-escape-disabled=\"!dismissOnEscape\"\n :is-outside-click-disabled=\"!dismissOnOutsideClick\"\n :on-escape=\"handleEscape\"\n :on-outside-pointer-down=\"handleOutsidePointerDown\"\n role=\"dialog\"\n v-bind=\"rest\"\n :class=\"classes\"\n >\n <slot />\n </DismissableLayer>\n </FocusScope>\n </AnchoredPositioner>\n </div>\n </Presence>\n </Portal>\n</template>\n"],"names":["_renderSlot","_openBlock","_createBlock","_unref","_mergeProps","Portal","_createVNode","_createElementVNode","AnchoredPositioner","FocusScope"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PopoverContent.vue_vue_type_script_setup_true_lang-DYd617X5.js","sources":["../../src/presentation/overlays/OverlayHelpers.ts","../../src/presentation/overlays/popover/Popover.vue","../../src/presentation/overlays/popover/PopoverTrigger.vue","../../src/presentation/overlays/popover/PopoverContent.vue"],"sourcesContent":["// Domain-internal helpers for `overlays/`. Not exported from the group barrel —\n// the \"internal\" signal is absence from `index.ts`, not the file name.\n\n/**\n * The DOM node behind a template ref, or `null`.\n *\n * The `typeof` guard is load-bearing rather than defensive. Every overlay seeds\n * its trigger element from a `watch(..., { immediate: true, flush: 'post' })`,\n * and Vue runs an *immediate* watcher once during SSR — where `HTMLElement` is\n * not a global, so a bare `value instanceof HTMLElement` throws `ReferenceError`\n * and takes the whole server render down. Returning `null` on the server is\n * correct as well as safe: there is no element to anchor to until hydration.\n */\nexport function toHtmlElement(value: unknown): HTMLElement | null {\n if (typeof HTMLElement === 'undefined') return null;\n return value instanceof HTMLElement ? value : null;\n}\n","<script lang=\"ts\">\nimport { inject, type ComputedRef, type InjectionKey, type Ref, type ShallowRef } from 'vue';\nimport type { Placement } from '@floating-ui/vue';\n\n/**\n * The value shared with `PopoverTrigger` / `PopoverContent`.\n *\n * React carried the trigger twice — a ref for imperative focus and a state copy\n * so an initially-open popover re-rendered anchored. A `shallowRef` is already\n * reactive, so one field covers both here.\n */\nexport interface PopoverContextValue {\n /** The resolved open state. Writable — an assignment routes through `setOpen`. */\n open: Ref<boolean>;\n setOpen: (open: boolean) => void;\n /** The trigger element — the positioning anchor and the focus-return target. */\n triggerEl: ShallowRef<HTMLElement | null>;\n placement: ComputedRef<Placement>;\n offset: ComputedRef<number>;\n dismissOnOutsideClick: ComputedRef<boolean>;\n dismissOnEscape: ComputedRef<boolean>;\n}\n\nexport const popoverContextKey: InjectionKey<PopoverContextValue> = Symbol('wow-two.popover');\n\nexport function usePopoverContext(): PopoverContextValue {\n const context = inject(popoverContextKey, null);\n if (!context) throw new Error('Popover.* must be used inside <Popover>');\n return context;\n}\n\n/**\n * The prop surface of `Popover`.\n *\n * `open` and `isOpen` are the same controlled state under two names: `open` is\n * the `v-model:open` binding target, `isOpen` the house boolean spelling that\n * mirrors the rest of the port. `open` wins when both are set. React's\n * `onOpenChange` is the `open-change` emit; `update:open` fires alongside it so\n * `v-model:open` works.\n */\nexport interface PopoverProps {\n /** The open state, controlled. The `v-model:open` binding target. */\n open?: boolean;\n\n /** The open state, controlled — the house spelling of `open`; `open` wins when both are set. */\n isOpen?: boolean;\n\n /** The initial open state when uncontrolled. Default `false`. */\n defaultOpen?: boolean;\n\n /** The Floating UI placement. Default `bottom`. */\n placement?: Placement;\n\n /** The distance between anchor and panel in px. Default 8. */\n offset?: number;\n\n /** The outside-click dismissal toggle. Default `true`. */\n dismissOnOutsideClick?: boolean;\n\n /** The Escape dismissal toggle. Default `true`. */\n dismissOnEscape?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, provide, shallowRef } from 'vue';\nimport { useControlled } from '../../../foundation/hooks';\n\n/**\n * State owner for a Popover tree. Renders only its slot — React returned a bare\n * context Provider, which has no element of its own.\n */\ndefineOptions({ name: 'Popover', inheritAttrs: false });\n\n/** The Popover tree — `PopoverTrigger` and `PopoverContent`. React's `children`. */\ndefineSlots<{ default(): unknown }>();\n\n/** `open` / `isOpen` default to `undefined` so an absent prop cannot read as an explicit `false`. */\nconst props = withDefaults(defineProps<PopoverProps>(), {\n open: undefined,\n isOpen: undefined,\n defaultOpen: false,\n placement: 'bottom',\n offset: 8,\n dismissOnOutsideClick: true,\n dismissOnEscape: true,\n});\n\nconst emit = defineEmits<{\n /** The `v-model:open` half. */\n 'update:open': [open: boolean];\n /** Replaces React's `onOpenChange`. */\n 'open-change': [open: boolean];\n}>();\n\nconst controlled = useControlled<boolean>({\n controlled: () => (props.open !== undefined ? props.open : props.isOpen),\n default: () => props.defaultOpen,\n onChange: (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n});\n\nconst triggerEl = shallowRef<HTMLElement | null>(null);\n\nprovide(popoverContextKey, {\n open: controlled.value,\n setOpen: controlled.setValue,\n triggerEl,\n placement: computed(() => props.placement),\n offset: computed(() => props.offset),\n dismissOnOutsideClick: computed(() => props.dismissOnOutsideClick),\n dismissOnEscape: computed(() => props.dismissOnEscape),\n});\n</script>\n\n<template>\n <slot />\n</template>\n","<script lang=\"ts\">\n/**\n * The prop surface of `PopoverTrigger`.\n *\n * React declared `extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'>`;\n * attributes reach the root through `useAttrs` here, so only `asChild` remains.\n */\nexport interface PopoverTriggerProps {\n /** Merge onto the single slot child instead of rendering a `<button>`. */\n asChild?: boolean;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useAttrs, useTemplateRef, watch, type ComponentPublicInstance } from 'vue';\nimport { toHtmlElement } from '../OverlayHelpers';\nimport { Primitive } from '../../../foundation/primitives';\nimport { usePopoverContext } from './Popover.vue';\n\n/* Toggles the enclosing `Popover` and doubles as its positioning anchor. */\ndefineOptions({ name: 'PopoverTrigger', inheritAttrs: false });\n\n/** The trigger content — React's `children`. */\ndefineSlots<{ default(): unknown }>();\n\nconst props = withDefaults(defineProps<PopoverTriggerProps>(), { asChild: false });\n\nconst attrs = useAttrs();\nconst context = usePopoverContext();\nconst inner = useTemplateRef<ComponentPublicInstance>('inner');\n\n/* Lifted to a setup const so the template auto-unwraps it (a plain injected object does not). */\nconst isOpen = context.open;\n\n/* React memoized a composed callback ref to keep the anchor node from thrashing; a post-flush watch is the equivalent. */\nwatch(\n inner,\n (instance) => {\n context.triggerEl.value = toHtmlElement(instance?.$el);\n },\n { immediate: true, flush: 'post' },\n);\n\n/**\n * `@click` is declared after `v-bind=\"attrs\"`, so Vue chains the caller's own\n * handler first and this one second — React's `onClick?.(e)` order, which is\n * what makes the `defaultPrevented` opt-out work.\n */\nfunction handleClick(event: MouseEvent): void {\n if (event.defaultPrevented) return;\n context.setOpen(!context.open.value);\n}\n\n/** `Primitive` renders the real element, so its `$el` is this component's root. */\nconst el = computed(() => (inner.value?.$el ?? null) as HTMLElement | null);\n\ndefineExpose({ el });\n</script>\n\n<template>\n <Primitive\n ref=\"inner\"\n as=\"button\"\n :as-child=\"props.asChild\"\n type=\"button\"\n aria-haspopup=\"dialog\"\n :aria-expanded=\"isOpen\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n v-bind=\"attrs\"\n @click=\"handleClick\"\n >\n <slot />\n </Primitive>\n</template>\n","<script lang=\"ts\">\nimport type {\n SurfaceElevation,\n SurfacePadding,\n SurfaceRadius,\n SurfaceTone,\n SurfaceVariant,\n} from '../../../foundation/utils';\n\n/**\n * Represents the prop surface of `PopoverContent`.\n *\n * React declared the surface axes by `extends SurfaceVariants`; they are\n * spelled out here because the SFC compiler's type resolver cannot follow a\n * `VariantProps<typeof …>` base and fails the build on it. The aliases below\n * are the canonical ones from `foundation/utils`, already locked against the\n * `surfaceVariants` config there, so the two cannot drift.\n */\nexport interface PopoverContentProps {\n /** The bare toggle — skips the surface chrome (bg/border/shadow); keeps only z-index + animation. */\n isBare?: boolean;\n\n /** The visual recipe. */\n variant?: SurfaceVariant;\n\n /** The color tone the recipe is tinted with. */\n tone?: SurfaceTone;\n\n /** The corner rounding. */\n radius?: SurfaceRadius;\n\n /** The inner spacing step. Defaults to `lg` with chrome on, `none` when bare. */\n padding?: SurfacePadding;\n\n /** The shadow depth. */\n elevation?: SurfaceElevation;\n}\n\n/** Contains the default chrome width that preserves the historical look. */\nconst DEFAULT_WIDTH = 'w-72';\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, useAttrs } from 'vue';\nimport { cn, surfaceVariants } from '../../../foundation/utils';\nimport {\n AnchoredPositioner,\n DismissableLayer,\n FocusScope,\n Portal,\n Presence,\n} from '../../../foundation/primitives';\nimport { usePopoverContext } from './Popover.vue';\n\n/* The anchored, dismissable popover panel. */\ndefineOptions({ name: 'PopoverContent', inheritAttrs: false });\n\n/** The panel content — React's `children`. */\ndefineSlots<{ default(): unknown }>();\n\nconst props = defineProps<PopoverContentProps>();\n\nconst attrs = useAttrs();\nconst context = usePopoverContext();\n\n/* Refs lifted to setup consts so the template auto-unwraps them (a plain injected object does not). */\nconst isOpen = context.open;\nconst placement = context.placement;\nconst offset = context.offset;\nconst dismissOnEscape = context.dismissOnEscape;\nconst dismissOnOutsideClick = context.dismissOnOutsideClick;\n\nconst anchor = computed(() => context.triggerEl.value);\n\n/** Default to `lg` padding when chrome is on (matches the old `p-4`); the caller can override. */\nconst resolvedPadding = computed(() => props.padding ?? (props.isBare ? 'none' : 'lg'));\n\nconst classes = computed(() =>\n cn(\n /* pop (fade+scale) gated on the portal-root data-state + motion-safe\n so reduced-motion users get no movement. */\n 'outline-none',\n 'motion-safe:group-data-[state=open]:animate-(--animate-pop-in)',\n 'motion-safe:group-data-[state=closed]:animate-(--animate-pop-out) motion-reduce:animate-none',\n !props.isBare &&\n cn(\n DEFAULT_WIDTH,\n surfaceVariants({\n variant: props.variant,\n tone: props.tone,\n radius: props.radius,\n padding: resolvedPadding.value,\n elevation: props.elevation,\n }),\n ),\n attrs.class as string | undefined,\n ),\n);\n\n/** Everything but `class`, which is re-applied through `cn` above. */\nconst rest = computed(() => {\n const { class: _class, ...others } = attrs;\n return others;\n});\n\nfunction handleEscape(): void {\n context.setOpen(false);\n requestAnimationFrame(() => context.triggerEl.value?.focus());\n}\n\nfunction handleOutsidePointerDown(event: PointerEvent): void {\n if (context.triggerEl.value?.contains(event.target as Node)) return;\n context.setOpen(false);\n}\n</script>\n\n<template>\n <!--\n React portalled from *inside* the Presence-cloned root; Vue resolves a cloned\n `ref` through `$el` and a Teleport has no element, so `Portal` is hoisted and\n the `contents` root stays the Presence node — which is what carries\n `data-state` for the panel's `group-data-[state=*]` pop.\n -->\n <Portal>\n <Presence :is-present=\"isOpen\">\n <!--\n `Presence`-clonable root: accepts `data-state` + `ref`, marked `group` so\n the panel animates off it, and holds no layout of its own\n (`display: contents`) so anchored positioning is unaffected.\n -->\n <div class=\"group contents\">\n <!-- z-popover (80) on the SC root (transform makes the stacking context) so a\n popover from a Modal (z-modal, 70) paints above it — both portal to body. -->\n <AnchoredPositioner\n :anchor=\"anchor\"\n :placement=\"placement\"\n :offset=\"offset\"\n class=\"z-popover\"\n >\n <!--\n `FocusScope as-child` merges into `DismissableLayer`, whose own root div\n *is* the panel — React kept a layer div around a separate panel div. The\n two share a box, and collapsing them puts `role`, the surface classes and\n the outside-click boundary on one node.\n -->\n <FocusScope as-child trapped loop>\n <DismissableLayer\n :is-escape-disabled=\"!dismissOnEscape\"\n :is-outside-click-disabled=\"!dismissOnOutsideClick\"\n :on-escape=\"handleEscape\"\n :on-outside-pointer-down=\"handleOutsidePointerDown\"\n role=\"dialog\"\n v-bind=\"rest\"\n :class=\"classes\"\n >\n <slot />\n </DismissableLayer>\n </FocusScope>\n </AnchoredPositioner>\n </div>\n </Presence>\n </Portal>\n</template>\n"],"names":["_renderSlot","_openBlock","_createBlock","_unref","_mergeProps","Portal","_createVNode","_createElementVNode","AnchoredPositioner","FocusScope"],"mappings":"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"}
|