@swiftwc/ui 0.0.0-dev.86 → 0.0.0-dev.87

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 (41) hide show
  1. package/generated/components/bordered-button.js +1 -1
  2. package/generated/components/bordered-prominent-button.js +1 -1
  3. package/generated/components/borderless-button.js +1 -1
  4. package/generated/components/date-picker.js +4 -3
  5. package/generated/components/glass-button.js +1 -1
  6. package/generated/components/glass-prominent-button.js +1 -1
  7. package/generated/components/image-view.js +10 -11
  8. package/generated/components/label-view.js +13 -10
  9. package/generated/components/labeled-content.js +43 -23
  10. package/generated/components/menu-view.js +3 -2
  11. package/generated/components/navigation-title.js +22 -16
  12. package/generated/components/picker-view.js +13 -8
  13. package/generated/components/progress-view.js +4 -3
  14. package/generated/components/scroll-view.js +26 -7
  15. package/generated/components/section-view.js +33 -17
  16. package/generated/components/table-view.js +5 -6
  17. package/generated/components/text-field.js +3 -2
  18. package/generated/components/toggle-view.js +3 -2
  19. package/generated/components/tool-bar-item.js +2 -2
  20. package/generated/internal/utils/ensure-placeholder.d.ts +1 -1
  21. package/generated/internal/utils/ensure-placeholder.js +8 -9
  22. package/generated/internal/utils/index.d.ts +0 -3
  23. package/generated/internal/utils/index.js +0 -3
  24. package/generated/internal/vendor/morphdom.d.ts +6 -0
  25. package/generated/internal/vendor/morphdom.js +720 -0
  26. package/generated/morphdom/html.d.ts +8 -0
  27. package/generated/morphdom/html.js +37 -0
  28. package/generated/morphdom/index.d.ts +6 -0
  29. package/generated/morphdom/index.js +6 -0
  30. package/generated/morphdom/morph.d.ts +4 -0
  31. package/generated/morphdom/morph.js +9 -0
  32. package/generated/morphdom/query-morph.d.ts +5 -0
  33. package/generated/morphdom/query-morph.js +12 -0
  34. package/package.json +4 -3
  35. package/web-components.html-data/en.json +3 -0
  36. package/generated/internal/utils/render-label-icon.d.ts +0 -2
  37. package/generated/internal/utils/render-label-icon.js +0 -19
  38. package/generated/internal/utils/render-label-title.d.ts +0 -2
  39. package/generated/internal/utils/render-label-title.js +0 -16
  40. package/generated/internal/utils/render-label.d.ts +0 -1
  41. package/generated/internal/utils/render-label.js +0 -19
@@ -45,7 +45,7 @@ export class BorderedButton extends ButtonBase {
45
45
  case 'title-key':
46
46
  case 'role':
47
47
  Snapshot.waitReady.then(() => {
48
- ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'));
48
+ ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'), Snapshot.config);
49
49
  });
50
50
  break;
51
51
  }
@@ -45,7 +45,7 @@ export class BorderedProminentButton extends ButtonBase {
45
45
  case 'title-key':
46
46
  case 'role':
47
47
  Snapshot.waitReady.then(() => {
48
- ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'));
48
+ ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'), Snapshot.config);
49
49
  });
50
50
  break;
51
51
  }
@@ -45,7 +45,7 @@ export class BorderlessButton extends ButtonBase {
45
45
  case 'title-key':
46
46
  case 'role':
47
47
  Snapshot.waitReady.then(() => {
48
- ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'));
48
+ ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'), Snapshot.config);
49
49
  });
50
50
  break;
51
51
  }
@@ -3,7 +3,8 @@ import { I18n } from '../i18n';
3
3
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
4
4
  import { FormAssociatedBase, getInternals } from '../internal/class/form-associated-base';
5
5
  import { MutationObserverSet } from '../internal/class/mutation-observer-set';
6
- import { $, clamp, devFlags, kebabCase, onoff, renderLabel, set } from '../internal/utils';
6
+ import { $, clamp, devFlags, kebabCase, onoff, set } from '../internal/utils';
7
+ import { html, queryMorph } from '../morphdom';
7
8
  const datePickerStyles = ['graphical', 'field', 'automatic'];
