@shortfuse/materialdesignweb 0.7.6 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +57 -68
  2. package/components/Badge.js +2 -2
  3. package/components/BottomAppBar.js +3 -5
  4. package/components/Box.js +33 -3
  5. package/components/Button.js +48 -21
  6. package/components/Button.md +9 -9
  7. package/components/Card.js +9 -16
  8. package/components/Checkbox.js +45 -36
  9. package/components/CheckboxIcon.js +2 -2
  10. package/components/Chip.js +1 -1
  11. package/components/Dialog.js +228 -359
  12. package/components/DialogActions.js +2 -2
  13. package/components/Divider.js +3 -3
  14. package/components/ExtendedFab.js +4 -8
  15. package/components/Fab.js +1 -2
  16. package/components/FilterChip.js +4 -4
  17. package/components/Headline.js +1 -1
  18. package/components/Icon.js +8 -8
  19. package/components/IconButton.js +9 -14
  20. package/components/Input.js +273 -1
  21. package/components/Layout.js +485 -16
  22. package/components/List.js +6 -4
  23. package/components/ListItem.js +12 -12
  24. package/components/ListOption.js +21 -5
  25. package/components/Listbox.js +239 -0
  26. package/components/Menu.js +77 -526
  27. package/components/MenuItem.js +12 -14
  28. package/components/Nav.js +0 -2
  29. package/components/NavBar.js +8 -79
  30. package/components/NavDrawer.js +12 -11
  31. package/components/NavDrawerItem.js +2 -1
  32. package/components/NavItem.js +18 -8
  33. package/components/NavRail.js +15 -7
  34. package/components/NavRailItem.js +3 -1
  35. package/components/Popup.js +20 -0
  36. package/components/Progress.js +24 -23
  37. package/components/Radio.js +42 -35
  38. package/components/RadioIcon.js +3 -3
  39. package/components/Ripple.js +2 -3
  40. package/components/Search.js +85 -0
  41. package/components/SegmentedButton.js +1 -10
  42. package/components/SegmentedButtonGroup.js +16 -10
  43. package/components/Select.js +4 -4
  44. package/components/Shape.js +1 -1
  45. package/components/Slider.js +43 -50
  46. package/components/Snackbar.js +4 -5
  47. package/components/Surface.js +3 -3
  48. package/components/Switch.js +55 -21
  49. package/components/SwitchIcon.js +10 -8
  50. package/components/Tab.js +11 -9
  51. package/components/TabContent.js +4 -3
  52. package/components/TabList.js +2 -2
  53. package/components/TabPanel.js +11 -8
  54. package/components/TextArea.js +38 -35
  55. package/components/Tooltip.js +2 -2
  56. package/components/TopAppBar.js +65 -147
  57. package/core/Composition.js +985 -628
  58. package/core/CompositionAdapter.js +315 -0
  59. package/core/CustomElement.js +153 -90
  60. package/core/DomAdapter.js +586 -0
  61. package/core/ICustomElement.d.ts +2 -2
  62. package/core/css.js +8 -7
  63. package/core/customTypes.js +53 -31
  64. package/{utils → core}/jsonMergePatch.js +36 -14
  65. package/core/observe.js +111 -57
  66. package/core/optimizations.js +23 -0
  67. package/core/template.js +17 -11
  68. package/core/test.js +126 -0
  69. package/core/typings.d.ts +11 -5
  70. package/core/uid.js +13 -0
  71. package/dist/index.min.js +83 -152
  72. package/dist/index.min.js.map +4 -4
  73. package/dist/meta.json +1 -1
  74. package/mixins/AriaReflectorMixin.js +1 -2
  75. package/mixins/AriaToolbarMixin.js +2 -3
  76. package/mixins/ControlMixin.js +25 -17
  77. package/mixins/DensityMixin.js +0 -1
  78. package/mixins/FlexableMixin.js +1 -2
  79. package/mixins/FormAssociatedMixin.js +13 -10
  80. package/mixins/InputMixin.js +2 -9
  81. package/mixins/KeyboardNavMixin.js +14 -1
  82. package/mixins/PopupMixin.js +757 -0
  83. package/mixins/RTLObserverMixin.js +0 -1
  84. package/mixins/ResizeObserverMixin.js +0 -1
  85. package/mixins/RippleMixin.js +3 -4
  86. package/mixins/ScrollListenerMixin.js +41 -32
  87. package/mixins/SemiStickyMixin.js +151 -0
  88. package/mixins/ShapeMixin.js +29 -24
  89. package/mixins/StateMixin.js +11 -6
  90. package/mixins/SurfaceMixin.js +3 -57
  91. package/mixins/TextFieldMixin.js +57 -65
  92. package/mixins/ThemableMixin.js +78 -156
  93. package/mixins/TooltipTriggerMixin.js +7 -13
  94. package/mixins/TouchTargetMixin.js +4 -3
  95. package/package.json +9 -5
  96. package/theming/index.js +1 -1
  97. package/theming/themableMixinLoader.js +12 -0
  98. package/utils/{hct → material-color}/blend.js +8 -10
  99. package/utils/{hct → material-color/hct}/Cam16.js +196 -69
  100. package/utils/{hct → material-color/hct}/Hct.js +61 -19
  101. package/utils/{hct → material-color/hct}/ViewingConditions.js +3 -3
  102. package/utils/{hct → material-color/hct}/hctSolver.js +9 -16
  103. package/utils/{hct → material-color}/helper.js +11 -18
  104. package/utils/{hct → material-color/palettes}/CorePalette.js +79 -19
  105. package/utils/{hct → material-color/palettes}/TonalPalette.js +12 -4
  106. package/utils/material-color/scheme/Scheme.js +376 -0
  107. package/utils/{hct/colorUtils.js → material-color/utils/color.js} +61 -1
  108. package/utils/popup.js +46 -25
  109. package/components/ListSelect.js +0 -220
  110. package/components/Option.js +0 -91
  111. package/components/Pane.js +0 -281
  112. package/core/identify.js +0 -40
  113. package/utils/hct/Scheme.js +0 -587
  114. /package/utils/{hct/mathUtils.js → material-color/utils/math.js} +0 -0
