@swiftwc/ui 0.0.0-dev.112 → 0.0.0-dev.114
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/components/h-flex-stack.d.ts +16 -0
- package/generated/components/h-flex-stack.js +18 -0
- package/generated/components/index.d.ts +2 -0
- package/generated/components/index.js +2 -0
- package/generated/components/picker-view.d.ts +3 -20
- package/generated/components/picker-view.js +306 -257
- package/generated/components/tab-view.js +1 -5
- package/generated/components/v-flex-stack.d.ts +16 -0
- package/generated/components/v-flex-stack.js +18 -0
- package/generated/css/index.css +274 -150
- package/html-data/en.json +91 -21
- package/package.json +1 -1
- package/scss/_maps.scss +3 -1
- package/scss/components/_h-flex-stack.scss +2 -0
- package/scss/components/_index.scss +1 -1
- package/scss/components/_picker-view.scss +157 -117
- package/scss/components/_v-flex-stack.scss +2 -0
- package/scss/utils/_stacks.scss +3 -1
|
@@ -8,7 +8,7 @@ import { queryInsertPosition, startViewTransition } from '../internal/privateNam
|
|
|
8
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
13
|
debug(`PickerView: update`);
|
|
14
14
|
if (!(path instanceof NavigationPath))
|
|
@@ -109,42 +109,73 @@ const indexGroups = (nodes, parentPath = '') => {
|
|
|
109
109
|
return map;
|
|
110
110
|
};
|
|
111
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
|
+
};
|
|
112
132
|
/**
|
|
113
133
|
* @summary A control that selects one value from a set of options.
|
|
114
134
|
*
|
|
115
|
-
* @attr {menu|inline|navigation-link|sheet|automatic} picker-style
|
|
116
|
-
*
|
|
117
|
-
* @attr help — Adds a help tooltip to the trigger of the picker, if style supports one
|
|
118
|
-
*
|
|
119
|
-
* @attr {DictEntry[]} dictionary — Renders all options using this array
|
|
120
|
-
*
|
|
121
135
|
* @attr {vertical|horizontal|auto} label-value-placement
|
|
122
136
|
*
|
|
137
|
+
* @attr {boolean} horizontal-radio-group-layout
|
|
138
|
+
*
|
|
123
139
|
* @slot — The default slot.
|
|
124
140
|
* @slot label
|
|
125
141
|
* @slot list
|
|
126
142
|
* @slot {HTMLOptionElement[]} validity-options
|
|
127
143
|
*/
|
|
128
144
|
export class PickerView extends FormAssociatedBase {
|
|
129
|
-
static get ATTR() {
|
|
130
|
-
return {
|
|
131
|
-
PLACEHOLDER: 'prompt',
|
|
132
|
-
PLACEHOLDER_ICON: 'prompt-icon',
|
|
133
|
-
LABEL: 'label',
|
|
134
|
-
PICKER_STYLE: 'picker-style',
|
|
135
|
-
SELECTION: 'selection',
|
|
136
|
-
SEARCHABLE: 'searchable',
|
|
137
|
-
CURRENT_VALUE_LABEL: 'current-value-label',
|
|
138
|
-
CURRENT_VALUE_ICON: 'current-value-icon',
|
|
139
|
-
TRIGGER_HELP: 'help',
|
|
140
|
-
DICTIONARY: 'dictionary',
|
|
141
|
-
REQUIRED: 'required',
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
145
|
static get observedAttributes() {
|
|
145
|
-
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
|
+
];
|
|
146
176
|
}
|
|
147
177
|
static #templates = new Map();
|
|
178
|
+
#guuid = self.crypto.randomUUID();
|
|
148
179
|
#spawn;
|
|
149
180
|
#makeGroupClickHandler(el, groupId) {
|
|
150
181
|
return async (evt) => {
|
|
@@ -247,15 +278,15 @@ export class PickerView extends FormAssociatedBase {
|
|
|
247
278
|
if (el instanceof Element)
|
|
248
279
|
switch (el.tagName) {
|
|
249
280
|
case 'OPTGROUP': {
|
|
250
|
-
const group =
|
|
251
|
-
|
|
281
|
+
const group = this.#wrapOptgroupTag(el);
|
|
282
|
+
this.#reflectButtons([...el.children], group);
|
|
252
283
|
for (const btn of group.querySelectorAll(':scope>button'))
|
|
253
284
|
btn.addEventListener('click', this.#handlePageBtnClick);
|
|
254
285
|
list?.appendChild(group);
|
|
255
286
|
break;
|
|
256
287
|
}
|
|
257
288
|
case 'OPTION': {
|
|
258
|
-
const btn =
|
|
289
|
+
const btn = this.#wrapOptionTag(el);
|
|
259
290
|
btn.addEventListener('click', this.#handlePageBtnClick);
|
|
260
291
|
list?.appendChild(btn);
|
|
261
292
|
break;
|
|
@@ -279,8 +310,8 @@ export class PickerView extends FormAssociatedBase {
|
|
|
279
310
|
else {
|
|
280
311
|
if (el.children.length)
|
|
281
312
|
if (allLeaves(el)) {
|
|
282
|
-
const group =
|
|
283
|
-
|
|
313
|
+
const group = this.#wrapOptgroupTag(el);
|
|
314
|
+
this.#reflectButtons(el.children, group);
|
|
284
315
|
for (const btn of group.querySelectorAll(':scope>button'))
|
|
285
316
|
btn.addEventListener('click', this.#handlePageBtnClick);
|
|
286
317
|
list?.appendChild(group);
|
|
@@ -293,7 +324,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
293
324
|
list?.appendChild(btn);
|
|
294
325
|
}
|
|
295
326
|
else {
|
|
296
|
-
const btn =
|
|
327
|
+
const btn = this.#wrapOptionTag(el);
|
|
297
328
|
btn.addEventListener('click', this.#handlePageBtnClick);
|
|
298
329
|
list?.appendChild(btn);
|
|
299
330
|
}
|
|
@@ -326,28 +357,9 @@ export class PickerView extends FormAssociatedBase {
|
|
|
326
357
|
debug(`${_a.name} #renderButtons`);
|
|
327
358
|
switch (input.mode) {
|
|
328
359
|
case 'dictionary': {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const frame = stack[stack.length - 1], i = idx[idx.length - 1];
|
|
333
|
-
if (i >= frame.length) {
|
|
334
|
-
stack.pop();
|
|
335
|
-
idx.pop();
|
|
336
|
-
continue;
|
|
337
|
-
}
|
|
338
|
-
idx[idx.length - 1]++;
|
|
339
|
-
const { value, title, systemImage, children } = frame[i];
|
|
340
|
-
out1[value] = title;
|
|
341
|
-
out2[value] = systemImage;
|
|
342
|
-
if (children.length) {
|
|
343
|
-
stack.push(children);
|
|
344
|
-
idx.push(0);
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return { labels: out1, icons: out2 };
|
|
348
|
-
};
|
|
349
|
-
this.#lastRenderedLabelMap = flattenDictionary(input.source).labels;
|
|
350
|
-
this.#lastRenderedIconMap = flattenDictionary(input.source).icons;
|
|
360
|
+
const { labels, icons } = flattenDictionary(input.source);
|
|
361
|
+
this.#lastRenderedLabelMap = labels;
|
|
362
|
+
this.#lastRenderedIconMap = icons;
|
|
351
363
|
// const collectLeafValues = (node: DictEntry): string[] => (node.children.length ? node.children.flatMap(collectLeafValues) : [node.value])
|
|
352
364
|
// collectGroups = (nodes: DictEntry[]): string[][] => {
|
|
353
365
|
// const groups: string[][] = []
|
|
@@ -404,8 +416,8 @@ export class PickerView extends FormAssociatedBase {
|
|
|
404
416
|
el.remove();
|
|
405
417
|
CleanupRegistry.unregister(this, 'trigger');
|
|
406
418
|
CleanupRegistry.register(this, onoff('click', this.#handleTriggerClick, currentValueLabel).on(), 'trigger');
|
|
407
|
-
if (this.hasAttribute(
|
|
408
|
-
currentValueLabel?.setAttribute(
|
|
419
|
+
if (this.hasAttribute('help'))
|
|
420
|
+
currentValueLabel?.setAttribute('help', this.getAttribute('help') ?? '');
|
|
409
421
|
// rebuild snapshot(tree)
|
|
410
422
|
if (!this.#spawn)
|
|
411
423
|
break;
|
|
@@ -439,9 +451,21 @@ export class PickerView extends FormAssociatedBase {
|
|
|
439
451
|
// renderLabelIcon(currentValueLabel, 'dots-three') // overwritten
|
|
440
452
|
// renderLabelTitle(currentValueLabel, this.#currentValueLabel) // overwritten
|
|
441
453
|
// }
|
|
442
|
-
if (this.hasAttribute(
|
|
443
|
-
currentValueLabel?.setAttribute(
|
|
444
|
-
|
|
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);
|
|
445
469
|
break;
|
|
446
470
|
}
|
|
447
471
|
case 'inline':
|
|
@@ -455,32 +479,35 @@ export class PickerView extends FormAssociatedBase {
|
|
|
455
479
|
if (inlineList !== el)
|
|
456
480
|
el.remove();
|
|
457
481
|
// add label as a plain element
|
|
458
|
-
const value = this.getAttribute(
|
|
482
|
+
const value = this.getAttribute('label');
|
|
459
483
|
if (value) {
|
|
460
|
-
const hStack = $(html `<h-stack distribution="leading" template="auto spacer"
|
|
461
|
-
|
|
462
|
-
|
|
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');
|
|
463
490
|
queryMorph('label-view:nth-child(2)', html `<label-view>${value ? html `<span>${value}</span>` : null}</label-view>`, hStack);
|
|
464
491
|
// if (label) renderLabelTitle(label, value) //label.setAttribute('title', value)
|
|
465
492
|
section.insertAdjacentElement('beforeend', hStack);
|
|
466
493
|
}
|
|
467
494
|
if ('dictionary' === input.mode)
|
|
468
|
-
|
|
495
|
+
this.#reflectButtons(input.source.filter((el) => 0 === el.children.length), section);
|
|
469
496
|
else
|
|
470
|
-
|
|
497
|
+
this.#reflectButtons(input.source.filter((el) => el.matches('option')), section);
|
|
471
498
|
break;
|
|
472
499
|
}
|
|
473
500
|
}
|
|
474
501
|
this.#reflectSelectionOnButtons();
|
|
475
502
|
this.#reflectSelectionOnCurrentValueLabel();
|
|
476
503
|
}
|
|
477
|
-
#renderDictionary = (dictionary) => {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
}
|
|
504
|
+
// #renderDictionary = (dictionary: Dictionary) => {
|
|
505
|
+
// debug(`${PickerView.name} ⚡️ mutation`)
|
|
506
|
+
// this.#renderButtons({ mode: 'dictionary', source: dictionary })
|
|
507
|
+
// }
|
|
481
508
|
#renderSlotted = (entries) => {
|
|
482
509
|
debug(`${_a.name} ⚡️ mutation`);
|
|
483
|
-
this.#renderButtons({ mode: 'list', source: this.#slots?.get('list')?.assignedElements({ flatten: true }) ?? [] })
|
|
510
|
+
this.#renderButtons(this.#resolveSource()); //this.#renderButtons({ mode: 'list', source: this.#slots?.get('list')?.assignedElements({ flatten: true }) ?? [] })
|
|
484
511
|
};
|
|
485
512
|
#renderValidityMsgs = (entries) => {
|
|
486
513
|
debug(`${_a.name} ⚡️ mutation`);
|
|
@@ -508,11 +535,10 @@ export class PickerView extends FormAssociatedBase {
|
|
|
508
535
|
#lastRenderedIconMap = {};
|
|
509
536
|
#lastIndexedRoot = [];
|
|
510
537
|
get #currentValueLabel() {
|
|
511
|
-
return ((this.getAttribute(
|
|
512
|
-
this.#lastRenderedLabelMap[this.#selection]);
|
|
538
|
+
return ((this.getAttribute('current-value-label') ?? '').replaceAll('{{selection}}', this.#selection).replaceAll('{{currentValueLabel}}', this.#selection) || this.#lastRenderedLabelMap[this.#selection]);
|
|
513
539
|
}
|
|
514
540
|
get #currentValueIcon() {
|
|
515
|
-
return (this.getAttribute(
|
|
541
|
+
return (this.getAttribute('current-value-icon') ?? '') || this.#lastRenderedIconMap[this.#selection];
|
|
516
542
|
}
|
|
517
543
|
get #internals() {
|
|
518
544
|
return getInternals(this);
|
|
@@ -548,32 +574,46 @@ export class PickerView extends FormAssociatedBase {
|
|
|
548
574
|
<slot name="validity-options" hidden></slot>
|
|
549
575
|
</label>
|
|
550
576
|
`));
|
|
551
|
-
// break
|
|
552
|
-
// case 'compact':
|
|
553
|
-
// PickerView.#templates.set(
|
|
554
|
-
// style,
|
|
555
|
-
// Object.assign(document.createElement('template'), {
|
|
556
|
-
// innerHTML: String.raw`
|
|
557
|
-
// <label part="compact-picker">
|
|
558
|
-
// <input type="text" part="compact-input">
|
|
559
|
-
// </label>
|
|
560
|
-
// `,
|
|
561
|
-
// })
|
|
562
|
-
// )
|
|
563
|
-
// break
|
|
564
|
-
// case 'fancy':
|
|
565
|
-
// PickerView.#templates.set(
|
|
566
|
-
// style,
|
|
567
|
-
// Object.assign(document.createElement('template'), {
|
|
568
|
-
// innerHTML: String.raw`
|
|
569
|
-
// <div part="fancy-picker">
|
|
570
|
-
// <span>Fancy Picker</span>
|
|
571
|
-
// <input type="text" part="fancy-input">
|
|
572
|
-
// </div>
|
|
573
|
-
// `,
|
|
574
|
-
// })
|
|
575
|
-
// )
|
|
576
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
|
+
// )
|
|
577
617
|
// case 'gg':
|
|
578
618
|
// PickerView.#templates.set(
|
|
579
619
|
// style,
|
|
@@ -617,47 +657,56 @@ export class PickerView extends FormAssociatedBase {
|
|
|
617
657
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
618
658
|
debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
|
|
619
659
|
switch (name) {
|
|
620
|
-
case
|
|
621
|
-
|
|
660
|
+
// case 'horizontal-radio-group-layout':
|
|
661
|
+
// if (oldValue === newValue) break
|
|
662
|
+
// this.#renderSlotted([])
|
|
663
|
+
// break
|
|
664
|
+
case 'prompt':
|
|
665
|
+
case 'prompt-icon':
|
|
622
666
|
if (oldValue === newValue)
|
|
623
667
|
break;
|
|
624
668
|
this.#reflectSelectionOnCurrentValueLabel(); //this.#reflectPlaceholder(newValue)
|
|
625
669
|
break;
|
|
626
|
-
case
|
|
670
|
+
case 'label':
|
|
627
671
|
this.#reflectLabel(newValue);
|
|
628
672
|
// this.#sendValueToForm()
|
|
629
673
|
break;
|
|
630
|
-
case
|
|
674
|
+
case 'picker-style':
|
|
631
675
|
if (oldValue === newValue)
|
|
632
676
|
break;
|
|
633
677
|
this.#render();
|
|
634
678
|
break;
|
|
635
|
-
case
|
|
679
|
+
case 'searchable':
|
|
636
680
|
if (oldValue === newValue)
|
|
637
681
|
break;
|
|
638
682
|
this.#renderSlotted([]);
|
|
639
683
|
break;
|
|
640
|
-
case
|
|
641
|
-
case
|
|
684
|
+
case 'current-value-label':
|
|
685
|
+
case 'current-value-icon':
|
|
642
686
|
// if (oldValue === newValue) break
|
|
643
687
|
this.#reflectSelectionOnCurrentValueLabel();
|
|
644
688
|
break;
|
|
645
|
-
case
|
|
689
|
+
case 'help':
|
|
646
690
|
// if (oldValue === newValue) break
|
|
647
691
|
this.#reflectTriggerHelp();
|
|
648
692
|
break;
|
|
649
|
-
case
|
|
693
|
+
case 'dictionary':
|
|
650
694
|
if (oldValue === newValue)
|
|
651
695
|
break;
|
|
652
|
-
this.#renderDictionary(parseDictionary(newValue))
|
|
696
|
+
this.#renderSlotted([]); // re-resolve: dictionary present → wins; removed → falls back to slotted //this.#renderDictionary(parseDictionary(newValue))
|
|
653
697
|
break;
|
|
654
|
-
case
|
|
698
|
+
case 'name':
|
|
699
|
+
case 'required':
|
|
655
700
|
if (oldValue === newValue)
|
|
656
701
|
break;
|
|
657
702
|
this.#sendValueToForm(false);
|
|
658
703
|
break;
|
|
659
|
-
case
|
|
660
|
-
|
|
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);
|
|
661
710
|
break;
|
|
662
711
|
}
|
|
663
712
|
}
|
|
@@ -673,7 +722,8 @@ export class PickerView extends FormAssociatedBase {
|
|
|
673
722
|
this.#renderSlotted([]);
|
|
674
723
|
}, I18n.on).on());
|
|
675
724
|
CleanupRegistry.register(this, onoff('click', this.#handleClick, this).on());
|
|
676
|
-
|
|
725
|
+
CleanupRegistry.register(this, onoff('input', this.#handleInput, this).on());
|
|
726
|
+
if (!this.hasAttribute('picker-style'))
|
|
677
727
|
this.#render(); // skip if already rendered by attr-change during upgrade!
|
|
678
728
|
// finally
|
|
679
729
|
if (!this.hasAttribute('selection'))
|
|
@@ -682,12 +732,17 @@ export class PickerView extends FormAssociatedBase {
|
|
|
682
732
|
this.#sendValueToForm(false);
|
|
683
733
|
}
|
|
684
734
|
get pickerStyle() {
|
|
685
|
-
const attr =
|
|
735
|
+
const attr = 'picker-style';
|
|
686
736
|
return pickerStyles.includes(this.getAttribute(attr) ?? '') ? this.getAttribute(attr) : 'automatic';
|
|
687
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
|
+
}
|
|
688
743
|
#render() {
|
|
689
744
|
debug(`${_a.name} ⚡️ #render (${this.pickerStyle})`);
|
|
690
|
-
// const style = this.getAttribute(
|
|
745
|
+
// const style = this.getAttribute('picker-style')
|
|
691
746
|
if (this.#lastRenderedStyle === this.pickerStyle)
|
|
692
747
|
return; // skip if already applied
|
|
693
748
|
this.#lastRenderedStyle = this.pickerStyle;
|
|
@@ -731,7 +786,9 @@ export class PickerView extends FormAssociatedBase {
|
|
|
731
786
|
if (!(target instanceof HTMLElement))
|
|
732
787
|
return;
|
|
733
788
|
this.#spawn?.remove?.();
|
|
734
|
-
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' : 'body-view', undefined, this.hasAttribute('searchable'), this.getAttribute('label'));
|
|
735
792
|
if (!level0)
|
|
736
793
|
return;
|
|
737
794
|
const path = new NavigationPath(target)?.hydrate();
|
|
@@ -776,6 +833,22 @@ export class PickerView extends FormAssociatedBase {
|
|
|
776
833
|
this.#reflectSelectionOnCurrentValueLabel();
|
|
777
834
|
this.#sendValueToForm();
|
|
778
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
|
+
}
|
|
779
852
|
#handleValiditiesSlotchange = ({ type, target: slot }) => {
|
|
780
853
|
debug(`${_a.name} ⚡️ ${type}`);
|
|
781
854
|
if (!(slot instanceof HTMLSlotElement))
|
|
@@ -803,188 +876,161 @@ export class PickerView extends FormAssociatedBase {
|
|
|
803
876
|
<label-view data-role="check" style="visibility: hidden">
|
|
804
877
|
<image-view slot="icon" system-name="check"></image-view>
|
|
805
878
|
</label-view>
|
|
806
|
-
|
|
807
|
-
${icon ? html `<label-view system-image="${icon}"></label-view>` : null}
|
|
808
|
-
<v-stack spacing="3" alignment="fill">
|
|
809
|
-
<label-view title="${title}"></label-view>
|
|
810
|
-
${subtitle ? html `<label-view foreground="secondary" font="callout" title="${subtitle}"></label-view>` : null}
|
|
811
|
-
</v-stack>
|
|
812
|
-
</h-stack>
|
|
879
|
+
${_a.#morphITSLabel({ title, subtitle, icon })}
|
|
813
880
|
</h-stack>
|
|
814
881
|
</button>`, mount);
|
|
815
|
-
// const btn = $<HTMLButtonElement>(
|
|
816
|
-
// `<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>`,
|
|
817
|
-
// '>1'
|
|
818
|
-
// ),
|
|
819
|
-
// hStack = btn.querySelector<LabelView>(':scope>h-stack') ?? undefined
|
|
820
|
-
// renderLabel(
|
|
821
|
-
// ':scope>label-view:nth-child(2)',
|
|
822
|
-
// `<label-view><span></span></label-view>`,
|
|
823
|
-
// hStack,
|
|
824
|
-
// extractLabelFromGroup(node as HTMLDataListElement),
|
|
825
|
-
// extractImgFromGroup(node as HTMLDataListElement)
|
|
826
|
-
// )
|
|
827
|
-
// // label = btn.querySelector<LabelView>(':scope>h-stack>label-view:nth-child(2)')
|
|
828
|
-
// // if (label) {
|
|
829
|
-
// // const lbl = extractLabelFromGroup(node as HTMLDataListElement),
|
|
830
|
-
// // img =extractImgFromGroup(node as HTMLDataListElement)
|
|
831
|
-
// // if(lbl) renderLabelTitle(label, node.dataset.label) //label?.setAttribute('title', el.dataset.label)
|
|
832
|
-
// // }
|
|
833
882
|
return mount.firstElementChild; //btn
|
|
834
883
|
}
|
|
835
|
-
|
|
884
|
+
#wrapOptionTag(node) {
|
|
836
885
|
debug(`${_a.name} #wrapOptionTag`);
|
|
837
886
|
const tag = extractTag(node), title = extractLabel(node), subtitle = extractSubtitle(node), icon = extractIcon(node);
|
|
838
887
|
const mount = document.createElement('div');
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
// renderLabelTitle(label, extractLabel(node)) // label.querySelector('span')!.textContent = extractCurrentValueFromOption(node) //label.setAttribute('title', extractCurrentValueFromOption(node))
|
|
863
|
-
// renderLabelIcon(label, extractIcon(node))
|
|
864
|
-
// hStack?.appendChild(label)
|
|
865
|
-
return mount.firstElementChild; //btn
|
|
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>`;
|
|
866
911
|
}
|
|
867
|
-
static #
|
|
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>`;
|
|
919
|
+
}
|
|
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) {
|
|
868
930
|
debug(`${_a.name} #wrapOptgroupTag`);
|
|
869
931
|
const title = extractLabel(node), subtitle = extractSubtitle(node), icon = extractIcon(node);
|
|
870
932
|
const mount = document.createElement('div');
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
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 })}
|
|
883
973
|
</h-stack>
|
|
884
|
-
</
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
return mount.firstElementChild;
|
|
888
|
-
// const labelT = `<label-view><span></span></label-view>`,
|
|
889
|
-
// 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>`
|
|
890
|
-
// const group = $(`<details is="disclosure-group" disclosure-style="marker-trailing">${summaryT}</details>`, '>1'), // NOTE: already applied, here it covers spawned sheets
|
|
891
|
-
// hStack = group.querySelector(':scope>summary>h-stack') ?? undefined // ?? group.appendChild($(summaryT, '>1'))
|
|
892
|
-
// // summaryLabel = summary.querySelector(':scope>label-view') ?? summary.appendChild($(labelT, '>1'))
|
|
893
|
-
// // if (node.hasAttribute('label')) summaryLabel.setAttribute('title', node.getAttribute('label') ?? '')
|
|
894
|
-
// // if (node.hasAttribute('data-system-image')) summaryLabel.setAttribute('system-image', node.getAttribute('data-system-image') ?? '')
|
|
895
|
-
// renderLabel(':scope>label-view:nth-child(2)', labelT, hStack, extractLabel(node), extractIcon(node))
|
|
896
|
-
// return group
|
|
974
|
+
</menu-view>`, mount);
|
|
975
|
+
return mount.firstElementChild;
|
|
976
|
+
}
|
|
897
977
|
}
|
|
898
|
-
|
|
899
|
-
// static #reflectButtons(nodes: Dictionary, container: Element): void
|
|
900
|
-
static #reflectButtons(nodes, container) {
|
|
978
|
+
#reflectButtons(nodes, container) {
|
|
901
979
|
debug(`${_a.name} #reflectButtons`);
|
|
980
|
+
const flatten = 'radio-group' === this.pickerStyle;
|
|
902
981
|
for (const node of nodes)
|
|
903
982
|
if (node instanceof Element)
|
|
904
983
|
switch (node.tagName) {
|
|
905
984
|
case 'DATALIST': {
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
</label-view>
|
|
913
|
-
<h-stack distribution="fill" template="${icon ? 'auto spacer' : null}">
|
|
914
|
-
${icon ? html `<label-view system-image="${icon}"></label-view>` : null}
|
|
915
|
-
<v-stack spacing="3" alignment="fill">
|
|
916
|
-
<label-view title="${title}"></label-view>
|
|
917
|
-
${subtitle ? html `<label-view foreground="secondary" font="callout" title="${subtitle}"></label-view>` : null}
|
|
918
|
-
</v-stack>
|
|
919
|
-
</h-stack>
|
|
920
|
-
</h-stack>
|
|
921
|
-
</menu-view>`, mount);
|
|
922
|
-
const group = mount.firstElementChild;
|
|
923
|
-
// const group = $(
|
|
924
|
-
// `<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>`,
|
|
925
|
-
// '>1'
|
|
926
|
-
// ),
|
|
927
|
-
// hStack = group.querySelector(':scope>h-stack[slot=label]') ?? undefined
|
|
928
|
-
// // label = group.querySelector(':scope>label-view[slot=label]') ?? group.appendChild($(`<label-view slot="label"></label-view>`, '>1'))
|
|
929
|
-
// // if (node.hasAttribute('data-label')) label.setAttribute('title', node.getAttribute('data-label') ?? '')
|
|
930
|
-
// // if (node.hasAttribute('data-system-image')) label.setAttribute('system-image', node.getAttribute('data-system-image') ?? '')
|
|
931
|
-
// renderLabel(':scope>label-view:nth-child(2)', `<label-view><span></span></label-view>`, hStack, extractLabel(node as HTMLDataListElement), extractIcon(node as HTMLDataListElement))
|
|
932
|
-
_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);
|
|
933
991
|
container.appendChild(group);
|
|
934
992
|
break;
|
|
935
993
|
}
|
|
936
994
|
case 'OPTGROUP': {
|
|
937
|
-
|
|
938
|
-
|
|
995
|
+
if (flatten) {
|
|
996
|
+
this.#reflectButtons([...node.children], container);
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
const group = this.#wrapOptgroupTag(node);
|
|
1000
|
+
this.#reflectButtons([...node.children], group);
|
|
939
1001
|
container.appendChild(group);
|
|
940
1002
|
break;
|
|
941
1003
|
}
|
|
942
1004
|
case 'OPTION':
|
|
943
1005
|
default: {
|
|
944
|
-
container.appendChild(
|
|
1006
|
+
container.appendChild(this.#wrapOptionTag(node));
|
|
945
1007
|
break;
|
|
946
1008
|
}
|
|
947
1009
|
}
|
|
948
1010
|
else {
|
|
949
1011
|
if (node.children.length)
|
|
950
|
-
if (
|
|
951
|
-
|
|
952
|
-
|
|
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);
|
|
953
1017
|
container.appendChild(group);
|
|
954
1018
|
}
|
|
955
1019
|
else {
|
|
956
|
-
const
|
|
957
|
-
|
|
958
|
-
render(html `<menu-view tabindex="0">
|
|
959
|
-
<h-stack slot="label" distribution="leading" template="auto spacer">
|
|
960
|
-
<label-view data-role="check" style="visibility: hidden">
|
|
961
|
-
<image-view slot="icon" system-name="check"></image-view>
|
|
962
|
-
</label-view>
|
|
963
|
-
<h-stack distribution="fill" template="${icon ? 'auto spacer' : null}">
|
|
964
|
-
${icon ? html `<label-view system-image="${icon}"></label-view>` : null}
|
|
965
|
-
<v-stack spacing="3" alignment="fill">
|
|
966
|
-
<label-view title="${title}"></label-view>
|
|
967
|
-
${subtitle ? html `<label-view foreground="secondary" font="callout" title="${subtitle}"></label-view>` : null}
|
|
968
|
-
</v-stack>
|
|
969
|
-
</h-stack>
|
|
970
|
-
</h-stack>
|
|
971
|
-
</menu-view>`, mount);
|
|
972
|
-
const group = mount.firstElementChild;
|
|
973
|
-
// const group = $(`<menu-view tabindex="0"></menu-view>`, '>1')
|
|
974
|
-
// renderLabel(':scope>label-view[slot=label]', `<label-view slot="label"><span></span></label-view>`, group, extractLabel(node), extractIcon(node))
|
|
975
|
-
_a.#reflectButtons(node.children, group);
|
|
1020
|
+
const group = this.#wrapDatalistTag(node);
|
|
1021
|
+
this.#reflectButtons(node.children, group);
|
|
976
1022
|
container.appendChild(group);
|
|
977
1023
|
}
|
|
978
1024
|
else
|
|
979
|
-
container.appendChild(
|
|
1025
|
+
container.appendChild(this.#wrapOptionTag(node));
|
|
980
1026
|
}
|
|
981
1027
|
}
|
|
982
1028
|
// #reflectPlaceholder(value: string | null) {
|
|
983
1029
|
// debug(`#reflectPlaceholder`)
|
|
984
1030
|
// const input = this.#shadowRoot.querySelector('input')
|
|
985
1031
|
// if (input) {
|
|
986
|
-
// if (value) input.setAttribute(
|
|
987
|
-
// else input.removeAttribute(
|
|
1032
|
+
// if (value) input.setAttribute('prompt', value)
|
|
1033
|
+
// else input.removeAttribute('prompt')
|
|
988
1034
|
// }
|
|
989
1035
|
// }
|
|
990
1036
|
#reflectLabel(value) {
|
|
@@ -999,11 +1045,11 @@ export class PickerView extends FormAssociatedBase {
|
|
|
999
1045
|
const groupMap = indexGroups(this.#lastIndexedRoot);
|
|
1000
1046
|
const groupContainsSelection = (source) => source instanceof Element ? [...source.querySelectorAll('option')].some((opt) => extractTag(opt) === this.#selection) : collectLeafValues(source).includes(this.#selection);
|
|
1001
1047
|
const syncButtons = (root) => {
|
|
1002
|
-
// 1. plain value buttons
|
|
1048
|
+
// 1. plain value buttons
|
|
1003
1049
|
for (const el of root.querySelectorAll('button[value]:not([slot])'))
|
|
1004
1050
|
// $.prop('visibility', el.getAttribute('value') === this.#selection ? 'visible' : 'hidden', el.querySelector<HTMLElement>('label-view[data-role="check"]'))
|
|
1005
1051
|
el.querySelector('label-view[data-role="check"]')?.style.setProperty('visibility', el.getAttribute('value') === this.#selection ? 'visible' : 'hidden');
|
|
1006
|
-
// 2. details/optgroups
|
|
1052
|
+
// 2. details/optgroups
|
|
1007
1053
|
for (const details of root.querySelectorAll('details[is="disclosure-group"]')) {
|
|
1008
1054
|
const hasSelectedDescendant = [...details.querySelectorAll('button[value]')].some((btn) => btn.getAttribute('value') === this.#selection);
|
|
1009
1055
|
details.querySelector(':scope>summary label-view[data-role="check"]')?.style.setProperty('visibility', hasSelectedDescendant ? 'visible' : 'hidden');
|
|
@@ -1014,6 +1060,9 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1014
1060
|
const hasSelectedDescendant = source ? groupContainsSelection(source) : false;
|
|
1015
1061
|
btn.querySelector('label-view[data-role="check"]')?.style.setProperty('visibility', hasSelectedDescendant ? 'visible' : 'hidden');
|
|
1016
1062
|
}
|
|
1063
|
+
// 4. radio inputs
|
|
1064
|
+
for (const el of root.querySelectorAll('input[type=radio][value]'))
|
|
1065
|
+
el.checked = el.getAttribute('value') === this.#selection;
|
|
1017
1066
|
};
|
|
1018
1067
|
syncButtons(this);
|
|
1019
1068
|
if (this.#spawn)
|
|
@@ -1034,7 +1083,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1034
1083
|
break;
|
|
1035
1084
|
// if (!cvl) currentValueLabel.setAttribute('foreground', 'secondary')
|
|
1036
1085
|
// else currentValueLabel.removeAttribute('foreground')
|
|
1037
|
-
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');
|
|
1038
1087
|
queryMorph(':not([slot])', html `<span>${title}</span>`, currentValueLabel, { removeIf: !title });
|
|
1039
1088
|
queryMorph('[slot=icon]', html `<image-view slot="icon" system-name="${systemImage}"></image-view>`, currentValueLabel, { removeIf: !systemImage });
|
|
1040
1089
|
// morph(
|
|
@@ -1049,7 +1098,7 @@ export class PickerView extends FormAssociatedBase {
|
|
|
1049
1098
|
break;
|
|
1050
1099
|
// if (!cvl) currentValueLabel.setAttribute('foreground', 'secondary')
|
|
1051
1100
|
// else currentValueLabel.removeAttribute('foreground')
|
|
1052
|
-
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');
|
|
1053
1102
|
queryMorph(':not([slot])', html `<span>${title}</span>`, currentValueLabel, { removeIf: !title });
|
|
1054
1103
|
queryMorph('[slot=icon]', html `<image-view slot="icon" system-name="${systemImage}"></image-view>`, currentValueLabel, { removeIf: !systemImage });
|
|
1055
1104
|
// morph(
|
|
@@ -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
|