@m3-baseui/react-tailwind 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/components/badge/index.js +13 -1
  2. package/dist/components/badge/index.js.map +1 -1
  3. package/dist/components/bottom-app-bar/index.js +13 -1
  4. package/dist/components/bottom-app-bar/index.js.map +1 -1
  5. package/dist/components/bottom-sheet/index.js +13 -1
  6. package/dist/components/bottom-sheet/index.js.map +1 -1
  7. package/dist/components/button/index.d.ts +106 -1
  8. package/dist/components/button/index.js +168 -25
  9. package/dist/components/button/index.js.map +1 -1
  10. package/dist/components/button-group/index.js +13 -1
  11. package/dist/components/button-group/index.js.map +1 -1
  12. package/dist/components/card/index.js +13 -1
  13. package/dist/components/card/index.js.map +1 -1
  14. package/dist/components/carousel/index.js +13 -1
  15. package/dist/components/carousel/index.js.map +1 -1
  16. package/dist/components/date-picker/index.js +13 -1
  17. package/dist/components/date-picker/index.js.map +1 -1
  18. package/dist/components/dialog/index.js +13 -1
  19. package/dist/components/dialog/index.js.map +1 -1
  20. package/dist/components/fab-menu/index.js +13 -1
  21. package/dist/components/fab-menu/index.js.map +1 -1
  22. package/dist/components/item/index.d.ts +5 -5
  23. package/dist/components/item/index.js +13 -1
  24. package/dist/components/item/index.js.map +1 -1
  25. package/dist/components/list/index.js +13 -1
  26. package/dist/components/list/index.js.map +1 -1
  27. package/dist/components/loading-indicator/index.js +13 -1
  28. package/dist/components/loading-indicator/index.js.map +1 -1
  29. package/dist/components/menu/index.js +13 -1
  30. package/dist/components/menu/index.js.map +1 -1
  31. package/dist/components/navigation-drawer/index.js +13 -1
  32. package/dist/components/navigation-drawer/index.js.map +1 -1
  33. package/dist/components/navigation-rail/index.js +13 -1
  34. package/dist/components/navigation-rail/index.js.map +1 -1
  35. package/dist/components/search/index.js +13 -1
  36. package/dist/components/search/index.js.map +1 -1
  37. package/dist/components/segmented-button/index.js +13 -1
  38. package/dist/components/segmented-button/index.js.map +1 -1
  39. package/dist/components/select/index.js +13 -1
  40. package/dist/components/select/index.js.map +1 -1
  41. package/dist/components/side-sheet/index.js +13 -1
  42. package/dist/components/side-sheet/index.js.map +1 -1
  43. package/dist/components/slider/index.js +49 -15
  44. package/dist/components/slider/index.js.map +1 -1
  45. package/dist/components/snackbar/index.d.ts +5 -5
  46. package/dist/components/split-button/index.js +13 -1
  47. package/dist/components/split-button/index.js.map +1 -1
  48. package/dist/components/tabs/index.js +13 -1
  49. package/dist/components/tabs/index.js.map +1 -1
  50. package/dist/components/time-picker/index.js +13 -1
  51. package/dist/components/time-picker/index.js.map +1 -1
  52. package/dist/components/toolbar/index.js +13 -1
  53. package/dist/components/toolbar/index.js.map +1 -1
  54. package/dist/components/tooltip/index.js +13 -1
  55. package/dist/components/tooltip/index.js.map +1 -1
  56. package/dist/components/top-app-bar/index.js +13 -1
  57. package/dist/components/top-app-bar/index.js.map +1 -1
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.js +247 -111
  60. package/dist/index.js.map +1 -1
  61. package/dist/tv.d.ts +13 -8
  62. package/dist/tv.js +13 -1
  63. package/dist/tv.js.map +1 -1
  64. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,20 +1,59 @@
1
1
  "use client";
2
- import { createButton, createIconButton, createSwitch, createCheckbox, createRadio, createRadioGroup, createChip, createTooltip, createRichTooltip, createDialog, createMenu, createTabs, createSlider, createSelect, createTextField, createNavigationBar, createFab, createFabMenu, createDivider, createProgress, createLoadingIndicator, createList, createSnackbar, createItem, createBadge, createCard, createSegmentedButton, createButtonGroup, createSplitButton, createNavigationDrawer, createTopAppBar, createBottomAppBar, createNavigationRail, createBottomSheet, createSideSheet, createSearch, createDatePicker, createTimePicker, createToolbar, createCarousel } from '@m3-baseui/core';
2
+ import { createButton, toToggle, createIconButton, createSwitch, createCheckbox, createRadio, createRadioGroup, createChip, createTooltip, createRichTooltip, createDialog, createMenu, createTabs, createSlider, createSelect, createTextField, createNavigationBar, createFab, createFabMenu, createDivider, createProgress, createLoadingIndicator, createList, createSnackbar, createItem, createBadge, createCard, createSegmentedButton, createButtonGroup, createSplitButton, createNavigationDrawer, createTopAppBar, createBottomAppBar, createNavigationRail, createBottomSheet, createSideSheet, createSearch, createDatePicker, createTimePicker, createToolbar, createCarousel } from '@m3-baseui/core';
3
3
  export { ITEM_LEADING_VARIANTS, LIST_LEADING_VARIANTS, Ripple, ThemeProvider, applyScheme, generateScheme, schemeToCssText, useSnackbar, useTheme } from '@m3-baseui/core';