8
9
  export class DatePicker extends FormAssociatedBase {
9
10
  static get observedAttributes() {
@@ -89,7 +90,7 @@ export class DatePicker extends FormAssociatedBase {
89
90
  input.setAttribute('placeholder', map[input.name] ?? '');
90
91
  break;
91
92
  case 'label':
92
- renderLabel(':scope>label-view[slot=label]', `<label-view slot="label" foreground="secondary"><span></span></label-view>`, this, newValue);
93
+ queryMorph('[slot=label]', html `<label-view slot="label" foreground="secondary">${newValue ? html `<span>${newValue}</span>` : null}</label-view>`, this); //renderLabel(':scope>label-view[slot=label]', `<label-view slot="label" foreground="secondary"><span></span></label-view>`, this, newValue)
93
94
  // this.#sendValueToForm()
94
95
  break;
95
96
  case 'disabled':
@@ -121,7 +122,7 @@ export class DatePicker extends FormAssociatedBase {
121
122
  }
122
123
  #render() {
123
124
  if (devFlags.debug)
124
- console.debug(`${_a.name} ⚡️ render (${this.datePickerStyle})`);
125
+ console.debug(`${_a.name} ⚡️ #render (${this.datePickerStyle})`);
125
126
  // if (this.#lastRenderedStyle === this.datePickerStyle) return // skip if already applied
126
127
  // this.#lastRenderedStyle = this.datePickerStyle
127
128
  // clear shadow DOM
@@ -45,7 +45,7 @@ export class GlassButton extends ButtonBase {
45
45
  case 'title-key':
46
46
  case 'role':
47
47
  Snapshot.waitReady.then(() => {
48
- ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'));
48
+ ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'), Snapshot.config);
49
49
  });
50
50
  break;
51
51
  }
@@ -45,7 +45,7 @@ export class GlassProminentButton extends ButtonBase {
45
45
  case 'title-key':
46
46
  case 'role':
47
47
  Snapshot.waitReady.then(() => {
48
- ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'));
48
+ ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'), Snapshot.config);
49
49
  });
50
50
  break;
51
51
  }
@@ -1,4 +1,5 @@
1
1
  import { $, devFlags } from '../internal/utils';
2
+ import { html, queryMorph } from '../morphdom';
2
3
  export class ImageView extends HTMLElement {
3
4
  static get observedAttributes() {
4
5
  return ['system-name', 'system-weight'];
@@ -40,18 +41,16 @@ export class ImageView extends HTMLElement {
40
41
  }
41
42
  }
42
43
  #render(icon, weight) {
43
- if (!icon) {
44
- this.querySelector(':scope>:not([slot])')?.remove();
45
- return;
46
- }
44
+ // if (!icon) {
45
+ // this.querySelector(':scope>:not([slot])')?.remove()
46
+ // return
47
+ // }
47
48
  const tokens = [`ph${weight ? `-${weight}` : ''}`, `ph-${icon}`];
48
- const container = this.querySelector(':scope>:not([slot])') ?? this.appendChild($(`<i style="line-height: 1"></i>`, '>1'));
49
- if ('1' !== container.style.getPropertyValue('line-height'))
50
- container.style.setProperty('line-height', '1');
51
- for (const token of container.classList)
52
- if (token.startsWith('ph') && !tokens.includes(token))
53
- container.classList.remove(token);
54
- container.classList.add(...tokens);
49
+ // const container = this.querySelector<HTMLElement>(':scope>:not([slot])') ?? this.appendChild<HTMLElement>($(`<i style="line-height: 1"></i>`, '>1'))
50
+ queryMorph(':not([slot])', html `<i style="line-height: 1" class="${tokens.join(' ')}"></i>`, this, { removeIf: !icon });
51
+ // if ('1' !== container.style.getPropertyValue('line-height')) container.style.setProperty('line-height', '1')
52
+ // for (const token of container.classList) if (token.startsWith('ph') && !tokens.includes(token)) container.classList.remove(token)
53
+ // container.classList.add(...tokens)
55
54
  }
56
55
  disconnectedCallback() {
57
56
  if (devFlags.debug)
@@ -1,5 +1,5 @@
1
1
  import { $, devFlags } from '../internal/utils';
2
- import { html, render } from '../tpl';
2
+ import { html, queryMorph } from '../morphdom';
3
3
  /**
4
4
  *
5
5
  * @attr {@fontSet} font - Sets the default font for text in this view.
@@ -40,18 +40,21 @@ export class LabelView extends HTMLElement {
40
40
  return;
41
41
  // this.#scheduleReflect()
42
42
  switch (name) {
43
- case 'system-image':
44
- case 'title':
45
- render(html `${this.getAttribute('title') ? html `<span>${this.getAttribute('title')}</span>` : null}${this.getAttribute('system-image')
46
- ? html `<image-view slot="icon" system-name="${this.getAttribute('system-image')}"></image-view>`
47
- : null}`, this);
48
- break;
49
43
  // case 'system-image':
50
- // renderLabelIcon(this, newValue)
51
- // break
52
44
  // case 'title':
53
- // renderLabelTitle(this, newValue)
45
+ // render(
46
+ // html`${this.getAttribute('title') ? html`<span>${this.getAttribute('title')}</span>` : null}${this.getAttribute('system-image')
47
+ // ? html`<image-view slot="icon" system-name="${this.getAttribute('system-image')}"></image-view>`
48
+ // : null}`,
49
+ // this
50
+ // )
54
51
  // break
52
+ case 'system-image':
53
+ queryMorph('[slot=icon]', html `<image-view slot="icon" system-name="${newValue}"></image-view>`, this, { removeIf: !newValue }); //renderLabelIcon(this, newValue)
54
+ break;
55
+ case 'title':
56
+ queryMorph(':not([slot])', html `<span>${newValue}</span>`, this, { removeIf: !newValue }); //renderLabelTitle(this, newValue)
57
+ break;
55
58
  }
56
59
  }
57
60
  disconnectedCallback() {
@@ -1,5 +1,5 @@
1
- import { $, devFlags, renderLabel } from '../internal/utils';
2
- import { html, render } from '../tpl';
1
+ import { $, devFlags } from '../internal/utils';
2
+ import { html, queryMorph } from '../morphdom';
3
3
  export class LabeledContent extends HTMLElement {
4
4
  static get observedAttributes() {
5
5
  return ['value', 'label', 'header', 'footer', 'labeled-content-style', 'format'];
@@ -34,33 +34,53 @@ export class LabeledContent extends HTMLElement {
34
34
  return;
35
35
  switch (name) {
36
36
  case 'header':
37
- if (!newValue) {
38
- this.querySelector(':scope>[slot=header]')?.remove();
39
- break;
40
- }
41
- const header = this.querySelector(':scope>[slot=header]') ?? this.appendChild(Object.assign(document.createElement('header'), { slot: 'header' }));
42
- render(html `<label-view font="callout">
43
- <span>${newValue}</span>
44
- </label-view>`, header);
37
+ // if (!newValue) {
38
+ // this.querySelector(':scope>[slot=header]')?.remove()
39
+ // break
40
+ // }
41
+ // const header = this.querySelector(':scope>[slot=header]') ?? this.appendChild(Object.assign(document.createElement('header'), { slot: 'header' }))
42
+ queryMorph('[slot=header]', html `<header slot="header">
43
+ <label-view font="callout">
44
+ <span>${newValue}</span>
45
+ </label-view>
46
+ </header>`, this, { removeIf: !newValue });
47
+ // render(
48
+ // html`<label-view font="callout">
49
+ // <span>${newValue}</span>
50
+ // </label-view>`,
51
+ // header
52
+ // )
45
53
  break;
46
54
  case 'footer':
47
- if (!newValue) {
48
- this.querySelector(':scope>[slot=footer]')?.remove();
49
- break;
50
- }
51
- const footer = this.querySelector(':scope>[slot=footer]') ?? this.appendChild(Object.assign(document.createElement('footer'), { slot: 'footer' }));
52
- render(html `<label-view font="callout">
53
- <span>${newValue}</span>
54
- </label-view>`, footer);
55
+ // if (!newValue) {
56
+ // this.querySelector(':scope>[slot=footer]')?.remove()
57
+ // break
58
+ // }
59
+ // const footer = this.querySelector(':scope>[slot=footer]') ?? this.appendChild(Object.assign(document.createElement('footer'), { slot: 'footer' }))
60
+ queryMorph('[slot=footer]', html `<footer slot="footer">
61
+ <label-view font="callout">
62
+ <span>${newValue}</span>
63
+ </label-view>
64
+ </footer>`, this, { removeIf: !newValue });
65
+ // render(
66
+ // html`<label-view font="callout">
67
+ // <span>${newValue}</span>
68
+ // </label-view>`,
69
+ // footer
70
+ // )
55
71
  break;
56
- case 'value':
57
- renderLabel(':scope>label-view:not([slot])', `<label-view><span></span></label-view>`, this, this.#fmt(newValue, this.getAttribute('format')));
72
+ case 'value': {
73
+ const val = this.#fmt(newValue, this.getAttribute('format'));
74
+ queryMorph('label-view:not([slot])', html `<label-view>${val ? html `<span>${val}</span>` : null}</label-view>`, this); //renderLabel(':scope>label-view:not([slot])', `<label-view><span></span></label-view>`, this, this.#fmt(newValue, this.getAttribute('format')))
58
75
  break;
59
- case 'format':
60
- renderLabel(':scope>label-view:not([slot])', `<label-view><span></span></label-view>`, this, this.#fmt(this.getAttribute('value'), newValue));
76
+ }
77
+ case 'format': {
78
+ const val = this.#fmt(this.getAttribute('value'), newValue);
79
+ queryMorph('label-view:not([slot])', html `<label-view>${val ? html `<span>${val}</span>` : null}</label-view>`, this); //renderLabel(':scope>label-view:not([slot])', `<label-view><span></span></label-view>`, this, this.#fmt(this.getAttribute('value'), newValue))
61
80
  break;
81
+ }
62
82
  case 'label':
63
- renderLabel(':scope>label-view[slot=label]', `<label-view slot="label"><span></span></label-view>`, this, newValue);
83
+ queryMorph('[slot=label]', html `<label-view slot="label">${newValue ? html `<span>${newValue}</span>` : null}</label-view>`, this); //renderLabel(':scope>label-view[slot=label]', `<label-view slot="label"><span></span></label-view>`, this, newValue)
64
84
  break;
65
85
  }
66
86
  }
@@ -1,6 +1,7 @@
1
1
  var _a;
2
2
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
3
- import { $, devFlags, onoff, renderLabel, touchGlass } from '../internal/utils';
3
+ import { $, devFlags, onoff, touchGlass } from '../internal/utils';
4
+ import { html, queryMorph } from '../morphdom';
4
5
  /**
5
6
  * @summary A control for presenting a menu of actions.
6
7
  *
@@ -60,7 +61,7 @@ export class MenuView extends HTMLElement {
60
61
  }
61
62
  break;
62
63
  case 'label':
63
- renderLabel(':scope>[slot=label]', `<label-view slot="label"><span></span></label-view>`, this, newValue);
64
+ queryMorph('[slot=label]', html `<label-view slot="label">${newValue ? html `<span>${newValue}</span>` : null}</label-view>`, this); //renderLabel(':scope>[slot=label]', `<label-view slot="label"><span></span></label-view>`, this, newValue)
64
65
  break;
65
66
  }
66
67
  }
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var NavigationTitle_1;
8
8
  import { microtaskOnConnected } from '../internal/decorators';
9
9
  import { devFlags } from '../internal/utils';
10
- import { html, render } from '../tpl';
10
+ import { html, queryMorph } from '../morphdom';
11
11
  let NavigationTitle = NavigationTitle_1 = class NavigationTitle extends HTMLElement {
12
12
  static get observedAttributes() {
13
13
  return ['value', 'subtitle', 'system-image', 'system-image-weight'];
@@ -29,21 +29,27 @@ let NavigationTitle = NavigationTitle_1 = class NavigationTitle extends HTMLElem
29
29
  console.debug(`${NavigationTitle_1.name} ⚡️ connect`);
30
30
  }
31
31
  #render = (title, subtitle, systemImage, systemImageWeight) => {
32
- const template = html `
33
- <v-stack alignment="fill">
34
- ${systemImage ? html `<image-view system-name="${systemImage}" system-weight="${systemImageWeight}" foreground="blue"></image-view>` : null}
35
- <v-stack spacing="0" alignment="fill">
36
- <label-view line-limit="1" truncation-mode="tail" font="headline">
37
- <span>${title ?? ''}</span>
38
- </label-view>
39
- <label-view line-limit="1" truncation-mode="tail" foreground="secondary" font="callout">
40
- <span>${subtitle ?? ''}</span>
41
- </label-view>
42
- </v-stack>
43
- </v-stack>
44
- `;
45
- const container = this.querySelector(':scope>:not([slot])') ?? this.appendChild(document.createElement('navigation-large-title'));
46
- render(template, container);
32
+ // const container = this.querySelector(':scope>:not([slot])') ?? this.appendChild(document.createElement('navigation-large-title'))
33
+ // render(template, container)
34
+ queryMorph(':not([slot])', html `
35
+ <navigation-large-title>
36
+ <v-stack alignment="fill">
37
+ ${systemImage ? html `<image-view system-name="${systemImage}" system-weight="${systemImageWeight}" foreground="blue"></image-view>` : null}
38
+ <v-stack spacing="0" alignment="fill">
39
+ ${title
40
+ ? html `<label-view line-limit="1" truncation-mode="tail" font="headline">
41
+ <span>${title}</span>
42
+ </label-view>`
43
+ : null}
44
+ ${subtitle
45
+ ? html `<label-view line-limit="1" truncation-mode="tail" foreground="secondary" font="callout">
46
+ <span>${subtitle}</span>
47
+ </label-view>`
48
+ : null}
49
+ </v-stack>
50
+ </v-stack>
51
+ </navigation-large-title>
52
+ `, this);
47
53
  // const titleTemplate = `<label-view line-limit="1" truncation-mode="tail" font="headline"><span></span></label-view>`,
48
54
  // subtitleTemplate = `<label-view line-limit="1" truncation-mode="tail" foreground="secondary" font="callout"><span></span></label-view>`,
49
55
  // vStactTemplate = `<v-stack spacing="0" alignment="fill">${titleTemplate}${subtitleTemplate}</v-stack>`
@@ -5,7 +5,8 @@ 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 { $, devFlags, kebabCase, onoff, renderLabel, renderLabelIcon, renderLabelTitle } from '../internal/utils';
8
+ import { $, devFlags, kebabCase, onoff } from '../internal/utils';
9
+ import { html as htmx, morph, queryMorph } from '../morphdom';
9
10
  import { html, render } from '../tpl';
10
11
  const pickerStyles = ['menu', 'inline', 'navigation-link', 'sheet', 'automatic'];
11
12
  const update = (path, node, overwrite = true) => {
@@ -435,7 +436,7 @@ export class PickerView extends FormAssociatedBase {
435
436
  const value = this.getAttribute(this.constructor.ATTR.LABEL);
436
437
  if (value) {
437
438
  const hStack = $(`<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>`, '>1');
438
- renderLabel(':scope>label-view:nth-child(2)', `<label-view><span></span></label-view>`, hStack, value);
439
+ queryMorph('label-view:nth-child(2)', htmx `<label-view>${value ? htmx `<span>${value}</span>` : null}</label-view>`, hStack); //renderLabel(':scope>label-view:nth-child(2)', `<label-view><span></span></label-view>`, hStack, value)
439
440
  // if (label) renderLabelTitle(label, value) //label.setAttribute('title', value)
440
441
  section.insertAdjacentElement('beforeend', hStack);
441
442
  }
@@ -669,7 +670,7 @@ export class PickerView extends FormAssociatedBase {
669
670
  }
670
671
  #render() {
671
672
  if (devFlags.debug)
672
- console.debug(`${_a.name} ⚡️ render (${this.pickerStyle})`);
673
+ console.debug(`${_a.name} ⚡️ #render (${this.pickerStyle})`);
673
674
  // const style = this.getAttribute((this.constructor as typeof PickerView).ATTR.PICKER_STYLE)
674
675
  if (this.#lastRenderedStyle === this.pickerStyle)
675
676
  return; // skip if already applied
@@ -982,7 +983,7 @@ export class PickerView extends FormAssociatedBase {
982
983
  #reflectLabel(value) {
983
984
  if (devFlags.debug)
984
985
  console.debug(`${_a.name} #reflectLabel`);
985
- renderLabel(':scope>label-view[slot=label]', `<label-view slot="label"><span></span></label-view>`, this, value);
986
+ queryMorph('[slot=label]', htmx `<label-view slot="label">${value ? htmx `<span>${value}</span>` : null}</label-view>`, this); //renderLabel(':scope>label-view[slot=label]', `<label-view slot="label"><span></span></label-view>`, this, value)
986
987
  this.#renderSlotted([]);
987
988
  }
988
989
  #reflectSelectionOnButtons() {
@@ -1029,8 +1030,10 @@ export class PickerView extends FormAssociatedBase {
1029
1030
  break;
1030
1031
  // if (!cvl) currentValueLabel.setAttribute('foreground', 'secondary')
1031
1032
  // else currentValueLabel.removeAttribute('foreground')
1032
- renderLabelTitle(currentValueLabel, this.#currentValueLabel || this.#selection || this.getAttribute(this.constructor.ATTR.PLACEHOLDER));
1033
- renderLabelIcon(currentValueLabel, this.#currentValueIcon || this.getAttribute(this.constructor.ATTR.PLACEHOLDER_ICON));
1033
+ const title = this.#currentValueLabel || this.#selection || this.getAttribute(this.constructor.ATTR.PLACEHOLDER), systemImage = this.#currentValueIcon || this.getAttribute(this.constructor.ATTR.PLACEHOLDER_ICON);
1034
+ // queryMorph(':not([slot])', htmx`<span>${title}</span>`, currentValueLabel, { removeIf: !title }) //renderLabelTitle(currentValueLabel, this.#currentValueLabel || this.#selection || this.getAttribute((this.constructor as typeof PickerView).ATTR.PLACEHOLDER))
1035
+ // queryMorph('[slot=icon]', htmx`<image-view slot="icon" system-name="${systemImage}"></image-view>`, currentValueLabel, { removeIf: !systemImage }) //renderLabelIcon(currentValueLabel, this.#currentValueIcon || this.getAttribute((this.constructor as typeof PickerView).ATTR.PLACEHOLDER_ICON))
1036
+ morph(htmx `<label-view>${systemImage ? htmx `<image-view slot="icon" system-name="${systemImage}"></image-view>` : null}${title ? htmx `<span>${title}</span>` : null}</label-view>`, currentValueLabel);
1034
1037
  break;
1035
1038
  }
1036
1039
  case 'menu': {
@@ -1039,8 +1042,10 @@ export class PickerView extends FormAssociatedBase {
1039
1042
  break;
1040
1043
  // if (!cvl) currentValueLabel.setAttribute('foreground', 'secondary')
1041
1044
  // else currentValueLabel.removeAttribute('foreground')
1042
- renderLabelTitle(currentValueLabel, this.#currentValueLabel || this.#selection || this.getAttribute(this.constructor.ATTR.PLACEHOLDER));
1043
- renderLabelIcon(currentValueLabel, this.#currentValueIcon || this.getAttribute(this.constructor.ATTR.PLACEHOLDER_ICON));
1045
+ const title = this.#currentValueLabel || this.#selection || this.getAttribute(this.constructor.ATTR.PLACEHOLDER), systemImage = this.#currentValueIcon || this.getAttribute(this.constructor.ATTR.PLACEHOLDER_ICON);
1046
+ // queryMorph(':not([slot])', htmx`<span>${title}</span>`, currentValueLabel, { removeIf: !title }) //renderLabelTitle(currentValueLabel, this.#currentValueLabel || this.#selection || this.getAttribute((this.constructor as typeof PickerView).ATTR.PLACEHOLDER))
1047
+ // queryMorph('[slot=icon]', htmx`<image-view slot="icon" system-name="${systemImage}"></image-view>`, currentValueLabel, { removeIf: !systemImage }) //renderLabelIcon(currentValueLabel, this.#currentValueIcon || this.getAttribute((this.constructor as typeof PickerView).ATTR.PLACEHOLDER_ICON))
1048
+ morph(htmx `<label-view slot="label">${systemImage ? htmx `<image-view slot="icon" system-name="${systemImage}"></image-view>` : null}${title ? htmx `<span>${title}</span>` : null}</label-view>`, currentValueLabel);
1044
1049
  break;
1045
1050
  }
1046
1051
  case 'inline':
@@ -1,7 +1,8 @@
1
1
  var _a;
2
2
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
3
3
  import { CSSStyleObserver } from '../internal/class/css-style-observer';
4
- import { $, devFlags, renderLabel } from '../internal/utils';
4
+ import { $, devFlags } from '../internal/utils';
5
+ import { html, queryMorph } from '../morphdom';
5
6
  import { Snapshot } from '../snapshot';
6
7
  const progressViewStyles = ['circular', 'linear'];
7
8
  /**
@@ -70,7 +71,7 @@ export class ProgressView extends HTMLElement {
70
71
  break;
71
72
  }
72
73
  case 'current-value-label': {
73
- renderLabel(':scope>[slot=current-value]', `<label-view slot="current-value" font="callout" foreground="secondary"><span></span></label-view>`, this, newValue);
74
+ queryMorph('[slot=current-value]', html `<label-view slot="current-value" font="callout" foreground="secondary">${newValue ? html `<span>${newValue}</span>` : null}</label-view>`, this); //renderLabel(':scope>[slot=current-value]', `<label-view slot="current-value" font="callout" foreground="secondary"><span></span></label-view>`, this, newValue)
74
75
  break;
75
76
  }
76
77
  }
@@ -102,7 +103,7 @@ export class ProgressView extends HTMLElement {
102
103
  };
103
104
  #render() {
104
105
  if (devFlags.debug)
105
- console.debug(`${_a.name} ⚡️ render (${this.#progressViewStyle})`);
106
+ console.debug(`${_a.name} ⚡️ #render (${this.#progressViewStyle})`);
106
107
  if (this.#lastRenderedStyle === this.#progressViewStyle)
107
108
  return; // skip if already applied
108
109
  this.#lastRenderedStyle = this.#progressViewStyle;
@@ -3,7 +3,7 @@ import { lifecycleObserver } from '../buses';
3
3
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
4
4
  import { ResizeObserverSingleton } from '../internal/class/resize-observer-singleton';
5
5
  import { $, devFlags, frame, onoff, slowHideShow } from '../internal/utils';
6
- import { html, render } from '../tpl';
6
+ import { html, queryMorph } from '../morphdom';
7
7
  const observers = new ResizeObserverSingleton();
8
8
  /**
9
9
  * @slot top-bar-principal
@@ -11,7 +11,7 @@ const observers = new ResizeObserverSingleton();
11
11
  */
12
12
  export class ScrollView extends HTMLElement {
13
13
  static get observedAttributes() {
14
- return ['navigation-title', 'navigation-inline-title', 'navigation-inline-subtitle', 'navigation-bar-title-display-mode'];
14
+ return ['navigation-title', 'navigation-inline-title', 'navigation-inline-subtitle', 'navigation-icon', 'navigation-bar-title-display-mode'];
15
15
  }
16
16
  static #template;
17
17
  static get template() {
@@ -55,9 +55,12 @@ export class ScrollView extends HTMLElement {
55
55
  case 'navigation-inline-subtitle':
56
56
  this.#renderNavTitle(this.getAttribute('navigation-inline-title'), newValue);
57
57
  break;
58
- case 'navigation-title':
59
- //
58
+ case 'navigation-title': {
59
+ if (oldValue === newValue)
60
+ return;
61
+ this.#renderNavTitleComponent(newValue, null, this.getAttribute('navigation-icon'));
60
62
  break;
63
+ }
61
64
  case 'navigation-bar-title-display-mode':
62
65
  if (oldValue === newValue)
63
66
  break;
@@ -197,11 +200,27 @@ export class ScrollView extends HTMLElement {
197
200
  // this.querySelector(':scope>[slot=top-bar-principal]') ?? this.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal">${titleTemplate}${subtitleTemplate}</v-stack>`, '>1'))
198
201
  // renderLabel(':scope>label-view:nth-child(1)', titleTemplate, vStack, title)
199
202
  // renderLabel(':scope>label-view:nth-child(2)', subtitleTemplate, vStack, subtitle)
200
- const container = this.querySelector(':scope>[slot=top-bar-principal]') ?? this.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal"></v-stack>`, '>1'));
201
- render(html `
203
+ // const container = this.querySelector(':scope>[slot=top-bar-principal]') ?? this.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal"></v-stack>`, '>1'))
204
+ queryMorph('[slot=top-bar-principal]', html `<v-stack spacing="0" alignment="fill" slot="top-bar-principal">
202
205
  ${title ? html `<label-view line-limit="1" truncation-mode="tail" font="headline"><span>${title}</span></label-view>` : null}
203
206
  ${subtitle ? html `<label-view line-limit="1" truncation-mode="tail" foreground="secondary" font="callout"><span>${subtitle}</span></label-view>` : null}
204
- `, container);
207
+ </v-stack>`, this);
208
+ // render(
209
+ // html`
210
+ // ${title ? html`<label-view line-limit="1" truncation-mode="tail" font="headline"><span>${title}</span></label-view>` : null}
211
+ // ${subtitle ? html`<label-view line-limit="1" truncation-mode="tail" foreground="secondary" font="callout"><span>${subtitle}</span></label-view>` : null}
212
+ // `,
213
+ // container
214
+ // )
215
+ };
216
+ #renderNavTitleComponent = (title, subtitle, icon) => {
217
+ if (!title)
218
+ return this.querySelector(':scope>v-stack>navigation-title:not([slot])')?.remove?.();
219
+ // const container = ((vs = this.querySelector<HTMLElement>(':scope>v-stack') ?? (this.appendChild($(`<v-stack></v-stack>`, '>1')) as HTMLElement)) =>
220
+ // vs.querySelector<HTMLElement>(':scope>navigation-title:not([slot])') ??
221
+ // vs.appendChild($(html`<navigation-title value="${title}" subtitle="${subtitle}" system-image="${icon}" padding></navigation-title>`.toString(), '>1')))()
222
+ const container = this.querySelector(':scope>v-stack') ?? this.appendChild($(`<v-stack></v-stack>`, '>1'));
223
+ queryMorph('navigation-title:not([slot])', html `<navigation-title value="${title}" subtitle="${subtitle}" system-image="${icon}" padding></navigation-title>`, container);
205
224
  };
206
225
  }
207
226
  _a = ScrollView;
@@ -1,5 +1,5 @@
1
1
  import { $, devFlags } from '../internal/utils';
2
- import { html, render } from '../tpl';
2
+ import { html, queryMorph } from '../morphdom';
3
3
  /**
4
4
  * @slot header
5
5
  * @slot footer
@@ -42,24 +42,40 @@ export class SectionView extends HTMLElement {
42
42
  // Snapshot.waitReady.then(() => {
43
43
  switch (name) {
44
44
  case 'header':
45
- if (!newValue) {
46
- this.querySelector(':scope>[slot=header]')?.remove();
47
- break;
48
- }
49
- const header = this.querySelector(':scope>[slot=header]') ?? this.appendChild(Object.assign(document.createElement('header'), { slot: 'header' }));
50
- render(html `<label-view line-limit="1" truncation-mode="tail" font="callout">
51
- <span>${newValue}</span>
52
- </label-view>`, header);
45
+ // if (!newValue) {
46
+ // this.querySelector(':scope>[slot=header]')?.remove()
47
+ // break
48
+ // }
49
+ // const header = this.querySelector(':scope>[slot=header]') ?? this.appendChild(Object.assign(document.createElement('header'), { slot: 'header' }))
50
+ queryMorph('[slot=header]', html `<header slot="header">
51
+ <label-view line-limit="1" truncation-mode="tail" font="callout">
52
+ <span>${newValue}</span>
53
+ </label-view>
54
+ </header>`, this, { removeIf: !newValue });
55
+ // render(
56
+ // html`<label-view line-limit="1" truncation-mode="tail" font="callout">
57
+ // <span>${newValue}</span>
58
+ // </label-view>`,
59
+ // header
60
+ // )
53
61
  break;
54
62
  case 'footer':
55
- if (!newValue) {
56
- this.querySelector(':scope>[slot=footer]')?.remove();
57
- break;
58
- }
59
- const footer = this.querySelector(':scope>[slot=footer]') ?? this.appendChild(Object.assign(document.createElement('footer'), { slot: 'footer' }));
60
- render(html `<label-view line-limit="1" truncation-mode="tail" font="callout">
61
- <span>${newValue}</span>
62
- </label-view>`, footer);
63
+ // if (!newValue) {
64
+ // this.querySelector(':scope>[slot=footer]')?.remove()
65
+ // break
66
+ // }
67
+ // const footer = this.querySelector(':scope>[slot=footer]') ?? this.appendChild(Object.assign(document.createElement('footer'), { slot: 'footer' }))
68
+ queryMorph('[slot=footer]', html `<footer slot="footer">
69
+ <label-view line-limit="1" truncation-mode="tail" font="callout">
70
+ <span>${newValue}</span>
71
+ </label-view>
72
+ </footer>`, this, { removeIf: !newValue });
73
+ // render(
74
+ // html`<label-view line-limit="1" truncation-mode="tail" font="callout">
75
+ // <span>${newValue}</span>
76
+ // </label-view>`,
77
+ // footer
78
+ // )
63
79
  break;
64
80
  }
65
81
  // })
@@ -2,7 +2,8 @@ var _a;
2
2
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
3
3
  import { CSSStyleObserver } from '../internal/class/css-style-observer';
4
4
  import { MutationObserverSet } from '../internal/class/mutation-observer-set';
5
- import { $, devFlags, listActive, onoff, renderLabelTitle } from '../internal/utils';
5
+ import { $, devFlags, listActive, onoff } from '../internal/utils';
6
+ import { html, queryMorph } from '../morphdom';
6
7
  import { Snapshot } from '../snapshot';
7
8
  /**
8
9
  * @summary Display selectable, sortable data arranged in rows and columns.
@@ -113,11 +114,9 @@ export class TableView extends HTMLElement {
113
114
  <label-view></label-view>
114
115
  <label-view font="callout" foreground="secondary"></label-view>
115
116
  </v-stack>
116
- </button>`, '>1'), title = btn.querySelector('label-view:first-child'), subTitle = btn.querySelector('label-view:last-child');
117
- if (title)
118
- renderLabelTitle(title, node.textContent.trim()); //title?.setAttribute('title', node.textContent.trim())
119
- if (subTitle)
120
- renderLabelTitle(subTitle, node.ariaSort ?? ''); //subTitle?.setAttribute('title', node.ariaSort ?? '')
117
+ </button>`, '>1'), title = btn.querySelector('label-view:first-child') ?? undefined, subTitle = btn.querySelector('label-view:last-child') ?? undefined;
118
+ queryMorph(':not([slot])', html `<span>${node.textContent.trim()}</span>`, title, { removeIf: !node.textContent.trim() }); //renderLabelTitle(title, node.textContent.trim()) //title?.setAttribute('title', node.textContent.trim())
119
+ queryMorph(':not([slot])', html `<span>${node.ariaSort ?? ''}</span>`, subTitle, { removeIf: !(node.ariaSort ?? '') }); //renderLabelTitle(subTitle, node.ariaSort ?? '') //subTitle?.setAttribute('title', node.ariaSort ?? '')
121
120
  this.#compactToolbarItem.appendChild(btn);
122
121
  }
123
122
  };
@@ -3,7 +3,8 @@ import { I18n } from '../i18n';
3
3
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
4
4
  import { FormAssociatedBase, getInternals } from '../internal/class/form-associated-base';
5
5
  import { MutationObserverSet } from '../internal/class/mutation-observer-set';
6
- import { $, compareBigDecimals, devFlags, kebabCase, onoff, renderLabel, set } from '../internal/utils';
6
+ import { $, compareBigDecimals, devFlags, kebabCase, onoff, set } from '../internal/utils';
7
+ import { html, queryMorph } from '../morphdom';
7
8
  const keyboardTypes = ['decimal-pad', 'number-pad', 'default'];
8
9
  /**
9
10
  * @slot label
@@ -137,7 +138,7 @@ export class TextField extends FormAssociatedBase {
137
138
  this.#sendValueToForm();
138
139
  break;
139
140
  case 'label':
140
- renderLabel(':scope>label-view[slot=label]', `<label-view slot="label" foreground="secondary"><span></span></label-view>`, this, newValue);
141
+ queryMorph('[slot=label]', html `<label-view slot="label" foreground="secondary">${newValue ? html `<span>${newValue}</span>` : null}</label-view>`, this); //renderLabel(':scope>label-view[slot=label]', `<label-view slot="label" foreground="secondary"><span></span></label-view>`, this, newValue)
141
142
  // this.#sendValueToForm()
142
143
  break;
143
144
  case 'disabled':
@@ -2,7 +2,8 @@ var _a;
2
2
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
3
3
  import { FormAssociatedBase, getInternals } from '../internal/class/form-associated-base';
4
4
  import { MutationObserverSet } from '../internal/class/mutation-observer-set';
5
- import { $, devFlags, kebabCase, onoff, renderLabel } from '../internal/utils';
5
+ import { $, devFlags, kebabCase, onoff } from '../internal/utils';
6
+ import { html, queryMorph } from '../morphdom';
6
7
  const toggleStyles = ['switch', 'button'];
7
8
  /**
8
9
  * @slot label
@@ -84,7 +85,7 @@ export class ToggleView extends FormAssociatedBase {
84
85
  this.#sendValueToForm(this.#connected);
85
86
  break;
86
87
  case 'label':
87
- renderLabel(':scope>label-view[slot=label]', `<label-view slot="label"><span></span></label-view>`, this, newValue);
88
+ queryMorph('[slot=label]', html `<label-view slot="label">${newValue ? html `<span>${newValue}</span>` : null}</label-view>`, this); //renderLabel(':scope>label-view[slot=label]', `<label-view slot="label"><span></span></label-view>`, this, newValue)
88
89
  break;
89
90
  case 'disabled':
90
91
  for (const el of this.#shadowRoot.querySelectorAll('input'))