@@ -1,35 +1,504 @@
1
+ /* https://m3.material.io/foundations/layout/applying-layout/window-size-classes */
2
+
1
3
  import CustomElement from '../core/CustomElement.js';
4
+ import { ELEMENT_STYLER_TYPE } from '../core/customTypes.js';
2
5
 
3
6
  export default CustomElement
4
7
  .extend()
5
- .html/* html */`
6
- <slot id=slot-top name=top></slot>
7
- <slot id=slot></slot>
8
+ .observe({
9
+ navBar: 'string',
10
+ navRail: 'string',
11
+ navDrawer: 'string',
12
+ oneFlexible: 'boolean',
13
+ oneFixed: 'boolean',
14
+ twoFlexible: 'boolean',
15
+ twoFixed: 'boolean',
16
+ paneTwoActive: 'boolean',
17
+ paneOneColumns: 'integer',
18
+ paneTwoColumns: 'integer',
19
+ padding: 'integer',
20
+ panes: 'integer',
21
+ _touchDeltaX: 'integer',
22
+ _touchStartX: 'integer',
23
+ _navDrawerTranslateX: {
24
+ empty: '-100%',
25
+ },
26
+ _navDrawerDuration: {
27
+ empty: 0,
28
+ },
29
+ })
30
+ .observe({
31
+ hasTwo: {
32
+ type: 'boolean',
33
+ reflect: 'write',
34
+ get({ twoFlexible, twoFixed }) {
35
+ return twoFlexible || twoFixed;
36
+ },
37
+ },
38
+ singlePane: {
39
+ type: 'boolean',
40
+ reflect: 'write',
41
+ get({ oneFlexible, oneFixed, twoFlexible, twoFixed }) {
42
+ return (oneFlexible || oneFixed) && !(twoFlexible || twoFixed);
43
+ },
44
+ },
45
+ _navDrawerStyle: {
46
+ ...ELEMENT_STYLER_TYPE,
47
+ get({ _navDrawerTranslateX, _navDrawerDuration }) {
48
+ return {
49
+ target: 'slot-nav-drawer',
50
+ styles: {
51
+ transform: `translateX(${_navDrawerTranslateX})`,
52
+ },
53
+ timing: {
54
+ duration: _navDrawerDuration,
55
+ },
56
+ };
57
+ },
58
+ },
59
+ })
60
+ .set({
61
+ /** @type {Map<string, MediaQueryList>} */
62
+ registeredMediaQueries: null,
63
+ refreshedOpenStatesFlag: false,
64
+ _windowResizeListener: null,
65
+ })
66
+ /* Slots should follow tab order */
67
+ .html`
68
+ <slot id=slot-nav-drawer name=nav-drawer state={navDrawer}></slot>
69
+ <div id=scrim state={navDrawer}></div>
70
+ <slot id=slot-nav-rail name=nav-rail state={navRail}></slot>
71
+ <slot id=slot-app-bar name=app-bar></slot>
72
+ <slot id=slot class="pane pane1" columns={paneOneColumns} slotted={oneFlexible}></slot>
73
+ <slot id=slot-fixed name=fixed class="pane pane1" columns={paneOneColumns} slotted={oneFixed} ></slot>
74
+ <slot id=slot-two name=two class="pane pane2" panes={panes} columns={paneTwoColumns} slotted={twoFlexible}></slot>
75
+ <slot id=slot-two-fixed name=two-fixed class="pane pane2" panes={panes} columns={paneTwoColumns} slotted={twoFixed} ></slot>
76
+ <slot id=slot-nav-bar name=nav-bar state={navBar}></slot>
8
77
  `
9
- .css`
10
- /* https://m3.material.io/foundations/layout/applying-layout/window-size-classes */
78
+ .methods({
79
+ refreshLayoutValues() {
80
+ /**
81
+ * Prefer content to navigation (eg: Don't shrink content for nav)
82
+ * Prefer 2nd pane always
83
+ * Breakpoints ( x = 16, | = 24 )
84
+ * - Nav Pane1 Pane2 Columns Nav Detail Content Width Use?
85
+ * - Modal 4col x 0 x 0 0 0 0 YES
86
+ * - Rail 4col 80 x 360 x 80 0 360 472 NO
87
+ * - Modal 8col x 600 x 0 0 600 632 YES
88
+ * - Modal 8col | 600 | 0 0 600 648 YES
89
+ * - Rail 8col 80 | 600 | 80 0 600 728 YES
90
+ * - Drawer 4col 360 | 360 | 360 0 360 768 NO
91
+ * - Modal 4col 4col | 360 | 360 | 360 360 720 792 YES
92
+ * - Modal Fixed 4col | 360 | 360 | 360 360 720 792 YES
93
+ * - Rail 4col 4col 80 | 360 | 360 | 80 360 720 872 YES
94
+ * - Rail Fixed 4col 80 | 360 | 360 | 80 360 720 872 YES
95
+ * - Modal 12col | 840 | 0 0 840 888 If Single Pane + No Rail
96
+ * - Rail 12col 80 | 840 | 80 0 840 968 If Single Pane
97
+ * - Drawer 8col 360 | 600 | 360 0 600 1008 NO (Loses Content)
98
+ * - Modal Fixed 8col | 360 | 600 | 0 600 960 1032 If No Rail
99
+ * - Rail Fixed 8col 80 | 360 | 600 | 80 600 960 1112 YES
100
+ * - Drawer 4col 4col 360 | 360 | 360 | 360 360 720 1152 NO (Modal 4/4 has more content)
101
+ * - Drawer Fixed 4col 360 | 360 | 360 | 360 360 720 1152 NO (Modal F/8 has more content)
102
+ * - Drawer 12col 360 | 840 | 360 0 840 1248 If Single Pane
103
+ * - Modal 8col 8col | 600 | 600 | 0 600 1200 1272 *If No Rail
104
+ * - Modal Fixed 12col | 360 | 840 | 0 840 1200 1272 *If No Rail
105
+ * - Rail 8col 8col 80 | 600 | 600 | 80 600 1200 1352 YES
106
+ * - Rail Fixed 12col 80 | 360 | 840 | 80 840 1200 1352 YES
107
+ * - Drawer Fixed 8col 360 | 360 | 600 | 360 600 960 1392 *If No Rail
108
+ * - Drawer 8col 8col 360 | 600 | 600 | 360 600 720 1632 *If No Rail
109
+ * - Drawer Fixed 12col 360 | 360 | 840 | 360 840 1200 1632 YES
110
+ * - Modal 12col 12col | 840 | 840 | 0 840 1680 1752 If No Rail + No Nav Drawer
111
+ * - Rail 12col 12col 80 | 840 | 840 | 80 840 1680 1832 If No Drawer
112
+ * - Drawer 12col 12col 360 | 840 | 840 | 360 840 1680 2112 YES
113
+ */
114
+
115
+ /**
116
+ * SORTED + FILTERED
117
+ * - Nav Pane1 Pane2 Columns Nav Detail Content Width
118
+ * - Modal 4col x 0 x 0 0 0 0
119
+ * - Modal 8col x 600 x 0 0 600 632
120
+ * - Modal 8col | 600 | 0 0 600 648
121
+ * - Modal 12col | 840 | 0 0 840 888
122
+ * - Rail 8col 80 | 600 | 80 0 600 728
123
+ * - Rail 12col 80 | 840 | 80 0 840 968
124
+ * - Drawer 12col 360 | 840 | 360 0 840 1248
125
+ * - Modal 4col 4col | 360 | 360 | 0 360 720 792
126
+ * - Modal 8col 8col | 600 | 600 | 0 600 1200 1272
127
+ * - Modal 12col 12col | 840 | 840 | 0 840 1680 1752
128
+ * - Modal Fixed 4col | 360 | 360 | 0 360 720 792
129
+ * - Modal Fixed 8col | 360 | 600 | 0 600 960 1032
130
+ * - Modal Fixed 12col | 360 | 840 | 0 840 1200 1272
131
+ * - Drawer 8col 8col 360 | 600 | 600 | 360 600 720 1632
132
+ * - Drawer Fixed 8col 360 | 360 | 600 | 360 600 960 1392
133
+ * - Rail 4col 4col 80 | 360 | 360 | 80 360 720 872
134
+ * - Rail 8col 8col 80 | 600 | 600 | 80 600 1200 1352
135
+ * - Rail 12col 12col 80 | 840 | 840 | 80 840 1680 1832
136
+ * - Rail Fixed 4col 80 | 360 | 360 | 80 360 720 872
137
+ * - Rail Fixed 8col 80 | 360 | 600 | 80 600 960 1112
138
+ * - Rail Fixed 12col 80 | 360 | 840 | 80 840 1200 1352
139
+ * - Drawer 12col 12col 360 | 840 | 840 | 360 840 1680 2112
140
+ * - Drawer Fixed 12col 360 | 360 | 840 | 360 840 1200 1632
141
+ */
11
142
 
143
+ const { innerWidth } = window;
144
+ /** @type {[number, 'modal'|'rail'|'drawer', 4|8|12|'fixed', number, number][]} */
145
+ const breakpointTable = [
146
+ [1632, 'drawer', 'fixed', 12, 24],
147
+ [2112, 'drawer', 12, 12, 24],
148
+ [1352, 'rail', 'fixed', 12, 24],
149
+ [1112, 'rail', 'fixed', 8, 24],
150
+ [872, 'rail', 'fixed', 4, 24],
151
+ [1832, 'rail', 12, 12, 24],
152
+ [1352, 'rail', 8, 8, 24],
153
+ [872, 'rail', 4, 4, 24],
154
+ [1392, 'drawer', 'fixed', 8, 24],
155
+ [1632, 'drawer', 8, 8, 24],
156
+ [1272, 'modal', 'fixed', 12, 24],
157
+ [1032, 'modal', 'fixed', 8, 24],
158
+ [792, 'modal', 'fixed', 4, 24],
159
+ [1752, 'modal', 12, 12, 24],
160
+ [1272, 'modal', 8, 8, 24],
161
+ [792, 'modal', 4, 4, 24],
162
+ [1248, 'drawer', 12, 0, 24],
163
+ [960, 'rail', 12, 0, 24],
164
+ [728, 'rail', 8, 0, 24],
165
+ [888, 'modal', 12, 0, 24],
166
+ [648, 'modal', 8, 0, 24],
167
+ [632, 'modal', 8, 0, 16],
168
+ [0, 'modal', 4, 0, 16],
169
+ ];
170
+ breakpointTable.some(([minWidth, nav, column1, column2, padding]) => {
171
+ if (innerWidth < minWidth) return false;
172
+ if (column2 && !this.hasTwo) return false;
173
+ if (nav === 'rail') {
174
+ if (!this.navRail) return false;
175
+ this.navRail = 'fixed';
176
+ if (this.navDrawer) this.navDrawer = 'closed';
177
+ if (this.navBar) this.navBar = 'closed';
178
+ } else if (nav === 'drawer') {
179
+ if (!this.navDrawer) return false;
180
+ if (this.navRail) this.navRail = 'closed';
181
+ if (this.navBar) this.navBar = 'closed';
182
+ this.navDrawer = 'fixed';
183
+ } else {
184
+ if (this.navRail) this.navRail = 'closed';
185
+ if (this.navDrawer) this.navDrawer = 'closed';
186
+ if (this.navBar) this.navBar = 'open';
187
+ }
188
+ this.padding = padding;
189
+ if (column2) {
190
+ this.panes = 2;
191
+ if (this.oneFixed) {
192
+ this.paneOneColumns = 4;
193
+ this.paneTwoColumns = column2;
194
+ } else if (this.twoFixed) {
195
+ this.paneOneColumns = column2;
196
+ this.paneTwoColumns = 4;
197
+ }
198
+ } else {
199
+ this.panes = 1;
200
+ this.paneOneColumns = /** @type {number} */ (column1);
201
+ this.paneTwoColumns = this.hasTwo
202
+ ? /** @type {number} */ (column1)
203
+ : null;
204
+ }
205
+ return true;
206
+ });
207
+ },
208
+ checkTouchFinished() {
209
+ if (this.navDrawer !== 'open') return;
210
+ const { _touchDeltaX, refs } = this;
211
+ const clientWidth = refs.slotNavDrawer.clientWidth;
212
+ const visibility = (_touchDeltaX + clientWidth) / clientWidth;
213
+ if (visibility < 0.5) {
214
+ this._navDrawerTranslateX = '-100%';
215
+ this._navDrawerDuration = 200 * visibility;
216
+ this.navDrawer = 'closed';
217
+ } else {
218
+ this._navDrawerTranslateX = '0';
219
+ this._navDrawerDuration = 200 * (0.5 * visibility);
220
+ }
221
+ },
222
+ })
223
+ .events({
224
+ '~touchstart'(event) {
225
+ if (this.navDrawer !== 'open') return;
226
+ if (!event.touches.length) return;
227
+ let [{ clientX, pageX }] = event.touches;
228
+ clientX ??= pageX - window.scrollX; // Safari
229
+ this._touchStartX = clientX;
230
+ },
231
+ '~touchmove'({ touches }) {
232
+ if (this.navDrawer !== 'open') return;
233
+ if (!touches.length) return;
234
+ let [{ clientX, pageX }] = touches;
235
+ clientX ??= pageX - window.scrollX; // Safari
236
+ const delta = Math.min(clientX - this._touchStartX, 0);
237
+
238
+ this._touchDeltaX = delta;
239
+ this._navDrawerTranslateX = `${delta}px`;
240
+ this._navDrawerDuration = 0;
241
+ },
242
+ touchcancel: 'checkTouchFinished',
243
+ '~touchend': 'checkTouchFinished',
244
+ })
245
+ .rootEvents({
246
+ slotchange({ target }) {
247
+ const slotElement = /** @type HTMLSlotElement */ (target);
248
+ const slotted = slotElement.assignedElements().length > 0;
249
+ switch (slotElement.name) {
250
+ case 'nav-rail':
251
+ this.navRail = slotted ? 'closed' : null;
252
+ break;
253
+ case 'nav-bar':
254
+ this.navBar = slotted ? 'closed' : null;
255
+ break;
256
+ case 'nav-drawer':
257
+ this.navDrawer = slotted ? 'closed' : null;
258
+ break;
259
+ case 'fixed':
260
+ this.oneFixed = slotted;
261
+ break;
262
+ case 'two':
263
+ this.twoFlexible = slotted;
264
+ break;
265
+ case 'two-fixed':
266
+ this.twoFixed = slotted;
267
+ break;
268
+ default:
269
+ this.oneFlexible = slotted;
270
+ break;
271
+ }
272
+ this.refreshLayoutValues();
273
+ },
274
+ })
275
+ .childEvents({
276
+ scrim: {
277
+ click() {
278
+ this.navDrawer = 'closed';
279
+ },
280
+ },
281
+ })
282
+ .on({
283
+ navDrawerChanged(previous, current) {
284
+ this._navDrawerTranslateX = current === 'closed' ? '-100%' : '0';
285
+ this._navDrawerDuration = current === 'fixed' ? 0 : 200;
286
+ },
287
+ connected() {
288
+ this._windowResizeListener = this.refreshLayoutValues.bind(this);
289
+ window.addEventListener('resize', this._windowResizeListener);
290
+ },
291
+ disconnected() {
292
+ window.removeEventListener('resize', this._windowResizeListener);
293
+ },
294
+ })
295
+ .css`
12
296
  :host {
13
- display: block;
297
+ --mdw-grid__columns: 4;
298
+ --mdw-content__max-width: 1040px;
299
+ --mdw-content__padding: 16px;
300
+ --mdw-layout__spacer-width: 24px;
301
+ --mdw-layout__nav-drawer__ratio: 0;
302
+ --mdw-layout__nav-drawer-width: 360px;
303
+ --mdw-layout__nav-rail__ratio: 0;
304
+ --mdw-layout__nav-rail-width: 80px;
305
+ --mdw-layout__pane1-width: minmax(0, 1fr);
306
+ --mdw-layout__pane2-width: 0;
307
+ --mdw-layout__window-padding: 16px;
308
+
309
+ display: grid;
310
+ grid-template-rows: auto 1fr auto;
311
+ grid-template-columns:
312
+ calc(var(--mdw-layout__nav-drawer-width) * var(--mdw-layout__nav-drawer__ratio))
313
+ calc(var(--mdw-layout__nav-rail-width) * var(--mdw-layout__nav-rail__ratio))
314
+ var(--mdw-layout__window-padding)
315
+ var(--mdw-layout__pane1-width)
316
+ var(--mdw-layout__window-padding)
317
+ var(--mdw-layout__pane2-width) 0;
318
+ grid-template-areas:
319
+ "nav-drawer nav-rail app-bar app-bar app-bar pane2 ."
320
+ "nav-drawer nav-rail . pane1 . pane2 ."
321
+ "nav-drawer nav-rail nav-bar nav-bar nav-bar nav-bar .";
322
+ overflow-x: clip;
14
323
 
15
- /* QOL */
16
324
  font: var(--mdw-typescale__body-large__font);
17
325
  letter-spacing: var(--mdw-typescale__body-large__letter-spacing);
18
-
19
326
  }
20
327
 
21
- /* Pane Slot */
22
- #slot {
23
- display: flex;
24
- gap: 24px;
328
+ :host(:where([pane-two-active])) {
329
+ grid-template-areas:
330
+ "nav-drawer nav-rail app-bar app-bar app-bar pane1 ."
331
+ "nav-drawer nav-rail . pane2 . pane1 ."
332
+ "nav-drawer nav-rail nav-bar nav-bar nav-bar nav-bar .";
333
+ }
334
+
335
+ :host(:where([panes="2"])) {
336
+ --mdw-content__max-width: auto;
337
+ --mdw-layout__pane2-width: 1fr;
338
+ grid-template-columns:
339
+ calc(var(--mdw-layout__nav-drawer-width) * var(--mdw-layout__nav-drawer__ratio))
340
+ calc(var(--mdw-layout__nav-rail-width) * var(--mdw-layout__nav-rail__ratio))
341
+ var(--mdw-layout__window-padding)
342
+ var(--mdw-layout__pane1-width)
343
+ var(--mdw-layout__spacer-width)
344
+ var(--mdw-layout__pane2-width)
345
+ var(--mdw-layout__window-padding);
346
+
347
+ grid-template-areas:
348
+ "nav-drawer nav-rail app-bar app-bar app-bar pane2 ."
349
+ "nav-drawer nav-rail . pane1 . pane2 ."
350
+ "nav-drawer nav-rail nav-bar nav-bar nav-bar nav-bar .";
351
+ }
352
+
353
+ :host(:where([nav-rail="fixed"])) {
354
+ --mdw-layout__nav-rail__ratio: 1;
355
+ }
356
+
357
+ :host(:where([nav-drawer="fixed"])) {
358
+ --mdw-layout__nav-drawer__ratio: 1;
359
+ }
360
+
361
+ :host(:where([padding="24"])) {
362
+ --mdw-layout__window-padding: 24px;
363
+ --mdw-content__padding: 24px;
364
+ }
365
+
366
+ :host(:where([panes="2"][one-fixed])) {
367
+ --mdw-layout__pane1-width: 360px;
368
+ }
369
+
370
+ :host(:where([panes="2"][two-fixed])) {
371
+ --mdw-layout__pane2-width: 360px;
372
+ }
373
+
374
+ #scrim {
375
+ position:fixed;
376
+ inset: 0;
377
+
378
+ pointer-events: none;
379
+
380
+ opacity: 0;
381
+ z-index: 25;
382
+
383
+ background-color: rgb(var(--mdw-color__scrim));
384
+
385
+ transition: opacity 200ms;
386
+ }
387
+
388
+ #scrim[state="open"] {
389
+ pointer-events: auto;
390
+
391
+ opacity: 0.38;
392
+ }
393
+
394
+ .pane {
395
+ overflow: visible;
396
+ }
397
+
398
+ .pane[columns="8"] {
399
+ /* stylelint-disable-next-line rule-selector-property-disallowed-list */
400
+ --mdw-grid__columns: 8;
401
+ }
402
+
403
+ .pane[columns="12"] {
404
+ /* stylelint-disable-next-line rule-selector-property-disallowed-list */
405
+ --mdw-grid__columns: 12;
406
+ }
407
+
408
+ .pane1 {
409
+ grid-area: pane1;
25
410
 
26
- justify-content: center;
411
+ box-sizing: content-box;
412
+ inline-size: 100%;
413
+ max-inline-size: var(--mdw-content__max-width, auto);
414
+ margin-inline: auto;
415
+ }
416
+
417
+ .pane1[slotted] {
418
+ display: block;
419
+ }
420
+
421
+ .pane2 {
422
+ --mdw-content__padding: 0;
423
+ grid-area: pane2;
424
+
425
+ visibility: hidden;
426
+ }
427
+
428
+ .pane2[active] {
429
+ inset-inline-end: 0;
430
+
431
+ box-sizing: border-box;
432
+ inline-size: 100%;
433
+ padding-inline: var(--mdw-content__padding);
434
+
435
+ visibility: visible;
436
+ }
437
+
438
+ .pane2[slotted] {
439
+ display: block;
440
+ }
441
+
442
+ .pane2[panes="2"] {
443
+ position: sticky;
444
+ inset: 0;
445
+
446
+ overflow-y: auto;
447
+
448
+ block-size: 100vh;
449
+
450
+ visibility: visible;
451
+ }
27
452
 
28
- padding-inline: 16px;
453
+ #slot-app-bar {
454
+ display: contents; /* Allow sticky */
29
455
 
30
- transition: padding-inline 100ms;
456
+ z-index: 2;
31
457
  }
32
458
 
33
- @media screen and (min-width: 648px) { #slot { padding-inline: 24px; } }
459
+ #slot-nav-bar {
460
+ display: contents;
461
+ grid-area: nav-bar;
462
+ }
463
+
464
+ #slot-nav-bar[state="closed"] {
465
+ display: none;
466
+ }
467
+
468
+ #slot-nav-rail {
469
+ display: none;
470
+ grid-area: nav-rail;
471
+
472
+ z-index: 3;
473
+ }
474
+
475
+ #slot-nav-rail[state="fixed"] {
476
+ display: block;
477
+ }
478
+
479
+ #slot-nav-drawer {
480
+ position: fixed;
481
+
482
+ display: block;
483
+ grid-area: nav-drawer;
484
+
485
+ /** Initially hidden */
486
+ transform: translateX(-100%);
487
+ visibility: hidden;
488
+ z-index: 26;
489
+
490
+ transition-delay: 0s, 200ms;
491
+ transition-duration: 200ms, 0s;
492
+ transition-property: transform, visibility;
493
+ transition-timing-function: cubic-bezier(0.3, 0, 0.8, 0.15);
494
+ }
495
+
496
+ #slot-nav-drawer:is([state="open"],[state="fixed"]) {
497
+ transform: translateX(0);
498
+ visibility: visible;
499
+
500
+ transition-delay: 0s, 0s;
501
+ transition-timing-function: cubic-bezier(0.05, 0.7, 0.1, 1);
502
+ }
34
503
  `
