@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
@@ -3,9 +3,9 @@ import ShapeMixin from '../mixins/ShapeMixin.js';
3
3
  import ThemableMixin from '../mixins/ThemableMixin.js';
4
4
 
5
5
  export default CustomElement
6
+ .extend()
6
7
  .mixin(ThemableMixin)
7
8
  .mixin(ShapeMixin)
8
- .extend()
9
9
  .observe({
10
10
  selected: 'boolean',
11
11
  icon: 'string',
@@ -21,12 +21,12 @@ export default CustomElement
21
21
  set(value) { this.selected = value; },
22
22
  },
23
23
  })
24
- .html/* html */`
24
+ .html`
25
25
  <div id=inner-shape class=shape selected={selected}></div>
26
26
  `.on({
27
27
  composed() {
28
28
  const { outline } = this.refs;
29
- outline.removeAttribute('_if');
29
+ outline.removeAttribute('mdw-if');
30
30
  outline.setAttribute('selected', '{selected}');
31
31
  },
32
32
  })
@@ -34,8 +34,8 @@ export default CustomElement
34
34
  minBlockSize: `${_radius}px`,
35
35
  minInlineSize: `${_radius}px`,
36
36
  boxShadow: `0 0 calc(0.10 * ${_radius}px) calc(0.10 * ${_radius}px) currentColor`,
37
- left: `calc(50% + ${_positionX}px)`,
38
37
  top: `calc(50% + ${_positionY}px)`,
38
+ left: `calc(50% + ${_positionX}px)`,
39
39
  },
40
40
  };
41
41
  },
@@ -109,6 +109,7 @@ export default CustomElement
109
109
  },
110
110
  })
111
111
  .css`
