@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
@@ -8,7 +8,6 @@ let rtlObserver;
8
8
  */
9
9
  export default function RTLObserverMixin(Base) {
10
10
  return Base
11
- .extend()
12
11
  .observe({
13
12
  pageIsRTL: {
14
13
  type: 'boolean',
@@ -10,7 +10,6 @@ const resizeObserver = new ResizeObserver((entries) => {
10
10
  */
11
11
  export default function ResizeObserverMixin(Base) {
12
12
  return Base
13
- .extend()
14
13
  .set({
15
14
  observeResizeOnConnected: true,
16
15
  })
@@ -7,7 +7,6 @@ import Ripple from '../components/Ripple.js';
7
7
  */
8
8
  export default function RippleMixin(Base) {
9
9
  return Base
10
- .extend()
11
10
  .set({
12
11
  /** @type {WeakRef<InstanceType<Ripple>>} */
13
12
  _lastRippleWeakRef: null,
@@ -42,7 +41,7 @@ export default function RippleMixin(Base) {
42
41
  // Reset before next event loop;
43
42
  this._rippleAdded = false;
44
43
  });
45
- rippleContainer.appendChild(ripple);
44
+ rippleContainer.append(ripple);
46
45
  if (hold) {
47
46
  ripple.holdRipple = true;
48
47
  }
@@ -51,8 +50,8 @@ export default function RippleMixin(Base) {
51
50
  return ripple;
52
51
  },
53
52
  })
54
- .html/* html */`
55
- <div id=ripple-container _if={!disabledState} aria-hidden=true></div>
53
+ .html`
54
+ <div id=ripple-container mdw-if={!disabledState} aria-hidden=true></div>
56
55
  `
57
56
  .events({
58
57
  '~pointerdown'(event) {
@@ -5,10 +5,12 @@ const IDLE_TIMEOUT_MS = 500;
5
5
  */
6
6
  export default function ScrollListenerMixin(Base) {
7
7
  return Base
8
- .extend()
9
8
  .observe({
10
- scrollListenerPositionX: { type: 'float', empty: 0, reflect: false },
11
- scrollListenerPositionY: { type: 'float', empty: 0, reflect: false },
9
+ _scrollListenerPositionX: { type: 'float', empty: 0, reflect: false },
10
+ _scrollListenerPositionY: { type: 'float', empty: 0, reflect: false },
11
+ _scrollListenerLastIdle: { type: 'float', empty: 0 },
12
+ _scrollListenerLastScroll: { type: 'float', empty: 0 },
13
+ _scrollListenerLastResize: { type: 'float', empty: 0 },
12
14
  })
13
15
  .set({
14
16
  /** @type {WeakRef<EventTarget>} */
@@ -20,25 +22,29 @@ export default function ScrollListenerMixin(Base) {
20
22
  _scrollDebounce: null,
21
23
  })
22
24
  .methods({
23
- // eslint-disable-next-line @typescript-eslint/no-empty-function
24
- onScrollIdle() {},
25
+ _scrollListenerOnScrollIdle() {
26
+ this._scrollListenerLastIdle = performance.now();
27
+ },
25
28
 
26
29
  /** @param {Event} event */
27
- onScrollerScroll(event) {
28
- this.scrollListenerPositionY = (event.currentTarget === window)
30
+ _scrollListenerOnScrollerScroll(event) {
31
+ this._scrollListenerPositionY = (event.currentTarget === window)
29
32
  ? window.scrollY
30
33
  : /** @type {HTMLElement} */ (event.currentTarget).scrollTop;
31
34
 
32
- this.scrollListenerPositionX = (event.currentTarget === window)
35
+ this._scrollListenerPositionX = (event.currentTarget === window)
33
36
  ? window.scrollX
34
37
  : /** @type {HTMLElement} */ (event.currentTarget).scrollLeft;
35
38
 
39
+ this._scrollListenerLastScroll = performance.now();
36
40
  clearTimeout(this._scrollDebounce);
37
- this._scrollDebounce = setTimeout(() => this.onScrollIdle(), IDLE_TIMEOUT_MS);
41
+ this._scrollDebounce = setTimeout(() => this._scrollListenerOnScrollIdle(), IDLE_TIMEOUT_MS);
38
42
  },
39
43
 
40
44
  /** @param {Event} event */
41
- onScrollerResize(event) {},
45
+ _scrollListenerOnScrollerResize(event) {
46
+ this._scrollListenerLastResize = performance.now();
47
+ },
42
48
 
43
49
  /**
44
50
  * @param {EventTarget} [scroller]
@@ -54,42 +60,45 @@ export default function ScrollListenerMixin(Base) {
54
60
  }
55
61
 
56
62
  this._scroller = new WeakRef(scroller);
57
- this._scrollerScrollListener = this.onScrollerScroll.bind(this);
58
- this._scrollerResizeListener = this.onScrollerResize.bind(this);
59
- scroller.addEventListener('scroll', this._scrollerScrollListener);
60
- scroller.addEventListener('resize', this._scrollerResizeListener);
61
- this.scrollListenerPositionX = 0;
62
- this.scrollListenerPositionY = 0;
63
+ this._scrollerScrollListener = this._scrollListenerOnScrollerScroll.bind(this);
64
+ this._scrollerResizeListener = this._scrollListenerOnScrollerResize.bind(this);
65
+ scroller.addEventListener('scroll', this._scrollerScrollListener, { passive: true });
66
+ scroller.addEventListener('resize', this._scrollerResizeListener, { passive: true });
67
+ this._scrollListenerPositionX = 0;
68
+ this._scrollListenerPositionY = 0;
63
69
  return true;
64
70
  },
71
+ })
72
+ .define({
73
+ /** @return {Window|HTMLElement} */
74
+ _scrollListenerScroller() {
75
+ return this._scroller.deref();
76
+ },
77
+ })
78
+ .define({
65
79
 
66
- getScrollingElementScrollHeight() {
67
- const element = this.getScroller();
68
- if (element === window) {
80
+ _scrollListenerScrollerScrollHeight() {
81
+ const scroller = this._scrollListenerScroller;
82
+ if (scroller === window) {
69
83
  return document.documentElement.scrollHeight;
70
84
  }
71
- // @ts-expect-error Skip Element cast
72
- return element.scrollHeight;
85
+ return scroller.scrollHeight;
73
86
  },
74
-
75
- getScrollingElementClientHeight() {
76
- const element = this.getScroller();
77
- if (element === window) {
87
+ _scrollListenerScrollerClientHeight() {
88
+ const scroller = this._scrollListenerScroller;
89
+ if (scroller === window) {
78
90
  return window.innerHeight;
79
91
  }
80
92
  // @ts-expect-error Skip Element cast
81
- return element.clientHeight;
82
- },
83
-
84
- getScroller() {
85
- return this._scroller.deref();
93
+ return scroller.clientHeight;
86
94
  },
87
-
95
+ })
96
+ .methods({
88
97
  /**
89
98
  * @param {EventTarget} [scroller]
90
99
  * @return {boolean}
91
100
  */
92
- clearScrollListener(scroller) {
101
+ _scrollListenerClear(scroller) {
93
102
  scroller ??= this._scroller?.deref();
94
103
  if (!scroller) return false;
95
104
  if (!this._scrollerScrollListener) return false;
@@ -0,0 +1,151 @@
1
+ import { ELEMENT_STYLER_TYPE } from '../core/customTypes.js';
2
+
3
+ import ScrollListenerMixin from './ScrollListenerMixin.js';
4
+
5
+ /**
6
+ * Hides sticky element when scrolling down
7
+ * @param {typeof import('../core/CustomElement.js').default} Base
8
+ */
9
+ export default function SemiStickyMixin(Base) {
10
+ return Base
11
+ .mixin(ScrollListenerMixin)
12
+ .observe({
13
+ _semiStickyHeight: { type: 'float', empty: 0 },
14
+ _semiStickyOffsetY: { type: 'float', empty: 0 },
15
+ _semiStickyWidth: { type: 'float', empty: 0 },
16
+ _semiStickyOffsetX: { type: 'float', empty: 0 },
17
+ _semiStickyTranslateY: { type: 'float', empty: 0 },
18
+ _semiStickyTranslateX: { type: 'float', empty: 0 },
19
+ _semiStickyDuration: { type: 'float', empty: 0 },
20
+ _semiStickyEasing: { empty: 'ease-in' },
21
+ _semiStickyAnchor: {
22
+ /** @type {'top'|'start'|'end'|'bottom'|'left'|'right'} */
23
+ empty: 'top',
24
+ },
25
+ stickyAlways: 'boolean',
26
+ })
27
+ .methods({
28
+ /** @return {HTMLElement} */
29
+ _getSemiStickyElement() { return this; },
30
+ _refreshSemiStickyMetrics() {
31
+ const semiStickyElement = this._getSemiStickyElement();
32
+ this._semiStickyHeight = semiStickyElement.offsetHeight;
33
+ this._semiStickyWidth = semiStickyElement.offsetWidth;
34
+ // No way to measure offset when stickied ?
35
+ semiStickyElement.style.position = 'relative';
36
+ this._semiStickyOffsetY = semiStickyElement.offsetTop;
37
+ this._semiStickyOffsetX = semiStickyElement.offsetLeft;
38
+ semiStickyElement.style.position = 'sticky';
39
+ },
40
+ })
41
+ .observe({
42
+ _semiStickyStyleStyle: {
43
+ ...ELEMENT_STYLER_TYPE,
44
+ get({ _semiStickyTranslateX, _semiStickyTranslateY, _semiStickyDuration, _semiStickyEasing }) {
45
+ return {
46
+ target: this._getSemiStickyElement(),
47
+ styles: {
48
+ transform: `translateX(${_semiStickyTranslateX}px) translateY(${_semiStickyTranslateY}px)`,
49
+ },
50
+ timing: {
51
+ duration: _semiStickyDuration,
52
+ easing: _semiStickyEasing,
53
+ },
54
+ };
55
+ },
56
+ },
57
+ })
58
+ .on({
59
+ _scrollListenerLastResizeChanged() {
60
+ if (this._semiStickyAnchor !== 'bottom') return;
61
+ // Chrome Bug: When window resizes bottom sticky needs to be recomputed
62
+ // Force style recalculation
63
+ const semiStickyElement = this._getSemiStickyElement();
64
+ semiStickyElement.style.setProperty('bottom', 'auto');
65
+ // eslint-disable-next-line no-unused-expressions
66
+ semiStickyElement.clientHeight;
67
+ semiStickyElement.style.removeProperty('bottom');
68
+ this.propChangedCallback('_scrollListenerPositionY', this._scrollListenerPositionY, this._scrollListenerPositionY);
69
+ },
70
+ _scrollListenerPositionYChanged(oldValue, newValue) {
71
+ const delta = newValue - oldValue;
72
+ if (this._semiStickyAnchor === 'top') {
73
+ this._semiStickyDuration = 0;
74
+ this._semiStickyTranslateY = (this.stickyAlways || newValue < this._semiStickyOffsetY)
75
+ ? 0
76
+ : Math.min(0, Math.max(this._semiStickyTranslateY - delta, -this._semiStickyHeight));
77
+ } else if (this._semiStickyAnchor === 'bottom') {
78
+ this._semiStickyDuration = 0;
79
+ const anchor = this._scrollListenerScrollerClientHeight + newValue;
80
+ const distanceFromAnchor = this._semiStickyOffsetY - anchor;
81
+ this._semiStickyTranslateY = this.stickyAlways
82
+ ? 0
83
+ : Math.max(0, Math.min(
84
+ this._semiStickyTranslateY + delta,
85
+ this._semiStickyHeight + Math.min(0, distanceFromAnchor),
86
+ ));
87
+ }
88
+ },
89
+ _scrollListenerLastIdleChanged() {
90
+ if (this.stickyAlways) return;
91
+ this._refreshSemiStickyMetrics();
92
+ if (this._semiStickyAnchor === 'top') {
93
+ const { offsetTop } = this.refs.surface;
94
+ const offset = this._scrollListenerPositionY - offsetTop;
95
+ const delta = offset - this._semiStickyTranslateY;
96
+ const visibility = delta / this._semiStickyHeight;
97
+
98
+ if (visibility <= 0) return;
99
+ if (visibility >= 1) return;
100
+ if (visibility <= 0.5 || offsetTop < this._semiStickyHeight) {
101
+ // Reveal all
102
+ this._semiStickyDuration = 250;
103
+ this._semiStickyEasing = 'ease-in';
104
+ this._semiStickyTranslateY = 0;
105
+ // this._semiStickyHeadlineOpacity = 1;
106
+ } else {
107
+ this._semiStickyDuration = 200;
108
+ this._semiStickyEasing = 'ease-out';
109
+ // Don't hide past origin
110
+ this._semiStickyTranslateY = Math.max(
111
+ this._semiStickyOffsetY - this._scrollListenerPositionY,
112
+ -this._semiStickyHeight,
113
+ );
114
+ }
115
+ } else if (this._semiStickyAnchor === 'bottom') {
116
+ const max = this._semiStickyHeight;
117
+ const visibility = (max - this._semiStickyTranslateY) / max;
118
+ if (visibility <= 0) return;
119
+ if (visibility >= 1) return;
120
+ if (visibility >= 0.5) {
121
+ // Reveal all
122
+ this._semiStickyDuration = 250;
123
+ this._semiStickyEasing = 'ease-in';
124
+ this._semiStickyTranslateY = 0;
125
+ // this._semiStickyHeadlineOpacity = 1;
126
+ } else {
127
+ this._semiStickyDuration = 200;
128
+ this._semiStickyEasing = 'ease-out';
129
+ const anchor = this._scrollListenerScrollerClientHeight + this._scrollListenerPositionY;
130
+ const distanceFromAnchor = this._semiStickyOffsetY - anchor;
131
+ // Don't hide past origin
132
+ this._semiStickyTranslateY = this._semiStickyHeight + Math.min(0, distanceFromAnchor);
133
+ }
134
+ }
135
+ },
136
+ connected() {
137
+ const semiStickyElement = this._getSemiStickyElement();
138
+ // Connect scroll when element gets first size
139
+ const resizeObserver = new ResizeObserver(() => {
140
+ this.startScrollListener(semiStickyElement.offsetParent ?? window);
141
+ resizeObserver.disconnect();
142
+ this._refreshSemiStickyMetrics();
143
+ });
144
+ resizeObserver.observe(semiStickyElement);
145
+ this._refreshSemiStickyMetrics();
146
+ },
147
+ disconnected() {
148
+ this._scrollListenerClear();
149
+ },
150
+ });
151
+ }
@@ -3,7 +3,6 @@
3
3
  */
4
4
  export default function ShapeMixin(Base) {
5
5
  return Base
6
- .extend()
7
6
  .observe({
8
7
  shapeTop: 'boolean',
9
8
  shapeBottom: 'boolean',
@@ -12,9 +11,11 @@ export default function ShapeMixin(Base) {
12
11
  shapeStyle: 'string',
13
12
  outlined: 'boolean',
14
13
  })
15
- .html/* html */`
16
- <div id=shape part=shape class=shape elevated={elevated} shape-top={shapeTop} shape-bottom={shapeBottom} shape-start={shapeStart} shape-end={shapeEnd} shape-style={shapeStyle} color={color} outlined={outlined} disabled={disabledState}>
17
- <div id=outline _if={outlined} class=outline disabled={disabledState} focused={focusedState} pressed={pressedState} hovered={hoveredState}>
14
+ .html`
15
+ <div id=shape part=shape class=shape elevated={elevated}
16
+ shape-top={shapeTop} shape-bottom={shapeBottom} shape-start={shapeStart} shape-end={shapeEnd} shape-style={shapeStyle}
17
+ color={color} outlined={outlined} disabled={disabledState}>
18
+ <div id=outline mdw-if={outlined} class=outline disabled={disabledState} focused={focusedState} pressed={pressedState} hovered={hoveredState}>
18
19
  <div id=outline-left class="outline-section outline-left"></div>
19
20
  <div id=outline-right class="outline-section outline-right"></div>
20
21
  </div>
@@ -25,77 +26,81 @@ export default function ShapeMixin(Base) {
25
26
  --mdw-shape__size: 0px;
26
27
  --mdw-shape__bg: transparent;
27
28
  --mdw-surface__will-change: none;
29
+ --mdw-shape__ltr: calc(0.5 * var(--mdw-dir, 1) + 0.5); /* 1 if LTR, 0 if RTL */
30
+ --mdw-shape__rtl: calc(-0.5 * var(--mdw-dir, 1) + 0.5); /* 0 if LTR, 1 if RTL */
31
+
32
+ /** By default, fallback to border-radius */
33
+ --mdw-shape__rounded: 1;
34
+ --mdw-shape__inline-start-deg: calc(var(--mdw-dir, 1) * -90deg);
35
+ z-index: 0;
36
+ }
37
+
38
+ .shape {
28
39
  --mdw-shape__size__top-start-size: var(--mdw-shape__size);
29
40
  --mdw-shape__size__top-end-size: var(--mdw-shape__size);
30
41
  --mdw-shape__size__bottom-start-size: var(--mdw-shape__size);
31
42
  --mdw-shape__size__bottom-end-size: var(--mdw-shape__size);
32
43
 
33
44
  /* (1/2n + 1/2)L + (-1/2n + 1/2)R */
34
- --mdw-shape__ltr: calc(0.5 * var(--mdw-dir, 1) + 0.5); /* 1 if LTR, 0 if RTL */
35
- --mdw-shape__rtl: calc(-0.5 * var(--mdw-dir, 1) + 0.5); /* 0 if LTR, 1 if RTL */
45
+
36
46
  --mdw-shape__size__top-left-size: calc((var(--mdw-shape__ltr) * var(--mdw-shape__size__top-start-size)) + (var(--mdw-shape__rtl) * var(--mdw-shape__size__top-end-size)));
37
47
  --mdw-shape__size__top-right-size: calc((var(--mdw-shape__rtl) * var(--mdw-shape__size__top-start-size)) + (var(--mdw-shape__ltr) * var(--mdw-shape__size__top-end-size)));
38
48
  --mdw-shape__size__bottom-left-size: calc((var(--mdw-shape__ltr) * var(--mdw-shape__size__bottom-start-size)) + (var(--mdw-shape__rtl) * var(--mdw-shape__size__bottom-end-size)));
39
49
  --mdw-shape__size__bottom-right-size: calc((var(--mdw-shape__rtl) * var(--mdw-shape__size__bottom-start-size)) + (var(--mdw-shape__ltr) * var(--mdw-shape__size__bottom-end-size)));
40
50
 
41
- /** By default, fallback to border-radius */
42
- --mdw-shape__rounded: 1;
43
- --mdw-shape__inline-start-deg: calc(var(--mdw-dir, 1) * -90deg);
44
- z-index: 0;
45
51
  }
46
52
 
47
- :host([shape-style="none"]) {
53
+ .shape[shape-style="none"] {
48
54
  --mdw-shape__size: 0px;
49
55
  }
50
56
 
51
- :host([shape-style="extra-small"]) {
57
+ .shape[shape-style="extra-small"] {
52
58
  --mdw-shape__size: var(--mdw-shape__extra-small);
53
59
  }
54
60
 
55
- :host([shape-style="small"]) {
61
+ .shape[shape-style="small"] {
56
62
  --mdw-shape__size: var(--mdw-shape__small);
57
63
  }
58
64
 
59
- :host([shape-style="medium"]) {
65
+ .shape[shape-style="medium"] {
60
66
  --mdw-shape__size: var(--mdw-shape__medium);
61
67
  }
62
68
 
63
- :host([shape-style="large"]) {
69
+ .shape[shape-style="large"] {
64
70
  --mdw-shape__size: var(--mdw-shape__large);
65
71
  }
66
72
 
67
- :host([shape-style="extra-large"]) {
73
+ .shape[shape-style="extra-large"] {
68
74
  --mdw-shape__size: var(--mdw-shape__extra-large);
69
75
  }
70
76
 
71
- :host([shape-style="full"]) {
77
+ .shape[shape-style="full"] {
72
78
  --mdw-shape__size: var(--mdw-shape__full);
73
79
  }
74
80
 
75
- :host([shape-style="inherit"]) {
81
+ .shape[shape-style="inherit"] {
76
82
  --mdw-shape__size: inherit;
77
83
  }
78
84
 
79
- :host([shape-top]) {
85
+ .shape[shape-top] {
80
86
  --mdw-shape__size__bottom-start-size: 0px;
81
87
  --mdw-shape__size__bottom-end-size: 0px;
82
88
  --mdw-shape__mask: linear-gradient(transparent 50%, black 50%);
83
-
84
89
  }
85
90
 
86
- :host([shape-bottom]) {
91
+ .shape[shape-bottom] {
87
92
  --mdw-shape__size__top-start-size: 0px;
88
93
  --mdw-shape__size__top-end-size: 0px;
89
94
  --mdw-shape__mask: linear-gradient(black 50%, transparent 50%);
90
95
  }
91
96
 
92
- :host([shape-start]) {
97
+ .shape[shape-start] {
93
98
  --mdw-shape__size__top-end-size: 0px;
94
99
  --mdw-shape__size__bottom-end-size: 0px;
95
100
  --mdw-shape__mask: linear-gradient(var(--mdw-shape__inline-start-deg), black 50%, transparent 50%);
96
101
  }
97
102
 
98
- :host([shape-end]) {
103
+ .shape[shape-end] {
99
104
  --mdw-shape__size__top-start-size: 0px;
100
105
  --mdw-shape__size__bottom-start-size: 0px;
101
106
  --mdw-shape__mask: linear-gradient(var(--mdw-shape__inline-start-deg), transparent 50%, black 50%);
@@ -130,7 +135,7 @@ export default function ShapeMixin(Base) {
130
135
  will-change: background-color, color;
131
136
 
132
137
  }
133
-
138
+
134
139
  .shape[outlined] {
135
140
  background-color: transparent;
136
141
  }
@@ -7,9 +7,14 @@ let lastInteractionWasTouch = window?.matchMedia?.('(any-pointer: coarse)').matc
7
7
  */
8
8
  export default function StateMixin(Base) {
9
9
  return Base
10
- .extend()
11
10
  .observe({
12
11
  disabled: 'boolean',
12
+ /** Force focus state (independent of document) */
13
+ focused: 'boolean',
14
+ /** Force hover state (independent of interaction) */
15
+ hovered: 'boolean',
16
+ /** Force pressed state (independent of interaction) */
17
+ pressed: 'boolean',
13
18
  _lastInteraction: {
14
19
  /** @type {'mouse'|'touch'|'key'|'pen'|null} */
15
20
  value: null,
@@ -21,9 +26,9 @@ export default function StateMixin(Base) {
21
26
  })
22
27
  .observe({
23
28
  disabledState({ disabled }) { return disabled; },
24
- hoveredState({ _hovered }) { return _hovered; },
25
- focusedState({ _focused }) { return _focused; },
26
- pressedState({ _pressed }) { return _pressed; },
29
+ hoveredState({ _hovered, hovered }) { return _hovered || hovered; },
30
+ focusedState({ _focused, focused }) { return _focused || focused; },
31
+ pressedState({ _pressed, pressed }) { return _pressed || pressed; },
27
32
  touchedState({ _lastInteraction }) {
28
33
  return _lastInteraction === 'touch';
29
34
  },
@@ -31,8 +36,8 @@ export default function StateMixin(Base) {
31
36
  .define({
32
37
  stateTargetElement() { return this; },
33
38
  })
34
- .html/* html */`
35
- <div id=state _if={stateLayer}
39
+ .html`
40
+ <div id=state mdw-if={stateLayer}
36
41
  disabled={disabledState}
37
42
  focused={focusedState}
38
43
  hovered={hoveredState}
@@ -3,7 +3,6 @@
3
3
  */
4
4
  export default function SurfaceMixin(Base) {
5
5
  return Base
6
- .extend()
7
6
  .observe({
8
7
  elevated: 'boolean',
9
8
  elevation: 'integer',
@@ -14,17 +13,8 @@ export default function SurfaceMixin(Base) {
14
13
  },
15
14
  },
16
15
  })
17
- .expressions({
18
- showSurfaceTint({ elevated, elevation, disabledState, color }) {
19
- return (elevated || elevation !== null)
20
- && !disabledState
21
- && (!color || color.includes('surface'));
22
- },
23
- })
24
- .html/* html */`
25
- <div id=surface class=surface raised={_raised} disabled={disabledState} color={color}>
26
- <div _if={showSurfaceTint} id=surface-tint class=surface-tint raised={_raised} color={color} aria-hidden=true></div>
27
- </div>
16
+ .html`
17
+ <div id=surface class=surface raised={_raised} disabled={disabledState} color={color}></div>
28
18
  `
29
19
  .css`
30
20
  :host {
@@ -74,54 +64,39 @@ export default function SurfaceMixin(Base) {
74
64
  --mdw-surface__shadow__3: drop-shadow(0px 1px 1.5px rgba(0,0,0,0.3)) drop-shadow(0px 4px 007px rgba(0,0,0,0.263));
75
65
  --mdw-surface__shadow__4: drop-shadow(0px 2px 1.5px rgba(0,0,0,0.3)) drop-shadow(0px 6px 009px rgba(0,0,0,0.270));
76
66
  --mdw-surface__shadow__5: drop-shadow(0px 4px 2.0px rgba(0,0,0,0.3)) drop-shadow(0px 8px 012px rgba(0,0,0,0.300));
77
-
78
- --mdw-surface__tint__1: 0.05;
79
- --mdw-surface__tint__2: 0.08;
80
- --mdw-surface__tint__3: 0.11;
81
- --mdw-surface__tint__4: 0.12;
82
- --mdw-surface__tint__5: 0.14;
83
-
67
+
84
68
  /** Configurables */
85
69
 
86
70
  --mdw-surface__shadow__resting: none;
87
71
  --mdw-surface__shadow: var(--mdw-surface__shadow__resting);
88
- --mdw-surface__tint: 0;
89
- --mdw-surface__tint__raised: 0;
90
72
  z-index: 0;
91
73
  }
92
74
 
93
75
  :host([elevation="0"]) {
94
- --mdw-surface__tint: 0;
95
76
  --mdw-surface__shadow__resting: none;
96
77
  }
97
78
 
98
79
  :host([elevation="1"]) {
99
- --mdw-surface__tint: var(--mdw-surface__tint__1);
100
80
  --mdw-surface__shadow__resting: var(--mdw-surface__shadow__1);
101
81
  }
102
82
 
103
83
  :host([elevation="2"]) {
104
- --mdw-surface__tint: var(--mdw-surface__tint__2);
105
84
  --mdw-surface__shadow__resting: var(--mdw-surface__shadow__2);
106
85
  }
107
86
 
108
87
  :host([elevation="3"]) {
109
- --mdw-surface__tint: var(--mdw-surface__tint__3);
110
88
  --mdw-surface__shadow__resting: var(--mdw-surface__shadow__3);
111
89
  }
112
90
 
113
91
  :host([elevation="4"]) {
114
- --mdw-surface__tint: var(--mdw-surface__tint__4);
115
92
  --mdw-surface__shadow__resting: var(--mdw-surface__shadow__4);
116
93
  }
117
94
 
118
95
  :host([elevation="5"]) {
119
- --mdw-surface__tint: var(--mdw-surface__tint__5);
120
96
  --mdw-surface__shadow__resting: var(--mdw-surface__shadow__5);
121
97
  }
122
98
 
123
99
  :host([elevation]) {
124
- --mdw-surface__tint__raised: var(--mdw-surface__tint);
125
100
  --mdw-surface__shadow__raised: var(--mdw-surface__shadow__resting);
126
101
  }
127
102
 
@@ -148,34 +123,5 @@ export default function SurfaceMixin(Base) {
148
123
  .surface[disabled] {
149
124
  filter:none;
150
125
  }
151
-
152
- .surface-tint {
153
- position: absolute;
154
- inset: 0;
155
-
156
- pointer-events: none;
157
-
158
- opacity: var(--mdw-surface__tint, 0);
159
-
160
- background-color: rgb(var(--mdw-color__primary));
161
- border-radius: inherit;
162
-
163
- transition-delay: 1ms;
164
- transition-duration: 200ms;
165
- transition-property: opacity;
166
- will-change: opacity;
167
- }
168
-
169
- .surface-tint[raised] {
170
- opacity: var(--mdw-surface__tint__raised, 0);
171
- }
172
-
173
- .surface-tint[pressed] {
174
- opacity: var(--mdw-surface__tint, 0);
175
- }
176
-
177
- .surface-tint[color]:not([color|="surface"]) {
178
- display: none;
179
- }
180
126
  `;
181
127
  }