@api-client/ui 0.2.10 → 0.2.12

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 (154) hide show
  1. package/build/src/elements/http/CertificateAdd.element.d.ts.map +1 -1
  2. package/build/src/elements/http/CertificateAdd.element.js +2 -5
  3. package/build/src/elements/http/CertificateAdd.element.js.map +1 -1
  4. package/build/src/elements/user/internals/UserAvatar.styles.d.ts.map +1 -1
  5. package/build/src/elements/user/internals/UserAvatar.styles.js +0 -1
  6. package/build/src/elements/user/internals/UserAvatar.styles.js.map +1 -1
  7. package/build/src/md/UiElement.d.ts +5 -0
  8. package/build/src/md/UiElement.d.ts.map +1 -1
  9. package/build/src/md/UiElement.js +7 -0
  10. package/build/src/md/UiElement.js.map +1 -1
  11. package/build/src/md/button/ui-elevated-button.d.ts +1 -1
  12. package/build/src/md/button/ui-elevated-button.js +1 -1
  13. package/build/src/md/button/ui-elevated-button.js.map +1 -1
  14. package/build/src/md/button/ui-filled-button.d.ts +1 -1
  15. package/build/src/md/button/ui-filled-button.js +1 -1
  16. package/build/src/md/button/ui-filled-button.js.map +1 -1
  17. package/build/src/md/button/ui-filled-tonal-button.d.ts +3 -3
  18. package/build/src/md/button/ui-filled-tonal-button.d.ts.map +1 -1
  19. package/build/src/md/button/ui-filled-tonal-button.js +6 -6
  20. package/build/src/md/button/ui-filled-tonal-button.js.map +1 -1
  21. package/build/src/md/button/ui-outlined-button.d.ts +1 -1
  22. package/build/src/md/button/ui-outlined-button.js +1 -1
  23. package/build/src/md/button/ui-outlined-button.js.map +1 -1
  24. package/build/src/md/button/ui-text-button.d.ts +1 -1
  25. package/build/src/md/button/ui-text-button.js +1 -1
  26. package/build/src/md/button/ui-text-button.js.map +1 -1
  27. package/build/src/md/checkbox/internals/Checkbox.styles.d.ts.map +1 -1
  28. package/build/src/md/checkbox/internals/Checkbox.styles.js +55 -216
  29. package/build/src/md/checkbox/internals/Checkbox.styles.js.map +1 -1
  30. package/build/src/md/checkbox/internals/CheckboxElement.d.ts +10 -7
  31. package/build/src/md/checkbox/internals/CheckboxElement.d.ts.map +1 -1
  32. package/build/src/md/checkbox/internals/CheckboxElement.js +39 -32
  33. package/build/src/md/checkbox/internals/CheckboxElement.js.map +1 -1
  34. package/build/src/md/checkbox/internals/CheckedElement.d.ts.map +1 -1
  35. package/build/src/md/checkbox/internals/CheckedElement.js +1 -0
  36. package/build/src/md/checkbox/internals/CheckedElement.js.map +1 -1
  37. package/build/src/md/dropdown-list/internals/UiDropdownList.d.ts +13 -2
  38. package/build/src/md/dropdown-list/internals/UiDropdownList.d.ts.map +1 -1
  39. package/build/src/md/dropdown-list/internals/UiDropdownList.js +59 -20
  40. package/build/src/md/dropdown-list/internals/UiDropdownList.js.map +1 -1
  41. package/build/src/md/icon-button/internals/IconButton.d.ts +8 -24
  42. package/build/src/md/icon-button/internals/IconButton.d.ts.map +1 -1
  43. package/build/src/md/icon-button/internals/IconButton.js +35 -63
  44. package/build/src/md/icon-button/internals/IconButton.js.map +1 -1
  45. package/build/src/md/icon-button/internals/{IconButton.styles.d.ts → base.styles.d.ts} +1 -1
  46. package/build/src/md/icon-button/internals/base.styles.d.ts.map +1 -0
  47. package/build/src/md/icon-button/internals/base.styles.js +93 -0
  48. package/build/src/md/icon-button/internals/base.styles.js.map +1 -0
  49. package/build/src/md/icon-button/internals/filled-tonal.styles.d.ts +3 -0
  50. package/build/src/md/icon-button/internals/filled-tonal.styles.d.ts.map +1 -0
  51. package/build/src/md/icon-button/internals/filled-tonal.styles.js +30 -0
  52. package/build/src/md/icon-button/internals/filled-tonal.styles.js.map +1 -0
  53. package/build/src/md/icon-button/internals/filled.styles.d.ts +3 -0
  54. package/build/src/md/icon-button/internals/filled.styles.d.ts.map +1 -0
  55. package/build/src/md/icon-button/internals/filled.styles.js +36 -0
  56. package/build/src/md/icon-button/internals/filled.styles.js.map +1 -0
  57. package/build/src/md/icon-button/internals/outlined.styles.d.ts +3 -0
  58. package/build/src/md/icon-button/internals/outlined.styles.d.ts.map +1 -0
  59. package/build/src/md/icon-button/internals/outlined.styles.js +31 -0
  60. package/build/src/md/icon-button/internals/outlined.styles.js.map +1 -0
  61. package/build/src/md/icon-button/internals/standard.styles.d.ts +3 -0
  62. package/build/src/md/icon-button/internals/standard.styles.d.ts.map +1 -0
  63. package/build/src/md/icon-button/internals/standard.styles.js +18 -0
  64. package/build/src/md/icon-button/internals/standard.styles.js.map +1 -0
  65. package/build/src/md/icon-button/ui-filled-icon-button.d.ts +11 -0
  66. package/build/src/md/icon-button/ui-filled-icon-button.d.ts.map +1 -0
  67. package/build/src/md/icon-button/ui-filled-icon-button.js +28 -0
  68. package/build/src/md/icon-button/ui-filled-icon-button.js.map +1 -0
  69. package/build/src/md/icon-button/ui-filled-tonal-icon-button.d.ts +11 -0
  70. package/build/src/md/icon-button/ui-filled-tonal-icon-button.d.ts.map +1 -0
  71. package/build/src/md/icon-button/ui-filled-tonal-icon-button.js +28 -0
  72. package/build/src/md/icon-button/ui-filled-tonal-icon-button.js.map +1 -0
  73. package/build/src/md/icon-button/ui-icon-button.d.ts.map +1 -1
  74. package/build/src/md/icon-button/ui-icon-button.js +3 -2
  75. package/build/src/md/icon-button/ui-icon-button.js.map +1 -1
  76. package/build/src/md/icon-button/ui-outlined-icon-button.d.ts +11 -0
  77. package/build/src/md/icon-button/ui-outlined-icon-button.d.ts.map +1 -0
  78. package/build/src/md/icon-button/ui-outlined-icon-button.js +28 -0
  79. package/build/src/md/icon-button/ui-outlined-icon-button.js.map +1 -0
  80. package/build/src/md/icons/internals/Icon.d.ts +1 -0
  81. package/build/src/md/icons/internals/Icon.d.ts.map +1 -1
  82. package/build/src/md/icons/internals/Icon.js +13 -0
  83. package/build/src/md/icons/internals/Icon.js.map +1 -1
  84. package/build/src/md/icons/internals/Icon.styles.d.ts.map +1 -1
  85. package/build/src/md/icons/internals/Icon.styles.js +31 -2
  86. package/build/src/md/icons/internals/Icon.styles.js.map +1 -1
  87. package/build/src/md/list/internals/ListItem.d.ts +4 -3
  88. package/build/src/md/list/internals/ListItem.d.ts.map +1 -1
  89. package/build/src/md/list/internals/ListItem.js +20 -18
  90. package/build/src/md/list/internals/ListItem.js.map +1 -1
  91. package/build/src/md/list/internals/ListItem.styles.d.ts.map +1 -1
  92. package/build/src/md/list/internals/ListItem.styles.js +6 -2
  93. package/build/src/md/list/internals/ListItem.styles.js.map +1 -1
  94. package/build/src/md/ripple/internals/ripple.d.ts +2 -1
  95. package/build/src/md/ripple/internals/ripple.d.ts.map +1 -1
  96. package/build/src/md/ripple/internals/ripple.js +42 -12
  97. package/build/src/md/ripple/internals/ripple.js.map +1 -1
  98. package/build/src/md/segmented-button/internals/SegmentedButton.d.ts +1 -1
  99. package/build/src/md/segmented-button/internals/SegmentedButton.d.ts.map +1 -1
  100. package/build/src/md/segmented-button/internals/SegmentedButton.js +1 -1
  101. package/build/src/md/segmented-button/internals/SegmentedButton.js.map +1 -1
  102. package/demo/md/buttons/{button.html → index.html} +1 -1
  103. package/demo/md/{inputs/checkbox.html → checkbox/index.html} +1 -1
  104. package/demo/md/{list/dropdown-list.html → dropdown-list/index.html} +1 -1
  105. package/demo/md/{buttons/icon-button.html → icon-button/index.html} +5 -1
  106. package/demo/md/icon-button/index.ts +236 -0
  107. package/demo/md/index.html +36 -29
  108. package/demo/md/listbox/listbox.html +31 -0
  109. package/demo/md/listbox/listbox.ts +27 -0
  110. package/demo/md/{buttons/segmented-buttons.html → segmented-button/index.html} +1 -1
  111. package/package.json +2 -2
  112. package/src/elements/http/CertificateAdd.element.ts +2 -5
  113. package/src/elements/user/internals/UserAvatar.styles.ts +0 -1
  114. package/src/md/UiElement.ts +8 -0
  115. package/src/md/button/ui-elevated-button.ts +1 -1
  116. package/src/md/button/ui-filled-button.ts +1 -1
  117. package/src/md/button/ui-filled-tonal-button.ts +3 -3
  118. package/src/md/button/ui-outlined-button.ts +1 -1
  119. package/src/md/button/ui-text-button.ts +1 -1
  120. package/src/md/checkbox/internals/Checkbox.styles.ts +55 -216
  121. package/src/md/checkbox/internals/CheckboxElement.ts +39 -26
  122. package/src/md/checkbox/internals/CheckedElement.ts +1 -0
  123. package/src/md/dropdown-list/internals/UiDropdownList.ts +60 -21
  124. package/src/md/icon-button/internals/IconButton.ts +29 -46
  125. package/src/md/icon-button/internals/base.styles.ts +93 -0
  126. package/src/md/icon-button/internals/filled-tonal.styles.ts +30 -0
  127. package/src/md/icon-button/internals/filled.styles.ts +36 -0
  128. package/src/md/icon-button/internals/outlined.styles.ts +31 -0
  129. package/src/md/icon-button/internals/standard.styles.ts +18 -0
  130. package/src/md/icon-button/ui-filled-icon-button.ts +16 -0
  131. package/src/md/icon-button/ui-filled-tonal-icon-button.ts +16 -0
  132. package/src/md/icon-button/ui-icon-button.ts +3 -2
  133. package/src/md/icon-button/ui-outlined-icon-button.ts +16 -0
  134. package/src/md/icons/internals/Icon.styles.ts +31 -2
  135. package/src/md/icons/internals/Icon.ts +14 -0
  136. package/src/md/list/internals/ListItem.styles.ts +6 -2
  137. package/src/md/list/internals/ListItem.ts +16 -21
  138. package/src/md/ripple/internals/ripple.ts +47 -13
  139. package/src/md/segmented-button/internals/SegmentedButton.ts +2 -2
  140. package/test/ui/button/UiIconButton.test.ts +1 -8
  141. package/build/src/lib/UserCache.d.ts +0 -13
  142. package/build/src/lib/UserCache.d.ts.map +0 -1
  143. package/build/src/lib/UserCache.js +0 -30
  144. package/build/src/lib/UserCache.js.map +0 -1
  145. package/build/src/md/icon-button/internals/IconButton.styles.d.ts.map +0 -1
  146. package/build/src/md/icon-button/internals/IconButton.styles.js +0 -614
  147. package/build/src/md/icon-button/internals/IconButton.styles.js.map +0 -1
  148. package/demo/md/buttons/icon-button.ts +0 -184
  149. package/src/lib/UserCache.ts +0 -33
  150. package/src/md/icon-button/internals/IconButton.styles.ts +0 -614
  151. /package/demo/md/buttons/{button.ts → index.ts} +0 -0
  152. /package/demo/md/{inputs/checkbox.ts → checkbox/index.ts} +0 -0
  153. /package/demo/md/{list/dropdown-list.ts → dropdown-list/index.ts} +0 -0
  154. /package/demo/md/{buttons/segmented-buttons.ts → segmented-button/index.ts} +0 -0
