@swiftwc/ui 0.0.0-dev.20 → 0.0.0-dev.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/generated/buses/alert-dialog.d.ts +2 -0
  2. package/generated/buses/alert-dialog.js +1 -0
  3. package/generated/buses/confirmation-dialog.d.ts +2 -0
  4. package/generated/buses/confirmation-dialog.js +1 -0
  5. package/generated/buses/index.d.ts +6 -0
  6. package/generated/buses/index.js +6 -0
  7. package/generated/buses/lifecycle-observer.d.ts +2 -0
  8. package/generated/buses/lifecycle-observer.js +1 -0
  9. package/generated/client/index.d.ts +17 -4
  10. package/generated/client/index.js +83 -32
  11. package/generated/components/alert-dialog.d.ts +8 -0
  12. package/generated/components/alert-dialog.js +94 -0
  13. package/generated/components/bordered-button.d.ts +6 -0
  14. package/generated/components/bordered-button.js +22 -1
  15. package/generated/components/bordered-prominent-button.d.ts +6 -0
  16. package/generated/components/bordered-prominent-button.js +22 -1
  17. package/generated/components/borderless-button.d.ts +5 -1
  18. package/generated/components/borderless-button.js +13 -7
  19. package/generated/components/confirmation-dialog.d.ts +1 -1
  20. package/generated/components/confirmation-dialog.js +26 -20
  21. package/generated/components/content-unavailable-view.js +2 -2
  22. package/generated/components/date-picker.js +24 -10
  23. package/generated/components/disclosure-group.js +4 -1
  24. package/generated/components/glass-button.d.ts +6 -0
  25. package/generated/components/glass-button.js +22 -1
  26. package/generated/components/glass-prominent-button.d.ts +6 -0
  27. package/generated/components/glass-prominent-button.js +22 -1
  28. package/generated/components/index.d.ts +1 -0
  29. package/generated/components/index.js +1 -0
  30. package/generated/components/label-view.js +3 -35
  31. package/generated/components/menu-view.js +12 -7
  32. package/generated/components/navigation-title.js +4 -4
  33. package/generated/components/picker-view.js +35 -25
  34. package/generated/components/scroll-view.js +27 -13
  35. package/generated/components/section-view.js +3 -3
  36. package/generated/components/sheet-view.d.ts +1 -2
  37. package/generated/components/sheet-view.js +38 -22
  38. package/generated/components/sidebar-toggle.js +6 -4
  39. package/generated/components/sidebar-view.js +10 -4
  40. package/generated/components/sticky-container.js +3 -1
  41. package/generated/components/tab-bar.js +10 -4
  42. package/generated/components/tab-item.js +3 -1
  43. package/generated/components/tab-view.js +11 -8
  44. package/generated/components/table-view.js +22 -10
  45. package/generated/components/text-field.js +37 -32
  46. package/generated/components/tool-bar-item-group.js +17 -0
  47. package/generated/components/tool-bar-item.js +20 -1
  48. package/generated/components/tool-bar.d.ts +12 -0
  49. package/generated/components/tool-bar.js +20 -7
  50. package/generated/components/v-stack.d.ts +5 -0
  51. package/generated/components/v-stack.js +5 -0
  52. package/generated/css/index.css +377 -86
  53. package/generated/events/alert-dialog.d.ts +8 -0
  54. package/generated/events/alert-dialog.js +1 -0
  55. package/generated/events/confirmation-dialog.d.ts +2 -2
  56. package/generated/events/index.d.ts +1 -0
  57. package/generated/events/index.js +1 -0
  58. package/generated/events/tab-view.d.ts +6 -2
  59. package/generated/i18n/locales/el.d.ts +9 -0
  60. package/generated/i18n/locales/el.js +9 -0
  61. package/generated/i18n/locales/en.d.ts +9 -0
  62. package/generated/i18n/locales/en.js +9 -0
  63. package/generated/internal/class/css-style-observer.js +1 -1
  64. package/generated/internal/class/form-associated-base.js +4 -1
  65. package/generated/internal/class/navigation-view.js +4 -4
  66. package/generated/internal/utils/button-role.d.ts +1 -0
  67. package/generated/internal/utils/button-role.js +39 -0
  68. package/generated/internal/utils/cash/index.d.ts +4 -3
  69. package/generated/internal/utils/cash/index.js +6 -4
  70. package/generated/internal/utils/index.d.ts +2 -0
  71. package/generated/internal/utils/index.js +2 -0
  72. package/generated/internal/utils/is-inside.d.ts +1 -0
  73. package/generated/internal/utils/is-inside.js +4 -0
  74. package/generated/internal/utils/list-active.js +15 -5
  75. package/generated/snapshot/index.d.ts +2 -0
  76. package/generated/snapshot/index.js +21 -0
  77. package/package.json +7 -4
  78. package/scss/_components.scss +2 -0
  79. package/scss/_functions.scss +10 -0
  80. package/scss/_transitions.scss +1 -0
  81. package/scss/_vars.scss +5 -0
  82. package/scss/base/_reboot.scss +10 -0
  83. package/scss/colors/_index.scss +39 -21
  84. package/scss/components/_alert-dialog.scss +106 -0
  85. package/scss/components/_bordered-button.scss +14 -0
  86. package/scss/components/_bordered-prominent-button.scss +13 -0
  87. package/scss/components/_borderless-button.scss +4 -0
  88. package/scss/components/_confirmation-dialog.scss +39 -39
  89. package/scss/components/_content-unavailable-view.scss +1 -1
  90. package/scss/components/_disclosure-group.scss +80 -33
  91. package/scss/components/_glass-button.scss +14 -0
  92. package/scss/components/_glass-prominent-button.scss +14 -0
  93. package/scss/components/_h-stack.scss +3 -13
  94. package/scss/components/_index.scss +1 -0
  95. package/scss/components/_label-view.scss +42 -16
  96. package/scss/components/_label-view.scss.txt +536 -0
  97. package/scss/components/_sheet-view.scss +13 -3
  98. package/scss/components/_tab-bar.scss +5 -0
  99. package/scss/components/_tool-bar-item.scss +19 -0
  100. package/scss/components/_tool-bar.scss +25 -0
  101. package/scss/components/_v-stack.scss +3 -13
  102. package/scss/final/_touch-glass.scss +7 -0
  103. package/scss/mixins/_index.scss +17 -0
  104. package/scss/placeholders/_buttons.scss +87 -10
  105. package/scss/transitions/_alert-dialog.scss +19 -0
  106. package/scss/transitions/_tab-bar.scss +6 -5
  107. package/scss/utils/_frame.scss +7 -0
  108. package/web-components.html-data/en.json +81 -13
  109. package/generated/confirmation-dialog/index.d.ts +0 -1
  110. package/generated/confirmation-dialog/index.js +0 -1
  111. package/generated/lifecycle-observer/index.d.ts +0 -1
  112. package/generated/lifecycle-observer/index.js +0 -1
  113. package/scss/components/_components.scss +0 -76
