@swiftwc/ui 0.0.0-dev.8 → 0.0.0-dev.81

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 (243) 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 +21 -10
  10. package/generated/client/index.js +177 -194
  11. package/generated/components/alert-dialog.d.ts +8 -0
  12. package/generated/components/alert-dialog.js +99 -0
  13. package/generated/components/body-view.js +5 -2
  14. package/generated/components/bordered-button.d.ts +10 -0
  15. package/generated/components/bordered-button.js +39 -3
  16. package/generated/components/bordered-prominent-button.d.ts +10 -0
  17. package/generated/components/bordered-prominent-button.js +39 -3
  18. package/generated/components/borderless-button.d.ts +9 -1
  19. package/generated/components/borderless-button.js +32 -11
  20. package/generated/components/color-scheme.d.ts +7 -0
  21. package/generated/components/color-scheme.js +54 -0
  22. package/generated/components/confirmation-dialog.d.ts +1 -1
  23. package/generated/components/confirmation-dialog.js +43 -32
  24. package/generated/components/content-unavailable-view.d.ts +24 -0
  25. package/generated/components/content-unavailable-view.js +81 -0
  26. package/generated/components/date-picker.d.ts +2 -12
  27. package/generated/components/date-picker.js +96 -65
  28. package/generated/components/disclosure-group.d.ts +5 -0
  29. package/generated/components/disclosure-group.js +18 -7
  30. package/generated/components/fine-tooltip.d.ts +7 -0
  31. package/generated/components/fine-tooltip.js +107 -0
  32. package/generated/components/form-view.d.ts +3 -0
  33. package/generated/components/form-view.js +8 -3
  34. package/generated/components/glass-button.d.ts +10 -0
  35. package/generated/components/glass-button.js +39 -3
  36. package/generated/components/glass-prominent-button.d.ts +10 -0
  37. package/generated/components/glass-prominent-button.js +39 -3
  38. package/generated/components/h-stack.d.ts +14 -0
  39. package/generated/components/h-stack.js +23 -0
  40. package/generated/components/image-view.d.ts +9 -0
  41. package/generated/components/image-view.js +64 -0
  42. package/generated/components/index.d.ts +11 -3
  43. package/generated/components/index.js +11 -3
  44. package/generated/components/label-view.d.ts +6 -1
  45. package/generated/components/label-view.js +40 -60
  46. package/generated/components/labeled-content.d.ts +9 -0
  47. package/generated/components/labeled-content.js +116 -0
  48. package/generated/components/list-view.d.ts +3 -0
  49. package/generated/components/list-view.js +20 -17
  50. package/generated/components/menu-view.d.ts +4 -1
  51. package/generated/components/menu-view.js +60 -51
  52. package/generated/components/navigation-large-title.js +9 -5
  53. package/generated/components/navigation-split-view.d.ts +4 -1
  54. package/generated/components/navigation-split-view.js +13 -6
  55. package/generated/components/navigation-stack.d.ts +4 -1
  56. package/generated/components/navigation-stack.js +16 -9
  57. package/generated/components/navigation-title.d.ts +1 -1
  58. package/generated/components/navigation-title.js +58 -55
  59. package/generated/components/picker-view.d.ts +32 -4
  60. package/generated/components/picker-view.js +924 -234
  61. package/generated/components/plain-button.js +5 -3
  62. package/generated/components/progress-view.d.ts +13 -0
  63. package/generated/components/progress-view.js +120 -0
  64. package/generated/components/screen-view.js +3 -1
  65. package/generated/components/scroll-view-proxy.d.ts +8 -0
  66. package/generated/components/scroll-view-proxy.js +17 -0
  67. package/generated/components/scroll-view.d.ts +1 -1
  68. package/generated/components/scroll-view.js +101 -85
  69. package/generated/components/search-view.d.ts +7 -0
  70. package/generated/components/search-view.js +30 -0
  71. package/generated/components/section-view.d.ts +1 -1
  72. package/generated/components/section-view.js +35 -30
  73. package/generated/components/sheet-view.d.ts +1 -2
  74. package/generated/components/sheet-view.js +32 -39
  75. package/generated/components/sidebar-toggle.js +44 -66
  76. package/generated/components/sidebar-view.js +13 -8
  77. package/generated/components/sticky-container.js +8 -4
  78. package/generated/components/tab-bar.d.ts +3 -0
  79. package/generated/components/tab-bar.js +20 -10
  80. package/generated/components/tab-item.js +24 -13
  81. package/generated/components/tab-view.js +25 -17
  82. package/generated/components/table-view.d.ts +5 -0
  83. package/generated/components/table-view.js +55 -77
  84. package/generated/components/text-field.d.ts +2 -2
  85. package/generated/components/text-field.js +95 -88
  86. package/generated/components/toggle-view.d.ts +28 -0
  87. package/generated/components/toggle-view.js +224 -0
  88. package/generated/components/tool-bar-item-group.js +21 -4
  89. package/generated/components/tool-bar-item.d.ts +4 -1
  90. package/generated/components/tool-bar-item.js +57 -10
  91. package/generated/components/tool-bar.d.ts +12 -0
  92. package/generated/components/tool-bar.js +27 -11
  93. package/generated/components/v-keyboard.d.ts +3 -1
  94. package/generated/components/v-keyboard.js +12 -6
  95. package/generated/components/v-stack.d.ts +12 -0
  96. package/generated/components/v-stack.js +17 -2
  97. package/generated/css/index.css +2533 -941
  98. package/generated/events/alert-dialog.d.ts +8 -0
  99. package/generated/events/alert-dialog.js +1 -0
  100. package/generated/events/confirmation-dialog.d.ts +2 -2
  101. package/generated/events/index.d.ts +2 -0
  102. package/generated/events/index.js +2 -0
  103. package/generated/events/picker-view.d.ts +7 -0
  104. package/generated/events/scroll-view.js +4 -0
  105. package/generated/events/tab-view.d.ts +6 -2
  106. package/generated/events/text-field.js +3 -0
  107. package/generated/events/toggle-view.d.ts +9 -0
  108. package/generated/events/toggle-view.js +4 -0
  109. package/generated/i18n/index.d.ts +20 -10
  110. package/generated/i18n/index.js +82 -54
  111. package/generated/i18n/locales/el.d.ts +16 -0
  112. package/generated/i18n/locales/el.js +16 -0
  113. package/generated/i18n/locales/en.d.ts +16 -0
  114. package/generated/i18n/locales/en.js +16 -0
  115. package/generated/i18n/locales/index.d.ts +4 -0
  116. package/generated/i18n/locales/index.js +4 -0
  117. package/generated/internal/class/css-style-observer.js +3 -2
  118. package/generated/internal/class/form-associated-base.d.ts +0 -4
  119. package/generated/internal/class/form-associated-base.js +23 -38
  120. package/generated/internal/class/mutation-observer-set.d.ts +9 -0
  121. package/generated/internal/class/mutation-observer-set.js +42 -0
  122. package/generated/internal/class/mutation-observer-singleton.js +18 -0
  123. package/generated/internal/class/navigation-view.d.ts +1 -1
  124. package/generated/internal/class/navigation-view.js +38 -43
  125. package/generated/internal/decorators/adaptive-slot.d.ts +1 -0
  126. package/generated/internal/decorators/adaptive-slot.js +50 -0
  127. package/generated/internal/decorators/custom-element.d.ts +1 -1
  128. package/generated/internal/decorators/custom-element.js +2 -1
  129. package/generated/internal/decorators/index.d.ts +6 -0
  130. package/generated/internal/decorators/index.js +6 -0
  131. package/generated/internal/decorators/microtask-on-connected.d.ts +39 -0
  132. package/generated/internal/decorators/microtask-on-connected.js +67 -0
  133. package/generated/internal/privateNamespace.d.ts +10 -0
  134. package/generated/internal/privateNamespace.js +168 -1
  135. package/generated/internal/utils/cash/index.d.ts +4 -3
  136. package/generated/internal/utils/cash/index.js +6 -4
  137. package/generated/internal/utils/dev-flags.d.ts +3 -0
  138. package/generated/internal/utils/dev-flags.js +5 -0
  139. package/generated/internal/utils/ensure-placeholder.d.ts +1 -0
  140. package/generated/internal/utils/ensure-placeholder.js +55 -0
  141. package/generated/internal/utils/index.d.ts +7 -2
  142. package/generated/internal/utils/index.js +9 -2
  143. package/generated/internal/utils/is-inside.d.ts +1 -0
  144. package/generated/internal/utils/is-inside.js +4 -0
  145. package/generated/internal/utils/list-active.js +67 -12
  146. package/generated/internal/utils/render-label-icon.d.ts +2 -0
  147. package/generated/internal/utils/render-label-icon.js +19 -0
  148. package/generated/internal/utils/render-label-title.d.ts +2 -0
  149. package/generated/internal/utils/render-label-title.js +16 -0
  150. package/generated/internal/utils/render-label.d.ts +1 -0
  151. package/generated/internal/utils/render-label.js +19 -0
  152. package/generated/internal/utils/touch-glass.js +5 -5
  153. package/generated/namespace-browser/base.d.ts +12 -3
  154. package/generated/namespace-browser/base.js +41 -18
  155. package/generated/namespace-browser/event.d.ts +10 -0
  156. package/generated/namespace-browser/event.js +1 -0
  157. package/generated/snapshot/index.d.ts +3 -1
  158. package/generated/snapshot/index.js +25 -2
  159. package/generated/tpl/html.d.ts +5 -0
  160. package/generated/tpl/html.js +3 -0
  161. package/generated/tpl/index.d.ts +4 -0
  162. package/generated/tpl/index.js +4 -0
  163. package/generated/tpl/render.d.ts +2 -0
  164. package/generated/tpl/render.js +132 -0
  165. package/package.json +18 -4
  166. package/scss/_components.scss +14 -0
  167. package/scss/_functions.scss +10 -0
  168. package/scss/_mixins.scss +4 -0
  169. package/scss/_transitions.scss +6 -1
  170. package/scss/_vars.scss +9 -2
  171. package/scss/base/_layout.scss +17 -7
  172. package/scss/base/_reboot.scss +34 -1
  173. package/scss/base/_root.scss +117 -114
  174. package/scss/colors/_index.scss +304 -85
  175. package/scss/components/_alert-dialog.scss +111 -0
  176. package/scss/components/_bordered-button.scss +35 -0
  177. package/scss/components/_bordered-prominent-button.scss +45 -0
  178. package/scss/components/_borderless-button.scss +25 -0
  179. package/scss/components/_confirmation-dialog.scss +41 -49
  180. package/scss/components/_content-unavailable-view.scss +56 -0
  181. package/scss/components/_date-picker.scss +15 -15
  182. package/scss/components/_detail-placeholder.scss +1 -3
  183. package/scss/components/_disclosure-group.scss +84 -33
  184. package/scss/components/_fine-tooltip.scss +84 -0
  185. package/scss/components/_form-view.scss +58 -20
  186. package/scss/components/_glass-button.scss +35 -0
  187. package/scss/components/_glass-prominent-button.scss +46 -0
  188. package/scss/components/_group-box.scss +27 -0
  189. package/scss/components/_h-flex-stack.scss +23 -0
  190. package/scss/components/_h-stack.scss +21 -15
  191. package/scss/components/_image-view.scss +20 -0
  192. package/scss/components/_index.scss +40 -20
  193. package/scss/components/_label-view copy.scss.txt +420 -0
  194. package/scss/components/_label-view.scss +94 -110
  195. package/scss/components/_label-view.scss.txt +536 -0
  196. package/scss/components/_labeled-content.scss +59 -1
  197. package/scss/components/_list-view.scss +65 -25
  198. package/scss/components/_menu-view.scss +95 -60
  199. package/scss/components/_navigation-large-title.scss +17 -0
  200. package/scss/components/_navigation-split-view.scss +3 -3
  201. package/scss/components/_picker-view.scss +259 -59
  202. package/scss/components/_plain-button.scss +7 -0
  203. package/scss/components/_progress-view.scss +98 -0
  204. package/scss/components/_scroll-view-proxy.scss +22 -20
  205. package/scss/components/_scroll-view.scss +4 -0
  206. package/scss/components/_search-view.scss +22 -0
  207. package/scss/components/_section-view.scss +23 -22
  208. package/scss/components/_sheet-view.scss +16 -6
  209. package/scss/components/_sidebar-toggle.scss +1 -4
  210. package/scss/components/_sticky-container.scss +1 -1
  211. package/scss/components/_tab-bar.scss +17 -3
  212. package/scss/components/_tab-view.scss +4 -2
  213. package/scss/components/_table-column.scss +2 -0
  214. package/scss/components/_table-row.scss +69 -1
  215. package/scss/components/_table-view.scss +22 -14
  216. package/scss/components/_text-field.scss +37 -17
  217. package/scss/components/_toggle-view.scss +112 -0
  218. package/scss/components/_tool-bar-item.scss +34 -82
  219. package/scss/components/_tool-bar.scss +77 -57
  220. package/scss/components/_v-stack.scss +9 -2
  221. package/scss/final/_touch-glass.scss +24 -0
  222. package/scss/mixins/_button.scss +44 -0
  223. package/scss/mixins/_color.scss +16 -0
  224. package/scss/mixins/_dialog.scss +1 -0
  225. package/scss/mixins/_index.scss +64 -2
  226. package/scss/placeholders/_buttons.scss +44 -10
  227. package/scss/placeholders/_lists.scss +133 -126
  228. package/scss/transitions/_alert-dialog.scss +18 -0
  229. package/scss/transitions/_confirmation-dialog.scss +8 -0
  230. package/scss/transitions/_fine-tooltip.scss +21 -0
  231. package/scss/transitions/_menu-view.scss +17 -15
  232. package/scss/transitions/_progress-view.scss +23 -0
  233. package/scss/transitions/_sheet-view.scss +30 -0
  234. package/scss/transitions/_tab-bar.scss +6 -5
  235. package/scss/utils/_frame.scss +42 -0
  236. package/scss/utils/_index.scss +67 -52
  237. package/scss/utils/_stacks.scss +56 -73
  238. package/web-components.html-data/en.json +623 -24
  239. package/generated/confirmation-dialog/index.d.ts +0 -1
  240. package/generated/confirmation-dialog/index.js +0 -1
  241. package/generated/lifecycle-observer/index.d.ts +0 -1
  242. package/generated/lifecycle-observer/index.js +0 -1
  243. package/scss/transitions/_dialog.scss +0 -28
