@shortfuse/materialdesignweb 0.9.0 → 0.9.2

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 (282) hide show
  1. package/README.md +50 -206
  2. package/components/Badge.js +5 -2
  3. package/components/Body.js +4 -0
  4. package/components/BottomAppBar.js +6 -2
  5. package/components/BottomSheet.js +62 -14
  6. package/components/Button.js +20 -0
  7. package/components/Card.js +20 -3
  8. package/components/Checkbox.js +8 -0
  9. package/components/CheckboxIcon.js +9 -3
  10. package/components/Chip.js +5 -2
  11. package/components/Dialog.js +22 -3
  12. package/components/DialogActions.js +4 -0
  13. package/components/Display.js +9 -0
  14. package/components/Divider.js +5 -0
  15. package/components/Fab.js +11 -0
  16. package/components/FabContainer.js +9 -0
  17. package/components/FilterChip.js +9 -0
  18. package/components/Grid.js +11 -0
  19. package/components/Headline.js +4 -0
  20. package/components/Icon.js +27 -3
  21. package/components/IconButton.js +8 -2
  22. package/components/Input.js +87 -14
  23. package/components/InputChip.js +33 -1
  24. package/components/Label.js +4 -0
  25. package/components/List.js +10 -0
  26. package/components/ListItem.js +53 -0
  27. package/components/ListOption.js +62 -1
  28. package/components/Listbox.js +44 -13
  29. package/components/Menu.js +31 -9
  30. package/components/MenuItem.js +24 -10
  31. package/components/NavBar.js +14 -3
  32. package/components/NavBarItem.js +5 -0
  33. package/components/NavDrawer.js +17 -0
  34. package/components/NavDrawerItem.js +5 -0
  35. package/components/NavItem.js +22 -2
  36. package/components/NavRail.js +9 -0
  37. package/components/NavRailItem.js +5 -0
  38. package/components/Page.js +15 -1
  39. package/components/Pane.js +7 -1
  40. package/components/Popup.js +6 -0
  41. package/components/Progress.js +25 -5
  42. package/components/Radio.js +6 -2
  43. package/components/RadioIcon.js +14 -1
  44. package/components/Ripple.js +14 -0
  45. package/components/Root.js +16 -0
  46. package/components/Scrim.js +10 -2
  47. package/components/Search.js +18 -5
  48. package/components/SegmentedButton.js +22 -6
  49. package/components/SegmentedButtonGroup.js +7 -10
  50. package/components/Select.js +13 -3
  51. package/components/Shape.js +4 -0
  52. package/components/SideSheet.js +31 -2
  53. package/components/Slider.js +22 -2
  54. package/components/Snackbar.js +30 -4
  55. package/components/SnackbarContainer.js +9 -0
  56. package/components/Surface.js +5 -0
  57. package/components/Switch.js +18 -2
  58. package/components/SwitchIcon.js +22 -1
  59. package/components/Tab.js +21 -0
  60. package/components/TabContent.js +32 -12
  61. package/components/TabList.js +36 -3
  62. package/components/TabPanel.js +9 -0
  63. package/components/Table.js +38 -3
  64. package/components/TextArea.js +32 -1
  65. package/components/Title.js +4 -0
  66. package/components/Tooltip.js +9 -2
  67. package/components/TopAppBar.js +15 -0
  68. package/core/Composition.js +45 -16
  69. package/core/CompositionAdapter.js +24 -6
  70. package/core/CustomElement.js +77 -49
  71. package/core/customTypes.js +43 -26
  72. package/core/dom.js +1 -0
  73. package/core/jsonMergePatch.js +15 -1
  74. package/core/observe.js +28 -21
  75. package/dist/CustomElement.min.js +2 -0
  76. package/dist/CustomElement.min.js.map +7 -0
  77. package/dist/core/CustomElement.min.js +2 -0
  78. package/dist/core/CustomElement.min.js.map +7 -0
  79. package/dist/index.min.js +9 -9
  80. package/dist/index.min.js.map +3 -3
  81. package/dist/meta.json +1 -1
  82. package/dom/HTMLOptionsCollectionProxy.js +5 -3
  83. package/mixins/AriaReflectorMixin.js +22 -13
  84. package/mixins/AriaToolbarMixin.js +3 -0
  85. package/mixins/ControlMixin.js +3 -0
  86. package/mixins/DelegatesFocusMixin.js +9 -1
  87. package/mixins/DensityMixin.js +5 -1
  88. package/mixins/ElevationMixin.js +1 -2
  89. package/mixins/FlexableMixin.js +21 -2
  90. package/mixins/FormAssociatedMixin.js +19 -5
  91. package/mixins/HyperlinkMixin.js +11 -1
  92. package/mixins/InputMixin.js +22 -0
  93. package/mixins/KeyboardNavMixin.js +3 -1
  94. package/mixins/PopupMixin.js +41 -12
  95. package/mixins/RTLObserverMixin.js +2 -0
  96. package/mixins/ResizeObserverMixin.js +2 -0
  97. package/mixins/RippleMixin.js +3 -1
  98. package/mixins/ScrollListenerMixin.js +13 -1
  99. package/mixins/SemiStickyMixin.js +7 -0
  100. package/mixins/ShapeMaskedMixin.js +9 -1
  101. package/mixins/ShapeMixin.js +9 -0
  102. package/mixins/StateMixin.js +4 -0
  103. package/mixins/TextFieldMixin.js +21 -2
  104. package/mixins/ThemableMixin.js +13 -0
  105. package/mixins/TooltipTriggerMixin.js +17 -3
  106. package/mixins/TouchTargetMixin.js +4 -1
  107. package/mixins/TypographyMixin.js +8 -1
  108. package/package.json +53 -45
  109. package/services/theme.js +4 -5
  110. package/types/components/BottomAppBar.d.ts +3 -4
  111. package/types/components/BottomSheet.d.ts +33 -7
  112. package/types/components/BottomSheet.d.ts.map +1 -1
  113. package/types/components/Button.d.ts +3 -472
  114. package/types/components/Button.d.ts.map +1 -1
  115. package/types/components/Card.d.ts +9 -274
  116. package/types/components/Card.d.ts.map +1 -1
  117. package/types/components/Checkbox.d.ts +2 -0
  118. package/types/components/Checkbox.d.ts.map +1 -1
  119. package/types/components/Chip.d.ts +3 -1180
  120. package/types/components/Dialog.d.ts +8 -191
  121. package/types/components/Dialog.d.ts.map +1 -1
  122. package/types/components/Display.d.ts +5 -4
  123. package/types/components/Display.d.ts.map +1 -1
  124. package/types/components/Fab.d.ts +2 -470
  125. package/types/components/FilterChip.d.ts +5 -4032
  126. package/types/components/Grid.d.ts +1 -0
  127. package/types/components/Grid.d.ts.map +1 -1
  128. package/types/components/Headline.d.ts +3 -4
  129. package/types/components/Icon.d.ts +1 -49
  130. package/types/components/Icon.d.ts.map +1 -1
  131. package/types/components/IconButton.d.ts +3 -1205
  132. package/types/components/Input.d.ts +1485 -50245
  133. package/types/components/Input.d.ts.map +1 -1
  134. package/types/components/InputChip.d.ts +2 -160
  135. package/types/components/List.d.ts +8 -4
  136. package/types/components/List.d.ts.map +1 -1
  137. package/types/components/ListItem.d.ts +10 -235
  138. package/types/components/ListItem.d.ts.map +1 -1
  139. package/types/components/ListOption.d.ts +17 -1352
  140. package/types/components/ListOption.d.ts.map +1 -1
  141. package/types/components/Listbox.d.ts +199 -11448
  142. package/types/components/Listbox.d.ts.map +1 -1
  143. package/types/components/Menu.d.ts +21 -10
  144. package/types/components/Menu.d.ts.map +1 -1
  145. package/types/components/MenuItem.d.ts +17 -2894
  146. package/types/components/MenuItem.d.ts.map +1 -1
  147. package/types/components/NavBar.d.ts +2 -0
  148. package/types/components/NavBar.d.ts.map +1 -1
  149. package/types/components/NavBarItem.d.ts +1 -90
  150. package/types/components/NavDrawer.d.ts +3 -4
  151. package/types/components/NavDrawerItem.d.ts +1 -90
  152. package/types/components/NavItem.d.ts +1 -92
  153. package/types/components/NavItem.d.ts.map +1 -1
  154. package/types/components/NavRail.d.ts +3 -4
  155. package/types/components/NavRailItem.d.ts +1 -90
  156. package/types/components/Page.d.ts +1 -0
  157. package/types/components/Page.d.ts.map +1 -1
  158. package/types/components/Popup.d.ts +5 -3
  159. package/types/components/Popup.d.ts.map +1 -1
  160. package/types/components/Progress.d.ts +2 -0
  161. package/types/components/Progress.d.ts.map +1 -1
  162. package/types/components/Radio.d.ts +2 -0
  163. package/types/components/Radio.d.ts.map +1 -1
  164. package/types/components/Ripple.d.ts +1 -0
  165. package/types/components/Ripple.d.ts.map +1 -1
  166. package/types/components/Root.d.ts +1 -1
  167. package/types/components/Root.d.ts.map +1 -1
  168. package/types/components/Search.d.ts +502 -2
  169. package/types/components/Search.d.ts.map +1 -1
  170. package/types/components/SegmentedButton.d.ts +4 -470
  171. package/types/components/SegmentedButton.d.ts.map +1 -1
  172. package/types/components/SegmentedButtonGroup.d.ts +3 -4
  173. package/types/components/SegmentedButtonGroup.d.ts.map +1 -1
  174. package/types/components/Select.d.ts +5 -1208
  175. package/types/components/Select.d.ts.map +1 -1
  176. package/types/components/SideSheet.d.ts +9 -4
  177. package/types/components/SideSheet.d.ts.map +1 -1
  178. package/types/components/Slider.d.ts +10 -189
  179. package/types/components/Slider.d.ts.map +1 -1
  180. package/types/components/Snackbar.d.ts +13 -5
  181. package/types/components/Snackbar.d.ts.map +1 -1
  182. package/types/components/Switch.d.ts +4 -0
  183. package/types/components/Switch.d.ts.map +1 -1
  184. package/types/components/SwitchIcon.d.ts +2 -110
  185. package/types/components/SwitchIcon.d.ts.map +1 -1
  186. package/types/components/Tab.d.ts +12 -752
  187. package/types/components/Tab.d.ts.map +1 -1
  188. package/types/components/TabContent.d.ts +23 -21
  189. package/types/components/TabContent.d.ts.map +1 -1
  190. package/types/components/TabList.d.ts +646 -5801
  191. package/types/components/TabList.d.ts.map +1 -1
  192. package/types/components/TabPanel.d.ts +4 -4
  193. package/types/components/TabPanel.d.ts.map +1 -1
  194. package/types/components/Table.d.ts +24 -1
  195. package/types/components/Table.d.ts.map +1 -1
  196. package/types/components/TextArea.d.ts +15 -1208
  197. package/types/components/TextArea.d.ts.map +1 -1
  198. package/types/components/Title.d.ts +3 -4
  199. package/types/components/Tooltip.d.ts +4 -4
  200. package/types/components/Tooltip.d.ts.map +1 -1
  201. package/types/components/TopAppBar.d.ts +4 -5
  202. package/types/components/TopAppBar.d.ts.map +1 -1
  203. package/types/constants/shapes.d.ts.map +1 -1
  204. package/types/core/Composition.d.ts +19 -11
  205. package/types/core/Composition.d.ts.map +1 -1
  206. package/types/core/CompositionAdapter.d.ts +30 -8
  207. package/types/core/CompositionAdapter.d.ts.map +1 -1
  208. package/types/core/CustomElement.d.ts +27 -25
  209. package/types/core/CustomElement.d.ts.map +1 -1
  210. package/types/core/customTypes.d.ts +2 -6
  211. package/types/core/customTypes.d.ts.map +1 -1
  212. package/types/core/dom.d.ts.map +1 -1
  213. package/types/core/jsonMergePatch.d.ts.map +1 -1
  214. package/types/core/observe.d.ts +20 -19
  215. package/types/core/observe.d.ts.map +1 -1
  216. package/types/core/template.d.ts.map +1 -1
  217. package/types/dom/HTMLOptionsCollectionProxy.d.ts +4 -4
  218. package/types/dom/HTMLOptionsCollectionProxy.d.ts.map +1 -1
  219. package/types/mixins/AriaReflectorMixin.d.ts +18 -10
  220. package/types/mixins/AriaReflectorMixin.d.ts.map +1 -1
  221. package/types/mixins/AriaToolbarMixin.d.ts +6 -4
  222. package/types/mixins/AriaToolbarMixin.d.ts.map +1 -1
  223. package/types/mixins/ControlMixin.d.ts +1 -1
  224. package/types/mixins/ControlMixin.d.ts.map +1 -1
  225. package/types/mixins/DelegatesFocusMixin.d.ts +9 -1
  226. package/types/mixins/DelegatesFocusMixin.d.ts.map +1 -1
  227. package/types/mixins/DensityMixin.d.ts +4 -1
  228. package/types/mixins/DensityMixin.d.ts.map +1 -1
  229. package/types/mixins/ElevationMixin.d.ts +1 -2
  230. package/types/mixins/ElevationMixin.d.ts.map +1 -1
  231. package/types/mixins/FlexableMixin.d.ts +1 -0
  232. package/types/mixins/FlexableMixin.d.ts.map +1 -1
  233. package/types/mixins/FormAssociatedMixin.d.ts +3 -2
  234. package/types/mixins/FormAssociatedMixin.d.ts.map +1 -1
  235. package/types/mixins/HyperlinkMixin.d.ts +4 -1
  236. package/types/mixins/HyperlinkMixin.d.ts.map +1 -1
  237. package/types/mixins/InputMixin.d.ts +1 -7
  238. package/types/mixins/InputMixin.d.ts.map +1 -1
  239. package/types/mixins/KeyboardNavMixin.d.ts +4 -5
  240. package/types/mixins/KeyboardNavMixin.d.ts.map +1 -1
  241. package/types/mixins/PopupMixin.d.ts +22 -6
  242. package/types/mixins/PopupMixin.d.ts.map +1 -1
  243. package/types/mixins/RTLObserverMixin.d.ts +1 -0
  244. package/types/mixins/RTLObserverMixin.d.ts.map +1 -1
  245. package/types/mixins/ResizeObserverMixin.d.ts +1 -0
  246. package/types/mixins/ResizeObserverMixin.d.ts.map +1 -1
  247. package/types/mixins/RippleMixin.d.ts +3 -1
  248. package/types/mixins/RippleMixin.d.ts.map +1 -1
  249. package/types/mixins/ScrollListenerMixin.d.ts +7 -2
  250. package/types/mixins/ScrollListenerMixin.d.ts.map +1 -1
  251. package/types/mixins/SemiStickyMixin.d.ts +1 -1
  252. package/types/mixins/SemiStickyMixin.d.ts.map +1 -1
  253. package/types/mixins/ShapeMaskedMixin.d.ts +4 -1
  254. package/types/mixins/ShapeMaskedMixin.d.ts.map +1 -1
  255. package/types/mixins/ShapeMixin.d.ts +1 -0
  256. package/types/mixins/ShapeMixin.d.ts.map +1 -1
  257. package/types/mixins/StateMixin.d.ts +2 -0
  258. package/types/mixins/StateMixin.d.ts.map +1 -1
  259. package/types/mixins/TextFieldMixin.d.ts +7 -1208
  260. package/types/mixins/TextFieldMixin.d.ts.map +1 -1
  261. package/types/mixins/ThemableMixin.d.ts +1 -0
  262. package/types/mixins/ThemableMixin.d.ts.map +1 -1
  263. package/types/mixins/TooltipTriggerMixin.d.ts +12 -4
  264. package/types/mixins/TooltipTriggerMixin.d.ts.map +1 -1
  265. package/types/mixins/TouchTargetMixin.d.ts +4 -1
  266. package/types/mixins/TouchTargetMixin.d.ts.map +1 -1
  267. package/types/mixins/TypographyMixin.d.ts +4 -1
  268. package/types/mixins/TypographyMixin.d.ts.map +1 -1
  269. package/types/services/theme.d.ts.map +1 -1
  270. package/types/utils/jsx-runtime.d.ts +3 -3
  271. package/types/utils/jsx-runtime.d.ts.map +1 -1
  272. package/types/utils/material-color/hct/Hct.d.ts.map +1 -1
  273. package/types/utils/material-color/palettes/CorePalette.d.ts +1 -1
  274. package/types/utils/material-color/palettes/CorePalette.d.ts.map +1 -1
  275. package/types/utils/material-color/scheme/Scheme.d.ts.map +1 -1
  276. package/types/utils/pixelmatch.d.ts +3 -3
  277. package/types/utils/pixelmatch.d.ts.map +1 -1
  278. package/types/utils/searchParams.d.ts.map +1 -1
  279. package/utils/jsx-runtime.js +9 -4
  280. package/utils/pixelmatch.js +10 -7
  281. package/utils/searchParams.js +3 -0
  282. package/components/Button.md +0 -61
