@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/list-item.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
2
|
import { LitElement } from 'lit';
|
|
3
3
|
import { property } from 'lit/decorators.js';
|
|
4
4
|
import { genUniqueId } from '../core/unique-id.js';
|
|
@@ -6,11 +6,13 @@ import { InternalsAttached, internals } from './mixins/internals-attached.js';
|
|
|
6
6
|
import { FormAssociated } from './mixins/form-associated.js';
|
|
7
7
|
import { hiddenStyles } from './hidden-styles.css.js';
|
|
8
8
|
export class ListItem extends FormAssociated(InternalsAttached(LitElement)) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this._role = 'option';
|
|
12
|
+
this.selected = false;
|
|
13
|
+
this.focused = false;
|
|
13
14
|
}
|
|
15
|
+
static { this.styles = [hiddenStyles]; }
|
|
14
16
|
get displayText() {
|
|
15
17
|
return this.innerText.trim();
|
|
16
18
|
}
|
|
@@ -20,19 +22,26 @@ export class ListItem extends FormAssociated(InternalsAttached(LitElement)) {
|
|
|
20
22
|
this[internals].role = this._role;
|
|
21
23
|
this.setAttribute('tabindex', '-1');
|
|
22
24
|
this.#updateInternals();
|
|
23
|
-
if (!this.id)
|
|
25
|
+
if (!this.id)
|
|
26
|
+
this.id = genUniqueId('item');
|
|
24
27
|
}
|
|
25
28
|
updated(changed) {
|
|
26
29
|
super.updated(changed);
|
|
27
|
-
if (changed.has('disabled') ||
|
|
30
|
+
if (changed.has('disabled') ||
|
|
31
|
+
changed.has('focused') ||
|
|
32
|
+
changed.has('selected')) {
|
|
28
33
|
this.#updateInternals();
|
|
29
34
|
}
|
|
30
35
|
}
|
|
31
36
|
#updateInternals() {
|
|
32
37
|
this[internals].ariaDisabled = this.disabled ? 'true' : 'false';
|
|
33
|
-
this.focused
|
|
38
|
+
this.focused
|
|
39
|
+
? this[internals].states.add('focused')
|
|
40
|
+
: this[internals].states.delete('focused');
|
|
34
41
|
this[internals].ariaSelected = this.selected ? 'true' : 'false';
|
|
35
|
-
this.selected
|
|
42
|
+
this.selected
|
|
43
|
+
? this[internals].states.add('selected')
|
|
44
|
+
: this[internals].states.delete('selected');
|
|
36
45
|
}
|
|
37
46
|
focus() {
|
|
38
47
|
this.focused = true;
|
|
@@ -40,19 +49,10 @@ export class ListItem extends FormAssociated(InternalsAttached(LitElement)) {
|
|
|
40
49
|
blur() {
|
|
41
50
|
this.focused = false;
|
|
42
51
|
}
|
|
43
|
-
constructor(...args){
|
|
44
|
-
super(...args), this._role = 'option', this.selected = false, this.focused = false;
|
|
45
|
-
}
|
|
46
52
|
}
|
|
47
|
-
|
|
48
|
-
property({
|
|
49
|
-
type: Boolean,
|
|
50
|
-
reflect: true
|
|
51
|
-
})
|
|
53
|
+
__decorate([
|
|
54
|
+
property({ type: Boolean, reflect: true })
|
|
52
55
|
], ListItem.prototype, "selected", void 0);
|
|
53
|
-
|
|
54
|
-
property({
|
|
55
|
-
type: Boolean,
|
|
56
|
-
reflect: true
|
|
57
|
-
})
|
|
56
|
+
__decorate([
|
|
57
|
+
property({ type: Boolean, reflect: true })
|
|
58
58
|
], ListItem.prototype, "focused", void 0);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { ListItem } from './list-item.js';
|
|
3
|
+
declare const Base: Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
|
|
4
|
+
interface ListSelectDetail {
|
|
5
|
+
item: ListItem;
|
|
6
|
+
index: number;
|
|
7
|
+
}
|
|
8
|
+
export type ListSelectEvent = CustomEvent<ListSelectDetail>;
|
|
9
|
+
interface ItemFocusDetail {
|
|
10
|
+
item: ListItem;
|
|
11
|
+
}
|
|
12
|
+
export type ListItemFocusEvent = CustomEvent<ItemFocusDetail>;
|
|
13
|
+
/**
|
|
14
|
+
* @csspart items
|
|
15
|
+
*
|
|
16
|
+
* @fires {Event} open - Fires when the menu is opened.
|
|
17
|
+
* @fires {Event} close - Fires when the menu is closed.
|
|
18
|
+
* @fires {ListSelectEvent} select - Fires when an item is selected.
|
|
19
|
+
* @fires {ListItemFocusEvent} item-focus - Fires when an item is focused
|
|
20
|
+
*/
|
|
21
|
+
export declare class List extends Base {
|
|
22
|
+
#private;
|
|
23
|
+
readonly _scrollPadding: number;
|
|
24
|
+
noFocusControl: boolean;
|
|
25
|
+
slotItems: Array<ListItem | HTMLElement>;
|
|
26
|
+
get $items(): ListItem[];
|
|
27
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
28
|
+
renderItemSlot(): import("lit-html").TemplateResult<1>;
|
|
29
|
+
private readonly listController;
|
|
30
|
+
constructor();
|
|
31
|
+
protected updated(changed: Map<string, any>): void;
|
|
32
|
+
get currentIndex(): number;
|
|
33
|
+
focusFirstItem(): void;
|
|
34
|
+
focusLastItem(): void;
|
|
35
|
+
focusItem(item: ListItem): void;
|
|
36
|
+
}
|
|
37
|
+
export declare const MenuActions: {
|
|
38
|
+
Close: number;
|
|
39
|
+
CloseSelect: number;
|
|
40
|
+
First: number;
|
|
41
|
+
Last: number;
|
|
42
|
+
Next: number;
|
|
43
|
+
Open: number;
|
|
44
|
+
PageDown: number;
|
|
45
|
+
PageUp: number;
|
|
46
|
+
Previous: number;
|
|
47
|
+
Select: number;
|
|
48
|
+
Type: number;
|
|
49
|
+
};
|
|
50
|
+
export declare function filterOptions(options: string[], filter: string, exclude?: string[]): string[];
|
|
51
|
+
export declare function getActionFromKey(event: KeyboardEvent): number;
|
|
52
|
+
export declare function getUpdatedIndex(currentIndex: number, maxIndex: number, action: number): number;
|
|
53
|
+
export declare function scrollItemIntoView(list: HTMLElement, item: HTMLElement, paddingY?: number): void;
|
|
54
|
+
export {};
|
package/src/base/list.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
2
|
import { LitElement, html, isServer } from 'lit';
|
|
3
3
|
import { property, queryAssignedElements } from 'lit/decorators.js';
|
|
4
4
|
import { setFocusVisible } from '../core/focus-visible.js';
|
|
@@ -12,63 +12,68 @@ const Base = InternalsAttached(LitElement);
|
|
|
12
12
|
* @fires {Event} close - Fires when the menu is closed.
|
|
13
13
|
* @fires {ListSelectEvent} select - Fires when an item is selected.
|
|
14
14
|
* @fires {ListItemFocusEvent} item-focus - Fires when an item is focused
|
|
15
|
-
*/
|
|
15
|
+
*/
|
|
16
|
+
export class List extends Base {
|
|
16
17
|
get $items() {
|
|
17
18
|
return this.listController.items || [];
|
|
18
19
|
}
|
|
19
20
|
render() {
|
|
20
|
-
return html`${this.renderItemSlot()}`;
|
|
21
|
+
return html `${this.renderItemSlot()}`;
|
|
21
22
|
}
|
|
22
23
|
renderItemSlot() {
|
|
23
|
-
return html`<slot part="items"></slot>`;
|
|
24
|
-
}
|
|
25
|
-
constructor(){
|
|
26
|
-
super()
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
return html `<slot part="items"></slot>`;
|
|
25
|
+
}
|
|
26
|
+
constructor() {
|
|
27
|
+
super();
|
|
28
|
+
this._scrollPadding = 0;
|
|
29
|
+
this.noFocusControl = false;
|
|
30
|
+
this.listController = new ListController(this, {
|
|
31
|
+
isItem: (item) => item.getAttribute('seele-base') === 'option' &&
|
|
32
|
+
!item.hasAttribute('disabled') &&
|
|
33
|
+
!item.hidden,
|
|
34
|
+
getPossibleItems: () => this.slotItems,
|
|
35
|
+
blurItem: (item) => {
|
|
30
36
|
item.focused = false;
|
|
31
37
|
},
|
|
32
|
-
focusItem: (item)=>{
|
|
38
|
+
focusItem: (item) => {
|
|
33
39
|
item.focused = true;
|
|
34
40
|
if (!this.noFocusControl) {
|
|
35
41
|
this[internals].ariaActiveDescendantElement = item;
|
|
36
42
|
}
|
|
37
43
|
scrollItemIntoView(this, item, this._scrollPadding);
|
|
38
44
|
this.dispatchEvent(new CustomEvent('item-focus', {
|
|
39
|
-
detail: {
|
|
40
|
-
item: item
|
|
41
|
-
},
|
|
45
|
+
detail: { item: item },
|
|
42
46
|
bubbles: true,
|
|
43
|
-
composed: true
|
|
47
|
+
composed: true,
|
|
44
48
|
}));
|
|
45
49
|
},
|
|
46
|
-
wrapNavigation: ()=>false
|
|
50
|
+
wrapNavigation: () => false,
|
|
47
51
|
});
|
|
48
52
|
this[internals].role = 'listbox';
|
|
49
53
|
if (!this.hasAttribute('tabindex')) {
|
|
50
54
|
this.setAttribute('tabindex', '0');
|
|
51
55
|
}
|
|
52
56
|
if (!isServer) {
|
|
53
|
-
this.addEventListener('keydown', (e)=>this.#handleKeyDown(e));
|
|
54
|
-
this.addEventListener('focusin', ()=>this.#handleFocusIn());
|
|
55
|
-
this.addEventListener('focusout', ()=>this.#handleFocusOut());
|
|
56
|
-
this.addEventListener('pointerdown', (e)=>this.#handlePointerDown(e));
|
|
57
|
-
this.addEventListener('click', (e)=>this.#handleClick(e));
|
|
58
|
-
this.addEventListener('mouseover', (e)=>this.#handleMouseOver(e));
|
|
57
|
+
this.addEventListener('keydown', (e) => this.#handleKeyDown(e));
|
|
58
|
+
this.addEventListener('focusin', () => this.#handleFocusIn());
|
|
59
|
+
this.addEventListener('focusout', () => this.#handleFocusOut());
|
|
60
|
+
this.addEventListener('pointerdown', (e) => this.#handlePointerDown(e));
|
|
61
|
+
this.addEventListener('click', (e) => this.#handleClick(e));
|
|
62
|
+
this.addEventListener('mouseover', (e) => this.#handleMouseOver(e));
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
updated(changed) {
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
// TODO: Find somewhere to put this
|
|
67
|
+
// this.listController.clearSearch();
|
|
64
68
|
}
|
|
65
69
|
#handleKeyDown(event) {
|
|
66
|
-
if (event.defaultPrevented)
|
|
70
|
+
if (event.defaultPrevented)
|
|
71
|
+
return;
|
|
67
72
|
const action = getActionFromKey(event);
|
|
68
73
|
const items = this.$items;
|
|
69
74
|
const currentIndex = this.listController.currentIndex;
|
|
70
75
|
const maxIndex = items.length - 1;
|
|
71
|
-
switch(action){
|
|
76
|
+
switch (action) {
|
|
72
77
|
case MenuActions.Last:
|
|
73
78
|
case MenuActions.First:
|
|
74
79
|
case MenuActions.Next:
|
|
@@ -86,10 +91,10 @@ const Base = InternalsAttached(LitElement);
|
|
|
86
91
|
this.dispatchEvent(new CustomEvent('select', {
|
|
87
92
|
detail: {
|
|
88
93
|
item: items[currentIndex],
|
|
89
|
-
index: currentIndex
|
|
94
|
+
index: currentIndex,
|
|
90
95
|
},
|
|
91
96
|
bubbles: true,
|
|
92
|
-
composed: true
|
|
97
|
+
composed: true,
|
|
93
98
|
}));
|
|
94
99
|
}
|
|
95
100
|
return;
|
|
@@ -99,8 +104,10 @@ const Base = InternalsAttached(LitElement);
|
|
|
99
104
|
}
|
|
100
105
|
}
|
|
101
106
|
#handleFocusIn() {
|
|
102
|
-
if (this.currentIndex == -1)
|
|
103
|
-
|
|
107
|
+
if (this.currentIndex == -1)
|
|
108
|
+
this.listController.focusFirstItem();
|
|
109
|
+
else
|
|
110
|
+
this.$items[this.currentIndex].focused = true;
|
|
104
111
|
}
|
|
105
112
|
#handleFocusOut() {
|
|
106
113
|
this.$items[this.currentIndex].focused = false;
|
|
@@ -116,20 +123,22 @@ const Base = InternalsAttached(LitElement);
|
|
|
116
123
|
event.preventDefault(); // This makes sure that the container is focused
|
|
117
124
|
this.focus();
|
|
118
125
|
const item = this.#getEventItem(event);
|
|
119
|
-
if (!item || !this.listController.items.includes(item))
|
|
126
|
+
if (!item || !this.listController.items.includes(item))
|
|
127
|
+
return;
|
|
120
128
|
this.listController._focusItem(item);
|
|
121
129
|
}
|
|
122
130
|
#handleClick(event) {
|
|
123
131
|
this.focus();
|
|
124
132
|
const item = this.#getEventItem(event);
|
|
125
|
-
if (!item || !this.listController.items.includes(item))
|
|
133
|
+
if (!item || !this.listController.items.includes(item))
|
|
134
|
+
return;
|
|
126
135
|
this.dispatchEvent(new CustomEvent('select', {
|
|
127
136
|
detail: {
|
|
128
137
|
item: item,
|
|
129
|
-
index: this.listController.items.indexOf(item)
|
|
138
|
+
index: this.listController.items.indexOf(item),
|
|
130
139
|
},
|
|
131
140
|
bubbles: true,
|
|
132
|
-
composed: true
|
|
141
|
+
composed: true,
|
|
133
142
|
}));
|
|
134
143
|
}
|
|
135
144
|
#getEventItem(event) {
|
|
@@ -148,16 +157,11 @@ const Base = InternalsAttached(LitElement);
|
|
|
148
157
|
this.listController._focusItem(item);
|
|
149
158
|
}
|
|
150
159
|
}
|
|
151
|
-
|
|
152
|
-
property({
|
|
153
|
-
type: Boolean,
|
|
154
|
-
attribute: 'no-focus-control'
|
|
155
|
-
})
|
|
160
|
+
__decorate([
|
|
161
|
+
property({ type: Boolean, attribute: 'no-focus-control' })
|
|
156
162
|
], List.prototype, "noFocusControl", void 0);
|
|
157
|
-
|
|
158
|
-
queryAssignedElements({
|
|
159
|
-
flatten: true
|
|
160
|
-
})
|
|
163
|
+
__decorate([
|
|
164
|
+
queryAssignedElements({ flatten: true })
|
|
161
165
|
], List.prototype, "slotItems", void 0);
|
|
162
166
|
// Reference: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
|
|
163
167
|
export const MenuActions = {
|
|
@@ -171,10 +175,10 @@ export const MenuActions = {
|
|
|
171
175
|
PageUp: 7,
|
|
172
176
|
Previous: 8,
|
|
173
177
|
Select: 9,
|
|
174
|
-
Type: 10
|
|
178
|
+
Type: 10,
|
|
175
179
|
};
|
|
176
180
|
export function filterOptions(options = [], filter, exclude = []) {
|
|
177
|
-
return options.filter((option)=>{
|
|
181
|
+
return options.filter((option) => {
|
|
178
182
|
const matches = option.toLowerCase().indexOf(filter.toLowerCase()) === 0;
|
|
179
183
|
return matches && exclude.indexOf(option) < 0;
|
|
180
184
|
});
|
|
@@ -187,29 +191,37 @@ export function getActionFromKey(event) {
|
|
|
187
191
|
if (key === 'End') {
|
|
188
192
|
return MenuActions.Last;
|
|
189
193
|
}
|
|
190
|
-
if (key === 'Backspace' ||
|
|
194
|
+
if (key === 'Backspace' ||
|
|
195
|
+
key === 'Clear' ||
|
|
196
|
+
(key.length === 1 && key !== ' ' && !altKey && !ctrlKey && !metaKey)) {
|
|
191
197
|
return MenuActions.Type;
|
|
192
198
|
}
|
|
193
199
|
if (key === 'ArrowUp' && altKey) {
|
|
194
200
|
return MenuActions.CloseSelect;
|
|
195
|
-
}
|
|
201
|
+
}
|
|
202
|
+
else if (key === 'ArrowDown' && !altKey) {
|
|
196
203
|
return MenuActions.Next;
|
|
197
|
-
}
|
|
204
|
+
}
|
|
205
|
+
else if (key === 'ArrowUp') {
|
|
198
206
|
return MenuActions.Previous;
|
|
199
|
-
}
|
|
207
|
+
}
|
|
208
|
+
else if (key === 'PageUp') {
|
|
200
209
|
return MenuActions.PageUp;
|
|
201
|
-
}
|
|
210
|
+
}
|
|
211
|
+
else if (key === 'PageDown') {
|
|
202
212
|
return MenuActions.PageDown;
|
|
203
|
-
}
|
|
213
|
+
}
|
|
214
|
+
else if (key === 'Escape') {
|
|
204
215
|
return MenuActions.Close;
|
|
205
|
-
}
|
|
216
|
+
}
|
|
217
|
+
else if (key === 'Enter' || key === ' ') {
|
|
206
218
|
return MenuActions.CloseSelect;
|
|
207
219
|
}
|
|
208
220
|
return undefined;
|
|
209
221
|
}
|
|
210
222
|
export function getUpdatedIndex(currentIndex, maxIndex, action) {
|
|
211
223
|
const pageSize = 10;
|
|
212
|
-
switch(action){
|
|
224
|
+
switch (action) {
|
|
213
225
|
case MenuActions.First:
|
|
214
226
|
return 0;
|
|
215
227
|
case MenuActions.Last:
|
|
@@ -227,13 +239,15 @@ export function getUpdatedIndex(currentIndex, maxIndex, action) {
|
|
|
227
239
|
}
|
|
228
240
|
}
|
|
229
241
|
export function scrollItemIntoView(list, item, paddingY = 0) {
|
|
230
|
-
if (!list)
|
|
242
|
+
if (!list)
|
|
243
|
+
return;
|
|
231
244
|
// Basic scroll into view logic
|
|
232
245
|
const menuRect = list.getBoundingClientRect();
|
|
233
246
|
const itemRect = item.getBoundingClientRect();
|
|
234
247
|
if (itemRect.bottom + paddingY > menuRect.bottom) {
|
|
235
248
|
list.scrollTop += itemRect.bottom - menuRect.bottom + paddingY;
|
|
236
|
-
}
|
|
249
|
+
}
|
|
250
|
+
else if (itemRect.top - paddingY < menuRect.top) {
|
|
237
251
|
list.scrollTop -= menuRect.top - itemRect.top + paddingY;
|
|
238
252
|
}
|
|
239
253
|
}
|
package/src/base/menu-item.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ListItem } from './list-item.js';
|
|
2
|
-
export const MenuItemMixin = (superClass)=>{
|
|
2
|
+
export const MenuItemMixin = (superClass) => {
|
|
3
3
|
class MenuItemElement extends superClass {
|
|
4
|
-
constructor(
|
|
5
|
-
super(...
|
|
4
|
+
constructor() {
|
|
5
|
+
super(...arguments);
|
|
6
|
+
this._role = 'menuitem';
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
9
|
return MenuItemElement;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { Placement, Strategy } from '@floating-ui/dom';
|
|
3
|
+
import type { MenuItem } from './menu-item.js';
|
|
4
|
+
declare const Base: Constructor<import("./mixins/focus-delegated.js").FocusDelegatedInterface> & Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & Constructor<import("./mixins/attachable.js").AttachableInterface> & typeof LitElement;
|
|
5
|
+
interface MenuSelectDetail {
|
|
6
|
+
item: MenuItem;
|
|
7
|
+
index: number;
|
|
8
|
+
}
|
|
9
|
+
export type MenuSelectEvent = CustomEvent<MenuSelectDetail>;
|
|
10
|
+
interface ItemFocusDetail {
|
|
11
|
+
item: MenuItem;
|
|
12
|
+
}
|
|
13
|
+
export type MenuItemFocusEvent = CustomEvent<ItemFocusDetail>;
|
|
14
|
+
/**
|
|
15
|
+
* @csspart menu
|
|
16
|
+
* @csspart items
|
|
17
|
+
*
|
|
18
|
+
* @fires {Event} open - Fires when the menu is opened.
|
|
19
|
+
* @fires {Event} close - Fires when the menu is closed.
|
|
20
|
+
* @fires {MenuSelectEvent} select - Fires when an item is selected.
|
|
21
|
+
* @fires {MenuItemFocusEvent} item-focus - Fires when an item is focused
|
|
22
|
+
*/
|
|
23
|
+
export declare class Menu extends Base {
|
|
24
|
+
#private;
|
|
25
|
+
readonly _durations: {
|
|
26
|
+
show: number;
|
|
27
|
+
hide: number;
|
|
28
|
+
};
|
|
29
|
+
readonly _scrollPadding: number;
|
|
30
|
+
type: string;
|
|
31
|
+
open: boolean;
|
|
32
|
+
quick: boolean;
|
|
33
|
+
offset: number;
|
|
34
|
+
align: Placement;
|
|
35
|
+
alignStrategy: Strategy;
|
|
36
|
+
keepOpenBlur: boolean;
|
|
37
|
+
keepOpenSelect: boolean;
|
|
38
|
+
keepOpenClickAway: boolean;
|
|
39
|
+
noFocusControl: boolean;
|
|
40
|
+
tabIndex: number;
|
|
41
|
+
$menu: HTMLElement;
|
|
42
|
+
slotItems: Array<MenuItem | HTMLElement>;
|
|
43
|
+
get $items(): MenuItem[];
|
|
44
|
+
private $lastFocused;
|
|
45
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
46
|
+
renderItemSlot(): import("lit-html").TemplateResult<1>;
|
|
47
|
+
private readonly popoverController;
|
|
48
|
+
private readonly listController;
|
|
49
|
+
connectedCallback(): void;
|
|
50
|
+
disconnectedCallback(): void;
|
|
51
|
+
protected updated(changed: Map<string, any>): void;
|
|
52
|
+
get currentIndex(): number;
|
|
53
|
+
focusFirstItem(): void;
|
|
54
|
+
focusLastItem(): void;
|
|
55
|
+
focusItem(item: MenuItem): void;
|
|
56
|
+
show(): void;
|
|
57
|
+
close(): void;
|
|
58
|
+
}
|
|
59
|
+
export declare const MenuActions: {
|
|
60
|
+
Close: number;
|
|
61
|
+
CloseSelect: number;
|
|
62
|
+
First: number;
|
|
63
|
+
Last: number;
|
|
64
|
+
Next: number;
|
|
65
|
+
Open: number;
|
|
66
|
+
PageDown: number;
|
|
67
|
+
PageUp: number;
|
|
68
|
+
Previous: number;
|
|
69
|
+
Select: number;
|
|
70
|
+
Type: number;
|
|
71
|
+
};
|
|
72
|
+
export declare function filterOptions(options: string[], filter: string, exclude?: string[]): string[];
|
|
73
|
+
export declare function getActionFromKey(event: KeyboardEvent, menuOpen: boolean): number;
|
|
74
|
+
export declare function getUpdatedIndex(currentIndex: number, maxIndex: number, action: number): number;
|
|
75
|
+
export declare function scrollItemIntoView(menu: HTMLElement, item: HTMLElement, paddingY?: number): void;
|
|
76
|
+
export {};
|