@swiftwc/ui 0.0.0-dev.25 → 0.0.0-dev.27

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.
@@ -1,6 +1,7 @@
1
1
  import { lifecycleObserver } from '../buses';
2
2
  import { I18n } from '../i18n';
3
3
  import { NavigationPath } from '../internal/class/navigation-path';
4
+ import { type NavigationHost } from '../internal/privateNamespace';
4
5
  import { type WebComponentCtor } from '../namespace-browser';
5
6
  import { Snapshot } from '../snapshot';
6
7
  export declare const polyfills: Map<string, WebComponentCtor>;
@@ -25,5 +26,6 @@ export declare const confirmationDialog: (trigger: HTMLElement, title: string, a
25
26
  }[], options?: {
26
27
  controller?: AbortController;
27
28
  titleVisibility?: boolean;
28
- }) => Promise<any>;
29
+ }) => Promise<string>;
29
30
  export { I18n, lifecycleObserver, NavigationPath, Snapshot };
31
+ export { type NavigationHost };
@@ -328,7 +328,11 @@ export const alert = async (title, message, actions, options) => {
328
328
  label.setAttribute('title', message);
329
329
  vStack.insertAdjacentElement('beforeend', label);
330
330
  }
331
- for (const [index, action] of (actions ?? []).entries()) {
331
+ for (const [index, action] of (actions ?? [
332
+ {
333
+ role: 'close',
334
+ },
335
+ ]).entries()) {
332
336
  const btn = $(`<button type="button" tabindex="0" is="bordered-button"></button>`, '>1');
333
337
  btn.setAttribute('value', `${index}`);
334
338
  if (action?.role)
@@ -368,7 +372,7 @@ export const confirmationDialog = async (trigger, title, actions, options) => {
368
372
  if (action?.role)
369
373
  btn.setAttribute('role', action.role);
370
374
  if (action.label || action.image) {
371
- const label = $(`<label-view title="${action.label}"></label-view>`, '>1');
375
+ const label = $(`<label-view></label-view>`, '>1');
372
376
  if (action.label)
373
377
  label.setAttribute('title', action.label);
374
378
  if (action.image)
@@ -377,7 +381,7 @@ export const confirmationDialog = async (trigger, title, actions, options) => {
377
381
  }
378
382
  dialog.insertAdjacentElement('beforeend', btn);
379
383
  }
380
- trigger.closest('body-view')?.insertAdjacentElement('beforeend', dialog); // dialog.showModal()
384
+ trigger.closest('body-view,dialog')?.insertAdjacentElement('beforeend', dialog); // dialog.showModal()
381
385
  const { promise, resolve } = Promise.withResolvers(), off = onoff('confirmation:return', (evt) => {
382
386
  off();
383
387
  resolve(evt.detail.returnValue);
@@ -8,7 +8,7 @@ import { Snapshot } from '../snapshot';
8
8
  */
9
9
  export class BorderedButton extends ButtonBase {
10
10
  static get observedAttributes() {
11
- return ['role'];
11
+ return ['role', 'title-key'];
12
12
  }
13
13
  constructor() {
14
14
  super();
@@ -28,9 +28,10 @@ export class BorderedButton extends ButtonBase {
28
28
  if (!node)
29
29
  return;
30
30
  switch (attributeName) {
31
+ case 'title-key':
31
32
  case 'role':
32
33
  Snapshot.waitReady.then(() => {
33
- buttonRole(target, target.getAttribute(attributeName));
34
+ buttonRole(target, target.getAttribute('role'), target.getAttribute('title-key'));
34
35
  });
35
36
  break;
36
37
  }
@@ -8,7 +8,7 @@ import { Snapshot } from '../snapshot';
8
8
  */
9
9
  export class BorderedProminentButton extends ButtonBase {
10
10
  static get observedAttributes() {
11
- return ['role'];
11
+ return ['role', 'title-key'];
12
12
  }
13
13
  constructor() {
14
14
  super();
@@ -28,9 +28,10 @@ export class BorderedProminentButton extends ButtonBase {
28
28
  if (!node)
29
29
  return;
30
30
  switch (attributeName) {
31
+ case 'title-key':
31
32
  case 'role':
32
33
  Snapshot.waitReady.then(() => {
33
- buttonRole(target, target.getAttribute(attributeName));
34
+ buttonRole(target, target.getAttribute('role'), target.getAttribute('title-key'));
34
35
  });
35
36
  break;
36
37
  }
@@ -8,7 +8,7 @@ import { Snapshot } from '../snapshot';
8
8
  */
9
9
  export class BorderlessButton extends ButtonBase {
10
10
  static get observedAttributes() {
11
- return ['role'];
11
+ return ['role', 'title-key'];
12
12
  }
13
13
  constructor() {
14
14
  super();
@@ -28,9 +28,10 @@ export class BorderlessButton extends ButtonBase {
28
28
  if (!node)
29
29
  return;
30
30
  switch (attributeName) {
31
+ case 'title-key':
31
32
  case 'role':
32
33
  Snapshot.waitReady.then(() => {
33
- buttonRole(target, target.getAttribute(attributeName));
34
+ buttonRole(target, target.getAttribute('role'), target.getAttribute('title-key'));
34
35
  });
35
36
  break;
36
37
  }
@@ -5,7 +5,12 @@ export class FineTooltip extends HTMLElement {
5
5
  constructor() {
6
6
  super();
7
7
  }
8
- #handleMutation = (mutations) => {
8
+ #handleTriggerRemovalMutation = (mutations) => {
9
+ if (this.#queryTrigger?.isConnected)
10
+ return;
11
+ this?.remove();
12
+ };
13
+ #handleTriggerAttrMutation = (mutations) => {
9
14
  for (const { target, attributeName } of mutations)
10
15
  if (target instanceof HTMLElement && target && attributeName)
11
16
  this.#render(target.getAttribute(attributeName));
@@ -23,7 +28,8 @@ export class FineTooltip extends HTMLElement {
23
28
  target.style.setProperty('transform-origin', 'bottom');
24
29
  }
25
30
  };
26
- #observer = new MutationObserver(this.#handleMutation);
31
+ #mutationObserver = new MutationObserver(this.#handleTriggerAttrMutation);
32
+ #mutationObserver2 = new MutationObserver(this.#handleTriggerRemovalMutation);
27
33
  #resizeObserver = new ResizeObserver(this.#handleMeasure);
28
34
  get #queryTrigger() {
29
35
  const positionAnchor = this.style.positionAnchor;
@@ -51,7 +57,8 @@ export class FineTooltip extends HTMLElement {
51
57
  disconnectedCallback() {
52
58
  console.debug(`${_a.name} ⚡️ disconnect`);
53
59
  this.#resizeObserver.unobserve(this);
54
- this.#observer?.disconnect();
60
+ this.#mutationObserver?.disconnect();
61
+ this.#mutationObserver2?.disconnect();
55
62
  this.#queryTrigger?.style.removeProperty('anchor-name');
56
63
  CleanupRegistry.unregister(this);
57
64
  }
@@ -71,10 +78,14 @@ export class FineTooltip extends HTMLElement {
71
78
  }
72
79
  else {
73
80
  this.#render(trigger.getAttribute('help'));
74
- this.#observer.observe(trigger, {
81
+ this.#mutationObserver.observe(trigger, {
75
82
  attributes: true,
76
83
  attributeFilter: ['help'],
77
84
  });
85
+ this.#mutationObserver2.observe(document.body, {
86
+ childList: true,
87
+ subtree: true,
88
+ });
78
89
  this.#resizeObserver.observe(this);
79
90
  }
80
91
  this.toggleAttribute('open', 'open' === evt.newState);
@@ -8,7 +8,7 @@ import { Snapshot } from '../snapshot';
8
8
  */
9
9
  export class GlassButton extends ButtonBase {
10
10
  static get observedAttributes() {
11
- return ['role'];
11
+ return ['role', 'title-key'];
12
12
  }
13
13
  constructor() {
14
14
  super();
@@ -28,9 +28,10 @@ export class GlassButton extends ButtonBase {
28
28
  if (!node)
29
29
  return;
30
30
  switch (attributeName) {
31
+ case 'title-key':
31
32
  case 'role':
32
33
  Snapshot.waitReady.then(() => {
33
- buttonRole(target, target.getAttribute(attributeName));
34
+ buttonRole(target, target.getAttribute('role'), target.getAttribute('title-key'));
34
35
  });
35
36
  break;
36
37
  }
@@ -8,7 +8,7 @@ import { Snapshot } from '../snapshot';
8
8
  */
9
9
  export class GlassProminentButton extends ButtonBase {
10
10
  static get observedAttributes() {
11
- return ['role'];
11
+ return ['role', 'title-key'];
12
12
  }
13
13
  constructor() {
14
14
  super();
@@ -28,9 +28,10 @@ export class GlassProminentButton extends ButtonBase {
28
28
  if (!node)
29
29
  return;
30
30
  switch (attributeName) {
31
+ case 'title-key':
31
32
  case 'role':
32
33
  Snapshot.waitReady.then(() => {
33
- buttonRole(target, target.getAttribute(attributeName));
34
+ buttonRole(target, target.getAttribute('role'), target.getAttribute('title-key'));
34
35
  });
35
36
  break;
36
37
  }
@@ -33,34 +33,17 @@ export class NavigationTitle extends HTMLElement {
33
33
  }
34
34
  }
35
35
  #render = (title, subtitle) => {
36
- const el = this.querySelector(':scope>:not([slot])') ??
37
- this.appendChild($(`<navigation-large-title><v-stack spacing="0" alignment="fill"><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"><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
- let titleLabel = vStack.querySelector(':scope>label-view:nth-child(1)');
40
- if (title) {
41
- titleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="headline"></label-view>`, '>1'));
36
+ const titleTemplate = `<label-view line-limit="1" truncation-mode="tail" font="headline"></label-view>`, subtitleTemplate = `<label-view line-limit="1" truncation-mode="tail" foreground="secondary" font="callout"></label-view>`, vStactTemplate = `<v-stack spacing="0" alignment="fill">${titleTemplate}${subtitleTemplate}</v-stack>`;
37
+ const el = this.querySelector(':scope>:not([slot])') ?? this.appendChild($(`<navigation-large-title>${vStactTemplate}</navigation-large-title>`, '>1')), vStack = el.querySelector(':scope>v-stack') ?? el.appendChild($(vStactTemplate, '>1'));
38
+ const titleLabel = vStack.querySelector(':scope>label-view:nth-child(1)') ?? vStack.appendChild($(titleTemplate, '>1'));
39
+ if (title)
42
40
  titleLabel.setAttribute('title', title);
43
- }
44
41
  else
45
- titleLabel?.remove();
46
- let subtitleLabel = vStack.querySelector(':scope>label-view:nth-child(2)');
47
- if (subtitle) {
48
- subtitleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="callout"></label-view>`, '>1'));
42
+ titleLabel?.removeAttribute('title');
43
+ const subtitleLabel = vStack.querySelector(':scope>label-view:nth-child(2)') ?? vStack.appendChild($(subtitleTemplate, '>1'));
44
+ if (subtitle)
49
45
  subtitleLabel.setAttribute('title', subtitle);
50
- }
51
46
  else
52
- subtitleLabel?.remove();
53
- // for (const el of this.querySelectorAll(':scope>*')) el.remove()
54
- // const el = this.appendChild(
55
- // Object.assign(document.createElement('template'), {
56
- // innerHTML: `<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>`,
57
- // }).content.firstElementChild!
58
- // ),
59
- // titleLabel = el.querySelector('label-view:nth-child(1)'),
60
- // subtitleLabel = el.querySelector('label-view:nth-child(2)')
61
- // if (title) titleLabel?.setAttribute('label', title)
62
- // else titleLabel?.remove()
63
- // if (subtitle) subtitleLabel?.setAttribute('label', subtitle)
64
- // else subtitleLabel?.remove()
47
+ subtitleLabel?.removeAttribute('title');
65
48
  };
66
49
  }
@@ -180,22 +180,18 @@ export class ScrollView extends HTMLElement {
180
180
  });
181
181
  }
182
182
  #renderNavTitle = (title, subtitle) => {
183
- const vStack = this.querySelector(':scope>[slot=top-bar-principal]') ??
184
- this.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal"><label-view line-limit="1" truncation-mode="tail" font="headline"></label-view><label-view line-limit="1" truncation-mode="tail" font="callout"></label-view></v-stack>`, '>1'));
185
- let titleLabel = vStack.querySelector(':scope>label-view:nth-child(1)');
186
- if (title) {
187
- titleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="headline"></label-view>`, '>1'));
183
+ const titleTemplate = `<label-view line-limit="1" truncation-mode="tail" font="headline"></label-view>`, subtitleTemplate = `<label-view line-limit="1" truncation-mode="tail" foreground="secondary" font="callout"></label-view>`;
184
+ const vStack = this.querySelector(':scope>[slot=top-bar-principal]') ?? this.appendChild($(`<v-stack spacing="0" alignment="fill" slot="top-bar-principal">${titleTemplate}${subtitleTemplate}</v-stack>`, '>1'));
185
+ const titleLabel = vStack.querySelector(':scope>label-view:nth-child(1)') ?? vStack.appendChild($(titleTemplate, '>1'));
186
+ if (title)
188
187
  titleLabel.setAttribute('title', title);
189
- }
190
188
  else
191
- titleLabel?.remove();
192
- let subtitleLabel = vStack.querySelector(':scope>label-view:nth-child(2)');
193
- if (subtitle) {
194
- subtitleLabel ??= vStack.appendChild($(`<label-view line-limit="1" truncation-mode="tail" font="callout"></label-view>`, '>1'));
189
+ titleLabel?.removeAttribute('title');
190
+ let subtitleLabel = vStack.querySelector(':scope>label-view:nth-child(2)') ?? vStack.appendChild($(subtitleTemplate, '>1'));
191
+ if (subtitle)
195
192
  subtitleLabel.setAttribute('title', subtitle);
196
- }
197
193
  else
198
- subtitleLabel?.remove();
194
+ subtitleLabel?.removeAttribute('title');
199
195
  };
200
196
  }
201
197
  _a = ScrollView;
@@ -3,7 +3,7 @@ import { buttonRole, onoff, touchGlass } from '../internal/utils';
3
3
  import { Snapshot } from '../snapshot';
4
4
  export class ToolBarItem extends HTMLElement {
5
5
  static get observedAttributes() {
6
- return ['slot', 'data-previous-slot'];
6
+ return ['slot', 'data-previous-slot', 'title-key'];
7
7
  }
8
8
  constructor() {
9
9
  super();
@@ -41,10 +41,11 @@ export class ToolBarItem extends HTMLElement {
41
41
  switch (name) {
42
42
  case 'slot':
43
43
  case 'data-previous-slot':
44
- const target = this.querySelector(':scope>button');
45
- if (target && ['confirmation-action'].includes(newValue ?? ''))
44
+ case 'title-key':
45
+ const target = this.querySelector(':scope>button'), nv = this.getAttribute('data-previous-slot') ?? this.getAttribute('slot') ?? '';
46
+ if (target && ['confirmation-action'].includes(nv))
46
47
  Snapshot.waitReady.then(() => {
47
- buttonRole(target, newValue);
48
+ buttonRole(target, nv, this.getAttribute('title-key'));
48
49
  });
49
50
  break;
50
51
  }
@@ -101,7 +101,7 @@
101
101
  --toolbar-cell-block-padding-start: 0.25rem;
102
102
  --toolbar-cell-block-padding-end: 0.25rem;
103
103
  --toolbar-cell-border-radius: var(--pill-border-radius);
104
- --toolbar-cell-min-size: 2.8rem;
104
+ --toolbar-cell-min-size: 2.9rem;
105
105
  --toolbar-cell-focus-bg: var(--control-clear-glass-focus-bg);
106
106
  --toolbar-cell-focus-bg-dark: var(--control-clear-glass-focus-bg-dark);
107
107
  --toolbar-cell-active-bg: var(--control-clear-glass-active-bg);
@@ -1695,9 +1695,10 @@
1695
1695
  color: var(--text, );
1696
1696
  touch-action: none;
1697
1697
  position: fixed;
1698
- inline-size: fit-content;
1699
- block-size: fit-content;
1698
+ inline-size: max-content;
1699
+ block-size: max-content;
1700
1700
  height: auto;
1701
+ min-inline-size: min(20rem, 80svw);
1701
1702
  max-inline-size: var(--confirmation--dialog-max-inline-size, );
1702
1703
  max-block-size: var(--confirmation--dialog-max-block-size, );
1703
1704
  margin-block: var(--confirmation--dialog-margin-block, );
@@ -1748,6 +1749,12 @@
1748
1749
  :where([is=alert-dialog])::backdrop {
1749
1750
  background-color: transparent;
1750
1751
  }
1752
+ @media (prefers-reduced-motion: no-preference) {
1753
+ :where([is=alert-dialog])::backdrop {
1754
+ transition: display var(--view-transition-duration) ease-out allow-discrete, overlay var(--view-transition-duration) ease-out allow-discrete, background-color var(--view-transition-duration) ease-out allow-discrete;
1755
+ will-change: background-color, overlay, display;
1756
+ }
1757
+ }
1751
1758
  :where([is=alert-dialog]) {
1752
1759
  color: var(--text, );
1753
1760
  touch-action: none;
@@ -1772,6 +1779,14 @@
1772
1779
  --alert--dialog-scale: scale(1.2);
1773
1780
  --alert--dialog-opacity: 0.8;
1774
1781
  }
1782
+ :where([is=alert-dialog][open])::backdrop {
1783
+ background-color: var(--view-transition-dialog-onscreen-backdrop-bg);
1784
+ }
1785
+ @starting-style {
1786
+ :where([is=alert-dialog][open])::backdrop {
1787
+ background-color: transparent;
1788
+ }
1789
+ }
1775
1790
  :where([is=alert-dialog][open]) {
1776
1791
  --alert--dialog-scale: scale(1);
1777
1792
  --alert--dialog-opacity: 1;
@@ -1782,6 +1797,14 @@
1782
1797
  --alert--dialog-opacity: 0.8;
1783
1798
  }
1784
1799
  }
1800
+ :where([is=alert-dialog][closing])::backdrop {
1801
+ background-color: var(--clear);
1802
+ }
1803
+ @starting-style {
1804
+ :where([is=alert-dialog][closing])::backdrop {
1805
+ background-color: transparent;
1806
+ }
1807
+ }
1785
1808
  :where([is=alert-dialog][closing]) {
1786
1809
  --alert--dialog-scale: scale(0.98);
1787
1810
  --alert--dialog-opacity: 0;
@@ -2369,7 +2392,7 @@
2369
2392
  }
2370
2393
  }
2371
2394
  @layer sw-colors {
2372
- [is=bordered-prominent-button] {
2395
+ [is=glass-prominent-button] {
2373
2396
  --secondary: var(--btntext);
2374
2397
  --blue: var(--btntext);
2375
2398
  }
@@ -6805,7 +6828,8 @@
6805
6828
  @layer sw-transitions {
6806
6829
  @media (prefers-reduced-motion: no-preference) {
6807
6830
  :where([is=alert-dialog]) {
6808
- transition: all var(--touchglass-transition-duration) allow-discrete ease-out;
6831
+ transition: display var(--touchglass-transition-duration) allow-discrete ease-out, overlay var(--touchglass-transition-duration) allow-discrete ease-out, transform var(--touchglass-transition-duration) allow-discrete ease-out, opacity var(--touchglass-transition-duration) allow-discrete ease-out;
6832
+ will-change: transform, overlay, display, opacity;
6809
6833
  }
6810
6834
  }
6811
6835
  }
@@ -7795,6 +7819,16 @@
7795
7819
  --toolbaritemactiveface: light-dark(oklch(from var(--accentColor) min(calc(l * 1.2), 1) min(calc(c * 1.1), c) h), oklch(from var(--accentColor) min(calc(l * 1.2), 1) min(calc(c * 1.1), c) h));
7796
7820
  --toolbaritemactivetext: light-dark(oklch(from var(--accentColor) clamp(0, (0.7 - l) * 999, 1) none none), oklch(from var(--accentColor) clamp(0, (0.7 - l) * 999, 1) none none));
7797
7821
  }
7822
+ :where(tool-bar-item[tint], [tint] tool-bar-item,
7823
+ tool-bar-item-group[tint],
7824
+ [tint] tool-bar-item-group,
7825
+ navigation-split-view sidebar-toggle[tint],
7826
+ [tint] navigation-split-view sidebar-toggle) > button {
7827
+ --secondary: var(--btntext);
7828
+ --blue: var(--btntext);
7829
+ --accentColorEffective: var(--btntext);
7830
+ --accentColor: var(--btntext);
7831
+ }
7798
7832
  :where(sidebar-toggle) {
7799
7833
  --toolbaritemhighlightface: light-dark(var(--toolbar-cell-focus-bg), var(--toolbar-cell-focus-bg-dark));
7800
7834
  --toolbaritemactiveface: light-dark(var(--toolbar-cell-active-bg), var(--toolbar-cell-active-bg-dark));
@@ -5,13 +5,11 @@ declare const _default: () => {
5
5
  readonly Description: "Ελέγξτε την ορθογραφία ή δοκιμάστε μια νέα αναζήτηση.";
6
6
  };
7
7
  readonly ButtonRole: {
8
- readonly Default: {
9
- readonly Cancel: "Cancel";
10
- readonly Close: "Close";
11
- readonly Confirm: "Confirm";
12
- readonly Destructive: "Διαγραφή";
13
- readonly OK: "OK";
14
- };
8
+ readonly Cancel: "Cancel";
9
+ readonly Close: "Close";
10
+ readonly Confirm: "Confirm";
11
+ readonly Destructive: "Διαγραφή";
12
+ readonly OK: "OK";
15
13
  };
16
14
  };
17
15
  export default _default;
@@ -6,12 +6,10 @@ export default defineTranslations(() => ({
6
6
  Description: 'Ελέγξτε την ορθογραφία ή δοκιμάστε μια νέα αναζήτηση.',
7
7
  },
8
8
  ButtonRole: {
9
- Default: {
10
- Cancel: 'Cancel',
11
- Close: 'Close',
12
- Confirm: 'Confirm',
13
- Destructive: 'Διαγραφή',
14
- OK: 'OK',
15
- },
9
+ Cancel: 'Cancel',
10
+ Close: 'Close',
11
+ Confirm: 'Confirm',
12
+ Destructive: 'Διαγραφή',
13
+ OK: 'OK',
16
14
  },
17
15
  }));
@@ -5,13 +5,11 @@ declare const _default: () => {
5
5
  readonly Description: "Check the spelling or try a new search.";
6
6
  };
7
7
  readonly ButtonRole: {
8
- readonly Default: {
9
- readonly Cancel: "Cancel";
10
- readonly Close: "Close";
11
- readonly Confirm: "Confirm";
12
- readonly Destructive: "Delete";
13
- readonly OK: "OK";
14
- };
8
+ readonly Cancel: "Cancel";
9
+ readonly Close: "Close";
10
+ readonly Confirm: "Confirm";
11
+ readonly Destructive: "Delete";
12
+ readonly OK: "OK";
15
13
  };
16
14
  };
17
15
  export default _default;
@@ -6,12 +6,10 @@ export default defineTranslations(() => ({
6
6
  Description: 'Check the spelling or try a new search.',
7
7
  },
8
8
  ButtonRole: {
9
- Default: {
10
- Cancel: 'Cancel',
11
- Close: 'Close',
12
- Confirm: 'Confirm',
13
- Destructive: 'Delete',
14
- OK: 'OK',
15
- },
9
+ Cancel: 'Cancel',
10
+ Close: 'Close',
11
+ Confirm: 'Confirm',
12
+ Destructive: 'Delete',
13
+ OK: 'OK',
16
14
  },
17
15
  }));
@@ -1 +1 @@
1
- export default function (target: HTMLElement, role: string | null): void;
1
+ export default function (target: HTMLElement, role: string | null, titleKey?: string | null): void;
@@ -3,41 +3,53 @@ import { Snapshot } from '../../snapshot';
3
3
  import { CleanupRegistry } from '../class/cleanup-registry';
4
4
  import { default as $ } from './cash';
5
5
  import onoff from './onoff';
6
- function renderPlaceholder(el, role) {
7
- const label = el.querySelector(':scope>[slot=placeholder]') ?? el.appendChild($(`<label-view slot="placeholder"></label-view>`, '>1'));
8
- switch (role) {
9
- case 'cancel':
10
- label.setAttribute('title', I18n.t('ButtonRole').Default.Cancel);
11
- label.setAttribute('system-image', Snapshot.config['cancel-button-icon']);
12
- break;
13
- case 'close':
14
- label.setAttribute('title', I18n.t('ButtonRole').Default.Close);
15
- label.setAttribute('system-image', Snapshot.config['close-button-icon']);
16
- break;
17
- case 'confirm':
18
- label.setAttribute('title', I18n.t('ButtonRole').Default.Confirm);
19
- label.setAttribute('system-image', Snapshot.config['confirm-button-icon']);
20
- break;
21
- case 'confirmation-action':
22
- label.setAttribute('title', I18n.t('ButtonRole').Default.Confirm);
23
- label.setAttribute('system-image', Snapshot.config['confirm-button-icon']);
24
- break;
25
- case 'destructive':
26
- label.setAttribute('title', I18n.t('ButtonRole').Default.Destructive);
27
- label.setAttribute('system-image', Snapshot.config['delete-button-icon']);
28
- break;
29
- default:
30
- label?.remove();
31
- break;
32
- }
33
- // if (role) {
34
- // label.setAttribute('title', I18n.t('ButtonRole').Default.Destructive)
35
- // } else label?.remove()
6
+ function renderPlaceholder(el, role, titleKey) {
7
+ if (!el.isConnected)
8
+ return;
9
+ self.requestAnimationFrame(() => {
10
+ if (!el.isConnected)
11
+ return;
12
+ const label = el.querySelector(':scope>[slot=placeholder]') ?? el.appendChild($(`<label-view slot="placeholder"></label-view>`, '>1'));
13
+ switch (role) {
14
+ case 'cancel':
15
+ label.setAttribute('title', titleKey && titleKey in I18n.t('ButtonRole') ? I18n.t('ButtonRole')[titleKey] : I18n.t('ButtonRole').Cancel);
16
+ label.setAttribute('system-image', Snapshot.config['cancel-button-icon']);
17
+ break;
18
+ case 'close':
19
+ if (label.closest('[is=alert-dialog]')) {
20
+ label.setAttribute('title', titleKey && titleKey in I18n.t('ButtonRole') ? I18n.t('ButtonRole')[titleKey] : I18n.t('ButtonRole').OK);
21
+ }
22
+ else {
23
+ label.setAttribute('title', titleKey && titleKey in I18n.t('ButtonRole') ? I18n.t('ButtonRole')[titleKey] : I18n.t('ButtonRole').Close);
24
+ label.setAttribute('system-image', Snapshot.config['close-button-icon']);
25
+ }
26
+ break;
27
+ case 'confirm':
28
+ label.setAttribute('title', titleKey && titleKey in I18n.t('ButtonRole') ? I18n.t('ButtonRole')[titleKey] : I18n.t('ButtonRole').Confirm);
29
+ label.setAttribute('system-image', Snapshot.config['confirm-button-icon']);
30
+ break;
31
+ case 'confirmation-action':
32
+ label.setAttribute('title', titleKey && titleKey in I18n.t('ButtonRole') ? I18n.t('ButtonRole')[titleKey] : I18n.t('ButtonRole').Confirm);
33
+ label.setAttribute('system-image', Snapshot.config['confirm-button-icon']);
34
+ break;
35
+ case 'destructive':
36
+ label.setAttribute('title', titleKey && titleKey in I18n.t('ButtonRole') ? I18n.t('ButtonRole')[titleKey] : I18n.t('ButtonRole').Destructive);
37
+ label.setAttribute('system-image', Snapshot.config['delete-button-icon']);
38
+ break;
39
+ default:
40
+ label?.remove();
41
+ break;
42
+ }
43
+ // if (role) {
44
+ // label.setAttribute('title', I18n.t('ButtonRole').Default.Destructive)
45
+ // } else label?.remove()
46
+ });
36
47
  }
37
- export default function (target, role) {
38
- renderPlaceholder(target, role);
48
+ export default function (target, role, titleKey) {
49
+ const overiderTitle = typeof titleKey === 'string' && titleKey in I18n.t('ButtonRole') ? titleKey : undefined;
50
+ renderPlaceholder(target, role, overiderTitle);
39
51
  CleanupRegistry.unregister(target, 'i18n');
40
52
  CleanupRegistry.register(target, onoff('localechange', () => {
41
- renderPlaceholder(target, role);
53
+ renderPlaceholder(target, role, overiderTitle);
42
54
  }, I18n.on).on(), 'i18n');
43
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swiftwc/ui",
3
- "version": "0.0.0-dev.25",
3
+ "version": "0.0.0-dev.27",
4
4
  "description": "Elegant SwiftUI-inspired web components for standalone web apps and web extensions.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -8,7 +8,7 @@
8
8
 
9
9
  @forward 'transitions/bwd.navbar';
10
10
 
11
- @forward 'transitions/dialog';
11
+ @forward 'transitions/sheet-view';
12
12
 
13
13
  @forward 'transitions/fine-tooltip';
14
14
 
@@ -174,7 +174,7 @@
174
174
  --toolbar-cell-block-padding-start: 0.25rem;
175
175
  --toolbar-cell-block-padding-end: 0.25rem;
176
176
  --toolbar-cell-border-radius: var(--pill-border-radius);
177
- --toolbar-cell-min-size: 2.8rem;
177
+ --toolbar-cell-min-size: 2.9rem;
178
178
 
179
179
  --toolbar-cell-focus-bg: var(--control-clear-glass-focus-bg); //oklch(0 0 0 / 0%);
180
180
  --toolbar-cell-focus-bg-dark: var(--control-clear-glass-focus-bg-dark); //oklch(0 0 0 / 0%);
@@ -517,12 +517,23 @@ $colors: map.merge(
517
517
  // }
518
518
  }
519
519
 
520
- :where(&[tint], [tint] &) {
521
- // --toolbaritemtext: oklch(from var(--accentColor) clamp(0, (0.7 - l) * 999, 1) none none);
522
- // --toolbaritemhighlighttext: oklch(from var(--accentColor) clamp(0, (0.7 - l) * 999, 1) none none);
523
- // --toolbaritemactivetext: oklch(from var(--accentColor) clamp(0, (0.7 - l) * 999, 1) none none);
520
+ &[tint],
521
+ [tint] & {
522
+ :where(&) {
523
+ // --toolbaritemtext: oklch(from var(--accentColor) clamp(0, (0.7 - l) * 999, 1) none none);
524
+ // --toolbaritemhighlighttext: oklch(from var(--accentColor) clamp(0, (0.7 - l) * 999, 1) none none);
525
+ // --toolbaritemactivetext: oklch(from var(--accentColor) clamp(0, (0.7 - l) * 999, 1) none none);
526
+
527
+ @include mixins.wire-tinted-glass(toolbaritem);
524
528
 
525
- @include mixins.wire-tinted-glass(toolbaritem);
529
+ > button {
530
+ --secondary: var(--btntext);
531
+ --blue: var(--btntext);
532
+
533
+ --accentColorEffective: var(--btntext);
534
+ --accentColor: var(--btntext);
535
+ }
536
+ }
526
537
  }
527
538
  }
528
539
 
@@ -6,6 +6,8 @@
6
6
  :where(&) {
7
7
  @include mixins.reset-dialog;
8
8
 
9
+ @include mixins.make-backdrop-transitionable;
10
+
9
11
  color: var(--text,);
10
12
 
11
13
  touch-action: none;
@@ -43,6 +45,8 @@
43
45
 
44
46
  &[open] {
45
47
  :where(&) {
48
+ @include mixins.add-dialog-backdrop-transition-frames(var(--view-transition-dialog-onscreen-backdrop-bg));
49
+
46
50
  --alert--dialog-scale: scale(1);
47
51
  --alert--dialog-opacity: 1;
48
52
 
@@ -55,6 +59,8 @@
55
59
 
56
60
  &[closing] {
57
61
  :where(&) {
62
+ @include mixins.add-dialog-backdrop-transition-frames(var(--clear));
63
+
58
64
  --alert--dialog-scale: scale(0.98);
59
65
  --alert--dialog-opacity: 0;
60
66
  }
@@ -12,9 +12,12 @@
12
12
 
13
13
  position: fixed;
14
14
 
15
- inline-size: fit-content;
16
- block-size: fit-content;
15
+ inline-size: max-content;
16
+ block-size: max-content;
17
17
  height: auto; // safari
18
+
19
+ min-inline-size: min(20rem, 80svw);
20
+
18
21
  max-inline-size: var(--confirmation--dialog-max-inline-size,);
19
22
  max-block-size: var(--confirmation--dialog-max-block-size,);
20
23
 
@@ -41,7 +41,7 @@
41
41
  }
42
42
 
43
43
  @layer #{vars.$colors-layer} {
44
- [is='bordered-prominent-button'] {
44
+ [is='glass-prominent-button'] {
45
45
  --secondary: var(--btntext);
46
46
  --blue: var(--btntext);
47
47
  }
@@ -40,10 +40,9 @@
40
40
  :where(&:has([disabled])) {
41
41
  pointer-events: none;
42
42
  }
43
- }
44
43
 
45
- // NOTE: MUST be right-after the above `all: unset` in this SAME page!
46
- tool-bar-item {
44
+ // NOTE: MUST be right-after the above `all: unset` in this SAME page!
45
+
47
46
  :where(& > button),
48
47
  :where(& > picker-view > menu-view)::part(menu-summary),
49
48
  :where(& > menu-view)::part(menu-summary) {
@@ -54,6 +53,18 @@
54
53
 
55
54
  > button {
56
55
  @include mixins.takeover-button-slots;
56
+
57
+ // [tint] &,
58
+ // &[tint] {
59
+ // :where(&) {
60
+ // // NOTE: Make everything inside prominent buttons white
61
+ // --secondary: var(--btntext);
62
+ // --blue: var(--btntext);
63
+
64
+ // --accentColorEffective: var(--btntext);
65
+ // --accentColor: var(--btntext);
66
+ // }
67
+ // }
57
68
  }
58
69
 
59
70
  // NOTE: add paddings to labels w/ text in toolbar items
@@ -75,86 +86,9 @@
75
86
  // }
76
87
  // }
77
88
  }
78
-
79
- // tool-bar-item[slot],
80
- // tool-bar-item-group {
81
- // @media (prefers-reduced-motion: no-preference) {
82
- // transition:
83
- // display var(--menu-animation-duration) allow-discrete ease-out,
84
- // overlay var(--menu-animation-duration) allow-discrete ease-out,
85
- // transform var(--menu-animation-duration) allow-discrete ease-out;
86
- // will-change: transform, overlay, display;
87
- // }
88
- // }
89
-
90
- // tool-bar-item {
91
- // min-height: var(--toolbar-cell-min-size);
92
- // min-width: var(--toolbar-cell-min-size);
93
- // }
94
89
  }
95
90
 
96
- // @layer #{vars.$colors-layer} {
97
- // sidebar-toggle > button,
98
- // tool-bar-item > button,
99
- // tool-bar-item > input,
100
- // [is='tab-item'],
101
- // // list-view > button,
102
- // menu-view > button,
103
- // [is='disclosure-group'] > button,
104
- // [is='disclosure-group'] > summary {
105
- // &:not(:disabled):not([readonly]) {
106
- // :where(&) {
107
- // @include mixins.add-focus-visible-state {
108
- // --toolbaritemface: light-dark(var(--toolbar-cell-focus-bg), var(--toolbar-cell-focus-bg-dark));
109
- // }
110
- // }
111
- // }
112
- // }
113
-
114
- // menu-view {
115
- // @include mixins.add-focus-visible-state('::part(menu-summary)') {
116
- // --toolbaritemface: var(--toolbaritemhighlightface,); //light-dark(var(--toolbar-cell-focus-bg), var(--toolbar-cell-focus-bg-dark));
117
- // }
118
- // @include mixins.add-hover-state('::part(menu-summary)') {
119
- // --toolbaritemface: var(--toolbaritemhighlightface,); //light-dark(var(--toolbar-cell-focus-bg), var(--toolbar-cell-focus-bg-dark));
120
- // }
121
- // }
122
-
123
- // list-view > button,
124
- // [is='form-view'] > button {
125
- // &:not(:disabled):not([readonly]) {
126
- // :where(&) {
127
- // --toolbaritempadistart: 0.3rem;
128
- // --toolbaritempadbstart: 0.3rem;
129
- // }
130
- // }
131
- // }
132
- // }
133
-
134
91
  @layer #{vars.$ui-layer} {
135
- // sidebar-toggle > button,
136
- // tool-bar-item > button,
137
- // tool-bar-item > input,
138
- // [is='tab-item'],
139
- // // list-view > button,
140
- // menu-view > button,
141
- // [is='disclosure-group'] > summary,
142
- // [is='disclosure-group'] > button {
143
- // // &:not(:disabled):not([readonly]) {
144
- // // :where(&) {
145
- // @include mixins.add-active-state {
146
- // --toolbaritemface: light-dark(var(--toolbar-cell-active-bg), var(--toolbar-cell-active-bg-dark));
147
- // }
148
- // // }
149
- // // }
150
- // }
151
-
152
- // menu-view {
153
- // @include mixins.add-active-state('::part(menu-summary)') {
154
- // --toolbaritemface: var(--toolbaritemactiveface,); //light-dark(var(--toolbar-cell-active-bg), var(--toolbar-cell-active-bg-dark));
155
- // }
156
- // }
157
-
158
92
  :where(tool-bar-item[slot]:has(menu-view[open])),
159
93
  :where(tool-bar-item-group:has(> tool-bar-item menu-view[open])) {
160
94
  --toolbar-cell-scale: var(--menu-host-offscreen-transform);
@@ -5,14 +5,13 @@
5
5
  @media (prefers-reduced-motion: no-preference) {
6
6
  [is='alert-dialog'] {
7
7
  :where(&) {
8
- // transition:
9
- // block-size var(--menu-animation-duration) allow-discrete ease-out,
10
- // inline-size var(--menu-animation-duration) allow-discrete ease-out,
11
- // display var(--menu-animation-duration) allow-discrete ease-out,
12
- // overlay var(--menu-animation-duration) allow-discrete ease-out,
13
- // transform var(--menu-animation-duration) allow-discrete ease-out;
14
- transition: all var(--touchglass-transition-duration) allow-discrete ease-out;
15
- // will-change: block-size, inline-size, transform, overlay, display;
8
+ transition:
9
+ display var(--touchglass-transition-duration) allow-discrete ease-out,
10
+ overlay var(--touchglass-transition-duration) allow-discrete ease-out,
11
+ transform var(--touchglass-transition-duration) allow-discrete ease-out,
12
+ opacity var(--touchglass-transition-duration) allow-discrete ease-out;
13
+ // transition: all var(--touchglass-transition-duration) allow-discrete ease-out;
14
+ will-change: transform, overlay, display, opacity;
16
15
  }
17
16
  }
18
17
  }
@@ -0,0 +1,30 @@
1
+ @use '../vars';
2
+ @use '../mixins';
3
+
4
+ @layer #{vars.$transitions-layer} {
5
+ [is='sheet-view'] {
6
+ &:not([open]) {
7
+ z-index: var(--top-layer-polyfill-z-index);
8
+ }
9
+
10
+ &[open] {
11
+ --sheet-view-translate: translateY(var(--view-transition-dialog-onscreen-y));
12
+
13
+ @include mixins.if-ipad-sheet-fits {
14
+ @include mixins.if-2col-split-view-fits {
15
+ navigation-split-view & {
16
+ margin-inline-start: var(--safe-area-inset-left);
17
+ }
18
+ }
19
+ }
20
+
21
+ @include mixins.add-dialog-backdrop-transition-frames(var(--view-transition-dialog-onscreen-backdrop-bg));
22
+
23
+ @starting-style {
24
+ & {
25
+ --sheet-view-translate: translateY(var(--view-transition-dialog-offscreen-y));
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
@@ -13,6 +13,9 @@
13
13
  "attributes": [
14
14
  {
15
15
  "name": "role"
16
+ },
17
+ {
18
+ "name": "title-key"
16
19
  }
17
20
  ]
18
21
  },
@@ -22,6 +25,9 @@
22
25
  "attributes": [
23
26
  {
24
27
  "name": "role"
28
+ },
29
+ {
30
+ "name": "title-key"
25
31
  }
26
32
  ]
27
33
  },
@@ -31,6 +37,9 @@
31
37
  "attributes": [
32
38
  {
33
39
  "name": "role"
40
+ },
41
+ {
42
+ "name": "title-key"
34
43
  }
35
44
  ]
36
45
  },
@@ -116,6 +125,9 @@
116
125
  "attributes": [
117
126
  {
118
127
  "name": "role"
128
+ },
129
+ {
130
+ "name": "title-key"
119
131
  }
120
132
  ]
121
133
  },
@@ -125,6 +137,9 @@
125
137
  "attributes": [
126
138
  {
127
139
  "name": "role"
140
+ },
141
+ {
142
+ "name": "title-key"
128
143
  }
129
144
  ]
130
145
  },
@@ -322,6 +337,9 @@
322
337
  },
323
338
  {
324
339
  "name": "data-previous-slot"
340
+ },
341
+ {
342
+ "name": "title-key"
325
343
  }
326
344
  ]
327
345
  },
@@ -1,28 +0,0 @@
1
- @use '../vars';
2
- @use '../mixins';
3
-
4
- @layer #{vars.$transitions-layer} {
5
- [is='sheet-view']:not([open]) {
6
- z-index: var(--top-layer-polyfill-z-index);
7
- }
8
-
9
- [is='sheet-view'][open] {
10
- --sheet-view-translate: translateY(var(--view-transition-dialog-onscreen-y));
11
-
12
- @include mixins.if-ipad-sheet-fits {
13
- @include mixins.if-2col-split-view-fits {
14
- navigation-split-view & {
15
- margin-inline-start: var(--safe-area-inset-left);
16
- }
17
- }
18
- }
19
-
20
- @include mixins.add-dialog-backdrop-transition-frames(var(--view-transition-dialog-onscreen-backdrop-bg));
21
-
22
- @starting-style {
23
- & {
24
- --sheet-view-translate: translateY(var(--view-transition-dialog-offscreen-y));
25
- }
26
- }
27
- }
28
- }