35
504
  .autoRegister('mdw-layout');
@@ -6,24 +6,26 @@ import Box from './Box.js';
6
6
  /** @typedef {'compact'} DeprecatedHTMLMenuElementProperties */
7
7
 
8
8
  export default Box
9
+ .extend()
9
10
  .mixin(DensityMixin)
10
11
  .mixin(AriaReflectorMixin)
11
- .extend()
12
12
  .set({
13
13
  _ariaRole: 'list',
14
+ color: { empty: 'surface' },
14
15
  })
15
16
  .css`
16
17
  /* https://m3.material.io/components/lists/specs */
17
18
 
18
19
  :host {
20
+ --mdw-bg: var(--mdw-color__surface);
21
+ --mdw-ink: var(--mdw-color__on-surface);
19
22
  display: flex;
20
23
  flex-direction: column;
21
24
 
22
25
  padding-block: 8px;
23
- }
24
26
 
25
- :host(:focus) {
26
- outline: 1px solid red;
27
+ background-color: rgb(var(--mdw-bg));
28
+ color: rgb(var(--mdw-ink));
27
29
  }
28
30
 
29
31
  `
@@ -12,11 +12,11 @@ import StateMixin from '../mixins/StateMixin.js';
12
12
  import ThemableMixin from '../mixins/ThemableMixin.js';