@@ -1,8 +1,9 @@
1
1
  var _a;
2
2
  import { I18n } from '../i18n';
3
3
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
4
- import { FormAssociatedBase, getInternals, makeSlotchangeHandler } from '../internal/class/form-associated-base';
5
- import { $, clamp, kebabCase, onoff, set } from '../internal/utils';
4
+ import { FormAssociatedBase, getInternals } from '../internal/class/form-associated-base';
5
+ import { MutationObserverSet } from '../internal/class/mutation-observer-set';
6
+ import { $, clamp, devFlags, kebabCase, onoff, renderLabel, set } from '../internal/utils';
6
7
  const datePickerStyles = ['graphical', 'field', 'automatic'];
7
8
  export class DatePicker extends FormAssociatedBase {
8
9
  static get observedAttributes() {
@@ -24,9 +25,16 @@ export class DatePicker extends FormAssociatedBase {
24
25
  }
25
26
  static #templates = new Map();
26
27
  // #lastRenderedStyle?: DatePickerStyle //string | null
28
+ #renderValidityMsgs = (entries) => {
29
+ if (devFlags.debug)
30
+ console.debug(`${_a.name} ⚡️ mutation`);
31
+ this.setValidity(this.validity, this.validationMessage);
32
+ };
27
33
  #shadowRoot;
28
34
  #customValidity = '';
29
- #validitiesSlot;
35
+ #slots = new Map();
36
+ #validityObservers = new MutationObserverSet(this.#renderValidityMsgs);
37
+ // #validitiesSlot?: HTMLSlotElement
30
38
  #inputs = [];
31
39
  get #internals() {
32
40
  return getInternals(this);
@@ -48,7 +56,7 @@ export class DatePicker extends FormAssociatedBase {
48
56
  <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
57
  </div>
50
58
  <slot name="validity-options" hidden></slot>
51
- </label>`, ''));
59
+ </label>`));
52
60
  break;