@@ -26,7 +26,8 @@ export class DatePicker extends FormAssociatedBase {
26
26
  // #lastRenderedStyle?: DatePickerStyle //string | null
27
27
  #shadowRoot;
28
28
  #customValidity = '';
29
- #validitiesSlot;
29
+ #slots = new Map();
30
+ // #validitiesSlot?: HTMLSlotElement
30
31
  #inputs = [];
31
32
  get #internals() {
32
33
  return getInternals(this);
@@ -48,7 +49,7 @@ export class DatePicker extends FormAssociatedBase {
48
49
  <input type="text" name="year" inputmode="numeric" pattern="\d*" minlength="4" maxlength="4" min="0" max="9999" part="root input date-picker-form-input">
49
50
  </div>
50
51
  <slot name="validity-options" hidden></slot>
51
- </label>`, ''));
52
+ </label>`));
52
53
  break;
53
54
  }
54
55
  return _a.#templates.get(this.datePickerStyle);
@@ -99,7 +100,7 @@ export class DatePicker extends FormAssociatedBase {
99
100
  case 'label':
100
101
  let label = this.querySelector(':scope>[slot=label]');
101
102
  if (newValue) {
102
- label ??= this.appendChild($(`<span slot="label"></span>`));
103
+ label ??= this.appendChild($(`<span slot="label"></span>`, '>1'));
103
104
  label.textContent = newValue;
104
105
  }
105
106
  else
@@ -123,9 +124,14 @@ export class DatePicker extends FormAssociatedBase {
123
124
  // this.#lastRenderedStyle = this.datePickerStyle
124
125
  // clear shadow DOM
125
126
  this.#shadowRoot.replaceChildren(document.importNode(this.template, true));
126
- this.#validitiesSlot = this.#shadowRoot.querySelector('slot[name=validity-options]') ?? undefined;
127
+ CleanupRegistry.unregister(this, 'slots');
128
+ for (const slot of this.#shadowRoot.querySelectorAll('slot'))
129
+ this.#slots?.set(slot.name, slot);
130
+ CleanupRegistry.register(this, () => {
131
+ this.#slots = new Map();
132
+ }, 'slots');
127
133
  CleanupRegistry.unregister(this, 'validities');
128
- CleanupRegistry.register(this, onoff(makeSlotchangeHandler(this), this.#validitiesSlot).on(), 'validities');
134
+ CleanupRegistry.register(this, onoff(makeSlotchangeHandler(this), this.#slots?.get('validity-options')).on(), 'validities');
129
135
  switch (this.datePickerStyle) {
130
136
  default:
131
137
  const [yyyy = '', mm = '', dd = ''] = new Date().toISOString().split('T').shift()?.split('-') ?? [], map = { year: yyyy, month: mm, day: dd };
@@ -177,7 +183,10 @@ export class DatePicker extends FormAssociatedBase {
177
183
  }
178
184
  #handleClick = (evt) => {
179
185
  console.debug(`${_a.name} ⚡️ ${evt?.type}`);
180
- const input = evt.target?.closest('input');
186
+ const target = evt.target instanceof HTMLElement && evt.target;
187
+ if (!target)
188
+ return;
189
+ const input = target.closest('input');
181
190
  if (input)
182
191
  return;
183
192
  this.#shadowRoot.querySelector('input.focus')?.focus?.();
@@ -217,7 +226,7 @@ export class DatePicker extends FormAssociatedBase {
217
226
  };
218
227
  #handleInputPaste = (evt) => {
219
228
  console.debug(`${_a.name} ⚡️ ${evt?.type}`);
220
- const input = evt.target;
229
+ const input = evt.target instanceof HTMLInputElement && evt.target;
221
230
  if (!input)
222
231
  return;
223
232
  evt.preventDefault();
@@ -239,7 +248,7 @@ export class DatePicker extends FormAssociatedBase {
239
248
  };
240
249
  #handleInputBeforeinput = (evt) => {
241
250
  console.debug(`${_a.name} ⚡️ ${evt?.type}`);
242
- const input = evt.target;
251
+ const input = evt.target instanceof HTMLInputElement && evt.target;
243
252
  if (!input)
244
253
  return;
245
254
  if ('insertText' !== evt.inputType)
@@ -262,6 +271,8 @@ export class DatePicker extends FormAssociatedBase {
262
271
  };
263
272
  #handleInputKeydown = ({ type, target, key }) => {
264
273
  console.debug(`${_a.name} ⚡️ ${type}`);
274
+ if (!(target instanceof HTMLInputElement && target))
275
+ return;
265
276
  const input = target;
266
277
  if (!input)
267
278
  return;
@@ -284,7 +295,10 @@ export class DatePicker extends FormAssociatedBase {
284
295
  };
285
296
  #handleInputBlur = (evt) => {
286
297
  console.debug(`${_a.name} ⚡️ ${evt?.type}`);
287
- const input = evt.target;
298
+ const target = evt.target instanceof HTMLInputElement && evt.target;
299
+ if (!target)
300
+ return;
301
+ const input = target;
288
302
  if (0 === input.value.length)
289
303
  return;
290
304
  const finalText = `${clamp(this.value[input.name] ?? '0', _a.#min(input), _a.#max(input))}`.padStart(parseInt(input.getAttribute('maxlength') ?? '0'), '0');
@@ -377,7 +391,7 @@ export class DatePicker extends FormAssociatedBase {
377
391
  const key = k; // ✅ type-safe cast
378
392
  if (true !== flags[key])
379
393
  continue;
380
- for (const el of this.#validitiesSlot?.assignedElements({ flatten: true }) ?? []) {
394
+ for (const el of this.#slots?.get('validity-options')?.assignedElements({ flatten: true }) ?? []) {
381
395
  if (!el.matches('option'))
382
396
  continue;
383
397
  const option = el;
@@ -35,7 +35,10 @@ export class DisclosureGroup extends DetailsBase {
35
35
  }
36
36
  static #handleToggle = async (evt) => {
37
37
  console.debug(`${DisclosureGroup.name} ⚡️ ${evt?.type}`);
38
- const details = evt.currentTarget, newValue = details.open ? 'opening' : 'closing';
38
+ const details = evt.currentTarget instanceof HTMLDetailsElement && evt.currentTarget;
39
+ if (!details)
40
+ return;
41
+ const newValue = details.open ? 'opening' : 'closing';
39
42
  if (newValue !== details.dataset.state)
40
43
  details.dataset.state = newValue;
41
44
  if (!toggleTimers.has(details))
@@ -1,6 +1,12 @@
1
1
  import { ButtonBase } from '../namespace-browser/base';
2
+ /**
3
+ * @slot overlay
4
+ *
5
+ */
2
6
  export declare class GlassButton extends ButtonBase {
7
+ static get observedAttributes(): string[];
3
8
  constructor();
4
9
  static polyfillDisconnectedCallback(el: ButtonBase): void;
5
10
  static polyfillConnectedCallback(el: ButtonBase): void;
11
+ static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]: Pick<MutationRecord, 'attributeName' | 'oldValue' | 'target'>[]): void;
6
12
  }
@@ -1,7 +1,15 @@
1
1
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
2
- import { onoff, touchGlass } from '../internal/utils';
2
+ import { buttonRole, onoff, touchGlass } from '../internal/utils';
3
3
  import { ButtonBase } from '../namespace-browser/base';
4
+ import { Snapshot } from '../snapshot';
5
+ /**
6
+ * @slot overlay
7
+ *
8
+ */
4
9
  export class GlassButton extends ButtonBase {
10
+ static get observedAttributes() {
11
+ return ['role'];
12
+ }
5
13
  constructor() {
6
14
  super();
7
15
  }
@@ -14,4 +22,17 @@ export class GlassButton extends ButtonBase {
14
22
  CleanupRegistry.register(el, onoff(touchGlass(el, (t) => t, () => true), el).on());
15
23
  el.tabIndex = 0;
16
24
  }
25
+ static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]) {
26
+ console.debug(`${GlassButton.name} ⚡️ attr-change [${attributeName}] ("${oldValue}" → "${target.getAttribute(attributeName ?? '')}")`);
27
+ const node = target instanceof HTMLButtonElement && target;
28
+ if (!node)
29
+ return;
30
+ switch (attributeName) {
31
+ case 'role':
32
+ Snapshot.waitReady.then(() => {
33
+ buttonRole(target, attributeName);
34
+ });
35
+ break;
36
+ }
37
+ }
17
38
  }
@@ -1,6 +1,12 @@
1
1
  import { ButtonBase } from '../namespace-browser/base';
2
+ /**
3
+ * @slot overlay
4
+ *
5
+ */
2
6
  export declare class GlassProminentButton extends ButtonBase {
7
+ static get observedAttributes(): string[];
3
8
  constructor();
4
9
  static polyfillDisconnectedCallback(el: ButtonBase): void;
5
10
  static polyfillConnectedCallback(el: ButtonBase): void;
11
+ static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]: Pick<MutationRecord, 'attributeName' | 'oldValue' | 'target'>[]): void;
6
12
  }
@@ -1,7 +1,15 @@
1
1
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
2
- import { onoff, touchGlass } from '../internal/utils';
2
+ import { buttonRole, onoff, touchGlass } from '../internal/utils';
3
3
  import { ButtonBase } from '../namespace-browser/base';
4
+ import { Snapshot } from '../snapshot';
5
+ /**
6
+ * @slot overlay
7
+ *
8
+ */
4
9
  export class GlassProminentButton extends ButtonBase {
10
+ static get observedAttributes() {
11
+ return ['role'];
12
+ }
5
13
  constructor() {
6
14
  super();
7
15
  }
@@ -14,4 +22,17 @@ export class GlassProminentButton extends ButtonBase {
14
22
  CleanupRegistry.register(el, onoff(touchGlass(el, (t) => t, () => true), el).on());
15
23
  el.tabIndex = 0;
16
24
  }
25
+ static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]) {
26
+ console.debug(`${GlassProminentButton.name} ⚡️ attr-change [${attributeName}] ("${oldValue}" → "${target.getAttribute(attributeName ?? '')}")`);
27
+ const node = target instanceof HTMLButtonElement && target;
28
+ if (!node)
29
+ return;
30
+ switch (attributeName) {
31
+ case 'role':
32
+ Snapshot.waitReady.then(() => {
33
+ buttonRole(target, attributeName);
34
+ });
35
+ break;
36
+ }
37
+ }
17
38
  }
@@ -1,3 +1,4 @@
1
+ export * from './alert-dialog';
1
2
  export * from './body-view';
2
3
  export * from './bordered-button';
3
4
  export * from './bordered-prominent-button';
@@ -1,3 +1,4 @@
1
+ export * from './alert-dialog';
1
2
  export * from './body-view';
2
3
  export * from './bordered-button';
3
4
  export * from './bordered-prominent-button';
@@ -11,73 +11,41 @@ export class LabelView extends HTMLElement {
11
11
  </div>
12
12
  <div part="root label-title-stack">
13
13
  <slot></slot>
14
- </div>`, ''));
14
+ </div>`));
15
15
  }
16
16
  #shadowRoot;
17
- // #imgSlot?: HTMLSlotElement
18
- // #slot?: HTMLSlotElement
19
17
  constructor() {
20
18
  super();
21
19
  this.#shadowRoot = this.attachShadow({ mode: 'closed' });
22
- // Snapshot.waitReady.then(() => {
23
20
  this.#shadowRoot.appendChild(document.importNode(this.constructor.template, true));
24
- // // this.#imgSlot = this.#shadowRoot.querySelector<HTMLSlotElement>('slot[name=image]') ?? undefined
25
- // // this.#slot = this.#shadowRoot.querySelector<HTMLSlotElement>('slot:not([name])') ?? undefined
26
- //
27
- // // this.#slot?.addEventListener('slotchange', this.#handleSlotchange)
28
- // // // this.#imgSlot?.addEventListener('slotchange', this.#handleSlotchange)
29
- // // // this.#handleSlotchange(new CustomEvent('slotchange'))
30
- // })
31
21
  }
32
22
  disconnectedCallback() {
33
23
  console.debug(`${LabelView.name} ⚡️ disconnect`);
34
- // this.#slot?.removeEventListener('slotchange', this.#handleSlotchange)
35
24
  }
36
25
  connectedCallback() {
37
26
  console.debug(`${LabelView.name} ⚡️ connect`);
38
27
  }
39
28
  attributeChangedCallback(name, oldValue, newValue) {
40
29
  console.debug(`${LabelView.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
41
- // Snapshot.waitReady.then(() => {
42
30
  switch (name) {
43
31
  case 'system-image':
44
32
  let image = this.querySelector(':scope>[slot=image]');
45
33
  if (newValue) {
46
- image ??= this.appendChild($(`<i slot="image"></i>`));
34
+ image ??= this.appendChild($(`<i slot="image" style="line-height: 1.05"></i>`, '>1'));
47
35
  image.setAttribute('class', `ph ph-${newValue}`);
48
36
  }
49
37
  else
50
38
  image?.remove();
51
- // // const imgSlot = this.#shadowRoot.querySelector<HTMLSlotElement>('slot[name=image]')
52
- // // if (!imgSlot) break
53
- // const assigned = this.#imgSlot!.assignedElements({ flatten: true }) as HTMLElement[]
54
- // let el = assigned[0] as HTMLElement | undefined
55
- // if (!el) {
56
- // el = document.createElement('i')
57
- // el.slot = 'image'
58
- // this.append(el)
59
- // }
60
- // el.setAttribute('class', `ph ph-${newValue}`)
61
39
  break;
62
40
  case 'title':
63
41
  let title = this.querySelector(':scope>:not([slot])');
64
42
  if (newValue) {
65
- title ??= this.appendChild($(`<span></span>`));
43
+ title ??= this.appendChild($(`<span></span>`, '>1'));
66
44
  title.textContent = newValue;
67
45
  }
68
46
  else
69
47
  title?.remove();
70
- // // const titleSlot = this.#shadowRoot.querySelector<HTMLSlotElement>('slot:not([name])')
71
- // // if (!titleSlot) break
72
- // const title = this.#slot!.assignedElements({ flatten: true }) as HTMLElement[]
73
- // let el2 = title[0] as HTMLElement | undefined
74
- // if (!el2) {
75
- // el2 = document.createElement('span')
76
- // this.append(el2)
77
- // }
78
- // el2.textContent = newValue //el2.replaceChildren(escapeHTMLPolicy.createHTML(newValue))
79
48
  break;
80
49
  }
81
- // })
82
50
  }
83
51
  }
@@ -17,7 +17,7 @@ export class MenuView extends HTMLElement {
17
17
  <slot></slot>
18
18
  </div>
19
19
  </form>
20
- </dialog>`, ''));
20
+ </dialog>`));
21
21
  }
22
22
  #shadowRoot;
23
23
  #dialog;
@@ -50,9 +50,12 @@ export class MenuView extends HTMLElement {
50
50
  { types: 'cancel', listener: this.#handleDialogCancel },
51
51
  ], this.#dialog).on());
52
52
  CleanupRegistry.register(this, onoff(touchGlass(this, (t) => t, (evt) => {
53
- if (evt.target.matches('menu-view'))
53
+ const target = evt.target instanceof HTMLElement && evt.target;
54
+ if (!target)
55
+ return true;
56
+ if (target.matches('menu-view'))
54
57
  return false;
55
- if (!evt.target.closest('menu-view[open]'))
58
+ if (!target.closest('menu-view[open]'))
56
59
  return false;
57
60
  return true;
58
61
  }), this).on());
@@ -89,7 +92,7 @@ export class MenuView extends HTMLElement {
89
92
  case 'label':
90
93
  let label = this.querySelector(':scope>[slot=label]');
91
94
  if (newValue) {
92
- label ??= this.appendChild($(`<label-view slot="label"></label-view>`));
95
+ label ??= this.appendChild($(`<label-view slot="label"></label-view>`, '>1'));
93
96
  label.setAttribute('title', newValue);
94
97
  }
95
98
  else
@@ -99,15 +102,17 @@ export class MenuView extends HTMLElement {
99
102
  }
100
103
  #handleDialogClick = (evt) => {
101
104
  console.debug(`${_a.name} ⚡️ ${evt?.type}`);
102
- if (evt.target.matches('dialog'))
105
+ const target = evt.target instanceof HTMLElement && evt.target;
106
+ if (!target)
107
+ return;
108
+ if (target.matches('dialog'))
103
109
  return this.toggleAttribute('open', false); // click outside
104
- const target = evt.target;
105
110
  target.scrollIntoView({
106
111
  behavior: self.matchMedia('(prefers-reduced-motion: no-preference)').matches ? 'smooth' : 'instant',
107
112
  block: 'nearest',
108
113
  inline: 'nearest',
109
114
  });
110
- if (!evt.target.closest('button'))
115
+ if (!target.closest('button'))
111
116
  return;
112
117
  // TODO: Handle btns this.toggleAttribute('open', false)
113
118
  this.toggleAttribute('open', false);
@@ -34,18 +34,18 @@ export class NavigationTitle extends HTMLElement {
34
34
  }
35
35
  #render = (title, subtitle) => {
36
36
  const el = this.querySelector(':scope>:not([slot])') ??
37
- this.appendChild($(`<navigation-large-title><v-stack spacing="0" alignment="fill" slot="top-bar-principal"><label-view line-limit="1" truncation-mode="tail" font="headline"></label-view><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></v-stack></navigation-large-title>`)), vStack = el.querySelector(':scope>v-stack') ??
38
- el.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal"><label-view line-limit="1" truncation-mode="tail" font="headline"></label-view><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></v-stack>`));
37
+ this.appendChild($(`<navigation-large-title><v-stack spacing="0" alignment="fill" slot="top-bar-principal"><label-view line-limit="1" truncation-mode="tail" font="headline"></label-view><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></v-stack></navigation-large-title>`, '>1')), vStack = el.querySelector(':scope>v-stack') ??
38
+ el.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal"><label-view line-limit="1" truncation-mode="tail" font="headline"></label-view><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></v-stack>`, '>1'));
39
39
  let titleLabel = vStack.querySelector(':scope>label-view:nth-child(1)');