@@ -11,6 +11,10 @@ import ThemableMixin from '../mixins/ThemableMixin.js';
11
11
  import './Button.js';
12
12
  import './IconButton.js';
13
13
 
14
+ /**
15
+ * Snackbars provide brief messages about app processes and optional actions.
16
+ * @see https://m3.material.io/components/snackbar/specs
17
+ */
14
18
  export default CustomElement
15
19
  .extend()
16
20
  .mixin(ThemableMixin)
@@ -23,17 +27,32 @@ export default CustomElement
23
27
  elevated: true,
24
28
  })
25
29
  .observe({
30
+ /** Whether the snackbar is visible. */
26
31
  open: 'boolean',
32
+ /** When true the snackbar does not auto-dismiss. */
27
33
  persistent: 'boolean',
34
+ /** Optional action label to display as a button. */
28
35
  action: 'string',
36
+ /** Ink token used for the action button (defaults to inverse-primary). */
29
37
  actionInk: { empty: 'inverse-primary' },
38
+ /** Typographic style used for the action (e.g. 'label-large'). */
30
39
  actionTypeStyle: { empty: 'label-large' },
40
+ /** Render a close icon button when true. */
31
41
  closeButton: 'boolean',
42
+ /** Icon name used for the close button. */
32
43
  closeIcon: { empty: 'close' },
44
+ /** Ink token used for the close icon. */
33
45
  closeInk: { empty: 'inherit' },
46
+ /** Event handler invoked when the action is triggered. */
34
47
  onaction: EVENT_HANDLER_TYPE,
48
+ /** Event handler invoked when the snackbar toggles open/closed. */
49
+ ontoggle: EVENT_HANDLER_TYPE,
35
50
  })
