@vollowx/seele 0.13.5 → 0.13.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/custom-elements.json +1256 -115
- package/package.json +22 -14
- package/src/all.d.ts +34 -0
- package/src/base/autocomplete.d.ts +56 -0
- package/src/base/autocomplete.js +75 -87
- package/src/base/button.d.ts +13 -0
- package/src/base/button.js +21 -19
- package/src/base/checkbox.d.ts +18 -0
- package/src/base/checkbox.js +39 -34
- package/src/base/controllers/list-controller.d.ts +37 -0
- package/src/base/controllers/list-controller.js +23 -15
- package/src/base/controllers/popover-controller.d.ts +35 -0
- package/src/base/controllers/popover-controller.js +37 -29
- package/src/base/dialog.d.ts +20 -0
- package/src/base/dialog.js +11 -9
- package/src/base/field.d.ts +3 -0
- package/src/base/input.d.ts +44 -0
- package/src/base/input.js +57 -65
- package/src/base/item.d.ts +7 -0
- package/src/base/item.js +2 -1
- package/src/base/list-item.d.ts +15 -0
- package/src/base/list-item.js +22 -22
- package/src/base/list.d.ts +54 -0
- package/src/base/list.js +69 -55
- package/src/base/menu-item.d.ts +6 -0
- package/src/base/menu-item.js +4 -3
- package/src/base/menu.d.ts +76 -0
- package/src/base/menu.js +135 -143
- package/src/base/mixins/attachable.d.ts +9 -0
- package/src/base/mixins/attachable.js +22 -18
- package/src/base/mixins/focus-delegated.d.ts +5 -0
- package/src/base/mixins/focus-delegated.js +6 -8
- package/src/base/mixins/form-associated.d.ts +15 -0
- package/src/base/mixins/form-associated.js +11 -18
- package/src/base/mixins/internals-attached.d.ts +6 -0
- package/src/base/mixins/internals-attached.js +1 -1
- package/src/base/option.d.ts +9 -0
- package/src/base/option.js +7 -8
- package/src/base/radio.d.ts +13 -0
- package/src/base/radio.js +49 -42
- package/src/base/select.d.ts +116 -0
- package/src/base/select.js +130 -128
- package/src/base/slider.d.ts +75 -0
- package/src/base/slider.js +115 -118
- package/src/base/tab-panel.d.ts +9 -0
- package/src/base/tab-panel.js +11 -11
- package/src/base/tab.d.ts +18 -0
- package/src/base/tab.js +25 -24
- package/src/base/tabs.d.ts +19 -0
- package/src/base/tabs.js +84 -81
- package/src/base/toggle-button.d.ts +47 -0
- package/src/base/toggle-button.js +56 -52
- package/src/base/tooltip.d.ts +37 -0
- package/src/base/tooltip.js +70 -65
- package/src/core/decorators.d.ts +2 -0
- package/src/core/decorators.js +4 -3
- package/src/core/focus-visible.d.ts +2 -0
- package/src/core/focus-visible.js +4 -4
- package/src/core/shared.d.ts +1 -0
- package/src/core/unique-id.d.ts +4 -0
- package/src/core/unique-id.js +2 -1
- package/src/m3/autocomplete/autocomplete.d.ts +8 -0
- package/src/m3/autocomplete/autocomplete.js +10 -10
- package/src/m3/badge/badge.d.ts +12 -0
- package/src/m3/badge/badge.js +24 -37
- package/src/m3/button/common-button-toggle.d.ts +31 -0
- package/src/m3/button/common-button-toggle.js +44 -41
- package/src/m3/button/common-button.d.ts +29 -0
- package/src/m3/button/common-button.js +40 -40
- package/src/m3/button/icon-button-toggle.d.ts +24 -0
- package/src/m3/button/icon-button-toggle.js +35 -32
- package/src/m3/button/icon-button.d.ts +23 -0
- package/src/m3/button/icon-button.js +33 -31
- package/src/m3/button-group/connected-button-group.d.ts +19 -0
- package/src/m3/button-group/connected-button-group.js +26 -24
- package/src/m3/button-group/standard-button-group.d.ts +24 -0
- package/src/m3/button-group/standard-button-group.js +71 -65
- package/src/m3/checkbox/checkbox.d.ts +25 -0
- package/src/m3/checkbox/checkbox.js +23 -22
- package/src/m3/dialog/dialog-spring.d.ts +45 -0
- package/src/m3/dialog/dialog-spring.js +83 -86
- package/src/m3/dialog/dialog.d.ts +46 -0
- package/src/m3/dialog/dialog.js +90 -117
- package/src/m3/divider/divider.d.ts +13 -0
- package/src/m3/divider/divider.js +20 -33
- package/src/m3/fab/fab.d.ts +23 -0
- package/src/m3/fab/fab.js +24 -23
- package/src/m3/field/field.d.ts +28 -0
- package/src/m3/field/field.js +40 -55
- package/src/m3/field/filled-field.d.ts +11 -0
- package/src/m3/field/filled-field.js +7 -11
- package/src/m3/field/outlined-field.d.ts +11 -0
- package/src/m3/field/outlined-field.js +8 -12
- package/src/m3/focus-ring/focus-ring.d.ts +32 -0
- package/src/m3/focus-ring/focus-ring.js +38 -23
- package/src/m3/item/item.d.ts +31 -0
- package/src/m3/item/item.js +32 -17
- package/src/m3/list/list-item.d.ts +22 -0
- package/src/m3/list/list-item.js +18 -16
- package/src/m3/list/list.d.ts +15 -0
- package/src/m3/list/list.js +16 -15
- package/src/m3/loading-indicator/loading-indicator.d.ts +26 -0
- package/src/m3/loading-indicator/loading-indicator.js +113 -161
- package/src/m3/menu/menu-item.d.ts +15 -0
- package/src/m3/menu/menu-item.js +10 -4
- package/src/m3/menu/menu.d.ts +22 -0
- package/src/m3/menu/menu.js +20 -18
- package/src/m3/radio/radio-styles.css.js +1 -1
- package/src/m3/radio/radio.d.ts +17 -0
- package/src/m3/radio/radio.js +22 -11
- package/src/m3/ripple/ripple.d.ts +43 -0
- package/src/m3/ripple/ripple.js +82 -89
- package/src/m3/select/filled-select.d.ts +16 -0
- package/src/m3/select/filled-select.js +12 -10
- package/src/m3/select/option.d.ts +15 -0
- package/src/m3/select/option.js +10 -4
- package/src/m3/select/outlined-select.d.ts +16 -0
- package/src/m3/select/outlined-select.js +12 -10
- package/src/m3/select/select.d.ts +13 -0
- package/src/m3/select/select.js +16 -16
- package/src/m3/slider/slider.d.ts +20 -0
- package/src/m3/slider/slider.js +32 -26
- package/src/m3/switch/switch.d.ts +27 -0
- package/src/m3/switch/switch.js +62 -53
- package/src/m3/system/motion.d.ts +12 -0
- package/src/m3/system/motion.js +16 -9
- package/src/m3/tab/tab-panel.d.ts +9 -0
- package/src/m3/tab/tab-panel.js +6 -9
- package/src/m3/tab/tab.d.ts +19 -0
- package/src/m3/tab/tab.js +14 -12
- package/src/m3/tab/tabs.d.ts +25 -0
- package/src/m3/tab/tabs.js +34 -30
- package/src/m3/text-field/filled-text-field.d.ts +13 -0
- package/src/m3/text-field/filled-text-field.js +15 -20
- package/src/m3/text-field/outlined-text-field.d.ts +13 -0
- package/src/m3/text-field/outlined-text-field.js +15 -20
- package/src/m3/toolbar/toolbar.d.ts +26 -0
- package/src/m3/toolbar/toolbar.js +28 -25
- package/src/m3/tooltip/tooltip.d.ts +19 -0
- package/src/m3/tooltip/tooltip.js +15 -14
- package/src/win98/button/button.d.ts +13 -0
- package/src/win98/button/button.js +13 -11
- package/src/win98/button/radio.d.ts +3 -0
- package/src/win98/button/radio.js +5 -4
- package/src/win98/radio/radio.d.ts +3 -0
- package/src/win98/radio/radio.js +5 -4
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LitElement, PropertyValues } from 'lit';
|
|
2
|
+
declare const Radio_base: Constructor<import("./mixins/form-associated.js").FormAssociatedInterface> & Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
|
|
3
|
+
export declare class Radio extends Radio_base {
|
|
4
|
+
#private;
|
|
5
|
+
value: string;
|
|
6
|
+
checked: boolean;
|
|
7
|
+
constructor();
|
|
8
|
+
connectedCallback(): void;
|
|
9
|
+
disconnectedCallback(): void;
|
|
10
|
+
protected updated(changedProperties: PropertyValues<this>): void;
|
|
11
|
+
formResetCallback(): void;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
package/src/base/radio.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
var _a;
|
|
2
|
+
import { __decorate } from "tslib";
|
|
2
3
|
import { LitElement } from 'lit';
|
|
3
4
|
import { property } from 'lit/decorators.js';
|
|
4
5
|
import { FormAssociated } from './mixins/form-associated.js';
|
|
@@ -8,8 +9,11 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
|
|
|
8
9
|
static #registry = new Map();
|
|
9
10
|
#currentScope;
|
|
10
11
|
#currentName;
|
|
11
|
-
constructor(){
|
|
12
|
-
super()
|
|
12
|
+
constructor() {
|
|
13
|
+
super();
|
|
14
|
+
this.#currentScope = null;
|
|
15
|
+
this.#currentName = '';
|
|
16
|
+
this.checked = false;
|
|
13
17
|
this[internals].role = 'radio';
|
|
14
18
|
}
|
|
15
19
|
connectedCallback() {
|
|
@@ -37,24 +41,25 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
|
|
|
37
41
|
}
|
|
38
42
|
this[internals].setFormValue(this.checked ? this.value : null);
|
|
39
43
|
this.#updateGroupTabIndices();
|
|
40
|
-
this.dispatchEvent(new Event('change', {
|
|
41
|
-
bubbles: true,
|
|
42
|
-
composed: true
|
|
43
|
-
}));
|
|
44
|
+
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
44
45
|
}
|
|
45
|
-
if (changedProperties.has('disabled') || changedProperties.has('checked'))
|
|
46
|
+
if (changedProperties.has('disabled') || changedProperties.has('checked'))
|
|
47
|
+
this.#updateAriaState();
|
|
46
48
|
}
|
|
47
49
|
#handleClick() {
|
|
48
|
-
if (this.disabled || this.checked)
|
|
50
|
+
if (this.disabled || this.checked)
|
|
51
|
+
return;
|
|
49
52
|
this.checked = true;
|
|
50
53
|
this.focus();
|
|
51
54
|
}
|
|
52
55
|
#handleKeyDown(event) {
|
|
53
|
-
if (this.disabled)
|
|
54
|
-
|
|
56
|
+
if (this.disabled)
|
|
57
|
+
return;
|
|
58
|
+
switch (event.key) {
|
|
55
59
|
case ' ':
|
|
56
60
|
event.preventDefault();
|
|
57
|
-
if (!this.checked)
|
|
61
|
+
if (!this.checked)
|
|
62
|
+
this.checked = true;
|
|
58
63
|
break;
|
|
59
64
|
case 'ArrowDown':
|
|
60
65
|
case 'ArrowRight':
|
|
@@ -72,14 +77,15 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
|
|
|
72
77
|
return this.form ?? this.getRootNode();
|
|
73
78
|
}
|
|
74
79
|
#registerToGroup() {
|
|
75
|
-
if (!this.name)
|
|
80
|
+
if (!this.name)
|
|
81
|
+
return;
|
|
76
82
|
const scope = this.#getScope();
|
|
77
83
|
this.#currentScope = scope;
|
|
78
84
|
this.#currentName = this.name;
|
|
79
|
-
let scopeMap =
|
|
85
|
+
let scopeMap = _a.#registry.get(scope);
|
|
80
86
|
if (!scopeMap) {
|
|
81
87
|
scopeMap = new Map();
|
|
82
|
-
|
|
88
|
+
_a.#registry.set(scope, scopeMap);
|
|
83
89
|
}
|
|
84
90
|
let group = scopeMap.get(this.name);
|
|
85
91
|
if (!group) {
|
|
@@ -90,51 +96,56 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
|
|
|
90
96
|
this.#updateGroupTabIndices(group);
|
|
91
97
|
}
|
|
92
98
|
#unregisterFromGroup() {
|
|
93
|
-
if (!this.#currentScope || !this.#currentName)
|
|
94
|
-
|
|
99
|
+
if (!this.#currentScope || !this.#currentName)
|
|
100
|
+
return;
|
|
101
|
+
const scopeMap = _a.#registry.get(this.#currentScope);
|
|
95
102
|
if (scopeMap) {
|
|
96
103
|
const group = scopeMap.get(this.#currentName);
|
|
97
104
|
if (group) {
|
|
98
105
|
group.delete(this);
|
|
99
106
|
if (group.size === 0) {
|
|
100
107
|
scopeMap.delete(this.#currentName);
|
|
101
|
-
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
102
110
|
this.#updateGroupTabIndices(group);
|
|
103
111
|
}
|
|
104
112
|
}
|
|
105
|
-
if (scopeMap.size === 0)
|
|
113
|
+
if (scopeMap.size === 0)
|
|
114
|
+
_a.#registry.delete(this.#currentScope);
|
|
106
115
|
}
|
|
107
116
|
this.#currentScope = null;
|
|
108
117
|
this.#currentName = '';
|
|
109
118
|
}
|
|
110
119
|
#getGroupRadios() {
|
|
111
|
-
if (!this.name)
|
|
112
|
-
this
|
|
113
|
-
];
|
|
120
|
+
if (!this.name)
|
|
121
|
+
return [this];
|
|
114
122
|
const scope = this.#getScope();
|
|
115
|
-
const group =
|
|
116
|
-
return group ? Array.from(group) : [
|
|
117
|
-
this
|
|
118
|
-
];
|
|
123
|
+
const group = _a.#registry.get(scope)?.get(this.name);
|
|
124
|
+
return group ? Array.from(group) : [this];
|
|
119
125
|
}
|
|
120
126
|
#uncheckSiblings() {
|
|
121
127
|
const radios = this.#getGroupRadios();
|
|
122
|
-
for (const radio of radios)
|
|
128
|
+
for (const radio of radios)
|
|
129
|
+
if (radio !== this && radio.checked)
|
|
130
|
+
radio.checked = false;
|
|
123
131
|
}
|
|
124
132
|
#updateGroupTabIndices(groupSet) {
|
|
125
133
|
const radios = groupSet ? Array.from(groupSet) : this.#getGroupRadios();
|
|
126
|
-
if (radios.length === 0)
|
|
127
|
-
|
|
134
|
+
if (radios.length === 0)
|
|
135
|
+
return;
|
|
136
|
+
const hasChecked = radios.some((r) => r.checked && !r.disabled);
|
|
128
137
|
let enabledFound = false;
|
|
129
|
-
for (const radio of radios){
|
|
138
|
+
for (const radio of radios) {
|
|
130
139
|
const active = !radio.disabled && (hasChecked ? radio.checked : !enabledFound);
|
|
131
|
-
if (active)
|
|
140
|
+
if (active)
|
|
141
|
+
enabledFound = true;
|
|
132
142
|
radio.tabIndex = active ? 0 : -1;
|
|
133
143
|
}
|
|
134
144
|
}
|
|
135
145
|
#navigateGroup(direction) {
|
|
136
|
-
const radios = this.#getGroupRadios().filter((r)
|
|
137
|
-
if (radios.length <= 1)
|
|
146
|
+
const radios = this.#getGroupRadios().filter((r) => !r.disabled);
|
|
147
|
+
if (radios.length <= 1)
|
|
148
|
+
return;
|
|
138
149
|
const currentIndex = radios.indexOf(this);
|
|
139
150
|
const nextIndex = (currentIndex + direction + radios.length) % radios.length;
|
|
140
151
|
const targetRadio = radios[nextIndex];
|
|
@@ -149,14 +160,10 @@ export class Radio extends FormAssociated(InternalsAttached(LitElement)) {
|
|
|
149
160
|
this.checked = this.hasAttribute('checked');
|
|
150
161
|
}
|
|
151
162
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
})
|
|
163
|
+
_a = Radio;
|
|
164
|
+
__decorate([
|
|
165
|
+
property({ type: String })
|
|
156
166
|
], Radio.prototype, "value", void 0);
|
|
157
|
-
|
|
158
|
-
property({
|
|
159
|
-
type: Boolean,
|
|
160
|
-
reflect: true
|
|
161
|
-
})
|
|
167
|
+
__decorate([
|
|
168
|
+
property({ type: Boolean, reflect: true })
|
|
162
169
|
], Radio.prototype, "checked", void 0);
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { LitElement, PropertyValues } from 'lit';
|
|
2
|
+
import type { Placement, Strategy } from '@floating-ui/dom';
|
|
3
|
+
import type { Field } from './field.js';
|
|
4
|
+
import type { Menu, MenuItemFocusEvent, MenuSelectEvent } from './menu.js';
|
|
5
|
+
import type { Option } from './option.js';
|
|
6
|
+
declare const VALUE: unique symbol;
|
|
7
|
+
declare const Base: Constructor<import("./mixins/form-associated.js").FormAssociatedInterface> & Constructor<import("./mixins/focus-delegated.js").FocusDelegatedInterface> & Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
|
|
8
|
+
/**
|
|
9
|
+
* @csspart field
|
|
10
|
+
* @csspart menu
|
|
11
|
+
* @csspart items
|
|
12
|
+
*
|
|
13
|
+
* @fires {Event} change - Fires when the value is changed.
|
|
14
|
+
* @fires {Event} input - Fires when the value is changed.
|
|
15
|
+
*
|
|
16
|
+
* TODO: Render multiple values
|
|
17
|
+
* FIXME: `aria-expanded` set twice by both Lit and Menu
|
|
18
|
+
*/
|
|
19
|
+
export declare class Select extends Base {
|
|
20
|
+
#private;
|
|
21
|
+
required: boolean;
|
|
22
|
+
error: boolean;
|
|
23
|
+
quick: boolean;
|
|
24
|
+
offset: number;
|
|
25
|
+
align: Placement;
|
|
26
|
+
alignStrategy: Strategy;
|
|
27
|
+
open: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Text to display in the field. Only set for SSR.
|
|
30
|
+
*/
|
|
31
|
+
displayText: string;
|
|
32
|
+
get value(): string;
|
|
33
|
+
set value(value: string);
|
|
34
|
+
[VALUE]: string;
|
|
35
|
+
get $options(): Option[];
|
|
36
|
+
get selectedIndex(): number;
|
|
37
|
+
set selectedIndex(index: number);
|
|
38
|
+
get selectedOptions(): Option[];
|
|
39
|
+
$field: Field;
|
|
40
|
+
$menu: Menu;
|
|
41
|
+
private lastUserSetValue;
|
|
42
|
+
private lastUserSetSelectedIndex;
|
|
43
|
+
private lastSelectedOption;
|
|
44
|
+
private lastSelectedOptionRecords;
|
|
45
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
46
|
+
/**
|
|
47
|
+
* Example content:
|
|
48
|
+
*
|
|
49
|
+
* ```html
|
|
50
|
+
* <your-field
|
|
51
|
+
* id="field"
|
|
52
|
+
* part="field"
|
|
53
|
+
* @click=${this.toggle}
|
|
54
|
+
* @keydown=${this.handleFieldKeydown}
|
|
55
|
+
* tabindex=${this.disabled ? '-1' : '0'}
|
|
56
|
+
* role="combobox"
|
|
57
|
+
* aria-haspopup="listbox"
|
|
58
|
+
* aria-expanded=${this.open}
|
|
59
|
+
* aria-controls="menu"
|
|
60
|
+
* aria-disabled=${this.disabled}
|
|
61
|
+
* aria-required=${this.required}
|
|
62
|
+
* >
|
|
63
|
+
* ${this.renderFieldContent()}
|
|
64
|
+
* </your-field>
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
protected renderField(): import("lit-html").TemplateResult<1>;
|
|
68
|
+
/**
|
|
69
|
+
* Example content:
|
|
70
|
+
*
|
|
71
|
+
* ```html
|
|
72
|
+
* <your-menu
|
|
73
|
+
* id="menu"
|
|
74
|
+
* for="field"
|
|
75
|
+
* type="listbox"
|
|
76
|
+
* data-tabindex="-1"
|
|
77
|
+
* ?quick="${this.quick}"
|
|
78
|
+
* offset="${this.offset}"
|
|
79
|
+
* align="${this.align}"
|
|
80
|
+
* align-strategy="${this.alignStrategy}"
|
|
81
|
+
* keep-open-blur
|
|
82
|
+
* no-focus-control
|
|
83
|
+
* ?open="${this.open}"
|
|
84
|
+
* @item-focus="${this.handleMenuItemFocus}"
|
|
85
|
+
* @select="${this.handleMenuSelect}"
|
|
86
|
+
* >
|
|
87
|
+
* <slot part="items" @slotchange=${this.handleSlotChange}></slot>
|
|
88
|
+
* </your-menu>
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
protected renderMenu(): import("lit-html").TemplateResult<1>;
|
|
92
|
+
protected renderFieldContent(): import("lit-html").TemplateResult<1>;
|
|
93
|
+
constructor();
|
|
94
|
+
protected firstUpdated(changed: PropertyValues<Select>): Promise<void>;
|
|
95
|
+
protected update(changed: PropertyValues<Select>): void;
|
|
96
|
+
protected updated(changed: PropertyValues): void;
|
|
97
|
+
/**
|
|
98
|
+
* TODO: Handle clear action
|
|
99
|
+
*/
|
|
100
|
+
protected _handleFieldKeydown(event: KeyboardEvent): void;
|
|
101
|
+
protected _handleMenuSelect(event: MenuSelectEvent): void;
|
|
102
|
+
protected _handleMenuItemFocus(event: MenuItemFocusEvent): void;
|
|
103
|
+
protected _handleFocusOut(event: FocusEvent): void;
|
|
104
|
+
protected _handleSlotChange(): void;
|
|
105
|
+
private selectItem;
|
|
106
|
+
private initUserSelection;
|
|
107
|
+
private updateValueAndDisplayText;
|
|
108
|
+
private getSelectedOptions;
|
|
109
|
+
formResetCallback(): void;
|
|
110
|
+
formStateRestoreCallback(state: string): void;
|
|
111
|
+
select(value: string): void;
|
|
112
|
+
selectIndex(index: number): void;
|
|
113
|
+
reset(): void;
|
|
114
|
+
toggle(): void;
|
|
115
|
+
}
|
|
116
|
+
export {};
|
package/src/base/select.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
var _a;
|
|
2
|
+
import { __decorate } from "tslib";
|
|
2
3
|
import { LitElement, isServer, html } from 'lit';
|
|
3
4
|
import { property, query } from 'lit/decorators.js';
|
|
4
5
|
import { InternalsAttached } from './mixins/internals-attached.js';
|
|
@@ -16,12 +17,15 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
16
17
|
*
|
|
17
18
|
* TODO: Render multiple values
|
|
18
19
|
* FIXME: `aria-expanded` set twice by both Lit and Menu
|
|
19
|
-
*/
|
|
20
|
+
*/
|
|
21
|
+
export class Select extends Base {
|
|
22
|
+
static { _a = VALUE; }
|
|
20
23
|
get value() {
|
|
21
24
|
return this[VALUE];
|
|
22
25
|
}
|
|
23
26
|
set value(value) {
|
|
24
|
-
if (isServer)
|
|
27
|
+
if (isServer)
|
|
28
|
+
return;
|
|
25
29
|
this.lastUserSetValue = value;
|
|
26
30
|
this.select(value);
|
|
27
31
|
}
|
|
@@ -40,76 +44,88 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
40
44
|
this.selectIndex(index);
|
|
41
45
|
}
|
|
42
46
|
get selectedOptions() {
|
|
43
|
-
return (this.getSelectedOptions() ?? []).map(([option])=>option);
|
|
47
|
+
return (this.getSelectedOptions() ?? []).map(([option]) => option);
|
|
44
48
|
}
|
|
45
49
|
render() {
|
|
46
|
-
return html`${this.renderField()}${this.renderMenu()}`;
|
|
50
|
+
return html `${this.renderField()}${this.renderMenu()}`;
|
|
47
51
|
}
|
|
48
52
|
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
53
|
+
* Example content:
|
|
54
|
+
*
|
|
55
|
+
* ```html
|
|
56
|
+
* <your-field
|
|
57
|
+
* id="field"
|
|
58
|
+
* part="field"
|
|
59
|
+
* @click=${this.toggle}
|
|
60
|
+
* @keydown=${this.handleFieldKeydown}
|
|
61
|
+
* tabindex=${this.disabled ? '-1' : '0'}
|
|
62
|
+
* role="combobox"
|
|
63
|
+
* aria-haspopup="listbox"
|
|
64
|
+
* aria-expanded=${this.open}
|
|
65
|
+
* aria-controls="menu"
|
|
66
|
+
* aria-disabled=${this.disabled}
|
|
67
|
+
* aria-required=${this.required}
|
|
68
|
+
* >
|
|
69
|
+
* ${this.renderFieldContent()}
|
|
70
|
+
* </your-field>
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
renderField() {
|
|
74
|
+
return html ``;
|
|
70
75
|
}
|
|
71
76
|
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
77
|
+
* Example content:
|
|
78
|
+
*
|
|
79
|
+
* ```html
|
|
80
|
+
* <your-menu
|
|
81
|
+
* id="menu"
|
|
82
|
+
* for="field"
|
|
83
|
+
* type="listbox"
|
|
84
|
+
* data-tabindex="-1"
|
|
85
|
+
* ?quick="${this.quick}"
|
|
86
|
+
* offset="${this.offset}"
|
|
87
|
+
* align="${this.align}"
|
|
88
|
+
* align-strategy="${this.alignStrategy}"
|
|
89
|
+
* keep-open-blur
|
|
90
|
+
* no-focus-control
|
|
91
|
+
* ?open="${this.open}"
|
|
92
|
+
* @item-focus="${this.handleMenuItemFocus}"
|
|
93
|
+
* @select="${this.handleMenuSelect}"
|
|
94
|
+
* >
|
|
95
|
+
* <slot part="items" @slotchange=${this.handleSlotChange}></slot>
|
|
96
|
+
* </your-menu>
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
renderMenu() {
|
|
100
|
+
return html ``;
|
|
95
101
|
}
|
|
96
102
|
renderFieldContent() {
|
|
97
|
-
return html`<span part="value">${this.displayText || html` `}</span>`;
|
|
103
|
+
return html `<span part="value">${this.displayText || html ` `}</span>`;
|
|
98
104
|
}
|
|
99
|
-
constructor(){
|
|
100
|
-
super()
|
|
101
|
-
|
|
102
|
-
this.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
constructor() {
|
|
106
|
+
super();
|
|
107
|
+
// Form-related
|
|
108
|
+
this.required = false;
|
|
109
|
+
// Passed to field
|
|
110
|
+
this.error = false;
|
|
111
|
+
// Passed to menu
|
|
112
|
+
this.quick = false;
|
|
113
|
+
this.offset = 0;
|
|
114
|
+
this.align = 'bottom-start';
|
|
115
|
+
this.alignStrategy = 'absolute';
|
|
116
|
+
this.open = false;
|
|
117
|
+
/**
|
|
118
|
+
* Text to display in the field. Only set for SSR.
|
|
119
|
+
*/
|
|
120
|
+
this.displayText = '';
|
|
121
|
+
this[_a] = '';
|
|
122
|
+
this.lastUserSetValue = null;
|
|
123
|
+
this.lastUserSetSelectedIndex = null;
|
|
124
|
+
this.lastSelectedOption = null;
|
|
125
|
+
this.lastSelectedOptionRecords = [];
|
|
126
|
+
this.#dispatchChangeEvent = () => {
|
|
127
|
+
this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
128
|
+
this.dispatchEvent(new Event('change', { bubbles: true }));
|
|
113
129
|
};
|
|
114
130
|
if (!isServer) {
|
|
115
131
|
this.addEventListener('focusout', this._handleFocusOut);
|
|
@@ -122,8 +138,10 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
122
138
|
}
|
|
123
139
|
// Case for when the DOM is streaming, there are no children, and a child
|
|
124
140
|
// has [selected] set on it, we need to wait for DOM to render something.
|
|
125
|
-
if (!this.lastSelectedOptionRecords.length &&
|
|
126
|
-
|
|
141
|
+
if (!this.lastSelectedOptionRecords.length &&
|
|
142
|
+
!isServer &&
|
|
143
|
+
!this.$options.length) {
|
|
144
|
+
setTimeout(() => {
|
|
127
145
|
this.updateValueAndDisplayText();
|
|
128
146
|
}, 0);
|
|
129
147
|
}
|
|
@@ -140,18 +158,21 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
140
158
|
if (changed.has('open')) {
|
|
141
159
|
if (this.open) {
|
|
142
160
|
this.#focusSelectedItemOrFirst();
|
|
143
|
-
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
144
163
|
this.$field.setAttribute('aria-activedescendant', '');
|
|
145
164
|
}
|
|
146
165
|
}
|
|
147
166
|
}
|
|
148
167
|
/**
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
168
|
+
* TODO: Handle clear action
|
|
169
|
+
*/
|
|
170
|
+
_handleFieldKeydown(event) {
|
|
171
|
+
if (this.disabled)
|
|
172
|
+
return;
|
|
152
173
|
const eventClone = new KeyboardEvent(event.type, event);
|
|
153
|
-
eventClone.preventDefault = ()=>event.preventDefault();
|
|
154
|
-
eventClone.stopPropagation = ()=>event.stopPropagation();
|
|
174
|
+
eventClone.preventDefault = () => event.preventDefault();
|
|
175
|
+
eventClone.stopPropagation = () => event.stopPropagation();
|
|
155
176
|
this.$menu.$menu.dispatchEvent(eventClone);
|
|
156
177
|
}
|
|
157
178
|
_handleMenuSelect(event) {
|
|
@@ -177,7 +198,7 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
177
198
|
}
|
|
178
199
|
selectItem(item) {
|
|
179
200
|
const selectedOptions = this.getSelectedOptions() ?? [];
|
|
180
|
-
selectedOptions.forEach(([option])=>{
|
|
201
|
+
selectedOptions.forEach(([option]) => {
|
|
181
202
|
if (item !== option) {
|
|
182
203
|
option.selected = false;
|
|
183
204
|
}
|
|
@@ -188,9 +209,12 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
188
209
|
initUserSelection() {
|
|
189
210
|
if (this.lastUserSetValue && !this.lastSelectedOptionRecords.length) {
|
|
190
211
|
this.select(this.lastUserSetValue);
|
|
191
|
-
}
|
|
212
|
+
}
|
|
213
|
+
else if (this.lastUserSetSelectedIndex !== null &&
|
|
214
|
+
!this.lastSelectedOptionRecords.length) {
|
|
192
215
|
this.selectIndex(this.lastUserSetSelectedIndex);
|
|
193
|
-
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
194
218
|
this.updateValueAndDisplayText();
|
|
195
219
|
}
|
|
196
220
|
}
|
|
@@ -203,7 +227,8 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
203
227
|
this.lastSelectedOption = firstSelectedOption;
|
|
204
228
|
this[VALUE] = firstSelectedOption.value;
|
|
205
229
|
this.displayText = firstSelectedOption.displayText;
|
|
206
|
-
}
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
207
232
|
changed = this.lastSelectedOption !== null;
|
|
208
233
|
this.lastSelectedOption = null;
|
|
209
234
|
this[VALUE] = '';
|
|
@@ -218,12 +243,9 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
218
243
|
getSelectedOptions() {
|
|
219
244
|
const items = this.$options;
|
|
220
245
|
const records = [];
|
|
221
|
-
items.forEach((item, index)=>{
|
|
246
|
+
items.forEach((item, index) => {
|
|
222
247
|
if (item.selected) {
|
|
223
|
-
records.push([
|
|
224
|
-
item,
|
|
225
|
-
index
|
|
226
|
-
]);
|
|
248
|
+
records.push([item, index]);
|
|
227
249
|
}
|
|
228
250
|
});
|
|
229
251
|
this.lastSelectedOptionRecords = records;
|
|
@@ -235,7 +257,8 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
235
257
|
if (selectedOptions && selectedOptions.length > 0) {
|
|
236
258
|
const [item] = selectedOptions[0];
|
|
237
259
|
this.$menu.focusItem(item);
|
|
238
|
-
}
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
239
262
|
this.$menu.focusFirstItem();
|
|
240
263
|
}
|
|
241
264
|
}
|
|
@@ -246,7 +269,7 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
246
269
|
this.value = state;
|
|
247
270
|
}
|
|
248
271
|
select(value) {
|
|
249
|
-
const item = this.$options.find((option)=>option.value === value);
|
|
272
|
+
const item = this.$options.find((option) => option.value === value);
|
|
250
273
|
if (item) {
|
|
251
274
|
this.selectItem(item);
|
|
252
275
|
}
|
|
@@ -258,71 +281,50 @@ const Base = FormAssociated(FocusDelegated(InternalsAttached(LitElement)));
|
|
|
258
281
|
}
|
|
259
282
|
}
|
|
260
283
|
reset() {
|
|
261
|
-
for (const option of this.$options){
|
|
284
|
+
for (const option of this.$options) {
|
|
262
285
|
option.selected = option.hasAttribute('selected');
|
|
263
286
|
}
|
|
264
287
|
this.updateValueAndDisplayText();
|
|
265
288
|
}
|
|
266
289
|
toggle() {
|
|
267
|
-
if (this.disabled)
|
|
290
|
+
if (this.disabled)
|
|
291
|
+
return;
|
|
268
292
|
this.open = !this.open;
|
|
269
293
|
}
|
|
270
294
|
}
|
|
271
|
-
|
|
272
|
-
property({
|
|
273
|
-
type: Boolean,
|
|
274
|
-
reflect: true
|
|
275
|
-
})
|
|
295
|
+
__decorate([
|
|
296
|
+
property({ type: Boolean, reflect: true })
|
|
276
297
|
], Select.prototype, "required", void 0);
|
|
277
|
-
|
|
278
|
-
property({
|
|
279
|
-
type: Boolean
|
|
280
|
-
})
|
|
298
|
+
__decorate([
|
|
299
|
+
property({ type: Boolean })
|
|
281
300
|
], Select.prototype, "error", void 0);
|
|
282
|
-
|
|
283
|
-
property({
|
|
284
|
-
type: Boolean
|
|
285
|
-
})
|
|
301
|
+
__decorate([
|
|
302
|
+
property({ type: Boolean })
|
|
286
303
|
], Select.prototype, "quick", void 0);
|
|
287
|
-
|
|
288
|
-
property({
|
|
289
|
-
type: Number
|
|
290
|
-
})
|
|
304
|
+
__decorate([
|
|
305
|
+
property({ type: Number })
|
|
291
306
|
], Select.prototype, "offset", void 0);
|
|
292
|
-
|
|
293
|
-
property({
|
|
294
|
-
reflect: true
|
|
295
|
-
})
|
|
307
|
+
__decorate([
|
|
308
|
+
property({ reflect: true })
|
|
296
309
|
], Select.prototype, "align", void 0);
|
|
297
|
-
|
|
298
|
-
property({
|
|
299
|
-
type: String,
|
|
300
|
-
reflect: true,
|
|
301
|
-
attribute: 'align-strategy'
|
|
302
|
-
})
|
|
310
|
+
__decorate([
|
|
311
|
+
property({ type: String, reflect: true, attribute: 'align-strategy' })
|
|
303
312
|
], Select.prototype, "alignStrategy", void 0);
|
|
304
|
-
|
|
305
|
-
property({
|
|
306
|
-
type: Boolean
|
|
307
|
-
})
|
|
313
|
+
__decorate([
|
|
314
|
+
property({ type: Boolean })
|
|
308
315
|
], Select.prototype, "open", void 0);
|
|
309
|
-
|
|
310
|
-
property({
|
|
311
|
-
attribute: 'display-text'
|
|
312
|
-
})
|
|
316
|
+
__decorate([
|
|
317
|
+
property({ attribute: 'display-text' })
|
|
313
318
|
], Select.prototype, "displayText", void 0);
|
|
314
|
-
|
|
319
|
+
__decorate([
|
|
315
320
|
property()
|
|
316
321
|
], Select.prototype, "value", null);
|
|
317
|
-
|
|
318
|
-
property({
|
|
319
|
-
type: Number,
|
|
320
|
-
attribute: 'selected-index'
|
|
321
|
-
})
|
|
322
|
+
__decorate([
|
|
323
|
+
property({ type: Number, attribute: 'selected-index' })
|
|
322
324
|
], Select.prototype, "selectedIndex", null);
|
|
323
|
-
|
|
325
|
+
__decorate([
|
|
324
326
|
query('[part="field"]')
|
|
325
327
|
], Select.prototype, "$field", void 0);
|
|
326
|
-
|
|
328
|
+
__decorate([
|
|
327
329
|
query('[part="menu"]')
|
|
328
330
|
], Select.prototype, "$menu", void 0);
|