53
61
  }
54
62
  return _a.#templates.get(this.datePickerStyle);
@@ -57,29 +65,13 @@ export class DatePicker extends FormAssociatedBase {
57
65
  super();
58
66
  this.#shadowRoot = this.attachShadow({ mode: 'closed' });
59
67
  }
60
- connectedCallback() {
61
- super.connectedCallback();
62
- CleanupRegistry.register(this, onoff('click', this.#handleClick, this).on());
63
- this.#render();
64
- CleanupRegistry.register(this, onoff('change', () => {
65
- this.#render();
66
- }, I18n.on).on());
67
- // finally
68
- if (!this.hasAttribute('selection'))
69
- return;
70
- const [y = '', m = '', d = ''] = (this.getAttribute('selection') ?? '').split(/\D+/);
71
- this.selection = { year: y, month: m, day: d };
72
- this.#sendValueToForm(false);
73
- }
74
- disconnectedCallback() {
75
- super.disconnectedCallback();
76
- }
77
68
  attributeChangedCallback(name, oldValue, newValue) {
78
- console.debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
69
+ if (devFlags.debug)
70
+ console.debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
79
71
  switch (name) {
80
72
  case 'selection':
81
- const [y = '', m = '', d = ''] = (newValue ?? '').split(/\D+/);
82
- this.selection = { year: y, month: m, day: d };
73
+ // nothing happens// const [y = '', m = '', d = ''] = (newValue ?? '').split(/\D+/)
74
+ // this.#selectedDate = { year: y, month: m, day: d }
83
75
  break;
84
76
  case 'required':
85
77
  for (const input of this.#inputs)
@@ -97,14 +89,8 @@ export class DatePicker extends FormAssociatedBase {
97
89
  input.setAttribute('placeholder', map[input.name] ?? '');
98
90
  break;
99
91
  case 'label':
100
- let label = this.querySelector(':scope>[slot=label]');
101
- if (newValue) {
102
- label ??= this.appendChild($(`<span slot="label"></span>`));
103
- label.textContent = newValue;
104
- }
105
- else
106
- label?.remove();
107
- this.#sendValueToForm();
92
+ renderLabel(':scope>label-view[slot=label]', `<label-view slot="label" foreground="secondary"><span></span></label-view>`, this, newValue);
93
+ // this.#sendValueToForm()
108
94
  break;
109
95
  case 'disabled':
110
96
  for (const input of this.#inputs)
@@ -112,22 +98,42 @@ export class DatePicker extends FormAssociatedBase {
112
98
  break;
113
99
  }
114
100
  }
101
+ disconnectedCallback() {
102
+ super.disconnectedCallback();
103
+ this.#validityObservers.unobserveAll();
104
+ }
105
+ connectedCallback() {
106
+ super.connectedCallback();
107
+ CleanupRegistry.register(this, onoff('click', this.#handleClick, this).on());
108
+ this.#render();
109
+ CleanupRegistry.register(this, onoff('localechange', () => {
110
+ this.#render();
111
+ }, I18n.on).on());
112
+ // finally
113
+ if (!this.hasAttribute('selection'))
114
+ return;
115
+ const [y = '', m = '', d = ''] = (this.getAttribute('selection') ?? '').split(/\D+/);
116
+ this.#selectedDate = { year: y, month: m, day: d };
117
+ this.#sendValueToForm(false);
118
+ }
115
119
  get datePickerStyle() {
116
- return datePickerStyles.includes(this.getAttribute('date-picker-style') ?? '')
117
- ? this.getAttribute('date-picker-style')
118
- : 'automatic';
120
+ return datePickerStyles.includes(this.getAttribute('date-picker-style') ?? '') ? this.getAttribute('date-picker-style') : 'automatic';
119
121
  }
120
122
  #render() {
121
- console.debug(`${_a.name} ⚡️ render (${this.datePickerStyle})`);
122
- if (!this.isConnected)
123
- return;
123
+ if (devFlags.debug)
124
+ console.debug(`${_a.name} ⚡️ render (${this.datePickerStyle})`);
124
125
  // if (this.#lastRenderedStyle === this.datePickerStyle) return // skip if already applied
125
126
  // this.#lastRenderedStyle = this.datePickerStyle
126
127
  // clear shadow DOM
127
128
  this.#shadowRoot.replaceChildren(document.importNode(this.template, true));
128
- this.#validitiesSlot = this.#shadowRoot.querySelector('slot[name=validity-options]') ?? undefined;
129
+ CleanupRegistry.unregister(this, 'slots');
130
+ for (const slot of this.#shadowRoot.querySelectorAll('slot'))
131
+ this.#slots?.set(slot.name, slot);
132
+ CleanupRegistry.register(this, () => {
133
+ this.#slots = new Map();
134
+ }, 'slots');
129
135
  CleanupRegistry.unregister(this, 'validities');
130
- CleanupRegistry.register(this, onoff(makeSlotchangeHandler(this), this.#validitiesSlot).on(), 'validities');
136
+ CleanupRegistry.register(this, onoff('slotchange', this.#handleValiditiesSlotchange, this.#slots?.get('validity-options')).on(), 'validities');
131
137
  switch (this.datePickerStyle) {
132
138
  default:
133
139
  const [yyyy = '', mm = '', dd = ''] = new Date().toISOString().split('T').shift()?.split('-') ?? [], map = { year: yyyy, month: mm, day: dd };
@@ -158,7 +164,17 @@ export class DatePicker extends FormAssociatedBase {
158
164
  break;
159
165
  }
160
166
  }
161
- get selection() {
167
+ #handleValiditiesSlotchange = ({ type, target: slot }) => {
168
+ if (devFlags.debug)
169
+ console.debug(`${_a.name} ⚡️ ${type}`);
170
+ if (!(slot instanceof HTMLSlotElement))
171
+ return;
172
+ const assigned = slot.assignedElements();
173
+ this.#validityObservers.syncObservations(assigned, ['value', 'label']);
174
+ // if (0 < assigned.length)
175
+ this.#renderValidityMsgs([]);
176
+ };
177
+ get #selectedDate() {
162
178
  const map = Object.fromEntries(this.#inputs.map(({ name, value }) => [name, value]));
163
179
  return {
164
180
  year: map.year ?? '',
@@ -166,7 +182,7 @@ export class DatePicker extends FormAssociatedBase {
166
182
  day: map.day ?? '',
167
183
  };
168
184
  }
169
- set selection(v) {
185
+ set #selectedDate(v) {
170
186
  for (const input of this.#inputs) {
171
187
  const nv = v[input.name] ?? '', pattern = /^(\d+)?$/;
172
188
  let finalValue = pattern.test(nv) ? nv : '', parsedValue = parseInt(finalValue);
@@ -178,8 +194,12 @@ export class DatePicker extends FormAssociatedBase {
178
194
  }
179
195
  }
180
196
  #handleClick = (evt) => {
181
- console.debug(`${_a.name} ⚡️ ${evt?.type}`);
182
- const input = evt.target?.closest('input');
197
+ if (devFlags.debug)
198
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
199
+ const { target } = evt;
200
+ if (!(target instanceof HTMLElement))
201
+ return;
202
+ const input = target.closest('input');
183
203
  if (input)
184
204
  return;
185
205
  this.#shadowRoot.querySelector('input.focus')?.focus?.();
@@ -210,7 +230,7 @@ export class DatePicker extends FormAssociatedBase {
210
230
  else
211
231
  this.setValidity({});
212
232
  }
213
- const selection = `${this.selection.year}-${this.selection.month}-${this.selection.day}`;
233
+ const selection = `${this.#selectedDate.year}-${this.#selectedDate.month}-${this.#selectedDate.day}`;
214
234
  const entries = new FormData();
215
235
  entries.append(this.name, selection);
216
236
  this.#internals.setFormValue(entries);
@@ -218,9 +238,10 @@ export class DatePicker extends FormAssociatedBase {
218
238
  this.dispatchEvent(new CustomEvent('selection', { detail: { selection }, bubbles: true, composed: true }));
219
239
  };
220
240
  #handleInputPaste = (evt) => {
221
- console.debug(`${_a.name} ⚡️ ${evt?.type}`);
222
- const input = evt.target;
223
- if (!input)
241
+ if (devFlags.debug)
242
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
243
+ const { target: input } = evt;
244
+ if (!(input instanceof HTMLInputElement))
224
245
  return;
225
246
  evt.preventDefault();
226
247
  const data = [...`${(evt.clipboardData?.getData('text') ?? '').trim()}`].reduce((acc, ch, i) => {
@@ -240,9 +261,10 @@ export class DatePicker extends FormAssociatedBase {
240
261
  this.#sendValueToForm();
241
262
  };
242
263
  #handleInputBeforeinput = (evt) => {
243
- console.debug(`${_a.name} ⚡️ ${evt?.type}`);
244
- const input = evt.target;
245
- if (!input)
264
+ if (devFlags.debug)
265
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
266
+ const { target: input } = evt;
267
+ if (!(input instanceof HTMLInputElement))
246
268
  return;
247
269
  if ('insertText' !== evt.inputType)
248
270
  return;
@@ -263,7 +285,10 @@ export class DatePicker extends FormAssociatedBase {
263
285
  }
264
286
  };
265
287
  #handleInputKeydown = ({ type, target, key }) => {
266
- console.debug(`${_a.name} ⚡️ ${type}`);
288
+ if (devFlags.debug)
289
+ console.debug(`${_a.name} ⚡️ ${type}`);
290
+ if (!(target instanceof HTMLInputElement))
291
+ return;
267
292
  const input = target;
268
293
  if (!input)
269
294
  return;
@@ -280,13 +305,17 @@ export class DatePicker extends FormAssociatedBase {
280
305
  this.#inputs[index]?.focus();
281
306
  };
282
307
  #handleInputFocus = (evt) => {
283
- console.debug(`${_a.name} ⚡️ ${evt?.type}`);
308
+ if (devFlags.debug)
309
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
284
310
  for (const input of this.#inputs)
285
311
  input.classList.toggle('focus', input === evt.target);
286
312
  };
287
- #handleInputBlur = (evt) => {
288
- console.debug(`${_a.name} ⚡️ ${evt?.type}`);
289
- const input = evt.target;
313
+ #handleInputBlur = ({ target, type }) => {
314
+ if (devFlags.debug)
315
+ console.debug(`${_a.name} ⚡️ ${type}`);
316
+ if (!(target instanceof HTMLInputElement))
317
+ return;
318
+ const input = target;
290
319
  if (0 === input.value.length)
291
320
  return;
292
321
  const finalText = `${clamp(this.value[input.name] ?? '0', _a.#min(input), _a.#max(input))}`.padStart(parseInt(input.getAttribute('maxlength') ?? '0'), '0');
@@ -296,7 +325,8 @@ export class DatePicker extends FormAssociatedBase {
296
325
  this.#sendValueToForm();
297
326
  };
298
327
  #handleInputInput = (evt) => {
299
- console.debug(`${_a.name} ⚡️ ${evt?.type}`);
328
+ if (devFlags.debug)
329
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
300
330
  this.#sendValueToForm();
301
331
  };
302
332
  // Optional: form participation properties
@@ -379,16 +409,16 @@ export class DatePicker extends FormAssociatedBase {
379
409
  const key = k; // ✅ type-safe cast
380
410
  if (true !== flags[key])
381
411
  continue;
382
- for (const el of this.#validitiesSlot?.assignedElements({ flatten: true }) ?? []) {
412
+ for (const el of this.#slots?.get('validity-options')?.assignedElements({ flatten: true }) ?? []) {
383
413
  if (!el.matches('option'))
384
414
  continue;
385
- const option = el;
386
- if (`${kebabCase(key)}` === option.value) {
387
- message = option.label;
415
+ const { label, value } = el;
416
+ if (`${kebabCase(key)}` === value) {
417
+ message = label;
388
418
  break;
389
419
  }
390
- else if (`${kebabCase(key)}:${message}` === option.value) {
391
- message = option.label;
420
+ else if (`${kebabCase(key)}:${message}` === value) {
421
+ message = label;
392
422
  break;
393
423
  }
394
424
  }
@@ -401,7 +431,8 @@ export class DatePicker extends FormAssociatedBase {
401
431
  message = kebabCase(key);
402
432
  break;
403
433
  }
404
- console.debug(`${_a.name} ⚡️ validity-change`);
434
+ if (devFlags.debug)
435
+ console.debug(`${_a.name} ⚡️ validity-change`);
405
436
  return this.#internals.setValidity(flags, this.#customValidity || message, anchor ?? this.#inputs.at(0));
406
437
  };
407
438
  setCustomValidity = (message) => {
@@ -419,7 +450,7 @@ export class DatePicker extends FormAssociatedBase {
419
450
  input.toggleAttribute('disabled', !disabled);
420
451
  };
421
452
  formResetCallback = () => {
422
- this.selection = {
453
+ this.#selectedDate = {
423
454
  year: '',
424
455
  month: '',
425
456
  day: '',
@@ -1,4 +1,9 @@
1
1
  import { DetailsBase } from '../namespace-browser/base';
2
+ /**
3
+ * @summary A view that shows or hides another content view, based on the state of a disclosure control.
4
+ *
5
+ * @example <details is="disclosure-group"><summary><label-view title="Items"></label-view></summary><label-view title="Item 1"></label-view><label-view title="Item 2"></label-view><details is="disclosure-group"><summary><label-view title="Sub-items"></label-view></summary><label-view title="Sub-item 1"></label-view></details></details>
6
+ */
2
7
  export declare class DisclosureGroup extends DetailsBase {
3
8
  #private;
4
9
  static get observedAttributes(): string[];
@@ -1,7 +1,12 @@
1
1
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
2
- import { cssTime, onoff, timeout } from '../internal/utils';
2
+ import { cssTime, devFlags, onoff, timeout } from '../internal/utils';
3
3
  import { DetailsBase } from '../namespace-browser/base';
4
4
  const toggleTimers = new WeakMap();
5
+ /**
6
+ * @summary A view that shows or hides another content view, based on the state of a disclosure control.
7
+ *
8
+ * @example <details is="disclosure-group"><summary><label-view title="Items"></label-view></summary><label-view title="Item 1"></label-view><label-view title="Item 2"></label-view><details is="disclosure-group"><summary><label-view title="Sub-items"></label-view></summary><label-view title="Sub-item 1"></label-view></details></details>
9
+ */
5
10
  export class DisclosureGroup extends DetailsBase {
6
11
  static get observedAttributes() {
7
12
  return [
@@ -15,15 +20,18 @@ export class DisclosureGroup extends DetailsBase {
15
20
  super();
16
21
  }
17
22
  attributeChangedCallback(name, oldValue, newValue) {
18
- console.debug(`${DisclosureGroup.name} ⚡️ attr-change [${name}]`);
23
+ if (devFlags.debug)
24
+ console.debug(`${DisclosureGroup.name} ⚡️ attr-change [${name}]`);
19
25
  // if (CSS.supports('interpolate-size', 'allow-keywords')) return
20
26
  }
21
27
  static polyfillDisconnectedCallback(el) {
22
- console.debug(`${DisclosureGroup.name} ⚡️ disconnect`);
28
+ if (devFlags.debug)
29
+ console.debug(`${DisclosureGroup.name} ⚡️ disconnect`);
23
30
  CleanupRegistry.unregister(el);
24
31
  }
25
32
  static polyfillConnectedCallback(el) {
26
- console.debug(`${DisclosureGroup.name} ⚡️ connect`);
33
+ if (devFlags.debug)
34
+ console.debug(`${DisclosureGroup.name} ⚡️ connect`);
27
35
  const newValue = el.open ? 'open' : 'closed';
28
36
  if (newValue !== el.dataset.state)
29
37
  el.dataset.state = newValue;
@@ -33,9 +41,12 @@ export class DisclosureGroup extends DetailsBase {
33
41
  toggleTimers.delete(el);
34
42
  });
35
43
  }
36
- static #handleToggle = async (evt) => {
37
- console.debug(`${DisclosureGroup.name} ⚡️ ${evt?.type}`);
38
- const details = evt.currentTarget, newValue = details.open ? 'opening' : 'closing';
44
+ static #handleToggle = async ({ type, currentTarget: details }) => {
45
+ if (devFlags.debug)
46
+ console.debug(`${DisclosureGroup.name} ⚡️ ${type}`);
47
+ if (!(details instanceof HTMLDetailsElement))
48
+ return;
49
+ const newValue = details.open ? 'opening' : 'closing';
39
50
  if (newValue !== details.dataset.state)
40
51
  details.dataset.state = newValue;
41
52
  if (!toggleTimers.has(details))
@@ -0,0 +1,7 @@
1
+ export declare class FineTooltip extends HTMLElement {
2
+ #private;
3
+ constructor();
4
+ connectedCallback(): void;
5
+ disconnectedCallback(): void;
6
+ hidePopover(): void;
7
+ }
@@ -0,0 +1,107 @@
1
+ var _a;
2
+ import { CleanupRegistry } from '../internal/class/cleanup-registry';
3
+ import { $, devFlags, onoff } from '../internal/utils';
4
+ export class FineTooltip extends HTMLElement {
5
+ constructor() {
6
+ super();
7
+ }
8
+ #handleTriggerRemovalMutation = (mutations) => {
9
+ if (this.#queryTrigger?.isConnected)
10
+ return;
11
+ this?.remove();
12
+ };
13
+ #handleTriggerAttrMutation = (mutations) => {
14
+ for (const { target, attributeName } of mutations)
15
+ if (target instanceof HTMLElement && attributeName)
16
+ this.#render(target.getAttribute(attributeName));
17
+ };
18
+ #handleMeasure = ([{ target, borderBoxSize }]) => {
19
+ if (devFlags.debug)
20
+ console.debug(`${_a.name} ⚡️ measure`);
21
+ if (target.hasAttribute('closing'))
22
+ return;
23
+ if (!(target instanceof HTMLElement))
24
+ return;
25
+ const { top } = target.getBoundingClientRect();
26
+ const vpHeight = self.visualViewport?.height ?? 0, blockSize = borderBoxSize.at(0)?.blockSize ?? 0;
27
+ if (top > vpHeight - blockSize - 50) {
28
+ target.style.setProperty('position-area', 'top center');
29
+ target.style.setProperty('transform-origin', 'bottom');
30
+ }
31
+ };
32
+ #mutationObserver = new MutationObserver(this.#handleTriggerAttrMutation);
33
+ #mutationObserver2 = new MutationObserver(this.#handleTriggerRemovalMutation);
34
+ #resizeObserver = new ResizeObserver(this.#handleMeasure);
35
+ get #queryTrigger() {
36
+ const positionAnchor = this.style.positionAnchor;
37
+ if (!positionAnchor.startsWith('--help-'))
38
+ return;
39
+ const trigger = document.querySelector(`[style*="${CSS.escape(positionAnchor)}"][help]`);
40
+ return trigger ?? undefined;
41
+ }
42
+ #render = (str) => {
43
+ const label = this.querySelector(':scope>label-view') ?? this.appendChild($(`<label-view></label-view>`, '>1'));
44
+ if (str)
45
+ label.setAttribute('title', str);
46
+ else
47
+ label.removeAttribute('title');
48
+ };
49
+ connectedCallback() {
50
+ if (devFlags.debug)
51
+ console.debug(`${_a.name} ⚡️ connect`);
52
+ this.removeAttribute('closing');
53
+ this.popover = 'manual';
54
+ this.inert = true;
55
+ CleanupRegistry.register(this, onoff('toggle', this.#handleToggle, this).on());
56
+ CleanupRegistry.register(this, onoff('beforetoggle', this.#handleBeforetoggle, this).on());
57
+ this.showPopover();
58
+ }
59
+ disconnectedCallback() {
60
+ if (devFlags.debug)
61
+ console.debug(`${_a.name} ⚡️ disconnect`);
62
+ this.#resizeObserver.unobserve(this);
63
+ this.#mutationObserver?.disconnect();
64
+ this.#mutationObserver2?.disconnect();
65
+ this.#queryTrigger?.style.removeProperty('anchor-name');
66
+ CleanupRegistry.unregister(this);
67
+ }
68
+ #handleToggle = ({ newState }) => {
69
+ if ('closed' !== newState)
70
+ return;
71
+ this.remove();
72
+ };
73
+ #handleBeforetoggle = (evt) => {
74
+ if ('open' !== evt.newState)
75
+ return;
76
+ const trigger = this.#queryTrigger;
77
+ if (!trigger) {
78
+ evt.preventDefault();
79
+ this.remove();
80
+ return;
81
+ }
82
+ else {
83
+ this.#render(trigger.getAttribute('help'));
84
+ this.#mutationObserver.observe(trigger, {
85
+ attributes: true,
86
+ attributeFilter: ['help'],
87
+ });
88
+ this.#mutationObserver2.observe(document.body, {
89
+ childList: true,
90
+ subtree: true,
91
+ });
92
+ this.#resizeObserver.observe(this);
93
+ }
94
+ this.toggleAttribute('open', 'open' === evt.newState);
95
+ };
96
+ hidePopover() {
97
+ if (this.hasAttribute('closing'))
98
+ return;
99
+ this.setAttribute('closing', '');
100
+ Promise.allSettled(this.getAnimations().map(({ finished }) => finished)).then(() => {
101
+ if (!this.hasAttribute('closing'))
102
+ return;
103
+ this?.remove();
104
+ });
105
+ }
106
+ }
107
+ _a = FineTooltip;
@@ -1,4 +1,7 @@
1
1
  import { FormBase } from '../namespace-browser/base';
2
+ /**
3
+ * @attr {hidden} navigation-link-indicator-visibility - Hides accessories like right-arrow-chevron on NavigationLink buttons inside.
4
+ */
2
5
  export declare class FormView extends FormBase {
3
6
  constructor();
4
7
  static polyfillDisconnectedCallback(el: HTMLFormElement): void;
@@ -1,17 +1,22 @@
1
1
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
2
- import { listActive, onoff } from '../internal/utils';
2
+ import { devFlags, listActive, onoff } from '../internal/utils';
3
3
  import { FormBase } from '../namespace-browser/base';
4
+ /**
5
+ * @attr {hidden} navigation-link-indicator-visibility - Hides accessories like right-arrow-chevron on NavigationLink buttons inside.
6
+ */
4
7
  export class FormView extends FormBase {
5
8
  constructor() {
6
9
  super();
7
10
  }
8
11
  static polyfillDisconnectedCallback(el) {
9
- console.debug(`${FormView.name} ⚡️ disconnect`);
12
+ if (devFlags.debug)
13
+ console.debug(`${FormView.name} ⚡️ disconnect`);
10
14
  // finally
11
15
  CleanupRegistry.unregister(el);
12
16
  }
13
17
  static polyfillConnectedCallback(el) {
14
- console.debug(`${FormView.name} ⚡️ connect`);
18
+ if (devFlags.debug)
19
+ console.debug(`${FormView.name} ⚡️ connect`);
15
20
  if (el.closest('[is=sidebar-view],[is=tab-bar]')) {
16
21
  el.method = 'dialog';
17
22
  el.noValidate = true;
@@ -1,6 +1,16 @@
1
1
  import { ButtonBase } from '../namespace-browser/base';
2
+ /**
3
+ * @summary A button that applies glass border artwork based on the button’s context.
4
+ *
5
+ * @example <button is="glass-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button>
6
+ *
7
+ * @slot overlay
8
+ *
9
+ */
2
10
  export declare class GlassButton extends ButtonBase {
11
+ static get observedAttributes(): string[];
3
12
  constructor();
4
13
  static polyfillDisconnectedCallback(el: ButtonBase): void;
5
14
  static polyfillConnectedCallback(el: ButtonBase): void;
15
+ static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]: Pick<MutationRecord, 'attributeName' | 'oldValue' | 'target'>[]): void;
6
16
  }
@@ -1,17 +1,53 @@
1
1
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
2
- import { onoff, touchGlass } from '../internal/utils';
2
+ import { devFlags, ensurePlaceholder, onoff, touchGlass } from '../internal/utils';
3
3
  import { ButtonBase } from '../namespace-browser/base';
4
+ import { Snapshot } from '../snapshot';
5
+ /**
6
+ * @summary A button that applies glass border artwork based on the button’s context.
7
+ *
8
+ * @example <button is="glass-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button>
9
+ *
10
+ * @slot overlay
11
+ *
12
+ */
4
13
  export class GlassButton extends ButtonBase {
14
+ static get observedAttributes() {
15
+ return [
16
+ /**
17
+ * A value that describes the purpose of a button
18
+ * @type {destructive|confirm}
19
+ */
20
+ 'role',
21
+ 'title-key',
22
+ ];
23
+ }
5
24
  constructor() {
6
25
  super();
7
26
  }
8
27
  static polyfillDisconnectedCallback(el) {
9
- console.debug(`${GlassButton.name} ⚡️ disconnect`);
28
+ if (devFlags.debug)
29
+ console.debug(`${GlassButton.name} ⚡️ disconnect`);
10
30
  CleanupRegistry.unregister(el);
11
31
  }
12
32
  static polyfillConnectedCallback(el) {
13
- console.debug(`${GlassButton.name} ⚡️ connect`);
33
+ if (devFlags.debug)
34
+ console.debug(`${GlassButton.name} ⚡️ connect`);
14
35
  CleanupRegistry.register(el, onoff(touchGlass(el, (t) => t, () => true), el).on());
15
36
  el.tabIndex = 0;
16
37
  }
38
+ static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]) {
39
+ if (devFlags.debug)
40
+ console.debug(`${GlassButton.name} ⚡️ attr-change [${attributeName}] ("${oldValue}" → "${target.getAttribute(attributeName ?? '')}")`);
41
+ const node = target instanceof HTMLButtonElement;
42
+ if (!node)
43
+ return;
44
+ switch (attributeName) {
45
+ case 'title-key':
46
+ case 'role':
47
+ Snapshot.waitReady.then(() => {
48
+ ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'));
49
+ });
50
+ break;
51
+ }
52
+ }
17
53
  }
@@ -1,6 +1,16 @@
1
1
  import { ButtonBase } from '../namespace-browser/base';
2
+ /**
3
+ * @summary A button that applies prominent glass border artwork based on the button’s context.
4
+ *
5
+ * @example <button is="glass-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button>
6
+ *
7
+ * @slot overlay
8
+ *
9
+ */
2
10
  export declare class GlassProminentButton extends ButtonBase {
11
+ static get observedAttributes(): string[];
3
12
  constructor();
4
13
  static polyfillDisconnectedCallback(el: ButtonBase): void;
5
14
  static polyfillConnectedCallback(el: ButtonBase): void;
15
+ static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]: Pick<MutationRecord, 'attributeName' | 'oldValue' | 'target'>[]): void;
6
16
  }
@@ -1,17 +1,53 @@
1
1
  import { CleanupRegistry } from '../internal/class/cleanup-registry';
2
- import { onoff, touchGlass } from '../internal/utils';
2
+ import { devFlags, ensurePlaceholder, onoff, touchGlass } from '../internal/utils';
3
3
  import { ButtonBase } from '../namespace-browser/base';
4
+ import { Snapshot } from '../snapshot';
5
+ /**
6
+ * @summary A button that applies prominent glass border artwork based on the button’s context.
7
+ *
8
+ * @example <button is="glass-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button>
9
+ *
10
+ * @slot overlay
11
+ *
12
+ */
4
13
  export class GlassProminentButton extends ButtonBase {
14
+ static get observedAttributes() {
15
+ return [
16
+ /**
17
+ * A value that describes the purpose of a button
18
+ * @type {destructive|confirm}
19
+ */
20
+ 'role',
21
+ 'title-key',
22
+ ];
23
+ }
5
24
  constructor() {
6
25
  super();
7
26
  }
8
27
  static polyfillDisconnectedCallback(el) {
9
- console.debug(`${GlassProminentButton.name} ⚡️ disconnect`);
28
+ if (devFlags.debug)
29
+ console.debug(`${GlassProminentButton.name} ⚡️ disconnect`);
10
30
  CleanupRegistry.unregister(el);
11
31
  }
12
32
  static polyfillConnectedCallback(el) {
13
- console.debug(`${GlassProminentButton.name} ⚡️ connect`);
33
+ if (devFlags.debug)
34
+ console.debug(`${GlassProminentButton.name} ⚡️ connect`);
14
35
  CleanupRegistry.register(el, onoff(touchGlass(el, (t) => t, () => true), el).on());
15
36
  el.tabIndex = 0;
16
37
  }
38
+ static polyfillAttributeChangedCallback([{ attributeName, target, oldValue }]) {
39
+ if (devFlags.debug)
40
+ console.debug(`${GlassProminentButton.name} ⚡️ attr-change [${attributeName}] ("${oldValue}" → "${target.getAttribute(attributeName ?? '')}")`);
41
+ const node = target instanceof HTMLButtonElement;
42
+ if (!node)
43
+ return;
44
+ switch (attributeName) {
45
+ case 'title-key':
46
+ case 'role':
47
+ Snapshot.waitReady.then(() => {
48
+ ensurePlaceholder(target, target.getAttribute('role'), target.getAttribute('title-key'));
49
+ });
50
+ break;
51
+ }
52
+ }
17
53
  }