36
51
  .methods({
52
+ /**
53
+ * Close the snackbar. Dispatches a cancelable `close` event; if not
54
+ * prevented the snackbar will hide and await the closing transition.
55
+ */
37
56
  async close() {
38
57
  if (!this.dispatchEvent(new Event('close', { cancelable: true }))) return;
39
58
  if (!this.open) return;
@@ -43,10 +62,14 @@ export default CustomElement
43
62
  this.addEventListener('transitionend', resolve, { once: true });
44
63
  });
45
64
  },
65
+ /** Show the snackbar (set `open` true). */
46
66
  show() {
47
67
  this.open = true;
48
68
  },
49
- /** @param {string} text */
69
+ /**
70
+ * Update the snackbar text content.
71
+ * @param {string} text
72
+ */
50
73
  update(text) {
51
74
  this.textContent = text;
52
75
  },
@@ -54,7 +77,7 @@ export default CustomElement
54
77
  .html`
55
78
  <div id=content><slot id=slot></div>
56
79
  <mdw-button mdw-if={action} id=action class=button ink={actionInk} type-style={actionTypeStyle}>{action}</mdw-button>
57
- <mdw-icon-button mdw-if={closeButton} id=close class=button icon={closeIcon} ink={closeInk}>Close</mdw-button>
80
+ <mdw-icon-button mdw-if={closeButton} id=close class=button icon={closeIcon} ink={closeInk}>Close</mdw-icon-button>
58
81
  `
