mtrl 0.10.4 → 0.10.6

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 (230) hide show
  1. package/README.md +15 -5
  2. package/dist/README.md +15 -5
  3. package/dist/components/bottom-app-bar/bottom-app-bar.js +2 -1
  4. package/dist/components/bottom-app-bar/index.d.ts +3 -1
  5. package/dist/components/button/api.js +3 -0
  6. package/dist/components/button/constants.d.ts +2 -0
  7. package/dist/components/button/index.d.ts +1 -0
  8. package/dist/components/button/types.d.ts +7 -1
  9. package/dist/components/button-group/button-group.js +25 -6
  10. package/dist/components/button-group/config.js +2 -2
  11. package/dist/components/button-group/constants.d.ts +8 -2
  12. package/dist/components/button-group/index.d.ts +1 -0
  13. package/dist/components/button-group/types.d.ts +5 -1
  14. package/dist/components/card/index.d.ts +21 -3
  15. package/dist/components/card/index.js +1 -1
  16. package/dist/components/card/types.d.ts +20 -4
  17. package/dist/components/carousel/api.d.ts +1 -0
  18. package/dist/components/carousel/api.js +4 -0
  19. package/dist/components/carousel/features/scroll.d.ts +1 -0
  20. package/dist/components/carousel/features/scroll.js +117 -2
  21. package/dist/components/carousel/types.d.ts +11 -0
  22. package/dist/components/checkbox/api.js +3 -0
  23. package/dist/components/checkbox/config.js +1 -0
  24. package/dist/components/checkbox/types.d.ts +8 -2
  25. package/dist/components/chips/types.d.ts +10 -2
  26. package/dist/components/datepicker/index.d.ts +3 -1
  27. package/dist/components/datepicker/index.js +1 -1
  28. package/dist/components/extended-fab/api.d.ts +2 -0
  29. package/dist/components/extended-fab/api.js +3 -0
  30. package/dist/components/extended-fab/config.d.ts +1 -0
  31. package/dist/components/extended-fab/config.js +1 -0
  32. package/dist/components/extended-fab/types.d.ts +2 -0
  33. package/dist/components/fab/api.d.ts +2 -0
  34. package/dist/components/fab/api.js +3 -0
  35. package/dist/components/fab/config.d.ts +1 -0
  36. package/dist/components/fab/config.js +1 -0
  37. package/dist/components/fab/constants.d.ts +2 -1
  38. package/dist/components/fab/types.d.ts +2 -0
  39. package/dist/components/fab-menu/fab-menu.js +2 -1
  40. package/dist/components/icon-button/api.js +3 -0
  41. package/dist/components/icon-button/constants.d.ts +2 -0
  42. package/dist/components/icon-button/types.d.ts +5 -0
  43. package/dist/components/index.d.ts +18 -5
  44. package/dist/components/index.js +2 -1
  45. package/dist/components/list/types.d.ts +5 -3
  46. package/dist/components/menu/features/keyboard.js +8 -5
  47. package/dist/components/menu/features/opener.js +1 -1
  48. package/dist/components/menu/index.d.ts +1 -0
  49. package/dist/components/navigation-rail/types.d.ts +2 -0
  50. package/dist/components/progress/features/canvas.js +1 -1
  51. package/dist/components/progress/features/colors.d.ts +2 -1
  52. package/dist/components/progress/features/colors.js +20 -10
  53. package/dist/components/radios/api.d.ts +1 -0
  54. package/dist/components/radios/api.js +3 -0
  55. package/dist/components/radios/constants.d.ts +9 -9
  56. package/dist/components/radios/radio.d.ts +1 -0
  57. package/dist/components/radios/radio.js +1 -0
  58. package/dist/components/radios/types.d.ts +10 -3
  59. package/dist/components/search/features/states.d.ts +2 -0
  60. package/dist/components/search/features/states.js +12 -1
  61. package/dist/components/search/features/structure.js +2 -0
  62. package/dist/components/search/types.d.ts +6 -6
  63. package/dist/components/segmented-button/config.js +2 -2
  64. package/dist/components/select/api.js +3 -0
  65. package/dist/components/select/constants.d.ts +1 -1
  66. package/dist/components/select/features.js +2 -0
  67. package/dist/components/select/index.d.ts +1 -0
  68. package/dist/components/select/types.d.ts +6 -0
  69. package/dist/components/split-button/types.d.ts +5 -1
  70. package/dist/components/switch/api.js +3 -0
  71. package/dist/components/switch/config.js +1 -0
  72. package/dist/components/switch/index.d.ts +6 -2
  73. package/dist/components/switch/index.js +1 -1
  74. package/dist/components/switch/types.d.ts +6 -2
  75. package/dist/components/tabs/config.js +2 -2
  76. package/dist/components/tabs/index.d.ts +36 -3
  77. package/dist/components/tabs/index.js +2 -1
  78. package/dist/components/tabs/tab.js +8 -1
  79. package/dist/components/tabs/types.d.ts +3 -1
  80. package/dist/components/tabs/utils.js +2 -1
  81. package/dist/components/textfield/api.d.ts +5 -0
  82. package/dist/components/textfield/api.js +209 -188
  83. package/dist/components/textfield/config.js +4 -3
  84. package/dist/components/textfield/constants.d.ts +24 -7
  85. package/dist/components/textfield/constants.js +9 -7
  86. package/dist/components/textfield/features/index.d.ts +3 -1
  87. package/dist/components/textfield/features/index.js +1 -0
  88. package/dist/components/textfield/features/leading-icon.js +1 -0
  89. package/dist/components/textfield/features/placement.js +15 -2
  90. package/dist/components/textfield/features/required.d.ts +33 -0
  91. package/dist/components/textfield/features/required.js +50 -0
  92. package/dist/components/textfield/features/supporting-text.js +43 -21
  93. package/dist/components/textfield/features/trailing-icon.d.ts +23 -1
  94. package/dist/components/textfield/features/trailing-icon.js +39 -5
  95. package/dist/components/textfield/index.d.ts +16 -1
  96. package/dist/components/textfield/index.js +1 -0
  97. package/dist/components/textfield/textfield.js +2 -2
  98. package/dist/components/textfield/types.d.ts +33 -3
  99. package/dist/components/timepicker/types.d.ts +2 -1
  100. package/dist/components/toolbar/toolbar.js +2 -1
  101. package/dist/components/tooltip/api.js +20 -18
  102. package/dist/components/tooltip/constants.d.ts +4 -1
  103. package/dist/components/top-app-bar/index.d.ts +3 -1
  104. package/dist/components/top-app-bar/top-app-bar.d.ts +2 -57
  105. package/dist/components/top-app-bar/top-app-bar.js +2 -1
  106. package/dist/core/compose/features/input.d.ts +9 -2
  107. package/dist/core/utils/theme.d.ts +6 -2
  108. package/dist/core/utils/theme.js +12 -19
  109. package/dist/elements/carousel.d.ts +5 -0
  110. package/dist/elements/carousel.js +1 -0
  111. package/dist/elements/css/textfield.js +1 -1
  112. package/dist/elements/define.d.ts +8 -0
  113. package/dist/elements/define.js +2 -1
  114. package/dist/elements/dialog.js +1 -1
  115. package/dist/elements/icon-button.d.ts +3 -2
  116. package/dist/elements/index.d.ts +15 -4
  117. package/dist/elements/index.js +2 -1
  118. package/dist/elements/preupgrade.css +1 -1
  119. package/dist/elements/textfield.d.ts +1 -1
  120. package/dist/elements/textfield.js +1 -1
  121. package/dist/index.cjs +0 -0
  122. package/dist/package.json +1 -1
  123. package/dist/react/dialog.d.ts +3 -0
  124. package/dist/react/dialog.js +3 -0
  125. package/dist/react/index.d.ts +4 -1
  126. package/dist/react/index.js +2 -1
  127. package/dist/solid/dialog.d.ts +3 -0
  128. package/dist/solid/dialog.js +3 -0
  129. package/dist/solid/index.d.ts +4 -1
  130. package/dist/solid/index.js +2 -1
  131. package/dist/styles/badge.css +1 -1
  132. package/dist/styles/base.css +2 -2
  133. package/dist/styles/bottom-app-bar.css +1 -1
  134. package/dist/styles/bottom-sheet.css +1 -1
  135. package/dist/styles/button-group.css +1 -1
  136. package/dist/styles/button.css +1 -1
  137. package/dist/styles/card.css +1 -1
  138. package/dist/styles/carousel.css +1 -1
  139. package/dist/styles/checkbox.css +1 -1
  140. package/dist/styles/chips.css +1 -1
  141. package/dist/styles/datepicker.css +1 -1
  142. package/dist/styles/dialog.css +1 -1
  143. package/dist/styles/divider.css +1 -1
  144. package/dist/styles/drawer.css +1 -1
  145. package/dist/styles/extended-fab.css +1 -1
  146. package/dist/styles/fab-menu.css +1 -1
  147. package/dist/styles/fab.css +1 -1
  148. package/dist/styles/icon-button.css +1 -1
  149. package/dist/styles/list.css +1 -1
  150. package/dist/styles/loading-indicator.css +1 -1
  151. package/dist/styles/menu.css +1 -1
  152. package/dist/styles/navigation-rail.css +1 -1
  153. package/dist/styles/progress.css +1 -1
  154. package/dist/styles/radios.css +1 -1
  155. package/dist/styles/search.css +1 -1
  156. package/dist/styles/segmented-button.css +1 -1
  157. package/dist/styles/select.css +1 -1
  158. package/dist/styles/side-sheet.css +1 -1
  159. package/dist/styles/slider.css +1 -1
  160. package/dist/styles/snackbar.css +1 -1
  161. package/dist/styles/split-button.css +1 -1
  162. package/dist/styles/switch.css +1 -1
  163. package/dist/styles/tabs.css +1 -1
  164. package/dist/styles/textfield.css +2 -2
  165. package/dist/styles/timepicker.css +1 -1
  166. package/dist/styles/toolbar.css +1 -1
  167. package/dist/styles/tooltip.css +1 -1
  168. package/dist/styles/top-app-bar.css +1 -1
  169. package/dist/styles/utilities.css +1 -1
  170. package/dist/styles.css +2 -2
  171. package/dist/svelte/Dialog.svelte +3 -0
  172. package/dist/svelte/index.d.ts +5 -1
  173. package/dist/svelte/index.js +5 -1
  174. package/dist/themes/autumn.css +2 -2
  175. package/dist/themes/baseline.css +2 -2
  176. package/dist/themes/brownbeige.css +2 -2
  177. package/dist/themes/browngreen.css +2 -2
  178. package/dist/themes/content.css +2 -2
  179. package/dist/themes/desert.css +2 -2
  180. package/dist/themes/expressive.css +2 -2
  181. package/dist/themes/fidelity.css +2 -2
  182. package/dist/themes/forest.css +2 -2
  183. package/dist/themes/fruit-salad.css +2 -2
  184. package/dist/themes/highcontrast.css +2 -2
  185. package/dist/themes/legacy.css +2 -2
  186. package/dist/themes/material.css +2 -2
  187. package/dist/themes/monochrome.css +2 -2
  188. package/dist/themes/neutral.css +2 -2
  189. package/dist/themes/ocean.css +2 -2
  190. package/dist/themes/rainbow.css +2 -2
  191. package/dist/themes/sageivory.css +2 -2
  192. package/dist/themes/spring.css +2 -2
  193. package/dist/themes/summer.css +2 -2
  194. package/dist/themes/sunset.css +2 -2
  195. package/dist/themes/tealcaramel.css +2 -2
  196. package/dist/themes/vibrant.css +2 -2
  197. package/dist/themes/winter.css +2 -2
  198. package/dist/vue/dialog.d.ts +3 -0
  199. package/dist/vue/dialog.js +3 -0
  200. package/dist/vue/index.d.ts +4 -1
  201. package/dist/vue/index.js +2 -1
  202. package/package.json +1 -1
  203. package/src/styles/abstract/_theme.scss +6 -6
  204. package/src/styles/abstract/_variables.scss +14 -4
  205. package/src/styles/components/_textfield.scss +61 -8
  206. package/src/styles/themes/_autumn.scss +173 -0
  207. package/src/styles/themes/_base-theme.scss +100 -12
  208. package/src/styles/themes/_baseline.scss +172 -0
  209. package/src/styles/themes/_brownbeige.scss +150 -0
  210. package/src/styles/themes/_browngreen.scss +183 -0
  211. package/src/styles/themes/_content.scss +148 -0
  212. package/src/styles/themes/_desert.scss +150 -0
  213. package/src/styles/themes/_expressive.scss +150 -0
  214. package/src/styles/themes/_fidelity.scss +148 -0
  215. package/src/styles/themes/_forest.scss +175 -0
  216. package/src/styles/themes/_fruit-salad.scss +150 -0
  217. package/src/styles/themes/_highcontrast.scss +74 -0
  218. package/src/styles/themes/_legacy.scss +181 -0
  219. package/src/styles/themes/_material.scss +181 -0
  220. package/src/styles/themes/_monochrome.scss +134 -0
  221. package/src/styles/themes/_neutral.scss +150 -0
  222. package/src/styles/themes/_ocean.scss +175 -0
  223. package/src/styles/themes/_rainbow.scss +150 -0
  224. package/src/styles/themes/_sageivory.scss +150 -0
  225. package/src/styles/themes/_spring.scss +171 -0
  226. package/src/styles/themes/_summer.scss +150 -0
  227. package/src/styles/themes/_sunset.scss +175 -0
  228. package/src/styles/themes/_tealcaramel.scss +150 -0
  229. package/src/styles/themes/_vibrant.scss +150 -0
  230. package/src/styles/themes/_winter.scss +181 -0