40
40
  if (title) {
41
- titleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="headline"></label-view>`));
41
+ titleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="headline"></label-view>`, '>1'));
42
42
  titleLabel.setAttribute('title', title);
43
43
  }
44
44
  else
45
45
  titleLabel?.remove();
46
46
  let subtitleLabel = vStack.querySelector(':scope>label-view:nth-child(2)');
47
47
  if (subtitle) {
48
- subtitleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="callout"></label-view>`));
48
+ subtitleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="callout"></label-view>`, '>1'));
49
49
  subtitleLabel.setAttribute('title', subtitle);
50
50
  }
51
51
  else
@@ -21,9 +21,10 @@ export class PickerView extends FormAssociatedBase {
21
21
  #lastRenderedStyle; //string | null
22
22
  #shadowRoot;
23
23
  #customValidity = '';
24
- #validitiesSlot;
25
- #datalistSlot;
26
- #tagSlot;
24
+ #slots = new Map();
25
+ // #validitiesSlot?: HTMLSlotElement
26
+ // #datalistSlot?: HTMLSlotElement
27
+ // #tagSlot?: HTMLSlotElement
27
28
  #trackedElements = new Set();
28
29
  #selection = '';
29
30
  get #internals() {
@@ -54,7 +55,7 @@ export class PickerView extends FormAssociatedBase {
54
55
  <slot name="tag" hidden></slot>
55
56
  <slot name="validity-options" hidden></slot>
56
57
  </label>
57
- `, ''));
58
+ `));
58
59
  // break
