@vollowx/seele 0.13.7 → 0.13.9
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 +33 -15
- package/package.json +2 -2
- package/src/all.d.ts +5 -0
- package/src/all.js +5 -0
- package/src/base/autocomplete.js +13 -13
- package/src/base/button.d.ts +4 -2
- package/src/base/button.js +15 -11
- package/src/base/checkbox.js +3 -8
- package/src/base/controllers/popover-controller.js +1 -1
- package/src/base/experimental/popup-styles.css.js +2 -0
- package/src/base/experimental/popup.d.ts +40 -0
- package/src/base/experimental/popup.js +278 -0
- package/src/base/mixins/attachable.d.ts +5 -2
- package/src/base/mixins/attachable.js +63 -23
- package/src/base/mixins/button-toggle-mixin.d.ts +7 -0
- package/src/base/mixins/button-toggle-mixin.js +101 -0
- package/src/base/mixins/internals-attached.d.ts +4 -0
- package/src/base/mixins/internals-attached.js +6 -0
- package/src/base/radio.d.ts +3 -0
- package/src/base/radio.js +28 -16
- package/src/base/tab-panel.d.ts +3 -3
- package/src/base/tab-panel.js +9 -11
- package/src/base/tab.d.ts +2 -8
- package/src/base/tab.js +16 -35
- package/src/base/tabs.d.ts +6 -6
- package/src/base/tabs.js +101 -99
- package/src/base/toggle-button.d.ts +6 -45
- package/src/base/toggle-button.js +6 -135
- package/src/base/tooltip.d.ts +2 -1
- package/src/base/tooltip.js +2 -2
- package/src/core/ensure-ready.d.ts +2 -1
- package/src/core/ensure-ready.js +12 -7
- package/src/m3/button/common-button-toggle.d.ts +4 -10
- package/src/m3/button/common-button-toggle.js +6 -40
- package/src/m3/button/icon-button-toggle.d.ts +4 -6
- package/src/m3/button/icon-button-toggle.js +6 -33
- package/src/m3/button/shared-button-styles.css.js +1 -1
- package/src/m3/button/shared-button-toggle-styles.css.js +1 -1
- package/src/m3/button-group/standard-button-group-styles.css.js +1 -1
- package/src/m3/button-group/standard-button-group.d.ts +2 -0
- package/src/m3/button-group/standard-button-group.js +44 -38
- package/src/m3/checkbox/checkbox-styles.css.js +1 -1
- package/src/m3/checkbox/checkbox.d.ts +1 -1
- package/src/m3/checkbox/checkbox.js +2 -5
- package/src/m3/dialog/dialog-styles.css.js +1 -1
- package/src/m3/dialog/dialog.d.ts +3 -1
- package/src/m3/dialog/dialog.js +6 -4
- package/src/m3/experimental/popup-styles.css.js +2 -0
- package/src/m3/experimental/popup.d.ts +9 -0
- package/src/m3/experimental/popup.js +11 -0
- package/src/m3/fab/fab-styles.css.js +1 -1
- package/src/m3/field/field-styles.css.js +1 -1
- package/src/m3/field/filled-field-styles.css.js +1 -1
- package/src/m3/focus-ring/focus-ring-styles.css.js +1 -1
- package/src/m3/focus-ring/focus-ring.d.ts +2 -1
- package/src/m3/focus-ring/focus-ring.js +4 -7
- package/src/m3/list/list-item-styles.css.js +1 -1
- package/src/m3/menu/menu-styles.css.js +1 -1
- package/src/m3/nagivation/navigation-rail-item-styles.css.js +2 -0
- package/src/m3/nagivation/navigation-rail-item.d.ts +21 -0
- package/src/m3/nagivation/navigation-rail-item.js +44 -0
- package/src/m3/nagivation/navigation-rail-styles.css.js +2 -0
- package/src/m3/nagivation/navigation-rail.d.ts +12 -0
- package/src/m3/nagivation/navigation-rail.js +17 -0
- package/src/m3/radio/radio-styles.css.js +1 -1
- package/src/m3/radio/radio.d.ts +3 -0
- package/src/m3/radio/radio.js +12 -4
- package/src/m3/ripple/ripple-styles.css.js +1 -1
- package/src/m3/ripple/ripple.d.ts +3 -13
- package/src/m3/ripple/ripple.js +28 -31
- package/src/m3/{system → styles}/defaults.css +1 -1
- package/src/m3/styles/motion-expressive.css +15 -0
- package/src/m3/styles/motion-standard.css +15 -0
- package/src/m3/styles/typography.css +24 -0
- package/src/m3/switch/switch-styles.css.js +1 -1
- package/src/m3/switch/switch.d.ts +4 -2
- package/src/m3/switch/switch.js +14 -12
- package/src/m3/tab/secondary-tab-styles.css.js +2 -0
- package/src/m3/tab/secondary-tab.d.ts +5 -0
- package/src/m3/tab/secondary-tab.js +15 -0
- package/src/m3/tab/tab-panel-styles.css.js +1 -1
- package/src/m3/tab/tab-styles.css.js +1 -1
- package/src/m3/tab/tab.d.ts +3 -0
- package/src/m3/tab/tab.js +68 -3
- package/src/m3/tab/tabs-styles.css.js +1 -1
- package/src/m3/tab/tabs.d.ts +1 -7
- package/src/m3/tab/tabs.js +6 -39
- package/src/m3/toolbar/toolbar-styles.css.js +1 -1
- package/src/win98/button/button-styles.css.js +1 -1
- package/src/m3/system/typography.css +0 -34
- /package/src/m3/{system → styles}/base.css +0 -0
- /package/src/m3/{system → styles}/elevation.css +0 -0
- /package/src/m3/{system → styles}/motion.d.ts +0 -0
- /package/src/m3/{system → styles}/motion.js +0 -0
package/src/base/tabs.js
CHANGED
|
@@ -1,133 +1,138 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { LitElement, html } from 'lit';
|
|
3
|
-
import { property
|
|
2
|
+
import { LitElement, html, isServer } from 'lit';
|
|
3
|
+
import { property } from 'lit/decorators.js';
|
|
4
4
|
import { internals } from './mixins/internals-attached.js';
|
|
5
5
|
/**
|
|
6
|
-
* @fires {CustomEvent}
|
|
6
|
+
* @fires {CustomEvent} select
|
|
7
7
|
*/
|
|
8
8
|
export class Tabs extends LitElement {
|
|
9
|
-
constructor() {
|
|
10
|
-
super(...arguments);
|
|
11
|
-
this._role = 'tablist';
|
|
12
|
-
this.switch = 'manual';
|
|
13
|
-
this.selected = '';
|
|
14
|
-
this.#handleSlotChange = (_) => {
|
|
15
|
-
const parent = this.$parent;
|
|
16
|
-
this.$tabs.forEach((tab) => {
|
|
17
|
-
const panel = parent.querySelector(`[seele-base="tab"][value="${tab.value}"]`);
|
|
18
|
-
if (!panel)
|
|
19
|
-
console.error('[seele] cannot find a matching panel for tab ', tab);
|
|
20
|
-
// TODO: ariaLabelledByElements
|
|
21
|
-
tab.setAttribute('aria-controls', panel.id);
|
|
22
|
-
panel.setAttribute('aria-labelledby', tab.id);
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
this.#handleKeyDown = (event) => {
|
|
26
|
-
const tabs = this.$tabs;
|
|
27
|
-
if (!tabs.length)
|
|
28
|
-
return;
|
|
29
|
-
const activeElement = this.getRootNode()
|
|
30
|
-
.activeElement;
|
|
31
|
-
const currentIndex = tabs.findIndex((t) => t === activeElement || t.focused);
|
|
32
|
-
let nextIndex = currentIndex !== -1 ? currentIndex : 0;
|
|
33
|
-
let handled = false;
|
|
34
|
-
switch (event.key) {
|
|
35
|
-
case 'ArrowLeft':
|
|
36
|
-
nextIndex = currentIndex <= 0 ? tabs.length - 1 : currentIndex - 1;
|
|
37
|
-
handled = true;
|
|
38
|
-
break;
|
|
39
|
-
case 'ArrowRight':
|
|
40
|
-
nextIndex = currentIndex >= tabs.length - 1 ? 0 : currentIndex + 1;
|
|
41
|
-
handled = true;
|
|
42
|
-
break;
|
|
43
|
-
case 'Home':
|
|
44
|
-
nextIndex = 0;
|
|
45
|
-
handled = true;
|
|
46
|
-
break;
|
|
47
|
-
case 'End':
|
|
48
|
-
nextIndex = tabs.length - 1;
|
|
49
|
-
handled = true;
|
|
50
|
-
break;
|
|
51
|
-
case 'Enter':
|
|
52
|
-
case ' ':
|
|
53
|
-
if (currentIndex !== -1) {
|
|
54
|
-
this.selectTab(tabs[currentIndex]);
|
|
55
|
-
}
|
|
56
|
-
handled = true;
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
if (handled) {
|
|
60
|
-
event.preventDefault();
|
|
61
|
-
event.stopPropagation();
|
|
62
|
-
if (event.key !== 'Enter' && event.key !== ' ') {
|
|
63
|
-
this.focusTab(tabs[nextIndex]);
|
|
64
|
-
if (this.switch === 'auto')
|
|
65
|
-
this.selectTab(tabs[nextIndex]);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
this.#handleClick = (event) => {
|
|
70
|
-
const target = event.target;
|
|
71
|
-
const tab = target.closest('md-tab');
|
|
72
|
-
if (tab && this.$tabs.includes(tab)) {
|
|
73
|
-
this.focusTab(tab);
|
|
74
|
-
this.selectTab(tab);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
9
|
get $tabs() {
|
|
79
|
-
return this
|
|
10
|
+
return [...this.querySelectorAll('[seele-base=tab]')];
|
|
80
11
|
}
|
|
81
|
-
get $
|
|
82
|
-
return
|
|
83
|
-
|
|
84
|
-
|
|
12
|
+
get $panels() {
|
|
13
|
+
return [
|
|
14
|
+
...this.querySelectorAll('[seele-base=tabpanel]'),
|
|
15
|
+
];
|
|
85
16
|
}
|
|
86
17
|
render() {
|
|
87
|
-
return html `<div part="tablist" role="tablist"><slot @slotchange="${this.#handleSlotChange}"></slot></div>`;
|
|
18
|
+
return html `<div part="tablist" role="tablist"><slot @slotchange="${this.#handleSlotChange}"></slot></div><slot name="panels"></slot>`;
|
|
19
|
+
}
|
|
20
|
+
constructor() {
|
|
21
|
+
super();
|
|
22
|
+
this.switch = 'manual';
|
|
23
|
+
this.selected = '';
|
|
24
|
+
if (!isServer) {
|
|
25
|
+
this.addEventListener('keydown', this.#handleKeyDown.bind(this));
|
|
26
|
+
this.addEventListener('click', this.#handleClick.bind(this));
|
|
27
|
+
}
|
|
88
28
|
}
|
|
89
29
|
connectedCallback() {
|
|
90
30
|
super.connectedCallback();
|
|
91
|
-
|
|
92
|
-
this.addEventListener('click', this.#handleClick.bind(this));
|
|
31
|
+
queueMicrotask(this.#handleSlotChange.bind(this));
|
|
93
32
|
}
|
|
94
33
|
updated(changed) {
|
|
95
34
|
if (changed.has('selected') && this.selected) {
|
|
96
35
|
const targetTab = this.$tabs.find((t) => t.value === this.selected);
|
|
97
|
-
if (targetTab
|
|
98
|
-
this.
|
|
36
|
+
if (targetTab)
|
|
37
|
+
this._selectTab(targetTab);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
#handleSlotChange() {
|
|
41
|
+
this.$tabs.forEach((tab) => {
|
|
42
|
+
const panel = this.$panels.find((panel) => panel.value === tab.value);
|
|
43
|
+
if (!panel) {
|
|
44
|
+
console.error('[seele] Cannot find a matching panel for tab ', tab);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
tab[internals].ariaControlsElements = [panel];
|
|
48
|
+
panel[internals].ariaLabelledByElements = [tab];
|
|
99
49
|
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
#handleKeyDown(event) {
|
|
53
|
+
const tabs = this.$tabs.filter((t) => !t.disabled);
|
|
54
|
+
if (!tabs.length)
|
|
55
|
+
return;
|
|
56
|
+
const activeElement = this.getRootNode()
|
|
57
|
+
.activeElement;
|
|
58
|
+
const currentIndex = tabs.findIndex((t) => t === activeElement);
|
|
59
|
+
let nextIndex = currentIndex !== -1 ? currentIndex : 0;
|
|
60
|
+
let handled = false;
|
|
61
|
+
switch (event.key) {
|
|
62
|
+
case 'ArrowLeft':
|
|
63
|
+
nextIndex = currentIndex <= 0 ? tabs.length - 1 : currentIndex - 1;
|
|
64
|
+
handled = true;
|
|
65
|
+
break;
|
|
66
|
+
case 'ArrowRight':
|
|
67
|
+
nextIndex = currentIndex >= tabs.length - 1 ? 0 : currentIndex + 1;
|
|
68
|
+
handled = true;
|
|
69
|
+
break;
|
|
70
|
+
case 'Home':
|
|
71
|
+
nextIndex = 0;
|
|
72
|
+
handled = true;
|
|
73
|
+
break;
|
|
74
|
+
case 'End':
|
|
75
|
+
nextIndex = tabs.length - 1;
|
|
76
|
+
handled = true;
|
|
77
|
+
break;
|
|
78
|
+
case 'Enter':
|
|
79
|
+
case ' ':
|
|
80
|
+
if (currentIndex !== -1) {
|
|
81
|
+
this._selectTab(tabs[currentIndex]);
|
|
82
|
+
}
|
|
83
|
+
handled = true;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
if (handled) {
|
|
87
|
+
event.preventDefault();
|
|
88
|
+
event.stopPropagation();
|
|
89
|
+
if (event.key !== 'Enter' && event.key !== ' ') {
|
|
90
|
+
this.focusTab(tabs[nextIndex]);
|
|
91
|
+
if (this.switch === 'auto')
|
|
92
|
+
this._selectTab(tabs[nextIndex], true);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
#handleClick(event) {
|
|
97
|
+
const target = event.target;
|
|
98
|
+
const tab = target.closest('[seele-base=tab]');
|
|
99
|
+
if (tab && !tab.disabled && this.$tabs.includes(tab)) {
|
|
100
|
+
this.focusTab(tab);
|
|
101
|
+
this._selectTab(tab, true);
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
|
-
#handleSlotChange;
|
|
103
|
-
#handleKeyDown;
|
|
104
|
-
#handleClick;
|
|
105
104
|
focusTab(tab) {
|
|
106
105
|
this.$tabs.forEach((t) => {
|
|
107
106
|
t.blur();
|
|
108
107
|
t.tabIndex = -1;
|
|
109
108
|
});
|
|
110
109
|
tab.tabIndex = 0;
|
|
111
|
-
|
|
110
|
+
// TODO: prevent scrolling in other containers
|
|
111
|
+
tab.scrollIntoView({
|
|
112
|
+
block: 'nearest',
|
|
113
|
+
inline: 'nearest',
|
|
114
|
+
behavior: 'smooth',
|
|
115
|
+
});
|
|
116
|
+
tab.focus({ preventScroll: true });
|
|
112
117
|
}
|
|
113
|
-
|
|
118
|
+
_selectTab(selectedTab, dispatchEvent = false) {
|
|
114
119
|
this.selected = selectedTab.value;
|
|
115
|
-
const
|
|
116
|
-
const panels = Array.from(parent.querySelectorAll('[seele-base="tabpanel"]'));
|
|
120
|
+
const panels = this.$panels;
|
|
117
121
|
this.$tabs.forEach((tab) => {
|
|
118
122
|
tab.selected = tab === selectedTab;
|
|
119
|
-
tab.tabIndex = tab === selectedTab ? 0 : -1;
|
|
123
|
+
tab.tabIndex = tab === selectedTab && !tab.disabled ? 0 : -1;
|
|
120
124
|
});
|
|
121
125
|
panels.forEach((panel) => {
|
|
122
126
|
if (panel.value && selectedTab.value) {
|
|
123
|
-
panel.
|
|
127
|
+
panel.selected = panel.value === selectedTab.value;
|
|
124
128
|
}
|
|
125
129
|
});
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
130
|
+
if (dispatchEvent)
|
|
131
|
+
this.dispatchEvent(new CustomEvent('select', {
|
|
132
|
+
detail: { tab: selectedTab, value: this.selected },
|
|
133
|
+
bubbles: true,
|
|
134
|
+
composed: true,
|
|
135
|
+
}));
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
138
|
__decorate([
|
|
@@ -136,6 +141,3 @@ __decorate([
|
|
|
136
141
|
__decorate([
|
|
137
142
|
property({ type: String, reflect: true })
|
|
138
143
|
], Tabs.prototype, "selected", void 0);
|
|
139
|
-
__decorate([
|
|
140
|
-
queryAssignedElements({ flatten: true })
|
|
141
|
-
], Tabs.prototype, "$slotItems", void 0);
|
|
@@ -1,47 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
constructor();
|
|
8
|
-
connectedCallback(): void;
|
|
9
|
-
disconnectedCallback(): void;
|
|
10
|
-
protected updated(changed: Map<string, any>): void;
|
|
11
|
-
protected _updateInternals(): void;
|
|
12
|
-
/**
|
|
13
|
-
* --> Drag-and-drop to the other side
|
|
14
|
-
*
|
|
15
|
-
* `checked` is supposed to be changed once
|
|
16
|
-
*
|
|
17
|
-
* 1. `pointerdown`: _ignoreClick = false
|
|
18
|
-
* 2. `pointermove`: _ignoreClick = true
|
|
19
|
-
* 3. `pointerup`: `checked` changed
|
|
20
|
-
* 4. `click`: ignored, _ignoreClick = false
|
|
21
|
-
*
|
|
22
|
-
* --> Drag-and-drop to the other side, then click
|
|
23
|
-
*
|
|
24
|
-
* `checked` is supposed to be changed twice
|
|
25
|
-
*
|
|
26
|
-
* 1. `pointerdown`: _ignoreClick = false
|
|
27
|
-
* 2. `pointermove`: _ignoreClick = true
|
|
28
|
-
* 3. `pointerup`: `checked` changed(1)
|
|
29
|
-
* 4. `click`: ignored, _ignoreClick = false
|
|
30
|
-
* 5. `click`: `checked` changed(2)
|
|
31
|
-
*
|
|
32
|
-
* --> Drag-and-drop to the other side, then click the label
|
|
33
|
-
*
|
|
34
|
-
* `checked` is supposed to be changed twice
|
|
35
|
-
*
|
|
36
|
-
* 1. `pointerdown`: _ignoreClick = false
|
|
37
|
-
* 2. `pointermove`: _ignoreClick = true
|
|
38
|
-
* 3. `pointerup`: `checked` changed(1)
|
|
39
|
-
* 4. `click` on label: _ignoreClick = false
|
|
40
|
-
* 5. `click` on switch: `checked` changed(2)
|
|
41
|
-
*/
|
|
42
|
-
protected _ignoreClick: boolean;
|
|
43
|
-
protected toggleChecked(): void;
|
|
44
|
-
formResetCallback(): void;
|
|
45
|
-
formStateRestoreCallback(state: string, _reason: string): void;
|
|
1
|
+
import { Button } from './button.js';
|
|
2
|
+
declare const ToggleButton_base: Constructor<import("./mixins/button-toggle-mixin.js").ToggleableInterface> & typeof Button;
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated compose the mixins yourself instead
|
|
5
|
+
*/
|
|
6
|
+
export declare class ToggleButton extends ToggleButton_base {
|
|
46
7
|
}
|
|
47
8
|
export {};
|
|
@@ -1,136 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const PROPERTY_FROM_ARIA_PRESSED = {
|
|
8
|
-
true: 'checked',
|
|
9
|
-
false: 'unchecked',
|
|
10
|
-
};
|
|
11
|
-
const Base = FormAssociated(InternalsAttached(LitElement));
|
|
12
|
-
export class ToggleButton extends Base {
|
|
13
|
-
static { this.styles = [hiddenStyles]; }
|
|
14
|
-
constructor() {
|
|
15
|
-
super();
|
|
16
|
-
this.checked = false;
|
|
17
|
-
/**
|
|
18
|
-
* --> Drag-and-drop to the other side
|
|
19
|
-
*
|
|
20
|
-
* `checked` is supposed to be changed once
|
|
21
|
-
*
|
|
22
|
-
* 1. `pointerdown`: _ignoreClick = false
|
|
23
|
-
* 2. `pointermove`: _ignoreClick = true
|
|
24
|
-
* 3. `pointerup`: `checked` changed
|
|
25
|
-
* 4. `click`: ignored, _ignoreClick = false
|
|
26
|
-
*
|
|
27
|
-
* --> Drag-and-drop to the other side, then click
|
|
28
|
-
*
|
|
29
|
-
* `checked` is supposed to be changed twice
|
|
30
|
-
*
|
|
31
|
-
* 1. `pointerdown`: _ignoreClick = false
|
|
32
|
-
* 2. `pointermove`: _ignoreClick = true
|
|
33
|
-
* 3. `pointerup`: `checked` changed(1)
|
|
34
|
-
* 4. `click`: ignored, _ignoreClick = false
|
|
35
|
-
* 5. `click`: `checked` changed(2)
|
|
36
|
-
*
|
|
37
|
-
* --> Drag-and-drop to the other side, then click the label
|
|
38
|
-
*
|
|
39
|
-
* `checked` is supposed to be changed twice
|
|
40
|
-
*
|
|
41
|
-
* 1. `pointerdown`: _ignoreClick = false
|
|
42
|
-
* 2. `pointermove`: _ignoreClick = true
|
|
43
|
-
* 3. `pointerup`: `checked` changed(1)
|
|
44
|
-
* 4. `click` on label: _ignoreClick = false
|
|
45
|
-
* 5. `click` on switch: `checked` changed(2)
|
|
46
|
-
*/
|
|
47
|
-
this._ignoreClick = false;
|
|
48
|
-
this.#handleLabelClick = () => {
|
|
49
|
-
this._ignoreClick = false;
|
|
50
|
-
};
|
|
51
|
-
this.#handleClick = (e) => {
|
|
52
|
-
e.stopPropagation();
|
|
53
|
-
e.preventDefault();
|
|
54
|
-
if (this._ignoreClick) {
|
|
55
|
-
this._ignoreClick = false;
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
this.toggleChecked();
|
|
59
|
-
};
|
|
60
|
-
this.#handleKeyDown = (e) => {
|
|
61
|
-
if (e.key !== ' ' && e.key !== 'Enter')
|
|
62
|
-
return;
|
|
63
|
-
e.preventDefault();
|
|
64
|
-
e.stopPropagation();
|
|
65
|
-
if (e.key === 'Enter')
|
|
66
|
-
this.toggleChecked();
|
|
67
|
-
};
|
|
68
|
-
this.#handleKeyUp = (e) => {
|
|
69
|
-
if (e.key === ' ') {
|
|
70
|
-
e.preventDefault();
|
|
71
|
-
e.stopPropagation();
|
|
72
|
-
this.toggleChecked();
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
this[internals].role = 'button';
|
|
76
|
-
this.checked = this.hasAttribute('checked');
|
|
77
|
-
this._updateInternals();
|
|
78
|
-
this.setAttribute('notransition', '');
|
|
79
|
-
}
|
|
80
|
-
connectedCallback() {
|
|
81
|
-
super.connectedCallback();
|
|
82
|
-
this.addEventListener('click', this.#handleClick);
|
|
83
|
-
this.addEventListener('keydown', this.#handleKeyDown);
|
|
84
|
-
this.addEventListener('keyup', this.#handleKeyUp);
|
|
85
|
-
this.labels.forEach((label) => {
|
|
86
|
-
label.addEventListener('click', this.#handleLabelClick);
|
|
87
|
-
});
|
|
88
|
-
requestAnimationFrame(() => requestAnimationFrame(() => this.removeAttribute('notransition')));
|
|
89
|
-
}
|
|
90
|
-
disconnectedCallback() {
|
|
91
|
-
this.removeEventListener('click', this.#handleClick);
|
|
92
|
-
this.removeEventListener('keydown', this.#handleKeyDown);
|
|
93
|
-
this.removeEventListener('keyup', this.#handleKeyUp);
|
|
94
|
-
this.labels.forEach((label) => {
|
|
95
|
-
label.removeEventListener('click', this.#handleLabelClick);
|
|
96
|
-
});
|
|
97
|
-
super.disconnectedCallback();
|
|
98
|
-
}
|
|
99
|
-
updated(changed) {
|
|
100
|
-
if (changed.has('checked') || changed.has('disabled')) {
|
|
101
|
-
this._updateInternals();
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
_updateInternals() {
|
|
105
|
-
this[internals].states.delete('unchecked');
|
|
106
|
-
this[internals].states.delete('checked');
|
|
107
|
-
this[internals].ariaPressed = this.checked ? 'true' : 'false';
|
|
108
|
-
this[internals].states.add(`${PROPERTY_FROM_ARIA_PRESSED[this[internals].ariaPressed]}`);
|
|
109
|
-
this.setAttribute('tabindex', this.disabled ? '-1' : '0');
|
|
110
|
-
this[internals].ariaDisabled = this.disabled ? 'true' : 'false';
|
|
111
|
-
this[internals].setFormValue(this.checked ? 'on' : null);
|
|
112
|
-
}
|
|
113
|
-
#handleLabelClick;
|
|
114
|
-
#handleClick;
|
|
115
|
-
#handleKeyDown;
|
|
116
|
-
#handleKeyUp;
|
|
117
|
-
toggleChecked() {
|
|
118
|
-
if (this.disabled)
|
|
119
|
-
return;
|
|
120
|
-
this.checked = !this.checked;
|
|
121
|
-
this.dispatchEvent(new CustomEvent('change', {
|
|
122
|
-
bubbles: true,
|
|
123
|
-
composed: true,
|
|
124
|
-
detail: this.checked,
|
|
125
|
-
}));
|
|
126
|
-
}
|
|
127
|
-
formResetCallback() {
|
|
128
|
-
this.checked = this.hasAttribute('checked');
|
|
129
|
-
}
|
|
130
|
-
formStateRestoreCallback(state, _reason) {
|
|
131
|
-
this.checked = state === 'on';
|
|
132
|
-
}
|
|
1
|
+
import { Button } from './button.js';
|
|
2
|
+
import { ButtonToggleMixin } from './mixins/button-toggle-mixin.js';
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated compose the mixins yourself instead
|
|
5
|
+
*/
|
|
6
|
+
export class ToggleButton extends ButtonToggleMixin(Button) {
|
|
133
7
|
}
|
|
134
|
-
__decorate([
|
|
135
|
-
property({ type: Boolean })
|
|
136
|
-
], ToggleButton.prototype, "checked", void 0);
|
package/src/base/tooltip.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
|
+
import { handleControlChange } from './mixins/attachable.js';
|
|
2
3
|
declare const Base: Constructor<import("./mixins/attachable.js").AttachableInterface> & Constructor<import("./mixins/internals-attached.js").InternalsAttachedInterface> & typeof LitElement;
|
|
3
4
|
/**
|
|
4
5
|
* TODO: Check if $control controls a menu/popover and keep hidden when it is open.
|
|
@@ -31,7 +32,7 @@ export declare class Tooltip extends Base {
|
|
|
31
32
|
render(): import("lit-html").TemplateResult<1>;
|
|
32
33
|
private readonly popoverController;
|
|
33
34
|
constructor();
|
|
34
|
-
handleControlChange(prev?: HTMLElement | null, next?: HTMLElement | null): void;
|
|
35
|
+
[handleControlChange](prev?: HTMLElement | null, next?: HTMLElement | null): void;
|
|
35
36
|
set visible(value: boolean);
|
|
36
37
|
}
|
|
37
38
|
export {};
|
package/src/base/tooltip.js
CHANGED
|
@@ -2,7 +2,7 @@ import { __decorate } from "tslib";
|
|
|
2
2
|
import { LitElement, html } from 'lit';
|
|
3
3
|
import { property, query } from 'lit/decorators.js';
|
|
4
4
|
import { focusVisible } from '../core/focus-visible.js';
|
|
5
|
-
import { Attachable } from './mixins/attachable.js';
|
|
5
|
+
import { Attachable, handleControlChange } from './mixins/attachable.js';
|
|
6
6
|
import { InternalsAttached, internals } from './mixins/internals-attached.js';
|
|
7
7
|
import { PopoverController } from './controllers/popover-controller.js';
|
|
8
8
|
let lastHidingTime = 0;
|
|
@@ -83,7 +83,7 @@ export class Tooltip extends Base {
|
|
|
83
83
|
};
|
|
84
84
|
this[internals].role = 'tooltip';
|
|
85
85
|
}
|
|
86
|
-
handleControlChange(prev = null, next = null) {
|
|
86
|
+
[handleControlChange](prev = null, next = null) {
|
|
87
87
|
const eventHandlers = {
|
|
88
88
|
focusin: this.#handleFocusIn,
|
|
89
89
|
focusout: this.#handleFocusOut,
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export declare function ensureReady(element: HTMLElement): Promise<
|
|
1
|
+
export declare function ensureReady(element: HTMLElement | null, useAnimationFrame?: boolean): Promise<void>;
|
|
2
|
+
export declare function ensureSlottedReady(host: HTMLElement, getSlotted?: () => (HTMLElement | null)[], useAnimationFrame?: boolean): Promise<void>;
|
package/src/core/ensure-ready.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
export async function ensureReady(element) {
|
|
1
|
+
export async function ensureReady(element, useAnimationFrame = false) {
|
|
2
2
|
if (!element)
|
|
3
3
|
return null;
|
|
4
4
|
if (element.matches(':not(:defined)'))
|
|
5
5
|
await customElements.whenDefined(element.tagName.toLowerCase());
|
|
6
|
-
|
|
7
|
-
if ('updateComplete' in element) {
|
|
6
|
+
if ('updateComplete' in element)
|
|
8
7
|
await element.updateComplete;
|
|
9
|
-
|
|
10
|
-
else {
|
|
11
|
-
// Yield to the next frame to allow initial render to finish
|
|
8
|
+
if (useAnimationFrame)
|
|
12
9
|
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
10
|
+
}
|
|
11
|
+
export async function ensureSlottedReady(host, getSlotted, useAnimationFrame = false) {
|
|
12
|
+
await ensureReady(host);
|
|
13
|
+
if (getSlotted) {
|
|
14
|
+
const elements = getSlotted();
|
|
15
|
+
await Promise.all(elements.map((el) => ensureReady(el, false)));
|
|
13
16
|
}
|
|
14
|
-
|
|
17
|
+
// Might be useful when you need to use sth like `getBoundingClientRect()`
|
|
18
|
+
if (useAnimationFrame)
|
|
19
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
15
20
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ToggleButton } from '../../base/toggle-button.js';
|
|
2
1
|
import '../focus-ring/focus-ring.js';
|
|
3
2
|
import '../ripple/ripple.js';
|
|
3
|
+
import { M3Button } from './common-button.js';
|
|
4
|
+
declare const M3ButtonToggle_base: Constructor<import("../../base/mixins/button-toggle-mixin.js").ToggleableInterface> & typeof M3Button;
|
|
4
5
|
/**
|
|
5
6
|
* @tag md-button-toggle
|
|
6
7
|
*
|
|
@@ -12,15 +13,7 @@ import '../ripple/ripple.js';
|
|
|
12
13
|
* @slot - label
|
|
13
14
|
* @slot icon - leading icon
|
|
14
15
|
*/
|
|
15
|
-
export declare class M3ButtonToggle extends
|
|
16
|
-
size: 'xs' | 's' | 'm' | 'l' | 'xl';
|
|
17
|
-
square: boolean;
|
|
18
|
-
color: 'primary' | 'secondary' | 'tertiary';
|
|
19
|
-
variant: 'filled' | 'tonal' | 'elevated' | 'outlined' | 'text';
|
|
20
|
-
/**
|
|
21
|
-
* Whether to show the icon at the end of the button.
|
|
22
|
-
*/
|
|
23
|
-
trailingIcon: boolean;
|
|
16
|
+
export declare class M3ButtonToggle extends M3ButtonToggle_base {
|
|
24
17
|
static styles: any[];
|
|
25
18
|
render(): import("lit-html").TemplateResult<1>;
|
|
26
19
|
}
|
|
@@ -29,3 +22,4 @@ declare global {
|
|
|
29
22
|
'md-button-toggle': M3ButtonToggle;
|
|
30
23
|
}
|
|
31
24
|
}
|
|
25
|
+
export {};
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { html } from 'lit';
|
|
3
|
-
import { customElement, property } from 'lit/decorators.js';
|
|
4
|
-
import { ToggleButton } from '../../base/toggle-button.js';
|
|
5
2
|
import '../focus-ring/focus-ring.js';
|
|
6
3
|
import '../ripple/ripple.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
4
|
+
import { html } from 'lit';
|
|
5
|
+
import { customElement } from 'lit/decorators.js';
|
|
6
|
+
import { M3Button } from './common-button.js';
|
|
7
|
+
import { ButtonToggleMixin } from '../../base/mixins/button-toggle-mixin.js';
|
|
9
8
|
import { sharedButtonToggleStyles } from './shared-button-toggle-styles.css.js';
|
|
10
|
-
import { commonButtonStyles } from './common-button-styles.css.js';
|
|
11
9
|
/**
|
|
12
10
|
* @tag md-button-toggle
|
|
13
11
|
*
|
|
@@ -19,44 +17,12 @@ import { commonButtonStyles } from './common-button-styles.css.js';
|
|
|
19
17
|
* @slot - label
|
|
20
18
|
* @slot icon - leading icon
|
|
21
19
|
*/
|
|
22
|
-
let M3ButtonToggle = class M3ButtonToggle extends
|
|
23
|
-
|
|
24
|
-
super(...arguments);
|
|
25
|
-
this.size = 's';
|
|
26
|
-
this.square = false;
|
|
27
|
-
this.color = 'primary';
|
|
28
|
-
this.variant = 'filled';
|
|
29
|
-
/**
|
|
30
|
-
* Whether to show the icon at the end of the button.
|
|
31
|
-
*/
|
|
32
|
-
this.trailingIcon = false;
|
|
33
|
-
}
|
|
34
|
-
static { this.styles = [
|
|
35
|
-
...super.styles,
|
|
36
|
-
targetStyles,
|
|
37
|
-
sharedButtonStyles,
|
|
38
|
-
sharedButtonToggleStyles,
|
|
39
|
-
commonButtonStyles,
|
|
40
|
-
]; }
|
|
20
|
+
let M3ButtonToggle = class M3ButtonToggle extends ButtonToggleMixin(M3Button) {
|
|
21
|
+
static { this.styles = [...super.styles, sharedButtonToggleStyles]; }
|
|
41
22
|
render() {
|
|
42
23
|
return html `<md-focus-ring></md-focus-ring><md-ripple></md-ripple><span part="target"></span><slot part="icon unchecked" name="icon" aria-hidden="true"></slot><slot part="icon checked" name="icon-checked" aria-hidden="true"></slot><slot part="label unchecked"></slot><slot part="label checked" name="checked"></slot>`;
|
|
43
24
|
}
|
|
44
25
|
};
|
|
45
|
-
__decorate([
|
|
46
|
-
property({ reflect: true })
|
|
47
|
-
], M3ButtonToggle.prototype, "size", void 0);
|
|
48
|
-
__decorate([
|
|
49
|
-
property({ reflect: true, type: Boolean })
|
|
50
|
-
], M3ButtonToggle.prototype, "square", void 0);
|
|
51
|
-
__decorate([
|
|
52
|
-
property({ reflect: true })
|
|
53
|
-
], M3ButtonToggle.prototype, "color", void 0);
|
|
54
|
-
__decorate([
|
|
55
|
-
property({ reflect: true })
|
|
56
|
-
], M3ButtonToggle.prototype, "variant", void 0);
|
|
57
|
-
__decorate([
|
|
58
|
-
property({ type: Boolean, reflect: true, attribute: 'trailing-icon' })
|
|
59
|
-
], M3ButtonToggle.prototype, "trailingIcon", void 0);
|
|
60
26
|
M3ButtonToggle = __decorate([
|
|
61
27
|
customElement('md-button-toggle')
|
|
62
28
|
], M3ButtonToggle);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { ToggleButton } from '../../base/toggle-button.js';
|
|
2
1
|
import '../focus-ring/focus-ring.js';
|
|
3
2
|
import '../ripple/ripple.js';
|
|
3
|
+
import { M3IconButton } from './icon-button.js';
|
|
4
|
+
declare const M3IconButtonToggle_base: Constructor<import("../../base/mixins/button-toggle-mixin.js").ToggleableInterface> & typeof M3IconButton;
|
|
4
5
|
/**
|
|
5
6
|
* @tag md-icon-button-toggle
|
|
6
7
|
*
|
|
@@ -9,16 +10,13 @@ import '../ripple/ripple.js';
|
|
|
9
10
|
* @slot - icon
|
|
10
11
|
* @slot checked - icon when checked
|
|
11
12
|
*/
|
|
12
|
-
export declare class M3IconButtonToggle extends
|
|
13
|
+
export declare class M3IconButtonToggle extends M3IconButtonToggle_base {
|
|
13
14
|
static styles: any[];
|
|
14
15
|
render(): import("lit-html").TemplateResult<1>;
|
|
15
|
-
size: 'xs' | 's' | 'm' | 'l' | 'xl';
|
|
16
|
-
color: 'primary' | 'secondary' | 'tertiary';
|
|
17
|
-
variant: 'text' | 'filled' | 'tonal' | 'outlined';
|
|
18
|
-
width: 'standard' | 'narrow' | 'wide';
|
|
19
16
|
}
|
|
20
17
|
declare global {
|
|
21
18
|
interface HTMLElementTagNameMap {
|
|
22
19
|
'md-icon-button-toggle': M3IconButtonToggle;
|
|
23
20
|
}
|
|
24
21
|
}
|
|
22
|
+
export {};
|