59
82
  .childEvents({
60
83
  action: {
@@ -69,9 +92,12 @@ export default CustomElement
69
92
  },
70
93
  },
71
94
  })
95
+ .on({
96
+ openChanged() {
97
+ this.dispatchEvent(new Event('toggle'));
98
+ },
99
+ })
72
100
  .css`
73
- /* https://m3.material.io/components/snackbar/specs */
74
-
75
101
  :host {
76
102
  --mdw-shape__size: var(--mdw-shape__small);
77
103
  --mdw-bg: var(--mdw-color__inverse-surface);
@@ -1,6 +1,11 @@
1
1
  import CustomElement from '../core/CustomElement.js';
2
2
  import DelegatesFocusMixin from '../mixins/DelegatesFocusMixin.js';
3
3
 
4
+ /**
5
+ * Snackbar container positions snackbars within the app window and manages
6
+ * layout and pointer-events for stacked snackbars.
7
+ * @see https://m3.material.io/components/snackbar/specs
8
+ */
4
9
  export default CustomElement
5
10
  .extend()
6
11
  .mixin(DelegatesFocusMixin)
@@ -38,5 +43,9 @@ export default CustomElement
38
43
  }
39
44
  }
40
45
 
46
+ #slot {
47
+ pointer-events: auto;
48
+ }
49
+
41
50
  `
42
51
  .autoRegister('mdw-snackbar-container');
@@ -4,6 +4,11 @@ import FlexableMixin from '../mixins/FlexableMixin.js';
4
4
  import ShapeMixin from '../mixins/ShapeMixin.js';
5
5
  import ThemableMixin from '../mixins/ThemableMixin.js';
6
6
 
7
+ /**
8
+ * Surface represents a themed elevated surface used to display content with
9
+ * elevation, shape, and color tokens applied.
10
+ * @see https://m3.material.io/styles/elevation/overview
11
+ */
7
12
  export default CustomElement
8
13
  .extend()
9
14
  .mixin(ThemableMixin)
@@ -5,6 +5,10 @@ import StateMixin from '../mixins/StateMixin.js';
5
5
  import ThemableMixin from '../mixins/ThemableMixin.js';
6
6
  import TouchTargetMixin from '../mixins/TouchTargetMixin.js';
7
7
 
8
+ /**
9
+ * Switch is a binary control that toggles between on and off states.
10
+ * @see https://m3.material.io/components/switch/specs
11
+ */
8
12
  export default CustomElement
9
13
  .extend()
10
14
  .mixin(ThemableMixin)
@@ -13,15 +17,23 @@ export default CustomElement
13
17
  .mixin(TouchTargetMixin)
14
18
  // Switches have their own pressed animation (No ripple)
15
19
  .set({
20
+ /** The control `type` used for the underlying input element (always 'checkbox'). */
16
21
  type: 'checkbox',
22
+ /** Enables the state-layer visual treatment for pressed/hover states. */
17
23
  stateLayer: true,
18
24
  })