4
- import { tv } from 'tailwind-variants';
4
+ import { tv as tv$1 } from 'tailwind-variants';
5
+
6
+ // src/components/button/button.ts
7
+ var TYPESCALE = [
8
+ "display-large",
9
+ "display-medium",
10
+ "display-small",
11
+ "headline-large",
12
+ "headline-medium",
13
+ "headline-small",
14
+ "title-large",
15
+ "title-medium",
16
+ "title-small",
17
+ "body-large",
18
+ "body-medium",
19
+ "body-small",
20
+ "label-large",
21
+ "label-medium",
22
+ "label-small"
23
+ ];
24
+ var SHAPE = [
25
+ "none",
26
+ "extra-small",
27
+ "small",
28
+ "medium",
29
+ "large",
30
+ "large-increased",
31
+ "extra-large",
32
+ "extra-large-increased",
33
+ "full"
34
+ ];
35
+ var tv = (options, config) => tv$1(options, {
36
+ ...config,
37
+ twMergeConfig: {
38
+ extend: {
39
+ classGroups: {
40
+ "font-size": [{ text: [...TYPESCALE] }],
41
+ rounded: [{ rounded: [...SHAPE] }]
42
+ }
43
+ }
44
+ }
45
+ });
5
46
 
6
47
  // src/components/button/button.ts
