@vollowx/seele 0.8.4 → 0.8.6

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vollowx/seele",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "Standard Extensible Elements. A web components library that can be styled and extended freely, pre-providing components in Material Design 3.",
5
5
  "author": "vollowx",
6
6
  "license": "MIT",
@@ -18,6 +18,7 @@
18
18
  "LICENSE",
19
19
  "README.md"
20
20
  ],
21
+ "customElements": "custom-elements.json",
21
22
  "keywords": [
22
23
  "web-components",
23
24
  "material-design",
@@ -25,6 +26,7 @@
25
26
  "lit",
26
27
  "ui-components"
27
28
  ],
29
+ "homepage": "https://docs.seele.v9.nz",
28
30
  "repository": {
29
31
  "type": "git",
30
32
  "url": "https://github.com/vollowx/seele.git"
package/src/base/menu.js CHANGED
@@ -3,7 +3,7 @@ import { LitElement, html } from 'lit';
3
3
  import { property, query } from 'lit/decorators.js';
4
4
  import { setFocusVisible } from '../core/focus-visible.js';
5
5
  import { Attachable } from './mixins/attachable.js';
6
- import { internals, InternalsAttached } from './mixins/internals-attached.js';
6
+ import { InternalsAttached } from './mixins/internals-attached.js';
7
7
  import { PopoverController } from './controllers/popover-controller.js';
8
8
  import { ListController } from './controllers/list-controller.js';
9
9
  import { MenuActions, getActionFromKey, getUpdatedIndex, scrollItemIntoView, } from './menu-utils.js';
@@ -13,10 +13,12 @@ const Base = InternalsAttached(Attachable(LitElement));
13
13
  * @csspart items
14
14
  *
15
15
  * @fires {Event} select - Fired when a menu item has been selected.
16
+ * @fires {Event} open - Fired when the menu is opened.
17
+ * @fires {Event} close - Fired when the menu is closed.
16
18
  */
17
19
  export class Menu extends Base {
18
20
  constructor() {
19
- super();
21
+ super(...arguments);
20
22
  this._possibleItemTags = [];
21
23
  this._durations = { show: 0, hide: 0 };
22
24
  this._scrollPadding = 0;
@@ -57,32 +59,35 @@ export class Menu extends Base {
57
59
  },
58
60
  focusItem: (item) => {
59
61
  item.focused = true;
60
- // this[internals].ariaActiveDescendantElement = item;
61
- // Somehow setting ariaActiveDescendantElement doesn't actually update it
62
- this.setAttribute('aria-activedescendant', item.id);
62
+ this.$menu.setAttribute('aria-activedescendant', item.id);
63
63
  scrollItemIntoView(this.$menu, item, this._scrollPadding);
64
64
  },
65
65
  wrapNavigation: () => false,
66
66
  });
67
- this[internals].role = 'menu';
68
- this.tabIndex = -1;
69
67
  }
68
+ static { this.shadowRootOptions = {
69
+ ...LitElement.shadowRootOptions,
70
+ delegatesFocus: true,
71
+ }; }
70
72
  render() {
71
- return html `<div part="menu">${this.renderItemSlot()}</div>`;
73
+ return html `<div
74
+ part="menu"
75
+ role="menu"
76
+ tabindex="0"
77
+ @keydown=${this.#handleKeyDown.bind(this)}
78
+ @focusout=${this.#handleFocusOut.bind(this)}
79
+ >
80
+ ${this.renderItemSlot()}
81
+ </div>`;
72
82
  }
73
83
  renderItemSlot() {
74
84
  return html `<slot part="items"></slot>`;
75
85
  }