@@ -104,6 +104,14 @@ export abstract class UiElement extends LitElement implements ActionControllerHo
104
104
  this.actionController.pointerLeave(e)
105
105
  }
106
106
 
107
+ /**
108
+ * Subclasses should add this method as an event handler on the interactive
109
+ * template element with `@pointerenter="${this.handlePointerEnter}"`
110
+ */
111
+ handlePointerEnter(e: PointerEvent): void {
112
+ // this.actionController.pointerEnter(e)
113
+ }
114
+
107
115
  /**
108
116
  * Hook method for the ActionController.
109
117
  * Subclasses should add this method as an event handler on the interactive
@@ -5,7 +5,7 @@ import base from './internals/button-styles.js'
5
5
  import styles from './internals/elevated-button.styles.js'
6
6
 
7
7
  /**
8
- * @attrbite {string} form
8
+ * @attribute form
9
9
  */
10
10
  @customElement('ui-elevated-button')
11
11
  export class UiElevatedButtonElement extends Element {
@@ -5,7 +5,7 @@ import base from './internals/button-styles.js'
5
5
  import styles from './internals/filled-button.styles.js'
6
6
 
7
7
  /**
8
- * @attrbite {string} form
8
+ * @attribute {string} form
9
9
  */
10
10
  @customElement('ui-filled-button')
11
11
  export class UiFilledButtonElement extends Element {
@@ -5,15 +5,15 @@ import base from './internals/button-styles.js'
5
5
  import styles from './internals/filled-tonal-button.styles.js'
6
6
 
7
7
  /**
8
- * @attrbite {string} form
8
+ * @attribute {string} form
9
9
  */
10
10
  @customElement('ui-filled-tonal-button')
11
- export class UiFilltedButtonElement extends Element {
11
+ export class UiFilledButtonElement extends Element {
12
12
  static override styles: CSSResultOrNative[] = [base, styles]
13
13
  }
14
14
 
15
15
  declare global {
16
16
  interface HTMLElementTagNameMap {
17
- 'ui-filled-tonal-button': UiFilltedButtonElement
17
+ 'ui-filled-tonal-button': UiFilledButtonElement
18
18
  }
19
19
  }
@@ -5,7 +5,7 @@ import base from './internals/button-styles.js'
5
5
  import styles from './internals/outlined-button.styles.js'
6
6
 
7
7
  /**
8
- * @attrbite {string} form
8
+ * @attribute {string} form
9
9
  */
10
10
  @customElement('ui-outlined-button')
11
11
  export class UiOutlinedButtonElement extends Element {
@@ -5,7 +5,7 @@ import base from './internals/button-styles.js'
5
5
  import styles from './internals/text-button.styles.js'
6
6
 
7
7
  /**
8
- * @attrbite {string} form
8
+ * @attribute {string} form
9
9
  */
10
10
  @customElement('ui-text-button')
11
11
  export class UiTextButtonElement extends Element {
@@ -7,29 +7,44 @@ export default css`
7
7
  outline: none;
8
8
  -webkit-tap-highlight-color: transparent;
9
9
 
10
+ position: relative;
11
+
10
12
  --md-ripple-hover-state-layer-color: var(--md-sys-color-on-surface);
11
13
  --md-ripple-focus-state-layer-color: var(--md-sys-color-on-surface);
12
14
  --md-ripple-pressed-state-layer-color: var(--md-sys-color-primary);
15
+
16
+ --_container-border-color: var(--md-sys-color-on-surface);
17
+ --_container-border-width: 2px;
18
+ --_container-background-color: transparent;
19
+ --_container-opacity: 1;
20
+
21
+ --_check-mark-color: currentColor;
22
+
23
+ --_checkbox-width: 18px;
24
+ --_checkbox-height: 18px;
25
+ --_state-width: 40px;
26
+ --_state-height: 40px;
13
27
  }
14
28
 
15
29
  .surface {
16
30
  position: relative;
17
- min-width: 40px;
18
- height: 40px;
31
+ min-width: var(--_state-width);
32
+ height: var(--_state-height);
19
33
  display: flex;
20
34
  align-items: center;
21
35
  }
22
36
 
23
37
  .container {
24
38
  border-radius: 2px;
25
- border: 2px var(--md-sys-color-on-surface) solid;
26
- background-color: transparent;
39
+ border: var(--_container-border-width) var(--_container-border-color) solid;
40
+ background-color: var(--_container-background-color);
41
+ opacity: var(--_container-opacity);
27
42
 
28
43
  position: absolute;
29
44
  inset: 11px 0px 0px 11px;
30
45
 
31
- width: 18px;
32
- height: 18px;
46
+ width: var(--_checkbox-width);
47
+ height: var(--_checkbox-height);
33
48
 
34
49
  box-sizing: border-box;
35
50
 
@@ -40,22 +55,23 @@ export default css`
40
55
  }
41
56
 
42
57
  .icon {
43
- width: 18px;
44
- height: 18px;
58
+ width: var(--_checkbox-width);
59
+ height: var(--_checkbox-height);
45
60
  position: absolute;
46
61
  inset: 11px 0 0 11px;
47
62
  }
48
63
 
49
64
  .icon > svg {
50
- width: 18px !important;
51
- height: 18px !important;
65
+ width: var(--_checkbox-width) !important;
66
+ height: var(--_checkbox-height) !important;
67
+ fill: var(--_check-mark-color);
52
68
  }
53
69
 
54
70
  .state {
55
71
  position: absolute;
56
72
  inset: 0;
57
- width: 40px;
58
- height: 40px;
73
+ width: var(--_state-width);
74
+ height: var(--_state-height);
59
75
  border-radius: var(--md-sys-shape-corner-full);
60
76
  }
61
77
 
@@ -64,222 +80,45 @@ export default css`
64
80
  z-index: 3;
65
81
  }
66
82
 
67
- :host([checked]) .container,
68
- :host([indeterminate]) .container {
69
- border-width: 0px;
70
- background-color: var(--md-sys-color-primary);
71
- }
72
-
73
- :host([checked]) .icon > svg,
74
- :host([indeterminate]) .icon > svg {
75
- fill: var(--md-sys-color-on-primary);
76
- }
77
-
78
- /* Invalid state */
79
-
80
- :host([invalid]) .container {
81
- border-color: var(--md-sys-color-error);
82
- }
83
-
84
- :host([checked][invalid]) .container,
85
- :host([indeterminate][invalid]) .container {
86
- border-color: transparent;
87
- background-color: var(--md-sys-color-error);
88
- }
89
-
90
- :host([checked][invalid]) .icon > svg,
91
- :host([indeterminate][invalid]) .icon > svg {
92
- fill: var(--md-sys-color-on-error);
93
- }
94
-
95
- /* Disabled state */
96
-
97
- :host([disabled]) {
98
- pointer-events: none;
99
- }
100
-
101
- :host([disabled]) .container {
102
- border-color: var(--md-sys-color-on-surface);
103
- border-width: 2px;
104
- opacity: 38%;
83
+ :host([checked]) {
84
+ --md-ripple-hover-state-layer-color: var(--md-sys-color-primary);
85
+ --md-ripple-focus-state-layer-color: var(--md-sys-color-primary);
86
+ --md-ripple-pressed-state-layer-color: var(--md-sys-color-on-surface);
105
87
  }
106
88
 
107
- :host([checked][disabled]) .container,
108
- :host([indeterminate][disabled]) .container {
109
- background-color: var(--md-sys-color-on-surface);
110
- border-width: 0;
111
- opacity: 38%;
89
+ :host([checked]),
90
+ :host([indeterminate]) {
91
+ --_container-border-width: 0px;
92
+ --_container-background-color: var(--md-sys-color-primary);
93
+ --_check-mark-color: var(--md-sys-color-on-primary);
112
94
  }
113
95
 
114
- :host([checked][disabled]) .icon > svg,
115
- :host([indeterminate][disabled]) .icon > svg {
116
- fill: var(--md-sys-color-surface);
117
- }
118
-
119
- /* Hover state */
120
-
121
- /* :host(:hover) .state {
122
- background-color: var(--md-sys-color-on-surface);
123
- opacity: var(--md-sys-state-hover-state-layer-opacity);
124
- } */
125
-
126
- /* :host([checked]:hover) .state,
127
- :host([indeterminate]:hover) .state {
128
- background-color: var(--md-sys-color-primary);
129
- opacity: var(--md-sys-state-hover-state-layer-opacity);
130
- } */
131
-
132
- :host(:hover) .container {
133
- border-color: var(--md-sys-color-on-surface);
134
- border-width: 2px;
135
- }
136
-
137
- :host([checked]:hover) .container,
138
- :host([indeterminate]:hover) .container {
139
- background-color: var(--md-sys-color-primary);
140
- border-width: 0px;
141
- }
142
-
143
- :host(:hover) .icon > svg {
144
- fill: var(--md-sys-color-on-primary);
145
- }
146
-
147
- :host([invalid]:hover) {
96
+ :host([invalid]) {
148
97
  --md-ripple-hover-state-layer-color: var(--md-sys-color-error);
149
98
  --md-ripple-focus-state-layer-color: var(--md-sys-color-error);
150
99
  --md-ripple-pressed-state-layer-color: var(--md-sys-color-error);
100
+ --_container-border-color: var(--md-sys-color-error);
151
101
  }
152
102
 
153
- /* :host([invalid]:hover) .state {
154
- background-color: var(--md-sys-color-error);
155
- opacity: var(--md-sys-state-hover-state-layer-opacity);
156
- } */
157
-
158
- :host([invalid]:hover) .container {
159
- border-color: var(--md-sys-color-error);
160
- border-width: 2px;
103
+ :host([checked][invalid]),
104
+ :host([indeterminate][invalid]) {
105
+ --_check-mark-color: var(--md-sys-color-on-error);
106
+ --_container-border-color: transparent;
107
+ --_container-background-color: var(--md-sys-color-error);
161
108
  }
162
109
 
163
- :host([checked][invalid]:hover) .container,
164
- :host([indeterminate][invalid]:hover) .container {
165
- background-color: var(--md-sys-color-error);
166
- border-width: 0px;
167
- }
168
-
169
- :host([checked][invalid]:hover) .icon > svg,
170
- :host([indeterminate][invalid]:hover) .icon > svg {
171
- fill: var(--md-sys-color-on-error);
172
- }
173
-
174
- /* Focus state */
175
-
176
- /* :host(:focus) .state {
177
- background-color: var(--md-sys-color-primary);
178
- opacity: var(--md-sys-state-focus-state-layer-opacity);
179
- }
180
-
181
- :host([checked]:focus) .state,
182
- :host([indeterminate]:focus) .state {
183
- background-color: var(--md-sys-color-on-surface);
184
- opacity: var(--md-sys-state-focus-state-layer-opacity);
185
- } */
186
-
187
- :host(:focus) .container {
188
- border-color: var(--md-sys-color-on-surface);
189
- border-width: 2px;
190
- }
191
-
192
- :host([checked]:focus) .container,
193
- :host([indeterminate]:focus) .container {
194
- background-color: var(--md-sys-color-primary);
195
- border-width: 0px;
196
- }
197
-
198
- :host(:focus) .icon > svg {
199
- fill: var(--md-sys-color-on-primary);
200
- }
201
-
202
- /* :host([invalid]:focus) .state {
203
- background-color: var(--md-sys-color-error);
204
- opacity: var(--md-sys-state-focus-state-layer-opacity);
205
- } */
206
-
207
- :host([invalid]:focus) .container {
208
- border-color: var(--md-sys-color-error);
209
- border-width: 2px;
210
- }
211
-
212
- :host([checked][invalid]:focus) .container,
213
- :host([indeterminate][invalid]:focus) .container {
214
- background-color: var(--md-sys-color-error);
215
- border-width: 0px;
216
- }
217
-
218
- :host([checked][invalid]:focus) .icon > svg,
219
- :host([indeterminate][invalid]:focus) .icon > svg {
220
- fill: var(--md-sys-color-on-error);
221
- }
222
-
223
- /* Pressed state */
224
-
225
- /* :host(:active) .state,
226
- :host .pressed .state {
227
- background-color: var(--md-sys-color-primary);
228
- opacity: var(--md-sys-state-pressed-state-layer-opacity);
229
- }
230
-
231
- :host([checked]:active) .state,
232
- :host([checked]) .pressed .state,
233
- :host([indeterminate]:active) .state,
234
- :host([indeterminate]) .pressed .state {
235
- background-color: var(--md-sys-color-on-surface);
236
- opacity: var(--md-sys-state-pressed-state-layer-opacity);
237
- } */
238
-
239
- :host(:active) .container,
240
- :host .pressed .container {
241
- border-color: var(--md-sys-color-on-surface);
242
- border-width: 2px;
243
- }
244
-
245
- :host([checked]:active) .container,
246
- :host([checked]) .pressed .container,
247
- :host([indeterminate]:active) .container,
248
- :host([indeterminate]) .pressed .container {
249
- background-color: var(--md-sys-color-primary);
250
- border-width: 0px;
251
- }
252
-
253
- :host([checked]:active) .icon > svg,
254
- :host([checked]) .pressed .icon > svg,
255
- :host([indeterminate]:active) .icon > svg,
256
- :host([indeterminate]) .pressed .icon > svg {
257
- fill: var(--md-sys-color-on-primary);
258
- }
259
-
260
- /* :host([invalid]:active) .state,
261
- :host([invalid]) .pressed .state {
262
- background-color: var(--md-sys-color-error);
263
- opacity: var(--md-sys-state-pressed-state-layer-opacity);
264
- } */
265
-
266
- :host([invalid]:active) .container,
267
- :host([invalid]) .pressed .container {
268
- border-color: var(--md-sys-color-error);
269
- border-width: 2px;
270
- }
271
-
272
- :host([checked][invalid]:active) .container,
273
- :host([checked][invalid]) .pressed .container,
274
- :host([indeterminate][invalid]:active) .container :host([indeterminate][invalid]) .pressed .container {
275
- background-color: var(--md-sys-color-error);
276
- border-width: 0px;
110
+ :host([disabled]) {
111
+ pointer-events: none;
112
+ --_check-mark-color: var(--md-sys-color-surface);
113
+ --_container-border-color: var(--md-sys-color-on-surface);
114
+ --_container-border-width: 2px;
115
+ --_container-opacity: 38%;
277
116
  }
278
117
 
279
- :host([checked][invalid]:active) .icon > svg,
280
- :host([checked][invalid]) .pressed .icon > svg,
281
- :host([indeterminate][invalid]:active) .icon > svg,
282
- :host([indeterminate][invalid]) .pressed .icon > svg {
283
- fill: var(--md-sys-color-on-error);
118
+ :host([checked][disabled]),
119
+ :host([indeterminate][disabled]) {
120
+ --_container-background-color: var(--md-sys-color-on-surface);
121
+ --_container-border-width: 0;
122
+ --_container-opacity: 38%;
284
123
  }
285
124
  `
@@ -1,12 +1,13 @@
1
1
  import { html, SVGTemplateResult, TemplateResult, nothing } from 'lit'
2
- import { queryAsync, state } from 'lit/decorators.js'
2
+ import { query } from 'lit/decorators.js'
3
3
  import { classMap } from 'lit/directives/class-map.js'
4
- import { when } from 'lit/directives/when.js'
5
4
  import CheckedElement from './CheckedElement.js'
6
5
  import { check, checkIndeterminate } from '../../icons/Icons.js'
7
- import { ripple } from '../../effects/rippleDirective.js'
8
- import UiRipple from '../../ripple/internals/ripple.js'
6
+ import type UiRipple from '../../ripple/internals/ripple.js'
7
+ import type { BeginPressConfig, EndPressConfig } from '../../../controllers/ActionController.js'
8
+
9
9
  import '../../ripple/ui-ripple.js'
10
+ import '@material/web/focus/md-focus-ring.js'
10
11
 
11
12
  export default class CheckboxElement extends CheckedElement {
12
13
  protected get _icon(): SVGTemplateResult | typeof nothing {
@@ -20,38 +21,54 @@ export default class CheckboxElement extends CheckedElement {
20
21
  return nothing
21
22
  }
22
23
 
23
- @queryAsync('ui-ripple') protected accessor ripple!: Promise<UiRipple | null>
24
+ @query('ui-ripple') protected accessor ripple!: UiRipple | null
24
25
 
25
- @state() protected accessor showRipple = false
26
+ protected pressRipple(options: BeginPressConfig): void {
27
+ const element = this.ripple
28
+ if (element && !element.isPressed) {
29
+ element.beginPress(options.positionEvent as PointerEvent)
30
+ }
31
+ }
26
32
 
27
- protected readonly getRipple = (): Promise<UiRipple | null> => {
28
- this.showRipple = true
29
- return this.ripple
33
+ protected endRipple(): void {
34
+ this.ripple?.endPress()
30
35
  }
31
36
 
32
- protected override async handleFocus(): Promise<void> {
33
- const _ripple = await this.getRipple()
34
- _ripple?.beginFocus()
37
+ override beginPress(options: BeginPressConfig): void {
38
+ super.beginPress(options)
39
+ this.pressRipple(options)
35
40
  }
36
41
 
37
- protected override async handleBlur(): Promise<void> {
38
- const _ripple = await this.getRipple()
39
- _ripple?.endFocus()
42
+ override endPress(config: EndPressConfig): void {
43
+ super.endPress(config)
44
+ this.endRipple()
40
45
  }
41
46
 
42
47
  override async handleKeyDown(e: KeyboardEvent): Promise<void> {
43
48
  super.handleKeyDown(e)
44
49
  if (['Space'].includes(e.code)) {
45
- const _ripple = await this.getRipple()
46
- _ripple?.beginPress()
50
+ this.ripple?.beginPress()
47
51
  }
48
52
  }
49
53
 
50
54
  override async handleKeyUp(e: KeyboardEvent): Promise<void> {
51
55
  super.handleKeyUp(e)
52
56
  if (['Space'].includes(e.code)) {
53
- const _ripple = await this.getRipple()
54
- _ripple?.endPress()
57
+ this.ripple?.endPress()
58
+ }
59
+ }
60
+
61
+ override handlePointerEnter(e: PointerEvent): void {
62
+ super.handlePointerEnter(e)
63
+ if (this.ripple) {
64
+ this.ripple.beginHover(e)
65
+ }
66
+ }
67
+
68
+ override handlePointerLeave(e: PointerEvent): void {
69
+ super.handlePointerLeave(e)
70
+ if (this.ripple) {
71
+ this.ripple.endHover()
55
72
  }
56
73
  }
57
74
 
@@ -62,17 +79,13 @@ export default class CheckboxElement extends CheckedElement {
62
79
  pressed,
63
80
  })
64
81
  return html`
65
- <div class="${containerClasses}" ${ripple(this.getRipple)}>
82
+ <md-focus-ring part="focus-ring" .control="${this as HTMLElement}"></md-focus-ring>
83
+ <div class="${containerClasses}">
66
84
  <div class="container"></div>
67
85
  <div class="state"></div>
68
- ${when(this.showRipple, this.renderRipple)}
86
+ <ui-ripple class="ripple" unbounded ?disabled="${this.disabled}"></ui-ripple>
69
87
  <div class="icon">${this._icon}</div>
70
88
  </div>
71
89
  `
72
90
  }
73
-
74
- protected renderRipple = (): TemplateResult => {
75
- const { disabled } = this
76
- return html`<ui-ripple class="ripple" unbounded ?disabled="${disabled}"></ui-ripple>`
77
- }
78
91
  }
@@ -104,6 +104,7 @@ export default class CheckedElement extends UiElement {
104
104
  this.addEventListener('pointerdown', this.handlePointerDown.bind(this))
105
105
  this.addEventListener('pointerup', this.handlePointerUp.bind(this))
106
106
  this.addEventListener('pointercancel', this.handlePointerCancel.bind(this))
107
+ this.addEventListener('pointerenter', this.handlePointerEnter.bind(this))
107
108
  this.addEventListener('pointerleave', this.handlePointerLeave.bind(this))
108
109
  this.addEventListener('contextmenu', this.handleContextMenu.bind(this))
109
110
  this.addEventListener('keydown', this.handleKeyDown.bind(this))
@@ -156,6 +156,22 @@ export default class UiDropdownList extends LitElement {
156
156
  this.close()
157
157
  }
158
158
 
159
+ protected override willUpdate(cp: PropertyValues<this>): void {
160
+ super.willUpdate(cp)
161
+ if ((cp.has('noOverlap') || cp.has('verticalAlign') || cp.has('horizontalAlign') || cp.has('open')) && this.open) {
162
+ this.computePositioning()
163
+ }
164
+ }
165
+
166
+ protected override updated(cp: PropertyValues<this>): void {
167
+ super.updated(cp)
168
+ if (cp.has('open')) {
169
+ this.toggleOpened()
170
+ this.updateExpanded()
171
+ // this.manageTabindex()
172
+ }
173
+ }
174
+
159
175
  protected updateExpanded(): void {
160
176
  this.setAttribute('aria-expanded', String(this.open))
161
177
  }
@@ -202,7 +218,6 @@ export default class UiDropdownList extends LitElement {
202
218
 
203
219
  protected triggerClickHandler(): void {
204
220
  this.open = !this.open
205
- this.updateExpanded()
206
221
  this.notifyOpen()
207
222
  }
208
223
 
@@ -210,7 +225,6 @@ export default class UiDropdownList extends LitElement {
210
225
  if (['Enter', 'Space', 'ArrowDown', 'ArrowUp'].includes(e.code)) {
211
226
  e.preventDefault()
212
227
  this.open = true
213
- this.updateExpanded()
214
228
  this.notifyOpen()
215
229
  }
216
230
  }
@@ -236,7 +250,6 @@ export default class UiDropdownList extends LitElement {
236
250
 
237
251
  close(): void {
238
252
  this.open = false
239
- this.updateExpanded()
240
253
  this.notifyOpen()
241
254
  }
242
255
 
@@ -245,20 +258,6 @@ export default class UiDropdownList extends LitElement {
245
258
  this.close()
246
259
  }
247
260
 
248
- protected override willUpdate(cp: PropertyValues<this>): void {
249
- super.willUpdate(cp)
250
- if ((cp.has('noOverlap') || cp.has('verticalAlign') || cp.has('horizontalAlign') || cp.has('open')) && this.open) {
251
- this.computePositioning()
252
- }
253
- }
254
-
255
- protected override updated(cp: PropertyValues<this>): void {
256
- super.updated(cp)
257
- if (cp.has('open')) {
258
- this.toggleOpened()
259
- }
260
- }
261
-
262
261
  /**
263
262
  * Since the container for the dropdown content is positioned as fixed
264
263
  * we need to position the dropdown according to the configured rules.
@@ -304,12 +303,49 @@ export default class UiDropdownList extends LitElement {
304
303
  }
305
304
  }
306
305
 
306
+ /**
307
+ * When set, it is the last active child of the dropdown
308
+ * before the tabindex was removed from it. It is used to restore focus
309
+ * when the dropdown is re-opened.
310
+ */
311
+ lastActiveChild?: HTMLElement
312
+
313
+ /**
314
+ * When the list is closed, the tabindex of the dropdown is removed to prevent
315
+ * it from being focused while invisible.
316
+ */
317
+ protected manageTabindex(): void {
318
+ const { dropdown } = this
319
+ if (!dropdown) {
320
+ return
321
+ }
322
+ if (this.open) {
323
+ if (this.lastActiveChild) {
324
+ this.lastActiveChild.setAttribute('tabindex', '0')
325
+ this.lastActiveChild.focus()
326
+ this.lastActiveChild = undefined
327
+ } else {
328
+ // If no last active child, focus the dropdown itself
329
+ dropdown.setAttribute('tabindex', '0')
330
+ }
331
+ } else {
332
+ // const activeChild = dropdown.querySelector(':focus') || dropdown
333
+ // this.lastActiveChild = activeChild as HTMLElement
334
+ // activeChild.removeAttribute('tabindex')
335
+ // this.trigger?.focus()
336
+ }
337
+ }
338
+
307
339
  protected handleOpened(): void {
308
340
  const { trigger, dropdown } = this
309
341
  if (trigger) {
310
342
  trigger.removeAttribute('tabindex')
311
343
  }
312
- if (dropdown) {
344
+ if (this.lastActiveChild) {
345
+ this.lastActiveChild.setAttribute('tabindex', '0')
346
+ this.lastActiveChild.focus()
347
+ this.lastActiveChild = undefined
348
+ } else if (dropdown) {
313
349
  dropdown.setAttribute('tabindex', '0')
314
350
  dropdown.focus()
315
351
  }
@@ -319,11 +355,14 @@ export default class UiDropdownList extends LitElement {
319
355
  const { trigger, dropdown } = this
320
356
  if (trigger) {
321
357
  trigger.setAttribute('tabindex', '0')
322
- if (this.matches(':focus-within')) {
323
- trigger.focus()
324
- }
358
+ trigger.focus()
325
359
  }
326
360
  if (dropdown) {
361
+ const activeChild = dropdown.querySelector('[tabindex="0"]')
362
+ if (activeChild) {
363
+ this.lastActiveChild = activeChild as HTMLElement
364
+ activeChild.removeAttribute('tabindex')
365
+ }
327
366
  dropdown.removeAttribute('tabindex')
328
367
  }
329
368
  }