7
48
  var button = tv({
8
49
  base: [
9
- "relative inline-flex items-center justify-center gap-2",
10
- "h-10 px-6 rounded-full overflow-hidden cursor-pointer select-none border-0",
11
- "text-label-large",
12
- // M3 with-icon padding: the icon side trims to 16dp (label side stays 24dp).
13
- "data-[with-start-icon]:pl-4 data-[with-end-icon]:pr-4",
14
- // Icon slot: 18dp, centered.
50
+ "relative inline-flex items-center justify-center",
51
+ "overflow-hidden cursor-pointer select-none border-0",
52
+ // Icon slot: centered; the svg size comes from the `size` variant.
15
53
  "[&_[data-slot=button-icon]]:inline-flex [&_[data-slot=button-icon]]:items-center [&_[data-slot=button-icon]]:justify-center",
16
- "[&_[data-slot=button-icon]>svg]:size-[18px]",
17
- "transition-[box-shadow,background-color,color,border-color] duration-200 ease-[var(--md-sys-motion-easing-standard)]",
54
+ // Motion: Compose uses DefaultEffects (critically-damped spring, no bounce)
55
+ // for the shape/color/elevation transitions — spring-effects-default here.
56
+ "transition-[box-shadow,background-color,color,border-color,border-radius] duration-200 ease-spring-effects-default",
18
57
  // State layer overlay
19
58
  "before:absolute before:inset-0 before:rounded-[inherit] before:bg-current before:opacity-0 before:pointer-events-none",
20
59
  "before:transition-opacity before:duration-100",
@@ -25,20 +64,23 @@ var button = tv({
25
64
  // Focus ring (M3: 3px secondary, 2px offset)
26
65
  "focus-visible:outline-[3px] focus-visible:outline-offset-2 focus-visible:outline-secondary",
27
66
  // Disabled: no interaction, no state layer, no elevation. Per-variant
28
- // colors (container on-surface/12, label on-surface/38) live on each variant.
67
+ // colors (container on-surface/10, label on-surface-variant/38) live on
68
+ // each variant.
29
69
  "disabled:pointer-events-none disabled:shadow-none disabled:before:opacity-0",
30
70
  "data-[disabled]:pointer-events-none data-[disabled]:shadow-none data-[disabled]:before:opacity-0"
31
71
  ],
32
72
  variants: {
33
73
  // M3 elevation per variant: filled/tonal rest level0→hover level1→pressed level0;
34
- // elevated rest level1→hover level2→pressed level1. Disabled container is
35
- // on-surface/12 and label on-surface/38, matching material-web.
74
+ // elevated rest level1→hover level2→pressed level1. Expressive disabled:
75
+ // container on-surface/10, label on-surface-variant/38 — except tonal, which
76
+ // is unchanged upstream (FilledTonalButtonTokens v0_103) and keeps 0.12 /
77
+ // on-surface. Expressive also moves outlined/text labels to on-surface-variant.
36
78
  variant: {
37
79
  filled: [
38
80
  "bg-primary text-on-primary",
39
81
  "hover:shadow-level1 focus-visible:shadow-none active:shadow-none data-[pressed]:shadow-none",
40
- "disabled:bg-on-surface/12 disabled:text-on-surface/38",
41
- "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38"
82
+ "disabled:bg-on-surface/10 disabled:text-on-surface-variant/38",
83
+ "data-[disabled]:bg-on-surface/10 data-[disabled]:text-on-surface-variant/38"
42
84
  ],
43
85
  tonal: [
44
86
  "bg-secondary-container text-on-secondary-container",
@@ -47,28 +89,129 @@ var button = tv({
47
89
  "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38"
48
90
  ],
49
91
  outlined: [
50
- "bg-transparent text-primary border border-outline",
51
- "disabled:text-on-surface/38 disabled:border-on-surface/12",
52
- "data-[disabled]:text-on-surface/38 data-[disabled]:border-on-surface/12"
92
+ "bg-transparent text-on-surface-variant border border-outline-variant",
93
+ // Compose outlinedButtonBorder(enabled=false) tints the outline with
94
+ // DisabledContainerOpacity (0.1), so the disabled border is faint.
95
+ "disabled:text-on-surface-variant/38 disabled:border-outline-variant/10",
96
+ "data-[disabled]:text-on-surface-variant/38 data-[disabled]:border-outline-variant/10"
53
97
  ],
54
98
  elevated: [
55
99
  "bg-surface-container-low text-primary shadow-level1",
56
100
  "hover:shadow-level2 focus-visible:shadow-level1 active:shadow-level1 data-[pressed]:shadow-level1",
57
- "disabled:bg-on-surface/12 disabled:text-on-surface/38",
58
- "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38"
101
+ "disabled:bg-on-surface/10 disabled:text-on-surface-variant/38",
102
+ "data-[disabled]:bg-on-surface/10 data-[disabled]:text-on-surface-variant/38"
59
103
  ],
60
104
  text: [
61
- "bg-transparent text-primary px-3",
62
- "disabled:text-on-surface/38",
63
- "data-[disabled]:text-on-surface/38"
105
+ "bg-transparent text-on-surface-variant",
106
+ "disabled:text-on-surface-variant/38",
107
+ "data-[disabled]:text-on-surface-variant/38"
64
108
  ]
109
+ },
110
+ // Height / horizontal padding / gap / typescale / icon size per Expressive
111
+ // size. The pressed corner morph (PressedContainerShape: XS·S small 8 /
112
+ // M medium 12 / L·XL large 16) rides on data-[pressed]/active here so its
113
+ // attribute-selector specificity wins over the resting `rounded-*`.
114
+ size: {
115
+ xs: [
116
+ // XS is special-cased in Compose Button.kt: contentPaddingFor returns
117
+ // ExtraSmallContentPadding (12dp) and iconSpacingFor returns
118
+ // ExtraSmallIconSpacing (4dp) — tighter than the ButtonXSmallTokens
119
+ // Leading/TrailingSpace (16) and IconLabelSpace (8). S–XL use their tokens.
120
+ "h-8 px-3 gap-1 text-label-large [&_[data-slot=button-icon]>svg]:size-5",
121
+ "data-[pressed]:rounded-small active:rounded-small"
122
+ ],
123
+ s: [
124
+ "h-10 px-4 gap-2 text-label-large [&_[data-slot=button-icon]>svg]:size-5",
125
+ "data-[pressed]:rounded-small active:rounded-small"
126
+ ],
127
+ m: [
128
+ "h-14 px-6 gap-2 text-title-medium [&_[data-slot=button-icon]>svg]:size-6",
129
+ "data-[pressed]:rounded-medium active:rounded-medium"
130
+ ],
131
+ l: [
132
+ "h-24 px-12 gap-3 text-headline-small [&_[data-slot=button-icon]>svg]:size-8",
133
+ "data-[pressed]:rounded-large active:rounded-large"
134
+ ],
135
+ xl: [
136
+ "h-[136px] px-16 gap-4 text-headline-large [&_[data-slot=button-icon]>svg]:size-10",
137
+ "data-[pressed]:rounded-large active:rounded-large"
138
+ ]
139
+ },
140
+ // round = full pill; the square corner is size-specific (compounds below).
141
+ shape: {
142
+ round: "rounded-full",
143
+ square: ""
144
+ },
145
+ // Toggle state, string-keyed so a plain (non-toggle) button — `toggle`
146
+ // unset — fires neither compound below (a boolean variant would default to
147
+ // `off` in tailwind-variants and wrongly apply the unselected look).
148
+ toggle: {
149
+ on: "",
150
+ off: ""
65
151
  }
66
152
  },
153
+ compoundVariants: [
154
+ // ---- Resting square corner (ContainerShapeSquare) ---------------------
155
+ { shape: "square", size: "xs", class: "rounded-medium" },
156
+ // 12dp
157
+ { shape: "square", size: "s", class: "rounded-medium" },
158
+ // 12dp
159
+ { shape: "square", size: "m", class: "rounded-large" },
160
+ // 16dp
161
+ { shape: "square", size: "l", class: "rounded-extra-large" },
162
+ // 28dp
163
+ { shape: "square", size: "xl", class: "rounded-extra-large" },
164
+ // 28dp
165
+ // ---- Selected shape morph: swap to the opposite shape -----------------
166
+ // (listed after the resting corner so tailwind-merge keeps these).
167
+ { shape: "round", toggle: "on", size: "xs", class: "rounded-medium" },
168
+ { shape: "round", toggle: "on", size: "s", class: "rounded-medium" },
169
+ { shape: "round", toggle: "on", size: "m", class: "rounded-large" },
170
+ { shape: "round", toggle: "on", size: "l", class: "rounded-extra-large" },
171
+ { shape: "round", toggle: "on", size: "xl", class: "rounded-extra-large" },
172
+ { shape: "square", toggle: "on", size: "xs", class: "rounded-full" },
173
+ { shape: "square", toggle: "on", size: "s", class: "rounded-full" },
174
+ { shape: "square", toggle: "on", size: "m", class: "rounded-full" },
175
+ { shape: "square", toggle: "on", size: "l", class: "rounded-full" },
176
+ { shape: "square", toggle: "on", size: "xl", class: "rounded-full" },
177
+ // ---- Outlined border width (OutlinedOutlineWidth: L 2 / XL 3 dp) ------
178
+ { variant: "outlined", size: "l", class: "border-2" },
179
+ { variant: "outlined", size: "xl", class: "border-[3px]" },
180
+ // ---- Toggle colors (Selected*/Unselected* tokens) ---------------------
181
+ // filled/tonal: base = default & selected look; `toggle:off` = unselected.
182
+ { variant: "filled", toggle: "off", class: "bg-surface-container text-on-surface-variant" },
183
+ { variant: "tonal", toggle: "off", class: "bg-surface-container text-on-surface-variant" },
184
+ // elevated: distinct selected (primary) & unselected looks.
185
+ { variant: "elevated", toggle: "on", class: "bg-primary text-on-primary" },
186
+ {
187
+ variant: "elevated",
188
+ toggle: "off",
189
+ class: "bg-surface-container-low text-on-surface-variant"
190
+ },
191
+ // outlined: selected fills with the inverse surface (base = unselected).
192
+ {
193
+ variant: "outlined",
194
+ toggle: "on",
195
+ class: [
196
+ "bg-inverse-surface text-inverse-on-surface border-transparent",
197
+ "disabled:bg-on-surface/10 disabled:border-transparent",
198
+ "data-[disabled]:bg-on-surface/10 data-[disabled]:border-transparent"
199
+ ]
200
+ },
201
+ // text: no Selected/Unselected tokens exist upstream (TextButtonTokens),
202
+ // so selection raises the label emphasis to primary (base = unselected
203
+ // on-surface-variant) to communicate the toggle state.
204
+ { variant: "text", toggle: "on", class: "text-primary" }
205
+ ],
67
206
  defaultVariants: {
68
- variant: "filled"
207
+ variant: "filled",
208
+ size: "s",
209
+ shape: "round"
69
210
  }
70
211
  });
71
- var Button = createButton(({ variant }) => button({ variant }));
212
+ var Button = createButton(
213
+ ({ variant, size, shape, selected }) => button({ variant, size, shape, toggle: toToggle(selected) })
214
+ );
72
215
  var WIDTHS = {
73
216
  xs: { narrow: "w-7", default: "w-8", wide: "w-10" },
74
217
  // 28 / 32 / 40
@@ -88,7 +231,7 @@ var widthCompounds = Object.entries(WIDTHS).flatMap(
88
231
  class: klass
89
232
  }))
90
233
  );
91
- var iconButton = tv({
234
+ var iconButton = tv$1({
92
235
  base: [
93
236
  "relative inline-flex items-center justify-center shrink-0",
94
237
  // No `overflow-hidden`: it would clip the 48dp touch target on small sizes.
@@ -184,7 +327,7 @@ var iconButton = tv({
184
327
  var IconButton = createIconButton(
185
328
  ({ variant, selected, size, width }) => iconButton({ variant, selected, size, width })
186
329
  );
187
- var switchTv = tv({
330
+ var switchTv = tv$1({
188
331
  slots: {
189
332
  root: [
190
333
  "group relative inline-flex shrink-0 w-[52px] h-8 rounded-full border-2 box-border cursor-pointer",
@@ -244,7 +387,7 @@ var Switch = createSwitch({
244
387
  iconChecked: s.iconChecked(),
245
388
  iconUnchecked: s.iconUnchecked()
246
389
  });
247
- var checkboxTv = tv({
390
+ var checkboxTv = tv$1({
248
391
  slots: {
249
392
  root: [
250
393
  "group relative inline-flex items-center justify-center shrink-0 box-border",
@@ -300,7 +443,7 @@ var Checkbox = createCheckbox({
300
443
  indicator: c.indicator(),
301
444
  icon: c.icon()
302
445
  });
303
- var radioTv = tv({
446
+ var radioTv = tv$1({
304
447
  slots: {
305
448
  root: [
306
449
  "group relative inline-flex items-center justify-center shrink-0 box-border",
@@ -343,7 +486,7 @@ var radioTv = tv({
343
486
  var r = radioTv();
344
487
  var Radio = createRadio({ root: r.root(), indicator: r.indicator() });
345
488
  var RadioGroup = createRadioGroup("inline-flex flex-col gap-1");
346
- var chipTv = tv({
489
+ var chipTv = tv$1({
347
490
  slots: {
348
491
  root: [
349
492
  "group relative inline-flex items-center justify-center gap-2 box-border",
@@ -437,41 +580,12 @@ var Chip = createChip(({ variant, elevated }) => {
437
580
  icon: c3.icon()
438
581
  };
439
582
  });
440
- var TYPESCALE = [
441
- "display-large",
442
- "display-medium",
443
- "display-small",
444
- "headline-large",
445
- "headline-medium",
446
- "headline-small",
447
- "title-large",
448
- "title-medium",
449
- "title-small",
450
- "body-large",
451
- "body-medium",
452
- "body-small",
453
- "label-large",
454
- "label-medium",
455
- "label-small"
456
- ];
457
- var tv7 = (options, config) => tv(options, {
458
- ...config,
459
- twMergeConfig: {
460
- extend: {
461
- classGroups: {
462
- "font-size": [{ text: [...TYPESCALE] }]
463
- }
464
- }
465
- }
466
- });
467
-
468
- // src/components/tooltip/tooltip.ts
469
583
  var transition = [
470
584
  "origin-[var(--transform-origin)] transition-[opacity,transform] duration-150 ease-standard",
471
585
  "data-[starting-style]:opacity-0 data-[starting-style]:scale-95",
472
586
  "data-[ending-style]:opacity-0 data-[ending-style]:scale-95"
473
587
  ];
474
- var tooltipTv = tv7({
588
+ var tooltipTv = tv({
475
589
  slots: {
476
590
  popup: [
477
591
  "bg-inverse-surface text-inverse-on-surface text-body-small",
@@ -481,7 +595,7 @@ var tooltipTv = tv7({
481
595
  arrow: ["text-inverse-surface"]
482
596
  }
483
597
  });
484
- var richTooltipTv = tv7({
598
+ var richTooltipTv = tv({
485
599
  slots: {
486
600
  popup: [
487
601
  "bg-surface-container text-on-surface shadow-level2",
@@ -508,7 +622,7 @@ var RichTooltip = createRichTooltip({
508
622
  supportingText: r2.supportingText(),
509
623
  actions: r2.actions()
510
624
  });
511
- var dialogTv = tv7({
625
+ var dialogTv = tv({
512
626
  slots: {
513
627
  backdrop: [
514
628
  "fixed inset-0 z-40 bg-scrim/32",
@@ -613,7 +727,7 @@ var menuSelectableItemBase = [
613
727
  ...menuSelectableItemPositionShapeFallback,
614
728
  ...menuSelectableItemDisabled
615
729
  ];
616
- var menuSelectableItemTv = tv7({
730
+ var menuSelectableItemTv = tv({
617
731
  slots: {
618
732
  /** Select row: check + label + optional trailing meta. */
619
733
  selectItem: ["grid grid-cols-[24px_1fr_auto] items-center gap-3", ...menuSelectableItemBase],
@@ -638,7 +752,7 @@ var menuSurfaceBase = [
638
752
  "data-[ending-style]:opacity-0",
639
753
  "focus:outline-none"
640
754
  ];
641
- var menuSurfaceTv = tv7({
755
+ var menuSurfaceTv = tv({
642
756
  slots: {
643
757
  popup: ["max-w-[280px]", ...menuSurfaceBase],
644
758
  groupLabel: "px-3 py-2 text-label-small text-on-surface-variant"
@@ -666,7 +780,7 @@ menuSurfaceTv();
666
780
  // src/components/menu/menu.ts
667
781
  var surface = menuSurfaceTv({ width: "standard", scroll: "none" });
668
782
  var selectable = menuSelectableItem;
669
- var menuTv = tv7({
783
+ var menuTv = tv({
670
784
  slots: {
671
785
  popup: surface.popup(),
672
786
  item: [
@@ -716,7 +830,7 @@ var Menu = createMenu({
716
830
  radioItem: m.radioItem(),
717
831
  itemIndicator: m.itemIndicator()
718
832
  });
719
- var tabsTv = tv7({
833
+ var tabsTv = tv({
720
834
  slots: {
721
835
  root: "flex flex-col",
722
836
  list: [
@@ -775,36 +889,58 @@ var Tabs = createTabs((variant) => {
775
889
  panel: s14.panel()
776
890
  };
777
891
  });
778
- var sliderTv = tv7({
892
+ var sliderTv = tv({
779
893
  slots: {
780
894
  root: "group relative flex items-center select-none w-full touch-none",
781
- control: "relative flex items-center w-full h-10",
895
+ control: "relative flex items-center w-full h-11",
896
+ // Transparent positioning container; the inactive rail lives on the pseudos.
897
+ // `::before` = the rail after the active end (single + range). `::after` =
898
+ // the rail before the active start (range only; it collapses when
899
+ // `--m3-slider-start` is 0). Both offset by the 8px handle gap and keep a 2dp
900
+ // inside corner / full outside corner. Logical inline insets track RTL.
782
901
  track: [
783
- "relative w-full h-1 rounded-full bg-surface-container-highest",
784
- "group-data-[disabled]:bg-on-surface/[0.12]"
785
- ],
902
+ "relative w-full h-4",
903
+ "before:content-[''] before:absolute before:top-0 before:bottom-0 before:end-0",
904
+ "before:[inset-inline-start:calc(var(--m3-slider-end)_+_8px)]",
905
+ "before:bg-secondary-container before:rounded-s-[2px] before:rounded-e-full",
906
+ "group-data-[disabled]:before:bg-on-surface/[0.12]",
907
+ "after:content-[''] after:absolute after:top-0 after:bottom-0 after:start-0",
908
+ "after:[inset-inline-end:calc(100%_-_var(--m3-slider-start)_+_8px)]",
909
+ "after:bg-secondary-container after:rounded-s-full after:rounded-e-[2px]",
910
+ "group-data-[disabled]:after:bg-on-surface/[0.12]"
911
+ ],
912
+ // Active fill. Geometry (absolute insets built from the active fraction + 8px
913
+ // gap) is set inline by the factory; here we own colour + corners. Outer edge
914
+ // full, inner (handle-facing) edge 2dp; a range slider's start edge is inner
915
+ // too (`data-range`).
786
916
  indicator: [
787
- "absolute h-1 rounded-full bg-primary",
917
+ "bg-primary rounded-s-full rounded-e-[2px]",
918
+ "group-data-[range]:rounded-s-[2px]",
788
919
  "group-data-[disabled]:bg-on-surface/[0.38]"
789
920
  ],
921
+ // 4×44dp bar handle, CornerFull. No state layer: it shrinks to 2dp on
922
+ // pressed (data-dragging) / focus via the fast-spatial spring; hover stays
923
+ // 4dp. Disabled keeps the 4dp width (DisabledHandleWidth) and dims to 0.38.
790
924
  thumb: [
791
- "group/thumb relative size-5 rounded-full bg-primary outline-none",
792
- 'before:content-[""] before:absolute before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/2',
793
- "before:size-10 before:rounded-full before:bg-primary before:opacity-0 before:transition-opacity before:duration-100",
794
- "hover:before:opacity-[var(--md-sys-state-hover)]",
795
- "focus-visible:before:opacity-[var(--md-sys-state-focus)]",
796
- "data-[dragging]:before:opacity-[var(--md-sys-state-dragged)]",
925
+ "w-1 h-11 rounded-full bg-primary outline-none",
926
+ "transition-[width] ease-spring-spatial-fast duration-[var(--md-sys-motion-duration-spring-spatial-fast)]",
927
+ "focus-visible:w-0.5 data-[dragging]:w-0.5",
797
928
  "group-data-[disabled]:bg-on-surface/[0.38]"
798
929
  ],
799
930
  value: "text-label-large text-on-surface-variant tabular-nums",
800
931
  tickList: "pointer-events-none absolute inset-0",
932
+ // Stop dots reverse across the tracks: primary on the inactive rail,
933
+ // secondary-container on the active fill; disabled dots are on-surface.
801
934
  tick: [
802
- "absolute size-1 -translate-x-1/2 -translate-y-1/2 rounded-full bg-on-surface-variant",
803
- "data-[active]:bg-on-primary/[0.38]"
935
+ "absolute size-1 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary",
936
+ "data-[active]:bg-secondary-container",
937
+ "group-data-[disabled]:bg-on-surface"
804
938
  ],
939
+ // Floating value indicator: inverse-surface container / inverse-on-surface
940
+ // text, 12dp above the handle.
805
941
  valueLabel: [
806
- "pointer-events-none absolute bottom-full left-1/2 mb-2 -translate-x-1/2 whitespace-nowrap rounded px-2 py-0.5",
807
- "bg-primary text-label-large text-on-primary tabular-nums opacity-0",
942
+ "pointer-events-none absolute bottom-full left-1/2 mb-3 -translate-x-1/2 whitespace-nowrap rounded px-2 py-0.5",
943
+ "bg-inverse-surface text-label-large text-inverse-on-surface tabular-nums opacity-0",
808
944
  "data-[visible]:opacity-100"
809
945
  ]
810
946
  }
@@ -823,7 +959,7 @@ var Slider = createSlider({
823
959
  });
824
960
  var surface2 = menuSurfaceTv({ width: "anchor", scroll: "auto" });
825
961
  var selectable2 = menuSelectableItem;
826
- var selectTv = tv7({
962
+ var selectTv = tv({
827
963
  slots: {
828
964
  trigger: [
829
965
  "group relative inline-flex items-center justify-between gap-2 box-border",
@@ -849,7 +985,7 @@ var selectTv = tv7({
849
985
  groupLabel: surface2.groupLabel()
850
986
  }
851
987
  });
852
- var selectFieldTv = tv7({
988
+ var selectFieldTv = tv({
853
989
  slots: {
854
990
  // The `group` hook lives here (not in engine-neutral core): supporting text
855
991
  // keys its error color off Field.Root's `group-data-[invalid]`.
@@ -955,7 +1091,7 @@ var Select = createSelect(
955
1091
  }
956
1092
  );
957
1093
  var iconVisual = "inline-flex items-center justify-center shrink-0 text-on-surface-variant [&>svg]:size-6";
958
- var textFieldTv = tv({
1094
+ var textFieldTv = tv$1({
959
1095
  slots: {
960
1096
  root: "flex flex-col gap-1 min-w-[210px]",
961
1097
  field: [
@@ -1053,7 +1189,7 @@ var TextField = createTextField(({ variant }) => {
1053
1189
  counter: c3.counter()
1054
1190
  };
1055
1191
  });
1056
- var navigationBarTv = tv({
1192
+ var navigationBarTv = tv$1({
1057
1193
  slots: {
1058
1194
  root: "flex items-stretch justify-around w-full h-20 bg-surface-container",
1059
1195
  item: [
@@ -1108,7 +1244,7 @@ var NavigationBar = createNavigationBar({
1108
1244
  icon: s4.icon(),
1109
1245
  label: s4.label()
1110
1246
  });
1111
- var fabTv = tv({
1247
+ var fabTv = tv$1({
1112
1248
  base: [
1113
1249
  "relative inline-flex items-center justify-center box-border overflow-hidden",
1114
1250
  "border-0 cursor-pointer select-none outline-none",
@@ -1178,7 +1314,7 @@ var fabTv = tv({
1178
1314
  }
1179
1315
  });
1180
1316
  var Fab = createFab(({ size, color, variant }) => fabTv({ size, color, variant }));
1181
- var fabMenuTv = tv7({
1317
+ var fabMenuTv = tv({
1182
1318
  slots: {
1183
1319
  popup: [
1184
1320
  "flex flex-col items-end gap-1 bg-transparent outline-none",
@@ -1217,7 +1353,7 @@ var FabMenu = createFabMenu(({ size, color }) => fabTv({ size, color }), {
1217
1353
  popup: fabMenuTv().popup(),
1218
1354
  item: (color) => fabMenuTv({ color }).item()
1219
1355
  });
1220
- var dividerTv = tv({
1356
+ var dividerTv = tv$1({
1221
1357
  base: "shrink-0 self-stretch border-0 bg-outline-variant",
1222
1358
  variants: {
1223
1359
  orientation: {
@@ -1243,7 +1379,7 @@ var dividerTv = tv({
1243
1379
  }
1244
1380
  });
1245
1381
  var Divider = createDivider(({ inset, orientation }) => dividerTv({ inset, orientation }));
1246
- var linearTv = tv({
1382
+ var linearTv = tv$1({
1247
1383
  slots: {
1248
1384
  // The track-stop dot (primary, full track height) sits at the inline-end via
1249
1385
  // `after:`. It's a determinate-only M3 concept, so it's hidden while
@@ -1299,7 +1435,7 @@ var linearTv = tv({
1299
1435
  ]
1300
1436
  }
1301
1437
  });
1302
- var circularTv = tv({
1438
+ var circularTv = tv$1({
1303
1439
  slots: {
1304
1440
  // Size comes from the factory (inline width/height) so `size` is honored.
1305
1441
  // Indeterminate rotates the whole ring; the arc grows/shrinks via the
@@ -1335,7 +1471,7 @@ var Progress = createProgress({
1335
1471
  },
1336
1472
  circular: { root: c2.root(), track: c2.track(), indicator: c2.indicator() }
1337
1473
  });
1338
- var loadingIndicatorTv = tv7({
1474
+ var loadingIndicatorTv = tv({
1339
1475
  slots: {
1340
1476
  // The SVG is a fixed 38dp active indicator. Uncontained: the box shrinks to
1341
1477
  // the shape. Contained: a 48dp pill wraps it (5dp inset on each side).
@@ -1358,7 +1494,7 @@ var LoadingIndicator = createLoadingIndicator(({ contained }) => {
1358
1494
  const s14 = loadingIndicatorTv({ contained });
1359
1495
  return { root: s14.root(), indicator: s14.indicator() };
1360
1496
  });
1361
- var listTv = tv7({
1497
+ var listTv = tv({
1362
1498
  slots: {
1363
1499
  root: "list-none m-0 px-0 py-2 bg-transparent",
1364
1500
  item: [
@@ -1421,7 +1557,7 @@ var List = createList({
1421
1557
  };
1422
1558
  }
1423
1559
  });
1424
- var snackbarTv = tv({
1560
+ var snackbarTv = tv$1({
1425
1561
  slots: {
1426
1562
  viewport: [
1427
1563
  "fixed bottom-4 left-1/2 -translate-x-1/2 z-50",
@@ -1473,7 +1609,7 @@ var Snackbar = createSnackbar({
1473
1609
  action: s5.action(),
1474
1610
  close: s5.close()
1475
1611
  });
1476
- var itemTv = tv7({
1612
+ var itemTv = tv({
1477
1613
  slots: {
1478
1614
  root: [
1479
1615
  "relative flex w-full items-center gap-4 box-border px-4 py-3 min-h-14 text-left",
@@ -1504,7 +1640,7 @@ var Item = createItem({
1504
1640
  supporting: s6.supporting(),
1505
1641
  trailing: s6.trailing()
1506
1642
  });
1507
- var badgeTv = tv7({
1643
+ var badgeTv = tv({
1508
1644
  base: "pointer-events-none select-none inline-flex items-center justify-center bg-error text-on-error",
1509
1645
  variants: {
1510
1646
  size: {
@@ -1516,7 +1652,7 @@ var badgeTv = tv7({
1516
1652
  var Badge = createBadge({
1517
1653
  root: ({ size }) => badgeTv({ size })
1518
1654
  });
1519
- var cardTv = tv7({
1655
+ var cardTv = tv({
1520
1656
  base: "relative box-border rounded-medium text-on-surface",
1521
1657
  variants: {
1522
1658
  variant: {
@@ -1557,7 +1693,7 @@ var cardTv = tv7({
1557
1693
  var Card = createCard({
1558
1694
  root: ({ variant, interactive }) => cardTv({ variant, interactive })
1559
1695
  });
1560
- var segmentedButtonTv = tv7({
1696
+ var segmentedButtonTv = tv({
1561
1697
  slots: {
1562
1698
  root: "inline-flex items-stretch h-10 rounded-full border border-outline",
1563
1699
  item: [
@@ -1595,7 +1731,7 @@ var SegmentedButton = createSegmentedButton({
1595
1731
  icon: s7.icon(),
1596
1732
  label: s7.label()
1597
1733
  });
1598
- var buttonGroup = tv7({
1734
+ var buttonGroup = tv({
1599
1735
  base: "inline-flex items-center",
1600
1736
  variants: {
1601
1737
  variant: {
@@ -1653,7 +1789,7 @@ var VARIANT_TEXT = [
1653
1789
  "disabled:text-on-surface/38",
1654
1790
  "data-[disabled]:text-on-surface/38"
1655
1791
  ];
1656
- var splitButtonTv = tv7({
1792
+ var splitButtonTv = tv({
1657
1793
  slots: {
1658
1794
  group: "inline-flex items-center gap-0.5",
1659
1795
  // leading: outer (start) corner full, seam (end) corner reduced.
@@ -1703,7 +1839,7 @@ var SplitButton = createSplitButton({
1703
1839
  popup: splitButtonTv().popup(),
1704
1840
  item: splitButtonTv().item()
1705
1841
  });
1706
- var navigationDrawerTv = tv7({
1842
+ var navigationDrawerTv = tv({
1707
1843
  slots: {
1708
1844
  root: "flex flex-col gap-1 box-border w-[360px] p-3 bg-surface-container-low text-on-surface",
1709
1845
  headline: "px-4 pt-4 pb-1 text-title-small text-on-surface-variant",
@@ -1743,7 +1879,7 @@ var NavigationDrawer = createNavigationDrawer({
1743
1879
  label: s8.label(),
1744
1880
  trailing: s8.trailing()
1745
1881
  });
1746
- var topAppBarTv = tv7({
1882
+ var topAppBarTv = tv({
1747
1883
  slots: {
1748
1884
  root: "flex flex-col w-full box-border h-16 bg-surface text-on-surface",
1749
1885
  row: "flex items-center gap-1 h-16 px-1",
@@ -1773,7 +1909,7 @@ var TopAppBar = createTopAppBar((args) => {
1773
1909
  trailing: s14.trailing()
1774
1910
  };
1775
1911
  });
1776
- var bottomAppBarTv = tv7({
1912
+ var bottomAppBarTv = tv({
1777
1913
  slots: {
1778
1914
  root: "flex items-center justify-between w-full box-border h-20 px-1 bg-surface-container text-on-surface-variant",
1779
1915
  actions: "flex items-center gap-1 pl-2 [&_svg]:size-6",
@@ -1786,7 +1922,7 @@ var BottomAppBar = createBottomAppBar({
1786
1922
  actions: s9.actions(),
1787
1923
  fab: s9.fab()
1788
1924
  });
1789
- var navigationRailTv = tv7({
1925
+ var navigationRailTv = tv({
1790
1926
  slots: {
1791
1927
  root: "flex flex-col items-center gap-3 h-full w-20 py-5 bg-surface",
1792
1928
  header: "flex flex-col items-center gap-3 mb-1",
@@ -1840,7 +1976,7 @@ var NavigationRail = createNavigationRail({
1840
1976
  icon: s10.icon(),
1841
1977
  label: s10.label()
1842
1978
  });
1843
- var bottomSheetTv = tv7({
1979
+ var bottomSheetTv = tv({
1844
1980
  slots: {
1845
1981
  backdrop: [
1846
1982
  "fixed inset-0 z-40 bg-scrim/32",
@@ -1872,7 +2008,7 @@ var BottomSheet = createBottomSheet({
1872
2008
  title: s11.title(),
1873
2009
  description: s11.description()
1874
2010
  });
1875
- var sideSheetTv = tv7({
2011
+ var sideSheetTv = tv({
1876
2012
  slots: {
1877
2013
  backdrop: [
1878
2014
  "fixed inset-0 z-40 bg-scrim/32",
@@ -1924,7 +2060,7 @@ var SideSheet = createSideSheet({
1924
2060
  description: s12.description(),
1925
2061
  close: s12.close()
1926
2062
  });
1927
- var searchTv = tv7({
2063
+ var searchTv = tv({
1928
2064
  slots: {
1929
2065
  bar: [
1930
2066
  "flex items-center gap-1 h-14 min-w-[360px] max-w-full pl-4 pr-2",
@@ -1991,7 +2127,7 @@ var Search = createSearch({
1991
2127
  separator: s13.separator(),
1992
2128
  groupLabel: s13.groupLabel()
1993
2129
  });
1994
- var datePickerTv = tv7({
2130
+ var datePickerTv = tv({
1995
2131
  slots: {
1996
2132
  calendar: ["w-[328px] max-w-full p-3 text-on-surface"],
1997
2133
  header: ["flex items-center justify-between gap-2 h-12 pl-3 pr-1"],
@@ -2112,7 +2248,7 @@ var stateLayerBase = [
2112
2248
  "active:before:opacity-[var(--md-sys-state-pressed)]",
2113
2249
  "focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary focus-visible:outline-offset-2"
2114
2250
  ];
2115
- var timePickerTv = tv7({
2251
+ var timePickerTv = tv({
2116
2252
  slots: {
2117
2253
  root: ["inline-flex flex-col items-center p-2 text-on-surface"],
2118
2254
  header: ["flex items-center gap-3 min-h-[98px]"],
@@ -2182,7 +2318,7 @@ var TimePicker = createTimePicker(() => ({
2182
2318
  inputBox: tp.inputBox(),
2183
2319
  inputCaption: tp.inputCaption()
2184
2320
  }));
2185
- var toolbarTv = tv7({
2321
+ var toolbarTv = tv({
2186
2322
  base: "inline-flex items-center justify-center gap-1 box-border rounded-full shadow-level3 [&_svg]:size-6",
2187
2323
  variants: {
2188
2324
  variant: {
@@ -2199,7 +2335,7 @@ var toolbarTv = tv7({
2199
2335
  var Toolbar = createToolbar(
2200
2336
  ({ variant, orientation }) => toolbarTv({ variant, orientation })
2201
2337
  );
2202
- var carouselTv = tv7({
2338
+ var carouselTv = tv({
2203
2339
  slots: {
2204
2340
  root: [
2205
2341
  "flex gap-2 overflow-x-auto snap-x snap-mandatory scroll-smooth",