19
25
  .observe({
26
+ /** The icon name to show inside the thumb when provided. */
20
27
  icon: 'string',
28
+ /** The icon name to show when the switch is selected/on. */
21
29
  selectedIcon: 'string',
30
+ /** The icon name to show when the switch is unselected/off. */
22
31
  unselectedIcon: 'string',
32
+ /** The image `src` to show inside the thumb when provided. */
23
33
  src: 'string',
34
+ /** The image `src` to show when the switch is selected/on. */
24
35
  selectedSrc: 'string',
36
+ /** The image `src` to show when the switch is unselected/off. */
25
37
  unselectedSrc: 'string',
26
38
  })
27
39
  .html`
@@ -44,6 +56,8 @@ export default CustomElement
44
56
  })
45
57
  .methods({
46
58
  /**
59
+ * Handle pointer/touch input on the native control to compute dragging
60
+ * position and update the thumb drag state.
47
61
  * @param {(MouseEvent|TouchEvent) & {currentTarget:HTMLInputElement}} event
48
62
  * @return {void}
49
63
  */
@@ -97,12 +111,14 @@ export default CustomElement
97
111
 
98
112
  // this._isHoveringThumb = true;
99
113
 
100
- let currentValue = this.refs.switch.dragValue;
114
+ const switchIcon = /** @type {InstanceType<import('./SwitchIcon.js').default>} */ (this.refs.switch);
115
+
116
+ let currentValue = switchIcon.dragValue;
101
117
  if (currentValue == null) {
102
118
  currentValue = this.checked ? 1 : 0;
103
119
  }
104
120
  const pixels = offsetX - (clientWidth / 2);
105
- const currentPixels = this.refs.switch.clientWidth - (this.refs.switch.clientHeight);
121
+ const currentPixels = switchIcon.clientWidth - (switchIcon.clientHeight);
106
122
  // console.log(pixels, currentPixels, currentPixels * currentValue, pixels / currentPixels);
107
123
  const newRatio = pixels / currentPixels;
108
124
  const newValue = Math.max(Math.min(currentValue + newRatio, 1), 0);
@@ -7,42 +7,63 @@ import { loadGlobalStyles } from '../services/rtl.js';
7
7
 
8
8
  loadGlobalStyles();
9
9
 
10
+ /**
11
+ * Visual helper that renders the switch thumb and related visual states.
12
+ * @see https://m3.material.io/components/switch/specs
13
+ */
10
14
  export default CustomElement
11
15
  .extend()
12
16
  .mixin(ThemableMixin)
13
17
  .mixin(ShapeMixin)
14
18
  .observe({
19
+ /** Whether the switch is selected/on. */
15
20
  selected: 'boolean',
21
+ /** Named icon to render inside the thumb. */
16
22
  icon: 'string',
23
+ /** Whether the control is visually in an errored state. */
17
24
  errored: 'boolean',
25
+ /** Whether the control is disabled. */
18
26
  disabled: 'boolean',
27
+ /** Icon name to show when selected/on. */
19
28
  selectedIcon: 'string',
29
+ /** Icon name to show when unselected/off. */
20
30
  unselectedIcon: 'string',
31
+ /** Image `src` to render inside the thumb. */
21
32
  src: 'string',
33
+ /** Image `src` to render when selected/on. */
22
34
  selectedSrc: 'string',
35
+ /** Image `src` to render when unselected/off. */
23
36
  unselectedSrc: 'string',
37
+ /** Hover state for the thumb. */
24
38
  hovered: 'boolean',
39
+ /** Pressed state for the thumb. */
25
40
  pressed: 'boolean',
41
+ /** Focused state for the thumb. */
26
42
  focused: 'boolean',
43
+ /** Temporary drag position value (0..1) while the thumb is being dragged. */
27
44
  dragValue: 'float',
45
+ /** Color token to use for the thumb (defaults to primary). */
28
46
  color: { empty: 'primary' },
29
47
  })
30
48
  .observe({
31
- /** Alias for Selected (QoL) */
49
+ /** Alias for `selected` to match common control naming. */
32
50
  checked: {
33
51
  type: 'boolean',
34
52
  get({ selected }) { return selected; },
35
53
  /** @param {boolean} value */
36
54
  set(value) { this.selected = value; },
37
55
  },
56
+ /** Whether the thumb is in an active interactive state (not disabled). */
38
57
  _active({ disabled, pressed, focused, hovered }) {
39
58
  return !disabled && (pressed || focused || hovered);
40
59
  },
41
60
  })
42
61
  .observe({
62
+ /** Thumb fill token (e.g. "primary-container") when active. */
43
63
  _thumbColor({ color, _active }) {
44
64
  return _active ? `${color}-container` : '';
45
65
  },
66
+ /** Ink token used for icons inside the thumb based on state. */
46
67
  _iconInk({ disabled, selected, color }) {
47
68
  if (!selected) return 'surface-container-highest';
48
69
  if (disabled) return 'on-surface';
package/components/Tab.js CHANGED
@@ -11,6 +11,11 @@ import ScrollListenerMixin from '../mixins/ScrollListenerMixin.js';
11
11
  import ShapeMixin from '../mixins/ShapeMixin.js';
12
12
  import StateMixin from '../mixins/StateMixin.js';
13
13
 
14
+ /**
15
+ * Tabs organize content into separate views where only one view is visible
16
+ * at a time; tabs provide navigation between those views.
17
+ * @see https://m3.material.io/components/tabs/specs
18
+ */
14
19
  export default CustomElement
15
20
  .extend()
16
21
  .mixin(ShapeMixin)
@@ -23,19 +28,29 @@ export default CustomElement
23
28
  stateTargetElement() { return this.refs.anchor; },
24
29
  })
25
30
  .set({
31
+ /** Enable state-layer visual treatment for pressed/hover states. */
26
32
  stateLayer: true,
27
33
  })
28
34
  .observe({
35
+ /** Whether this tab is currently active/selected. */
29
36
  active: 'boolean',
37
+ /** Named icon to display above the label. */
30
38
  icon: 'string',
39
+ /** Image `src` for the icon when used instead of a named icon. */
31
40
  src: 'string',
41
+ /** Optional aria-label for the tab's anchor element. */
32
42
  ariaLabel: 'string',
33
43
  })
34
44
  .methods({
45
+ /** Move focus to the tab's anchor. */
35
46
  /** @type {HTMLElement['focus']} */
36
47
  focus(options) {
37
48
  this.refs.anchor.focus(options);
38
49
  },
50
+ /**
51
+ * Compute the label metrics used for indicator alignment.
52
+ * Returns an object with `width` and `left` in pixels.
53
+ */
39
54
  computeLabelMetrics() {
40
55
  const { slot, icon } = this.refs;
41
56
  const target = slot.clientWidth ? slot : icon;
@@ -46,21 +61,27 @@ export default CustomElement
46
61
  },
47
62
  })
48
63
  .expressions({
64
+ /** Derive the `aria-controls` value from `href` if it references an id. */
49
65
  anchorAriaControls({ href }) {
50
66
  return href?.startsWith('#') ? href.slice(1) : null;
51
67
  },
68
+ /** Stringified `aria-selected` for the anchor. */
52
69
  anchorAriaSelected({ active }) {
53
70
  return `${active}`;
54
71
  },
72
+ /** Stringified `aria-disabled` for the anchor. */
55
73
  anchorAriaDisabled({ disabledState }) {
56
74
  return `${disabledState}`;
57
75
  },
76
+ /** Ensure anchor `href` defaults to `#` when unset. */
58
77
  anchorHref({ href }) {
59
78
  return href ?? '#';
60
79
  },