112
+ /* stylelint-disable liberty/use-logical-spec */
112
113
  :host {
113
114
  --enter-delay: 80ms;
114
115
  --touch-down-acceleration: 1024;
@@ -121,9 +122,7 @@ export default CustomElement
121
122
 
122
123
  --size: 0;
123
124
  position: absolute;
124
- /* stylelint-disable-next-line liberty/use-logical-spec */
125
125
  top: 50%;
126
- /* stylelint-disable-next-line liberty/use-logical-spec */
127
126
  left: 50%;
128
127
 
129
128
  display: block;
@@ -0,0 +1,85 @@
1
+ import TopAppBar from './TopAppBar.js';
2
+
3
+ /* @implements {HTMLSelectElement} */
4
+ export default TopAppBar
5
+ .extend()
6
+ .undefine('headline')
7
+ // .undefine('_headlineOpacity')
8
+ .undefine('size')
9
+ .undefine('_headlineStyle')
10
+ .observe({
11
+ placeholder: { type: 'string', empty: 'Search' },
12
+ color: { empty: 'surface-container-high' },
13
+ shapeStyle: { empty: 'full' },
14
+ kbdNav: { empty: 'false' },
15
+ })
16
+ .define({
17
+ /** @return {HTMLInputElement} */
18
+ input() { return this.refs.input; },
19
+ value: {
20
+ get() { return this.refs.input.value; },
21
+ set(value) {
22
+ this.refs.input.value = value;
23
+ },
24
+ },
25
+ })
26
+ .html`
27
+ <mdw-input id=input placeholder={placeholder} aria-label={placeholder}></mdw-input>
28
+ `
29
+ .css`
30
+ :host {
31
+ --mdw-bg: var(--mdw-color__surface-container-high);
32
+ padding-block: 16px;
33
+ }
34
+
35
+ #surface {
36
+ background-color: transparent;
37
+ }
38
+
39
+ #leading:not([slotted]),
40
+ #trailing:not([slotted]) {
41
+ display: none;
42
+ }
43
+
44
+ #shape {
45
+ display: flex;
46
+ align-items: center;
47
+ gap: 16px;
48
+
49
+ padding-inline: 16px;
50
+
51
+ background-color: rgb(var(--mdw-bg));
52
+ }
53
+
54
+ #input {
55
+ --mdw-state__hovered-opacity: 0;
56
+ flex: 1;
57
+ }
58
+ `
59
+ .methods({
60
+ /** @param {{currentTarget:HTMLSlotElement}} event */
61
+ onSlotChange({ currentTarget }) {
62
+ currentTarget.toggleAttribute('slotted', currentTarget.assignedNodes().length >= 0);
63
+ },
64
+ })
65
+ .childEvents({
66
+ leading: { slotchange: 'onSlotChange' },
67
+ trailing: { slotchange: 'onSlotChange' },
68
+ input: {
69
+ change(event) {
70
+ // Change events are not composed. Rethrow.
71
+ event.stopPropagation();
72
+ this.dispatchEvent(new Event('change', { bubbles: true }));
73
+ },
74
+ },
75
+ })
76
+ .on({
77
+ composed() {
78
+ const { companion, headline, input, surface } = this.refs;
79
+ companion.remove();
80
+ headline.replaceWith(input);
81
+ surface.removeAttribute('aria-labelledby');
82
+ },
83
+ })
84
+
85
+ .autoRegister('mdw-search');
@@ -23,7 +23,7 @@ export default Button
23
23
  `);
24
24
  shape.setAttribute('selected', '{checked}');
25
25
 
26
- icon.removeAttribute('_if');
26
+ icon.removeAttribute('mdw-if');
27
27
  icon.setAttribute('has-icon', '{hasIcon}');
28
28
  icon.setAttribute('selected', '{checked}');
29
29
  outline.setAttribute('inner-segmented-button', '{innerSegmentedButton}');
@@ -74,10 +74,6 @@ export default Button
74
74
  background-color: rgb(var(--mdw-bg));
75
75
  }
76
76
 
77
- #label[selected] {
78
- color: rgb(var(--mdw-ink));
79
- }
80
-
81
77
  #icons {
82
78
  position: relative;
83
79
 
@@ -132,10 +128,5 @@ export default Button
132
128
  #shape[disabled][selected] {
133
129
  background-color: rgba(var(--mdw-color__on-surface), 0.12);
134
130
  }
135
-
136
- #label[disabled][selected] {
137
- color: rgba(var(--mdw-color__on-surface), 0.38);
138
- }
139
-
140
131
  `
141
132
  .autoRegister('mdw-segmented-button');
@@ -7,9 +7,9 @@ import SegmentedButton from './SegmentedButton.js';
7
7
  /** @typedef {'compact'} DeprecatedHTMLMenuElementProperties */
8
8
 
9
9
  export default Box
10
+ .extend()
10
11
  .mixin(KeyboardNav)
11
12
  .mixin(AriaReflectorMixin)
12
- .extend()
13
13
  .define({
14
14
  kbdNavQuery() {
15
15
  return SegmentedButton.elementName;
@@ -22,15 +22,12 @@ export default Box
22
22
  slot: {
23
23
  slotchange() {
24
24
  this.refreshTabIndexes();
25
- // eslint-disable-next-line github/array-foreach
26
- this.kbdNavChildren.forEach((child, index, list) => {
27
- /** @type {InstanceType<SegmentedButton>} */
28
- (child).shapeStart = index === 0;
29
- /** @type {InstanceType<SegmentedButton>} */
30
- (child).innerSegmentedButton = index > 0 && index < list.length - 1;
31
- /** @type {InstanceType<SegmentedButton>} */
32
- (child).shapeEnd = index === list.length - 1;
33
- });
25
+ const list = /** @type {NodeListOf<InstanceType<SegmentedButton>>} */ (this.kbdNavChildren);
26
+ for (const [index, child] of list.entries()) {
27
+ child.shapeStart = index === 0;
28
+ child.innerSegmentedButton = index > 0 && index < list.length - 1;
29
+ child.shapeEnd = index === list.length - 1;
30
+ }
34
31
  },
35
32
  },
36
33
  })
@@ -42,12 +39,21 @@ export default Box
42
39
  --mdw-ink: var(--mdw-color__on-secondary-container);
43
40
 
44
41
  display: inline-flex;
42
+ overflow-x: auto;
43
+ overflow-y: hidden;
45
44
  }
46
45
 
47
46
  :host([color]) {
48
47
  background-color: transparent;
49
48
  }
50
49
 
50
+ #slot {
51
+ display: grid;
52
+ grid-auto-flow: column;
53
+
54
+ flex: none;
55
+ }
56
+
51
57
  `
52
58
  .on({
53
59
  constructed() {
@@ -6,11 +6,11 @@ import ThemableMixin from '../mixins/ThemableMixin.js';
6
6
 
7
7
  /* @implements {HTMLSelectElement} */
8
8
  export default CustomElement
9
+ .extend()
9
10
  .mixin(ThemableMixin)
10
11
  .mixin(StateMixin)
11
12
  .mixin(ControlMixin)
12
13
  .mixin(TextFieldMixin)
13
- .extend()
14
14
  .observe({
15
15
  trailingIcon: { empty: 'arrow_drop_down' },
16
16
  })
@@ -27,7 +27,7 @@ export default CustomElement
27
27
  multiple: { value: false },
28
28
  size: { value: 1 },
29
29
  })
30
- .html/* html */`<slot id=slot></slot>`
30
+ .html`<slot id=slot></slot>`
31
31
  .childEvents({
32
32
  slot: {
33
33
  /** @param {Event & {currentTarget:HTMLSlotElement}} event */
@@ -59,13 +59,13 @@ export default CustomElement
59
59
  display: none;
60
60
  }
61
61
 
62
- #label {
62
+ #shape {
63
63
  padding: 0;
64
64
 
65
65
  cursor: pointer;
66
66
  }
67
67
 
68
- #label[disabled] {
68
+ #shape[disabled] {
69
69
  cursor: not-allowed;
70
70
  }
71
71
 
@@ -3,8 +3,8 @@ import ShapeMixin from '../mixins/ShapeMixin.js';
3
3
  import Box from './Box.js';
4
4
 
5
5
  export default Box
6
- .mixin(ShapeMixin)
7
6
  .extend()
7
+ .mixin(ShapeMixin)
8
8
  .on({
9
9
  composed() {
10
10
  const { shape, outline } = this.refs;
@@ -1,4 +1,5 @@
1
1
  import CustomElement from '../core/CustomElement.js';
2
+ import { isRtl } from '../core/dom.js';
2
3
  import InputMixin from '../mixins/InputMixin.js';
3
4
  import StateMixin from '../mixins/StateMixin.js';
4
5
  import ThemableMixin from '../mixins/ThemableMixin.js';
@@ -29,10 +30,10 @@ function valueAsFraction(value, min, max) {
29
30
  }
30
31
 
31
32
  export default CustomElement
33
+ .extend()
32
34
  .mixin(ThemableMixin)
33
35
  .mixin(StateMixin)
34
36
  .mixin(InputMixin)
35
- .extend()
36
37
  .set({
37
38
  stateLayer: true,
38
39
  type: 'range',
@@ -43,6 +44,7 @@ export default CustomElement
43
44
  _previewValue: { nullable: false },
44
45
  _roundedValue: 'float',
45
46
  _isHoveringThumb: 'boolean',
47
+ _lastDispatchedChangeValue: 'string',
46
48
  })
47
49
  .methods({
48
50
  /**
@@ -103,6 +105,9 @@ export default CustomElement
103
105
  const nMax = parseFloat(max, 100);
104
106
  const nStep = parseFloat(step, 1);
105
107
 
108
+ if (isRtl(this)) {
109
+ position = 1 - position;
110
+ }
106
111
  const currentValue = position * (nMax - nMin) + nMin;
107
112
  let roundedValue = Math.round(currentValue / nStep) * nStep;
108
113
 
@@ -121,7 +126,10 @@ export default CustomElement
121
126
 
122
127
  if (isTouch) return;
123
128
 
124
- const fractionalValue = valueAsFraction(this.value, this.min, this.max);
129
+ let fractionalValue = valueAsFraction(this.value, this.min, this.max);
130
+ if (isRtl(this)) {
131
+ fractionalValue = 1 - fractionalValue;
132
+ }
125
133
  const thumbOffset = fractionalValue * clientWidth;
126
134
  const thumbMin = thumbOffset - 20;
127
135
  const thumbMax = thumbOffset + 20;
@@ -143,8 +151,9 @@ export default CustomElement
143
151
  if (input.disabled) return;
144
152
  event.preventDefault();
145
153
  input.valueAsNumber = this._roundedValue;
146
- if (this._value !== input.value) {
147
- this._value = input.value;
154
+ this._value = input.value;
155
+ if (this._lastDispatchedChangeValue !== this._value) {
156
+ this._lastDispatchedChangeValue = this._value;
148
157
  input.dispatchEvent(new Event('change', { bubbles: true }));
149
158
  }
150
159
  },
@@ -175,25 +184,27 @@ export default CustomElement
175
184
  `--value:${valueAsFraction(_previewValue, min, max)}`,
176
185
  ].filter(Boolean).join(';') || null;
177
186
  },
187
+ _thumbLabelHidden({ _isHoveringThumb, focusedState }) {
188
+ return (!_isHoveringThumb && !focusedState);
189
+ },
178
190
  })
191
+ .html`
192
+ <div id=track style={computeTrackStyle} aria-hidden=true disabled={disabledState}>
193
+ <div mdw-if={ticks} id=ticks></div>
194
+ <div id=track-active></div>
195
+ <div id=thumb-anchor>
196
+ <div id=thumb></div>
197
+ <div id=thumb-label
198
+ hidden={_thumbLabelHidden}
199
+ text={_previewValue}></div>
200
+ </div>
201
+ </div>
202
+ `
179
203
  .on({
180
- composed({ template, html }) {
181
- const { state, label, control } = this.refs;
182
- template.append(html`
183
- <div id=track style={computeTrackStyle} aria-hidden=true disabled={disabledState}>
184
- <div _if={ticks} id=ticks></div>
185
- <div id=track-active></div>
186
- <div id=thumb-anchor>
187
- <div id=thumb>
188
- ${state}
189
- </div>
190
- <div id=thumb-label
191
- hidden=${({ _isHoveringThumb, focusedState }) => (!_isHoveringThumb && !focusedState)}
192
- text={_previewValue}></div>
193
- </div>
194
- </div>
195
- `);
196
- label.removeAttribute('aria-labelledby');
204
+ composed() {
205
+ const { thumb, state, control } = this.refs;
206
+ thumb.append(state);
207
+ control.removeAttribute('aria-labelledby');
197
208
  },
198
209
  valueChanged(oldValue, newValue) {
199
210
  this._previewValue = newValue;
@@ -220,20 +231,6 @@ export default CustomElement
220
231
  background-color: transparent;
221
232
  }
222
233
 
223
- #label {
224
- position: absolute;
225
- inset: 0;
226
-
227
- display: block;
228
-
229
- cursor: pointer;
230
-
231
- z-index: 1;
232
-
233
- /* border-radius: 50%; */
234
- color: rgb(var(--mdw-bg));
235
- }
236
-
237
234
  #control {
238
235
  inset:0;
239
236
 
@@ -246,12 +243,11 @@ export default CustomElement
246
243
 
247
244
  appearance: none;
248
245
 
249
- cursor: inherit;
246
+ cursor: pointer;
250
247
 
251
248
  transform: none;
252
249
 
253
250
  background-color: transparent;
254
- color: inherit;
255
251
  }
256
252
 
257
253
  #control::-webkit-slider-runnable-track {
@@ -323,7 +319,7 @@ export default CustomElement
323
319
  pointer-events: none;
324
320
  user-select: none;
325
321
 
326
- background-color: rgb(var(--mdw-color__surface-variant));
322
+ background-color: rgb(var(--mdw-color__surface-container-highest));
327
323
  border-radius: inherit;
328
324
  }
329
325
 
@@ -411,7 +407,7 @@ export default CustomElement
411
407
  inset: 0;
412
408
 
413
409
  transform: scaleX(var(--value));
414
- transform-origin: 0 0;
410
+ transform-origin: calc(100% * calc(-0.5 * var(--mdw-dir, 1) + 0.5)) 0;
415
411
 
416
412
  background-color: rgb(var(--mdw-bg));
417
413
 
@@ -420,23 +416,23 @@ export default CustomElement
420
416
 
421
417
  #thumb-anchor {
422
418
  position: absolute;
423
- inset-inline: 0;
419
+
420
+ inset-inline-start: calc(var(--value) * 100%);
424
421
 
425
422
  display: flex;
426
423
  align-items: flex-start;
427
424
  flex-direction: column;
428
425
 
429
- inline-size: 1%;
430
-
431
- transform: translateX(calc(var(--value) * 100 * 100%));
432
- transform-origin: 0 0;
433
426
  z-index: 24;
434
427
 
435
- will-change: transform;
428
+ /* stylelint-disable-next-line liberty/use-logical-spec */
429
+ will-change: inset-inline-start, left, right;
436
430
  }
437
431
 
438
432
  #thumb-label {
439
433
  position: absolute;
434
+ /* stylelint-disable-next-line liberty/use-logical-spec */
435
+ left: 0;
440
436
  inset-block-end: 14px;
441
437
 
442
438
  display: flex;
@@ -496,16 +492,13 @@ export default CustomElement
496
492
  background-color: rgb(var(--mdw-bg));
497
493
  }
498
494
 
499
- #track[disabled] {
500
- background-color: rgb(var(--mdw-color__on-surface), calc(0.12 / 0.38));
501
- }
502
-
503
- #label[disabled],
504
495
  #track[disabled] {
505
496
  --mdw-bg: var(--mdw-color__on-surface);
506
497
  cursor: not-allowed;
507
498
 
508
499
  opacity: 0.38;
500
+
501
+ background-color: rgb(var(--mdw-color__on-surface), calc(0.12 / 0.38));
509
502
  }
510
503
  `
