@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
@@ -7,7 +7,11 @@ import StateMixin from '../mixins/StateMixin.js';
7
7
  import List from './List.js';
8
8
  import ListOption from './ListOption.js';
9
9
 
10
- /** -implements {HTMLSelectElement} */
10
+ /**
11
+ * Listbox: a selectable list of options, used for autocompletes and selects.
12
+ * implements {HTMLSelectElement}
13
+ * @see https://m3.material.io/components/lists/specs
14
+ */
11
15
  export default List
12
16
  .extend()
13
17
  .mixin(StateMixin)
@@ -15,24 +19,41 @@ export default List
15
19
  .mixin(KeyboardNavMixin)
16
20
  .mixin(DelegatesFocusMixin)
17
21
  .observe({
22
+ /** When true, multiple options may be selected (select-multiple semantics). */
18
23
  multiple: 'boolean',
24
+
25
+ /** Visible size (number of rows) for the listbox; 0 means auto. */
19
26
  size: { type: 'integer', empty: 0 },
20
27
  })
21
28
  .set({
29
+ /** ARIA role applied to the host element (default: 'listbox'). */
22
30
  _ariaRole: 'listbox',
23
- /** @type {HTMLCollectionOf<InstanceType<ListOption>> & HTMLOptionsCollection} */
31
+
32
+ /**
33
+ * Lazily-constructed options collection proxy exposing `add`, indexed
34
+ * access, and other `HTMLOptionsCollection` semantics.
35
+ * @type {HTMLCollectionOf<InstanceType<typeof ListOption>> & HTMLOptionsCollection}
36
+ */
24
37
  _optionsCollection: null,
25
- /** @type {HTMLCollectionOf<InstanceType<ListOption>>} */
38
+
39
+ /** Cached collection of selected options (HTMLCollection). */
26
40
  _selectedOptionsCollection: null,
41
+
42
+ /** Internal guard to avoid reentrant selectedness updates. */
27
43
  _handlingSelectedness: false,
44
+
45
+ /** When true, form resets are honored; toggled when form association changes. */
28
46
  _handleFormReset: true,
29
47
  })