59
60
  // case 'compact':
60
61
  // PickerView.#templates.set(
@@ -114,7 +115,7 @@ export class PickerView extends FormAssociatedBase {
114
115
  <slot name="options" hidden></slot>
115
116
  <slot name="tag" hidden></slot>
116
117
  <slot name="validity-options" hidden></slot>
117
- </label>`, ''));
118
+ </label>`));
118
119
  break;
119
120
  }
120
121
  return _a.#templates.get(this.pickerStyle);
@@ -176,21 +177,24 @@ export class PickerView extends FormAssociatedBase {
176
177
  this.#lastRenderedStyle = this.pickerStyle;
177
178
  // clear shadow DOM
178
179
  this.#shadowRoot.replaceChildren(document.importNode(this.template, true));
179
- this.#validitiesSlot = this.#shadowRoot.querySelector('slot[name=validity-options]') ?? undefined;
180
- this.#datalistSlot = this.#shadowRoot.querySelector('slot[name=options]') ?? undefined;
181
- this.#tagSlot = this.#shadowRoot.querySelector('slot[name=tag]') ?? undefined;
180
+ CleanupRegistry.unregister(this, 'slots');
181
+ for (const slot of this.#shadowRoot.querySelectorAll('slot'))
182
+ this.#slots?.set(slot.name, slot);
183
+ CleanupRegistry.register(this, () => {
184
+ this.#slots = new Map();
185
+ }, 'slots');
182
186
  CleanupRegistry.unregister(this, 'validities');
183
- CleanupRegistry.register(this, onoff(makeSlotchangeHandler(this), this.#validitiesSlot).on(), 'validities');
187
+ CleanupRegistry.register(this, onoff(makeSlotchangeHandler(this), this.#slots?.get('validity-options')).on(), 'validities');
184
188
  CleanupRegistry.unregister(this, 'datalist'); //off1()
185
- CleanupRegistry.register(this, onoff('slotchange', this.#handleSlotchange, this.#datalistSlot).on(), 'datalist');
189
+ CleanupRegistry.register(this, onoff('slotchange', this.#handleSlotchange, this.#slots?.get('options')).on(), 'datalist');
186
190
  CleanupRegistry.unregister(this, 'tags'); //off2()
187
- CleanupRegistry.register(this, onoff('slotchange', this.#handleSlotchange, this.#tagSlot).on(), 'tags');
188
- // if (0 < (this.#datalistSlot?.assignedElements({ flatten: true }) ?? []).length) this.#handleTagMutation()
189
- // if (0 < (this.#tagSlot?.assignedElements({ flatten: true }) ?? []).length) this.#handleTagMutation()
191
+ CleanupRegistry.register(this, onoff('slotchange', this.#handleSlotchange, this.#slots?.get('tag')).on(), 'tags');
192
+ // if (0 < (this.#slots?.get('options')?.assignedElements({ flatten: true }) ?? []).length) this.#handleTagMutation()
193
+ // if (0 < (this.#slots?.get('tag')?.assignedElements({ flatten: true }) ?? []).length) this.#handleTagMutation()
190
194
  //this.getAttribute((this.constructor as typeof PickerView).ATTR.PICKER_STYLE)) {
191
195
  switch (this.pickerStyle
192
196
  // case 'menu':
193
- // // if (0 < (this.#datalistSlot?.assignedElements({ flatten: true }) ?? []).length) this.#handleMenuDatalistMutation()
197
+ // // if (0 < (this.#slots?.get('options')?.assignedElements({ flatten: true }) ?? []).length) this.#handleMenuDatalistMutation()
194
198
  // break
195
199
  // case 'gg':
196
200
  // // reattach input listener
@@ -209,7 +213,7 @@ export class PickerView extends FormAssociatedBase {
209
213
  // break
210
214
  // case 'inline':
211
215
  // default:
212
- // // if (0 < (this.#datalistSlot?.assignedElements({ flatten: true }) ?? []).length) this.#handleInlineDatalistMutation()
216
+ // // if (0 < (this.#slots?.get('options')?.assignedElements({ flatten: true }) ?? []).length) this.#handleInlineDatalistMutation()
213
217
  // break
214
218
  ) {
215
219
  }
@@ -235,7 +239,10 @@ export class PickerView extends FormAssociatedBase {
235
239
  };
236
240
  #handleClick(evt) {
237
241
  console.debug(`${_a.name} ⚡️ ${evt?.type}`);
238
- const target = evt.target, btn = target?.closest('button');
242
+ const target = evt.target instanceof HTMLElement && evt.target;
243
+ if (!target)
244
+ return;
245
+ const btn = target?.closest('button');
239
246
  if (!btn)
240
247
  return;
241
248
  if (btn.hasAttribute('tag')) {
@@ -248,7 +255,10 @@ export class PickerView extends FormAssociatedBase {
248
255
  }
249
256
  #handleSlotchange = (evt) => {
250
257
  console.debug(`${_a.name} ⚡️ ${evt?.type}`);
251
- const slot = evt.target, assigned = slot.assignedElements({ flatten: true });
258
+ const slot = evt.target instanceof HTMLSlotElement && evt.target;
259
+ if (!slot)
260
+ return;
261
+ const assigned = slot.assignedElements({ flatten: true });
252
262
  observers.syncObservations(this.#trackedElements, assigned, this.#handleTagMutation);
253
263
  // for (const el of this.#trackedElements)
254
264
  // if (!assigned.includes(el)) {
@@ -270,7 +280,7 @@ export class PickerView extends FormAssociatedBase {
270
280
  this.#handleTagMutation();
271
281
  };
272
282
  static wrapTag(node, slotName) {
273
- const btn = $(`<button type="button" tabindex="0"></button>`); //document.createElement('button')
283
+ const btn = $(`<button type="button" tabindex="0"></button>`, '>1'); //document.createElement('button')
274
284
  // btn.type = 'button'
275
285
  // btn.tabIndex = 0
276
286
  switch (slotName) {
@@ -283,7 +293,7 @@ export class PickerView extends FormAssociatedBase {
283
293
  default:
284
294
  if (node.hasAttribute('value'))
285
295
  btn.setAttribute('tag', node.getAttribute('value') ?? '');
286
- const label = $(`<label-view></label-view>`); //document.createElement('label-view')
296
+ const label = $(`<label-view></label-view>`, '>1'); //document.createElement('label-view')
287
297
  if (node.hasAttribute('label'))
288
298
  label.setAttribute('title', node.getAttribute('label') ?? '');
289
299
  btn.appendChild(label);
@@ -293,11 +303,11 @@ export class PickerView extends FormAssociatedBase {
293
303
  }
294
304
  #handleTagMutation = (entry) => {
295
305
  console.debug(`${_a.name} ⚡️ mutation`);
296
- const sourceSlot = 0 < (this.#datalistSlot?.assignedElements({ flatten: true }) ?? []).length ? this.#datalistSlot : this.#tagSlot;
306
+ const sourceSlot = 0 < (this.#slots?.get('options')?.assignedElements({ flatten: true }) ?? []).length ? this.#slots?.get('options') : this.#slots?.get('tag');
297
307
  // switch (this.getAttribute((this.constructor as typeof PickerView).ATTR.PICKER_STYLE)) {
298
308
  switch (this.pickerStyle) {
299
309
  case 'menu':
300
- const menu = this.querySelector(':scope>menu-view:not([slot])') ?? this.appendChild($(`<menu-view tabindex="0"></menu-view>`));
310
+ const menu = this.querySelector(':scope>menu-view:not([slot])') ?? this.appendChild($(`<menu-view tabindex="0"></menu-view>`, '>1'));
301
311
  menu.innerHTML = `<label-view slot="label" system-image="dots-three" title="rtyty"></label-view>`;
302
312
  for (const el of sourceSlot?.assignedElements({ flatten: true }) ?? [])
303
313
  menu.insertAdjacentElement('beforeend', _a.wrapTag(el, sourceSlot?.name));
@@ -308,11 +318,11 @@ export class PickerView extends FormAssociatedBase {
308
318
  break;
309
319
  case 'inline':
310
320
  default:
311
- const inlineList = this.querySelector(':scope>list-view:not([slot])') ?? this.appendChild($(`<list-view><section-view></section-view></list-view>`)), section = inlineList.querySelector(':scope>section-view') ?? inlineList.appendChild($(`<section-view></section-view>`));
321
+ const inlineList = this.querySelector(':scope>list-view:not([slot])') ?? this.appendChild($(`<list-view><section-view></section-view></list-view>`, '>1')), section = inlineList.querySelector(':scope>section-view') ?? inlineList.appendChild($(`<section-view></section-view>`, '>1'));
312
322
  const label = this.getAttribute(this.constructor.ATTR.LABEL);
313
323
  // if (label) section.setAttribute('header', label)
314
324
  if (label) {
315
- const el = $(`<label-view></label-view>`);
325
+ const el = $(`<label-view></label-view>`, '>1');
316
326
  el.setAttribute('title', label);
317
327
  section.insertAdjacentElement('beforeend', el);
318
328
  }
@@ -360,7 +370,7 @@ export class PickerView extends FormAssociatedBase {
360
370
  // default:
361
371
  let label = this.querySelector(':scope>[slot=label]');
362
372
  if (value) {
363
- label ??= this.appendChild($(`<span slot="label"></span>`));
373
+ label ??= this.appendChild($(`<span slot="label"></span>`, '>1'));
364
374
  label.textContent = value;
365
375
  }
366
376
  else
@@ -396,7 +406,7 @@ export class PickerView extends FormAssociatedBase {
396
406
  const key = k; // ✅ type-safe cast
397
407
  if (true !== flags[key])
398
408
  continue;
399
- for (const el of this.#validitiesSlot?.assignedElements({ flatten: true }) ?? []) {
409
+ for (const el of this.#slots?.get('validity-options')?.assignedElements({ flatten: true }) ?? []) {
400
410
  if (!el.matches('option'))
401
411
  continue;
402
412
  const option = el;