76
86
  connectedCallback() {
77
87
  super.connectedCallback();
78
- this.addEventListener('keydown', this.#handleKeyDown.bind(this));
79
- this.addEventListener('focusout', this.#handleFocusOut.bind(this));
80
88
  if (this.$control) {
89
+ // TODO: Manage $control ARIA attributes
81
90
  // TODO: Handle $control change
82
- this.$control.ariaHasPopup = 'true';
83
- this.$control.ariaExpanded = 'false';
84
- this.$control.ariaControlsElements = [this];
85
- this[internals].ariaLabelledByElements = [this.$control];
86
91
  this.$control.addEventListener('focusout', this.#handleFocusOut.bind(this));
87
92
  }
88
93
  this.listController.items.forEach((item) => {
@@ -92,8 +97,6 @@ export class Menu extends Base {
92
97
  }
93
98
  disconnectedCallback() {
94
99
  super.disconnectedCallback();
95
- this.removeEventListener('keydown', this.#handleKeyDown.bind(this));
96
- this.removeEventListener('focusout', this.#handleFocusOut.bind(this));
97
100
  if (this.$control) {
98
101
  this.$control.removeEventListener('focusout', this.#handleFocusOut.bind(this));
99
102
  }
@@ -101,16 +104,18 @@ export class Menu extends Base {
101
104
  updated(changed) {
102
105
  if (changed.has('open')) {
103
106
  if (this.open) {
107
+ this.dispatchEvent(new Event('open', { bubbles: true, composed: true }));
104
108
  this.$lastFocused = document.activeElement;
105
109
  if (this.$control) {
106
110
  this.$control.ariaExpanded = 'true';
107
111
  }
108
112
  this.popoverController.animateOpen().then(() => {
109
- this.focus();
113
+ this.$menu.focus();
110
114
  this.listController.focusFirstItem();
111
115
  });
112
116
  }
113
117
  else {
118
+ this.dispatchEvent(new Event('close', { bubbles: true, composed: true }));
114
119
  this.listController.clearSearch();
115
120
  if (this.$control) {
116
121
  this.$control.ariaExpanded = 'false';
@@ -1,11 +1,13 @@
1
+ var _a;
1
2
  import { __decorate } from "tslib";
2
3
  import { LitElement, isServer, html } from 'lit';
3
- import { property, query, state } from 'lit/decorators.js';
4
+ import { property, query } from 'lit/decorators.js';
4
5
  import { FormAssociated } from './mixins/form-associated.js';
5
6
  import { InternalsAttached } from './mixins/internals-attached.js';
6
7
  import { PopoverController } from './controllers/popover-controller.js';
7
8
  import { ListController } from './controllers/list-controller.js';
8
9
  import { MenuActions, getActionFromKey, getUpdatedIndex, scrollItemIntoView, } from './menu-utils.js';
10
+ const VALUE = Symbol('value');
9
11
  const Base = FormAssociated(InternalsAttached(LitElement));
10
12
  /**
11
13
  * @csspart field
@@ -23,15 +25,22 @@ export class Select extends Base {
23
25
  this._possibleItemTags = [];
24
26
  this._durations = { show: 0, hide: 0 };
25
27
  this._scrollPadding = 0;
26
- this.value = '';
27
- this.displayValue = '';
28
- this.placeholder = '';
29
- this.open = false;
30
- this.required = false;
31
28
  this.quick = false;
29
+ this.required = false;
30
+ this.error = false;
32
31
  this.align = 'bottom-start';
33
32
  this.alignStrategy = 'absolute';
34
33
  this.offset = 0;
34
+ /**
35
+ * Text to display in the field. Only set for SSR.
36
+ */
37
+ this.displayText = '';
38
+ this[_a] = '';
39
+ this.open = false;
40
+ this.lastUserSetValue = null;
41
+ this.lastUserSetSelectedIndex = null;
42
+ this.lastSelectedOption = null;
43
+ this.lastSelectedOptionRecords = [];
35
44
  this.popoverController = new PopoverController(this, {
36
45
  popover: () => this.$menu,
37
46
  trigger: () => this.$field,
@@ -66,6 +75,102 @@ export class Select extends Base {
66
75
  },
67
76
  wrapNavigation: () => false,
68
77
  });
78
+ this.#dispatchChangeEvent = () => {
79
+ this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
80
+ this.dispatchEvent(new Event('change', { bubbles: true }));
81
+ };
82
+ this.#handleOptionClick = (event) => {
83
+ const target = event.target;
84
+ const item = target.closest(this._possibleItemTags.join(','));
85
+ if (item && this.listController.items.includes(item)) {
86
+ if (this.selectItem(item)) {
87
+ this.#dispatchChangeEvent();
88
+ }
89
+ this.open = false;
90
+ }
91
+ };
92
+ this.#handleFocusOut = (event) => {
93
+ const relatedTarget = event.relatedTarget;
94
+ if (!this.contains(relatedTarget) && !this.$menu.contains(relatedTarget)) {
95
+ this.open = false;
96
+ }
97
+ };
98
+ }
99
+ static { _a = VALUE; }
100
+ static { this.shadowRootOptions = {
101
+ ...LitElement.shadowRootOptions,
102
+ delegatesFocus: true,
103
+ }; }
104
+ get value() {
105
+ return this[VALUE];
106
+ }
107
+ set value(value) {
108
+ if (isServer)
109
+ return;
110
+ this.lastUserSetValue = value;
111
+ this.select(value);
112
+ }
113
+ get options() {
114
+ return this.listController.items;
115
+ }
116
+ get selectedIndex() {
117
+ const selectedOptions = this.getSelectedOptions() ?? [];
118
+ if (selectedOptions.length > 0) {
119
+ return selectedOptions[0][1];
120
+ }
121
+ return -1;
122
+ }
123
+ set selectedIndex(index) {
124
+ this.lastUserSetSelectedIndex = index;
125
+ this.selectIndex(index);
126
+ }
127
+ get selectedOptions() {
128
+ return (this.getSelectedOptions() ?? []).map(([option]) => option);
129
+ }
130
+ connectedCallback() {
131
+ super.connectedCallback();
132
+ this.addEventListener('focusout', this.#handleFocusOut);
133
+ this.addEventListener('click', this.#handleOptionClick);
134
+ }
135
+ disconnectedCallback() {
136
+ super.disconnectedCallback();
137
+ this.removeEventListener('focusout', this.#handleFocusOut);
138
+ this.removeEventListener('click', this.#handleOptionClick);
139
+ }
140
+ async firstUpdated(changed) {
141
+ // If this has been handled on update already due to SSR, try again.
142
+ if (!this.lastSelectedOptionRecords.length) {
143
+ this.initUserSelection();
144
+ }
145
+ // Case for when the DOM is streaming, there are no children, and a child
146
+ // has [selected] set on it, we need to wait for DOM to render something.
147
+ if (!this.lastSelectedOptionRecords.length &&
148
+ !isServer &&
149
+ !this.options.length) {
150
+ setTimeout(() => {
151
+ this.updateValueAndDisplayText();
152
+ });
153
+ }
154
+ super.firstUpdated(changed);
155
+ }
156
+ update(changed) {
157
+ if (!this.hasUpdated) {
158
+ this.initUserSelection();
159
+ }
160
+ super.update(changed);
161
+ }
162
+ updated(changed) {
163
+ super.updated(changed);
164
+ if (changed.has('open')) {
165
+ if (this.open) {
166
+ this.popoverController.animateOpen();
167
+ this.#focusSelectedItemOrFirst();
168
+ }
169
+ else {
170
+ this.popoverController.animateClose();
171
+ this.listController.clearSearch();
172
+ }
173
+ }
69
174
  }
70
175
  render() {
71
176
  return html `${this.renderField()} ${this.renderMenu()}`;
@@ -96,50 +201,7 @@ export class Select extends Base {
96
201
  `;
97
202
  }
98
203
  renderFieldContent() {
99
- return html `<span part="value"
100
- >${this.displayValue || this.placeholder}</span
101
- >`;
102
- }
103
- connectedCallback() {
104
- super.connectedCallback();
105
- if (isServer)
106
- return;
107
- this.addEventListener('click', this.#handleOptionClick);
108
- this.addEventListener('focusout', this.#handleFocusOut);
109
- }
110
- disconnectedCallback() {
111
- super.disconnectedCallback();
112
- this.removeEventListener('click', this.#handleOptionClick);
113
- this.removeEventListener('focusout', this.#handleFocusOut);
114
- }
115
- updated(changed) {
116
- super.updated(changed);
117
- if (changed.has('value')) {
118
- this.#updateDisplayValue();
119
- this.#updateSelection();
120
- }
121
- if (changed.has('open')) {
122
- if (this.open) {
123
- this.popoverController.animateOpen();
124
- // Focus current item when opening
125
- const index = this.listController.items.findIndex((item) => (item.value || item.innerText) === this.value);
126
- if (index >= 0) {
127
- this.listController._focusItem(this.listController.items[index]);
128
- }
129
- else {
130
- this.listController.focusFirstItem();
131
- }
132
- }
133
- else {
134
- this.popoverController.animateClose();
135
- this.listController.clearSearch();
136
- }
137
- }
138
- }
139
- toggle() {
140
- if (this.disabled)
141
- return;
142
- this.open = !this.open;
204
+ return html `<span part="value">${this.displayText || html `&nbsp;`}</span>`;
143
205
  }
144
206
  handleFieldKeydown(event) {
145
207
  if (this.disabled)
@@ -159,11 +221,13 @@ export class Select extends Base {
159
221
  case MenuActions.PageDown:
160
222
  event.preventDefault();
161
223
  const nextIndex = getUpdatedIndex(currentIndex, maxIndex, action);
162
- this.#onOptionChange(nextIndex);
224
+ this.listController._focusItem(items[nextIndex]);
163
225
  return;
164
226
  case MenuActions.CloseSelect:
165
227
  event.preventDefault();
166
- this.#selectOption(currentIndex);
228
+ if (this.selectItem(items[currentIndex])) {
229
+ this.#dispatchChangeEvent();
230
+ }
167
231
  // intentional fallthrough
168
232
  case MenuActions.Close:
169
233
  event.preventDefault();
@@ -179,99 +243,115 @@ export class Select extends Base {
179
243
  return;
180
244
  }
181
245
  }
182
- #onOptionChange(index) {
183
- const items = this.listController.items;
184
- if (index >= 0 && index < items.length) {
185
- this.listController._focusItem(items[index]);
186
- }
187
- }
188
- #selectOption(index) {
189
- const items = this.listController.items;
190
- if (index >= 0 && index < items.length) {
191
- const item = items[index];
192
- const newValue = item.value || item.innerText;
193
- if (this.value !== newValue) {
194
- this.value = newValue;
195
- // According to https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event#event_type
196
- // the change and input events are just Event and should not include detail.
197
- this.dispatchEvent(new Event('input', { bubbles: true }));
198
- this.dispatchEvent(new Event('change', { bubbles: true }));
246
+ selectItem(item) {
247
+ const selectedOptions = this.getSelectedOptions() ?? [];
248
+ selectedOptions.forEach(([option]) => {
249
+ if (item !== option) {
250
+ option.selected = false;
199
251
  }
200
- this.open = false;
201
- }
252
+ });
253
+ item.selected = true;
254
+ return this.updateValueAndDisplayText();
202
255
  }
203
- #handleOptionClick(event) {
204
- const target = event.target;
205
- const item = target.closest(this._possibleItemTags.join(','));
206
- if (item && this.listController.items.includes(item)) {
207
- const index = this.listController.items.indexOf(item);
208
- this.#selectOption(index);
256
+ initUserSelection() {
257
+ if (this.lastUserSetValue && !this.lastSelectedOptionRecords.length) {
258
+ this.select(this.lastUserSetValue);
209
259
  }
210
- }
211
- #handleFocusOut(event) {
212
- const relatedTarget = event.relatedTarget;
213
- if (!this.contains(relatedTarget) && !this.$menu.contains(relatedTarget)) {
214
- this.open = false;
260
+ else if (this.lastUserSetSelectedIndex !== null &&
261
+ !this.lastSelectedOptionRecords.length) {
262
+ this.selectIndex(this.lastUserSetSelectedIndex);
263
+ }
264
+ else {
265
+ this.updateValueAndDisplayText();
215
266
  }
216
267
  }
217
- #updateDisplayValue() {
218
- if (isServer)
219
- return;
220
- // We need to wait for items to be available.
221
- // Using a microtask or just checking if items exist.
222
- // Since this is called in updated(), items might be available if children are slotted.
223
- const items = this.listController.items;
224
- const selectedItem = items.find((item) => (item.value || item.innerText) === this.value);
225
- if (selectedItem) {
226
- this.displayValue = selectedItem.innerText;
268
+ updateValueAndDisplayText() {
269
+ const selectedOptions = this.getSelectedOptions() ?? [];
270
+ let changed = false;
271
+ if (selectedOptions.length) {
272
+ const [firstSelectedOption] = selectedOptions[0];
273
+ changed = this.lastSelectedOption !== firstSelectedOption;
274
+ this.lastSelectedOption = firstSelectedOption;
275
+ this[VALUE] = firstSelectedOption.value;
276
+ this.displayText = firstSelectedOption.innerText;
227
277
  }
228
- else if (!this.value) {
229
- this.displayValue = '';
278
+ else {
279
+ changed = this.lastSelectedOption !== null;
280
+ this.lastSelectedOption = null;
281
+ this[VALUE] = '';
282
+ this.displayText = '';
230
283
  }
284
+ return changed;
231
285
  }
232
- // TODO: Store previously selected item to avoid looping through all items
233
- #updateSelection() {
286
+ getSelectedOptions() {
234
287
  const items = this.listController.items;
235
- items.forEach((item) => {
236
- const itemValue = item.value || item.innerText;
237
- item.selected = itemValue === this.value;
288
+ const records = [];
289
+ items.forEach((item, index) => {
290
+ if (item.selected) {
291
+ records.push([item, index]);
292
+ }
238
293
  });
294
+ this.lastSelectedOptionRecords = records;
295
+ return records.length ? records : null;
296
+ }
297
+ #dispatchChangeEvent;
298
+ #handleOptionClick;
299
+ #handleFocusOut;
300
+ #focusSelectedItemOrFirst() {
301
+ const selectedOptions = this.getSelectedOptions();
302
+ if (selectedOptions && selectedOptions.length > 0) {
303
+ const [item] = selectedOptions[0];
304
+ this.listController._focusItem(item);
305
+ }
306
+ else {
307
+ this.listController.focusFirstItem();
308
+ }
239
309
  }
240
- // TODO: Handle multiple selected items
241
310
  handleSlotChange() {
242
- const items = this.listController.items;
243
- if (!this.value && items.length > 0) {
244
- const selectedItem = items.find((item) => item.hasAttribute('selected'));
245
- if (selectedItem) {
246
- this.value = selectedItem.value || selectedItem.innerText;
247
- }
248
- else {
249
- const firstItem = items[0];
250
- this.value = firstItem.value || firstItem.innerText;
251
- }
311
+ // When slots change, check for initially selected items if value is not set
312
+ if (!this.value) {
313
+ this.updateValueAndDisplayText();
314
+ }
315
+ }
316
+ formResetCallback() {
317
+ this.reset();
318
+ }
319
+ formStateRestoreCallback(state) {
320
+ this.value = state;
321
+ }
322
+ select(value) {
323
+ const item = this.options.find((option) => option.value === value);
324
+ if (item) {
325
+ this.selectItem(item);
252
326
  }
253
- this.#updateDisplayValue();
254
- this.#updateSelection();
327
+ }
328
+ selectIndex(index) {
329
+ const item = this.options[index];
330
+ if (item) {
331
+ this.selectItem(item);
332
+ }
333
+ }
334
+ reset() {
335
+ for (const option of this.options) {
336
+ option.selected = option.hasAttribute('selected');
337
+ }
338
+ this.updateValueAndDisplayText();
339
+ }
340
+ toggle() {
341
+ if (this.disabled)
342
+ return;
343
+ this.open = !this.open;
255
344
  }
256
345
  }
257
346
  __decorate([
258
- property({ reflect: true })
259
- ], Select.prototype, "value", void 0);
260
- __decorate([
261
- state()
262
- ], Select.prototype, "displayValue", void 0);
263
- __decorate([
264
- property({ type: String })
265
- ], Select.prototype, "placeholder", void 0);
266
- __decorate([
267
- property({ type: Boolean, reflect: true })
268
- ], Select.prototype, "open", void 0);
347
+ property({ type: Boolean })
348
+ ], Select.prototype, "quick", void 0);
269
349
  __decorate([
270
350
  property({ type: Boolean, reflect: true })
271
351
  ], Select.prototype, "required", void 0);
272
352
  __decorate([
273
353
  property({ type: Boolean, reflect: true })
274
- ], Select.prototype, "quick", void 0);
354
+ ], Select.prototype, "error", void 0);
275
355
  __decorate([
276
356
  property({ reflect: true })
277
357
  ], Select.prototype, "align", void 0);
@@ -281,6 +361,18 @@ __decorate([
281
361
  __decorate([
282
362
  property({ type: Number, reflect: true })
283
363
  ], Select.prototype, "offset", void 0);
364
+ __decorate([
365
+ property({ attribute: 'display-text' })
366
+ ], Select.prototype, "displayText", void 0);
367
+ __decorate([
368
+ property()
369
+ ], Select.prototype, "value", null);
370
+ __decorate([
371
+ property({ type: Number, attribute: 'selected-index' })
372
+ ], Select.prototype, "selectedIndex", null);
373
+ __decorate([
374
+ property({ type: Boolean, reflect: true })
375
+ ], Select.prototype, "open", void 0);
284
376
  __decorate([
285
377
  query('[part="field"]')
286
378
  ], Select.prototype, "$field", void 0);
@@ -7,6 +7,9 @@ import { InternalsAttached, internals } from './mixins/internals-attached.js';
7
7
  import { PopoverController } from './controllers/popover-controller.js';
8
8
  let lastHidingTime = 0;
9
9
  const Base = Attachable(InternalsAttached(LitElement));
10
+ /**
11
+ * TODO: Check if $control controls a menu/popover and keep hidden when it is open.
12
+ */
10
13
  export class Tooltip extends Base {
11
14
  // Different from those in the popoverController, these timers are used to
12
15
  // manage the delay before showing/hiding the tooltip.
@@ -23,6 +26,7 @@ export class Tooltip extends Base {
23
26
  this._durations = { show: 100, hide: 100 };
24
27
  this.align = 'top';
25
28
  this.offset = 4;
29
+ this.forceInvisible = false;
26
30
  // Different from those in the popoverController, these timers are used to
27
31
  // manage the delay before showing/hiding the tooltip.
28
32
  this.#openTimer = null;
@@ -134,6 +138,9 @@ __decorate([
134
138
  __decorate([
135
139
  property({ type: Number, reflect: true })
136
140
  ], Tooltip.prototype, "offset", void 0);
141
+ __decorate([
142
+ property({ type: Boolean, reflect: true })
143
+ ], Tooltip.prototype, "forceInvisible", void 0);
137
144
  __decorate([
138
145
  query('slot')
139
146
  ], Tooltip.prototype, "$slot", void 0);
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const itemStyles = css `:host{border-radius:inherit;box-sizing:border-box;font:var(--md-sys-typography-body-large);text-overflow:ellipsis;-webkit-user-select:none;user-select:none;flex:1;align-items:center;gap:16px;min-height:48px;padding:12px;display:flex;position:relative;overflow:hidden}:host([multiline]){min-height:72px}[name=container]{border-radius:inherit}[name=container]::slotted(*){position:absolute;inset:0}.default-slot{display:inline}.default-slot,.text ::slotted(*){text-overflow:ellipsis;overflow:hidden}.text{flex-direction:column;flex:1;display:flex;overflow:hidden}`;
2
+ export const itemStyles = css `:host{border-radius:inherit;box-sizing:border-box;font:var(--md-sys-typography-body-large);text-overflow:ellipsis;-webkit-user-select:none;user-select:none;flex:1;align-items:center;gap:16px;min-height:48px;padding:12px;display:flex;position:relative}:host([multiline]){min-height:72px}[name=container]{border-radius:inherit}[name=container]::slotted(*){position:absolute;inset:0}.default-slot{display:inline}.default-slot,.text ::slotted(*){text-overflow:ellipsis;overflow:hidden}.text{flex-direction:column;flex:1;display:flex;overflow:hidden}`;
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const menuPartStyles = css `[part=menu]{background:var(--md-sys-color-surface-container);box-shadow:var(--md-sys-elevation-shadow-2);box-sizing:border-box;color:var(--md-sys-color-on-surface);height:inherit;max-height:inherit;max-width:inherit;min-width:inherit;opacity:0;-webkit-user-select:none;user-select:none;z-index:1000;border-radius:16px;padding:4px;inset:auto;overflow-y:auto;transform:scaleY(.4)}:host(:state(closed)) [part=menu]{display:none}:host(:state(opening)) [part=menu]{opacity:1;transition:opacity 67ms,transform var(--md-sys-motion-exp-effects-slow-duration)var(--md-sys-motion-exp-effects-slow);display:block;transform:scaleY(1)}:host(:state(opened)) [part=menu]{opacity:1;display:block;transform:scaleY(1)}:host(:state(closing)) [part=menu]{opacity:0;transition:opacity var(--md-sys-motion-exp-effects-default-duration),transform var(--md-sys-motion-exp-effects-default-duration)var(--md-sys-motion-exp-effects-default);transform:scaleY(.4)}[part=items]{opacity:0;flex-direction:column;gap:2px;display:flex}:host(:state(opening)) [part=items]{opacity:1;transition:opacity 67ms linear 67ms}:host(:state(opened)) [part=items]{opacity:1}:host(:state(closing)) [part=items]{opacity:0;transition:opacity 67ms}`;
2
+ export const menuPartStyles = css `[part=menu]{background:var(--md-sys-color-surface-container);box-shadow:var(--md-sys-elevation-shadow-2);box-sizing:border-box;color:var(--md-sys-color-on-surface);height:inherit;max-height:inherit;max-width:inherit;min-width:inherit;opacity:0;-webkit-user-select:none;user-select:none;z-index:1000;border-radius:16px;outline:0;padding:4px;inset:auto;overflow-y:auto;transform:scaleY(.4)}:host(:state(closed)) [part=menu]{display:none}:host(:state(opening)) [part=menu]{opacity:1;transition:opacity 67ms,transform var(--md-sys-motion-exp-effects-slow-duration)var(--md-sys-motion-exp-effects-slow);display:block;transform:scaleY(1)}:host(:state(opened)) [part=menu]{opacity:1;display:block;transform:scaleY(1)}:host(:state(closing)) [part=menu]{opacity:0;transition:opacity var(--md-sys-motion-exp-effects-default-duration),transform var(--md-sys-motion-exp-effects-default-duration)var(--md-sys-motion-exp-effects-default);transform:scaleY(.4)}[part=items]{opacity:0;flex-direction:column;gap:2px;display:flex}:host(:state(opening)) [part=items]{opacity:1;transition:opacity 67ms linear 67ms}:host(:state(opened)) [part=items]{opacity:1}:host(:state(closing)) [part=items]{opacity:0;transition:opacity 67ms}`;
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const menuStyles = css `:host{outline:0;min-width:112px;display:contents}:host([alignstrategy=fixed]){position:fixed}`;
2
+ export const menuStyles = css `:host{min-width:112px;display:contents}:host([alignstrategy=fixed]){position:fixed}`;
@@ -13,7 +13,6 @@ export class M3Select extends Select {
13
13
  this._scrollPadding = 4;
14
14
  this.label = '';
15
15
  this.supportingText = '';
16
- this.error = false;
17
16
  this.fieldFocused = false;
18
17
  }
19
18
  }
@@ -23,9 +22,6 @@ __decorate([
23
22
  __decorate([
24
23
  property({ type: String })
25
24
  ], M3Select.prototype, "supportingText", void 0);
26
- __decorate([
27
- property({ type: Boolean, reflect: true })
28
- ], M3Select.prototype, "error", void 0);
29
25
  __decorate([
30
26
  state()
31
27
  ], M3Select.prototype, "fieldFocused", void 0);
@@ -1,2 +1,2 @@
1
1
  import { css } from 'lit';
2
- export const tooltipStyles = css `:host{background-color:var(--md-sys-color-inverse-surface);box-sizing:border-box;color:#0000;font:var(--md-sys-typography-body-small);max-width:var(--_max-width,300px);opacity:0;pointer-events:none;z-index:9999;border-radius:4px;align-items:center;width:max-content;min-height:24px;padding:4px 8px;display:flex;position:absolute;top:0;left:0;transform:scaleY(.4)}:host(:state(closed)){display:none}:host(:state(opening)){color:var(--md-sys-color-inverse-on-surface);opacity:1;pointer-events:auto;transition:color linear 67ms 67ms,opacity var(--md-sys-motion-exp-effects-fast-duration)var(--md-sys-motion-exp-effects-fast),transform var(--md-sys-motion-exp-effects-fast-duration)var(--md-sys-motion-exp-effects-fast);transform:scaleY(1)}:host(:state(opened)){color:var(--md-sys-color-inverse-on-surface);opacity:1;pointer-events:auto;transform:scaleY(1)}:host(:state(closing)){color:#0000;opacity:0;transition:color linear 67ms,opacity var(--md-sys-motion-exp-effects-fast-duration)var(--md-sys-motion-exp-effects-fast),transform var(--md-sys-motion-exp-effects-fast-duration)var(--md-sys-motion-exp-effects-fast);transform:scaleY(.4)}`;
2
+ export const tooltipStyles = css `:host{background-color:var(--md-sys-color-inverse-surface);box-sizing:border-box;color:#0000;font:var(--md-sys-typography-body-small);max-width:var(--_max-width,300px);opacity:0;pointer-events:none;z-index:800;border-radius:4px;align-items:center;width:max-content;min-height:24px;padding:4px 8px;display:flex;position:absolute;top:0;left:0;transform:scaleY(.4)}:host(:state(closed)){display:none}:host(:state(opening):not([forceinvisible])){color:var(--md-sys-color-inverse-on-surface);opacity:1;pointer-events:auto;transition:color linear 67ms 67ms,opacity var(--md-sys-motion-exp-effects-fast-duration)var(--md-sys-motion-exp-effects-fast),transform var(--md-sys-motion-exp-effects-fast-duration)var(--md-sys-motion-exp-effects-fast);transform:scaleY(1)}:host(:state(opened):not([forceinvisible])){color:var(--md-sys-color-inverse-on-surface);opacity:1;pointer-events:auto;transform:scaleY(1)}:host(:state(closing):not([forceinvisible])){color:#0000;opacity:0;transition:color linear 67ms,opacity var(--md-sys-motion-exp-effects-fast-duration)var(--md-sys-motion-exp-effects-fast),transform var(--md-sys-motion-exp-effects-fast-duration)var(--md-sys-motion-exp-effects-fast);transform:scaleY(.4)}`;