30
48
  .define({
31
49
  options() {
32
50
  if (!this._optionsCollection) {
51
+ // eslint-disable-next-line operator-linebreak
52
+ const collection = /** @type {HTMLCollectionOf<InstanceType<typeof ListOption>>} */
53
+ (this.getElementsByTagName(ListOption.elementName));
33
54
  this._optionsCollection = constructHTMLOptionsCollectionProxy({
34
55
  host: this,
35
- collection: this.getElementsByTagName(ListOption.elementName),
56
+ collection,
36
57
  OptionConstructor: ListOption,
37
58
  GroupConstructor: ListOption,
38
59
  });
@@ -40,31 +61,39 @@ export default List
40
61
  return this._optionsCollection;
41
62
  },
42
63
 
43
- /** @return {HTMLCollectionOf<InstanceType<ListOption>>} */
64
+ /**
65
+ * Returns a live HTMLCollection of selected `mdw-list-option` elements.
66
+ * @return {HTMLCollectionOf<InstanceType<typeof ListOption>>}
67
+ */
44
68
  selectedOptions() {
45
69
  // eslint-disable-next-line no-return-assign
46
70
  return (this._selectedOptionsCollection
47
71
  ??= (
48
- /** @type {HTMLCollectionOf<InstanceType<ListOption>>} */
72
+ /** @type {HTMLCollectionOf<InstanceType<typeof ListOption>>} */
49
73
  (this.getElementsByClassName('mdw-list-option__selected')))
50
74
  );
51
75
  },
52
76
 
77
+ /** Returns the control type string compatible with `input`/`select` semantics. */
53
78
  type() { return this.multiple ? 'select-multiple' : 'select-one'; },
54
79
 
80
+ /** Query selector used by keyboard navigation mixin to find focusable options. */
55
81
  kbdNavQuery() { return ListOption.elementName; },
56
82
 
83
+ /** Allow keyboard navigation to focus disabled options in some patterns. */
57
84
  kbdNavFocusableWhenDisabled() { return true; },
58
85
  })
59
86
  .define({
60
87
  length() { return this.options.length; },
61
88
 
62
89
  selectedIndex: {
90
+ /** @return {number} */
63
91
  get() {
64
92
  const [selectedItem] = this.selectedOptions;
65
93
  if (!selectedItem) return -1;
66
94
  return Array.prototype.indexOf.call(this.options, selectedItem);
67
95
  },
96
+ /** @param {number} value */
68
97
  set(value) {
69
98
  const itemToSelect = this.options[value];
70
99
  this._handlingSelectedness = true;
@@ -131,12 +160,12 @@ export default List
131
160
  },
132
161
  /**
133
162
  * @param {number} index
134
- * @return {ListOption|null}
163
+ * @return {InstanceType<typeof ListOption>|null}
135
164
  */
136
165
  item(index) { return this.options[index]; },
137
166
  /**
138
167
  * @param {string} name ID of ListOption
139
- * @return {ListOption|null}
168
+ * @return {InstanceType<typeof ListOption>|null}
140
169
  */
141
170
  namedItem(name) {
142
171
  for (const option of this.options) {
@@ -152,17 +181,19 @@ export default List
152
181
  if (!(target instanceof ListOption)) return;
153
182
  event.stopImmediatePropagation();
154
183
  event.stopPropagation();
155
- if (target.disabledState) return;
184
+
185
+ const listOption = /** @type {InstanceType<ListOption>} */ (target);
186
+ if (listOption.disabledState) return;
156
187
 
157
188
  let sendUpdateNotifications = false;
158
189
  this._handlingSelectedness = true;
159
190
 
160
191
  // Perform unselect
161
- if (target.selected) {
192
+ if (listOption.selected) {
162
193
  // Unselect condition
163
194
  if (!this.required || (this.multiple && this.selectedOptions.length > 1)) {
164
195
  sendUpdateNotifications = true;
165
- target.selected = false;
196
+ listOption.selected = false;
166
197
  }
167
198
  } else {
168
199
  if (!this.multiple) {
@@ -172,7 +203,7 @@ export default List
172
203
  }
173
204
  }
174
205
 
175
- target.selected = true;
206
+ listOption.selected = true;
176
207
  sendUpdateNotifications = true;
177
208
  }
178
209
 
@@ -203,7 +234,7 @@ export default List
203
234
  if (this.multiple) return;
204
235
  if (this._handlingSelectedness) return;
205
236
 
206
- const target = /** @type {InstanceType<ListOption>} */ (/** @type {unknown} */ (event.target));
237
+ const target = /** @type {InstanceType<typeof ListOption>} */ (event.target);
207
238
  if (target.selected) return;
208
239
  this._handlingSelectedness = true;
209
240
 
@@ -1,5 +1,3 @@
1
- // https://www.w3.org/TR/wai-aria-practices/#menu
2
-
3
1
  import CustomElement from '../core/CustomElement.js';
4
2
  import { attemptFocus } from '../core/dom.js';
5
3
  import DensityMixin from '../mixins/DensityMixin.js';
@@ -9,6 +7,11 @@ import PopupMixin from '../mixins/PopupMixin.js';
9
7
  import ShapeMixin from '../mixins/ShapeMixin.js';
10
8
  import ThemableMixin from '../mixins/ThemableMixin.js';
11
9
 
10
+ /**
11
+ * Menus provide a list of choices or actions in a temporary surface.
12
+ * @see https://m3.material.io/components/menus/specs
13
+ * @see https://www.w3.org/TR/wai-aria-practices/#menu
14
+ */
12
15
  export default CustomElement
13
16
  .extend()
14
17
  .mixin(ThemableMixin)
@@ -18,11 +21,23 @@ export default CustomElement
18
21
  .mixin(DensityMixin)
19
22
  .mixin(KeyboardNavMixin)
20
23
  .set({
24
+ /** Placement strategy for the popup ('corner'). */
21
25
  flow: 'corner',
26
+
27
+ /** When true, show a scrim behind the menu (used by `showModal`). */
22
28
  _useScrim: false,
23
- /** @type {WeakRef<HTMLElement>} */
29
+
30
+ /**
31
+ * Weak reference to the element that requested a submenu cascade. Stored
32
+ * as a WeakRef to avoid retaining DOM nodes.
33
+ * @type {WeakRef<HTMLElement>}
34
+ */
24
35
  _cascader: null,
25
- /** @type {WeakRef<HTMLElement>} */
36
+
37
+ /**
38
+ * Weak reference to the currently opened submenu (if any).
39
+ * @type {WeakRef<HTMLElement>}
40
+ */
26
41
  _submenu: null,
27
42
  })
28
43
  .define({
@@ -32,9 +47,11 @@ export default CustomElement
32
47
  const submenuItems = [...this.querySelectorAll(':scope mdw-menu mdw-menu-item')];
33
48
  return items.filter((el) => !submenuItems.includes(el));
34
49
  },
50
+ /** Return the internal dialog element used for popup rendering (if any). */
35
51
  _dialog() {
36
52
  return /** @type {HTMLDialogElement} */ (this.refs.dialog);
37
53
  },
54
+ /** Element that cascaded this submenu (if present). */
38
55
  cascader: {
39
56
  get() {
40
57
  return this._cascader?.deref();
@@ -46,6 +63,7 @@ export default CustomElement
46
63
  this._cascader = value ? new WeakRef(value) : null;
47
64
  },
48
65
  },
66
+ /** Currently opened submenu element (if any). */
49
67
  submenu: {
50
68
  get() {
51
69
  return this._submenu?.deref();
@@ -85,6 +103,7 @@ export default CustomElement
85
103
  }
86
104
  `
87
105
  .methods({
106
+ /** @param {Parameters<InstanceType<ReturnType<PopupMixin>>['showPopup']>} args */
88
107
  showModal(...args) {
89
108
  this._useScrim = true;
90
109
  const result = this.showPopup(...args);
@@ -107,16 +126,17 @@ export default CustomElement
107
126
  })
108
127
  .events({
109
128
  'mdw-menu-item:cascade'(event) {
110
- const menuItem = event.target;
111
- const subMenuId = event.detail;
129
+ const menuItem = /** @type {HTMLElement} */ (event.target);
130
+ const subMenuId = /** @type {CustomEvent<string>} */ (event).detail;
112
131
  event.stopPropagation();
113
132
 
114
- const submenu = this.getRootNode().getElementById(subMenuId);
133
+ const root = /** @type {DocumentFragment|Document} */ (this.getRootNode());
134
+ const submenu = /** @type {typeof this} */ (root.getElementById(subMenuId));
115
135
  this.submenu = submenu;
116
136
  submenu.cascade(menuItem);
117
137
  },
118
138
  'mdw-menu-item:cascader-blur'() {
119
- const submenu = this.submenu;
139
+ const submenu = /** @type {typeof this} */ (this.submenu);
120
140
  if (!submenu) return;
121
141
  // Wait for focus event (if mouse focus on sub menu item)
122
142
  queueMicrotask(() => {
@@ -153,7 +173,9 @@ export default CustomElement
153
173
  // if (!this.submenu) break;
154
174
  if (getComputedStyle(this).direction === 'rtl') {
155
175
  if (event.key === 'ArrowLeft') break;
156
- } else if (event.key === 'ArrowRight') break;
176
+ } else if (event.key === 'ArrowRight') {
177
+ break;
178
+ }
157
179
  // Fallthrough;
158
180
  case 'Escape':
159
181
  case 'Esc':
@@ -6,12 +6,22 @@ import FormAssociatedMixin from '../mixins/FormAssociatedMixin.js';
6
6
  import './Icon.js';
7
7
  import ListOption from './ListOption.js';
8
8
 
9
+ /**
10
+ * Menu items represent selectable options within a menu. They can trigger
11
+ * actions, toggle state, or open nested submenus.
12
+ * @see https://m3.material.io/components/menus/specs
13
+ */
9
14
  export default ListOption
10
15
  .extend()
11
16
  .mixin(FormAssociatedMixin)
12
17
  .set({
18
+ /** Timeout handle used to schedule submenu cascade. */
13
19
  _cascadeTimeout: null,
20
+
21
+ /** Milliseconds to delay before opening a cascaded submenu. */
14
22
  CASCADE_TIMEOUT: 500,
23
+
24
+ /** Internal flag indicating a cascade is in progress. */
15
25
  _cascading: false,
16
26
  })
17
27
  .define({
@@ -22,9 +32,13 @@ export default ListOption
22
32
  },
23
33
  })
24
34
  .observe({
25
- /** ID of menu to cascade */
35
+ /** ID of the submenu to open when this item cascades. */
26
36
  cascades: 'string',
27
- /** Can be null */
37
+
38
+ /**
39
+ * Backing field for the menu item's value attribute. Can be `null` to
40
+ * indicate no explicit value; reflected to the `value` attribute.
41
+ */
28
42
  _defaultValue: {
29
43
  attr: 'value',
30
44
  reflect: true,
@@ -33,7 +47,10 @@ export default ListOption
33
47
  },
34
48
  })
35
49
  .observe({
36
- /** Never returns null */
50
+ /**
51
+ * Non-null string representation of the default value used for form
52
+ * association. Getter never returns null; setter writes to `_defaultValue`.
53
+ */
37
54
  defaultValue: {
38
55
  reflect: false,
39
56
  get() {
@@ -71,12 +88,7 @@ export default ListOption
71
88
  const [name, value] = event.detail;
72
89
  if (this.name !== name) return;
73
90
  if (value === this.value) return;
74
- if (this.value === '1') {
75
- console.log('unchecking', this.name, this.value);
76
- this.selected = false;
77
- } else {
78
- this.selected = false;
79
- }
91
+ this.selected = false;
80
92
  },
81
93
  })
82
94
  .expressions({
@@ -158,7 +170,9 @@ export default ListOption
158
170
  if (!this.cascades) break;
159
171
  if (getComputedStyle(this).direction === 'rtl') {
160
172
  if (event.key === 'ArrowRight') break;
161
- } else if (event.key === 'ArrowLeft') break;
173
+ } else if (event.key === 'ArrowLeft') {
174
+ break;
175
+ }
162
176
  event.stopPropagation();
163
177
  event.preventDefault();
164
178
  this.cascade();
@@ -4,25 +4,36 @@ import ThemableMixin from '../mixins/ThemableMixin.js';
4
4
 
5
5
  import NavItem from './NavItem.js';
6
6
 
7
+ /**
8
+ * Navigation bars let people switch between UI views on smaller devices
9
+ * @see https://m3.material.io/components/navigation-bar/specs
10
+ */
7
11
  export default CustomElement
8
12
  .extend()
9
13
  .mixin(DelegatesFocusMixin)
10
14
  .mixin(ThemableMixin)
11
15
  .observe({
16
+ /** When true, the navigation bar is expanded and visible on small viewports. */
12
17
  open: 'boolean',
18
+
19
+ /**
20
+ * Pixel threshold for auto-closing the nav bar based on viewport width.
21
+ * A value of `-1` disables auto-close. Default: 728.
22
+ */
13
23
  autoClose: {
14
24
  type: 'float',
15
25
  empty: 728,
16
26
  },
17
27
  })
18
28
  .set({
29
+ /** Color token used for the nav surface (defaults to `surface-container`). */
19
30
  color: 'surface-container',
31
+
32
+ /** ARIA role applied to the host element (default: 'navigation'). */
20
33
  _ariaRole: 'navigation',
21
34
  })
22
35
  .html`<slot id=slot></slot>`
23
36
  .css`
24
- /* https://m3.material.io/components/navigation-bar/specs */
25
-
26
37
  :host {
27
38
  --mdw-bg: var(--mdw-color__surface-container);
28
39
  --mdw-ink: var(--mdw-color__on-surface);
@@ -71,7 +82,7 @@ export default CustomElement
71
82
  if (event.target instanceof NavItem === false) return;
72
83
  for (const el of this.querySelectorAll('*')) {
73
84
  if (el instanceof NavItem === false) continue;
74
- el.active = (el === event.target);
85
+ /** @type {InstanceType<typeof NavItem>} */ (el).active = (el === event.target);
75
86
  }
76
87
  },
77
88
  })
@@ -1,5 +1,10 @@
1
1
  import NavItem from './NavItem.js';
2
2
 
3
+ /**
4
+ * A navigation bar item represents a destination within a navigation bar,
5
+ * providing an icon and optional label to help users move between app sections.
6
+ * @see https://m3.material.io/components/navigation-bar/specs
7
+ */
3
8
  export default NavItem
4
9
  .extend()
5
10
  .css`
@@ -1,16 +1,33 @@
1
1
  import SideSheet from './SideSheet.js';
2
2
 
3
+ /**
4
+ * Navigation drawers provide access to destinations and app-level navigation
5
+ * in a side panel. They can be modal, dismissible, or permanent depending on
6
+ * viewport and application needs.
7
+ * @see https://m3.material.io/components/navigation-drawer/specs
8
+ */
3
9
  export default SideSheet
4
10
  .extend()
5
11
  .observe({
12
+ /** When true, apply drawer shape at the end edge (RTL-aware). */
6
13
  shapeEnd: {
7
14
  type: 'boolean',
8
15
  empty: true,
9
16
  },
17
+
18
+ /**
19
+ * Viewport width in pixels at or above which the drawer auto-opens.
20
+ * Use `-1` to disable auto-open. Default: 1248.
21
+ */
10
22
  autoOpen: {
11
23
  type: 'float',
12
24
  empty: 1248,
13
25
  },
26
+
27
+ /**
28
+ * Fixed layout breakpoint in pixels for permanent/dismissible drawer modes.
29
+ * Default: 1248.
30
+ */
14
31
  fixedBreakpoint: {
15
32
  type: 'float',
16
33
  empty: 1248,
@@ -1,5 +1,10 @@
1
1
  import NavItem from './NavItem.js';
2
2
 
3
+ /**
4
+ * A navigation drawer item represents a destination inside a navigation drawer,
5
+ * showing an icon, label, and optional badge to help users navigate app sections.
6
+ * @see https://m3.material.io/components/navigation-drawer/specs
7
+ */
3
8
  export default NavItem
4
9
  .extend()
5
10
  .css`
@@ -12,6 +12,14 @@ import ThemableMixin from '../mixins/ThemableMixin.js';
12
12
 
13
13
  /** @typedef {'charset'|'coords'|'name'|'shape'} DeprecatedHTMLAnchorElementProperties */
14
14
 
15
+ /**
16
+ * A navigation item represents a single destination used by navigation bars,
17
+ * navigation drawers, and navigation rails. It provides an icon, optional
18
+ * label, and optional badge to help users move between app sections.
19
+ * @see https://m3.material.io/components/navigation-bar/specs
20
+ * @see https://m3.material.io/components/navigation-drawer/specs
21
+ * @see https://m3.material.io/components/navigation-rail/specs
22
+ */
15
23
  export default CustomElement
16
24
  .extend()
17
25
  .mixin(ThemableMixin)
@@ -23,14 +31,21 @@ export default CustomElement
23
31
  stateLayer: true,
24
32
  })
25
33
  .observe({
34
+ /** Whether the label slot is visible. When true the label is shown. */
26
35
  showLabel: 'string',
36
+ /** Whether the item is active/selected; affects styling and aria-current. */
27
37
  active: 'boolean',
38
+ /** Name of the icon to display (e.g. 'home'); ignored when `src` is provided. */
28
39
  icon: 'string',
40
+ /** URL of an icon image; takes precedence over `icon` when present. */
29
41
  src: 'string',
42
+ /** Badge content to display on the item (e.g. notification count). */
30
43
  badge: 'string',
44
+ /** Accessible label for the anchor; when present it is used instead of the slot text. */
31
45
  ariaLabel: 'string', // watch attribute and emit callback
32
46
  })
33
47
  .methods({
48
+ /** Focus the internal anchor element. */
34
49
  /** @type {HTMLElement['focus']} */
35
50
  focus(...args) {
36
51
  this.refs.anchor.focus(...args);
@@ -265,13 +280,18 @@ export default CustomElement
265
280
  },
266
281
  keydown({ key, repeat }) {
267
282
  if (key !== ' ') return true;
268
- if (!repeat) this.click();
283
+ if (!repeat) {
284
+ this.click();
285
+ }
269
286
  return false;
270
287
  },
271
288
  },
272
289
  })
273
290
  .extend((Base) => class NavItem extends Base {
274
- /** @type {InstanceType<ReturnType<RippleMixin>>['addRipple']} */
291
+ /**
292
+ * Add a ripple effect only when the item is active.
293
+ * @type {InstanceType<ReturnType<RippleMixin>>['addRipple']}
294
+ */
275
295
  addRipple(...args) {
276
296
  if (!this.active) return null;
277
297
  return super.addRipple(...args);
@@ -1,17 +1,26 @@
1
1
  import SideSheet from './SideSheet.js';
2
2
 
3
+ /**
4
+ * Navigation rails provide access to app destinations and destinations-level
5
+ * navigation in a vertical rail, suited for larger screens and desktop layouts.
6
+ * @see https://m3.material.io/components/navigation-rail/specs
7
+ */
3
8
  export default SideSheet
4
9
  .extend()
5
10
  .observe({
11
+ /** Horizontal alignment for rail content: 'start', 'center', or 'end'. */
6
12
  align: { value: /** @type {'start'|'center'|'end'} */ (null) },
13
+ /** Viewport width (pixels) threshold at or above which the rail will auto-open. */
7
14
  autoOpen: {
8
15
  type: 'float',
9
16
  empty: 728,
10
17
  },
18
+ /** Viewport width (pixels) threshold at or below which the rail will auto-close. */
11
19
  autoClose: {
12
20
  type: 'float',
13
21
  empty: 1248,
14
22
  },
23
+ /** Viewport width (pixels) at which the rail becomes fixed (non-collapsible). */
15
24
  fixedBreakpoint: {
16
25
  type: 'float',
17
26
  empty: 728,
@@ -2,6 +2,11 @@
2
2
 
3
3
  import NavItem from './NavItem.js';
4
4
 
5
+ /**
6
+ * A navigation rail item represents a destination within a navigation rail,
7
+ * showing an icon and optional label for vertical navigation on larger screens.
8
+ * @see https://m3.material.io/components/navigation-rail/specs
9
+ */
5
10
  export default NavItem
6
11
  .extend()
7
12
  .css`
@@ -5,33 +5,45 @@ import { ELEMENT_STYLE_TYPE } from '../core/customTypes.js';
5
5
  import DelegatesFocusMixin from '../mixins/DelegatesFocusMixin.js';
6
6
  import ResizeObserverMixin from '../mixins/ResizeObserverMixin.js';
7
7
 
8
+ /**
9
+ * Page is a top-level layout container that manages single or multi-pane
10
+ * application layouts, adapting to viewport size to show one or two panes.
11
+ * @see https://m3.material.io/foundations/layout/applying-layout/window-size-classes
12
+ */
8
13
  export default CustomElement
9
14
  .extend()
10
15
  .mixin(DelegatesFocusMixin)
11
16
  .mixin(ResizeObserverMixin)
12
17
  .observe({
18
+ /** Layout behavior for the first pane: 'fixed' keeps a fixed width, 'flexible' grows. */
13
19
  paneOne: {
14
20
  value: /** @type {'fixed'|'flexible'} */ ('flexible'),
15
21
  },
22
+ /** Layout behavior for the second pane; null disables the second pane. */
16
23
  paneTwo: {
17
24
  value: /** @type {'fixed'|'flexible'|null} */ (null),
18
25
  },
26
+ /** Whether the second pane is currently active/visible. */
19
27
  paneTwoActive: 'boolean',
28
+ /** Inline-size breakpoint (px) at which the second pane becomes visible. */
20
29
  paneTwoBreakpoint: {
21
30
  type: 'float',
22
31
  empty: 720,
23
32
  },
33
+ /** Internally tracked last measured inline size (pixels) used for layout decisions. */
24
34
  _lastComputedInlineSize: {
25
35
  type: 'float',
26
36
  nullable: false,
27
37
  },
28
38
  })
29
39
  .observe({
40
+ /** Computed: true when two-pane layout should be active based on measured size. */
30
41
  _isMultipane({ _lastComputedInlineSize, paneTwo, paneTwoBreakpoint }) {
31
42
  return Boolean(paneTwo && _lastComputedInlineSize >= paneTwoBreakpoint);
32
43
  },
33
44
  })
34
45
  .observe({
46
+ /** Computed inline CSS string that adjusts grid columns for single/multi-pane layouts. */
35
47
  _styles: {
36
48
  ...ELEMENT_STYLE_TYPE,
37
49
  get({ _isMultipane, paneOne, paneTwoActive }) {
@@ -89,7 +101,8 @@ export default CustomElement
89
101
  position: sticky;
90
102
  inset-block:0;
91
103
 
92
- display: block;
104
+ display: flex;
105
+ flex-direction: column;
93
106
 
94
107
  overflow-y:auto;
95
108
 
@@ -98,6 +111,7 @@ export default CustomElement
98
111
  }
99
112
  `
100
113
  .overrides({
114
+ /** Handle resize observer entries; update measured inline size for layout logic. */
101
115
  onResizeObserved(entry) {
102
116
  this._lastComputedInlineSize = entry.borderBoxSize[0]?.inlineSize;
103
117
  },
@@ -2,6 +2,13 @@ import ShapeMixin from '../mixins/ShapeMixin.js';
2
2
 
3
3
  import Box from './Box.js';
4
4
 
5
+ /**
6
+ * Pane is a layout surface used within `mdw-page` to provide shaped,
7
+ * padded content columns for app content. It is intended to be placed
8
+ * as a child of `mdw-page` to create consistent, shaped panes with the
9
+ * same padding and background surface used across the layout system.
10
+ * @see https://m3.material.io/foundations/layout/applying-layout/window-size-classes
11
+ */
5
12
  export default Box
6
13
  .extend()
7
14
  .mixin(ShapeMixin)
@@ -12,7 +19,6 @@ export default Box
12
19
  --mdw-ink: var(--mdw-color__on-surface);
13
20
  background-color: rgb(var(--mdw-bg));
14
21
  color: rgb(var(--mdw-ink));
15
-
16
22
  }
17
23
  `
18
24
  .autoRegister('mdw-pane');
@@ -4,6 +4,11 @@ import PopupMixin from '../mixins/PopupMixin.js';
4
4
  import ShapeMixin from '../mixins/ShapeMixin.js';
5
5
  import ThemableMixin from '../mixins/ThemableMixin.js';
6
6
 
7
+ /**
8
+ * Popup displays transient content such as menus or popovers and provides
9
+ * elevation, shape, and theming control for floating surfaces.
10
+ * @see https://m3.material.io/styles/elevation/overview
11
+ */
7
12
  export default CustomElement
8
13
  .extend()
9
14
  .mixin(ThemableMixin)
@@ -11,6 +16,7 @@ export default CustomElement
11
16
  .mixin(ShapeMixin)
12
17
  .mixin(PopupMixin)
13
18
  .observe({
19
+ /** Elevation level (0–5) controlling the drop-shadow depth of the popup. */
14
20
  elevation: 'integer',
15
21
  })
16
22
  .css`