511
504
  .autoRegister('mdw-slider');
@@ -10,9 +10,9 @@ import './IconButton.js';
10
10
  import Surface from './Surface.js';
11
11
 
12
12
  export default Surface
13
+ .extend()
13
14
  .mixin(DensityMixin)
14
15
  .mixin(AriaReflectorMixin)
15
- .extend()
16
16
  .set({
17
17
  _ariaRole: 'status',
18
18
  elevated: true,
@@ -46,10 +46,10 @@ export default Surface
46
46
  this.textContent = text;
47
47
  },
48
48
  })
49
- .html/* html */`
49
+ .html`
50
50
  <div id=content></div>
51
- <mdw-button _if={action} id=action class=button ink={actionInk} type-style={actionTypeStyle}>{action}</mdw-button>
52
- <mdw-icon-button _if={closeButton} id=close class=button icon={closeIcon} ink={closeInk}>Close</mdw-button>
51
+ <mdw-button mdw-if={action} id=action class=button ink={actionInk} type-style={actionTypeStyle}>{action}</mdw-button>
52
+ <mdw-icon-button mdw-if={closeButton} id=close class=button icon={closeIcon} ink={closeInk}>Close</mdw-button>
53
53
  `
54
54
  .on({
55
55
  composed() {
@@ -76,7 +76,6 @@ export default Surface
76
76
  :host {
77
77
  --mdw-shape__size: var(--mdw-shape__small);
78
78
  --mdw-surface__shadow: var(--mdw-surface__shadow__3);
79
- --mdw-surface__tint: var(--mdw-surface__tint__3);
80
79
  --mdw-shape__bg: rgb(var(--mdw-color__inverse-surface));
81
80
  --mdw-ink: var(--mdw-color__inverse-on-surface);
82
81
 
@@ -5,15 +5,15 @@ import SurfaceMixin from '../mixins/SurfaceMixin.js';
5
5
  import ThemableMixin from '../mixins/ThemableMixin.js';
6
6
 
7
7
  export default CustomElement
8
+ .extend()
8
9
  .mixin(ThemableMixin)
9
10
  .mixin(FlexableMixin)
10
11
  .mixin(SurfaceMixin)
11
12
  .mixin(ShapeMixin)
12
- .html/* html */`<slot id=slot></slot>`
13
+ .html`<slot id=slot></slot>`
13
14
  .on({
14
15
  composed() {
15
- const { surface, shape, surfaceTint } = this.refs;
16
- shape.append(surfaceTint);
16
+ const { surface, shape } = this.refs;
17
17
  surface.append(shape);
18
18
  },
19
19
  })
@@ -6,12 +6,12 @@ import ThemableMixin from '../mixins/ThemableMixin.js';
6
6
  import TouchTargetMixin from '../mixins/TouchTargetMixin.js';
7
7
 
8
8
  export default CustomElement
9
+ .extend()
9
10
  .mixin(ThemableMixin)
10
11
  .mixin(InputMixin) // Label as root
11
12
  .mixin(StateMixin)
12
13
  .mixin(TouchTargetMixin)
13
14
  // Switches have their own pressed animation (No ripple)
14
- .extend()
15
15
  .set({
16
16
  type: 'checkbox',
17
17
  stateLayer: true,
@@ -24,25 +24,34 @@ export default CustomElement
24
24
  selectedSrc: 'string',
25
25
  unselectedSrc: 'string',
26
26
  })
27
+ .html`
28
+ <mdw-switch-icon id=switch
29
+ color={color} ink={ink} selected={checked} hovered={hoveredState}
30
+ focused={focusedState} pressed={pressedState} disabled={disabledState}
31
+ icon={icon}
32
+ selected-icon={selectedIcon}
33
+ unselected-icon={unselectedIcon}
34
+ src={src}
35
+ selected-src={selectedSrc}
36
+ unselected-src={unselectedSrc}
37
+ >
38
+ </mdw-switch-icon>
39
+ <slot id=slot></slot>
40
+ `
41
+ .rootEvents({
42
+ click(event) {
43
+ const { control } = this.refs;
44
+ if (event.target !== control) {
45
+ // Label-like click
46
+ event.stopPropagation();
47
+ control.click();
48
+ }
49
+ },
50
+ })
27
51
  .on({
28
- composed({ html }) {
29
- const { state, label, control, touchTarget } = this.refs;
30
- label.append(html`
31
- ${touchTarget}
32
- <mdw-switch-icon id=switch
33
- color={color} ink={ink} selected={checked} hovered={hoveredState} focused={focusedState} pressed={pressedState} disabled={disabledState}
34
- icon={icon}
35
- selected-icon={selectedIcon}
36
- unselected-icon={unselectedIcon}
37
- src={src}
38
- selected-src={selectedSrc}
39
- unselected-src={unselectedSrc}
40
- >
41
- ${state}
42
- ${control}
43
- </mdw-switch-icon>
44
- <slot id=slot></slot>
45
- `);
52
+ composed() {
53
+ const { switch: switchEl, state, control } = this.refs;
54
+ switchEl.append(state, control);
46
55
  control.setAttribute('role', 'switch');
47
56
  },
48
57
  })
@@ -133,6 +142,11 @@ export default CustomElement
133
142
  gap: 12px;
134
143
  vertical-align: middle;
135
144
 
145
+ cursor: pointer;
146
+ }
147
+
148
+ #control {
149
+ cursor: inherit;
136
150
  }
137
151
 
138
152
  #touch-target {
@@ -161,7 +175,10 @@ export default CustomElement
161
175
 
162
176
  #state {
163
177
  position: absolute;
164
- inset: 50%;
178
+ /* stylelint-disable-next-line liberty/use-logical-spec */
179
+ top: 50%;
180
+ /* stylelint-disable-next-line liberty/use-logical-spec */
181
+ left: 50%;
165
182
 
166
183
  block-size: 100%;
167
184
  min-block-size: 40px;
@@ -175,9 +192,15 @@ export default CustomElement
175
192
  border-radius: 50%;
176
193
  }
177
194
 
195
+ #state[touched] {
196
+ /* Pressed state already has an animation */
197
+ /* stylelint-disable-next-line rule-selector-property-disallowed-list */
198
+ --mdw-state__pressed-opacity: 0;
199
+ }
200
+
178
201
  /** Disabled **/
179
202
 
180
- #label[disabled] {
203
+ :host(:disabled) {
181
204
  --mdw-ink: var(--mdw-color__on-surface); /* selected icon */
182
205
  --mdw-bg: var(--mdw-color__surface);
183
206
  cursor: not-allowed;
@@ -185,5 +208,16 @@ export default CustomElement
185
208
  opacity: 0.38;
186
209
  }
187
210
 
211
+ :host([internals-disabled]) {
212
+ --mdw-ink: var(--mdw-color__on-surface); /* selected icon */
213
+ --mdw-bg: var(--mdw-color__surface);
214
+ cursor: not-allowed;
215
+
216
+ opacity: 0.38;
217
+ }
218
+
219
+ #switch[disabled] {
220
+ opacity: 1;
221
+ }
188
222
  `
189
223
  .autoRegister('mdw-switch');