@swiftwc/ui 0.0.0-dev.99 → 1.0.0-canary.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/generated/client/index.js +8 -9
- package/generated/components/alert-dialog.js +9 -17
- package/generated/components/bordered-button.js +4 -7
- package/generated/components/bordered-prominent-button.js +4 -7
- package/generated/components/borderless-button.js +4 -7
- package/generated/components/color-scheme.js +4 -7
- package/generated/components/confirmation-dialog.js +9 -17
- package/generated/components/content-unavailable.d.ts +1 -1
- package/generated/components/content-unavailable.js +5 -8
- package/generated/components/{body-view.d.ts → content-view.d.ts} +2 -2
- package/generated/components/content-view.js +15 -0
- package/generated/components/date-picker.js +13 -25
- package/generated/components/detail-placeholder.d.ts +11 -0
- package/generated/components/detail-placeholder.js +15 -0
- package/generated/components/disclosure-group.js +5 -9
- package/generated/components/fine-tooltip.js +4 -7
- package/generated/components/form-view.js +3 -5
- package/generated/components/glass-button.js +4 -7
- package/generated/components/glass-prominent-button.js +4 -7
- package/generated/components/h-divider.d.ts +11 -0
- package/generated/components/h-divider.js +15 -0
- package/generated/components/h-flex-stack.d.ts +16 -0
- package/generated/components/h-flex-stack.js +18 -0
- package/generated/components/h-stack.js +3 -5
- package/generated/components/image-view.js +4 -7
- package/generated/components/index.d.ts +7 -1
- package/generated/components/index.js +7 -1
- package/generated/components/label-view.d.ts +2 -2
- package/generated/components/label-view.js +6 -9
- package/generated/components/labeled-content.d.ts +7 -1
- package/generated/components/labeled-content.js +32 -32
- package/generated/components/list-view.d.ts +5 -1
- package/generated/components/list-view.js +8 -6
- package/generated/components/menu-view.d.ts +1 -1
- package/generated/components/menu-view.js +11 -20
- package/generated/components/navigation-large-title.d.ts +0 -1
- package/generated/components/navigation-large-title.js +5 -10
- package/generated/components/navigation-split-view.js +4 -7
- package/generated/components/navigation-stack.js +4 -7
- package/generated/components/navigation-title.js +4 -7
- package/generated/components/picker-view.d.ts +4 -21
- package/generated/components/picker-view.js +374 -326
- package/generated/components/plain-button.js +3 -5
- package/generated/components/progress-view.d.ts +1 -1
- package/generated/components/progress-view.js +7 -12
- package/generated/components/screen-view.js +2 -3
- package/generated/components/scroll-view-proxy.js +3 -5
- package/generated/components/scroll-view.d.ts +1 -1
- package/generated/components/scroll-view.js +10 -17
- package/generated/components/search-view.js +4 -7
- package/generated/components/section-view.d.ts +1 -1
- package/generated/components/section-view.js +5 -8
- package/generated/components/sheet-view.js +6 -11
- package/generated/components/sidebar-toggle.js +5 -9
- package/generated/components/sidebar-view.js +2 -3
- package/generated/components/sticky-container.js +3 -5
- package/generated/components/tab-bar.js +4 -7
- package/generated/components/tab-item.js +8 -15
- package/generated/components/tab-view.js +19 -23
- package/generated/components/table-view.d.ts +1 -1
- package/generated/components/table-view.js +7 -12
- package/generated/components/text-field.js +10 -19
- package/generated/components/text-view.d.ts +11 -0
- package/generated/components/text-view.js +16 -0
- package/generated/components/toggle-view.d.ts +2 -0
- package/generated/components/toggle-view.js +33 -37
- package/generated/components/tool-bar-item-group.js +3 -5
- package/generated/components/tool-bar-item.js +4 -7
- package/generated/components/tool-bar.js +4 -7
- package/generated/components/v-divider.d.ts +11 -0
- package/generated/components/v-divider.js +15 -0
- package/generated/components/v-flex-stack.d.ts +16 -0
- package/generated/components/v-flex-stack.js +18 -0
- package/generated/components/v-keyboard.js +8 -12
- package/generated/components/v-stack.js +3 -5
- package/generated/css/index.css +762 -418
- package/generated/internal/class/css-style-observer.js +2 -3
- package/generated/internal/class/form-associated-base.js +6 -8
- package/generated/internal/class/navigation-path.js +2 -2
- package/generated/internal/class/navigation-view.js +3 -5
- package/generated/internal/decorators/adaptive-slot.js +4 -7
- package/generated/internal/decorators/microtask-on-connected.d.ts +2 -2
- package/generated/internal/decorators/microtask-on-connected.js +2 -2
- package/generated/internal/dev-flags.d.ts +4 -0
- package/generated/internal/dev-flags.js +1 -0
- package/generated/internal/privateNamespace.d.ts +2 -2
- package/generated/internal/privateNamespace.js +15 -24
- package/generated/internal/utils/$.d.ts +9 -0
- package/generated/internal/utils/$.js +11 -0
- package/generated/internal/utils/debug.d.ts +1 -0
- package/generated/internal/utils/debug.js +4 -0
- package/generated/internal/utils/index.d.ts +36 -2
- package/generated/internal/utils/index.js +36 -5
- package/generated/internal/utils/is-inside.js +1 -1
- package/generated/snapshot/index.js +3 -5
- package/{web-components.html-data → html-data}/en.json +155 -54
- package/package.json +24 -20
- package/scss/_components.scss +1 -1
- package/scss/_maps.scss +3 -1
- package/scss/_utils.scss +3 -1
- package/scss/_vars.scss +1 -0
- package/scss/base/_layout.scss +8 -8
- package/scss/base/_reboot.scss +4 -29
- package/scss/base/_root.scss +27 -12
- package/scss/colors/_index.scss +66 -1
- package/scss/components/_alert-dialog.scss +3 -3
- package/scss/components/_bordered-button.scss +2 -2
- package/scss/components/_bordered-prominent-button.scss +3 -3
- package/scss/components/_borderless-button.scss +2 -2
- package/scss/components/_confirmation-dialog.scss +1 -1
- package/scss/components/_content-unavailable.scss +1 -1
- package/scss/components/{_body-view.scss → _content-view.scss} +2 -2
- package/scss/components/_date-picker.scss +1 -1
- package/scss/components/_detail-placeholder.scss +5 -5
- package/scss/components/_disclosure-group.scss +2 -2
- package/scss/components/_fine-tooltip.scss +1 -1
- package/scss/components/_form-view.scss +3 -3
- package/scss/components/_full-screen.scss +1 -1
- package/scss/components/_glass-button.scss +2 -2
- package/scss/components/_glass-prominent-button.scss +3 -3
- package/scss/components/_group-box.scss +1 -1
- package/scss/components/_h-divider.scss +1 -1
- package/scss/components/_h-flex-stack.scss +3 -1
- package/scss/components/_h-stack.scss +1 -1
- package/scss/components/_image-view.scss +1 -1
- package/scss/components/_index.scss +34 -24
- package/scss/components/_label-view.scss +1 -1
- package/scss/components/_labeled-content.scss +1 -1
- package/scss/components/_list-view.scss +3 -3
- package/scss/components/_menu-view.scss +3 -3
- package/scss/components/_navigation-large-title.scss +15 -9
- package/scss/components/_navigation-split-view.scss +18 -18
- package/scss/components/_navigation-stack.scss +1 -1
- package/scss/components/_navigation-title.scss +1 -1
- package/scss/components/_picker-view.scss +159 -119
- package/scss/components/_plain-button.scss +2 -2
- package/scss/components/_progress-view.scss +1 -1
- package/scss/components/_scroll-view-proxy.scss +1 -1
- package/scss/components/_scroll-view-toolbars.scss +1 -1
- package/scss/components/_scroll-view.scss +2 -2
- package/scss/components/_search-view.scss +1 -1
- package/scss/components/_section-view.scss +1 -1
- package/scss/components/_sheet-view.scss +2 -2
- package/scss/components/_sidebar-toggle.scss +1 -1
- package/scss/components/_sidebar-view.scss +2 -2
- package/scss/components/_sticky-container.scss +1 -1
- package/scss/components/_tab-bar.scss +1 -1
- package/scss/components/_tab-item.scss +1 -1
- package/scss/components/_tab-view.scss +23 -15
- package/scss/components/_table-column.scss +1 -1
- package/scss/components/_table-row.scss +1 -1
- package/scss/components/_table-view.scss +1 -1
- package/scss/components/_text-field.scss +1 -1
- package/scss/components/_text-view.scss +1 -1
- package/scss/components/_toggle-view.scss +41 -21
- package/scss/components/_tool-bar-item-group.scss +1 -1
- package/scss/components/_tool-bar-item.scss +2 -2
- package/scss/components/_tool-bar.scss +2 -2
- package/scss/components/_v-divider.scss +1 -1
- package/scss/components/_v-flex-stack.scss +3 -1
- package/scss/components/_v-keyboard.scss +1 -1
- package/scss/components/_v-stack.scss +1 -1
- package/scss/final/_touch-glass.scss +2 -2
- package/scss/mixins/_index.scss +2 -2
- package/scss/placeholders/_buttons.scss +5 -5
- package/scss/placeholders/_lists.scss +3 -3
- package/scss/transitions/_alert-dialog.scss +1 -1
- package/scss/transitions/_bwd.navbar.scss +1 -1
- package/scss/transitions/_bwd.scss +3 -3
- package/scss/transitions/_confirmation-dialog.scss +1 -1
- package/scss/transitions/_disclosure-group.scss +1 -1
- package/scss/transitions/_fine-tooltip.scss +1 -1
- package/scss/transitions/_fwd.navbar.scss +1 -1
- package/scss/transitions/_fwd.scss +1 -1
- package/scss/transitions/_glass-button.scss +1 -1
- package/scss/transitions/_glass-prominent-button.scss +1 -1
- package/scss/transitions/_index.scss +1 -1
- package/scss/transitions/_menu-view.scss +1 -1
- package/scss/transitions/_navigation-split-view.scss +1 -1
- package/scss/transitions/_progress-view.scss +1 -1
- package/scss/transitions/_sheet-view.scss +1 -1
- package/scss/transitions/_sidebar-view.scss +1 -1
- package/scss/transitions/_tab-bar.scss +1 -1
- package/scss/utils/_background.scss +52 -0
- package/scss/utils/_frame.scss +2 -2
- package/scss/utils/_index.scss +33 -8
- package/scss/utils/_spacing.scss +1 -1
- package/scss/utils/_stacks.scss +5 -3
- package/generated/components/body-view.js +0 -17
- package/generated/internal/utils/cash/index.d.ts +0 -24
- package/generated/internal/utils/cash/index.js +0 -27
- package/generated/internal/utils/dev-flags.d.ts +0 -3
- package/generated/internal/utils/dev-flags.js +0 -5
- /package/{web-components.css-data → css-data}/en.json +0 -0
- /package/generated/internal/utils/{cash/ancestors.d.ts → ancestors.d.ts} +0 -0
- /package/generated/internal/utils/{cash/ancestors.js → ancestors.js} +0 -0
- /package/generated/internal/utils/{cash/next-all.d.ts → next-all.d.ts} +0 -0
- /package/generated/internal/utils/{cash/next-all.js → next-all.js} +0 -0
- /package/generated/internal/utils/{cash/next.d.ts → next.d.ts} +0 -0
- /package/generated/internal/utils/{cash/next.js → next.js} +0 -0
- /package/generated/internal/utils/{cash/prev-all.d.ts → prev-all.d.ts} +0 -0
- /package/generated/internal/utils/{cash/prev-all.js → prev-all.js} +0 -0
- /package/generated/internal/utils/{cash/prev.d.ts → prev.d.ts} +0 -0
- /package/generated/internal/utils/{cash/prev.js → prev.js} +0 -0
- /package/generated/internal/utils/{cash/prop.d.ts → prop.d.ts} +0 -0
- /package/generated/internal/utils/{cash/prop.js → prop.js} +0 -0
- /package/generated/internal/utils/{cash/siblings.d.ts → siblings.d.ts} +0 -0
- /package/generated/internal/utils/{cash/siblings.js → siblings.js} +0 -0
- /package/scss/utils/{_scroll-view.scss → _scroll-view.scss.txt} +0 -0
|
@@ -5,13 +5,12 @@ import { FormAssociatedBase, getInternals } from '../internal/class/form-associa
|
|
|
5
5
|
import { MutationObserverSet } from '../internal/class/mutation-observer-set';
|
|
6
6
|
import { NavigationPath } from '../internal/class/navigation-path';
|
|
7
7
|
import { queryInsertPosition, startViewTransition } from '../internal/privateNamespace';
|
|
8
|
-
import { $,
|
|
8
|
+
import { $, ancestors, debug, kebabCase, onoff } from '../internal/utils';
|
|
9
9
|
import { queryMorph } from '../morphdom';
|
|
10
10
|
import { html, render } from '../tpl';
|
|
11
|
-
const pickerStyles = ['menu', 'inline', 'navigation-link', 'sheet', 'automatic'];
|
|
11
|
+
const pickerStyles = ['menu', 'inline', 'navigation-link', 'sheet', 'radio-group', 'automatic'];
|
|
12
12
|
const update = (path, node, overwrite = true) => {
|
|
13
|
-
|
|
14
|
-
console.debug(`PickerView: update`);
|
|
13
|
+
debug(`PickerView: update`);
|
|
15
14
|
if (!(path instanceof NavigationPath))
|
|
16
15
|
throw new Error('invalid view');
|
|
17
16
|
const { component, page } = path;
|
|
@@ -23,8 +22,7 @@ const update = (path, node, overwrite = true) => {
|
|
|
23
22
|
page.insertAdjacentElement(position, node);
|
|
24
23
|
};
|
|
25
24
|
const reflectSpawnedPage = (current, source) => {
|
|
26
|
-
|
|
27
|
-
console.debug(`PickerView: reflectSpawnedPage`);
|
|
25
|
+
debug(`PickerView: reflectSpawnedPage`);
|
|
28
26
|
const { page: oldSv, toolBarConfig: oldToolbar } = new NavigationPath(current).hydrate(), { page: newSv, toolBarConfig: newToolbar } = new NavigationPath(source).hydrate();
|
|
29
27
|
const oldList = oldSv?.querySelector('list-view'), newList = newSv?.querySelector('list-view'), oldBackBtn = oldToolbar?.at(0)?.querySelector('button'), newBackBtn = newToolbar?.at(0)?.querySelector('button');
|
|
30
28
|
// pre replace list (always exists)
|
|
@@ -62,12 +60,10 @@ const reflectSpawnedPage = (current, source) => {
|
|
|
62
60
|
oldSearch?.remove();
|
|
63
61
|
};
|
|
64
62
|
const extractTag = (node) => {
|
|
65
|
-
|
|
66
|
-
console.debug(`PickerView: extractTag`);
|
|
63
|
+
debug(`PickerView: extractTag`);
|
|
67
64
|
return node instanceof HTMLOptionElement ? (((node.getAttribute('value') ?? node.textContent?.trim()) || node.getAttribute('label')) ?? '') : (node.value ?? '');
|
|
68
65
|
}, extractLabel = (node) => {
|
|
69
|
-
|
|
70
|
-
console.debug(`PickerView: extractLabelFromGroup`);
|
|
66
|
+
debug(`PickerView: extractLabelFromGroup`);
|
|
71
67
|
if (node instanceof Element)
|
|
72
68
|
if (node instanceof HTMLOptionElement)
|
|
73
69
|
return (node.getAttribute('label') ?? node.getAttribute('value') ?? node.textContent?.trim()) || null;
|
|
@@ -77,16 +73,14 @@ const extractTag = (node) => {
|
|
|
77
73
|
return node.title ?? node.value ?? null;
|
|
78
74
|
// return node instanceof Element ? node.getAttribute('DATALIST' === node.tagName ? 'data-label' : 'label') : (node.title ?? node.value ?? null)
|
|
79
75
|
}, extractIcon = (node) => {
|
|
80
|
-
|
|
81
|
-
console.debug(`PickerView: extractIcon`);
|
|
76
|
+
debug(`PickerView: extractIcon`);
|
|
82
77
|
// return node instanceof Element ? node.getAttribute('data-system-image') : (node.systemImage ?? null)
|
|
83
78
|
if (node instanceof Element)
|
|
84
79
|
return node.getAttribute('data-system-image');
|
|
85
80
|
else
|
|
86
81
|
return node.systemImage ?? null;
|
|
87
82
|
}, extractSubtitle = (node) => {
|
|
88
|
-
|
|
89
|
-
console.debug(`PickerView: extractSubtitle`);
|
|
83
|
+
debug(`PickerView: extractSubtitle`);
|
|
90
84
|
if (node instanceof Element)
|
|
91
85
|
return node.getAttribute('data-subtitle');
|
|
92
86
|
else
|
|
@@ -115,42 +109,73 @@ const indexGroups = (nodes, parentPath = '') => {
|
|
|
115
109
|
return map;
|
|
116
110
|
};
|
|
117
111
|
const collectLeafValues = (node) => (node.children.length ? node.children.flatMap(collectLeafValues) : [node.value]);
|
|
112
|
+
const flattenDictionary = (tree) => {
|
|
113
|
+
const out1 = {}, out2 = {}, stack = [tree], idx = [0];
|
|
114
|
+
while (stack.length) {
|
|
115
|
+
const frame = stack[stack.length - 1], i = idx[idx.length - 1];
|
|
116
|
+
if (i >= frame.length) {
|
|
117
|
+
stack.pop();
|
|
118
|
+
idx.pop();
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
idx[idx.length - 1]++;
|
|
122
|
+
const { value, title, systemImage, children } = frame[i];
|
|
123
|
+
out1[value] = title;
|
|
124
|
+
out2[value] = systemImage;
|
|
125
|
+
if (children.length) {
|
|
126
|
+
stack.push(children);
|
|
127
|
+
idx.push(0);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return { labels: out1, icons: out2 };
|
|
131
|
+
};
|
|
118
132
|
/**
|
|
119
133
|
* @summary A control that selects one value from a set of options.
|
|
120
134
|
*
|
|
121
|
-
* @attr {menu|inline|navigation-link|sheet|automatic} picker-style
|
|
122
|
-
*
|
|
123
|
-
* @attr help — Adds a help tooltip to the trigger of the picker, if style supports one
|
|
124
|
-
*
|
|
125
|
-
* @attr {DictEntry[]} dictionary — Renders all options using this array
|
|
126
|
-
*
|
|
127
135
|
* @attr {vertical|horizontal|auto} label-value-placement
|
|
128
136
|
*
|
|
129
|
-
* @
|
|
137
|
+
* @attr {boolean} horizontal-radio-group-layout
|
|
138
|
+
*
|
|
139
|
+
* @slot — The default slot
|
|
130
140
|
* @slot label
|
|
131
141
|
* @slot list
|
|
132
142
|
* @slot {HTMLOptionElement[]} validity-options
|
|
133
143
|
*/
|
|
134
144
|
export class PickerView extends FormAssociatedBase {
|
|
135
|
-
static get ATTR() {
|
|
136
|
-
return {
|
|
137
|
-
PLACEHOLDER: 'prompt',
|
|
138
|
-
PLACEHOLDER_ICON: 'prompt-icon',
|
|
139
|
-
LABEL: 'label',
|
|
140
|
-
PICKER_STYLE: 'picker-style',
|
|
141
|
-
SELECTION: 'selection',
|
|
142
|
-
SEARCHABLE: 'searchable',
|
|
143
|
-
CURRENT_VALUE_LABEL: 'current-value-label',
|
|
144
|
-
CURRENT_VALUE_ICON: 'current-value-icon',
|
|
145
|
-
TRIGGER_HELP: 'help',
|
|
146
|
-
DICTIONARY: 'dictionary',
|
|
147
|
-
REQUIRED: 'required',
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
145
|
static get observedAttributes() {
|
|
151
|
-
return
|
|
146
|
+
return [
|
|
147
|
+
'prompt',
|
|
148
|
+
'prompt-icon',
|
|
149
|
+
'label',
|
|
150
|
+
'name',
|
|
151
|
+
/**
|
|
152
|
+
* @type {menu|inline|navigation-link|sheet|automatic}
|
|
153
|
+
*/
|
|
154
|
+
'picker-style',
|
|
155
|
+
'selection',
|
|
156
|
+
/**
|
|
157
|
+
* @type {boolean}
|
|
158
|
+
*/
|
|
159
|
+
'searchable',
|
|
160
|
+
'current-value-label',
|
|
161
|
+
'current-value-icon',
|
|
162
|
+
/**
|
|
163
|
+
* Adds a help tooltip to the trigger of the picker, if style supports one
|
|
164
|
+
*/
|
|
165
|
+
'help',
|
|
166
|
+
/**
|
|
167
|
+
* Renders all options using this array
|
|
168
|
+
* @type {DictEntry[]}
|
|
169
|
+
*/
|
|
170
|
+
'dictionary',
|
|
171
|
+
/**
|
|
172
|
+
* @type {boolean}
|
|
173
|
+
*/
|
|
174
|
+
'required',
|
|
175
|
+
];
|
|
152
176
|
}
|
|
153
177
|
static #templates = new Map();
|
|
178
|
+
#guuid = self.crypto.randomUUID();
|
|
154
179
|
#spawn;
|
|
155
180
|
#makeGroupClickHandler(el, groupId) {
|
|
156
181
|
return async (evt) => {
|
|
@@ -159,7 +184,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
159
184
|
const { target } = evt;
|
|
160
185
|
if (!(target instanceof HTMLElement))
|
|
161
186
|
return;
|
|
162
|
-
const newPage = this.#spawnPage(el instanceof Element ? Array.from(el.children) : el.children, '
|
|
187
|
+
const newPage = this.#spawnPage(el instanceof Element ? Array.from(el.children) : el.children, 'content-view', groupId, this.hasAttribute('searchable'), extractLabel(el));
|
|
163
188
|
if (!newPage)
|
|
164
189
|
return;
|
|
165
190
|
newPage.dataset.groupId = groupId; // <-- tag the spawned page
|
|
@@ -171,9 +196,36 @@ export class PickerView extends FormAssociatedBase {
|
|
|
171
196
|
};
|
|
172
197
|
}
|
|
173
198
|
#spawnPage = (elements, tag, parentGroupId, searchable = false, title) => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
199
|
+
debug(`${_a.name} #spawnPage`);
|
|
200
|
+
const body = tag === 'sheet-view'
|
|
201
|
+
? $(html `<dialog is="sheet-view">
|
|
202
|
+
<scroll-view>
|
|
203
|
+
<v-stack placement="leading fill">
|
|
204
|
+
<list-view preferred-expanded-style="inset"></list-view>
|
|
205
|
+
</v-stack>
|
|
206
|
+
</scroll-view>
|
|
207
|
+
<tool-bar>
|
|
208
|
+
<tool-bar-item slot="top-bar-leading">
|
|
209
|
+
<button type="button" tabindex="0">
|
|
210
|
+
<label-view system-image="x"></label-view>
|
|
211
|
+
</button>
|
|
212
|
+
</tool-bar-item>
|
|
213
|
+
</tool-bar>
|
|
214
|
+
</dialog>`, '>1')
|
|
215
|
+
: $(html `<content-view>
|
|
216
|
+
<scroll-view>
|
|
217
|
+
<v-stack placement="leading fill">
|
|
218
|
+
<list-view preferred-expanded-style="inset"></list-view>
|
|
219
|
+
</v-stack>
|
|
220
|
+
</scroll-view>
|
|
221
|
+
<tool-bar>
|
|
222
|
+
<tool-bar-item slot="top-bar-leading">
|
|
223
|
+
<button type="button" tabindex="0">
|
|
224
|
+
<label-view system-image="caret-left"></label-view>
|
|
225
|
+
</button>
|
|
226
|
+
</tool-bar-item>
|
|
227
|
+
</tool-bar>
|
|
228
|
+
</content-view>`, '>1'), sv = body.querySelector('scroll-view'), list = body.querySelector('list-view'), backBtn = body.querySelector('button');
|
|
177
229
|
if (title)
|
|
178
230
|
sv?.setAttribute('navigation-inline-title', title);
|
|
179
231
|
if (searchable) {
|
|
@@ -226,15 +278,15 @@ export class PickerView extends FormAssociatedBase {
|
|
|
226
278
|
if (el instanceof Element)
|
|
227
279
|
switch (el.tagName) {
|
|
228
280
|
case 'OPTGROUP': {
|
|
229
|
-
const group =
|
|
230
|
-
|
|
281
|
+
const group = this.#wrapOptgroupTag(el);
|
|
282
|
+
this.#reflectButtons([...el.children], group);
|
|
231
283
|
for (const btn of group.querySelectorAll(':scope>button'))
|
|
232
284
|
btn.addEventListener('click', this.#handlePageBtnClick);
|
|
233
285
|
list?.appendChild(group);
|
|
234
286
|
break;
|
|
235
287
|
}
|
|
236
288
|
case 'OPTION': {
|
|
237
|
-
const btn =
|
|
289
|
+
const btn = this.#wrapOptionTag(el);
|
|
238
290
|
btn.addEventListener('click', this.#handlePageBtnClick);
|
|
239
291
|
list?.appendChild(btn);
|
|
240
292
|
break;
|
|
@@ -258,8 +310,8 @@ export class PickerView extends FormAssociatedBase {
|
|
|
258
310
|
else {
|
|
259
311
|
if (el.children.length)
|
|
260
312
|
if (allLeaves(el)) {
|
|
261
|
-
const group =
|
|
262
|
-
|
|
313
|
+
const group = this.#wrapOptgroupTag(el);
|
|
314
|
+
this.#reflectButtons(el.children, group);
|
|
263
315
|
for (const btn of group.querySelectorAll(':scope>button'))
|
|
264
316
|
btn.addEventListener('click', this.#handlePageBtnClick);
|
|
265
317
|
list?.appendChild(group);
|
|
@@ -272,7 +324,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
272
324
|
list?.appendChild(btn);
|
|
273
325
|
}
|
|
274
326
|
else {
|
|
275
|
-
const btn =
|
|
327
|
+
const btn = this.#wrapOptionTag(el);
|
|
276
328
|
btn.addEventListener('click', this.#handlePageBtnClick);
|
|
277
329
|
list?.appendChild(btn);
|
|
278
330
|
}
|
|
@@ -284,8 +336,8 @@ export class PickerView extends FormAssociatedBase {
|
|
|
284
336
|
if (!this.#spawn)
|
|
285
337
|
return;
|
|
286
338
|
const groupMap = indexGroups(freshRoot);
|
|
287
|
-
for (const el of this.#spawn.querySelectorAll('
|
|
288
|
-
const depth =
|
|
339
|
+
for (const el of this.#spawn.querySelectorAll('content-view')) {
|
|
340
|
+
const depth = ancestors('content-view,[is=sheet-view]', el).indexOf(this.#spawn);
|
|
289
341
|
if (0 >= depth)
|
|
290
342
|
continue;
|
|
291
343
|
const groupId = el.dataset.groupId;
|
|
@@ -296,38 +348,18 @@ export class PickerView extends FormAssociatedBase {
|
|
|
296
348
|
}
|
|
297
349
|
const children = source instanceof Element ? Array.from(source.children) : source.children;
|
|
298
350
|
const title = source instanceof Element ? extractLabel(source) : (source.title ?? null);
|
|
299
|
-
const newPage = this.#spawnPage(children, '
|
|
351
|
+
const newPage = this.#spawnPage(children, 'content-view', groupId, this.hasAttribute('searchable'), title);
|
|
300
352
|
newPage.dataset.groupId = groupId;
|
|
301
353
|
reflectSpawnedPage(el, newPage);
|
|
302
354
|
}
|
|
303
355
|
};
|
|
304
356
|
#renderButtons(input) {
|
|
305
|
-
|
|
306
|
-
console.debug(`${_a.name} #renderButtons`);
|
|
357
|
+
debug(`${_a.name} #renderButtons`);
|
|
307
358
|
switch (input.mode) {
|
|
308
359
|
case 'dictionary': {
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
const frame = stack[stack.length - 1], i = idx[idx.length - 1];
|
|
313
|
-
if (i >= frame.length) {
|
|
314
|
-
stack.pop();
|
|
315
|
-
idx.pop();
|
|
316
|
-
continue;
|
|
317
|
-
}
|
|
318
|
-
idx[idx.length - 1]++;
|
|
319
|
-
const { value, title, systemImage, children } = frame[i];
|
|
320
|
-
out1[value] = title;
|
|
321
|
-
out2[value] = systemImage;
|
|
322
|
-
if (children.length) {
|
|
323
|
-
stack.push(children);
|
|
324
|
-
idx.push(0);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
return { labels: out1, icons: out2 };
|
|
328
|
-
};
|
|
329
|
-
this.#lastRenderedLabelMap = flattenDictionary(input.source).labels;
|
|
330
|
-
this.#lastRenderedIconMap = flattenDictionary(input.source).icons;
|
|
360
|
+
const { labels, icons } = flattenDictionary(input.source);
|
|
361
|
+
this.#lastRenderedLabelMap = labels;
|
|
362
|
+
this.#lastRenderedIconMap = icons;
|
|
331
363
|
// const collectLeafValues = (node: DictEntry): string[] => (node.children.length ? node.children.flatMap(collectLeafValues) : [node.value])
|
|
332
364
|
// collectGroups = (nodes: DictEntry[]): string[][] => {
|
|
333
365
|
// const groups: string[][] = []
|
|
@@ -384,24 +416,24 @@ export class PickerView extends FormAssociatedBase {
|
|
|
384
416
|
el.remove();
|
|
385
417
|
CleanupRegistry.unregister(this, 'trigger');
|
|
386
418
|
CleanupRegistry.register(this, onoff('click', this.#handleTriggerClick, currentValueLabel).on(), 'trigger');
|
|
387
|
-
if (this.hasAttribute(
|
|
388
|
-
currentValueLabel?.setAttribute(
|
|
419
|
+
if (this.hasAttribute('help'))
|
|
420
|
+
currentValueLabel?.setAttribute('help', this.getAttribute('help') ?? '');
|
|
389
421
|
// rebuild snapshot(tree)
|
|
390
422
|
if (!this.#spawn)
|
|
391
423
|
break;
|
|
392
424
|
// rerender level 0
|
|
393
|
-
reflectSpawnedPage(this.#spawn, this.#spawnPage(input.source, 'DIALOG' === this.#spawn.tagName ? 'sheet-view' : '
|
|
425
|
+
reflectSpawnedPage(this.#spawn, this.#spawnPage(input.source, 'DIALOG' === this.#spawn.tagName ? 'sheet-view' : 'content-view', undefined, this.hasAttribute('searchable'), this.getAttribute('label')));
|
|
394
426
|
this.#resyncSpawnedPages(input.source);
|
|
395
427
|
// // FIXME:
|
|
396
|
-
// for (const el of this.#spawn.querySelectorAll<HTMLElement>('
|
|
397
|
-
// const depth = $.ancestors('
|
|
428
|
+
// for (const el of this.#spawn.querySelectorAll<HTMLElement>('content-view')) {
|
|
429
|
+
// const depth = $.ancestors('content-view,[is=sheet-view]', el).indexOf(this.#spawn)
|
|
398
430
|
// if (0 >= depth) continue
|
|
399
431
|
// const datalist = this.querySelector<HTMLElement>(`:scope>${Array.from({ length: depth }, () => 'datalist').join('>')}`)
|
|
400
432
|
// if (!datalist) {
|
|
401
433
|
// el.remove()
|
|
402
434
|
// break
|
|
403
435
|
// }
|
|
404
|
-
// reflectSpawnedElement(el, this.#spawnPage(Array.from(datalist.children), '
|
|
436
|
+
// reflectSpawnedElement(el, this.#spawnPage(Array.from(datalist.children), 'content-view', this.hasAttribute('searchable'), datalist.dataset.label))
|
|
405
437
|
// }
|
|
406
438
|
break;
|
|
407
439
|
}
|
|
@@ -419,9 +451,21 @@ export class PickerView extends FormAssociatedBase {
|
|
|
419
451
|
// renderLabelIcon(currentValueLabel, 'dots-three') // overwritten
|
|
420
452
|
// renderLabelTitle(currentValueLabel, this.#currentValueLabel) // overwritten
|
|
421
453
|
// }
|
|
422
|
-
if (this.hasAttribute(
|
|
423
|
-
currentValueLabel?.setAttribute(
|
|
424
|
-
|
|
454
|
+
if (this.hasAttribute('help'))
|
|
455
|
+
currentValueLabel?.setAttribute('help', this.getAttribute('help') ?? '');
|
|
456
|
+
this.#reflectButtons(input.source, menu);
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
case 'radio-group': {
|
|
460
|
+
// capture
|
|
461
|
+
// const stack = this.querySelector<HTMLElement>(':scope>v-stack:not([slot])') ?? this.appendChild<HTMLElement>($(html`<v-stack></v-stack>`, '>1'))
|
|
462
|
+
// reset state
|
|
463
|
+
// stack.innerHTML = ''
|
|
464
|
+
// clear all siblings
|
|
465
|
+
for (const el of this.querySelectorAll(':scope>:not([slot])'))
|
|
466
|
+
el.remove();
|
|
467
|
+
// add buttons
|
|
468
|
+
this.#reflectButtons(input.source, this);
|
|
425
469
|
break;
|
|
426
470
|
}
|
|
427
471
|
case 'inline':
|
|
@@ -435,38 +479,38 @@ export class PickerView extends FormAssociatedBase {
|
|
|
435
479
|
if (inlineList !== el)
|
|
436
480
|
el.remove();
|
|
437
481
|
// add label as a plain element
|
|
438
|
-
const value = this.getAttribute(
|
|
482
|
+
const value = this.getAttribute('label');
|
|
439
483
|
if (value) {
|
|
440
|
-
const hStack = $(html `<h-stack distribution="leading" template="auto spacer"
|
|
441
|
-
|
|
442
|
-
|
|
484
|
+
const hStack = $(html `<h-stack distribution="leading" template="auto spacer">
|
|
485
|
+
<label-view data-role="check" style="visibility: hidden">
|
|
486
|
+
<image-view slot="icon" system-name="check"></image-view>
|
|
487
|
+
</label-view>
|
|
488
|
+
<label-view><span></span></label-view>
|
|
489
|
+
</h-stack>`, '>1');
|
|
443
490
|
queryMorph('label-view:nth-child(2)', html `<label-view>${value ? html `<span>${value}</span>` : null}</label-view>`, hStack);
|
|
444
491
|
// if (label) renderLabelTitle(label, value) //label.setAttribute('title', value)
|
|
445
492
|
section.insertAdjacentElement('beforeend', hStack);
|
|
446
493
|
}
|
|
447
494
|
if ('dictionary' === input.mode)
|
|
448
|
-
|
|
495
|
+
this.#reflectButtons(input.source.filter((el) => 0 === el.children.length), section);
|
|
449
496
|
else
|
|
450
|
-
|
|
497
|
+
this.#reflectButtons(input.source.filter((el) => el.matches('option')), section);
|
|
451
498
|
break;
|
|
452
499
|
}
|
|
453
500
|
}
|
|
454
501
|
this.#reflectSelectionOnButtons();
|
|
455
502
|
this.#reflectSelectionOnCurrentValueLabel();
|
|
456
503
|
}
|
|
457
|
-
#renderDictionary = (dictionary) => {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
};
|
|
504
|
+
// #renderDictionary = (dictionary: Dictionary) => {
|
|
505
|
+
// debug(`${PickerView.name} ⚡️ mutation`)
|
|
506
|
+
// this.#renderButtons({ mode: 'dictionary', source: dictionary })
|
|
507
|
+
// }
|
|
462
508
|
#renderSlotted = (entries) => {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
this.#renderButtons({ mode: 'list', source: this.#slots?.get('list')?.assignedElements({ flatten: true }) ?? [] });
|
|
509
|
+
debug(`${_a.name} ⚡️ mutation`);
|
|
510
|
+
this.#renderButtons(this.#resolveSource()); //this.#renderButtons({ mode: 'list', source: this.#slots?.get('list')?.assignedElements({ flatten: true }) ?? [] })
|
|
466
511
|
};
|
|
467
512
|
#renderValidityMsgs = (entries) => {
|
|
468
|
-
|
|
469
|
-
console.debug(`${_a.name} ⚡️ mutation`);
|
|
513
|
+
debug(`${_a.name} ⚡️ mutation`);
|
|
470
514
|
this.setValidity(this.validity, this.validationMessage);
|
|
471
515
|
};
|
|
472
516
|
#lastRenderedStyle; //string | null
|
|
@@ -491,11 +535,10 @@ export class PickerView extends FormAssociatedBase {
|
|
|
491
535
|
#lastRenderedIconMap = {};
|
|
492
536
|
#lastIndexedRoot = [];
|
|
493
537
|
get #currentValueLabel() {
|
|
494
|
-
return ((this.getAttribute(
|
|
495
|
-
this.#lastRenderedLabelMap[this.#selection]);
|
|
538
|
+
return ((this.getAttribute('current-value-label') ?? '').replaceAll('{{selection}}', this.#selection).replaceAll('{{currentValueLabel}}', this.#selection) || this.#lastRenderedLabelMap[this.#selection]);
|
|
496
539
|
}
|
|
497
540
|
get #currentValueIcon() {
|
|
498
|
-
return (this.getAttribute(
|
|
541
|
+
return (this.getAttribute('current-value-icon') ?? '') || this.#lastRenderedIconMap[this.#selection];
|
|
499
542
|
}
|
|
500
543
|
get #internals() {
|
|
501
544
|
return getInternals(this);
|
|
@@ -531,32 +574,46 @@ export class PickerView extends FormAssociatedBase {
|
|
|
531
574
|
<slot name="validity-options" hidden></slot>
|
|
532
575
|
</label>
|
|
533
576
|
`));
|
|
534
|
-
// break
|
|
535
|
-
// case 'compact':
|
|
536
|
-
// PickerView.#templates.set(
|
|
537
|
-
// style,
|
|
538
|
-
// Object.assign(document.createElement('template'), {
|
|
539
|
-
// innerHTML: String.raw`
|
|
540
|
-
// <label part="compact-picker">
|
|
541
|
-
// <input type="text" part="compact-input">
|
|
542
|
-
// </label>
|
|
543
|
-
// `,
|
|
544
|
-
// })
|
|
545
|
-
// )
|
|
546
|
-
// break
|
|
547
|
-
// case 'fancy':
|
|
548
|
-
// PickerView.#templates.set(
|
|
549
|
-
// style,
|
|
550
|
-
// Object.assign(document.createElement('template'), {
|
|
551
|
-
// innerHTML: String.raw`
|
|
552
|
-
// <div part="fancy-picker">
|
|
553
|
-
// <span>Fancy Picker</span>
|
|
554
|
-
// <input type="text" part="fancy-input">
|
|
555
|
-
// </div>
|
|
556
|
-
// `,
|
|
557
|
-
// })
|
|
558
|
-
// )
|
|
559
577
|
break;
|
|
578
|
+
case 'radio-group':
|
|
579
|
+
_a.#templates.set(this.pickerStyle, $(html `
|
|
580
|
+
<label part="root picker-stack">
|
|
581
|
+
<div part="root picker-label-stack">
|
|
582
|
+
<slot name="label"></slot>
|
|
583
|
+
</div>
|
|
584
|
+
<div part="root picker-input-stack">
|
|
585
|
+
<slot></slot>
|
|
586
|
+
</div>
|
|
587
|
+
<slot name="list" hidden></slot>
|
|
588
|
+
<slot name="validity-options" hidden></slot>
|
|
589
|
+
</label>
|
|
590
|
+
`));
|
|
591
|
+
break;
|
|
592
|
+
// break
|
|
593
|
+
// case 'compact':
|
|
594
|
+
// PickerView.#templates.set(
|
|
595
|
+
// style,
|
|
596
|
+
// Object.assign(document.createElement('template'), {
|
|
597
|
+
// innerHTML: String.raw`
|
|
598
|
+
// <label part="compact-picker">
|
|
599
|
+
// <input type="text" part="compact-input">
|
|
600
|
+
// </label>
|
|
601
|
+
// `,
|
|
602
|
+
// })
|
|
603
|
+
// )
|
|
604
|
+
// break
|
|
605
|
+
// case 'fancy':
|
|
606
|
+
// PickerView.#templates.set(
|
|
607
|
+
// style,
|
|
608
|
+
// Object.assign(document.createElement('template'), {
|
|
609
|
+
// innerHTML: String.raw`
|
|
610
|
+
// <div part="fancy-picker">
|
|
611
|
+
// <span>Fancy Picker</span>
|
|
612
|
+
// <input type="text" part="fancy-input">
|
|
613
|
+
// </div>
|
|
614
|
+
// `,
|
|
615
|
+
// })
|
|
616
|
+
// )
|
|
560
617
|
// case 'gg':
|
|
561
618
|
// PickerView.#templates.set(
|
|
562
619
|
// style,
|
|
@@ -598,68 +655,75 @@ export class PickerView extends FormAssociatedBase {
|
|
|
598
655
|
this.#shadowRoot = this.attachShadow({ mode: 'closed' });
|
|
599
656
|
}
|
|
600
657
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
601
|
-
|
|
602
|
-
console.debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
|
|
658
|
+
debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
|
|
603
659
|
switch (name) {
|
|
604
|
-
case
|
|
605
|
-
|
|
660
|
+
// case 'horizontal-radio-group-layout':
|
|
661
|
+
// if (oldValue === newValue) break
|
|
662
|
+
// this.#renderSlotted([])
|
|
663
|
+
// break
|
|
664
|
+
case 'prompt':
|
|
665
|
+
case 'prompt-icon':
|
|
606
666
|
if (oldValue === newValue)
|
|
607
667
|
break;
|
|
608
668
|
this.#reflectSelectionOnCurrentValueLabel(); //this.#reflectPlaceholder(newValue)
|
|
609
669
|
break;
|
|
610
|
-
case
|
|
670
|
+
case 'label':
|
|
611
671
|
this.#reflectLabel(newValue);
|
|
612
672
|
// this.#sendValueToForm()
|
|
613
673
|
break;
|
|
614
|
-
case
|
|
674
|
+
case 'picker-style':
|
|
615
675
|
if (oldValue === newValue)
|
|
616
676
|
break;
|
|
617
677
|
this.#render();
|
|
618
678
|
break;
|
|
619
|
-
case
|
|
679
|
+
case 'searchable':
|
|
620
680
|
if (oldValue === newValue)
|
|
621
681
|
break;
|
|
622
682
|
this.#renderSlotted([]);
|
|
623
683
|
break;
|
|
624
|
-
case
|
|
625
|
-
case
|
|
684
|
+
case 'current-value-label':
|
|
685
|
+
case 'current-value-icon':
|
|
626
686
|
// if (oldValue === newValue) break
|
|
627
687
|
this.#reflectSelectionOnCurrentValueLabel();
|
|
628
688
|
break;
|
|
629
|
-
case
|
|
689
|
+
case 'help':
|
|
630
690
|
// if (oldValue === newValue) break
|
|
631
691
|
this.#reflectTriggerHelp();
|
|
632
692
|
break;
|
|
633
|
-
case
|
|
693
|
+
case 'dictionary':
|
|
634
694
|
if (oldValue === newValue)
|
|
635
695
|
break;
|
|
636
|
-
this.#renderDictionary(parseDictionary(newValue))
|
|
696
|
+
this.#renderSlotted([]); // re-resolve: dictionary present → wins; removed → falls back to slotted //this.#renderDictionary(parseDictionary(newValue))
|
|
637
697
|
break;
|
|
638
|
-
case
|
|
698
|
+
case 'name':
|
|
699
|
+
case 'required':
|
|
639
700
|
if (oldValue === newValue)
|
|
640
701
|
break;
|
|
641
702
|
this.#sendValueToForm(false);
|
|
642
703
|
break;
|
|
643
|
-
case
|
|
644
|
-
|
|
704
|
+
case 'selection':
|
|
705
|
+
if (oldValue === newValue)
|
|
706
|
+
break;
|
|
707
|
+
this.#selection = newValue ?? '';
|
|
708
|
+
// FIXME: What about other callbacks from this.#selection=???? Somehow they run correctly
|
|
709
|
+
this.#sendValueToForm(false);
|
|
645
710
|
break;
|
|
646
711
|
}
|
|
647
712
|
}
|
|
648
713
|
disconnectedCallback() {
|
|
649
|
-
|
|
650
|
-
console.debug(`${_a.name} ⚡️ disconnect`);
|
|
714
|
+
debug(`${_a.name} ⚡️ disconnect`);
|
|
651
715
|
CleanupRegistry.unregister(this);
|
|
652
716
|
this.#validityObservers.unobserveAll();
|
|
653
717
|
this.#observers.unobserveAll();
|
|
654
718
|
}
|
|
655
719
|
connectedCallback() {
|
|
656
|
-
|
|
657
|
-
console.debug(`${_a.name} ⚡️ connect`);
|
|
720
|
+
debug(`${_a.name} ⚡️ connect`);
|
|
658
721
|
CleanupRegistry.register(this, onoff('localechange', () => {
|
|
659
722
|
this.#renderSlotted([]);
|
|
660
723
|
}, I18n.on).on());
|
|
661
724
|
CleanupRegistry.register(this, onoff('click', this.#handleClick, this).on());
|
|
662
|
-
|
|
725
|
+
CleanupRegistry.register(this, onoff('input', this.#handleInput, this).on());
|
|
726
|
+
if (!this.hasAttribute('picker-style'))
|
|
663
727
|
this.#render(); // skip if already rendered by attr-change during upgrade!
|
|
664
728
|
// finally
|
|
665
729
|
if (!this.hasAttribute('selection'))
|
|
@@ -668,13 +732,17 @@ export class PickerView extends FormAssociatedBase {
|
|
|
668
732
|
this.#sendValueToForm(false);
|
|
669
733
|
}
|
|
670
734
|
get pickerStyle() {
|
|
671
|
-
const attr =
|
|
735
|
+
const attr = 'picker-style';
|
|
672
736
|
return pickerStyles.includes(this.getAttribute(attr) ?? '') ? this.getAttribute(attr) : 'automatic';
|
|
673
737
|
}
|
|
738
|
+
#resolveSource() {
|
|
739
|
+
if (this.hasAttribute('dictionary'))
|
|
740
|
+
return { mode: 'dictionary', source: parseDictionary(this.getAttribute('dictionary')) };
|
|
741
|
+
return { mode: 'list', source: this.#slots?.get('list')?.assignedElements({ flatten: true }) ?? [] };
|
|
742
|
+
}
|
|
674
743
|
#render() {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
// const style = this.getAttribute((this.constructor as typeof PickerView).ATTR.PICKER_STYLE)
|
|
744
|
+
debug(`${_a.name} ⚡️ #render (${this.pickerStyle})`);
|
|
745
|
+
// const style = this.getAttribute('picker-style')
|
|
678
746
|
if (this.#lastRenderedStyle === this.pickerStyle)
|
|
679
747
|
return; // skip if already applied
|
|
680
748
|
this.#lastRenderedStyle = this.pickerStyle;
|
|
@@ -714,12 +782,13 @@ export class PickerView extends FormAssociatedBase {
|
|
|
714
782
|
this.dispatchEvent(new CustomEvent('selection', { detail: { selection: this.#selection }, bubbles: true, composed: true }));
|
|
715
783
|
};
|
|
716
784
|
#handleTriggerClick = async ({ type, target }) => {
|
|
717
|
-
|
|
718
|
-
console.debug(`${_a.name} ⚡️ ${type}`);
|
|
785
|
+
debug(`${_a.name} ⚡️ ${type}`);
|
|
719
786
|
if (!(target instanceof HTMLElement))
|
|
720
787
|
return;
|
|
721
788
|
this.#spawn?.remove?.();
|
|
722
|
-
const
|
|
789
|
+
const { source } = this.#resolveSource();
|
|
790
|
+
const level0 = this.#spawnPage(source, // this.hasAttribute('dictionary') ? parseDictionary(this.getAttribute('dictionary')) : (this.#slots?.get('list')?.assignedElements() ?? []),
|
|
791
|
+
'sheet' === this.pickerStyle ? 'sheet-view' : 'content-view', undefined, this.hasAttribute('searchable'), this.getAttribute('label'));
|
|
723
792
|
if (!level0)
|
|
724
793
|
return;
|
|
725
794
|
const path = new NavigationPath(target)?.hydrate();
|
|
@@ -730,8 +799,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
730
799
|
});
|
|
731
800
|
};
|
|
732
801
|
#handlePageBtnClick = async (evt) => {
|
|
733
|
-
|
|
734
|
-
console.debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
802
|
+
debug(`${_a.name} ⚡️ ${evt?.type}`);
|
|
735
803
|
evt.stopImmediatePropagation();
|
|
736
804
|
evt.preventDefault();
|
|
737
805
|
const { currentTarget: btn } = evt;
|
|
@@ -754,8 +822,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
754
822
|
});
|
|
755
823
|
};
|
|
756
824
|
#handleClick({ type, target }) {
|
|
757
|
-
|
|
758
|
-
console.debug(`${_a.name} ⚡️ ${type}`);
|
|
825
|
+
debug(`${_a.name} ⚡️ ${type}`);
|
|
759
826
|
if (!(target instanceof HTMLElement))
|
|
760
827
|
return;
|
|
761
828
|
const btn = target.closest('button');
|
|
@@ -766,9 +833,24 @@ export class PickerView extends FormAssociatedBase {
|
|
|
766
833
|
this.#reflectSelectionOnCurrentValueLabel();
|
|
767
834
|
this.#sendValueToForm();
|
|
768
835
|
}
|
|
836
|
+
#handleInput({ type, target }) {
|
|
837
|
+
debug(`${_a.name} ⚡️ ${type}`);
|
|
838
|
+
if (!(target instanceof HTMLElement))
|
|
839
|
+
return;
|
|
840
|
+
switch (this.pickerStyle) {
|
|
841
|
+
case 'radio-group':
|
|
842
|
+
const radio = target.closest('input[type="radio"]');
|
|
843
|
+
if (!radio)
|
|
844
|
+
return;
|
|
845
|
+
this.#selection = radio.getAttribute('value') ?? '';
|
|
846
|
+
this.#reflectSelectionOnButtons();
|
|
847
|
+
this.#reflectSelectionOnCurrentValueLabel();
|
|
848
|
+
this.#sendValueToForm();
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
769
852
|
#handleValiditiesSlotchange = ({ type, target: slot }) => {
|
|
770
|
-
|
|
771
|
-
console.debug(`${_a.name} ⚡️ ${type}`);
|
|
853
|
+
debug(`${_a.name} ⚡️ ${type}`);
|
|
772
854
|
if (!(slot instanceof HTMLSlotElement))
|
|
773
855
|
return;
|
|
774
856
|
const assigned = slot.assignedElements();
|
|
@@ -777,8 +859,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
777
859
|
this.#renderValidityMsgs([]);
|
|
778
860
|
};
|
|
779
861
|
#handleListSlotchange = ({ type, target: slot }) => {
|
|
780
|
-
|
|
781
|
-
console.debug(`${_a.name} ⚡️ ${type}`);
|
|
862
|
+
debug(`${_a.name} ⚡️ ${type}`);
|
|
782
863
|
if (!(slot instanceof HTMLSlotElement))
|
|
783
864
|
return;
|
|
784
865
|
const assigned = slot.assignedElements();
|
|
@@ -787,8 +868,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
787
868
|
this.#renderSlotted([]);
|
|
788
869
|
};
|
|
789
870
|
static #wrapOptionSpawnTag(node) {
|
|
790
|
-
|
|
791
|
-
console.debug(`${_a.name} #wrapOptionSpawnTag`);
|
|
871
|
+
debug(`${_a.name} #wrapOptionSpawnTag`);
|
|
792
872
|
const title = extractLabel(node), subtitle = extractSubtitle(node), icon = extractIcon(node);
|
|
793
873
|
const mount = document.createElement('div');
|
|
794
874
|
render(html `<button type="button" tabindex="0" navigation-link>
|
|
@@ -796,212 +876,180 @@ export class PickerView extends FormAssociatedBase {
|
|
|
796
876
|
<label-view data-role="check" style="visibility: hidden">
|
|
797
877
|
<image-view slot="icon" system-name="check"></image-view>
|
|
798
878
|
</label-view>
|
|
799
|
-
|
|
800
|
-
${icon ? html `<label-view system-image="${icon}"></label-view>` : null}
|
|
801
|
-
<v-stack spacing="3" alignment="fill">
|
|
802
|
-
<label-view title="${title}"></label-view>
|
|
803
|
-
${subtitle ? html `<label-view foreground="secondary" font="callout" title="${subtitle}"></label-view>` : null}
|
|
804
|
-
</v-stack>
|
|
805
|
-
</h-stack>
|
|
879
|
+
${_a.#morphITSLabel({ title, subtitle, icon })}
|
|
806
880
|
</h-stack>
|
|
807
881
|
</button>`, mount);
|
|
808
|
-
// const btn = $<HTMLButtonElement>(
|
|
809
|
-
// `<button type="button" tabindex="0" navigation-link><h-stack distribution="leading" template="auto spacer"><label-view data-role="check" style="visibility: hidden"><image-view slot="icon" system-name="check"></image-view></label-view><label-view><span></span></label-view></h-stack></button>`,
|
|
810
|
-
// '>1'
|
|
811
|
-
// ),
|
|
812
|
-
// hStack = btn.querySelector<LabelView>(':scope>h-stack') ?? undefined
|
|
813
|
-
// renderLabel(
|
|
814
|
-
// ':scope>label-view:nth-child(2)',
|
|
815
|
-
// `<label-view><span></span></label-view>`,
|
|
816
|
-
// hStack,
|
|
817
|
-
// extractLabelFromGroup(node as HTMLDataListElement),
|
|
818
|
-
// extractImgFromGroup(node as HTMLDataListElement)
|
|
819
|
-
// )
|
|
820
|
-
// // label = btn.querySelector<LabelView>(':scope>h-stack>label-view:nth-child(2)')
|
|
821
|
-
// // if (label) {
|
|
822
|
-
// // const lbl = extractLabelFromGroup(node as HTMLDataListElement),
|
|
823
|
-
// // img =extractImgFromGroup(node as HTMLDataListElement)
|
|
824
|
-
// // if(lbl) renderLabelTitle(label, node.dataset.label) //label?.setAttribute('title', el.dataset.label)
|
|
825
|
-
// // }
|
|
826
882
|
return mount.firstElementChild; //btn
|
|
827
883
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
console.debug(`${_a.name} #wrapOptionTag`);
|
|
884
|
+
#wrapOptionTag(node) {
|
|
885
|
+
debug(`${_a.name} #wrapOptionTag`);
|
|
831
886
|
const tag = extractTag(node), title = extractLabel(node), subtitle = extractSubtitle(node), icon = extractIcon(node);
|
|
832
887
|
const mount = document.createElement('div');
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
888
|
+
switch (this.pickerStyle) {
|
|
889
|
+
case 'radio-group':
|
|
890
|
+
render(_a.#morphRadioGroupBtn({ name: this.#guuid, title, subtitle, icon, tag }), mount);
|
|
891
|
+
return mount.firstElementChild; //btn
|
|
892
|
+
default:
|
|
893
|
+
render(html `<button type="button" tabindex="0" value="${tag}">
|
|
894
|
+
<h-stack distribution="leading" template="auto spacer">
|
|
895
|
+
<label-view data-role="check">
|
|
896
|
+
<image-view slot="icon" system-name="check"></image-view>
|
|
897
|
+
</label-view>
|
|
898
|
+
${_a.#morphITSLabel({ title, subtitle, icon })}
|
|
899
|
+
</h-stack>
|
|
900
|
+
</button>`, mount);
|
|
901
|
+
return mount.firstElementChild; //btn
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
static #morphRadioGroupGroup({ name, title, subtitle, icon }) {
|
|
905
|
+
return html `<label>
|
|
906
|
+
<h-stack distribution="fill" template="auto spacer" spacing="5">
|
|
907
|
+
<input type="radio" name="${name}" style="min-inline-size: 20px; margin: 0" disabled />
|
|
908
|
+
${_a.#morphITSLabel({ title, subtitle, icon })}
|
|
909
|
+
</h-stack>
|
|
910
|
+
</label>`;
|
|
911
|
+
}
|
|
912
|
+
static #morphRadioGroupBtn({ name, title, subtitle, icon, tag }) {
|
|
913
|
+
return html `<label>
|
|
914
|
+
<h-stack distribution="fill" template="auto spacer" spacing="5">
|
|
915
|
+
<input type="radio" name="${name}" value="${tag}" style="min-inline-size: 20px; margin: 0" />
|
|
916
|
+
${_a.#morphITSLabel({ title, subtitle, icon })}
|
|
917
|
+
</h-stack>
|
|
918
|
+
</label>`;
|
|
860
919
|
}
|
|
861
|
-
static #
|
|
862
|
-
|
|
863
|
-
|
|
920
|
+
static #morphITSLabel({ title, subtitle, icon }) {
|
|
921
|
+
return html `<h-stack distribution="fill" template="${icon ? 'auto spacer' : null}">
|
|
922
|
+
${icon ? html `<label-view system-image="${icon}"></label-view>` : null}
|
|
923
|
+
<v-stack spacing="3" alignment="fill">
|
|
924
|
+
<label-view title="${title}"></label-view>
|
|
925
|
+
${subtitle ? html `<label-view foreground="secondary" font="callout" title="${subtitle}"></label-view>` : null}
|
|
926
|
+
</v-stack>
|
|
927
|
+
</h-stack>`;
|
|
928
|
+
}
|
|
929
|
+
#wrapOptgroupTag(node) {
|
|
930
|
+
debug(`${_a.name} #wrapOptgroupTag`);
|
|
864
931
|
const title = extractLabel(node), subtitle = extractSubtitle(node), icon = extractIcon(node);
|
|
865
932
|
const mount = document.createElement('div');
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
933
|
+
switch (this.pickerStyle) {
|
|
934
|
+
case 'radio-group':
|
|
935
|
+
render(_a.#morphRadioGroupGroup({ name: this.#guuid, title, subtitle, icon }),
|
|
936
|
+
// this.hasAttribute('horizontal-radio-group-layout')
|
|
937
|
+
// ? html`<h-flex-stack style="flex-wrap: wrap">${PickerView.#morphRadioGroupGroup({ name: this.#guuid, title, subtitle, icon })}</h-flex-stack>`
|
|
938
|
+
// : html`<v-stack>${PickerView.#morphRadioGroupGroup({ name: this.#guuid, title, subtitle, icon })}</v-stack>`,
|
|
939
|
+
mount);
|
|
940
|
+
return mount.firstElementChild;
|
|
941
|
+
default:
|
|
942
|
+
render(html `<details is="disclosure-group" disclosure-style="marker-trailing">
|
|
943
|
+
<summary>
|
|
944
|
+
<h-stack distribution="leading" template="auto spacer">
|
|
945
|
+
<label-view data-role="check" style="visibility: hidden">
|
|
946
|
+
<image-view slot="icon" system-name="check"></image-view>
|
|
947
|
+
</label-view>
|
|
948
|
+
${_a.#morphITSLabel({ title, subtitle, icon })}
|
|
949
|
+
</h-stack>
|
|
950
|
+
</summary>
|
|
951
|
+
</details>`, mount);
|
|
952
|
+
return mount.firstElementChild;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
#wrapDatalistTag(node) {
|
|
956
|
+
const title = extractLabel(node), subtitle = extractSubtitle(node), icon = extractIcon(node);
|
|
957
|
+
const mount = document.createElement('div');
|
|
958
|
+
switch (this.pickerStyle) {
|
|
959
|
+
case 'radio-group':
|
|
960
|
+
render(_a.#morphRadioGroupGroup({ name: this.#guuid, title, subtitle, icon }),
|
|
961
|
+
// this.hasAttribute('horizontal-radio-group-layout')
|
|
962
|
+
// ? html`<h-flex-stack style="flex-wrap: wrap">${PickerView.#morphRadioGroupGroup({ name: this.#guuid, title, subtitle, icon })}</h-flex-stack>`
|
|
963
|
+
// : html`<v-stack>${PickerView.#morphRadioGroupGroup({ name: this.#guuid, title, subtitle, icon })}</v-stack>`,
|
|
964
|
+
mount);
|
|
965
|
+
return mount.firstElementChild;
|
|
966
|
+
default:
|
|
967
|
+
render(html `<menu-view tabindex="0">
|
|
968
|
+
<h-stack slot="label" distribution="leading" template="auto spacer">
|
|
969
|
+
<label-view data-role="check" style="visibility: hidden">
|
|
970
|
+
<image-view slot="icon" system-name="check"></image-view>
|
|
971
|
+
</label-view>
|
|
972
|
+
${_a.#morphITSLabel({ title, subtitle, icon })}
|
|
878
973
|
</h-stack>
|
|
879
|
-
</
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
return mount.firstElementChild;
|
|
883
|
-
// const labelT = `<label-view><span></span></label-view>`,
|
|
884
|
-
// summaryT = `<summary><h-stack distribution="leading" template="auto spacer"><label-view data-role="check" style="visibility: hidden"><image-view slot="icon" system-name="check"></image-view></label-view>${labelT}</h-stack></summary>`
|
|
885
|
-
// const group = $(`<details is="disclosure-group" disclosure-style="marker-trailing">${summaryT}</details>`, '>1'), // NOTE: already applied, here it covers spawned sheets
|
|
886
|
-
// hStack = group.querySelector(':scope>summary>h-stack') ?? undefined // ?? group.appendChild($(summaryT, '>1'))
|
|
887
|
-
// // summaryLabel = summary.querySelector(':scope>label-view') ?? summary.appendChild($(labelT, '>1'))
|
|
888
|
-
// // if (node.hasAttribute('label')) summaryLabel.setAttribute('title', node.getAttribute('label') ?? '')
|
|
889
|
-
// // if (node.hasAttribute('data-system-image')) summaryLabel.setAttribute('system-image', node.getAttribute('data-system-image') ?? '')
|
|
890
|
-
// renderLabel(':scope>label-view:nth-child(2)', labelT, hStack, extractLabel(node), extractIcon(node))
|
|
891
|
-
// return group
|
|
974
|
+
</menu-view>`, mount);
|
|
975
|
+
return mount.firstElementChild;
|
|
976
|
+
}
|
|
892
977
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
if (devFlags.debug)
|
|
897
|
-
console.debug(`${_a.name} #reflectButtons`);
|
|
978
|
+
#reflectButtons(nodes, container) {
|
|
979
|
+
debug(`${_a.name} #reflectButtons`);
|
|
980
|
+
const flatten = 'radio-group' === this.pickerStyle;
|
|
898
981
|
for (const node of nodes)
|
|
899
982
|
if (node instanceof Element)
|
|
900
983
|
switch (node.tagName) {
|
|
901
984
|
case 'DATALIST': {
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
</label-view>
|
|
909
|
-
<h-stack distribution="fill" template="${icon ? 'auto spacer' : null}">
|
|
910
|
-
${icon ? html `<label-view system-image="${icon}"></label-view>` : null}
|
|
911
|
-
<v-stack spacing="3" alignment="fill">
|
|
912
|
-
<label-view title="${title}"></label-view>
|
|
913
|
-
${subtitle ? html `<label-view foreground="secondary" font="callout" title="${subtitle}"></label-view>` : null}
|
|
914
|
-
</v-stack>
|
|
915
|
-
</h-stack>
|
|
916
|
-
</h-stack>
|
|
917
|
-
</menu-view>`, mount);
|
|
918
|
-
const group = mount.firstElementChild;
|
|
919
|
-
// const group = $(
|
|
920
|
-
// `<menu-view tabindex="0"><h-stack slot="label" distribution="leading" template="auto spacer"><label-view data-role="check" style="visibility: hidden"><image-view slot="icon" system-name="check"></image-view></label-view><label-view><span></span></label-view></h-stack></menu-view>`,
|
|
921
|
-
// '>1'
|
|
922
|
-
// ),
|
|
923
|
-
// hStack = group.querySelector(':scope>h-stack[slot=label]') ?? undefined
|
|
924
|
-
// // label = group.querySelector(':scope>label-view[slot=label]') ?? group.appendChild($(`<label-view slot="label"></label-view>`, '>1'))
|
|
925
|
-
// // if (node.hasAttribute('data-label')) label.setAttribute('title', node.getAttribute('data-label') ?? '')
|
|
926
|
-
// // if (node.hasAttribute('data-system-image')) label.setAttribute('system-image', node.getAttribute('data-system-image') ?? '')
|
|
927
|
-
// renderLabel(':scope>label-view:nth-child(2)', `<label-view><span></span></label-view>`, hStack, extractLabel(node as HTMLDataListElement), extractIcon(node as HTMLDataListElement))
|
|
928
|
-
_a.#reflectButtons([...node.children], group);
|
|
985
|
+
if (flatten) {
|
|
986
|
+
this.#reflectButtons([...node.children], container);
|
|
987
|
+
break;
|
|
988
|
+
}
|
|
989
|
+
const group = this.#wrapDatalistTag(node);
|
|
990
|
+
this.#reflectButtons([...node.children], group);
|
|
929
991
|
container.appendChild(group);
|
|
930
992
|
break;
|
|
931
993
|
}
|
|
932
994
|
case 'OPTGROUP': {
|
|
933
|
-
|
|
934
|
-
|
|
995
|
+
if (flatten) {
|
|
996
|
+
this.#reflectButtons([...node.children], container);
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
const group = this.#wrapOptgroupTag(node);
|
|
1000
|
+
this.#reflectButtons([...node.children], group);
|
|
935
1001
|
container.appendChild(group);
|
|
936
1002
|
break;
|
|
937
1003
|
}
|
|
938
1004
|
case 'OPTION':
|
|
939
1005
|
default: {
|
|
940
|
-
container.appendChild(
|
|
1006
|
+
container.appendChild(this.#wrapOptionTag(node));
|
|
941
1007
|
break;
|
|
942
1008
|
}
|
|
943
1009
|
}
|
|
944
1010
|
else {
|
|
945
1011
|
if (node.children.length)
|
|
946
|
-
if (
|
|
947
|
-
|
|
948
|
-
|
|
1012
|
+
if (flatten)
|
|
1013
|
+
this.#reflectButtons(node.children, container);
|
|
1014
|
+
else if (allLeaves(node)) {
|
|
1015
|
+
const group = this.#wrapOptgroupTag(node);
|
|
1016
|
+
this.#reflectButtons(node.children, group);
|
|
949
1017
|
container.appendChild(group);
|
|
950
1018
|
}
|
|
951
1019
|
else {
|
|
952
|
-
const
|
|
953
|
-
|
|
954
|
-
render(html `<menu-view tabindex="0">
|
|
955
|
-
<h-stack slot="label" distribution="leading" template="auto spacer">
|
|
956
|
-
<label-view data-role="check" style="visibility: hidden">
|
|
957
|
-
<image-view slot="icon" system-name="check"></image-view>
|
|
958
|
-
</label-view>
|
|
959
|
-
<h-stack distribution="fill" template="${icon ? 'auto spacer' : null}">
|
|
960
|
-
${icon ? html `<label-view system-image="${icon}"></label-view>` : null}
|
|
961
|
-
<v-stack spacing="3" alignment="fill">
|
|
962
|
-
<label-view title="${title}"></label-view>
|
|
963
|
-
${subtitle ? html `<label-view foreground="secondary" font="callout" title="${subtitle}"></label-view>` : null}
|
|
964
|
-
</v-stack>
|
|
965
|
-
</h-stack>
|
|
966
|
-
</h-stack>
|
|
967
|
-
</menu-view>`, mount);
|
|
968
|
-
const group = mount.firstElementChild;
|
|
969
|
-
// const group = $(`<menu-view tabindex="0"></menu-view>`, '>1')
|
|
970
|
-
// renderLabel(':scope>label-view[slot=label]', `<label-view slot="label"><span></span></label-view>`, group, extractLabel(node), extractIcon(node))
|
|
971
|
-
_a.#reflectButtons(node.children, group);
|
|
1020
|
+
const group = this.#wrapDatalistTag(node);
|
|
1021
|
+
this.#reflectButtons(node.children, group);
|
|
972
1022
|
container.appendChild(group);
|
|
973
1023
|
}
|
|
974
1024
|
else
|
|
975
|
-
container.appendChild(
|
|
1025
|
+
container.appendChild(this.#wrapOptionTag(node));
|
|
976
1026
|
}
|
|
977
1027
|
}
|
|
978
1028
|
// #reflectPlaceholder(value: string | null) {
|
|
979
|
-
//
|
|
1029
|
+
// debug(`#reflectPlaceholder`)
|
|
980
1030
|
// const input = this.#shadowRoot.querySelector('input')
|
|
981
1031
|
// if (input) {
|
|
982
|
-
// if (value) input.setAttribute(
|
|
983
|
-
// else input.removeAttribute(
|
|
1032
|
+
// if (value) input.setAttribute('prompt', value)
|
|
1033
|
+
// else input.removeAttribute('prompt')
|
|
984
1034
|
// }
|
|
985
1035
|
// }
|
|
986
1036
|
#reflectLabel(value) {
|
|
987
|
-
|
|
988
|
-
console.debug(`${_a.name} #reflectLabel`);
|
|
1037
|
+
debug(`${_a.name} #reflectLabel`);
|
|
989
1038
|
queryMorph('[slot=label]', html `<label-view slot="label">${value ? html `<span>${value}</span>` : null}</label-view>`, this);
|
|
990
1039
|
this.#renderSlotted([]);
|
|
991
1040
|
}
|
|
992
1041
|
#reflectSelectionOnButtons() {
|
|
993
|
-
|
|
994
|
-
console.debug(`${_a.name} #reflectSelectionOnButtons`);
|
|
1042
|
+
debug(`${_a.name} #reflectSelectionOnButtons`);
|
|
995
1043
|
self.requestAnimationFrame(() => {
|
|
996
1044
|
this.ariaCurrent = this.#selection;
|
|
997
1045
|
const groupMap = indexGroups(this.#lastIndexedRoot);
|
|
998
1046
|
const groupContainsSelection = (source) => source instanceof Element ? [...source.querySelectorAll('option')].some((opt) => extractTag(opt) === this.#selection) : collectLeafValues(source).includes(this.#selection);
|
|
999
1047
|
const syncButtons = (root) => {
|
|
1000
|
-
// 1. plain value buttons
|
|
1048
|
+
// 1. plain value buttons
|
|
1001
1049
|
for (const el of root.querySelectorAll('button[value]:not([slot])'))
|
|
1002
1050
|
// $.prop('visibility', el.getAttribute('value') === this.#selection ? 'visible' : 'hidden', el.querySelector<HTMLElement>('label-view[data-role="check"]'))
|
|
1003
1051
|
el.querySelector('label-view[data-role="check"]')?.style.setProperty('visibility', el.getAttribute('value') === this.#selection ? 'visible' : 'hidden');
|
|
1004
|
-
// 2. details/optgroups
|
|
1052
|
+
// 2. details/optgroups
|
|
1005
1053
|
for (const details of root.querySelectorAll('details[is="disclosure-group"]')) {
|
|
1006
1054
|
const hasSelectedDescendant = [...details.querySelectorAll('button[value]')].some((btn) => btn.getAttribute('value') === this.#selection);
|
|
1007
1055
|
details.querySelector(':scope>summary label-view[data-role="check"]')?.style.setProperty('visibility', hasSelectedDescendant ? 'visible' : 'hidden');
|
|
@@ -1012,6 +1060,9 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1012
1060
|
const hasSelectedDescendant = source ? groupContainsSelection(source) : false;
|
|
1013
1061
|
btn.querySelector('label-view[data-role="check"]')?.style.setProperty('visibility', hasSelectedDescendant ? 'visible' : 'hidden');
|
|
1014
1062
|
}
|
|
1063
|
+
// 4. radio inputs
|
|
1064
|
+
for (const el of root.querySelectorAll('input[type=radio][value]'))
|
|
1065
|
+
el.checked = el.getAttribute('value') === this.#selection;
|
|
1015
1066
|
};
|
|
1016
1067
|
syncButtons(this);
|
|
1017
1068
|
if (this.#spawn)
|
|
@@ -1022,8 +1073,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1022
1073
|
* Overwrite cvlabel with the label prop of the current(find[value === #selection]) option/dictentry
|
|
1023
1074
|
*/
|
|
1024
1075
|
#reflectSelectionOnCurrentValueLabel() {
|
|
1025
|
-
|
|
1026
|
-
console.debug(`${_a.name} #reflectSelectionOnCurrentValueLabel`);
|
|
1076
|
+
debug(`${_a.name} #reflectSelectionOnCurrentValueLabel`);
|
|
1027
1077
|
self.requestAnimationFrame(() => {
|
|
1028
1078
|
switch (this.pickerStyle) {
|
|
1029
1079
|
case 'sheet':
|
|
@@ -1033,7 +1083,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1033
1083
|
break;
|
|
1034
1084
|
// if (!cvl) currentValueLabel.setAttribute('foreground', 'secondary')
|
|
1035
1085
|
// else currentValueLabel.removeAttribute('foreground')
|
|
1036
|
-
const title = this.#currentValueLabel || this.#selection || this.getAttribute(
|
|
1086
|
+
const title = this.#currentValueLabel || this.#selection || this.getAttribute('prompt'), systemImage = this.#currentValueIcon || this.getAttribute('prompt-icon');
|
|
1037
1087
|
queryMorph(':not([slot])', html `<span>${title}</span>`, currentValueLabel, { removeIf: !title });
|
|
1038
1088
|
queryMorph('[slot=icon]', html `<image-view slot="icon" system-name="${systemImage}"></image-view>`, currentValueLabel, { removeIf: !systemImage });
|
|
1039
1089
|
// morph(
|
|
@@ -1048,7 +1098,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1048
1098
|
break;
|
|
1049
1099
|
// if (!cvl) currentValueLabel.setAttribute('foreground', 'secondary')
|
|
1050
1100
|
// else currentValueLabel.removeAttribute('foreground')
|
|
1051
|
-
const title = this.#currentValueLabel || this.#selection || this.getAttribute(
|
|
1101
|
+
const title = this.#currentValueLabel || this.#selection || this.getAttribute('prompt'), systemImage = this.#currentValueIcon || this.getAttribute('prompt-icon');
|
|
1052
1102
|
queryMorph(':not([slot])', html `<span>${title}</span>`, currentValueLabel, { removeIf: !title });
|
|
1053
1103
|
queryMorph('[slot=icon]', html `<image-view slot="icon" system-name="${systemImage}"></image-view>`, currentValueLabel, { removeIf: !systemImage });
|
|
1054
1104
|
// morph(
|
|
@@ -1066,8 +1116,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1066
1116
|
});
|
|
1067
1117
|
}
|
|
1068
1118
|
#reflectTriggerHelp() {
|
|
1069
|
-
|
|
1070
|
-
console.debug(`${_a.name} #reflectTriggerHelp`);
|
|
1119
|
+
debug(`${_a.name} #reflectTriggerHelp`);
|
|
1071
1120
|
let trigger;
|
|
1072
1121
|
switch (this.pickerStyle) {
|
|
1073
1122
|
case 'sheet':
|
|
@@ -1082,10 +1131,10 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1082
1131
|
//udnefined
|
|
1083
1132
|
}
|
|
1084
1133
|
}
|
|
1085
|
-
if (this.hasAttribute(
|
|
1086
|
-
trigger?.setAttribute(
|
|
1134
|
+
if (this.hasAttribute('help'))
|
|
1135
|
+
trigger?.setAttribute('help', this.getAttribute('help') ?? '');
|
|
1087
1136
|
else
|
|
1088
|
-
trigger?.removeAttribute(
|
|
1137
|
+
trigger?.removeAttribute('help');
|
|
1089
1138
|
}
|
|
1090
1139
|
/**
|
|
1091
1140
|
* Form participation property
|
|
@@ -1122,8 +1171,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1122
1171
|
message = kebabCase(key);
|
|
1123
1172
|
break;
|
|
1124
1173
|
}
|
|
1125
|
-
|
|
1126
|
-
console.debug(`${_a.name} ⚡️ validity-change`);
|
|
1174
|
+
debug(`${_a.name} ⚡️ validity-change`);
|
|
1127
1175
|
return this.#internals.setValidity(flags, this.#customValidity || message, anchor);
|
|
1128
1176
|
};
|
|
1129
1177
|
setCustomValidity = (message) => {
|