13
13
 
14
14
  export default CustomElement
15
+ .extend()
15
16
  .mixin(ThemableMixin)
16
17
  .mixin(StateMixin)
17
18
  .mixin(RippleMixin)
18
19
  .mixin(AriaReflectorMixin)
19
- .extend()
20
20
  .set({
21
21
  _ariaRole: 'listitem',
22
22
  delegatesFocus: false,
@@ -59,7 +59,7 @@ export default CustomElement
59
59
  return href != null;
60
60
  },
61
61
  hasSupporting() {
62
- return this.supporting || this._supportingSlotted;
62
+ return Boolean(this.supporting || this._supportingSlotted);
63
63
  },
64
64
  checkboxClass() {
65
65
  return this.checkbox || 'leading';
@@ -68,22 +68,22 @@ export default CustomElement
68
68
  return this.radio || 'leading';
69
69
  },
70
70
  })
71
- .html/* html */`
72
- <a id=anchor _if={href} href={href} disabled={disabledState} aria-labelledby=content></a>
73
- <mdw-checkbox-icon id=checkbox _if={checkbox} aria-hidden=true class={checkboxClass} color={selectionColor} disabled={disabledState} icon=check selected={selected}></mdw-checkbox-icon>
74
- <mdw-radio-icon id=radio _if={radio} aria-hidden=true class={radioClass} disabled={disabledState} ink={selectionColor} selected={selected}></mdw-radio-icon>
75
- <mdw-box _if={avatar} id=avatar color={avatarColor} type-style=title-medium src={AvatarSrc}
71
+ .html`
72
+ <a id=anchor mdw-if={href} href={href} disabled={disabledState} aria-labelledby=content></a>
73
+ <mdw-checkbox-icon id=checkbox mdw-if={checkbox} aria-hidden=true class={checkboxClass} color={selectionColor} disabled={disabledState} icon=check selected={selected}></mdw-checkbox-icon>
74
+ <mdw-radio-icon id=radio mdw-if={radio} aria-hidden=true class={radioClass} disabled={disabledState} ink={selectionColor} selected={selected}></mdw-radio-icon>
75
+ <mdw-box mdw-if={avatar} id=avatar color={avatarColor} type-style=title-medium src={AvatarSrc}
76
76
  aria-hidden=true>{avatar}</mdw-box>
