@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
package/src/base/menu.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
2
|
import { LitElement, html } from 'lit';
|
|
3
3
|
import { property, query, queryAssignedElements } from 'lit/decorators.js';
|
|
4
4
|
import { setFocusVisible } from '../core/focus-visible.js';
|
|
@@ -16,15 +16,73 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
16
16
|
* @fires {Event} close - Fires when the menu is closed.
|
|
17
17
|
* @fires {MenuSelectEvent} select - Fires when an item is selected.
|
|
18
18
|
* @fires {MenuItemFocusEvent} item-focus - Fires when an item is focused
|
|
19
|
-
*/
|
|
19
|
+
*/
|
|
20
|
+
export class Menu extends Base {
|
|
21
|
+
constructor() {
|
|
22
|
+
super(...arguments);
|
|
23
|
+
this._durations = { show: 0, hide: 0 };
|
|
24
|
+
this._scrollPadding = 0;
|
|
25
|
+
this.type = 'menu';
|
|
26
|
+
this.open = false;
|
|
27
|
+
this.quick = false;
|
|
28
|
+
this.offset = 0;
|
|
29
|
+
this.align = 'bottom-start';
|
|
30
|
+
this.alignStrategy = 'absolute';
|
|
31
|
+
this.keepOpenBlur = false;
|
|
32
|
+
this.keepOpenSelect = false;
|
|
33
|
+
this.keepOpenClickAway = false;
|
|
34
|
+
this.noFocusControl = false;
|
|
35
|
+
this.tabIndex = 0;
|
|
36
|
+
this.$lastFocused = null;
|
|
37
|
+
this.popoverController = new PopoverController(this, {
|
|
38
|
+
popover: () => this.$menu,
|
|
39
|
+
trigger: () => this.$control,
|
|
40
|
+
positioning: {
|
|
41
|
+
placement: () => this.align,
|
|
42
|
+
strategy: () => this.alignStrategy,
|
|
43
|
+
offset: () => this.offset,
|
|
44
|
+
windowPadding: () => 16,
|
|
45
|
+
},
|
|
46
|
+
durations: {
|
|
47
|
+
open: () => (this.quick ? 0 : this._durations.show),
|
|
48
|
+
close: () => (this.quick ? 0 : this._durations.hide),
|
|
49
|
+
},
|
|
50
|
+
onClickAway: () => {
|
|
51
|
+
if (!this.keepOpenClickAway)
|
|
52
|
+
this.open = false;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
this.listController = new ListController(this, {
|
|
56
|
+
isItem: (item) => item.getAttribute('seele-base') === 'option' &&
|
|
57
|
+
!item.hasAttribute('disabled') &&
|
|
58
|
+
!item.hidden,
|
|
59
|
+
getPossibleItems: () => this.slotItems,
|
|
60
|
+
blurItem: (item) => {
|
|
61
|
+
item.focused = false;
|
|
62
|
+
},
|
|
63
|
+
focusItem: (item) => {
|
|
64
|
+
item.focused = true;
|
|
65
|
+
if (!this.noFocusControl) {
|
|
66
|
+
this.$menu.ariaActiveDescendantElement = item;
|
|
67
|
+
}
|
|
68
|
+
scrollItemIntoView(this.$menu, item, this._scrollPadding);
|
|
69
|
+
this.dispatchEvent(new CustomEvent('item-focus', {
|
|
70
|
+
detail: { item: item },
|
|
71
|
+
bubbles: true,
|
|
72
|
+
composed: true,
|
|
73
|
+
}));
|
|
74
|
+
},
|
|
75
|
+
wrapNavigation: () => false,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
20
78
|
get $items() {
|
|
21
79
|
return this.listController.items || [];
|
|
22
80
|
}
|
|
23
81
|
render() {
|
|
24
|
-
return html`<div part="menu" role="${this.type}" tabindex="${this.tabIndex}" @keydown="${this.#handleKeyDown.bind(this)}" @focusout="${this.#handleFocusOut.bind(this)}">${this.renderItemSlot()}</div>`;
|
|
82
|
+
return html `<div part="menu" role="${this.type}" tabindex="${this.tabIndex}" @keydown="${this.#handleKeyDown.bind(this)}" @focusout="${this.#handleFocusOut.bind(this)}">${this.renderItemSlot()}</div>`;
|
|
25
83
|
}
|
|
26
84
|
renderItemSlot() {
|
|
27
|
-
return html`<slot part="items"></slot>`;
|
|
85
|
+
return html `<slot part="items"></slot>`;
|
|
28
86
|
}
|
|
29
87
|
connectedCallback() {
|
|
30
88
|
super.connectedCallback();
|
|
@@ -33,8 +91,8 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
33
91
|
// TODO: Handle $control change
|
|
34
92
|
this.$control.addEventListener('focusout', this.#handleFocusOut.bind(this));
|
|
35
93
|
}
|
|
36
|
-
this.updateComplete.then(()=>{
|
|
37
|
-
this.$items.forEach((item)=>{
|
|
94
|
+
this.updateComplete.then(() => {
|
|
95
|
+
this.$items.forEach((item) => {
|
|
38
96
|
item.addEventListener('mouseover', this.#handleItemMouseOver.bind(this));
|
|
39
97
|
item.addEventListener('click', this.#handleItemClick.bind(this));
|
|
40
98
|
});
|
|
@@ -49,35 +107,31 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
49
107
|
updated(changed) {
|
|
50
108
|
if (changed.has('open')) {
|
|
51
109
|
if (this.open) {
|
|
52
|
-
this.dispatchEvent(new Event('open', {
|
|
53
|
-
bubbles: true,
|
|
54
|
-
composed: true
|
|
55
|
-
}));
|
|
110
|
+
this.dispatchEvent(new Event('open', { bubbles: true, composed: true }));
|
|
56
111
|
this.$lastFocused = document.activeElement;
|
|
57
112
|
if (this.$control) {
|
|
58
113
|
this.$control.ariaExpanded = 'true';
|
|
59
114
|
}
|
|
60
|
-
this.popoverController.animateOpen().then(()=>{
|
|
115
|
+
this.popoverController.animateOpen().then(() => {
|
|
61
116
|
if (!this.noFocusControl) {
|
|
62
117
|
this.$menu.focus();
|
|
63
118
|
this.listController.focusFirstItem();
|
|
64
119
|
}
|
|
65
120
|
});
|
|
66
|
-
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
67
123
|
if (!this.noFocusControl) {
|
|
68
124
|
this.$menu.ariaActiveDescendantElement = null;
|
|
69
125
|
}
|
|
70
|
-
this.dispatchEvent(new Event('close', {
|
|
71
|
-
bubbles: true,
|
|
72
|
-
composed: true
|
|
73
|
-
}));
|
|
126
|
+
this.dispatchEvent(new Event('close', { bubbles: true, composed: true }));
|
|
74
127
|
this.listController.clearSearch();
|
|
75
128
|
if (this.$control) {
|
|
76
129
|
this.$control.ariaExpanded = 'false';
|
|
77
130
|
}
|
|
78
|
-
this.popoverController.animateClose().then(()=>{
|
|
131
|
+
this.popoverController.animateClose().then(() => {
|
|
79
132
|
if (this.$lastFocused) {
|
|
80
|
-
if (!this.noFocusControl)
|
|
133
|
+
if (!this.noFocusControl)
|
|
134
|
+
this.$lastFocused.focus();
|
|
81
135
|
this.$lastFocused = null;
|
|
82
136
|
}
|
|
83
137
|
});
|
|
@@ -85,12 +139,13 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
85
139
|
}
|
|
86
140
|
}
|
|
87
141
|
#handleKeyDown(event) {
|
|
88
|
-
if (event.defaultPrevented)
|
|
142
|
+
if (event.defaultPrevented)
|
|
143
|
+
return;
|
|
89
144
|
const action = getActionFromKey(event, this.open);
|
|
90
145
|
const items = this.$items;
|
|
91
146
|
const currentIndex = this.listController.currentIndex;
|
|
92
147
|
const maxIndex = items.length - 1;
|
|
93
|
-
switch(action){
|
|
148
|
+
switch (action) {
|
|
94
149
|
case MenuActions.Last:
|
|
95
150
|
case MenuActions.First:
|
|
96
151
|
this.open = true;
|
|
@@ -110,12 +165,13 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
110
165
|
this.dispatchEvent(new CustomEvent('select', {
|
|
111
166
|
detail: {
|
|
112
167
|
item: items[currentIndex],
|
|
113
|
-
index: currentIndex
|
|
168
|
+
index: currentIndex,
|
|
114
169
|
},
|
|
115
170
|
bubbles: true,
|
|
116
|
-
composed: true
|
|
171
|
+
composed: true,
|
|
117
172
|
}));
|
|
118
|
-
if (this.keepOpenSelect)
|
|
173
|
+
if (this.keepOpenSelect)
|
|
174
|
+
return;
|
|
119
175
|
this.open = false;
|
|
120
176
|
}
|
|
121
177
|
return;
|
|
@@ -134,9 +190,12 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
134
190
|
}
|
|
135
191
|
}
|
|
136
192
|
#handleFocusOut(event) {
|
|
137
|
-
if (this.keepOpenBlur)
|
|
193
|
+
if (this.keepOpenBlur)
|
|
194
|
+
return;
|
|
138
195
|
const newFocus = event.relatedTarget;
|
|
139
|
-
const isInside = this.contains(newFocus) ||
|
|
196
|
+
const isInside = this.contains(newFocus) ||
|
|
197
|
+
this.shadowRoot?.contains(newFocus) ||
|
|
198
|
+
this.$control?.contains(newFocus);
|
|
140
199
|
if (!isInside) {
|
|
141
200
|
this.open = false;
|
|
142
201
|
}
|
|
@@ -153,12 +212,13 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
153
212
|
this.dispatchEvent(new CustomEvent('select', {
|
|
154
213
|
detail: {
|
|
155
214
|
item: clickedItem,
|
|
156
|
-
index: index
|
|
215
|
+
index: index,
|
|
157
216
|
},
|
|
158
217
|
bubbles: true,
|
|
159
|
-
composed: true
|
|
218
|
+
composed: true,
|
|
160
219
|
}));
|
|
161
|
-
if (!this.keepOpenSelect)
|
|
220
|
+
if (!this.keepOpenSelect)
|
|
221
|
+
this.open = false;
|
|
162
222
|
}
|
|
163
223
|
get currentIndex() {
|
|
164
224
|
return this.listController?.currentIndex;
|
|
@@ -178,118 +238,45 @@ const Base = FocusDelegated(InternalsAttached(Attachable(LitElement)));
|
|
|
178
238
|
close() {
|
|
179
239
|
this.open = false;
|
|
180
240
|
}
|
|
181
|
-
constructor(...args){
|
|
182
|
-
super(...args), this._durations = {
|
|
183
|
-
show: 0,
|
|
184
|
-
hide: 0
|
|
185
|
-
}, this._scrollPadding = 0, this.type = 'menu', this.open = false, this.quick = false, this.offset = 0, this.align = 'bottom-start', this.alignStrategy = 'absolute', this.keepOpenBlur = false, this.keepOpenSelect = false, this.keepOpenClickAway = false, this.noFocusControl = false, this.tabIndex = 0, this.$lastFocused = null, this.popoverController = new PopoverController(this, {
|
|
186
|
-
popover: ()=>this.$menu,
|
|
187
|
-
trigger: ()=>this.$control,
|
|
188
|
-
positioning: {
|
|
189
|
-
placement: ()=>this.align,
|
|
190
|
-
strategy: ()=>this.alignStrategy,
|
|
191
|
-
offset: ()=>this.offset,
|
|
192
|
-
windowPadding: ()=>16
|
|
193
|
-
},
|
|
194
|
-
durations: {
|
|
195
|
-
open: ()=>this.quick ? 0 : this._durations.show,
|
|
196
|
-
close: ()=>this.quick ? 0 : this._durations.hide
|
|
197
|
-
},
|
|
198
|
-
onClickAway: ()=>{
|
|
199
|
-
if (!this.keepOpenClickAway) this.open = false;
|
|
200
|
-
}
|
|
201
|
-
}), this.listController = new ListController(this, {
|
|
202
|
-
isItem: (item)=>item.getAttribute('seele-base') === 'option' && !item.hasAttribute('disabled') && !item.hidden,
|
|
203
|
-
getPossibleItems: ()=>this.slotItems,
|
|
204
|
-
blurItem: (item)=>{
|
|
205
|
-
item.focused = false;
|
|
206
|
-
},
|
|
207
|
-
focusItem: (item)=>{
|
|
208
|
-
item.focused = true;
|
|
209
|
-
if (!this.noFocusControl) {
|
|
210
|
-
this.$menu.ariaActiveDescendantElement = item;
|
|
211
|
-
}
|
|
212
|
-
scrollItemIntoView(this.$menu, item, this._scrollPadding);
|
|
213
|
-
this.dispatchEvent(new CustomEvent('item-focus', {
|
|
214
|
-
detail: {
|
|
215
|
-
item: item
|
|
216
|
-
},
|
|
217
|
-
bubbles: true,
|
|
218
|
-
composed: true
|
|
219
|
-
}));
|
|
220
|
-
},
|
|
221
|
-
wrapNavigation: ()=>false
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
241
|
}
|
|
225
|
-
|
|
242
|
+
__decorate([
|
|
226
243
|
property()
|
|
227
244
|
], Menu.prototype, "type", void 0);
|
|
228
|
-
|
|
229
|
-
property({
|
|
230
|
-
type: Boolean,
|
|
231
|
-
reflect: true
|
|
232
|
-
})
|
|
245
|
+
__decorate([
|
|
246
|
+
property({ type: Boolean, reflect: true })
|
|
233
247
|
], Menu.prototype, "open", void 0);
|
|
234
|
-
|
|
235
|
-
property({
|
|
236
|
-
type: Boolean
|
|
237
|
-
})
|
|
248
|
+
__decorate([
|
|
249
|
+
property({ type: Boolean })
|
|
238
250
|
], Menu.prototype, "quick", void 0);
|
|
239
|
-
|
|
240
|
-
property({
|
|
241
|
-
type: Number
|
|
242
|
-
})
|
|
251
|
+
__decorate([
|
|
252
|
+
property({ type: Number })
|
|
243
253
|
], Menu.prototype, "offset", void 0);
|
|
244
|
-
|
|
245
|
-
property({
|
|
246
|
-
reflect: true
|
|
247
|
-
})
|
|
254
|
+
__decorate([
|
|
255
|
+
property({ reflect: true })
|
|
248
256
|
], Menu.prototype, "align", void 0);
|
|
249
|
-
|
|
250
|
-
property({
|
|
251
|
-
type: String,
|
|
252
|
-
reflect: true,
|
|
253
|
-
attribute: 'align-strategy'
|
|
254
|
-
})
|
|
257
|
+
__decorate([
|
|
258
|
+
property({ type: String, reflect: true, attribute: 'align-strategy' })
|
|
255
259
|
], Menu.prototype, "alignStrategy", void 0);
|
|
256
|
-
|
|
257
|
-
property({
|
|
258
|
-
type: Boolean,
|
|
259
|
-
attribute: 'keep-open-blur'
|
|
260
|
-
})
|
|
260
|
+
__decorate([
|
|
261
|
+
property({ type: Boolean, attribute: 'keep-open-blur' })
|
|
261
262
|
], Menu.prototype, "keepOpenBlur", void 0);
|
|
262
|
-
|
|
263
|
-
property({
|
|
264
|
-
type: Boolean,
|
|
265
|
-
attribute: 'keep-open-select'
|
|
266
|
-
})
|
|
263
|
+
__decorate([
|
|
264
|
+
property({ type: Boolean, attribute: 'keep-open-select' })
|
|
267
265
|
], Menu.prototype, "keepOpenSelect", void 0);
|
|
268
|
-
|
|
269
|
-
property({
|
|
270
|
-
type: Boolean,
|
|
271
|
-
attribute: 'keep-open-click-away'
|
|
272
|
-
})
|
|
266
|
+
__decorate([
|
|
267
|
+
property({ type: Boolean, attribute: 'keep-open-click-away' })
|
|
273
268
|
], Menu.prototype, "keepOpenClickAway", void 0);
|
|
274
|
-
|
|
275
|
-
property({
|
|
276
|
-
type: Boolean,
|
|
277
|
-
attribute: 'no-focus-control'
|
|
278
|
-
})
|
|
269
|
+
__decorate([
|
|
270
|
+
property({ type: Boolean, attribute: 'no-focus-control' })
|
|
279
271
|
], Menu.prototype, "noFocusControl", void 0);
|
|
280
|
-
|
|
281
|
-
property({
|
|
282
|
-
type: Number,
|
|
283
|
-
attribute: 'data-tabindex'
|
|
284
|
-
})
|
|
272
|
+
__decorate([
|
|
273
|
+
property({ type: Number, attribute: 'data-tabindex' })
|
|
285
274
|
], Menu.prototype, "tabIndex", void 0);
|
|
286
|
-
|
|
275
|
+
__decorate([
|
|
287
276
|
query('[part="menu"]')
|
|
288
277
|
], Menu.prototype, "$menu", void 0);
|
|
289
|
-
|
|
290
|
-
queryAssignedElements({
|
|
291
|
-
flatten: true
|
|
292
|
-
})
|
|
278
|
+
__decorate([
|
|
279
|
+
queryAssignedElements({ flatten: true })
|
|
293
280
|
], Menu.prototype, "slotItems", void 0);
|
|
294
281
|
// Reference: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
|
|
295
282
|
export const MenuActions = {
|
|
@@ -303,22 +290,17 @@ export const MenuActions = {
|
|
|
303
290
|
PageUp: 7,
|
|
304
291
|
Previous: 8,
|
|
305
292
|
Select: 9,
|
|
306
|
-
Type: 10
|
|
293
|
+
Type: 10,
|
|
307
294
|
};
|
|
308
295
|
export function filterOptions(options = [], filter, exclude = []) {
|
|
309
|
-
return options.filter((option)=>{
|
|
296
|
+
return options.filter((option) => {
|
|
310
297
|
const matches = option.toLowerCase().indexOf(filter.toLowerCase()) === 0;
|
|
311
298
|
return matches && exclude.indexOf(option) < 0;
|
|
312
299
|
});
|
|
313
300
|
}
|
|
314
301
|
export function getActionFromKey(event, menuOpen) {
|
|
315
302
|
const { key, altKey, ctrlKey, metaKey } = event;
|
|
316
|
-
const openKeys = [
|
|
317
|
-
'ArrowDown',
|
|
318
|
-
'ArrowUp',
|
|
319
|
-
'Enter',
|
|
320
|
-
' '
|
|
321
|
-
];
|
|
303
|
+
const openKeys = ['ArrowDown', 'ArrowUp', 'Enter', ' '];
|
|
322
304
|
if (!menuOpen && openKeys.includes(key)) {
|
|
323
305
|
return MenuActions.Open;
|
|
324
306
|
}
|
|
@@ -328,23 +310,31 @@ export function getActionFromKey(event, menuOpen) {
|
|
|
328
310
|
if (key === 'End') {
|
|
329
311
|
return MenuActions.Last;
|
|
330
312
|
}
|
|
331
|
-
if (key === 'Backspace' ||
|
|
313
|
+
if (key === 'Backspace' ||
|
|
314
|
+
key === 'Clear' ||
|
|
315
|
+
(key.length === 1 && key !== ' ' && !altKey && !ctrlKey && !metaKey)) {
|
|
332
316
|
return MenuActions.Type;
|
|
333
317
|
}
|
|
334
318
|
if (menuOpen) {
|
|
335
319
|
if (key === 'ArrowUp' && altKey) {
|
|
336
320
|
return MenuActions.CloseSelect;
|
|
337
|
-
}
|
|
321
|
+
}
|
|
322
|
+
else if (key === 'ArrowDown' && !altKey) {
|
|
338
323
|
return MenuActions.Next;
|
|
339
|
-
}
|
|
324
|
+
}
|
|
325
|
+
else if (key === 'ArrowUp') {
|
|
340
326
|
return MenuActions.Previous;
|
|
341
|
-
}
|
|
327
|
+
}
|
|
328
|
+
else if (key === 'PageUp') {
|
|
342
329
|
return MenuActions.PageUp;
|
|
343
|
-
}
|
|
330
|
+
}
|
|
331
|
+
else if (key === 'PageDown') {
|
|
344
332
|
return MenuActions.PageDown;
|
|
345
|
-
}
|
|
333
|
+
}
|
|
334
|
+
else if (key === 'Escape') {
|
|
346
335
|
return MenuActions.Close;
|
|
347
|
-
}
|
|
336
|
+
}
|
|
337
|
+
else if (key === 'Enter' || key === ' ') {
|
|
348
338
|
return MenuActions.CloseSelect;
|
|
349
339
|
}
|
|
350
340
|
}
|
|
@@ -352,7 +342,7 @@ export function getActionFromKey(event, menuOpen) {
|
|
|
352
342
|
}
|
|
353
343
|
export function getUpdatedIndex(currentIndex, maxIndex, action) {
|
|
354
344
|
const pageSize = 10;
|
|
355
|
-
switch(action){
|
|
345
|
+
switch (action) {
|
|
356
346
|
case MenuActions.First:
|
|
357
347
|
return 0;
|
|
358
348
|
case MenuActions.Last:
|
|
@@ -370,13 +360,15 @@ export function getUpdatedIndex(currentIndex, maxIndex, action) {
|
|
|
370
360
|
}
|
|
371
361
|
}
|
|
372
362
|
export function scrollItemIntoView(menu, item, paddingY = 0) {
|
|
373
|
-
if (!menu)
|
|
363
|
+
if (!menu)
|
|
364
|
+
return;
|
|
374
365
|
// Basic scroll into view logic
|
|
375
366
|
const menuRect = menu.getBoundingClientRect();
|
|
376
367
|
const itemRect = item.getBoundingClientRect();
|
|
377
368
|
if (itemRect.bottom + paddingY > menuRect.bottom) {
|
|
378
369
|
menu.scrollTop += itemRect.bottom - menuRect.bottom + paddingY;
|
|
379
|
-
}
|
|
370
|
+
}
|
|
371
|
+
else if (itemRect.top - paddingY < menuRect.top) {
|
|
380
372
|
menu.scrollTop -= menuRect.top - itemRect.top + paddingY;
|
|
381
373
|
}
|
|
382
374
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
export declare class AttachableInterface {
|
|
3
|
+
$control: HTMLElement;
|
|
4
|
+
htmlFor: string | null;
|
|
5
|
+
attach(control: HTMLElement, force?: boolean): void;
|
|
6
|
+
detach(): void;
|
|
7
|
+
handleControlChange(prev: HTMLElement | null, next: HTMLElement | null): void;
|
|
8
|
+
}
|
|
9
|
+
export declare const Attachable: <T extends Constructor<LitElement>>(superClass: T) => Constructor<AttachableInterface> & T;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
|
-
export const Attachable = (superClass)=>{
|
|
3
|
+
export const Attachable = (superClass) => {
|
|
4
4
|
class AttachableElement extends superClass {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
this.currentControl = null;
|
|
8
|
+
}
|
|
5
9
|
connectedCallback() {
|
|
6
10
|
super.connectedCallback();
|
|
7
11
|
this.setCurrentControl(this.$control);
|
|
@@ -11,21 +15,25 @@ export const Attachable = (superClass)=>{
|
|
|
11
15
|
super.disconnectedCallback();
|
|
12
16
|
}
|
|
13
17
|
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
* If has `for` attribute, use it to find the control element.
|
|
19
|
+
* Otherwise, use the parent element as the control.
|
|
20
|
+
*/
|
|
21
|
+
get $control() {
|
|
17
22
|
if (this.hasAttribute('for')) {
|
|
18
23
|
if (!this.htmlFor || !this.isConnected) {
|
|
19
24
|
return null;
|
|
20
25
|
}
|
|
21
26
|
return this.getRootNode().querySelector(`#${this.htmlFor}`);
|
|
22
27
|
}
|
|
23
|
-
return this.currentControl || this.parentNode instanceof ShadowRoot
|
|
28
|
+
return this.currentControl || this.parentNode instanceof ShadowRoot
|
|
29
|
+
? this.parentNode.host
|
|
30
|
+
: this.parentElement;
|
|
24
31
|
}
|
|
25
32
|
set $control(control) {
|
|
26
33
|
if (control) {
|
|
27
34
|
this.attach(control);
|
|
28
|
-
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
29
37
|
this.detach();
|
|
30
38
|
}
|
|
31
39
|
}
|
|
@@ -38,7 +46,8 @@ export const Attachable = (superClass)=>{
|
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
48
|
setCurrentControl(control, force = false) {
|
|
41
|
-
if (control === this.currentControl && !force)
|
|
49
|
+
if (control === this.currentControl && !force)
|
|
50
|
+
return;
|
|
42
51
|
this.handleControlChange(this.currentControl, control);
|
|
43
52
|
this.currentControl = control;
|
|
44
53
|
}
|
|
@@ -51,17 +60,12 @@ export const Attachable = (superClass)=>{
|
|
|
51
60
|
this.setAttribute('for', '');
|
|
52
61
|
}
|
|
53
62
|
/**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
super(...args), this.currentControl = null;
|
|
58
|
-
}
|
|
63
|
+
* Handles the first attaching and actual control element changing
|
|
64
|
+
*/
|
|
65
|
+
handleControlChange(prev = null, next = null) { }
|
|
59
66
|
}
|
|
60
|
-
|
|
61
|
-
property({
|
|
62
|
-
attribute: 'for',
|
|
63
|
-
type: String
|
|
64
|
-
})
|
|
67
|
+
__decorate([
|
|
68
|
+
property({ attribute: 'for', type: String })
|
|
65
69
|
], AttachableElement.prototype, "htmlFor", void 0);
|
|
66
70
|
return AttachableElement;
|
|
67
71
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { InternalsAttachedInterface } from './internals-attached.js';
|
|
3
|
+
export declare class FocusDelegatedInterface {
|
|
4
|
+
}
|
|
5
|
+
export declare const FocusDelegated: <T extends Constructor<LitElement & InternalsAttachedInterface>>(superClass: T) => Constructor<FocusDelegatedInterface> & T;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
import { internals } from './internals-attached.js';
|
|
3
|
-
export const FocusDelegated = (superClass)=>{
|
|
3
|
+
export const FocusDelegated = (superClass) => {
|
|
4
4
|
class FocusDelegatedElement extends superClass {
|
|
5
|
-
static{
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
constructor(...args){
|
|
5
|
+
static { this.shadowRootOptions = {
|
|
6
|
+
...LitElement.shadowRootOptions,
|
|
7
|
+
delegatesFocus: true,
|
|
8
|
+
}; }
|
|
9
|
+
constructor(...args) {
|
|
12
10
|
super();
|
|
13
11
|
this[internals].role = 'presentation';
|
|
14
12
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { InternalsAttachedInterface } from './internals-attached.js';
|
|
3
|
+
export declare class FormAssociatedInterface {
|
|
4
|
+
form: HTMLFormElement | null;
|
|
5
|
+
labels: NodeList;
|
|
6
|
+
name: string | null;
|
|
7
|
+
disabled: boolean;
|
|
8
|
+
validity: ValidityState;
|
|
9
|
+
validationMessage: string;
|
|
10
|
+
willValidate: boolean;
|
|
11
|
+
formDisabledCallback(disabled: boolean): void;
|
|
12
|
+
checkValidity(): boolean;
|
|
13
|
+
reportValidity(): boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare const FormAssociated: <T extends Constructor<LitElement & InternalsAttachedInterface>>(superClass: T) => Constructor<FormAssociatedInterface> & T;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
3
|
import { internals } from './internals-attached.js';
|
|
4
|
-
export const FormAssociated = (superClass)=>{
|
|
4
|
+
export const FormAssociated = (superClass) => {
|
|
5
5
|
class FormAssociatedElement extends superClass {
|
|
6
|
-
static{
|
|
7
|
-
this.formAssociated = true;
|
|
8
|
-
}
|
|
6
|
+
static { this.formAssociated = true; }
|
|
9
7
|
get form() {
|
|
10
8
|
return this[internals].form;
|
|
11
9
|
}
|
|
@@ -25,16 +23,16 @@ export const FormAssociated = (superClass)=>{
|
|
|
25
23
|
set name(name) {
|
|
26
24
|
// Note: setting name to null or empty does not remove the attribute.
|
|
27
25
|
this.setAttribute('name', name);
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
// We don't need to call `requestUpdate()` since it's called synchronously
|
|
27
|
+
// in `attributeChangedCallback()`.
|
|
30
28
|
}
|
|
31
29
|
get disabled() {
|
|
32
30
|
return this.hasAttribute('disabled');
|
|
33
31
|
}
|
|
34
32
|
set disabled(disabled) {
|
|
35
33
|
this.toggleAttribute('disabled', disabled);
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
// We don't need to call `requestUpdate()` since it's called synchronously
|
|
35
|
+
// in `attributeChangedCallback()`.
|
|
38
36
|
}
|
|
39
37
|
attributeChangedCallback(name, old, value) {
|
|
40
38
|
if (name === 'disabled') {
|
|
@@ -61,16 +59,11 @@ export const FormAssociated = (superClass)=>{
|
|
|
61
59
|
return this[internals].reportValidity();
|
|
62
60
|
}
|
|
63
61
|
}
|
|
64
|
-
|
|
65
|
-
property({
|
|
66
|
-
noAccessor: true
|
|
67
|
-
})
|
|
62
|
+
__decorate([
|
|
63
|
+
property({ noAccessor: true })
|
|
68
64
|
], FormAssociatedElement.prototype, "name", null);
|
|
69
|
-
|
|
70
|
-
property({
|
|
71
|
-
type: Boolean,
|
|
72
|
-
noAccessor: true
|
|
73
|
-
})
|
|
65
|
+
__decorate([
|
|
66
|
+
property({ type: Boolean, noAccessor: true })
|
|
74
67
|
], FormAssociatedElement.prototype, "disabled", null);
|
|
75
68
|
return FormAssociatedElement;
|
|
76
69
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
export declare const internals: unique symbol;
|
|
3
|
+
export declare class InternalsAttachedInterface {
|
|
4
|
+
[internals]: ElementInternals;
|
|
5
|
+
}
|
|
6
|
+
export declare const InternalsAttached: <T extends Constructor<LitElement>>(superClass: T) => Constructor<InternalsAttachedInterface> & T;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const internals = Symbol('internals');
|
|
2
2
|
const privateInternals = Symbol('privateInternals');
|
|
3
|
-
export const InternalsAttached = (superClass)=>{
|
|
3
|
+
export const InternalsAttached = (superClass) => {
|
|
4
4
|
class InternalsAttachedElement extends superClass {
|
|
5
5
|
get [internals]() {
|
|
6
6
|
if (!this[privateInternals]) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ListItem } from './list-item.js';
|
|
2
|
+
export declare class OptionInterface {
|
|
3
|
+
value: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const OptionMixin: <T extends Constructor<ListItem>>(superClass: T) => Constructor<OptionInterface> & T;
|
|
6
|
+
declare const Option_base: Constructor<OptionInterface> & typeof ListItem;
|
|
7
|
+
export declare class Option extends Option_base {
|
|
8
|
+
}
|
|
9
|
+
export {};
|
package/src/base/option.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
3
|
import { ListItem } from './list-item.js';
|
|
4
|
-
export const OptionMixin = (superClass)=>{
|
|
4
|
+
export const OptionMixin = (superClass) => {
|
|
5
5
|
class OptionElement extends superClass {
|
|
6
|
-
constructor(
|
|
7
|
-
super(...
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.value = '';
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
|
-
|
|
11
|
-
property({
|
|
12
|
-
reflect: true
|
|
13
|
-
})
|
|
11
|
+
__decorate([
|
|
12
|
+
property({ reflect: true })
|
|
14
13
|
], OptionElement.prototype, "value", void 0);
|
|
15
14
|
return OptionElement;
|
|
16
15
|
};
|