@vollowx/seele 0.13.10 → 0.14.1
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/README.md +3 -3
- package/custom-elements.json +604 -359
- package/package.json +1 -1
- package/src/all.d.ts +2 -2
- package/src/all.js +2 -2
- package/src/base/autocomplete.d.ts +9 -33
- package/src/base/autocomplete.js +42 -65
- package/src/base/button.d.ts +0 -1
- package/src/base/button.js +7 -11
- package/src/base/checkbox.d.ts +0 -2
- package/src/base/checkbox.js +6 -13
- package/src/base/controllers/list-controller.d.ts +1 -0
- package/src/base/controllers/list-controller.js +6 -1
- package/src/base/dialog.d.ts +2 -2
- package/src/base/dialog.js +11 -2
- package/src/base/list-item.d.ts +1 -1
- package/src/base/list-item.js +11 -12
- package/src/base/list.d.ts +16 -33
- package/src/base/list.js +91 -173
- package/src/base/menu.d.ts +41 -61
- package/src/base/menu.js +184 -306
- package/src/base/{experimental/popup.d.ts → popup.d.ts} +7 -11
- package/src/base/{experimental/popup.js → popup.js} +45 -90
- package/src/base/radio.js +5 -5
- package/src/base/select.d.ts +7 -53
- package/src/base/select.js +45 -79
- package/src/base/tooltip.js +2 -2
- package/src/core/focus.d.ts +11 -0
- package/src/core/focus.js +53 -0
- package/src/m3/autocomplete/autocomplete-styles.css.js +1 -1
- package/src/m3/autocomplete/autocomplete.d.ts +1 -0
- package/src/m3/autocomplete/autocomplete.js +2 -1
- package/src/m3/button/common-button-styles.css.js +1 -1
- package/src/m3/button/icon-button-styles.css.js +1 -1
- package/src/m3/button/icon-button-toggle.js +1 -1
- package/src/m3/button/shared-button-styles.css.js +1 -1
- package/src/m3/button-group/standard-button-group.js +1 -1
- package/src/m3/checkbox/checkbox.js +1 -1
- package/src/m3/dialog/dialog.d.ts +2 -2
- package/src/m3/dialog/dialog.js +2 -2
- package/src/m3/field/field-styles.css.js +1 -1
- package/src/m3/field/field.js +2 -2
- package/src/m3/field/filled-field-styles.css.js +1 -1
- package/src/m3/field/filled-field.js +1 -1
- package/src/m3/field/outlined-field-styles.css.js +1 -1
- package/src/m3/focus-ring/focus-ring.js +1 -1
- package/src/m3/list/list-item.d.ts +2 -2
- package/src/m3/list/list-item.js +6 -6
- package/src/m3/menu/composed-menu.d.ts +19 -0
- package/src/m3/menu/composed-menu.js +42 -0
- package/src/m3/menu/menu-styles.css.js +1 -1
- package/src/m3/menu/menu.d.ts +1 -7
- package/src/m3/menu/menu.js +1 -13
- package/src/m3/navigation/navigation-rail-item-styles.css.js +1 -1
- package/src/m3/popup/popup-styles.css.js +2 -0
- package/src/m3/{experimental → popup}/popup.d.ts +2 -1
- package/src/m3/popup/popup.js +18 -0
- package/src/m3/radio/radio.js +1 -1
- package/src/m3/ripple/ripple.js +3 -3
- package/src/m3/select/filled-select.d.ts +2 -2
- package/src/m3/select/filled-select.js +5 -5
- package/src/m3/select/outlined-select.d.ts +2 -2
- package/src/m3/select/outlined-select.js +5 -5
- package/src/m3/select/select-styles.css.js +1 -1
- package/src/m3/select/select.d.ts +2 -5
- package/src/m3/select/select.js +3 -6
- package/src/m3/styles/color-default-dark.css +51 -0
- package/src/m3/styles/color-default-light.css +51 -0
- package/src/m3/switch/switch-styles.css.js +1 -1
- package/src/m3/switch/switch.js +1 -1
- package/src/m3/tab/tabs-styles.css.js +1 -1
- package/src/m3/tab/tabs.js +1 -1
- package/src/m3/text-field/filled-text-field.js +2 -2
- package/src/m3/text-field/outlined-text-field.js +2 -2
- package/src/m3/tooltip/tooltip-styles.css.js +1 -1
- package/src/core/focus-visible.d.ts +0 -2
- package/src/core/focus-visible.js +0 -13
- package/src/m3/experimental/popup-styles.css.js +0 -2
- package/src/m3/experimental/popup.js +0 -11
- /package/src/base/{experimental/popup-styles.css.js → popup-styles.css.js} +0 -0
package/package.json
CHANGED
package/src/all.d.ts
CHANGED
|
@@ -17,8 +17,10 @@ import './m3/list/list-item.js';
|
|
|
17
17
|
import './m3/loading-indicator/loading-indicator.js';
|
|
18
18
|
import './m3/menu/menu.js';
|
|
19
19
|
import './m3/menu/menu-item.js';
|
|
20
|
+
import './m3/menu/composed-menu.js';
|
|
20
21
|
import './m3/navigation/navigation-rail.js';
|
|
21
22
|
import './m3/navigation/navigation-rail-item.js';
|
|
23
|
+
import './m3/popup/popup.js';
|
|
22
24
|
import './m3/radio/radio.js';
|
|
23
25
|
import './m3/ripple/ripple.js';
|
|
24
26
|
import './m3/select/filled-select.js';
|
|
@@ -35,5 +37,3 @@ import './m3/text-field/outlined-text-field.js';
|
|
|
35
37
|
import './m3/toolbar/toolbar.js';
|
|
36
38
|
import './m3/tooltip/tooltip.js';
|
|
37
39
|
import './win98/button/button.js';
|
|
38
|
-
import './base/experimental/popup.js';
|
|
39
|
-
import './m3/experimental/popup.js';
|
package/src/all.js
CHANGED
|
@@ -17,8 +17,10 @@ import './m3/list/list-item.js';
|
|
|
17
17
|
import './m3/loading-indicator/loading-indicator.js';
|
|
18
18
|
import './m3/menu/menu.js';
|
|
19
19
|
import './m3/menu/menu-item.js';
|
|
20
|
+
import './m3/menu/composed-menu.js';
|
|
20
21
|
import './m3/navigation/navigation-rail.js';
|
|
21
22
|
import './m3/navigation/navigation-rail-item.js';
|
|
23
|
+
import './m3/popup/popup.js';
|
|
22
24
|
import './m3/radio/radio.js';
|
|
23
25
|
import './m3/ripple/ripple.js';
|
|
24
26
|
import './m3/select/filled-select.js';
|
|
@@ -35,5 +37,3 @@ import './m3/text-field/outlined-text-field.js';
|
|
|
35
37
|
import './m3/toolbar/toolbar.js';
|
|
36
38
|
import './m3/tooltip/tooltip.js';
|
|
37
39
|
import './win98/button/button.js';
|
|
38
|
-
import './base/experimental/popup.js';
|
|
39
|
-
import './m3/experimental/popup.js';
|
|
@@ -1,57 +1,33 @@
|
|
|
1
1
|
import { LitElement, PropertyValues } from 'lit';
|
|
2
|
-
import type {
|
|
3
|
-
import type { Menu,
|
|
2
|
+
import type { Popup } from './popup.js';
|
|
3
|
+
import type { Menu, MenuActionEvent } from './menu.js';
|
|
4
4
|
declare const Base: Constructor<import("./mixins/focus-delegated.js").FocusDelegatedInterface> & Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
|
|
5
|
-
type AutocompleteMode = 'none' | 'list' | 'both';
|
|
5
|
+
export type AutocompleteMode = 'none' | 'list' | 'both';
|
|
6
6
|
/**
|
|
7
7
|
* TODO: Check if manually dispatching input/change events on input is necessary
|
|
8
|
-
* TODO: handle slotchange
|
|
9
8
|
*/
|
|
10
9
|
export declare class Autocomplete extends Base {
|
|
10
|
+
#private;
|
|
11
11
|
open: boolean;
|
|
12
|
-
quick: boolean;
|
|
13
|
-
offset: number;
|
|
14
|
-
align: Placement;
|
|
15
|
-
alignStrategy: Strategy;
|
|
16
|
-
keepOpenSelect: boolean;
|
|
17
12
|
mode: AutocompleteMode;
|
|
13
|
+
$popup: Popup;
|
|
18
14
|
$menu: Menu;
|
|
19
15
|
inputSlotElements: HTMLElement[];
|
|
20
16
|
itemSlotElements: HTMLElement[];
|
|
21
17
|
private get $input();
|
|
22
18
|
render(): import("lit-html").TemplateResult<1>;
|
|
23
19
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* ```html
|
|
27
|
-
* <your-menu
|
|
28
|
-
* part="menu"
|
|
29
|
-
* id="menu"
|
|
30
|
-
* type="listbox"
|
|
31
|
-
* data-tabindex="-1"
|
|
32
|
-
* ?quick="${this.quick}"
|
|
33
|
-
* .offset=${this.offset}
|
|
34
|
-
* .align=${this.align}
|
|
35
|
-
* .alignStrategy=${this.alignStrategy}
|
|
36
|
-
* ?keep-open-select=${this.keepOpenSelect}
|
|
37
|
-
* no-focus-control
|
|
38
|
-
* ?open=${this.open}
|
|
39
|
-
* @open="${() => (this.open = true)}"
|
|
40
|
-
* @close="${() => (this.open = false)}"
|
|
41
|
-
* @select=${this.handleMenuSelect}
|
|
42
|
-
* >
|
|
43
|
-
* <slot @slotchange=${this.handleItemsSlotChange}></slot>
|
|
44
|
-
* </your-menu>
|
|
45
|
-
* ```
|
|
20
|
+
* Check example content from the m3 implementation
|
|
46
21
|
*/
|
|
47
22
|
renderMenu(): import("lit-html").TemplateResult<1>;
|
|
23
|
+
constructor();
|
|
48
24
|
private handleInputSlotChange;
|
|
49
|
-
protected handleItemsSlotChange(): void
|
|
25
|
+
protected handleItemsSlotChange(): Promise<void>;
|
|
50
26
|
private handleInput;
|
|
51
27
|
private applyInlineAutoComplete;
|
|
52
28
|
private filterOptions;
|
|
53
29
|
private handleInputKeydown;
|
|
54
|
-
protected
|
|
30
|
+
protected handleMenuAction(event: MenuActionEvent): void;
|
|
55
31
|
protected updated(changed: PropertyValues): void;
|
|
56
32
|
}
|
|
57
33
|
export {};
|
package/src/base/autocomplete.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { LitElement, html } from 'lit';
|
|
2
|
+
import { LitElement, html, isServer } from 'lit';
|
|
3
3
|
import { property, query, queryAssignedElements } from 'lit/decorators.js';
|
|
4
4
|
import { ensureReady } from '../core/ensure-ready.js';
|
|
5
5
|
import { InternalsAttached } from './mixins/internals-attached.js';
|
|
@@ -7,20 +7,8 @@ import { FocusDelegated } from './mixins/focus-delegated.js';
|
|
|
7
7
|
const Base = FocusDelegated(InternalsAttached(LitElement));
|
|
8
8
|
/**
|
|
9
9
|
* TODO: Check if manually dispatching input/change events on input is necessary
|
|
10
|
-
* TODO: handle slotchange
|
|
11
10
|
*/
|
|
12
11
|
export class Autocomplete extends Base {
|
|
13
|
-
constructor() {
|
|
14
|
-
super(...arguments);
|
|
15
|
-
this.open = false;
|
|
16
|
-
// Passed to menu
|
|
17
|
-
this.quick = false;
|
|
18
|
-
this.offset = 0;
|
|
19
|
-
this.align = 'bottom-start';
|
|
20
|
-
this.alignStrategy = 'absolute';
|
|
21
|
-
this.keepOpenSelect = false;
|
|
22
|
-
this.mode = 'none';
|
|
23
|
-
}
|
|
24
12
|
get $input() {
|
|
25
13
|
return this.inputSlotElements[0];
|
|
26
14
|
}
|
|
@@ -28,32 +16,35 @@ export class Autocomplete extends Base {
|
|
|
28
16
|
return html `<slot name="input" @slotchange="${this.handleInputSlotChange}"></slot>${this.renderMenu()}`;
|
|
29
17
|
}
|
|
30
18
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* ```html
|
|
34
|
-
* <your-menu
|
|
35
|
-
* part="menu"
|
|
36
|
-
* id="menu"
|
|
37
|
-
* type="listbox"
|
|
38
|
-
* data-tabindex="-1"
|
|
39
|
-
* ?quick="${this.quick}"
|
|
40
|
-
* .offset=${this.offset}
|
|
41
|
-
* .align=${this.align}
|
|
42
|
-
* .alignStrategy=${this.alignStrategy}
|
|
43
|
-
* ?keep-open-select=${this.keepOpenSelect}
|
|
44
|
-
* no-focus-control
|
|
45
|
-
* ?open=${this.open}
|
|
46
|
-
* @open="${() => (this.open = true)}"
|
|
47
|
-
* @close="${() => (this.open = false)}"
|
|
48
|
-
* @select=${this.handleMenuSelect}
|
|
49
|
-
* >
|
|
50
|
-
* <slot @slotchange=${this.handleItemsSlotChange}></slot>
|
|
51
|
-
* </your-menu>
|
|
52
|
-
* ```
|
|
19
|
+
* Check example content from the m3 implementation
|
|
53
20
|
*/
|
|
54
21
|
renderMenu() {
|
|
55
22
|
return html ``;
|
|
56
23
|
}
|
|
24
|
+
constructor() {
|
|
25
|
+
super();
|
|
26
|
+
this.open = false;
|
|
27
|
+
this.mode = 'none';
|
|
28
|
+
if (!isServer) {
|
|
29
|
+
this.addEventListener('focusout', this.#handleFocusOut.bind(this));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
#handleFocusOut(event) {
|
|
33
|
+
if (!this.open)
|
|
34
|
+
return;
|
|
35
|
+
const target = event.relatedTarget;
|
|
36
|
+
if (target && this.contains(target)) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (target) {
|
|
40
|
+
this.$popup.hide();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
requestAnimationFrame(() => {
|
|
44
|
+
if (!document.hasFocus())
|
|
45
|
+
this.$popup.hide();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
57
48
|
// TODO: handle multiple calls on this function, currently double-call
|
|
58
49
|
// disallowed
|
|
59
50
|
async handleInputSlotChange() {
|
|
@@ -61,16 +52,15 @@ export class Autocomplete extends Base {
|
|
|
61
52
|
const input = this.$input;
|
|
62
53
|
const $realInput = input.$inputOrTextarea;
|
|
63
54
|
$realInput.role = 'combobox';
|
|
64
|
-
$realInput.ariaExpanded = String(this.open);
|
|
65
55
|
$realInput.ariaHasPopup = 'listbox';
|
|
66
56
|
$realInput.ariaAutoComplete = this.mode;
|
|
67
57
|
$realInput.ariaControlsElements = [this.$menu];
|
|
68
58
|
input.addEventListener('input', this.handleInput.bind(this));
|
|
69
59
|
input.addEventListener('keydown', this.handleInputKeydown.bind(this));
|
|
70
|
-
|
|
71
|
-
this.$
|
|
60
|
+
this.$popup.$ariaControl = $realInput;
|
|
61
|
+
this.$popup.attach(input);
|
|
72
62
|
}
|
|
73
|
-
handleItemsSlotChange() {
|
|
63
|
+
async handleItemsSlotChange() {
|
|
74
64
|
// Initial filter based on current input value (if any)
|
|
75
65
|
this.filterOptions(this.$input?.value || '');
|
|
76
66
|
}
|
|
@@ -113,15 +103,17 @@ export class Autocomplete extends Base {
|
|
|
113
103
|
if (this.$input?.disabled)
|
|
114
104
|
return;
|
|
115
105
|
if (['Enter', 'Escape', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
106
|
+
if (!this.open && ['ArrowUp', 'ArrowDown'].includes(event.key)) {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
this.open = true;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (this.open) {
|
|
112
|
+
this.$menu.handleKeyDown(event);
|
|
113
|
+
}
|
|
122
114
|
}
|
|
123
115
|
}
|
|
124
|
-
|
|
116
|
+
handleMenuAction(event) {
|
|
125
117
|
const selectedItem = event.detail.item;
|
|
126
118
|
const newValue = selectedItem.getAttribute('value') ||
|
|
127
119
|
selectedItem.textContent?.trim() ||
|
|
@@ -129,9 +121,6 @@ export class Autocomplete extends Base {
|
|
|
129
121
|
if (this.$input) {
|
|
130
122
|
this.$input.value = newValue;
|
|
131
123
|
}
|
|
132
|
-
if (!this.keepOpenSelect) {
|
|
133
|
-
this.open = false;
|
|
134
|
-
}
|
|
135
124
|
}
|
|
136
125
|
updated(changed) {
|
|
137
126
|
if (changed.has('open') && this.$input) {
|
|
@@ -145,26 +134,14 @@ export class Autocomplete extends Base {
|
|
|
145
134
|
__decorate([
|
|
146
135
|
property({ type: Boolean })
|
|
147
136
|
], Autocomplete.prototype, "open", void 0);
|
|
148
|
-
__decorate([
|
|
149
|
-
property({ type: Boolean })
|
|
150
|
-
], Autocomplete.prototype, "quick", void 0);
|
|
151
|
-
__decorate([
|
|
152
|
-
property({ type: Number })
|
|
153
|
-
], Autocomplete.prototype, "offset", void 0);
|
|
154
|
-
__decorate([
|
|
155
|
-
property({ reflect: true })
|
|
156
|
-
], Autocomplete.prototype, "align", void 0);
|
|
157
|
-
__decorate([
|
|
158
|
-
property({ type: String, reflect: true, attribute: 'align-strategy' })
|
|
159
|
-
], Autocomplete.prototype, "alignStrategy", void 0);
|
|
160
|
-
__decorate([
|
|
161
|
-
property({ type: Boolean, attribute: 'keep-open-select' })
|
|
162
|
-
], Autocomplete.prototype, "keepOpenSelect", void 0);
|
|
163
137
|
__decorate([
|
|
164
138
|
property()
|
|
165
139
|
], Autocomplete.prototype, "mode", void 0);
|
|
166
140
|
__decorate([
|
|
167
|
-
query('[part=
|
|
141
|
+
query('[part=popup]')
|
|
142
|
+
], Autocomplete.prototype, "$popup", void 0);
|
|
143
|
+
__decorate([
|
|
144
|
+
query('[part=menu]')
|
|
168
145
|
], Autocomplete.prototype, "$menu", void 0);
|
|
169
146
|
__decorate([
|
|
170
147
|
queryAssignedElements({ slot: 'input', flatten: true })
|
package/src/base/button.d.ts
CHANGED
package/src/base/button.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { LitElement } from 'lit';
|
|
2
|
+
import { isServer, LitElement } from 'lit';
|
|
3
3
|
import { property } from 'lit/decorators.js';
|
|
4
4
|
import { InternalsAttached, internals, updateInternals, } from './mixins/internals-attached.js';
|
|
5
5
|
import { FormAssociated } from './mixins/form-associated.js';
|
|
@@ -23,7 +23,7 @@ export class Button extends Base {
|
|
|
23
23
|
// TODO: supporting `Enter` also requires listening on `focusout`
|
|
24
24
|
};
|
|
25
25
|
this.#handleKeyUp = (e) => {
|
|
26
|
-
if (e.key === ' ') {
|
|
26
|
+
if (e.key === ' ' && this[internals].states.has('active')) {
|
|
27
27
|
this[internals].states.delete('active');
|
|
28
28
|
e.preventDefault();
|
|
29
29
|
e.stopPropagation();
|
|
@@ -37,20 +37,16 @@ export class Button extends Base {
|
|
|
37
37
|
// Double `requestAnimationFrame` is necessary since the callback inside is
|
|
38
38
|
// called before the nth frame is printed.
|
|
39
39
|
this.setAttribute('notransition', '');
|
|
40
|
+
if (!isServer) {
|
|
41
|
+
this.addEventListener('keydown', this.#handleKeyDown);
|
|
42
|
+
this.addEventListener('keyup', this.#handleKeyUp);
|
|
43
|
+
this.addEventListener('click', this._handleClick.bind(this));
|
|
44
|
+
}
|
|
40
45
|
}
|
|
41
46
|
connectedCallback() {
|
|
42
47
|
super.connectedCallback();
|
|
43
|
-
this.addEventListener('keydown', this.#handleKeyDown);
|
|
44
|
-
this.addEventListener('keyup', this.#handleKeyUp);
|
|
45
|
-
this.addEventListener('click', this._handleClick.bind(this));
|
|
46
48
|
requestAnimationFrame(() => requestAnimationFrame(() => this.removeAttribute('notransition')));
|
|
47
49
|
}
|
|
48
|
-
disconnectedCallback() {
|
|
49
|
-
super.disconnectedCallback();
|
|
50
|
-
this.removeEventListener('keydown', this.#handleKeyDown);
|
|
51
|
-
this.removeEventListener('keyup', this.#handleKeyUp);
|
|
52
|
-
this.removeEventListener('click', this._handleClick.bind(this));
|
|
53
|
-
}
|
|
54
50
|
updated(changed) {
|
|
55
51
|
if (changed.has('disabled'))
|
|
56
52
|
this[updateInternals]();
|
package/src/base/checkbox.d.ts
CHANGED
|
@@ -7,8 +7,6 @@ export declare class Checkbox extends Base {
|
|
|
7
7
|
required: boolean;
|
|
8
8
|
static styles: any[];
|
|
9
9
|
constructor();
|
|
10
|
-
connectedCallback(): void;
|
|
11
|
-
disconnectedCallback(): void;
|
|
12
10
|
protected updated(changed: Map<string, any>): void;
|
|
13
11
|
protected updateState(): void;
|
|
14
12
|
protected toggleChecked(): void;
|
package/src/base/checkbox.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { LitElement } from 'lit';
|
|
2
|
+
import { isServer, LitElement } from 'lit';
|
|
3
3
|
import { property } from 'lit/decorators.js';
|
|
4
4
|
import { FormAssociated } from './mixins/form-associated.js';
|
|
5
5
|
import { InternalsAttached, internals, replaceStates, } from './mixins/internals-attached.js';
|
|
@@ -39,18 +39,11 @@ export class Checkbox extends Base {
|
|
|
39
39
|
this.checked = this.hasAttribute('checked');
|
|
40
40
|
this.indeterminate = this.hasAttribute('indeterminate');
|
|
41
41
|
this.updateState();
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.addEventListener('keyup', this.#handleKeyUp);
|
|
48
|
-
}
|
|
49
|
-
disconnectedCallback() {
|
|
50
|
-
this.removeEventListener('click', this.#handleClick);
|
|
51
|
-
this.removeEventListener('keydown', this.#handleKeyDown);
|
|
52
|
-
this.removeEventListener('keyup', this.#handleKeyUp);
|
|
53
|
-
super.disconnectedCallback();
|
|
42
|
+
if (!isServer) {
|
|
43
|
+
this.addEventListener('click', this.#handleClick);
|
|
44
|
+
this.addEventListener('keydown', this.#handleKeyDown);
|
|
45
|
+
this.addEventListener('keyup', this.#handleKeyUp);
|
|
46
|
+
}
|
|
54
47
|
}
|
|
55
48
|
updated(changed) {
|
|
56
49
|
if (changed.has('checked') ||
|
|
@@ -34,4 +34,5 @@ export declare class ListController<Item extends ListItem> implements ReactiveCo
|
|
|
34
34
|
focusPreviousItem(): void;
|
|
35
35
|
handleSlotChange(): void;
|
|
36
36
|
}
|
|
37
|
+
export declare function filterOptions(options: string[], filter: string, exclude?: string[]): string[];
|
|
37
38
|
export declare function getIndexByLetter(options: string[], filter: string, startIndex?: number): number;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { filterOptions } from '../menu.js';
|
|
2
1
|
export class ListController {
|
|
3
2
|
constructor(host, config) {
|
|
4
3
|
this._focusedItem = null;
|
|
@@ -99,6 +98,12 @@ export class ListController {
|
|
|
99
98
|
this._focusedItem = index >= 0 ? items[index] : null;
|
|
100
99
|
}
|
|
101
100
|
}
|
|
101
|
+
export function filterOptions(options = [], filter, exclude = []) {
|
|
102
|
+
return options.filter((option) => {
|
|
103
|
+
const matches = option.toLowerCase().indexOf(filter.toLowerCase()) === 0;
|
|
104
|
+
return matches && exclude.indexOf(option) < 0;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
102
107
|
export function getIndexByLetter(options, filter, startIndex = 0) {
|
|
103
108
|
const orderedOptions = [
|
|
104
109
|
...options.slice(startIndex),
|
package/src/base/dialog.d.ts
CHANGED
package/src/base/dialog.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import { LitElement } from 'lit';
|
|
3
3
|
import { query } from 'lit/decorators.js';
|
|
4
|
+
import { getFirstTabbable } from '../core/focus.js';
|
|
4
5
|
/**
|
|
5
6
|
* @csspart dialog
|
|
6
7
|
*
|
|
@@ -22,10 +23,18 @@ export class Dialog extends LitElement {
|
|
|
22
23
|
this.close();
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
|
-
show() {
|
|
26
|
+
async show() {
|
|
26
27
|
this.$dialog.showModal();
|
|
28
|
+
const autoFocus = this.querySelector('[autofocus]');
|
|
29
|
+
if (autoFocus) {
|
|
30
|
+
autoFocus.focus();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const firstTabbable = getFirstTabbable(this);
|
|
34
|
+
firstTabbable?.focus();
|
|
35
|
+
}
|
|
27
36
|
}
|
|
28
|
-
close() {
|
|
37
|
+
async close() {
|
|
29
38
|
this.$dialog.close();
|
|
30
39
|
}
|
|
31
40
|
}
|
package/src/base/list-item.d.ts
CHANGED
package/src/base/list-item.js
CHANGED
|
@@ -1,29 +1,28 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { LitElement } from 'lit';
|
|
2
|
+
import { isServer, LitElement } from 'lit';
|
|
3
3
|
import { property } from 'lit/decorators.js';
|
|
4
|
-
import { genUniqueId } from '../core/unique-id.js';
|
|
5
4
|
import { InternalsAttached, internals } from './mixins/internals-attached.js';
|
|
6
5
|
import { FormAssociated } from './mixins/form-associated.js';
|
|
7
6
|
import { hiddenStyles } from './hidden-styles.css.js';
|
|
8
7
|
export class ListItem extends FormAssociated(InternalsAttached(LitElement)) {
|
|
9
|
-
constructor() {
|
|
10
|
-
super(...arguments);
|
|
11
|
-
this._role = 'option';
|
|
12
|
-
this.selected = false;
|
|
13
|
-
this.focused = false;
|
|
14
|
-
}
|
|
15
8
|
static { this.styles = [hiddenStyles]; }
|
|
16
9
|
get displayText() {
|
|
17
10
|
return this.innerText.trim();
|
|
18
11
|
}
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
// Accessibility tools, particularly Narrator, only fires `click` event on
|
|
13
|
+
// elements that have listeners for them.
|
|
14
|
+
#handleDummy() { }
|
|
15
|
+
constructor() {
|
|
16
|
+
super();
|
|
17
|
+
this._role = 'option';
|
|
18
|
+
this.selected = false;
|
|
19
|
+
this.focused = false;
|
|
21
20
|
this.setAttribute('seele-base', 'option');
|
|
22
21
|
this[internals].role = this._role;
|
|
23
22
|
this.setAttribute('tabindex', '-1');
|
|
24
23
|
this.#updateInternals();
|
|
25
|
-
if (!
|
|
26
|
-
this.
|
|
24
|
+
if (!isServer)
|
|
25
|
+
this.addEventListener('click', this.#handleDummy);
|
|
27
26
|
}
|
|
28
27
|
updated(changed) {
|
|
29
28
|
super.updated(changed);
|
package/src/base/list.d.ts
CHANGED
|
@@ -1,54 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TODO: currently list and menu has too much in common, should be split into
|
|
3
|
+
* menu, listbox and a LinearFocusController for tabs/toolbars
|
|
4
|
+
*/
|
|
1
5
|
import { LitElement } from 'lit';
|
|
2
6
|
import type { ListItem } from './list-item.js';
|
|
3
|
-
|
|
4
|
-
interface ListSelectDetail {
|
|
7
|
+
export interface ListboxSelectDetail {
|
|
5
8
|
item: ListItem;
|
|
6
9
|
index: number;
|
|
7
10
|
}
|
|
8
|
-
export type
|
|
9
|
-
interface ItemFocusDetail {
|
|
11
|
+
export type ListboxSelectEvent = CustomEvent<ListboxSelectDetail>;
|
|
12
|
+
export interface ItemFocusDetail {
|
|
10
13
|
item: ListItem;
|
|
14
|
+
index: number;
|
|
11
15
|
}
|
|
12
16
|
export type ListItemFocusEvent = CustomEvent<ItemFocusDetail>;
|
|
17
|
+
declare const List_base: Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
|
|
13
18
|
/**
|
|
14
19
|
* @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.
|
|
20
|
+
* @fires {ListboxSelectEvent} select - Fires when an item is selected.
|
|
19
21
|
* @fires {ListItemFocusEvent} item-focus - Fires when an item is focused
|
|
20
22
|
*/
|
|
21
|
-
export declare class List extends
|
|
23
|
+
export declare class List extends List_base {
|
|
22
24
|
#private;
|
|
23
|
-
readonly _scrollPadding: number;
|
|
24
25
|
noFocusControl: boolean;
|
|
25
|
-
slotItems: Array<ListItem
|
|
26
|
+
slotItems: Array<ListItem>;
|
|
26
27
|
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
28
|
get currentIndex(): number;
|
|
33
29
|
focusFirstItem(): void;
|
|
34
30
|
focusLastItem(): void;
|
|
35
31
|
focusItem(item: ListItem): void;
|
|
32
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
33
|
+
private readonly listController;
|
|
34
|
+
constructor();
|
|
35
|
+
handleKeyDown(event: KeyboardEvent): void;
|
|
36
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
37
|
export {};
|