77
- <mdw-icon _if={icon} id=icon ink={iconInk} src={iconSrc} aria-hidden=true>{icon}</mdw-icon>
78
- <img id=img _if={src} src={src} alt={alt} video={video} />
77
+ <mdw-icon mdw-if={icon} id=icon ink={iconInk} src={iconSrc} aria-hidden=true>{icon}</mdw-icon>
78
+ <img id=img mdw-if={src} src={src} alt={alt} video={video} />
79
79
  <slot name=leading>{leading}</slot>
80
80
  <div id=content has-supporting={hasSupporting} lines={lines}>
81
81
  <slot id=slot></slot>
82
82
  <slot id=supporting name=supporting class=text lines={lines}>{supporting}</slot>
83
83
  </div>
84
- <mdw-icon _if={trailingIcon} id=trailing-icon ink={trailingIconInk} src={trailingIconSrc} aria-hidden=true>{trailingIcon}</mdw-icon>
84
+ <mdw-icon mdw-if={trailingIcon} id=trailing-icon ink={trailingIconInk} src={trailingIconSrc} aria-hidden=true>{trailingIcon}</mdw-icon>
85
85
  <slot id=trailing name=trailing role=note>{trailing}</slot>
86
- <mdw-divider _if={divider} id=divider divder={divider}></mdw-divider>
86
+ <mdw-divider mdw-if={divider} id=divider divder={divider}></mdw-divider>
87
87
  `
88
88
  .on({
89
89
  composed() {
@@ -183,7 +183,7 @@ export default CustomElement
183
183
 
184
184
  display: block;
185
185
 
186
- color: rgb(var(--mdw-color__surface-variant));
186
+ color: rgb(var(--mdw-color__surface-container-highest));
187
187
  }
188
188
 
189
189
  #divider[divider="inset"] {
@@ -18,7 +18,7 @@ export default class ListOption extends ListItem
18
18
  })
19
19
  .observe({
20
20
  // ListOption.prototype._form = ListOption.prop('_form');
21
- _label: { attr: 'label', nullParser: String },
21
+ _label: { attr: 'label', reflect: true, nullParser: String },
22
22
  defaultSelected: { attr: 'selected', reflect: true, type: 'boolean' },
23
23
  _selected: 'boolean',
24
24
  _value: { attr: 'value', reflect: true },
@@ -45,16 +45,16 @@ export default class ListOption extends ListItem
45
45
  })
46
46
  .define({
47
47
  index() { return this._index; },
48
- form() { return /** @type {import('./ListSelect.js').default} */ (this.parentElement)?.form; },
48
+ form() { return (this.parentElement)?.form; },
49
49
  label: {
50
- get() { return this._label; },
50
+ get() { return this._label ?? this.textContent; },
51
51
  /** @param {string} value */
52
52
  set(value) {
53
53
  this._label = value;
54
54
  },
55
55
  },
56
56
  value: {
57
- get() { return this._value; },
57
+ get() { return this._value ?? this.textContent; },
58
58
  /** @param {string} value */
59
59
  set(value) { this._label = value; },
60
60
  },
@@ -76,6 +76,7 @@ export default class ListOption extends ListItem
76
76
  // Form Associated elements cannot receive focus unless using delegatesFocus
77
77
  // Workaround by redirecting focus to an inner element
78
78
  // Reuse HTMLAnchorElement with no HREF
79
+ // Issues: Siblings (images) are not contained within tree
79
80
 
80
81
  anchor.setAttribute('disabled', '{disabledState}');
81
82
  anchor.setAttribute('role', 'option');
@@ -84,12 +85,27 @@ export default class ListOption extends ListItem
84
85
  anchor.setAttribute('aria-selected', inline(({ selected }) => `${selected}`));
85
86
  anchor.setAttribute('selected', '{selected}');
86
87
  anchor.removeAttribute('href');
87
- anchor.removeAttribute('_if');
88
+ anchor.removeAttribute('mdw-if');
88
89
 
89
90
  content.setAttribute('selected', '{selected}');
90
91
 
91
92
  state.setAttribute('state-disabled', 'focus');
92
93
  },
94
+ _labelChanged(previous, current) {
95
+ const { anchor } = this.refs;
96
+ if (current == null) {
97
+ anchor.setAttribute('aria-labelledby', 'content');
98
+ anchor.removeAttribute('aria-label');
99
+ } else {
100
+ anchor.setAttribute('aria-label', current);
101
+ anchor.removeAttribute('aria-labelledby');
102
+ }
103
+ },
104
+ selectedChanged(previous, current) {
105
+ // Used by HTMLCollection
106
+ this.classList.toggle('mdw-list-option__selected', current);
107
+ this.dispatchEvent(new Event('mdw-list-option:changed', { bubbles: true, composed: true }));
108
+ },
93
109
  })
94
110
  .css`
95
111
  :host {