80
+ /** True when an icon or src is provided and should render. */
61
81
  iconIf({ icon, src }) {
62
82
  return icon || src;
63
83
  },
84
+ /** Icon variation to use when active. */
64
85
  iconVariation({ active }) {
65
86
  return active ? 'filled' : null;
66
87
  },
@@ -4,25 +4,33 @@ import ResizeObserverMixin from '../mixins/ResizeObserverMixin.js';
4
4
 
5
5
  import TabPanel from './TabPanel.js';
6
6
 
7
+ /**
8
+ * Tab content hosts tab panels and manages which panel is visible based on
9
+ * scroll position or selected tab.
10
+ * @see https://m3.material.io/components/tabs/specs
11
+ */
7
12
  export default CustomElement
8
13
  .extend()
9
14
  .mixin(ResizeObserverMixin)
10
15
  .set({
11
- /** @type {InstanceType<TabPanel>[]} */
16
+ /**
17
+ * Internal list of `TabPanel` nodes currently assigned to the slot.
18
+ * @type {InstanceType<TabPanel>[]}
19
+ */
12
20
  _panelNodes: [],
13
21
  /**
14
- * @type {{
15
- * left:number,
16
- * width:number,
17
- * right:number,
18
- * center: number,
19
- * index: number,
20
- * }[]}
22
+ * Cached metrics for each panel used to determine visibility and
23
+ * which panel is active based on scroll position. Each entry contains
24
+ * `{ left, width, right, center, index }` in pixels.
25
+ * @type {{left:number,width:number,right:number,center:number,index:number}[]|null}
21
26
  */
22
27
  _panelMetrics: null,
23
28
  })
24
29
  .observe({
25
- /** Internal observed property */
30
+ /**
31
+ * Internal index of the currently selected panel. `-1` when none.
32
+ * This is maintained alongside panel `active` states.
33
+ */
26
34
  _selectedIndex: {
27
35
  type: 'integer',
28
36
  empty: -1,
@@ -44,7 +52,12 @@ export default CustomElement
44
52
  },
45
53
  })
