@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
@@ -29,6 +29,7 @@ const redispatchedClickEvents = new WeakSet();
29
29
  const rootClickEvents = new WeakSet();
30
30
 
31
31
  /**
32
+ * Enhances a component with input-like attributes and behaviors (value, step, min/max, etc.).
32
33
  * @see https://html.spec.whatwg.org/multipage/input.html#htmlinputelement
33
34
  * @param {ReturnType<import('./StateMixin.js').default>} Base
34
35
  */
@@ -36,26 +37,45 @@ export default function InputMixin(Base) {
36
37
  return Base
37
38
  .mixin(ControlMixin)
38
39
  .observe({
40
+ /** Accepted file types for file input (e.g. '.png,.jpg'). */
39
41
  accept: DOMString,
42
+ /** Alternate text for images (for `type='image'`). */
40
43
  alt: DOMString,
44
+ /** Directionality for form submission name (dirname attribute). */
41
45
  dirName: { attr: 'dirname', ...DOMString },
46
+ /** Form action URL when this input is used as a submit button. */
42
47
  _formAction: { attr: 'formaction' },
48
+ /** Form encoding type (formenctype). */
43
49
  formEnctype: { attr: 'formenctype', ...DOMString },
50
+ /** Form method when associated with a submit input (formmethod). */
44
51
  formMethod: { attr: 'formmethod', ...DOMString },
52
+ /** Target browsing context for form submission (formtarget). */
45
53
  formTarget: { attr: 'formtarget', ...DOMString },
54
+ /** Rendered height hint for certain input types (integer). */
46
55
  _height: { attr: 'height', type: 'integer' },
47
56
  _indeterminate: 'boolean',
57
+ /** Max value or token for the input. */
48
58
  max: DOMString,
59
+ /** Maximum length for text-like inputs. */
49
60
  maxLength: { attr: 'maxlength', type: 'integer', empty: -1 },
61
+ /** Min value or token for the input. */
50
62
  min: DOMString,
63
+ /** Minimum length for text-like inputs. */
51
64
  minLength: { attr: 'minlength', type: 'integer', empty: -1 },
65
+ /** When true, multiple values are allowed (e.g. file inputs). */
52
66
  multiple: 'boolean',
67
+ /** Pattern used for validation (RegExp as string). */
53
68
  pattern: DOMString,
69
+ /** Placeholder text shown when no value is present. */
54
70
  placeholder: DOMString,
71
+ /** Suggested control size (number of characters). */
55
72
  size: { type: 'integer', empty: 20 },
73
+ /** Source URL for image-type inputs. */
56
74
  src: DOMString,
75
+ /** Step interval for numeric inputs. */
57
76
  step: DOMString,
58
77
  // [CEReactions] attribute [LegacyNullToEmptyString] DOMString value;
78
+ /** Rendered width hint for certain input types (integer). */
59
79
  _width: { attr: 'width', type: 'integer' },
60
80
  })
61
81
  .set({
@@ -225,7 +245,9 @@ export default function InputMixin(Base) {
225
245
  // Inner Native Button
226
246
  return;
227
247
  }
248
+ // @ts-expect-error Verified in runtime
228
249
  if ((target instanceof HTMLElement && target.form instanceof HTMLFormElement
250
+ // @ts-expect-error Verified in runtime
229
251
  && (target.type === 'submit' || target.type === 'reset'))) {
230
252
  // Inner FACE Button
231
253
  return;
@@ -12,14 +12,16 @@ const DEFAULT_ELEMENT_QUERY = [
12
12
  ].join(', ');
13
13
 
14
14
  /**
15
+ * Adds keyboard roving navigation utilities for focus management within a list.
15
16
  * @param {typeof import('../core/CustomElement.js').default} Base
16
17
  */
17
18
  export default function KeyboardNavMixin(Base) {
18
19
  return Base
19
20
  .mixin(AriaReflectorMixin)
20
21
  .observe({
21
- /** Keyboard navigation attribute */
22
+ /** Enable keyboard roving navigation when present (set to 'true'). */
22
23
  kbdNav: { empty: 'true' },
24
+ /** Internal flag used to mark focusable children in the roving list. */
23
25
  _kbdFocusable: { empty: true },
24
26
 
25
27
  })
@@ -7,10 +7,12 @@ import ResizeObserverMixin from './ResizeObserverMixin.js';
7
7
 
8
8
  const supportsHTMLDialogElement = typeof HTMLDialogElement !== 'undefined';
9
9
 
10
+ /** @typedef {import('../utils/popup.js').DOMRectLike} DOMRectLike */
11
+
10
12
  /**
11
13
  * @typedef {Object} PopupStack
12
- * @prop {Element} element
13
- * @prop {Element} previousFocus
14
+ * @prop {InstanceType<ReturnType<typeof PopupMixin>>} element
15
+ * @prop {HTMLElement} previousFocus
14
16
  * @prop {boolean} [centered=false]
15
17
  * @prop {Record<string, any>} [state]
16
18
  * @prop {Record<string, any>} [previousState]
@@ -70,6 +72,7 @@ function onBeforeUnload(event) {
70
72
  }
71
73
 
72
74
  /**
75
+ * Provides positioning, modal behavior, and history-aware popup/dialog support.
73
76
  * @param {typeof import('../core/CustomElement.js').default} Base
74
77
  */
75
78
  export default function PopupMixin(Base) {
@@ -77,33 +80,59 @@ export default function PopupMixin(Base) {
77
80
  .mixin(DelegatesFocusMixin)
78
81
  .mixin(ResizeObserverMixin)
79
82
  .observe({
83
+ /** Whether the popup is currently open */
80
84
  open: 'boolean',
85
+ /** When true the popup behaves as a blocking modal */
81
86
  modal: 'boolean',
87
+ /** Use the native HTMLDialogElement when available */
82
88
  native: 'boolean',
89
+ /** Allow internal content to scroll when true */
83
90
  scrollable: 'boolean',
91
+ /** When true, match the popup width to the source element */
84
92
  matchSourceWidth: 'boolean',
93
+ /** Internal: current resolved flow used for positioning */
85
94
  _currentFlow: 'string',
86
95
  flow: {
87
96
  type: 'string',
88
97
  /** @type {'corner'|'adjacent'|'overflow'|'vcenter'|'hcenter'|'center'} */
89
98
  value: null,
90
99
  },
100
+ /** Margin between popup and viewport/anchor (px) */
91
101
  popupMargin: 'float',
92
102
  })
93
103
  .set({
104
+ /** Whether to push/pop history entries when opening the popup */
94
105
  useHistory: true,
106
+ /** Optional return value for dialog-like popups */
95
107
  returnValue: '',
108
+ /** Internal: true while closing is in-progress */
96
109
  _closing: false,
110
+ /** Internal: whether to show a scrim (overlay) for modal popups */
97
111
  _useScrim: false,
112
+ /**
113
+ * Source that triggered the popup
114
+ * @type {MouseEvent|PointerEvent|HTMLElement|Event}
115
+ */
116
+ _source: null,
117
+ /**
118
+ * Anchor used for positioning
119
+ * @type {MouseEvent|PointerEvent|HTMLElement|Event}
120
+ */
121
+ _anchor: null,
98
122
  })
99
123
  .define({
100
124
  _dialog() {
101
125
  return /** @type {HTMLDialogElement} */ (this.refs.dialog);
102
126
  },
103
127
  })
128
+ .expressions({
129
+ _ariaHidden({ open }) {
130
+ return (open ? 'false' : 'true');
131
+ },
132
+ })
104
133
  .methods({
105
134
  /**
106
- * @param {DOMRect|Element} [anchor]
135
+ * @param {DOMRectLike|Element} [anchor]
107
136
  * @return {void}
108
137
  */
109
138
  updatePopupPosition(anchor = this._anchor) {
@@ -121,7 +150,7 @@ export default function PopupMixin(Base) {
121
150
  Object.assign(layoutElement.style, { width: 'auto', height: 'auto' });
122
151
 
123
152
  const width = (anchor && this.matchSourceWidth)
124
- ? anchor.clientWidth
153
+ ? /** @type {Element} */ (anchor).clientWidth
125
154
  : 56 * Math.ceil(layoutElement.clientWidth / 56);
126
155
 
127
156
  layoutElement.style.setProperty('width', `${width}px`);
@@ -197,8 +226,7 @@ export default function PopupMixin(Base) {
197
226
  * - Open from center 9i █·
198
227
  */
199
228
 
200
- /** @type {import('../utils/popup.js').CanAnchorPopUpOptions[]} */
201
- const preferences = [
229
+ const preferences = /** @type {import('../utils/popup.js').CanAnchorPopUpOptions[]} */ ([
202
230
  ((flow ?? 'corner') === 'corner') ? [
203
231
  { clientY: 'bottom', clientX: xStart },
204
232
  { clientY: 'bottom', clientX: xEnd },
@@ -228,7 +256,7 @@ export default function PopupMixin(Base) {
228
256
  ((flow ?? 'center') === 'center') ? [
229
257
  { clientY: 'center', clientX: 'center', directionX: 'center', directionY: 'center' },
230
258
  ] : [],
231
- ].flat();
259
+ ].flat());
232
260
 
233
261
  let anchorResult;
234
262
  for (const preference of preferences) {
@@ -290,7 +318,9 @@ export default function PopupMixin(Base) {
290
318
  scrim.remove();
291
319
  }
292
320
 
293
- const previousFocus = source instanceof HTMLElement ? source : document.activeElement;
321
+ const previousFocus = source instanceof HTMLElement
322
+ ? source
323
+ : /** @type {HTMLElement} */(document.activeElement);
294
324
 
295
325
  if (supportsHTMLDialogElement && focus // Calling show will force focus which is not intended for non-modals
296
326
  && !this._dialog.open) {
@@ -301,6 +331,7 @@ export default function PopupMixin(Base) {
301
331
 
302
332
  // Short first, then move
303
333
  // Native modals can fail update bounds on Chrome
334
+ // @ts-ignore `updatePopupPosition` has runtime check
304
335
  this.updatePopupPosition(source);
305
336
 
306
337
  let newState;
@@ -407,7 +438,8 @@ export default function PopupMixin(Base) {
407
438
  // Closing a native dialog will return focus automatically.
408
439
  this._dialog.close();
409
440
  if (!attemptFocus(previousFocus, { preventScroll: true })) {
410
- document.activeElement?.blur?.();
441
+ const currentlyFocused = /** @type {SVGElement|HTMLElement} */ (document.activeElement);
442
+ currentlyFocused?.blur?.();
411
443
  }
412
444
  } else {
413
445
  this._dialog.returnValue = returnValue;
@@ -468,9 +500,6 @@ export default function PopupMixin(Base) {
468
500
  this.updatePopupPosition();
469
501
  },
470
502
  })
471
- .expressions({
472
- _ariaHidden({ open }) { return (open ? 'false' : 'true'); },
473
- })
474
503
  .html`
475
504
  <mdw-scrim id=scrim tabindex=-1 aria-hidden=true></mdw-scrim>
476
505
  <dialog id=dialog aria-modal=true role=dialog
@@ -4,11 +4,13 @@ const registeredElements = new Set();
4
4
  let rtlObserver;
5
5
 
6
6
  /**
7
+ * Observes document `dir` changes and updates `pageIsRTL` on hosts.
7
8
  * @param {typeof import('../core/CustomElement.js').default} Base
8
9
  */
9
10
  export default function RTLObserverMixin(Base) {
10
11
  return Base
11
12
  .observe({
13
+ /** Whether the page/document direction is RTL; kept in sync */
12
14
  pageIsRTL: {
13
15
  type: 'boolean',
14
16
  value: document.documentElement.dir === 'rtl',
@@ -6,11 +6,13 @@ const resizeObserver = new ResizeObserver((entries) => {
6
6
  });
7
7
 
8
8
  /**
9
+ * Attaches a shared ResizeObserver to the element and provides lifecycle helpers.
9
10
  * @param {typeof import('../core/CustomElement.js').default} Base
10
11
  */
11
12
  export default function ResizeObserverMixin(Base) {
12
13
  return Base
13
14
  .observe({
15
+ /** Enable or disable automatic ResizeObserver attachment (defaults true) */
14
16
  _resizeObserverEnabled: {
15
17
  type: 'boolean',
16
18
  value: true,
@@ -3,14 +3,16 @@ import Ripple from '../components/Ripple.js';
3
3
  /** @typedef {import('../components/Ripple.js').default} Ripple */
4
4
 
5
5
  /**
6
+ * Provides visual ripple effects (pointer/press ripples) and helpers to add/remove them.
6
7
  * @param {ReturnType<import('./StateMixin.js').default>} Base
7
8
  */
8
9
  export default function RippleMixin(Base) {
9
10
  return Base
10
11
  .set({
12
+ /** WeakRef to the last appended Ripple instance (used to release/hold) */
11
13
  /** @type {WeakRef<InstanceType<Ripple>>} */
12
14
  _lastRippleWeakRef: null,
13
- /** Flag set if ripple was added this event loop. */
15
+ /** Flag set if ripple was added this event loop to avoid duplicate ripples */
14
16
  _rippleAdded: false,
15
17
  })
16
18
  .define({
@@ -1,24 +1,34 @@
1
1
  const IDLE_TIMEOUT_MS = 500;
2
2
 
3
3
  /**
4
+ * Tracks scroll/resize positions and exposes scroll-related lifecycle helpers.
4
5
  * @param {typeof import('../core/CustomElement.js').default} Base
5
6
  */
6
7
  export default function ScrollListenerMixin(Base) {
7
8
  return Base
8
9
  .observe({
10
+ /** Current horizontal scroll position (px) */
9
11
  _scrollListenerPositionX: { type: 'float', empty: 0, reflect: false },
12
+ /** Current vertical scroll position (px) */
10
13
  _scrollListenerPositionY: { type: 'float', empty: 0, reflect: false },
14
+ /** Timestamp of the last idle period (ms) */
11
15
  _scrollListenerLastIdle: { type: 'float', empty: 0 },
16
+ /** Timestamp of the last scroll event (ms) */
12
17
  _scrollListenerLastScroll: { type: 'float', empty: 0 },
18
+ /** Timestamp of the last resize event (ms) */
13
19
  _scrollListenerLastResize: { type: 'float', empty: 0 },
14
20
  })
15
21
  .set({
16
- /** @type {WeakRef<EventTarget>} */
22
+ /** WeakRef to the current scroller (HTMLElement or window) */
23
+ /** @type {WeakRef<HTMLElement|Window>} */
17
24
  _scroller: null,
25
+ /** Listener bound to scroller 'scroll' events */
18
26
  /** @type {EventListener} */
19
27
  _scrollerScrollListener: null,
28
+ /** Listener bound to scroller 'resize' events */
20
29
  /** @type {EventListener} */
21
30
  _scrollerResizeListener: null,
31
+ /** Internal debounce timer id used for idle detection */
22
32
  _scrollDebounce: null,
23
33
  })
24
34
  .methods({
@@ -59,6 +69,7 @@ export default function ScrollListenerMixin(Base) {
59
69
  scroller = window;
60
70
  }
61
71
 
72
+ // @ts-expect-error Only HTMLElement or Window can scroll
62
73
  this._scroller = new WeakRef(scroller);
63
74
  this._scrollerScrollListener = this._scrollListenerOnScrollerScroll.bind(this);
64
75
  this._scrollerResizeListener = this._scrollListenerOnScrollerResize.bind(this);
@@ -82,6 +93,7 @@ export default function ScrollListenerMixin(Base) {
82
93
  if (scroller === window) {
83
94
  return document.documentElement.scrollHeight;
84
95
  }
96
+ // @ts-ignore Already checked for window
85
97
  return scroller.scrollHeight;
86
98
  },
87
99
  _scrollListenerScrollerClientHeight() {
@@ -10,12 +10,19 @@ export default function SemiStickyMixin(Base) {
10
10
  return Base
11
11
  .mixin(ScrollListenerMixin)
12
12
  .observe({
13
+ /** Measured full height of the element used for hiding calculations (px) */
13
14
  _semiStickyHeight: { type: 'float', empty: 0 },
15
+ /** Measured top offset used as reveal threshold (px) */
14
16
  _semiStickyOffsetY: { type: 'float', empty: 0 },
17
+ /** Current translateY applied to the element (px) */
15
18
  _semiStickyTranslateY: { type: 'float', empty: 0 },
19
+ /** Animation duration when transitioning translateY (ms) */
16
20
  _semiStickyDuration: { type: 'float', empty: 0 },
21
+ /** Animation easing function for transitions */
17
22
  _semiStickyEasing: { empty: 'ease-in' },
23
+ /** Whether measurements have been performed */
18
24
  _semiStickyMeasured: 'boolean',
25
+ /** When true, element remains always visible */
19
26
  stickyAlways: 'boolean',
20
27
  /** Stick to offsetParent instead of window */
21
28
  stickyParent: 'boolean',
@@ -1,11 +1,19 @@
1
- /** @param {typeof import('../core/CustomElement.js').default} Base */
1
+ /**
2
+ * Provides shape masking utilities and logical shape attributes (shape-top/start/end/bottom).
3
+ * @param {typeof import('../core/CustomElement.js').default} Base
4
+ */
2
5
  export default function ShapeMaskedMixin(Base) {
3
6
  return Base
4
7
  .observe({
8
+ /** Show top cut/shape on the element */
5
9
  shapeTop: 'boolean',
10
+ /** Show bottom cut/shape on the element */
6
11
  shapeBottom: 'boolean',
12
+ /** Show start-side cut/shape (logical start) */
7
13
  shapeStart: 'boolean',
14
+ /** Show end-side cut/shape (logical end) */
8
15
  shapeEnd: 'boolean',
16
+ /** Predefined shape size/style name (none|extra-small|small|medium|large|extra-large|full|inherit) */
9
17
  shapeStyle: 'string',
10
18
  })
11
19
  .css`
@@ -1,14 +1,21 @@
1
1
  /**
2
+ * Adds shape sizing and outline support for components (shape-style, shape-top, etc.).
2
3
  * @param {ReturnType<import('./StateMixin.js').default> & ReturnType<import('./ThemableMixin.js').default>} Base
3
4
  */
4
5
  export default function ShapeMixin(Base) {
5
6
  return Base
6
7
  .observe({
8
+ /** Show top cut/shape on the element */
7
9
  shapeTop: 'boolean',
10
+ /** Show bottom cut/shape on the element */
8
11
  shapeBottom: 'boolean',
12
+ /** Show start-side cut/shape (logical start) */
9
13
  shapeStart: 'boolean',
14
+ /** Show end-side cut/shape (logical end) */
10
15
  shapeEnd: 'boolean',
16
+ /** Predefined shape size/style name (none|extra-small|small|medium|large|extra-large|full|inherit) */
11
17
  shapeStyle: 'string',
18
+ /** When true, an outline is rendered around the element */
12
19
  outlined: 'boolean',
13
20
  })
14
21
  .html`
@@ -99,6 +106,8 @@ export default function ShapeMixin(Base) {
99
106
  position: absolute;
100
107
  inset: 0;
101
108
 
109
+ overflow: hidden;
110
+
102
111
  border-style: solid;
103
112
  border-width: 1px;
104
113
 
@@ -3,11 +3,14 @@
3
3
  let lastInteractionWasTouch = window?.matchMedia?.('(any-pointer: coarse)').matches;
4
4
 
5
5
  /**
6
+ * Manages interactive state flags (disabled, focused, hovered, pressed, touch)
7
+ * and derived state expressions used by components.
6
8
  * @param {typeof import('../core/CustomElement.js').default} Base
7
9
  */
8
10
  export default function StateMixin(Base) {
9
11
  return Base
10
12
  .observe({
13
+ /** Whether the element is disabled (affects interactive states) */
11
14
  disabled: 'boolean',
12
15
  /** Force focus state (independent of document) */
13
16
  focused: 'boolean',
@@ -27,6 +30,7 @@ export default function StateMixin(Base) {
27
30
  /** True if key was released this event loop. (Used to ignore clicks) */
28
31
  _keyReleased: 'boolean',
29
32
  _pointerPressed: 'boolean',
33
+ /** Show the visual state layer element when true */
30
34
  stateLayer: 'boolean',
31
35
  })
32
36
  .observe({
@@ -5,6 +5,7 @@ import ShapeMixin from './ShapeMixin.js';
5
5
  /** @typedef {import('../core/CustomElement.js').default} CustomElement */
6
6
 
7
7
  /**
8
+ * Composes a text field with label, supporting text, icons and control wiring.
8
9
  * @param {ReturnType<import('./ControlMixin.js').default>} Base
9
10
  */
10
11
  export default function TextFieldMixin(Base) {
@@ -12,23 +13,38 @@ export default function TextFieldMixin(Base) {
12
13
  .mixin(DensityMixin)
13
14
  .mixin(ShapeMixin)
14
15
  .set({
16
+ /** Show an internal visual state layer element */
15
17
  stateLayer: true,
16
18
  })
17
19
  .observe({
20
+ /** Input type (text, password, email, etc.) */
18
21
  type: { empty: 'text' },
22
+ /** Leading icon key/name to render inside the field */
19
23
  icon: 'string',
24
+ /** Variation of the icon display (e.g., filled) */
20
25
  iconVariation: 'string',
26
+ /** Floating label text for the field */
21
27
  label: 'string',
28
+ /** When true, use filled styling */
22
29
  filled: 'boolean',
30
+ /** When true, use outlined styling */
23
31
  outlined: 'boolean',
32
+ /** Prefix text shown before the input */
24
33
  inputPrefix: 'string',
34
+ /** Suffix text shown after the input */
25
35
  inputSuffix: 'string',
36
+ /** Trailing icon key/name */
26
37
  trailingIcon: 'string',
38
+ /** Ink/color token for the trailing icon */
27
39
  trailingIconInk: 'string',
40
+ /** Accessible label for the trailing icon */
28
41
  trailingIconLabel: 'string',
42
+ /** Supporting/helper text shown beneath the field */
29
43
  supporting: 'string',
44
+ /** Error message text */
30
45
  error: 'string',
31
- placeholder: { nullParser: String }, // DOMString
46
+ /** Placeholder text (DOMString) */
47
+ placeholder: { nullParser: String },
32
48
  })
33
49
  .observe({
34
50
  erroredState({ error, _invalid, _userInteracted }) { return _userInteracted && Boolean(error || _invalid); },
@@ -113,8 +129,11 @@ export default function TextFieldMixin(Base) {
113
129
  inline.prepend(control);
114
130
  })
115
131
  .on({
132
+ // @ts-ignore TODO: Missing observable size property
116
133
  sizeChanged(oldValue, newValue) {
117
- this.refs.control.style.setProperty('--size', `${newValue}ch`);
134
+ // @ts-ignore TODO: Missing {this} context
135
+ const control = /** @type {HTMLElement} */ (this.refs.control);
136
+ control.style.setProperty('--size', `${newValue}ch`);
118
137
  },
119
138
  })
120
139
  .css`
@@ -39,13 +39,26 @@ const typeStyleAttributeCSS = TYPE_STYLES.map((typeStyle) => [
39
39
  ].join('')).join('');
40
40
 
41
41
  /**
42
+ * Adds theming attributes (`color`, `ink`, `typeStyle`) that map to CSS tokens.
42
43
  * @param {typeof import('../core/CustomElement.js').default} Base
43
44
  */
44
45
  export default function ThemableMixin(Base) {
45
46
  return Base
46
47
  .observe({
48
+ /**
49
+ * Palette or surface token used to select background/ink tokens.
50
+ * Examples: 'primary', 'background', 'surface-container-low'.
51
+ */
47
52
  color: 'string',
53
+ /**
54
+ * Explicit ink override token (e.g. 'outline', 'on-primary', 'inverse-on-surface', 'inherit').
55
+ * Maps to `--mdw-ink`.
56
+ */
48
57
  ink: 'string',
58
+ /**
59
+ * Typographic style shortcut that maps to type scale variables
60
+ * (e.g. 'headline-large', 'body-medium').
61
+ */
49
62
  typeStyle: 'string',
50
63
  })
51
64
  .css(colorAttributeCSS)
@@ -5,26 +5,37 @@ import { canAnchorPopup } from '../utils/popup.js';
5
5
  /** @typedef {import('../components/Tooltip.js').default} Tooltip */
6
6
 
7
7
  /**
8
+ * Adds tooltip scheduling, positioning, and show/hide behavior for host elements.
8
9
  * @param {ReturnType<import('./StateMixin.js').default>} Base
9
10
  */
10
11
  export default function TooltipTriggerMixin(Base) {
11
12
  return Base
12
13
  .set({
14
+ /** Idle delay before showing tooltip for mouse (ms) */
13
15
  TOOLTIP_MOUSE_IDLE_MS: 500,
16
+ /** Idle delay before showing tooltip for touch (ms) */
14
17
  TOOLTIP_TOUCH_IDLE_MS: 1500,
18
+ /** Timer id used for tooltip show/hide debouncing */
15
19
  /** @type {any} */
16
20
  _idleDebounce: null,
21
+ /** Parents being observed for layout changes */
17
22
  /** @type {HTMLElement[]} */
18
23
  _watchedParents: null,
24
+ /** ResizeObserver used to track tooltip/anchor size changes */
19
25
  /** @type {ResizeObserver} */
20
26
  _resizeObserver: null,
27
+ /** IntersectionObserver used to detect occlusion */
21
28
  /** @type {IntersectionObserver} */
22
29
  _intersectObserver: null,
30
+ /** Bound scroll listener attached to parent elements */
23
31
  _parentScrollListener: null,
32
+ /** Slot id to use when cloning tooltip content */
24
33
  tooltipSlotId: 'slot',
25
34
  })
26
35
  .observe({
36
+ /** Text or content id used as tooltip content */
27
37
  tooltip: 'string',
38
+ /** When true, show tooltip automatically on hover/focus */
28
39
  autoTooltip: 'boolean',
29
40
  })
30
41
  .html`<mdw-tooltip id=tooltip></mdw-tooltip>`
@@ -41,7 +52,8 @@ export default function TooltipTriggerMixin(Base) {
41
52
  /** @param {'mouse'|'touch'|'keyboard'} type */
42
53
  scheduleHideTooltip(type) {
43
54
  this.cancelShowTooltip();
44
- if (!this.refs.tooltip.open) {
55
+ const tooltip = /** @type {InstanceType<Tooltip>} */ (this.refs.tooltip);
56
+ if (!tooltip.open) {
45
57
  // console.log('abort schedule (shown)');
46
58
  return;
47
59
  }
@@ -64,7 +76,8 @@ export default function TooltipTriggerMixin(Base) {
64
76
 
65
77
  /** @param {'mouse'|'touch'|'keyboard'} type */
66
78
  scheduleShowTooltip(type) {
67
- if (this.refs.tooltip.open) return;
79
+ const tooltip = /** @type {InstanceType<Tooltip>} */ (this.refs.tooltip);
80
+ if (tooltip.open) return;
68
81
  let timeout = 0;
69
82
  switch (type) {
70
83
  case 'mouse':
@@ -95,8 +108,9 @@ export default function TooltipTriggerMixin(Base) {
95
108
  this._intersectObserver.observe(this);
96
109
  this._intersectObserver.observe(tooltip);
97
110
  /** @type {HTMLElement} */
111
+ // eslint-disable-next-line unicorn/no-this-assignment, @typescript-eslint/no-this-alias
98
112
  let offsetParent = this;
99
- while ((offsetParent = offsetParent.offsetParent)) {
113
+ while ((offsetParent = /** @type {?HTMLElement} */ (offsetParent.offsetParent))) {
100
114
  this._resizeObserver.observe(offsetParent, { box: 'border-box' });
101
115
  // console.log('observing', offsetParent);
102
116
  this._watchedParents.push(offsetParent);
@@ -1,4 +1,7 @@
1
- /** @param {typeof import('../core/CustomElement.js').default} Base */
1
+ /**
2
+ * Provides a visually hidden touch target area to meet touch size recommendations.
3
+ * @param {typeof import('../core/CustomElement.js').default} Base
4
+ */
2
5
  export default function TouchTargetMixin(Base) {
3
6
  return Base
4
7
  .html`<div id=touch-target class=touch-target></div>`
@@ -12,14 +12,21 @@ function parseSize(input) {
12
12
  return `calc(${input.replace('sp', '')} * 0.0625rem)`;
13
13
  }
14
14
 
15
- /** @param {typeof import('../core/CustomElement.js').default} Base */
15
+ /**
16
+ * Provides typographic padding and leading helpers for text content.
17
+ * @param {typeof import('../core/CustomElement.js').default} Base
18
+ */
16
19
  export default function TypographyMixin(Base) {
17
20
  return Base
18
21
  .mixin(DelegatesFocusMixin)
19
22
  .observe({
23
+ /** General vertical padding for text content (css length) */
20
24
  textPadding: 'string',
25
+ /** Padding-top override for text content (css length) */
21
26
  textPaddingTop: 'string',
27
+ /** Line-leading (extra top spacing) for text (css length or 'sp' units) */
22
28
  textLeading: 'string',
29
+ /** Padding-bottom override for text content (css length) */
23
30
  textPaddingBottom: 'string',
24
31
  })
25
32
  .observe({