@swiftwc/ui 0.0.0-dev.20 → 0.0.0-dev.22
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/generated/buses/alert-dialog.d.ts +2 -0
- package/generated/buses/alert-dialog.js +1 -0
- package/generated/buses/confirmation-dialog.d.ts +2 -0
- package/generated/buses/confirmation-dialog.js +1 -0
- package/generated/buses/index.d.ts +6 -0
- package/generated/buses/index.js +6 -0
- package/generated/buses/lifecycle-observer.d.ts +2 -0
- package/generated/buses/lifecycle-observer.js +1 -0
- package/generated/client/index.d.ts +17 -4
- package/generated/client/index.js +83 -32
- package/generated/components/alert-dialog.d.ts +8 -0
- package/generated/components/alert-dialog.js +94 -0
- package/generated/components/bordered-button.d.ts +6 -0
- package/generated/components/bordered-button.js +22 -1
- package/generated/components/bordered-prominent-button.d.ts +6 -0
- package/generated/components/bordered-prominent-button.js +22 -1
- package/generated/components/borderless-button.d.ts +5 -1
- package/generated/components/borderless-button.js +13 -7
- package/generated/components/confirmation-dialog.d.ts +1 -1
- package/generated/components/confirmation-dialog.js +26 -20
- package/generated/components/content-unavailable-view.js +2 -2
- package/generated/components/date-picker.js +24 -10
- package/generated/components/disclosure-group.js +4 -1
- package/generated/components/glass-button.d.ts +6 -0
- package/generated/components/glass-button.js +22 -1
- package/generated/components/glass-prominent-button.d.ts +6 -0
- package/generated/components/glass-prominent-button.js +22 -1
- package/generated/components/index.d.ts +1 -0
- package/generated/components/index.js +1 -0
- package/generated/components/label-view.js +3 -35
- package/generated/components/menu-view.js +12 -7
- package/generated/components/navigation-title.js +4 -4
- package/generated/components/picker-view.js +35 -25
- package/generated/components/scroll-view.js +27 -13
- package/generated/components/section-view.js +3 -3
- package/generated/components/sheet-view.d.ts +1 -2
- package/generated/components/sheet-view.js +38 -22
- package/generated/components/sidebar-toggle.js +6 -4
- package/generated/components/sidebar-view.js +10 -4
- package/generated/components/sticky-container.js +3 -1
- package/generated/components/tab-bar.js +10 -4
- package/generated/components/tab-item.js +3 -1
- package/generated/components/tab-view.js +11 -8
- package/generated/components/table-view.js +22 -10
- package/generated/components/text-field.js +37 -32
- package/generated/components/tool-bar-item-group.js +17 -0
- package/generated/components/tool-bar-item.js +20 -1
- package/generated/components/tool-bar.d.ts +12 -0
- package/generated/components/tool-bar.js +20 -7
- package/generated/components/v-stack.d.ts +5 -0
- package/generated/components/v-stack.js +5 -0
- package/generated/css/index.css +377 -86
- package/generated/events/alert-dialog.d.ts +8 -0
- package/generated/events/alert-dialog.js +1 -0
- package/generated/events/confirmation-dialog.d.ts +2 -2
- package/generated/events/index.d.ts +1 -0
- package/generated/events/index.js +1 -0
- package/generated/events/tab-view.d.ts +6 -2
- package/generated/i18n/locales/el.d.ts +9 -0
- package/generated/i18n/locales/el.js +9 -0
- package/generated/i18n/locales/en.d.ts +9 -0
- package/generated/i18n/locales/en.js +9 -0
- package/generated/internal/class/css-style-observer.js +1 -1
- package/generated/internal/class/form-associated-base.js +4 -1
- package/generated/internal/class/navigation-view.js +4 -4
- package/generated/internal/utils/button-role.d.ts +1 -0
- package/generated/internal/utils/button-role.js +39 -0
- package/generated/internal/utils/cash/index.d.ts +4 -3
- package/generated/internal/utils/cash/index.js +6 -4
- package/generated/internal/utils/index.d.ts +2 -0
- package/generated/internal/utils/index.js +2 -0
- package/generated/internal/utils/is-inside.d.ts +1 -0
- package/generated/internal/utils/is-inside.js +4 -0
- package/generated/internal/utils/list-active.js +15 -5
- package/generated/snapshot/index.d.ts +2 -0
- package/generated/snapshot/index.js +21 -0
- package/package.json +7 -4
- package/scss/_components.scss +2 -0
- package/scss/_functions.scss +10 -0
- package/scss/_transitions.scss +1 -0
- package/scss/_vars.scss +5 -0
- package/scss/base/_reboot.scss +10 -0
- package/scss/colors/_index.scss +39 -21
- package/scss/components/_alert-dialog.scss +106 -0
- package/scss/components/_bordered-button.scss +14 -0
- package/scss/components/_bordered-prominent-button.scss +13 -0
- package/scss/components/_borderless-button.scss +4 -0
- package/scss/components/_confirmation-dialog.scss +39 -39
- package/scss/components/_content-unavailable-view.scss +1 -1
- package/scss/components/_disclosure-group.scss +80 -33
- package/scss/components/_glass-button.scss +14 -0
- package/scss/components/_glass-prominent-button.scss +14 -0
- package/scss/components/_h-stack.scss +3 -13
- package/scss/components/_index.scss +1 -0
- package/scss/components/_label-view.scss +42 -16
- package/scss/components/_label-view.scss.txt +536 -0
- package/scss/components/_sheet-view.scss +13 -3
- package/scss/components/_tab-bar.scss +5 -0
- package/scss/components/_tool-bar-item.scss +19 -0
- package/scss/components/_tool-bar.scss +25 -0
- package/scss/components/_v-stack.scss +3 -13
- package/scss/final/_touch-glass.scss +7 -0
- package/scss/mixins/_index.scss +17 -0
- package/scss/placeholders/_buttons.scss +87 -10
- package/scss/transitions/_alert-dialog.scss +19 -0
- package/scss/transitions/_tab-bar.scss +6 -5
- package/scss/utils/_frame.scss +7 -0
- package/web-components.html-data/en.json +81 -13
- package/generated/confirmation-dialog/index.d.ts +0 -1
- package/generated/confirmation-dialog/index.js +0 -1
- package/generated/lifecycle-observer/index.d.ts +0 -1
- package/generated/lifecycle-observer/index.js +0 -1
- package/scss/components/_components.scss +0 -76
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
var _a;
|
|
2
|
+
import { lifecycleObserver } from '../buses';
|
|
2
3
|
import { CleanupRegistry } from '../internal/class/cleanup-registry';
|
|
3
4
|
import { ResizeObserverSingleton } from '../internal/class/resize-observer-singleton';
|
|
4
5
|
import { $, frame, onoff, slowHideShow } from '../internal/utils';
|
|
5
|
-
import { LifecycleObserver } from '../lifecycle-observer';
|
|
6
6
|
const observers = new ResizeObserverSingleton();
|
|
7
7
|
export class ScrollView extends HTMLElement {
|
|
8
8
|
static get observedAttributes() {
|
|
@@ -21,10 +21,11 @@ export class ScrollView extends HTMLElement {
|
|
|
21
21
|
<div part="root scroll-view-toolbar-stack">
|
|
22
22
|
<slot name="bottom-bar-principal"></slot>
|
|
23
23
|
</div>
|
|
24
|
-
</div
|
|
24
|
+
</div>`));
|
|
25
25
|
}
|
|
26
26
|
#shadowRoot;
|
|
27
|
-
#
|
|
27
|
+
#slots = new Map();
|
|
28
|
+
// #navbarPrincipalSlot?: HTMLSlotElement
|
|
28
29
|
#isMidScroll;
|
|
29
30
|
#lastScrollTop = 0;
|
|
30
31
|
// #stopRecordingScrollTop?: boolean = false
|
|
@@ -33,13 +34,17 @@ export class ScrollView extends HTMLElement {
|
|
|
33
34
|
super();
|
|
34
35
|
this.#shadowRoot = this.attachShadow({ mode: 'closed' });
|
|
35
36
|
this.#shadowRoot.appendChild(document.importNode(this.constructor.template, true));
|
|
36
|
-
|
|
37
|
+
for (const slot of this.#shadowRoot.querySelectorAll('slot'))
|
|
38
|
+
this.#slots?.set(slot.name, slot);
|
|
39
|
+
CleanupRegistry.register(this, () => {
|
|
40
|
+
this.#slots = new Map();
|
|
41
|
+
});
|
|
37
42
|
}
|
|
38
43
|
disconnectedCallback() {
|
|
39
44
|
console.debug(`${_a.name} ⚡️ disconnect`);
|
|
40
45
|
CleanupRegistry.unregister(this);
|
|
41
46
|
observers.unobserve(this);
|
|
42
|
-
frame().then(() =>
|
|
47
|
+
frame().then(() => lifecycleObserver.dispatchEvent(new CustomEvent('pagehide', { detail: { page: this }, bubbles: true, composed: true })));
|
|
43
48
|
}
|
|
44
49
|
connectedCallback() {
|
|
45
50
|
console.debug(`${_a.name} ⚡️ connect`);
|
|
@@ -51,7 +56,7 @@ export class ScrollView extends HTMLElement {
|
|
|
51
56
|
{ types: 'scroll', listener: this.#handleScroll, addOptions: { passive: true } },
|
|
52
57
|
{ types: 'scrollend', listener: this.#handleScrollend, addOptions: { passive: true } },
|
|
53
58
|
], this).on());
|
|
54
|
-
frame().then(() =>
|
|
59
|
+
frame().then(() => lifecycleObserver.dispatchEvent(new CustomEvent('pageshow', { detail: { page: this }, bubbles: true, composed: true })));
|
|
55
60
|
observers.observe(this, this.#handleMeasure.bind(this));
|
|
56
61
|
// frame(this).then((r) => {
|
|
57
62
|
// if (!r) return
|
|
@@ -84,7 +89,7 @@ export class ScrollView extends HTMLElement {
|
|
|
84
89
|
break; // iREPAINT ALERT! if (0 === this.offsetHeight + this.offsetWidth) break
|
|
85
90
|
if (!this.#isMidScroll)
|
|
86
91
|
break;
|
|
87
|
-
const title = this.#
|
|
92
|
+
const title = this.#slots?.get('top-bar-principal')?.assignedElements({ flatten: true })?.at(0);
|
|
88
93
|
slowHideShow('largeinline' === `${oldValue}${newValue}` ? 'show' : 'hide', title);
|
|
89
94
|
break;
|
|
90
95
|
}
|
|
@@ -94,7 +99,10 @@ export class ScrollView extends HTMLElement {
|
|
|
94
99
|
if (!this.#isMidScroll)
|
|
95
100
|
this.#isMidScroll = true;
|
|
96
101
|
// if (this.#stopRecordingScrollTop) return
|
|
97
|
-
|
|
102
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
103
|
+
if (!target)
|
|
104
|
+
return;
|
|
105
|
+
this.#lastScrollTop = target.scrollTop;
|
|
98
106
|
};
|
|
99
107
|
#handleScrollend = (evt) => {
|
|
100
108
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
@@ -120,7 +128,10 @@ export class ScrollView extends HTMLElement {
|
|
|
120
128
|
};
|
|
121
129
|
#handleTabReveal = (evt) => {
|
|
122
130
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
123
|
-
|
|
131
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
132
|
+
if (!target)
|
|
133
|
+
return;
|
|
134
|
+
if (!target.contains(this))
|
|
124
135
|
return;
|
|
125
136
|
if (this.closest('[hidden]'))
|
|
126
137
|
return;
|
|
@@ -149,7 +160,10 @@ export class ScrollView extends HTMLElement {
|
|
|
149
160
|
};
|
|
150
161
|
#handleTabBeforeswap = (evt) => {
|
|
151
162
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
152
|
-
|
|
163
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
164
|
+
if (!target)
|
|
165
|
+
return;
|
|
166
|
+
if (!target.contains(this))
|
|
153
167
|
return;
|
|
154
168
|
if (this.closest('[hidden]'))
|
|
155
169
|
return;
|
|
@@ -167,17 +181,17 @@ export class ScrollView extends HTMLElement {
|
|
|
167
181
|
}
|
|
168
182
|
#renderNavTitle = (title, subtitle) => {
|
|
169
183
|
const vStack = this.querySelector(':scope>[slot=top-bar-principal]') ??
|
|
170
|
-
this.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal"><label-view line-limit="1" truncation-mode="tail" font="headline"></label-view><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></v-stack
|
|
184
|
+
this.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal"><label-view line-limit="1" truncation-mode="tail" font="headline"></label-view><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></v-stack>`, '>1'));
|
|
171
185
|
let titleLabel = vStack.querySelector(':scope>label-view:nth-child(1)');
|
|
172
186
|
if (title) {
|
|
173
|
-
titleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="headline"></label-view
|
|
187
|
+
titleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="headline"></label-view>`, '>1'));
|
|
174
188
|
titleLabel.setAttribute('title', title);
|
|
175
189
|
}
|
|
176
190
|
else
|
|
177
191
|
titleLabel?.remove();
|
|
178
192
|
let subtitleLabel = vStack.querySelector(':scope>label-view:nth-child(2)');
|
|
179
193
|
if (subtitle) {
|
|
180
|
-
subtitleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="callout"></label-view
|
|
194
|
+
subtitleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="callout"></label-view>`, '>1'));
|
|
181
195
|
subtitleLabel.setAttribute('title', subtitle);
|
|
182
196
|
}
|
|
183
197
|
else
|
|
@@ -14,7 +14,7 @@ export class SectionView extends HTMLElement {
|
|
|
14
14
|
</div>
|
|
15
15
|
<div part="root section-footer-stack">
|
|
16
16
|
<slot name="footer"></slot>
|
|
17
|
-
</div
|
|
17
|
+
</div>`));
|
|
18
18
|
// <div class="sticky-sentinel" style="grid-area:sentinel;inline-size:100%;block-size:0.1px;pointer-events:none;"></div>
|
|
19
19
|
}
|
|
20
20
|
#shadowRoot;
|
|
@@ -60,7 +60,7 @@ export class SectionView extends HTMLElement {
|
|
|
60
60
|
case 'header':
|
|
61
61
|
let header = this.querySelector(':scope>[slot=header]');
|
|
62
62
|
if (newValue) {
|
|
63
|
-
header ??= this.appendChild($(`<header slot="header"><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></header
|
|
63
|
+
header ??= this.appendChild($(`<header slot="header"><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></header>`, '>1'));
|
|
64
64
|
header.querySelector('label-view')?.setAttribute('title', newValue);
|
|
65
65
|
}
|
|
66
66
|
else
|
|
@@ -69,7 +69,7 @@ export class SectionView extends HTMLElement {
|
|
|
69
69
|
case 'footer':
|
|
70
70
|
let footer = this.querySelector(':scope>[slot=footer]');
|
|
71
71
|
if (newValue) {
|
|
72
|
-
footer ??= this.appendChild($(`<footer slot="footer"><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></footer
|
|
72
|
+
footer ??= this.appendChild($(`<footer slot="footer"><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></footer>`, '>1'));
|
|
73
73
|
footer.querySelector('label-view')?.setAttribute('title', newValue);
|
|
74
74
|
}
|
|
75
75
|
else
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { DialogBase } from '../namespace-browser/base';
|
|
2
2
|
export declare class SheetView extends DialogBase {
|
|
3
3
|
#private;
|
|
4
|
-
static get observedAttributes(): string[];
|
|
5
4
|
constructor();
|
|
6
5
|
static polyfillDisconnectedCallback(el: SheetView): void;
|
|
7
6
|
static polyfillConnectedCallback(el: SheetView): void;
|
|
8
|
-
static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]: Pick<MutationRecord, 'attributeName' | 'oldValue' | 'target'>[]):
|
|
7
|
+
static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]: Pick<MutationRecord, 'attributeName' | 'oldValue' | 'target'>[]): void;
|
|
9
8
|
}
|
|
@@ -3,9 +3,9 @@ import { onoff } from '../internal/utils';
|
|
|
3
3
|
import { DialogBase } from '../namespace-browser/base';
|
|
4
4
|
import { Snapshot } from '../snapshot';
|
|
5
5
|
export class SheetView extends DialogBase {
|
|
6
|
-
static get observedAttributes() {
|
|
7
|
-
|
|
8
|
-
}
|
|
6
|
+
// static get observedAttributes() {
|
|
7
|
+
// return ['fine-presentation-large-adaptation']
|
|
8
|
+
// }
|
|
9
9
|
constructor() {
|
|
10
10
|
super();
|
|
11
11
|
}
|
|
@@ -20,24 +20,38 @@ export class SheetView extends DialogBase {
|
|
|
20
20
|
{ types: 'keydown', listener: SheetView.#handleKeydown },
|
|
21
21
|
], el).on());
|
|
22
22
|
el.autofocus = true;
|
|
23
|
+
if (!self.matchMedia('(pointer: fine)').matches)
|
|
24
|
+
return;
|
|
25
|
+
const handler1 = this.#handleMediaChange.bind(null, el);
|
|
26
|
+
CleanupRegistry.register(el, onoff('fine_dialog_sheet:change', handler1, Snapshot.on).on());
|
|
27
|
+
Snapshot.waitReady.then(() => {
|
|
28
|
+
this.#handleMediaChange(el, new MediaQueryListEvent(`media-change`, {
|
|
29
|
+
matches: Snapshot.breakpoints?.get('fine_dialog_sheet'),
|
|
30
|
+
})); // Initial check
|
|
31
|
+
});
|
|
23
32
|
}
|
|
24
|
-
static
|
|
33
|
+
static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]) {
|
|
25
34
|
console.debug(`${SheetView.name} ⚡️ attr-change [${attributeName}] ("${oldValue}" → "${target.getAttribute(attributeName ?? '')}")`);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
// // NOTE: wait for config
|
|
36
|
+
// Snapshot.waitReady.then(() => {
|
|
37
|
+
// switch (attributeName) {
|
|
38
|
+
// case 'fine-presentation-large-adaptation':
|
|
39
|
+
// const node = target instanceof HTMLDialogElement && target
|
|
40
|
+
// if (!node) break
|
|
41
|
+
// CleanupRegistry.unregister(node, 'mediaquery')
|
|
42
|
+
// if ('bottom-bar' !== target.getAttribute(attributeName ?? '')) break
|
|
43
|
+
// const mediaQueryList = self.matchMedia(`(pointer: fine) and (min-width: ${Snapshot.config!['ipad-sheet-view-inline-size']}) and (min-height: ${Snapshot.config!['ipad-sheet-view-height']})`)
|
|
44
|
+
// SheetView.#handleMediaChange(
|
|
45
|
+
// node,
|
|
46
|
+
// new MediaQueryListEvent(`media-change`, {
|
|
47
|
+
// matches: mediaQueryList.matches,
|
|
48
|
+
// })
|
|
49
|
+
// ) // Initial check
|
|
50
|
+
// const handler1 = SheetView.#handleMediaChange.bind(null, node)
|
|
51
|
+
// CleanupRegistry.register(node, onoff('change', handler1 as unknown as EventListener, mediaQueryList).on(), 'mediaquery')
|
|
52
|
+
// break
|
|
53
|
+
// }
|
|
54
|
+
// })
|
|
41
55
|
}
|
|
42
56
|
static #handleKeydown = (evt) => {
|
|
43
57
|
console.debug(`${SheetView.name} ⚡️ ${evt?.type} (${evt.key})`);
|
|
@@ -56,9 +70,11 @@ export class SheetView extends DialogBase {
|
|
|
56
70
|
static #handleMediaChange = (el, evt) => {
|
|
57
71
|
console.debug(`${SheetView.name} ⚡️ ${evt?.type}`);
|
|
58
72
|
if (evt.matches)
|
|
59
|
-
for (const item of el.querySelectorAll(':scope>tool-bar>[slot^="top-bar-"]')) {
|
|
60
|
-
|
|
61
|
-
item.slot
|
|
73
|
+
for (const item of el.querySelectorAll(':scope>tool-bar>[slot^="top-bar-"],:scope>tool-bar>[slot="cancellation-action"],:scope>tool-bar>[slot="primary-action"],:scope>tool-bar>[slot="confirmation-action"],:scope>tool-bar>[slot="destructive-action"]')) {
|
|
74
|
+
const newSlot = item.slot.endsWith('leading') ? 'bottom-bar-leading' : 'bottom-bar-trailing';
|
|
75
|
+
if (item.slot !== newSlot)
|
|
76
|
+
item.dataset.previousSlot = item.slot;
|
|
77
|
+
item.slot = newSlot;
|
|
62
78
|
}
|
|
63
79
|
else
|
|
64
80
|
for (const item of el.querySelectorAll(':scope>tool-bar>[data-previous-slot]')) {
|
|
@@ -23,14 +23,14 @@ export class SidebarToggle extends HTMLElement {
|
|
|
23
23
|
CleanupRegistry.unregister(this);
|
|
24
24
|
}
|
|
25
25
|
static query(target) {
|
|
26
|
-
const container = target?.closest('navigation-split-view,tab-view'), sideBar = container?.querySelector(':scope
|
|
26
|
+
const container = target?.closest('navigation-split-view,tab-view'), sideBar = container?.querySelector(':scope>[is=sidebar-view]');
|
|
27
27
|
return { container, sideBar };
|
|
28
28
|
}
|
|
29
29
|
// This triggers on show/hide of any of sidebar-toggle elements
|
|
30
30
|
static #handleMeasure(entry) {
|
|
31
31
|
console.debug(`${_a.name} ⚡️ measure`);
|
|
32
|
-
const
|
|
33
|
-
if (!
|
|
32
|
+
const target = entry?.target instanceof HTMLElement && entry.target;
|
|
33
|
+
if (!target)
|
|
34
34
|
return;
|
|
35
35
|
// set/remove css var/prop to parent based on shown/hidden
|
|
36
36
|
const tv = target.parentElement;
|
|
@@ -67,7 +67,9 @@ export class SidebarToggle extends HTMLElement {
|
|
|
67
67
|
}
|
|
68
68
|
#handleClick(evt) {
|
|
69
69
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
70
|
-
const
|
|
70
|
+
const target = evt?.target instanceof HTMLElement && evt.target;
|
|
71
|
+
if (!target)
|
|
72
|
+
return;
|
|
71
73
|
if (!target?.closest('button'))
|
|
72
74
|
return;
|
|
73
75
|
const { sideBar } = _a.query(target);
|
|
@@ -12,9 +12,12 @@ export class SidebarView extends DialogBase {
|
|
|
12
12
|
static polyfillConnectedCallback(el) {
|
|
13
13
|
CleanupRegistry.register(el, onoff('click', SidebarView.#handleClick, el).on());
|
|
14
14
|
CleanupRegistry.register(el, onoff(touchGlass(el, (t) => t, (evt) => {
|
|
15
|
-
|
|
15
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
16
|
+
if (!target)
|
|
17
|
+
return true;
|
|
18
|
+
if (target.matches('[is=sidebar-view]'))
|
|
16
19
|
return false;
|
|
17
|
-
if (
|
|
20
|
+
if (target.closest('tool-bar-item'))
|
|
18
21
|
return false;
|
|
19
22
|
return true;
|
|
20
23
|
}), el).on());
|
|
@@ -23,7 +26,10 @@ export class SidebarView extends DialogBase {
|
|
|
23
26
|
/** Autoclose on click outside. */
|
|
24
27
|
static #handleClick = async (evt) => {
|
|
25
28
|
console.debug(`${SidebarView.name} ⚡️ ${evt?.type}`);
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
30
|
+
if (!target)
|
|
31
|
+
return;
|
|
32
|
+
if (target instanceof HTMLDialogElement && 'sidebar-view' === target.getAttribute('is'))
|
|
33
|
+
target.close?.();
|
|
28
34
|
};
|
|
29
35
|
}
|
|
@@ -14,7 +14,9 @@ export class StickyContainer extends HTMLElement {
|
|
|
14
14
|
CleanupRegistry.unregister(this);
|
|
15
15
|
}
|
|
16
16
|
#handleTransitionrun = ({ target, propertyName, pseudoElement }) => {
|
|
17
|
-
if (
|
|
17
|
+
if (!(target instanceof HTMLElement && target))
|
|
18
|
+
return;
|
|
19
|
+
if ('--stuck' !== propertyName || '::before' !== pseudoElement || !target.matches('sticky-container'))
|
|
18
20
|
return;
|
|
19
21
|
const stuck = self.getComputedStyle(this, 'before').getPropertyValue('--stuck');
|
|
20
22
|
this.toggleAttribute('stuck', '1' === stuck);
|
|
@@ -20,9 +20,12 @@ export class TabBar extends DialogBase {
|
|
|
20
20
|
// if (!r) return
|
|
21
21
|
CleanupRegistry.register(el, onoff('click', TabBar.#handleClick, el).on());
|
|
22
22
|
CleanupRegistry.register(el, onoff(touchGlass(el, (t) => t, (evt) => {
|
|
23
|
-
|
|
23
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
24
|
+
if (!target)
|
|
25
|
+
return true;
|
|
26
|
+
if (target.matches('[is=tab-bar]'))
|
|
24
27
|
return false;
|
|
25
|
-
if (
|
|
28
|
+
if (target.closest('tool-bar-item'))
|
|
26
29
|
return false;
|
|
27
30
|
return true;
|
|
28
31
|
}), el).on());
|
|
@@ -30,7 +33,10 @@ export class TabBar extends DialogBase {
|
|
|
30
33
|
}
|
|
31
34
|
static #handleClick = async (evt) => {
|
|
32
35
|
console.debug(`${TabBar.name} ⚡️ ${evt?.type}`);
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
37
|
+
if (!target)
|
|
38
|
+
return;
|
|
39
|
+
if (target instanceof HTMLDialogElement && 'tab-bar' === target.getAttribute('is'))
|
|
40
|
+
target.close?.();
|
|
35
41
|
};
|
|
36
42
|
}
|
|
@@ -63,7 +63,9 @@ export class TabItem extends ButtonBase {
|
|
|
63
63
|
};
|
|
64
64
|
static #handleClick = async (evt) => {
|
|
65
65
|
console.debug(`${TabItem.name} ⚡️ ${evt?.type}`);
|
|
66
|
-
const btn = evt.currentTarget;
|
|
66
|
+
const btn = evt.currentTarget instanceof HTMLElement && evt.currentTarget;
|
|
67
|
+
if (!btn)
|
|
68
|
+
return;
|
|
67
69
|
// const tag = btn.getAttribute('value')
|
|
68
70
|
// if (!tag) return // sidebartoggle > tab-item //throw new DOMException(`Attribute "tag" is set but invalid`, 'InvalidStateError')
|
|
69
71
|
const tv = btn.closest('tab-view');
|
|
@@ -73,7 +73,10 @@ export class TabView extends HTMLElement {
|
|
|
73
73
|
// })
|
|
74
74
|
}
|
|
75
75
|
#handleSummaryClick = (evt) => {
|
|
76
|
-
const
|
|
76
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
77
|
+
if (!target)
|
|
78
|
+
return;
|
|
79
|
+
const summary = target.closest('summary');
|
|
77
80
|
if (!summary)
|
|
78
81
|
return;
|
|
79
82
|
if (0 === $.siblings('[aria-selected=true]', summary).length)
|
|
@@ -86,7 +89,7 @@ export class TabView extends HTMLElement {
|
|
|
86
89
|
const style = self.getComputedStyle(form);
|
|
87
90
|
if ('sidebar' !== style.getPropertyValue('--list-style'))
|
|
88
91
|
return;
|
|
89
|
-
this.#addAnimations();
|
|
92
|
+
this.#addAnimations(new CustomEvent('beforetabreveal', { detail: { tag: '', ms: cssTime(`${this.computedStyleMap().get(`--tabbar-after-tabreveal-duration`)}`) }, bubbles: true, composed: true }));
|
|
90
93
|
};
|
|
91
94
|
#handleTabViewPagereveal = (evt) => {
|
|
92
95
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
@@ -199,28 +202,28 @@ export class TabView extends HTMLElement {
|
|
|
199
202
|
throw new Error('selectedTab[] must be in order of parent>child. You provided an element that contains the previous sibling.');
|
|
200
203
|
//
|
|
201
204
|
const selectors = [':not(:is(:scope>{{tag}}))', ':is(:scope>{{tag}})']; // first nested ones, then root ones
|
|
205
|
+
const ms = cssTime(`${this.computedStyleMap().get(`--tabbar-after-tabreveal-duration`)}`);
|
|
202
206
|
for (const selector of selectors)
|
|
203
207
|
for (const ns of this.querySelectorAll(`navigation-stack:not([hidden])${selector.replace('{{tag}}', 'navigation-stack')},navigation-split-view:not([hidden])${selector.replace('{{tag}}', 'navigation-split-view')}`)) {
|
|
204
208
|
if (!tabs.some((tab) => !ns.contains(tab)))
|
|
205
209
|
continue; // shouldRun
|
|
206
|
-
ns.dispatchEvent(new CustomEvent('beforetabswap', { detail: { tag: ns.id }, bubbles: true, composed: true }));
|
|
210
|
+
ns.dispatchEvent(new CustomEvent('beforetabswap', { detail: { tag: ns.id, ms }, bubbles: true, composed: true }));
|
|
207
211
|
ns.hidden = true; // triggers
|
|
208
212
|
}
|
|
209
213
|
for (const selector of selectors.reverse())
|
|
210
214
|
for (const ns of this.querySelectorAll(`navigation-stack[hidden]${selector.replace('{{tag}}', 'navigation-stack')},navigation-split-view[hidden]${selector.replace('{{tag}}', 'navigation-split-view')}`)) {
|
|
211
215
|
if (!tabs.some((tab) => ns.contains(tab)))
|
|
212
216
|
continue; // shouldRun
|
|
213
|
-
ns.dispatchEvent(new CustomEvent('beforetabreveal', { detail: { tag: ns.id }, bubbles: true, composed: true }));
|
|
217
|
+
ns.dispatchEvent(new CustomEvent('beforetabreveal', { detail: { tag: ns.id, ms }, bubbles: true, composed: true }));
|
|
214
218
|
ns.hidden = false; // triggers
|
|
215
219
|
}
|
|
216
220
|
}
|
|
217
|
-
#addAnimations = () => {
|
|
221
|
+
#addAnimations = (evt) => {
|
|
218
222
|
this.setAttribute('js-aftertabreveal', '');
|
|
223
|
+
// const ms = cssTime(`${this.computedStyleMap().get(`--tabbar-after-tabreveal-duration`)}`)
|
|
219
224
|
this.#afterTabRevealDelay.next(() => {
|
|
220
225
|
this.removeAttribute('js-aftertabreveal');
|
|
221
|
-
},
|
|
222
|
-
// this.removeAttribute('js-aftertabreveal')
|
|
223
|
-
// this.#afterTabRevealDelay = undefined
|
|
226
|
+
}, evt.detail.ms);
|
|
224
227
|
};
|
|
225
228
|
#handleSelectionChange = (evt) => {
|
|
226
229
|
this.#triggerToggleEvent(evt);
|
|
@@ -39,18 +39,24 @@ export class TableView extends HTMLElement {
|
|
|
39
39
|
<slot name="footer-trailing"></slot>
|
|
40
40
|
</div>
|
|
41
41
|
</div>
|
|
42
|
-
</div
|
|
42
|
+
</div>`));
|
|
43
43
|
}
|
|
44
44
|
#shadowRoot;
|
|
45
|
-
#
|
|
45
|
+
#slots = new Map();
|
|
46
|
+
// #colSlot?: HTMLSlotElement
|
|
46
47
|
// #slot?: HTMLSlotElement
|
|
47
48
|
constructor() {
|
|
48
49
|
super();
|
|
49
50
|
this.#shadowRoot = this.attachShadow({ mode: 'closed' });
|
|
50
51
|
this.#shadowRoot.appendChild(document.importNode(this.constructor.template, true));
|
|
51
|
-
|
|
52
|
+
for (const slot of this.#shadowRoot.querySelectorAll('slot'))
|
|
53
|
+
this.#slots?.set(slot.name, slot);
|
|
54
|
+
CleanupRegistry.register(this, () => {
|
|
55
|
+
this.#slots = new Map();
|
|
56
|
+
});
|
|
57
|
+
// this.#colSlot = this.#shadowRoot.querySelector<HTMLSlotElement>('slot[name=column]') ?? undefined
|
|
52
58
|
// this.#slot = this.#shadowRoot.querySelector<HTMLSlotElement>('slot:not([name])') ?? undefined
|
|
53
|
-
this.#
|
|
59
|
+
this.#slots?.get('column')?.addEventListener('slotchange', this.#handleSlotchange);
|
|
54
60
|
// this.append(
|
|
55
61
|
// document.createRange().createContextualFragment(`<menu-view slot="header-trailing">
|
|
56
62
|
// <label-view slot="label" title="Delete"></label-view>
|
|
@@ -103,25 +109,28 @@ export class TableView extends HTMLElement {
|
|
|
103
109
|
}
|
|
104
110
|
#handleSlotchange = (evt) => {
|
|
105
111
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
106
|
-
const slot = evt.target
|
|
112
|
+
const slot = evt.target instanceof HTMLSlotElement && evt.target;
|
|
113
|
+
if (!slot)
|
|
114
|
+
return;
|
|
115
|
+
const assigned = slot.assignedElements({ flatten: true });
|
|
107
116
|
observers.syncObservations(this.#trackedElements, assigned, this.#handleTagMutation);
|
|
108
117
|
if (0 < assigned.length)
|
|
109
118
|
this.#handleTagMutation();
|
|
110
119
|
};
|
|
111
120
|
#handleTagMutation = (entry) => {
|
|
112
121
|
console.debug(`${_a.name} ⚡️ mutation`);
|
|
113
|
-
// const sourceSlot = 0 < (this.#
|
|
122
|
+
// const sourceSlot = 0 < (this.#slots?.get('column')?.assignedElements({ flatten: true }) ?? []).length ? this.#slots?.get('column') : this.#slots?.get('column')
|
|
114
123
|
// const menu = this.querySelector(':scope>menu-view:not([slot])') ?? this.appendChild($(`<menu-view></menu-view>`))
|
|
115
124
|
// menu.innerHTML = `<label-view slot="label" system-image="dots-three" title="rtyty"></label-view>`
|
|
116
125
|
// for (const el of sourceSlot?.assignedElements({ flatten: true }) ?? []) menu.insertAdjacentElement('beforeend', TableView.wrapTag(el, sourceSlot?.name))
|
|
117
126
|
//
|
|
118
127
|
if (!this.#compactToolbarItem) {
|
|
119
|
-
this.#compactToolbarItem = $(`<menu-view tabindex="0" slot="header-trailing"></menu-view
|
|
128
|
+
this.#compactToolbarItem = $(`<menu-view tabindex="0" slot="header-trailing"></menu-view>`, '>1');
|
|
120
129
|
CleanupRegistry.unregister(this, 'compact_toolbar');
|
|
121
130
|
CleanupRegistry.register(this, onoff('click', this.#handleMenuClick, this.#compactToolbarItem).on(), 'compact_toolbar');
|
|
122
131
|
}
|
|
123
132
|
this.#compactToolbarItem.innerHTML = `<label-view slot="label" system-image="dots-three"></label-view>`;
|
|
124
|
-
for (const node of this.#
|
|
133
|
+
for (const node of this.#slots?.get('column')?.assignedElements({ flatten: true }) ?? []) {
|
|
125
134
|
if (!node.matches('[is=table-column]'))
|
|
126
135
|
continue;
|
|
127
136
|
const btn = $(`<button type="button" tabindex="0">
|
|
@@ -129,7 +138,7 @@ export class TableView extends HTMLElement {
|
|
|
129
138
|
<label-view></label-view>
|
|
130
139
|
<label-view font="callout" foreground="secondary"></label-view>
|
|
131
140
|
</v-stack>
|
|
132
|
-
</button
|
|
141
|
+
</button>`, '>1'), title = btn.querySelector('label-view:first-child'), subTitle = btn.querySelector('label-view:last-child');
|
|
133
142
|
title?.setAttribute('title', node.textContent.trim());
|
|
134
143
|
subTitle?.setAttribute('title', node.ariaSort ?? '');
|
|
135
144
|
this.#compactToolbarItem.appendChild(btn);
|
|
@@ -164,7 +173,10 @@ export class TableView extends HTMLElement {
|
|
|
164
173
|
}
|
|
165
174
|
};
|
|
166
175
|
#handleMenuClick = (evt) => {
|
|
167
|
-
const
|
|
176
|
+
const target = evt.target instanceof HTMLElement && evt.target;
|
|
177
|
+
if (!target)
|
|
178
|
+
return;
|
|
179
|
+
const btn = target.closest('button');
|
|
168
180
|
if (!btn)
|
|
169
181
|
return;
|
|
170
182
|
const siblings = [...(btn.parentNode?.querySelectorAll(':scope>button') ?? [])];
|
|
@@ -23,12 +23,13 @@ export class TextField extends FormAssociatedBase {
|
|
|
23
23
|
<input type="text" part="root input text-field-form-input">
|
|
24
24
|
</div>
|
|
25
25
|
<slot name="validity-options" hidden></slot>
|
|
26
|
-
</label
|
|
26
|
+
</label>`));
|
|
27
27
|
}
|
|
28
28
|
#shadowRoot;
|
|
29
29
|
// #internals: ElementInternals
|
|
30
30
|
#customValidity = '';
|
|
31
|
-
#validitiesSlot
|
|
31
|
+
// #validitiesSlot?: HTMLSlotElement
|
|
32
|
+
#slots = new Map();
|
|
32
33
|
#input;
|
|
33
34
|
get #internals() {
|
|
34
35
|
return getInternals(this);
|
|
@@ -37,9 +38,13 @@ export class TextField extends FormAssociatedBase {
|
|
|
37
38
|
super();
|
|
38
39
|
this.#shadowRoot = this.attachShadow({ mode: 'closed' });
|
|
39
40
|
this.#shadowRoot.appendChild(document.importNode(this.constructor.template, true));
|
|
40
|
-
|
|
41
|
+
for (const slot of this.#shadowRoot.querySelectorAll('slot'))
|
|
42
|
+
this.#slots?.set(slot.name, slot);
|
|
43
|
+
CleanupRegistry.register(this, () => {
|
|
44
|
+
this.#slots = new Map();
|
|
45
|
+
});
|
|
41
46
|
CleanupRegistry.unregister(this, 'validities');
|
|
42
|
-
CleanupRegistry.register(this, onoff(makeSlotchangeHandler(this), this.#
|
|
47
|
+
CleanupRegistry.register(this, onoff(makeSlotchangeHandler(this), this.#slots?.get('validity-options')).on(), 'validities');
|
|
43
48
|
this.#input = this.#shadowRoot.querySelector('input') ?? undefined;
|
|
44
49
|
CleanupRegistry.register(this, onoff([{ types: 'focusin', listener: this.#handleFocusin }], this).on());
|
|
45
50
|
CleanupRegistry.register(this, onoff([
|
|
@@ -137,7 +142,7 @@ export class TextField extends FormAssociatedBase {
|
|
|
137
142
|
case 'label':
|
|
138
143
|
let label = this.querySelector(':scope>[slot=label]');
|
|
139
144
|
if (newValue) {
|
|
140
|
-
label ??= this.appendChild($(`<span slot="label" foreground="secondary"></span
|
|
145
|
+
label ??= this.appendChild($(`<span slot="label" foreground="secondary"></span>`, '>1'));
|
|
141
146
|
label.textContent = newValue;
|
|
142
147
|
}
|
|
143
148
|
else
|
|
@@ -217,7 +222,7 @@ export class TextField extends FormAssociatedBase {
|
|
|
217
222
|
};
|
|
218
223
|
#handleInputPaste = (evt) => {
|
|
219
224
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
220
|
-
const input = evt.target;
|
|
225
|
+
const input = evt.target instanceof HTMLInputElement && evt.target;
|
|
221
226
|
if (!input)
|
|
222
227
|
return;
|
|
223
228
|
evt.preventDefault();
|
|
@@ -287,40 +292,40 @@ export class TextField extends FormAssociatedBase {
|
|
|
287
292
|
const allowedSignsRegex2 = /^[+-]?$|^[+-]?(\d+([.,]\d*)?|[.,]\d*)$/, // allow single '+' or '-', then allow only one ',' or '.' and finally only digits
|
|
288
293
|
digitsDecimalsOnlyRegex = /^(\d+([.,]\d*)?|[.,]\d*)?$/; // allow only one ',' or '.' and finally only digits
|
|
289
294
|
return (this.negativeNumbersAllowed ? allowedSignsRegex2 : digitsDecimalsOnlyRegex).test(str);
|
|
290
|
-
// //
|
|
291
|
-
// //
|
|
292
|
-
// //
|
|
293
|
-
// //
|
|
294
|
-
// //
|
|
295
|
-
// //
|
|
296
|
-
// //
|
|
297
|
-
// //
|
|
298
|
-
// //
|
|
299
|
-
// //
|
|
300
|
-
// //
|
|
301
|
-
// //
|
|
302
|
-
// //
|
|
303
|
-
// //
|
|
295
|
+
// // isValidDecimal(""); // true
|
|
296
|
+
// // isValidDecimal("+"); // true
|
|
297
|
+
// // isValidDecimal("-"); // true
|
|
298
|
+
// // isValidDecimal("123"); // true
|
|
299
|
+
// // isValidDecimal("+123"); // true
|
|
300
|
+
// // isValidDecimal("-456"); // true
|
|
301
|
+
// // isValidDecimal("12.34"); // true
|
|
302
|
+
// // isValidDecimal("-0,56"); // true
|
|
303
|
+
// // isValidDecimal(".78"); // true
|
|
304
|
+
// // isValidDecimal(",9"); // true
|
|
305
|
+
// // isValidDecimal("12.3.4"); // false
|
|
306
|
+
// // isValidDecimal("12,3,4"); // false
|
|
307
|
+
// // isValidDecimal("12-3"); // false
|
|
308
|
+
// // isValidDecimal("12a"); // false
|
|
304
309
|
case 'number-pad':
|
|
305
310
|
const allowedSignsRegex = /^([+-]|\d+|[+-]\d+)?$/, // allow single '+' or '-', then allow only digits
|
|
306
311
|
digitsOnlyRegex = /^(\d+)?$/; // allow only digits
|
|
307
312
|
return (this.negativeNumbersAllowed ? allowedSignsRegex : digitsOnlyRegex).test(str);
|
|
308
|
-
// //
|
|
309
|
-
// //
|
|
310
|
-
// //
|
|
311
|
-
// //
|
|
312
|
-
// //
|
|
313
|
-
// //
|
|
314
|
-
// //
|
|
315
|
-
// //
|
|
316
|
-
// //
|
|
313
|
+
// // isValidInteger(""); // true
|
|
314
|
+
// // isValidInteger("+"); // true
|
|
315
|
+
// // isValidInteger("-"); // true
|
|
316
|
+
// // isValidInteger("123"); // true
|
|
317
|
+
// // isValidInteger("+123"); // true
|
|
318
|
+
// // isValidInteger("-456"); // true
|
|
319
|
+
// // isValidInteger("12-3"); // false
|
|
320
|
+
// // isValidInteger("++123"); // false
|
|
321
|
+
// // isValidInteger("123a"); // false
|
|
317
322
|
default:
|
|
318
323
|
return true;
|
|
319
324
|
}
|
|
320
325
|
};
|
|
321
326
|
#handleInputBeforeinput = (evt) => {
|
|
322
327
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
323
|
-
const input = evt.target;
|
|
328
|
+
const input = evt.target instanceof HTMLInputElement && evt.target;
|
|
324
329
|
if (!input)
|
|
325
330
|
return;
|
|
326
331
|
if ('insertText' !== evt.inputType)
|
|
@@ -355,7 +360,7 @@ export class TextField extends FormAssociatedBase {
|
|
|
355
360
|
};
|
|
356
361
|
#handleInputBlur = (evt) => {
|
|
357
362
|
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
358
|
-
const input = evt.target;
|
|
363
|
+
const input = evt.target instanceof HTMLInputElement && evt.target;
|
|
359
364
|
if (!input)
|
|
360
365
|
return;
|
|
361
366
|
if (0 === input.value.length)
|
|
@@ -426,7 +431,7 @@ export class TextField extends FormAssociatedBase {
|
|
|
426
431
|
const key = k; // ✅ type-safe cast
|
|
427
432
|
if (true !== flags[key])
|
|
428
433
|
continue;
|
|
429
|
-
for (const el of this.#
|
|
434
|
+
for (const el of this.#slots?.get('validity-options')?.assignedElements({ flatten: true }) ?? []) {
|
|
430
435
|
if (!el.matches('option'))
|
|
431
436
|
continue;
|
|
432
437
|
const option = el;
|