package/README.md CHANGED
@@ -50,12 +50,12 @@ import 'mtrl/styles/base';
50
50
 
51
51
  ```tsx
52
52
  import 'mtrl/styles/base';
53
- import { Button, Switch, Textfield } from 'mtrl/react';
53
+ import { Button, Switch, TextField } from 'mtrl/react';
54
54
 
55
55
  export function Signup() {
56
56
  return (
57
57
  <form>
58
- <Textfield name="email" type="email" label="Email" required />
58
+ <TextField name="email" type="email" label="Email" required />
59
59
  <Switch name="news" defaultChecked>Newsletter</Switch>
60
60
  <Button type="submit">Sign up</Button>
61
61
  </form>
@@ -67,9 +67,9 @@ export function Signup() {
67
67
 
68
68
  ```typescript
69
69
  import 'mtrl/styles';
70
- import { createButton, createTextfield } from 'mtrl';
70
+ import { createButton, createTextField } from 'mtrl';
71
71
 
72
- const name = createTextfield({ label: 'Name' });
72
+ const name = createTextField({ label: 'Name' });
73
73
  const save = createButton({ text: 'Save', variant: 'filled' });
74
74
  save.disabled.disable();
75
75
 
@@ -100,7 +100,7 @@ Every component comes three ways: a factory (`createButton`), an element (`<m-bu
100
100
  | Containment | Card, Carousel, List, Divider, Dialog, Bottom sheet, Side sheet |
101
101
  | Communication | Badge, Progress, Loading indicator, Snackbar, Tooltip |
102
102
 
103
- The factories are exported from `mtrl`: `createButton`, `createIconButton`, `createButtonGroup`, `createSplitButton`, `createFab`, `createExtendedFab`, `createFabMenu`, `createToolbar`, `createCheckbox`, `createSwitch`, `createRadios`, `createChips` (with `createAssistChip`, `createFilterChip`, `createInputChip` and `createSuggestionChip`), `createSlider`, `createTextfield`, `createSelect`, `createSearch`, `createDatePicker`, `createTimePicker`, `createNavigationRail`, `createDrawer`, `createTabs` and `createTab`, `createMenu`, `createTopAppBar`, `createBottomAppBar`, `createCard` (with `createCardHeader`, `createCardContent`, `createCardMedia` and `createCardActions`), `createCarousel`, `createList`, `createDivider`, `createDialog`, `createBottomSheet`, `createSideSheet`, `createBadge`, `createProgress`, `createLoadingIndicator`, `createSnackbar` and `createTooltip`. Deprecated: `createSegmentedButton` and `createSegment`, replaced by `createButtonGroup` with `kind: 'connected'`.
103
+ The factories are exported from `mtrl`: `createButton`, `createIconButton`, `createButtonGroup`, `createSplitButton`, `createFab`, `createExtendedFab`, `createFabMenu`, `createToolbar`, `createCheckbox`, `createSwitch`, `createRadios`, `createChips` (with `createAssistChip`, `createFilterChip`, `createInputChip` and `createSuggestionChip`), `createSlider`, `createTextField`, `createSelect`, `createSearch`, `createDatePicker`, `createTimePicker`, `createNavigationRail`, `createDrawer`, `createTabs` and `createTab`, `createMenu`, `createTopAppBar`, `createBottomAppBar`, `createCard` (with `createCardHeader`, `createCardContent`, `createCardMedia` and `createCardActions`), `createCarousel`, `createList`, `createDivider`, `createDialog`, `createBottomSheet`, `createSideSheet`, `createBadge`, `createProgress`, `createLoadingIndicator`, `createSnackbar` and `createTooltip`. Deprecated: `createSegmentedButton` and `createSegment`, replaced by `createButtonGroup` with `kind: 'connected'`.
104
104
 
105
105
  ## Styles
106
106
 
@@ -141,6 +141,16 @@ document.documentElement.dataset.themeMode = 'dark';
141
141
 
142
142
  Available themes: `baseline`, `ocean`, `desert`, `forest`, `sunset`, `spring`, `summer`, `autumn`, `brownbeige`, `sageivory`, `tealcaramel` and `highcontrast`. With selective styles, import the theme's entry, for example `mtrl/themes/ocean`.
143
143
 
144
+ Every theme supports `data-theme-contrast="standard"`, `"medium"` and `"high"` on the same element as `data-theme` and `data-theme-mode`:
145
+
146
+ ```html
147
+ <html data-theme="desert" data-theme-mode="dark" data-theme-contrast="high">
148
+ ```
149
+
150
+ Without `data-theme-contrast`, `prefers-contrast: more` selects high contrast on every themed element independently. An explicit `standard` opts out on that element; `medium` overrides the preference too. Contrast settings do not inherit from an ancestor across a nested theme: put `data-theme-contrast` on the same element as each `data-theme`, including nested sections. For example, opting out on the root does not opt out a nested theme without its own `data-theme-contrast="standard"`.
151
+
152
+ The default baseline also supports this setting without `data-theme`. On that unthemed root, both standard and higher contrast follow the OS color scheme and `.dark-theme`, ignoring `data-theme-mode`. Medium and high use M3 contrast levels 0.5 and 1.0; hand-authored themes derive them with Tonal Spot from their documented seed (falling back to their light primary), preserving their light secondary and tertiary hues and chroma. Neutral palettes come from the seed, while standard colors stay unchanged. Success, warning and info keep their existing status colors. The `highcontrast` theme is a theme in its own right and supports all three contrast settings.
153
+
144
154
  M3's scheme variants, generated from the baseline seed, ship as their own entries only (not in the full stylesheet): `neutral`, `vibrant`, `expressive`, `fidelity`, `content`, `monochrome`, `rainbow` and `fruit-salad`, for example `mtrl/themes/vibrant`. `schemeToTokens` (`mtrl/core/theme`) turns any M3 scheme's role colours into these tokens.
145
155
 
146
156
  Deprecated, removed in 1.0: `material` (use `baseline`), `winter` (use `ocean`), `browngreen` (use `brownbeige`) and `legacy`.
package/dist/README.md CHANGED
@@ -50,12 +50,12 @@ import 'mtrl/styles/base';
50
50
 
51
51
  ```tsx
52
52
  import 'mtrl/styles/base';
53
- import { Button, Switch, Textfield } from 'mtrl/react';
53
+ import { Button, Switch, TextField } from 'mtrl/react';
54
54
 
55
55
  export function Signup() {
56
56
  return (
57
57
  <form>
58
- <Textfield name="email" type="email" label="Email" required />
58
+ <TextField name="email" type="email" label="Email" required />
59
59
  <Switch name="news" defaultChecked>Newsletter</Switch>
60
60
  <Button type="submit">Sign up</Button>
61
61
  </form>
@@ -67,9 +67,9 @@ export function Signup() {
67
67
 
68
68
  ```typescript
69
69
  import 'mtrl/styles';
70
- import { createButton, createTextfield } from 'mtrl';
70
+ import { createButton, createTextField } from 'mtrl';
71
71
 
72
- const name = createTextfield({ label: 'Name' });
72
+ const name = createTextField({ label: 'Name' });
73
73
  const save = createButton({ text: 'Save', variant: 'filled' });
74
74
  save.disabled.disable();
75
75
 
@@ -100,7 +100,7 @@ Every component comes three ways: a factory (`createButton`), an element (`<m-bu
100
100
  | Containment | Card, Carousel, List, Divider, Dialog, Bottom sheet, Side sheet |
101
101
  | Communication | Badge, Progress, Loading indicator, Snackbar, Tooltip |
102
102
 
103
- The factories are exported from `mtrl`: `createButton`, `createIconButton`, `createButtonGroup`, `createSplitButton`, `createFab`, `createExtendedFab`, `createFabMenu`, `createToolbar`, `createCheckbox`, `createSwitch`, `createRadios`, `createChips` (with `createAssistChip`, `createFilterChip`, `createInputChip` and `createSuggestionChip`), `createSlider`, `createTextfield`, `createSelect`, `createSearch`, `createDatePicker`, `createTimePicker`, `createNavigationRail`, `createDrawer`, `createTabs` and `createTab`, `createMenu`, `createTopAppBar`, `createBottomAppBar`, `createCard` (with `createCardHeader`, `createCardContent`, `createCardMedia` and `createCardActions`), `createCarousel`, `createList`, `createDivider`, `createDialog`, `createBottomSheet`, `createSideSheet`, `createBadge`, `createProgress`, `createLoadingIndicator`, `createSnackbar` and `createTooltip`. Deprecated: `createSegmentedButton` and `createSegment`, replaced by `createButtonGroup` with `kind: 'connected'`.
103
+ The factories are exported from `mtrl`: `createButton`, `createIconButton`, `createButtonGroup`, `createSplitButton`, `createFab`, `createExtendedFab`, `createFabMenu`, `createToolbar`, `createCheckbox`, `createSwitch`, `createRadios`, `createChips` (with `createAssistChip`, `createFilterChip`, `createInputChip` and `createSuggestionChip`), `createSlider`, `createTextField`, `createSelect`, `createSearch`, `createDatePicker`, `createTimePicker`, `createNavigationRail`, `createDrawer`, `createTabs` and `createTab`, `createMenu`, `createTopAppBar`, `createBottomAppBar`, `createCard` (with `createCardHeader`, `createCardContent`, `createCardMedia` and `createCardActions`), `createCarousel`, `createList`, `createDivider`, `createDialog`, `createBottomSheet`, `createSideSheet`, `createBadge`, `createProgress`, `createLoadingIndicator`, `createSnackbar` and `createTooltip`. Deprecated: `createSegmentedButton` and `createSegment`, replaced by `createButtonGroup` with `kind: 'connected'`.
104
104
 
105
105
  ## Styles
106
106
 
@@ -141,6 +141,16 @@ document.documentElement.dataset.themeMode = 'dark';
141
141
 
142
142
  Available themes: `baseline`, `ocean`, `desert`, `forest`, `sunset`, `spring`, `summer`, `autumn`, `brownbeige`, `sageivory`, `tealcaramel` and `highcontrast`. With selective styles, import the theme's entry, for example `mtrl/themes/ocean`.
143
143
 
144
+ Every theme supports `data-theme-contrast="standard"`, `"medium"` and `"high"` on the same element as `data-theme` and `data-theme-mode`:
145
+
146
+ ```html
147
+ <html data-theme="desert" data-theme-mode="dark" data-theme-contrast="high">
148
+ ```
149
+
150
+ Without `data-theme-contrast`, `prefers-contrast: more` selects high contrast on every themed element independently. An explicit `standard` opts out on that element; `medium` overrides the preference too. Contrast settings do not inherit from an ancestor across a nested theme: put `data-theme-contrast` on the same element as each `data-theme`, including nested sections. For example, opting out on the root does not opt out a nested theme without its own `data-theme-contrast="standard"`.
151
+
152
+ The default baseline also supports this setting without `data-theme`. On that unthemed root, both standard and higher contrast follow the OS color scheme and `.dark-theme`, ignoring `data-theme-mode`. Medium and high use M3 contrast levels 0.5 and 1.0; hand-authored themes derive them with Tonal Spot from their documented seed (falling back to their light primary), preserving their light secondary and tertiary hues and chroma. Neutral palettes come from the seed, while standard colors stay unchanged. Success, warning and info keep their existing status colors. The `highcontrast` theme is a theme in its own right and supports all three contrast settings.
153
+
144
154
  M3's scheme variants, generated from the baseline seed, ship as their own entries only (not in the full stylesheet): `neutral`, `vibrant`, `expressive`, `fidelity`, `content`, `monochrome`, `rainbow` and `fruit-salad`, for example `mtrl/themes/vibrant`. `schemeToTokens` (`mtrl/core/theme`) turns any M3 scheme's role colours into these tokens.
145
155
 
146
156
  Deprecated, removed in 1.0: `material` (use `baseline`), `winter` (use `ocean`), `browngreen` (use `brownbeige`) and `legacy`.
@@ -1,3 +1,4 @@
1
+ import { processClassNames } from "../../core/config/component.js";
1
2
  import { createBase, withElement, withEvents, withLifecycle, } from "../../core/compose/index.js";
2
3
  import { createConfig } from "./config.js";
3
4
  export const createBottomAppBar = (config = {}) => {
@@ -17,7 +18,7 @@ export const createBottomAppBar = (config = {}) => {
17
18
  componentConfig.fabPosition === "center"
18
19
  ? `${component.getClass("bottom-app-bar")}--fab-center`
19
20
  : "",
20
- componentConfig.class,
21
+ processClassNames(componentConfig.className || ""),
21
22
  ].filter((name) => Boolean(name)),
22
23
  attributes: {
23
24
  role: "toolbar",
@@ -5,4 +5,6 @@
5
5
  import { createBottomAppBar } from "./bottom-app-bar.js";
6
6
  export default createBottomAppBar;
7
7
  export { createBottomAppBar };
8
- export type { BottomAppBarConfig, BottomAppBar } from "./types.js";
8
+ export type { BottomAppBarConfig, BottomAppBar as BottomAppBarComponent,
9
+ /** @deprecated Use BottomAppBarComponent, the name every component type has. Removed in 1.0 (FLO-383). */
10
+ BottomAppBar, } from "./types.js";
@@ -54,6 +54,9 @@ export const withAPI = ({ disabled, lifecycle }) => (component) => {
54
54
  disabled.enable();
55
55
  return buttonComponent;
56
56
  },
57
+ isDisabled() {
58
+ return disabled.isDisabled();
59
+ },
57
60
  disable() {
58
61
  disabled.disable();
59
62
  return buttonComponent;
@@ -73,6 +73,8 @@ export declare const BUTTON_CLASSES: {
73
73
  */
74
74
  export declare const DEFAULT_RIPPLE_CONFIG: {
75
75
  readonly DURATION: 450;
76
+ /** @deprecated Has no effect: the option it is the default of is never applied (FLO-268). Removed in 1.0. */
76
77
  readonly TIMING: "cubic-bezier(0.4, 0.0, 0.2, 1)";
78
+ /** @deprecated Has no effect: the option it is the default of is never applied (FLO-268). Removed in 1.0. */
77
79
  readonly OPACITY: readonly ["0.7", "0"];
78
80
  };
@@ -4,4 +4,5 @@
4
4
  */
5
5
  export { default } from "./button.js";
6
6
  export type { ButtonConfig, ButtonComponent, ButtonVariant } from "./types.js";
7
+ export type { ButtonEvents } from "./types.js";
7
8
  export type { ButtonSize, ButtonShape } from "./constants.js";
@@ -197,11 +197,15 @@ export interface ButtonEventPayload<E extends Event = Event> {
197
197
  * compile error rather than a listener that never fires, and a handler's
198
198
  * payload is typed rather than `any`. FLO-114.
199
199
  *
200
- * Only these three exist. `mount` and `unmount` are *not* here: the lifecycle
200
+ * Native forwarding and toggle selection are reported here. `mount` and `unmount` are *not* here: the lifecycle
201
201
  * feature keeps its own emitter and exposes them as `lifecycle.onMount` and
202
202
  * `lifecycle.onUnmount`, so they never reach `component.on`.
203
203
  */
204
204
  export interface ButtonEvents {
205
+ /** Selection notification from a toggle button. */
206
+ change: (payload: {
207
+ selected: boolean;
208
+ }) => void;
205
209
  /** The button was clicked. Not forwarded while the button is disabled. */
206
210
  click: (payload: ButtonEventPayload<MouseEvent>) => void;
207
211
  /** The button took focus. */
@@ -290,6 +294,8 @@ export interface ButtonComponent {
290
294
  * @returns The button component for chaining
291
295
  */
292
296
  disable: () => ButtonComponent;
297
+ /** Whether the button is disabled (FLO-384) */
298
+ isDisabled: () => boolean;
293
299
  /**
294
300
  * Sets the button's text content
295
301
  * @param content - Text content
@@ -56,6 +56,8 @@ const createButtonGroup = (config = {}) => {
56
56
  const releasePress = () => {
57
57
  buttons.forEach(b => {
58
58
  b.element.style.width = '';
59
+ b.element.style.minWidth = '';
60
+ b.element.style.maxWidth = '';
59
61
  b.element.style.paddingLeft = '';
60
62
  b.element.style.paddingRight = '';
61
63
  });
@@ -70,26 +72,40 @@ const createButtonGroup = (config = {}) => {
70
72
  return;
71
73
  const view = component.element.ownerDocument.defaultView;
72
74
  const padding = (i, side) => view ? parseFloat(view.getComputedStyle(buttons[i].element)[side]) || 0 : 0;
75
+ const rtl = view?.getComputedStyle(component.element).direction === 'rtl';
73
76
  const previous = buttons[index - 1] ? index - 1 : -1;
74
77
  const next = buttons[index + 1] ? index + 1 : -1;
75
78
  const middle = previous >= 0 && next >= 0;
76
79
  const share = expandedRatio * widths[index] / (middle ? 2 : 1);
77
80
  let growth = 0;
81
+ const apply = [];
78
82
  const compress = (i, side) => {
79
83
  const limit = Math.min(share, BUTTON_GROUP_COMPRESSION_LIMIT, widths[i]);
80
84
  if (limit <= 0)
81
85
  return;
82
- buttons[i].element.style.width = `${widths[i] - limit}px`;
86
+ const el = buttons[i].element;
87
+ const to = widths[i] - limit;
88
+ el.style.minWidth = `${to}px`;
89
+ el.style.width = `${widths[i]}px`;
83
90
  const facing = padding(i, side);
84
- if (facing > 0)
85
- buttons[i].element.style[side] = `${Math.max(0, facing - limit)}px`;
91
+ apply.push(() => {
92
+ el.style.width = `${to}px`;
93
+ if (facing > 0)
94
+ el.style[side] = `${Math.max(0, facing - limit)}px`;
95
+ });
86
96
  growth += limit;
87
97
  };
88
98
  if (previous >= 0)
89
- compress(previous, 'paddingRight');
99
+ compress(previous, rtl ? 'paddingLeft' : 'paddingRight');
90
100
  if (next >= 0)
91
- compress(next, 'paddingLeft');
92
- buttons[index].element.style.width = `${widths[index] + growth}px`;
101
+ compress(next, rtl ? 'paddingRight' : 'paddingLeft');
102
+ const pressed = buttons[index].element;
103
+ const to = widths[index] + growth;
104
+ pressed.style.maxWidth = `${to}px`;
105
+ pressed.style.width = `${widths[index]}px`;
106
+ void pressed.offsetWidth;
107
+ apply.forEach(fn => fn());
108
+ pressed.style.width = `${to}px`;
93
109
  document.addEventListener('pointerup', releasePress);
94
110
  document.addEventListener('pointercancel', releasePress);
95
111
  };
@@ -287,6 +303,9 @@ const createButtonGroup = (config = {}) => {
287
303
  });
288
304
  return this;
289
305
  },
306
+ isDisabled() {
307
+ return component.element.classList.contains(`${baseConfig.prefix}-button-group--disabled`);
308
+ },
290
309
  disable() {
291
310
  component.element.classList.add(`${baseConfig.prefix}-button-group--disabled`);
292
311
  buttons.forEach(button => {
@@ -1,4 +1,4 @@
1
- import { createComponentConfig } from "../../core/config/component.js";
1
+ import { createComponentConfig, processClassNames } from "../../core/config/component.js";
2
2
  import { cornerToken } from "../../core/theme/shape.js";
3
3
  import { BUTTON_GROUP_DEFAULTS, BUTTON_GROUP_DENSITY, BUTTON_GROUP_SIZE_TOKENS, BUTTON_GROUP_CONNECTED_GAP, BUTTON_GROUP_CONNECTED_PRESSED_CORNER, BUTTON_GROUP_DENSITY_STEP } from "./constants.js";
4
4
  export const DEFAULT_CONFIG = {
@@ -41,7 +41,7 @@ export const getContainerConfig = (config) => {
41
41
  'data-labels': labels
42
42
  },
43
43
  className: [
44
- config.class,
44
+ processClassNames(config.className || ""),
45
45
  labels === 'selected' ? `${config.prefix}-button-group--labels-selected` : null,
46
46
  config.disabled ? `${config.prefix}-button-group--disabled` : null,
47
47
  `${config.prefix}-button-group--${orientation}`,
@@ -160,9 +160,15 @@ export declare const BUTTON_GROUP_DEFAULTS: {
160
160
  readonly EQUAL_WIDTH: false;
161
161
  /** Default ripple animation duration in milliseconds */
162
162
  readonly RIPPLE_DURATION: 300;
163
- /** Default ripple animation timing function */
163
+ /**
164
+ * Default ripple animation timing function
165
+ * @deprecated Has no effect: the option it is the default of is never applied (FLO-268). Removed in 1.0.
166
+ */
164
167
  readonly RIPPLE_TIMING: "cubic-bezier(0.4, 0, 0.2, 1)";
165
- /** Default ripple opacity values [start, end] */
168
+ /**
169
+ * Default ripple opacity values [start, end]
170
+ * @deprecated Has no effect: the option it is the default of is never applied (FLO-268). Removed in 1.0.
171
+ */
166
172
  readonly RIPPLE_OPACITY: [string, string];
167
173
  };
168
174
  /**
@@ -10,4 +10,5 @@
10
10
  export { default as createButtonGroup } from "./button-group.js";
11
11
  export { default } from "./button-group.js";
12
12
  export type { ButtonGroupConfig, ButtonGroupComponent, ButtonGroupItemConfig, ButtonGroupEvent, ButtonGroupEventType, ButtonGroupVariant, ButtonGroupOrientation, ButtonGroupDensity } from "./types.js";
13
+ export type { ButtonGroupKind, ButtonGroupSelection, ButtonGroupChangeEvent } from "./types.js";
13
14
  export { BUTTON_GROUP_VARIANTS, BUTTON_GROUP_ORIENTATIONS, BUTTON_GROUP_DENSITY, BUTTON_GROUP_EVENTS, BUTTON_GROUP_DEFAULTS, BUTTON_GROUP_CLASSES } from "./constants.js";
@@ -217,7 +217,9 @@ export interface ButtonGroupConfig {
217
217
  */
218
218
  ariaLabel?: string;
219
219
  /**
220
- * Event handlers for button group events
220
+ * Event handlers for button group events. On 0.10.x this map is accepted
221
+ * and never called: subscribe with `on(event, handler)` on the group. In 1.0
222
+ * the handlers run, with the listener's argument.
221
223
  */
222
224
  on?: {
223
225
  click?: (event: ButtonGroupEvent) => void;
@@ -290,6 +292,8 @@ export interface ButtonGroupComponent {
290
292
  * @returns The ButtonGroupComponent for chaining
291
293
  */
292
294
  disable: () => ButtonGroupComponent;
295
+ /** Whether the whole group is disabled (FLO-384) */
296
+ isDisabled: () => boolean;
293
297
  /**
294
298
  * Enables a specific button by index
295
299
  * @param index - Button index
@@ -65,7 +65,25 @@ export { default } from "./card.js";
65
65
  *
66
66
  * These types define the structure and behavior of the Card component.
67
67
  */
68
- export type { CardVariant, CardElevationLevel, CardSchema, CardHeaderConfig, CardContentConfig, CardActionsConfig, CardMediaConfig, CardAriaAttributes, CardComponent, CardEvents, LoadingFeature, ExpandableFeature, SwipeableFeature, } from "./types.js";
68
+ export type { CardVariant, CardElevationLevel, CardSchema as CardConfig,
69
+ /** @deprecated Use CardConfig. Removed in 1.0 (FLO-383). */
70
+ CardSchema, CardHeaderConfig, CardContentConfig, CardActionsConfig, CardMediaConfig, CardAriaAttributes, CardComponent, CardEvents,
71
+ /** @deprecated Internal, no replacement: removed from mtrl/components/card in 1.0.0 (FLO-381). */
72
+ LoadingFeature,
73
+ /** @deprecated Internal, no replacement: removed from mtrl/components/card in 1.0.0 (FLO-381). */
74
+ ExpandableFeature,
75
+ /** @deprecated Internal, no replacement: removed from mtrl/components/card in 1.0.0 (FLO-381). */
76
+ SwipeableFeature, } from "./types.js";
69
77
  export { createCardContent, createCardHeader, createCardActions, createCardMedia, } from "./content.js";
70
- export { withAPI } from "./api.js";
71
- export { withLoading, withExpandable, withSwipeable, withElevation, } from "./features.js";
78
+ export {
79
+ /** @deprecated Internal, no replacement: removed from mtrl/components/card in 1.0.0 (FLO-381). */
80
+ withAPI, } from "./api.js";
81
+ export {
82
+ /** @deprecated Internal, no replacement: removed from mtrl/components/card in 1.0.0 (FLO-381). */
83
+ withLoading,
84
+ /** @deprecated Internal, no replacement: removed from mtrl/components/card in 1.0.0 (FLO-381). */
85
+ withExpandable,
86
+ /** @deprecated Internal, no replacement: removed from mtrl/components/card in 1.0.0 (FLO-381). */
87
+ withSwipeable,
88
+ /** @deprecated Internal, no replacement: removed from mtrl/components/card in 1.0.0 (FLO-381). */
89
+ withElevation, } from "./features.js";
@@ -1,4 +1,4 @@
1
1
  export { default } from "./card.js";
2
2
  export { createCardContent, createCardHeader, createCardActions, createCardMedia, } from "./content.js";
3
- export { withAPI } from "./api.js";
3
+ export { withAPI, } from "./api.js";
4
4
  export { withLoading, withExpandable, withSwipeable, withElevation, } from "./features.js";
@@ -224,7 +224,7 @@ export interface BaseComponent {
224
224
  getElementClass: (base: string, element: string) => string;
225
225
  /** Add CSS class(es) */
226
226
  addClass: (...classes: string[]) => BaseComponent;
227
- /** Emit an event */
227
+ /** Emit an event. In 1.0, `emit` accepts only the card's own events ({@link CardEvents}). */
228
228
  emit?: (event: string, data?: unknown) => void;
229
229
  /** Component configuration */
230
230
  config: CardComponentConfig;
@@ -291,6 +291,10 @@ export interface CardComponentConfig extends CardSchema {
291
291
  * a draggable one emits `dragstart` and `dragend`.
292
292
  */
293
293
  export interface CardEvents {
294
+ /** Presentation state after expanding or collapsing. */
295
+ expandedChanged: (payload: {
296
+ expanded: boolean;
297
+ }) => void;
294
298
  click: (payload: ForwardedEventPayload<MouseEvent, HTMLElement>) => void;
295
299
  mouseenter: (payload: ForwardedEventPayload<MouseEvent, HTMLElement>) => void;
296
300
  mouseleave: (payload: ForwardedEventPayload<MouseEvent, HTMLElement>) => void;
@@ -439,11 +443,23 @@ export interface CardComponent extends BaseComponent {
439
443
  * ```
440
444
  */
441
445
  destroy: () => void;
442
- /** Optional loading feature */
446
+ /**
447
+ * Optional loading feature
448
+ * @deprecated Never set by `createCard`: only the deprecated `withLoading` feature adds it.
449
+ * Removed in 1.0 with that feature (FLO-381).
450
+ */
443
451
  loading?: LoadingFeature;
444
- /** Optional expandable feature */
452
+ /**
453
+ * Optional expandable feature
454
+ * @deprecated Never set by `createCard`: only the deprecated `withExpandable` feature adds it.
455
+ * Removed in 1.0 with that feature (FLO-381).
456
+ */
445
457
  expandable?: ExpandableFeature;
446
- /** Optional swipeable feature */
458
+ /**
459
+ * Optional swipeable feature
460
+ * @deprecated Never set by `createCard`: only the deprecated `withSwipeable` feature adds it.
461
+ * Removed in 1.0 with that feature (FLO-381).
462
+ */
447
463
  swipeable?: SwipeableFeature;
448
464
  }
449
465
  /**
@@ -9,6 +9,7 @@ interface ApiComponent {
9
9
  next: () => void;
10
10
  prev: () => void;
11
11
  goTo: (index: number) => void;
12
+ setWheel: (on: boolean) => void;
12
13
  lifecycle?: {
13
14
  destroy: () => void;
14
15
  };
@@ -16,6 +16,10 @@ export const withAPI = () => (component) => {
16
16
  component.goTo(index);
17
17
  return api;
18
18
  },
19
+ setWheel(on) {
20
+ component.setWheel(on);
21
+ return api;
22
+ },
19
23
  getCurrentSlide: () => component.getCurrentSlide(),
20
24
  getVariant: () => component.getVariant(),
21
25
  addSlide(slide, index) {
@@ -6,6 +6,7 @@ interface ScrollComponent {
6
6
  next: () => void;
7
7
  prev: () => void;
8
8
  goTo: (index: number) => void;
9
+ setWheel: (on: boolean) => void;
9
10
  lifecycle: {
10
11
  destroy: () => void;
11
12
  };
@@ -5,6 +5,7 @@ import { multiBrowseKeylines, heroKeylines, uncontainedKeylines, fullScreenKeyli
5
5
  import { createStrategy, keylinesForScrollOffset, snapPositionOffset, maxScrollOffset, placeItem, } from "../strategy.js";
6
6
  const FLING_VELOCITY = 0.4;
7
7
  const DRAG_THRESHOLD = 4;
8
+ const WHEEL_QUIET = 120;
8
9
  export const withScroll = (config) => (component) => {
9
10
  const { variant, gap, padding, snap } = resolveLayoutDefaults(config);
10
11
  const vertical = variant === CAROUSEL_VARIANTS.FULL_SCREEN;
@@ -25,6 +26,7 @@ export const withScroll = (config) => (component) => {
25
26
  const prefix = component.getClass("carousel");
26
27
  const snapClass = `${prefix}__snap`;
27
28
  element.classList.toggle(`${prefix}--snap`, snap);
29
+ let lastWheel = -Infinity;
28
30
  let strategy = null;
29
31
  let count = 0;
30
32
  let containerSize = 0;
@@ -172,6 +174,7 @@ export const withScroll = (config) => (component) => {
172
174
  }
173
175
  };
174
176
  const rebuild = () => {
177
+ stopWheel();
175
178
  build();
176
179
  if (strategy) {
177
180
  expect(currentIndex);
@@ -180,6 +183,7 @@ export const withScroll = (config) => (component) => {
180
183
  layout();
181
184
  };
182
185
  const goTo = (index) => {
186
+ stopWheel();
183
187
  if (!count)
184
188
  return;
185
189
  const target = Math.min(Math.max(index, 0), count - 1);
@@ -199,6 +203,7 @@ export const withScroll = (config) => (component) => {
199
203
  return item ? slideElements.indexOf(item) : -1;
200
204
  };
201
205
  const handleKeyDown = (e) => {
206
+ stopWheel();
202
207
  const from = indexOf(e.target);
203
208
  if (from < 0)
204
209
  return;
@@ -238,10 +243,12 @@ export const withScroll = (config) => (component) => {
238
243
  delete element.dataset.settling;
239
244
  };
240
245
  const handlePointerDown = (e) => {
246
+ stopWheel();
241
247
  clearPending();
242
248
  if (e.pointerType !== "mouse" || e.button !== 0 || !strategy)
243
249
  return;
244
250
  dragging = true;
251
+ lastWheel = -Infinity;
245
252
  dragged = false;
246
253
  dragStart = vertical ? e.clientY : e.clientX;
247
254
  dragLast = dragStart;
@@ -304,9 +311,115 @@ export const withScroll = (config) => (component) => {
304
311
  e.stopPropagation();
305
312
  }
306
313
  };
314
+ let wheelDirection = 0;
315
+ let wheelStart = 0;
316
+ let wheelDelta = 0;
317
+ let wheelTarget = 0;
318
+ let wheelFrame = 0;
319
+ let wheelPosition = 0;
320
+ let wheelVelocity = 0;
321
+ let wheelTime = 0;
322
+ let wheelSnap = null;
323
+ let wheelSnapPriority = "";
324
+ const stopWheel = (resetGesture = true) => {
325
+ if (wheelFrame)
326
+ window.cancelAnimationFrame(wheelFrame);
327
+ wheelFrame = 0;
328
+ wheelVelocity = 0;
329
+ if (resetGesture)
330
+ lastWheel = -Infinity;
331
+ if (wheelSnap !== null) {
332
+ scroller.style.setProperty("scroll-snap-type", wheelSnap, wheelSnapPriority);
333
+ wheelSnap = null;
334
+ clearPending();
335
+ }
336
+ };
337
+ const glide = (now) => {
338
+ const dt = (now - wheelTime) / 1000;
339
+ wheelTime = now;
340
+ const offset = wheelPosition - wheelTarget;
341
+ const decay = Math.exp(-12 * dt);
342
+ const carry = wheelVelocity + 12 * offset;
343
+ wheelPosition = wheelTarget + (offset + carry * dt) * decay;
344
+ wheelVelocity = (wheelVelocity - 12 * carry * dt) * decay;
345
+ const resting = wheelDirection * (wheelPosition - wheelTarget) >= 0 ||
346
+ (Math.abs(wheelPosition - wheelTarget) < 0.5 && Math.abs(wheelVelocity) < 5);
347
+ scroller.scrollLeft = resting ? wheelTarget : wheelPosition;
348
+ if (resting)
349
+ stopWheel(false);
350
+ else
351
+ wheelFrame = window.requestAnimationFrame(glide);
352
+ };
353
+ const handleTouchStart = () => {
354
+ stopWheel();
355
+ clearPending();
356
+ };
357
+ const handleWheel = (e) => {
358
+ if (e.ctrlKey || dragging || Math.abs(e.deltaX) >= Math.abs(e.deltaY) || !strategy)
359
+ return;
360
+ const position = scrollPosition();
361
+ const end = snapPositions[count - 1] ?? 0;
362
+ const direction = Math.sign(e.deltaY);
363
+ if (direction < 0 ? position <= 1 : position >= end - 1)
364
+ return;
365
+ e.preventDefault();
366
+ if (direction !== wheelDirection)
367
+ stopWheel();
368
+ if (e.timeStamp - lastWheel >= WHEEL_QUIET || direction !== wheelDirection) {
369
+ wheelStart = position;
370
+ wheelDelta = 0;
371
+ wheelTarget = position;
372
+ }
373
+ lastWheel = e.timeStamp;
374
+ wheelDirection = direction;
375
+ const unit = e.deltaMode === 1
376
+ ? parseFloat(window.getComputedStyle(scroller).lineHeight) || 16
377
+ : e.deltaMode === 2 ? containerSize : 1;
378
+ wheelDelta += e.deltaY * unit;
379
+ const destination = Math.max(0, Math.min(end, wheelStart + wheelDelta));
380
+ let index = direction > 0 ? count - 1 : 0;
381
+ for (let i = direction > 0 ? 0 : count - 1; i >= 0 && i < count; i += direction) {
382
+ if (direction * (snapPositions[i] - destination) >= 0 &&
383
+ direction * (snapPositions[i] - wheelStart) > 0) {
384
+ index = i;
385
+ break;
386
+ }
387
+ }
388
+ const target = snapPositions[index];
389
+ if (direction * (target - wheelTarget) > 0) {
390
+ wheelTarget = target;
391
+ expect(index);
392
+ if (reduceMotion?.matches) {
393
+ setScrollPosition(target, false);
394
+ }
395
+ else if (!wheelFrame) {
396
+ wheelSnap = scroller.style.getPropertyValue("scroll-snap-type");
397
+ wheelSnapPriority = scroller.style.getPropertyPriority("scroll-snap-type");
398
+ scroller.style.setProperty("scroll-snap-type", "none");
399
+ scroller.scrollLeft = position;
400
+ wheelPosition = position;
401
+ wheelTime = performance.now();
402
+ wheelFrame = window.requestAnimationFrame(glide);
403
+ }
404
+ if (index !== currentIndex) {
405
+ currentIndex = index;
406
+ emitChange();
407
+ }
408
+ }
409
+ else {
410
+ expect(currentIndex);
411
+ }
412
+ };
413
+ const setWheel = (on) => {
414
+ scroller.removeEventListener("wheel", handleWheel);
415
+ stopWheel();
416
+ if (on && !vertical)
417
+ scroller.addEventListener("wheel", handleWheel, { passive: false });
418
+ };
307
419
  scroller.addEventListener("scroll", layout, { passive: true });
308
420
  scroller.addEventListener("wheel", clearPending, { passive: true });
309
- scroller.addEventListener("touchstart", clearPending, { passive: true });
421
+ setWheel(!!config.wheel);
422
+ scroller.addEventListener("touchstart", handleTouchStart, { passive: true });
310
423
  scroller.addEventListener("keydown", handleKeyDown);
311
424
  scroller.addEventListener("focusin", handleFocusIn);
312
425
  scroller.addEventListener("pointerdown", handlePointerDown);
@@ -326,15 +439,17 @@ export const withScroll = (config) => (component) => {
326
439
  enhanced.next = next;
327
440
  enhanced.prev = prev;
328
441
  enhanced.goTo = goTo;
442
+ enhanced.setWheel = setWheel;
329
443
  enhanced.lifecycle = {
330
444
  destroy: () => {
445
+ setWheel(false);
331
446
  restoreSnap();
332
447
  resizeObserver?.disconnect();
333
448
  reduceMotion?.removeEventListener?.("change", rebuild);
334
449
  clearPending();
335
450
  scroller.removeEventListener("scroll", layout);
336
451
  scroller.removeEventListener("wheel", clearPending);
337
- scroller.removeEventListener("touchstart", clearPending);
452
+ scroller.removeEventListener("touchstart", handleTouchStart);
338
453
  scroller.removeEventListener("keydown", handleKeyDown);
339
454
  scroller.removeEventListener("focusin", handleFocusIn);
340
455
  scroller.removeEventListener("pointerdown", handlePointerDown);