46
54
  .define({
55
+ /**
56
+ * Modifiable index of the currently-selected panel. 0-based index.
57
+ * Setting this updates panel `active` states accordingly.
58
+ */
47
59
  selectedIndex: {
60
+
48
61
  get() {
49
62
  let index = 0;
50
63
  for (const panel of this.panels) {
@@ -68,16 +81,18 @@ export default CustomElement
68
81
  },
69
82
  })
70
83
  .define({
71
- selectedPanel: {
72
84
  /**
73
- * @return {InstanceType<TabPanel>}
85
+ * Modifiable currently selected panel.
86
+ * Setting this updates panel `active` states accordingly.
74
87
  */
88
+ selectedPanel: {
89
+ /** @return {InstanceType<TabPanel>|undefined} */
75
90
  get() {
76
91
  return this.panels.find((panel) => panel.active);
77
92
  },
78
93
  /**
79
94
  * @param {InstanceType<TabPanel>} value
80
- * @return {InstanceType<TabPanel>}
95
+ * @return {InstanceType<TabPanel>|null}
81
96
  */
82
97
  set(value) {
83
98
  const index = this.panels.indexOf(value);
@@ -89,11 +104,16 @@ export default CustomElement
89
104
  })
90
105
  .html`<slot id=slot></slot>`
91
106
  .methods({
107
+ /** Called when the component observes a resize; clears cached metrics. */
92
108
  onResizeObserved() {
93
109
  this._panelMetrics = null;
94
110
  this.updatePanels();
95
111
  // Resize should not change panel visibility (Chrome Bug?)
96
112
  },
113
+ /**
114
+ * Recompute which panels are visible based on scroll position and
115
+ * activate the panel whose visible percentage is >= 50%.
116
+ */
97
117
  updatePanels() {
98
118
  const start = this.scrollLeft;
99
119
  const width = this.clientWidth;
@@ -10,6 +10,11 @@ import ThemableMixin from '../mixins/ThemableMixin.js';
10
10
 
11
11
  import Tab from './Tab.js';
12
12
 
13
+ /**
14
+ * Tab list is the container for `mdw-tab` elements and renders the active
15
+ * indicator and keyboard navigation behavior.
16
+ * @see https://m3.material.io/components/tabs/specs
17
+ */
13
18
  export default CustomElement
14
19
  .extend()
15
20
  .mixin(ThemableMixin)
@@ -19,11 +24,13 @@ export default CustomElement
19
24
  .mixin(ShapeMixin)
20
25
  .mixin(SemiStickyMixin)
21
26
  .observe({
27
+ /** When true the tablist is scrollable (renders differently). */
22
28
  scrollable: 'boolean',
23
29
  })
24
30
  .set({
25
31
  /** @type {WeakRef<HTMLElement>} */
26
32
  _tabContentRef: null,
33
+ /** Listener function attached to the tab content's `scroll` event. */
27
34
  _tabContentScrollListener: null,
28
35
  /** @type {HTMLCollectionOf<InstanceType<Tab>>} */
29
36
  _tabCollection: null,
@@ -54,8 +61,10 @@ export default CustomElement
54
61
  }
55
62
  if (value) {
56
63
  this._tabContentRef = new WeakRef(value);
64
+ // @ts-expect-error this lacks forward declaration
57
65
  this._tabContentScrollListener = this.observeTabContent.bind(this);
58
66
  value.addEventListener('scroll', this._tabContentScrollListener);
67
+ // @ts-expect-error this lacks forward declaration
59
68
  this.observeTabContent();
60
69
  } else {
61
70
  this._tabContentRef = null;
@@ -64,10 +73,15 @@ export default CustomElement
64
73
  },
65
74
  })
66
75
  .observe({
76
+ /** Id of an external `TabContent` element to bind and observe. */
67
77
  tabContentId: 'string',
78
+ /** Whether the tablist is visually active (has a selected tab). */
68
79
  active: 'boolean',
80
+ /** Render the secondary (label-width) indicator style when true. */
69
81
  secondary: 'boolean',
82
+ /** Inline style used to position and size the indicator. */
70
83
  _indicatorStyle: { value: 'opacity: 0' },
84
+ /** Color token used for the tab ink. */
71
85
  color: { empty: 'surface-primary' },
72
86
  })
73
87
  .define({
@@ -120,6 +134,10 @@ export default CustomElement
120
134
  };
121
135
  });
122
136
  },
137
+ /**
138
+ * Modifiable index of the currently selected tab. 0-based index.
139
+ * Setting this updates tab `active` states accordingly.
140
+ */
123
141
  selectedIndex: {
124
142
  get() {
125
143
  let index = 0;
@@ -144,6 +162,10 @@ export default CustomElement
144
162
  },
145
163
  })
146
164
  .define({
165
+ /**
166
+ * Modifiable currently selected tab.
167
+ * Setting this updates tab `active` states accordingly.
168
+ */
147
169
  selectedItem: {
148
170
  /**
149
171
  * @return {InstanceType<Tab>}
@@ -172,15 +194,19 @@ export default CustomElement
172
194
  },
173
195
  })
174
196
  .methods({
197
+ /** Clear cached tab metrics (widths/positions). */
175
198
  clearCache() {
176
199
  this._tabMetrics = null;
177
200
  },
201
+ /** Find and bind to the external `TabContent` element by id. */
178
202
  searchForTabContent() {
179
203
  const { tabContentId, isConnected } = this;
180
204
  if (!tabContentId) return;
181
205
  if (!isConnected) return;
182
- this.tabContent = this.getRootNode().getElementById(tabContentId);
206
+ const root = /** @type {ShadowRoot|Document} */ (this.getRootNode());
207
+ this.tabContent = root.getElementById(tabContentId);
183
208
  },
209
+ /** Update the indicator position based on a specific `Tab`. */
184
210
  /** @param {InstanceType<Tab>} [tab] */
185
211
  updateIndicatorByTab(tab) {
186
212
  tab ??= this.selectedItem ?? this.tabs.item(0);
@@ -190,13 +216,18 @@ export default CustomElement
190
216
  const position = this.secondary ? metrics.left : metrics.left + metrics.label.left;
191
217
  this._indicatorStyle = `--width: ${width}; --offset: ${position}px`;
192
218
  },
219
+ /** Recompute and apply indicator; optionally disable animation when `animate` is false. */
193
220
  updateIndicator(animate = false) {
194
221
  this.updateIndicatorByTab();
195
222
  if (!animate) {
196
223
  this.refs.indicator.style.setProperty('--transition-ratio', '0');
197
224
  }
198
225
  },
199
- /** @param {number} percentage */
226
+ /**
227
+ * Update the indicator position by a floating `percentage` between 0..1
228
+ * representing the scroll progress across tab panels.
229
+ * @param {number} percentage
230
+ */
200
231
  updateIndicatorByPosition(percentage) {
201
232
  const metrics = this.tabMetrics;
202
233
 
@@ -242,10 +273,12 @@ export default CustomElement
242
273
  this._indicatorStyle = `--width: ${width}; --offset: ${center - (width / 2)}px`;
243
274
  this.refs.indicator.style.setProperty('--transition-ratio', '0');
244
275
  },
276
+ /** Update the indicator using a discrete tab index. */
245
277
  /** @param {number} index */
246
278
  updateIndicatorByIndex(index) {
247
279
  this.updateIndicatorByTab(this.tabs.item(index ?? this._selectedIndex));
248
280
  },
281
+ /** Observe the bound TabContent scroll and update indicator accordingly. */
249
282
  observeTabContent() {
250
283
  const tabContent = this.tabContent;
251
284
  if (!tabContent) return;
@@ -258,6 +291,7 @@ export default CustomElement
258
291
  const percentage = max === 0 ? 0 : start / max;
259
292
  this.updateIndicatorByPosition(percentage);
260
293
  },
294
+ /** Handler called when the element is resized; refresh cache and indicator. */
261
295
  onResizeObserved() {
262
296
  this.clearCache();
263
297
  this.updateIndicator();
@@ -327,7 +361,6 @@ export default CustomElement
327
361
  --mdw-ink: var(--mdw-color__primary);
328
362
  --mdw-bg: var(--mdw-color__surface);
329
363
  position: relative;
330
- position: sticky;
331
364
  inset-block-start: 0;
332
365
  inset-inline: 0;
333
366
 
@@ -2,19 +2,28 @@ import AriaReflectorMixin from '../mixins/AriaReflectorMixin.js';
2
2
 
3
3
  import Box from './Box.js';
4
4
 
5
+ /**
6
+ * TabPanel represents the content area for a single tab and updates ARIA
7
+ * when activated.
8
+ * @see https://m3.material.io/components/tabs/specs
9
+ */
5
10
  export default Box
6
11
  .extend()
7
12
  .mixin(AriaReflectorMixin)
8
13
  .set({
14
+ /** ARIA role applied by the AriaReflectorMixin (defaults to `tabpanel`). */
9
15
  _ariaRole: 'tabpanel',
10
16
  })
11
17
  .observe({
18
+ /** Whether this panel is active/visible; updates ARIA `aria-hidden`. */
12
19
  active: {
13
20
  type: 'boolean',
21
+ /** Update `aria-hidden` when `active` changes. */
14
22
  changedCallback(oldValue, newValue) {
15
23
  this.updateAriaProperty('ariaHidden', newValue ? 'false' : 'true');
16
24
  },
17
25
  },
26
+ /** True when the panel is partially visible (peeking). */
18
27
  peeking: 'boolean',
19
28
  })
20
29
  .css`
@@ -63,10 +63,21 @@ function deleteByTagName(parent, tagName) {
63
63
  this.setByTagName(parent, tagName, null);
64
64
  }
65
65
 
66
- /** -implements {HTMLTableElement} */
67
- CustomElement
66
+ /**
67
+ * Table provides an HTML-like table API using mdw elements for rows and sections.
68
+ * Implements the {@link https://html.spec.whatwg.org/multipage/tables.html#htmltableelement | HTMLTableElement} API
69
+ * using `mdw-` prefixed sections and rows.
70
+ *
71
+ * Legacy. Modern UI does not use tables and no longer part of Material Design Web.
72
+ * Tables are generally not responsive and do not adapt well to different screen sizes.
73
+ */
74
+ export default CustomElement
68
75
  .extend()
69
76
  .define({
77
+ /**
78
+ * The table caption element (`mdw-caption`) or `null` when not present.
79
+ * Mirrors `HTMLTableElement.caption` semantics.
80
+ */
70
81
  caption: {
71
82
  get() {
72
83
  return getByTagName(this, 'mdw-caption');
@@ -75,14 +86,21 @@ CustomElement
75
86
  return setByTagName(this, 'mdw-caption', value, "Failed to set the 'caption' property on 'MDWTableElement': Failed to convert value to 'MDWCaptionElement'.");
76
87
  },
77
88
  },
89
+ /**
90
+ * The table header section (`mdw-thead`) element or `null` when not present.
91
+ * Mirrors `HTMLTableElement.tHead` semantics.
92
+ */
78
93
  tHead: {
79
94
  get() {
80
- return getByTagName(this, 'mdw-thread');
95
+ return getByTagName(this, 'mdw-thead');
81
96
  },
82
97
  set(value) {
83
98
  return setByTagName(this, 'mdw-thead', value, "Failed to set the 'tHead' property on 'MDWTableElement': Failed to convert value to 'MDWTHeadElement'.");
84
99
  },
85
100
  },
101
+ /**
102
+ * The table footer section (`mdw-tfoot`) element or `null` when not present.
103
+ */
86
104
  tFoot: {
87
105
  get() {
88
106
  return getByTagName(this, 'mdw-tfoot');
@@ -91,20 +109,37 @@ CustomElement
91
109
  return setByTagName(this, 'mdw-tfoot', value, "Failed to set the 'tFoot' property on 'MDWTableElement': Failed to convert value to 'MDWTFootElement'.");
92
110
  },
93
111
  },
112
+ /**
113
+ * Live `HTMLCollection` of `mdw-tbody` elements contained by the table.
114
+ * Mirrors `HTMLTableElement.tBodies`.
115
+ * @return {HTMLCollectionOf<Element>}
116
+ */
94
117
  tBodies() {
95
118
  return this.getElementsByTagName('mdw-tbody');
96
119
  },
120
+ /**
121
+ * Live `HTMLCollection` of row elements (`mdw-tr`) in the table.
122
+ * Mirrors `HTMLTableElement.rows`.
123
+ * @return {HTMLCollectionOf<Element>}
124
+ */
97
125
  rows() {
98
126
  return this.getElementsByTagName('mdw-tr');
99
127
  },
100
128
  })
101
129
  .methods({
130
+ /** Create and return a `mdw-caption` element, appending when necessary. */
102
131
  createCaption() { return createByTagName(this, 'mdw-caption'); },
132
+ /** Remove the table's caption element when present. */
103
133
  deleteCaption() { return deleteByTagName(this, 'mdw-caption'); },
134
+ /** Create and return a `mdw-thead` element for the table. */
104
135
  createTHead() { return createByTagName(this, 'mdw-thead'); },
136
+ /** Remove the table's `mdw-thead` element when present. */
105
137
  deleteTHead() { return deleteByTagName(this, 'mdw-thead'); },
138
+ /** Create and return a `mdw-tfoot` element for the table. */
106
139
  createTFoot() { return createByTagName(this, 'mdw-tfoot'); },
140
+ /** Remove the table's `mdw-tfoot` element when present. */
107
141
  deleteTFoot() { return deleteByTagName(this, 'mdw-tfoot'); },
142
+ /** Insert and return a new `mdw-tbody` element before the tFoot (if any). */
108
143
  createTBody() { return this.insertBefore(this.tFoot, document.createElement('mdw-tbody')); },
109
144
  })
110
145
  .html`<slot id=slot></slot>`