@swiftwc/ui 0.0.0-dev.4 → 0.0.0-dev.40

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 (314) hide show
  1. package/README.md +15 -0
  2. package/generated/buses/alert-dialog.d.ts +2 -0
  3. package/generated/buses/alert-dialog.js +1 -0
  4. package/generated/buses/confirmation-dialog.d.ts +2 -0
  5. package/generated/buses/confirmation-dialog.js +1 -0
  6. package/generated/buses/index.d.ts +6 -0
  7. package/generated/buses/index.js +6 -0
  8. package/generated/buses/lifecycle-observer.d.ts +2 -0
  9. package/generated/buses/lifecycle-observer.js +1 -0
  10. package/generated/client/index.d.ts +24 -0
  11. package/generated/client/index.js +272 -0
  12. package/generated/components/alert-dialog.d.ts +8 -0
  13. package/generated/components/alert-dialog.js +99 -0
  14. package/generated/components/body-view.d.ts +5 -0
  15. package/generated/components/body-view.js +14 -0
  16. package/generated/components/bordered-button.d.ts +13 -0
  17. package/generated/components/bordered-button.js +45 -0
  18. package/generated/components/bordered-prominent-button.d.ts +13 -0
  19. package/generated/components/bordered-prominent-button.js +45 -0
  20. package/generated/components/borderless-button.d.ts +13 -0
  21. package/generated/components/borderless-button.js +45 -0
  22. package/generated/components/confirmation-dialog.d.ts +9 -0
  23. package/generated/components/confirmation-dialog.js +113 -0
  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 +36 -0
  27. package/generated/components/date-picker.js +468 -0
  28. package/generated/components/disclosure-group.d.ts +9 -0
  29. package/generated/components/disclosure-group.js +58 -0
  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 +6 -0
  33. package/generated/components/form-view.js +60 -0
  34. package/generated/components/glass-button.d.ts +12 -0
  35. package/generated/components/glass-button.js +42 -0
  36. package/generated/components/glass-prominent-button.d.ts +12 -0
  37. package/generated/components/glass-prominent-button.js +42 -0
  38. package/generated/components/index.d.ts +42 -0
  39. package/generated/components/index.js +42 -0
  40. package/generated/components/label-view.d.ts +9 -0
  41. package/generated/components/label-view.js +59 -0
  42. package/generated/components/list-view.d.ts +5 -0
  43. package/generated/components/list-view.js +29 -0
  44. package/generated/components/menu-view.d.ts +9 -0
  45. package/generated/components/menu-view.js +145 -0
  46. package/generated/components/navigation-large-title.d.ts +6 -0
  47. package/generated/components/navigation-large-title.js +181 -0
  48. package/generated/components/navigation-split-view.d.ts +10 -0
  49. package/generated/components/navigation-split-view.js +25 -0
  50. package/generated/components/navigation-stack.d.ts +10 -0
  51. package/generated/components/navigation-stack.js +31 -0
  52. package/generated/components/navigation-title.d.ts +8 -0
  53. package/generated/components/navigation-title.js +52 -0
  54. package/generated/components/picker-view.d.ts +28 -0
  55. package/generated/components/picker-view.js +681 -0
  56. package/generated/components/plain-button.d.ts +7 -0
  57. package/generated/components/plain-button.js +22 -0
  58. package/generated/components/progress-view.d.ts +13 -0
  59. package/generated/components/progress-view.js +125 -0
  60. package/generated/components/screen-view.d.ts +5 -0
  61. package/generated/components/screen-view.js +11 -0
  62. package/generated/components/scroll-view-proxy.d.ts +8 -0
  63. package/generated/components/scroll-view-proxy.js +17 -0
  64. package/generated/components/scroll-view.d.ts +10 -0
  65. package/generated/components/scroll-view.js +202 -0
  66. package/generated/components/search-view.d.ts +8 -0
  67. package/generated/components/search-view.js +30 -0
  68. package/generated/components/section-view.d.ts +9 -0
  69. package/generated/components/section-view.js +83 -0
  70. package/generated/components/sheet-view.d.ts +8 -0
  71. package/generated/components/sheet-view.js +62 -0
  72. package/generated/components/sidebar-toggle.d.ts +7 -0
  73. package/generated/components/sidebar-toggle.js +85 -0
  74. package/generated/components/sidebar-view.d.ts +7 -0
  75. package/generated/components/sidebar-view.js +34 -0
  76. package/generated/components/sticky-container.d.ts +6 -0
  77. package/generated/components/sticky-container.js +26 -0
  78. package/generated/components/tab-bar.d.ts +10 -0
  79. package/generated/components/tab-bar.js +43 -0
  80. package/generated/components/tab-item.d.ts +7 -0
  81. package/generated/components/tab-item.js +132 -0
  82. package/generated/components/tab-view.d.ts +22 -0
  83. package/generated/components/tab-view.js +264 -0
  84. package/generated/components/table-view.d.ts +7 -0
  85. package/generated/components/table-view.js +174 -0
  86. package/generated/components/text-field.d.ts +29 -0
  87. package/generated/components/text-field.js +503 -0
  88. package/generated/components/tool-bar-item-group.d.ts +5 -0
  89. package/generated/components/tool-bar-item-group.js +28 -0
  90. package/generated/components/tool-bar-item.d.ts +8 -0
  91. package/generated/components/tool-bar-item.js +66 -0
  92. package/generated/components/tool-bar.d.ts +19 -0
  93. package/generated/components/tool-bar.js +93 -0
  94. package/generated/components/v-keyboard.d.ts +15 -0
  95. package/generated/components/v-keyboard.js +89 -0
  96. package/generated/components/v-stack.d.ts +10 -0
  97. package/generated/components/v-stack.js +19 -0
  98. package/generated/css/index.css +8089 -0
  99. package/generated/events/alert-dialog.d.ts +8 -0
  100. package/generated/events/alert-dialog.js +1 -0
  101. package/generated/events/confirmation-dialog.d.ts +9 -0
  102. package/generated/events/confirmation-dialog.js +1 -0
  103. package/generated/events/date-picker.d.ts +8 -0
  104. package/generated/events/date-picker.js +1 -0
  105. package/generated/events/index.d.ts +8 -0
  106. package/generated/events/index.js +8 -0
  107. package/generated/events/lifecycle-observer.d.ts +10 -0
  108. package/generated/events/lifecycle-observer.js +1 -0
  109. package/generated/events/picker-view.d.ts +15 -0
  110. package/generated/events/picker-view.js +1 -0
  111. package/generated/events/scroll-view.d.ts +10 -0
  112. package/generated/events/scroll-view.js +1 -0
  113. package/generated/events/tab-view.d.ts +28 -0
  114. package/generated/events/tab-view.js +1 -0
  115. package/generated/events/text-field.d.ts +8 -0
  116. package/generated/events/text-field.js +1 -0
  117. package/generated/i18n/index.d.ts +34 -0
  118. package/generated/i18n/index.js +167 -0
  119. package/generated/i18n/locales/el.d.ts +16 -0
  120. package/generated/i18n/locales/el.js +16 -0
  121. package/generated/i18n/locales/en.d.ts +16 -0
  122. package/generated/i18n/locales/en.js +16 -0
  123. package/generated/i18n/locales/index.d.ts +4 -0
  124. package/generated/i18n/locales/index.js +4 -0
  125. package/generated/index.d.ts +2 -0
  126. package/generated/index.js +3 -0
  127. package/generated/internal/class/cleanup-registry.d.ts +5 -0
  128. package/generated/internal/class/cleanup-registry.js +38 -0
  129. package/generated/internal/class/css-style-observer.d.ts +8 -0
  130. package/generated/internal/class/css-style-observer.js +26 -0
  131. package/generated/internal/class/form-associated-base.d.ts +16 -0
  132. package/generated/internal/class/form-associated-base.js +78 -0
  133. package/generated/internal/class/mutation-observer-set.d.ts +9 -0
  134. package/generated/internal/class/mutation-observer-set.js +42 -0
  135. package/generated/internal/class/mutation-observer-singleton.d.ts +10 -0
  136. package/generated/internal/class/mutation-observer-singleton.js +64 -0
  137. package/generated/internal/class/navigation-path.d.ts +15 -0
  138. package/generated/internal/class/navigation-path.js +84 -0
  139. package/generated/internal/class/navigation-view.d.ts +8 -0
  140. package/generated/internal/class/navigation-view.js +79 -0
  141. package/generated/internal/class/resize-observer-singleton.d.ts +7 -0
  142. package/generated/internal/class/resize-observer-singleton.js +22 -0
  143. package/generated/internal/decorators/adaptive-slot.d.ts +1 -0
  144. package/generated/internal/decorators/adaptive-slot.js +50 -0
  145. package/generated/internal/decorators/custom-element.d.ts +5 -0
  146. package/generated/internal/decorators/custom-element.js +5 -0
  147. package/generated/internal/decorators/index.d.ts +4 -0
  148. package/generated/internal/decorators/index.js +4 -0
  149. package/generated/internal/privateNamespace.d.ts +14 -0
  150. package/generated/internal/privateNamespace.js +168 -0
  151. package/generated/internal/utils/add.d.ts +1 -0
  152. package/generated/internal/utils/add.js +7 -0
  153. package/generated/internal/utils/cash/ancestors.d.ts +1 -0
  154. package/generated/internal/utils/cash/ancestors.js +27 -0
  155. package/generated/internal/utils/cash/index.d.ts +23 -0
  156. package/generated/internal/utils/cash/index.js +25 -0
  157. package/generated/internal/utils/cash/next-all.d.ts +1 -0
  158. package/generated/internal/utils/cash/next-all.js +10 -0
  159. package/generated/internal/utils/cash/next.d.ts +1 -0
  160. package/generated/internal/utils/cash/next.js +9 -0
  161. package/generated/internal/utils/cash/prev-all.d.ts +1 -0
  162. package/generated/internal/utils/cash/prev-all.js +10 -0
  163. package/generated/internal/utils/cash/prev.d.ts +1 -0
  164. package/generated/internal/utils/cash/prev.js +9 -0
  165. package/generated/internal/utils/cash/prop.d.ts +18 -0
  166. package/generated/internal/utils/cash/prop.js +30 -0
  167. package/generated/internal/utils/cash/siblings.d.ts +1 -0
  168. package/generated/internal/utils/cash/siblings.js +10 -0
  169. package/generated/internal/utils/clamp.d.ts +1 -0
  170. package/generated/internal/utils/clamp.js +4 -0
  171. package/generated/internal/utils/compare-big-decimals.d.ts +1 -0
  172. package/generated/internal/utils/compare-big-decimals.js +90 -0
  173. package/generated/internal/utils/css-time.d.ts +1 -0
  174. package/generated/internal/utils/css-time.js +3 -0
  175. package/generated/internal/utils/debounce.d.ts +1 -0
  176. package/generated/internal/utils/debounce.js +13 -0
  177. package/generated/internal/utils/dev-flags.d.ts +3 -0
  178. package/generated/internal/utils/dev-flags.js +5 -0
  179. package/generated/internal/utils/ensure-placeholder.d.ts +1 -0
  180. package/generated/internal/utils/ensure-placeholder.js +55 -0
  181. package/generated/internal/utils/frame.d.ts +1 -0
  182. package/generated/internal/utils/frame.js +6 -0
  183. package/generated/internal/utils/index.d.ts +19 -0
  184. package/generated/internal/utils/index.js +22 -0
  185. package/generated/internal/utils/is-inside.d.ts +1 -0
  186. package/generated/internal/utils/is-inside.js +4 -0
  187. package/generated/internal/utils/kebab-case.d.ts +1 -0
  188. package/generated/internal/utils/kebab-case.js +11 -0
  189. package/generated/internal/utils/list-active.d.ts +7 -0
  190. package/generated/internal/utils/list-active.js +83 -0
  191. package/generated/internal/utils/microtask.d.ts +1 -0
  192. package/generated/internal/utils/microtask.js +3 -0
  193. package/generated/internal/utils/onoff.d.ts +45 -0
  194. package/generated/internal/utils/onoff.js +31 -0
  195. package/generated/internal/utils/set.d.ts +1 -0
  196. package/generated/internal/utils/set.js +7 -0
  197. package/generated/internal/utils/sleep.d.ts +1 -0
  198. package/generated/internal/utils/sleep.js +3 -0
  199. package/generated/internal/utils/slow-hide-show.d.ts +1 -0
  200. package/generated/internal/utils/slow-hide-show.js +16 -0
  201. package/generated/internal/utils/timeout.d.ts +5 -0
  202. package/generated/internal/utils/timeout.js +16 -0
  203. package/generated/internal/utils/touch-glass.d.ts +7 -0
  204. package/generated/internal/utils/touch-glass.js +19 -0
  205. package/generated/namespace-browser/base.d.ts +45 -0
  206. package/generated/namespace-browser/base.js +115 -0
  207. package/generated/namespace-browser/index.d.ts +7 -0
  208. package/generated/namespace-browser/index.js +1 -0
  209. package/generated/snapshot/index.d.ts +9 -0
  210. package/generated/snapshot/index.js +60 -0
  211. package/package.json +35 -11
  212. package/scss/_components.scss +59 -14
  213. package/scss/_final.scss +1 -0
  214. package/scss/_functions.scss +10 -0
  215. package/scss/_mixins.scss +4 -169
  216. package/scss/_placeholders.scss +3 -0
  217. package/scss/_transitions.scss +22 -1
  218. package/scss/_utils.scss +9 -0
  219. package/scss/_vars.scss +142 -23
  220. package/scss/base/_layout.scss +31 -16
  221. package/scss/base/_reboot.scss +151 -15
  222. package/scss/base/_root.scss +355 -25
  223. package/scss/colors/_index.scss +672 -70
  224. package/scss/components/_alert-dialog.scss +111 -0
  225. package/scss/components/_body-view.scss +12 -3
  226. package/scss/components/_bordered-button.scss +57 -0
  227. package/scss/components/_bordered-prominent-button.scss +63 -0
  228. package/scss/components/_borderless-button.scss +36 -6
  229. package/scss/components/_confirmation-dialog.scss +84 -0
  230. package/scss/components/_content-unavailable-view.scss +45 -0
  231. package/scss/components/_date-picker.scss +30 -0
  232. package/scss/components/_detail-placeholder.scss +153 -0
  233. package/scss/components/_disclosure-group.scss +146 -51
  234. package/scss/components/_fine-tooltip.scss +82 -0
  235. package/scss/components/_form-view.scss +195 -0
  236. package/scss/components/_full-screen.scss +7 -5
  237. package/scss/components/_glass-button.scss +59 -0
  238. package/scss/components/_glass-prominent-button.scss +68 -0
  239. package/scss/components/_h-divider.scss +13 -0
  240. package/scss/components/_h-flex-stack.scss +23 -0
  241. package/scss/components/_h-stack.scss +29 -0
  242. package/scss/components/_index.scss +234 -7
  243. package/scss/components/_label-view copy.scss.txt +420 -0
  244. package/scss/components/_label-view.scss +355 -0
  245. package/scss/components/_label-view.scss.txt +536 -0
  246. package/scss/components/_labeled-content.scss +9 -0
  247. package/scss/components/_list-view.scss +229 -0
  248. package/scss/components/_menu-view.scss +211 -0
  249. package/scss/components/_navigation-large-title.scss +27 -0
  250. package/scss/components/_navigation-split-view.scss +329 -269
  251. package/scss/components/_navigation-stack.scss +6 -6
  252. package/scss/components/_navigation-title.scss +10 -0
  253. package/scss/components/_picker-view.scss +131 -0
  254. package/scss/components/_plain-button.scss +18 -0
  255. package/scss/components/_progress-view.scss +98 -0
  256. package/scss/components/_scroll-view-proxy.scss +79 -0
  257. package/scss/components/_scroll-view-toolbars.scss +126 -0
  258. package/scss/components/_scroll-view.scss +114 -66
  259. package/scss/components/_search-view.scss +18 -0
  260. package/scss/components/_section-view.scss +119 -0
  261. package/scss/components/_sheet-view.scss +78 -35
  262. package/scss/components/_sidebar-toggle.scss +87 -27
  263. package/scss/components/_sidebar-view.scss +30 -40
  264. package/scss/components/_sticky-container.scss +42 -0
  265. package/scss/components/_tab-bar.scss +207 -84
  266. package/scss/components/_tab-item.scss +25 -0
  267. package/scss/components/_tab-view.scss +270 -126
  268. package/scss/components/_table-column.scss +52 -0
  269. package/scss/components/_table-row.scss +172 -0
  270. package/scss/components/_table-view.scss +223 -0
  271. package/scss/components/_text-field.scss +37 -0
  272. package/scss/components/_tool-bar-item-group.scss +30 -19
  273. package/scss/components/_tool-bar-item.scss +81 -71
  274. package/scss/components/_tool-bar.scss +126 -63
  275. package/scss/components/_v-divider.scss +13 -0
  276. package/scss/components/_v-flex-stack.scss +29 -0
  277. package/scss/components/_v-keyboard.scss +6 -4
  278. package/scss/components/_v-stack.scss +15 -9
  279. package/scss/final/_touch-glass.scss +91 -0
  280. package/scss/index.scss +6 -2
  281. package/scss/mixins/_button.scss +44 -0
  282. package/scss/mixins/_color.scss +16 -0
  283. package/scss/mixins/_dialog.scss +89 -0
  284. package/scss/mixins/_index.scss +422 -0
  285. package/scss/placeholders/_buttons.scss +117 -0
  286. package/scss/placeholders/_lists.scss +571 -0
  287. package/scss/transitions/_alert-dialog.scss +18 -0
  288. package/scss/transitions/_bwd.navbar.scss +3 -13
  289. package/scss/transitions/_bwd.scss +4 -20
  290. package/scss/transitions/_confirmation-dialog.scss +22 -0
  291. package/scss/transitions/_disclosure-group.scss +35 -0
  292. package/scss/transitions/_fine-tooltip.scss +21 -0
  293. package/scss/transitions/_fwd.navbar.scss +4 -9
  294. package/scss/transitions/_fwd.scss +4 -34
  295. package/scss/transitions/_glass-button.scss +12 -0
  296. package/scss/transitions/_glass-prominent-button.scss +12 -0
  297. package/scss/transitions/_index.scss +35 -143
  298. package/scss/transitions/_menu-view.scss +26 -0
  299. package/scss/transitions/_navigation-split-view.scss +23 -0
  300. package/scss/transitions/_progress-view.scss +23 -0
  301. package/scss/transitions/_sheet-view.scss +30 -0
  302. package/scss/transitions/_sidebar-view.scss +36 -0
  303. package/scss/transitions/_tab-bar.scss +20 -0
  304. package/scss/utils/_frame.scss +91 -0
  305. package/scss/utils/_index.scss +91 -0
  306. package/scss/utils/_scroll-view.scss +14 -0
  307. package/scss/utils/_spacing.scss +25 -0
  308. package/scss/utils/_stacks.scss +209 -0
  309. package/web-components.html-data/en.json +500 -0
  310. package/generated/styles.css +0 -1305
  311. package/scss/_dev.scss +0 -68
  312. package/scss/components/_tab-bar-stack.scss +0 -101
  313. package/scss/components/_toolbars.scss +0 -100
  314. package/scss/transitions/_dialog.scss +0 -32
@@ -0,0 +1,681 @@
1
+ var _a;
2
+ import { I18n } from '../i18n';
3
+ import { CleanupRegistry } from '../internal/class/cleanup-registry';
4
+ import { FormAssociatedBase, getInternals } from '../internal/class/form-associated-base';
5
+ import { MutationObserverSet } from '../internal/class/mutation-observer-set';
6
+ import { NavigationPath } from '../internal/class/navigation-path';
7
+ import { queryInsertPosition, startViewTransition } from '../internal/privateNamespace';
8
+ import { $, devFlags, kebabCase, onoff } from '../internal/utils';
9
+ const pickerStyles = ['menu', 'inline', 'navigation-link', 'sheet', 'automatic'];
10
+ const update = (path, node, overwrite = true) => {
11
+ if (!(path instanceof NavigationPath))
12
+ throw new Error('invalid view');
13
+ const { component, page } = path;
14
+ if (!component)
15
+ return;
16
+ const position = queryInsertPosition(component); //'afterend'
17
+ // const lookFor = 'beforebegin' === position ? 'previousElementSibling' : 'nextElementSibling'
18
+ if (page)
19
+ page.insertAdjacentElement(position, node);
20
+ };
21
+ const reflectSpawnedElement = (current, source) => {
22
+ const { page: oldSv, toolBarConfig: oldToolbar } = new NavigationPath(current).hydrate(), { page: newSv, toolBarConfig: newToolbar } = new NavigationPath(source).hydrate();
23
+ const oldVStack = oldSv?.querySelector(':scope>v-stack'), newVStack = newSv?.querySelector(':scope>v-stack'), oldBackBtn = oldToolbar?.at(0)?.querySelector('button'), newBackBtn = newToolbar?.at(0)?.querySelector('button');
24
+ // pre replace list (always exist)
25
+ const oldOpenedDetails = [...(oldVStack?.querySelectorAll('list-view details[open]>summary') ?? [])].map((item) => item.textContent.trim());
26
+ // replace list (always exist)
27
+ if (oldVStack && newVStack)
28
+ oldVStack.replaceWith(newVStack);
29
+ // post replace list (always exist)
30
+ for (const label of oldOpenedDetails)
31
+ for (const summary of newVStack?.querySelectorAll('list-view details>summary') ?? [])
32
+ if (summary.textContent.trim() === label) {
33
+ summary.parentElement?.setAttribute('open', 'open');
34
+ break;
35
+ }
36
+ // replace backbtns (always exist)
37
+ if (oldBackBtn && newBackBtn)
38
+ oldBackBtn.replaceWith(newBackBtn);
39
+ // overwrite navtitle (always exist)
40
+ oldSv?.setAttribute('navigation-inline-title', newSv?.getAttribute('navigation-inline-title') ?? '');
41
+ };
42
+ const extractTagFromOption = (node) => {
43
+ return ((node.getAttribute('value') ?? node.textContent?.trim()) || node.getAttribute('label')) ?? '';
44
+ };
45
+ const extractCurrentValueFromOption = (node) => {
46
+ return (node.getAttribute('label') ?? node.getAttribute('value') ?? node.textContent?.trim()) || '';
47
+ };
48
+ export class PickerView extends FormAssociatedBase {
49
+ static get ATTR() {
50
+ return {
51
+ PLACEHOLDER: 'placeholder',
52
+ LABEL: 'label',
53
+ PICKER_STYLE: 'picker-style',
54
+ SELECTION: 'selection',
55
+ SEARCHABLE: 'searchable',
56
+ CURRENT_VALUE_LABEL: 'current-value-label',
57
+ };
58
+ }
59
+ static get observedAttributes() {
60
+ return Object.values(this.ATTR);
61
+ }
62
+ static #templates = new Map();
63
+ #spawn;
64
+ #spawnPage = (tag, searchable = false, title, node) => {
65
+ const body = $(`<${'sheet-view' === tag ? 'dialog is="sheet-view"' : 'body-view'}><scroll-view><v-stack placement="leading fill"><list-view preferred-expanded-style="inset"></list-view></v-stack></scroll-view><tool-bar><tool-bar-item slot="top-bar-leading"><button type="button" tabindex="0"><label-view system-image="caret-left"></label-view></button></tool-bar-item></tool-bar></${'sheet-view' === tag ? 'dialog' : 'body-view'}>`, '>1'), sv = body.querySelector('scroll-view'), list = body.querySelector('list-view'), backBtn = body.querySelector('button');
66
+ if (title)
67
+ sv?.setAttribute('navigation-inline-title', title);
68
+ if (searchable) {
69
+ list?.style.setProperty('--list--sticky-block-size', '70px');
70
+ list?.insertAdjacentHTML('afterend', `<sticky-container edge="navbar" style="order: -1" padding>
71
+ <v-stack spacing="0" alignment="fill">
72
+ <input is="search-view" placeholder="Search">
73
+ <button type="button">Filters</button>
74
+ </v-stack>
75
+ </sticky-container>`);
76
+ const searchInput = sv?.querySelector('input'); // FIXME: compoennt is=search-view??
77
+ searchInput?.addEventListener('focus', (evt) => {
78
+ if (this.#spawn)
79
+ this.dispatchEvent(new CustomEvent('picker:searchfocus', {
80
+ detail: { element: this.#spawn, search: evt.target instanceof HTMLInputElement && evt.target ? evt.target.value : '' },
81
+ bubbles: true,
82
+ composed: true,
83
+ }));
84
+ });
85
+ searchInput?.addEventListener('blur', (evt) => {
86
+ if (this.#spawn)
87
+ this.dispatchEvent(new CustomEvent('picker:searchblur', {
88
+ detail: { element: this.#spawn, search: evt.target instanceof HTMLInputElement && evt.target ? evt.target.value : '' },
89
+ bubbles: true,
90
+ composed: true,
91
+ }));
92
+ });
93
+ searchInput?.addEventListener('input', (evt) => {
94
+ if (this.#spawn)
95
+ this.dispatchEvent(new CustomEvent('picker:searchinput', {
96
+ detail: { element: this.#spawn, search: evt.target instanceof HTMLInputElement && evt.target ? evt.target.value : '' },
97
+ bubbles: true,
98
+ composed: true,
99
+ }));
100
+ });
101
+ }
102
+ backBtn?.setAttribute('help', I18n.t('ButtonRole').Back);
103
+ backBtn?.addEventListener('click', async (evt) => {
104
+ evt.stopImmediatePropagation();
105
+ evt.preventDefault();
106
+ const { target } = evt;
107
+ if (!(target instanceof HTMLElement && target))
108
+ return;
109
+ const { component } = new NavigationPath(target)?.hydrate();
110
+ await startViewTransition(target, 'backwards', async () => {
111
+ component?.remove();
112
+ });
113
+ });
114
+ const elements = node ? Array.from(node.children) : (this.#slots?.get('list')?.assignedElements() ?? []);
115
+ for (const el of elements) {
116
+ if (!(el instanceof HTMLElement))
117
+ continue;
118
+ switch (el.tagName) {
119
+ case 'OPTGROUP': {
120
+ const details = _a.#wrapOptgroupTag(el);
121
+ _a.#reflectButtons([...el.children], details);
122
+ for (const btn of details.querySelectorAll(':scope>button'))
123
+ btn.addEventListener('click', this.#handlePageBtnClick);
124
+ list?.appendChild(details);
125
+ break;
126
+ }
127
+ case 'OPTION': {
128
+ const btn = _a.#wrapOptionTag(el);
129
+ btn.addEventListener('click', this.#handlePageBtnClick);
130
+ list?.appendChild(btn);
131
+ break;
132
+ }
133
+ default: {
134
+ const btn = $(`<button type="button" tabindex="0"><label-view></label-view></button>`, '>1'), label = btn.querySelector(':scope>label-view');
135
+ if (el.dataset.label)
136
+ label?.setAttribute('title', el.dataset.label);
137
+ btn.addEventListener('click', async (evt) => {
138
+ evt.stopImmediatePropagation();
139
+ evt.preventDefault();
140
+ const { target } = evt;
141
+ if (!(target instanceof HTMLElement && target))
142
+ return;
143
+ const newPage = this.#spawnPage('body-view', this.hasAttribute('searchable'), el.dataset.label, el);
144
+ if (!newPage)
145
+ return;
146
+ const path = new NavigationPath(target)?.hydrate();
147
+ await startViewTransition(target, 'forwards', async () => {
148
+ update(path, newPage);
149
+ this.#reflectSelectionOnButtons();
150
+ });
151
+ });
152
+ list?.appendChild(btn);
153
+ break;
154
+ }
155
+ }
156
+ }
157
+ return body;
158
+ };
159
+ #renderSlotted = (entries) => {
160
+ if (devFlags.debug)
161
+ console.debug(`${_a.name} ⚡️ mutation`);
162
+ switch (this.pickerStyle) {
163
+ case 'sheet':
164
+ case 'navigation-link': {
165
+ // current value label only
166
+ const currentValueLabel = this.querySelector(':scope>label-view:not([slot])') ?? this.appendChild($(`<label-view></label-view>`, '>1'));
167
+ // reset state
168
+ currentValueLabel.setAttribute('system-image', 'dots-three'); // overwritten
169
+ currentValueLabel.setAttribute('title', this.#currentValueLabel); // overwritten
170
+ // clear all siblings
171
+ for (const el of this.querySelectorAll(':scope>:not([slot])'))
172
+ if (currentValueLabel !== el)
173
+ el.remove();
174
+ CleanupRegistry.unregister(this, 'trigger');
175
+ CleanupRegistry.register(this, onoff('click', this.#handleTriggerClick, currentValueLabel).on(), 'trigger');
176
+ // rebuild snapshot(tree)
177
+ if (!this.#spawn)
178
+ break;
179
+ // rerender level 0
180
+ reflectSpawnedElement(this.#spawn, this.#spawnPage('body-view', this.hasAttribute('searchable'), this.getAttribute('label')));
181
+ for (const el of this.#spawn.querySelectorAll('body-view')) {
182
+ const depth = $.ancestors('body-view,[is=sheet-view]', el).indexOf(this.#spawn);
183
+ if (0 >= depth)
184
+ continue;
185
+ const datalist = this.querySelector(`:scope>${Array.from({ length: depth }, () => 'datalist').join('>')}`);
186
+ if (!datalist) {
187
+ el.remove();
188
+ break;
189
+ }
190
+ reflectSpawnedElement(el, this.#spawnPage('body-view', this.hasAttribute('searchable'), datalist.dataset.label, datalist));
191
+ }
192
+ break;
193
+ }
194
+ case 'menu': {
195
+ const menu = this.querySelector(':scope>menu-view:not([slot])') ?? this.appendChild($(`<menu-view></menu-view>`, '>1'));
196
+ // reset state
197
+ menu.innerHTML = '';
198
+ menu.tabIndex = 0;
199
+ // clear all siblings
200
+ for (const el of this.querySelectorAll(':scope>:not([slot])'))
201
+ if (menu !== el)
202
+ el.remove();
203
+ const currentValueLabel = menu.querySelector(':scope>label-view[slot=label]') ?? menu.appendChild($(`<label-view slot="label"></label-view>`, '>1'));
204
+ currentValueLabel.setAttribute('system-image', 'dots-three'); // overwritten
205
+ currentValueLabel.setAttribute('title', this.#currentValueLabel); // overwritten
206
+ _a.#reflectButtons([...(this.#slots?.get('list')?.assignedElements() ?? [])], menu);
207
+ break;
208
+ }
209
+ case 'inline':
210
+ default: {
211
+ const sectionTpl = `<section-view></section-view>`;
212
+ const inlineList = this.querySelector(':scope>list-view:not([slot])') ?? this.appendChild($(`<list-view>${sectionTpl}</list-view>`, '>1')), section = inlineList.querySelector(':scope>section-view') ?? inlineList.appendChild($(sectionTpl, '>1'));
213
+ // reset state
214
+ section.innerHTML = '';
215
+ // clear all siblings
216
+ for (const el of this.querySelectorAll(':scope>:not([slot])'))
217
+ if (inlineList !== el)
218
+ el.remove();
219
+ const value = this.getAttribute(this.constructor.ATTR.LABEL);
220
+ if (value) {
221
+ const label = $(`<label-view></label-view>`, '>1');
222
+ label.setAttribute('title', value);
223
+ section.insertAdjacentElement('beforeend', label);
224
+ }
225
+ _a.#reflectButtons([...(this.#slots?.get('list')?.assignedElements({ flatten: true }) ?? [])].filter((el) => el.matches('option')), section);
226
+ break;
227
+ }
228
+ }
229
+ this.#reflectSelectionOnButtons();
230
+ this.#reflectCurrentValueLabel();
231
+ };
232
+ #renderValidityMsgs = (entries) => {
233
+ if (devFlags.debug)
234
+ console.debug(`${_a.name} ⚡️ mutation`);
235
+ this.setValidity(this.validity, this.validationMessage);
236
+ };
237
+ #lastRenderedStyle; //string | null
238
+ #shadowRoot;
239
+ #slots = new Map();
240
+ #validityObservers = new MutationObserverSet(this.#renderValidityMsgs);
241
+ #observers = new MutationObserverSet(this.#renderSlotted);
242
+ #customValidity = '';
243
+ #selection = '';
244
+ get #internals() {
245
+ return getInternals(this);
246
+ }
247
+ get template() {
248
+ if (!_a.#templates.has(this.pickerStyle))
249
+ switch (this.pickerStyle) {
250
+ case 'sheet':
251
+ case 'navigation-link':
252
+ _a.#templates.set(this.pickerStyle, $(String.raw `
253
+ <label part="root picker-stack">
254
+ <div part="root picker-label-stack">
255
+ <slot name="label"></slot>
256
+ </div>
257
+ <div part="root picker-input-stack">
258
+ <slot></slot>
259
+ </div>
260
+ <slot name="list" hidden></slot>
261
+ <slot name="validity-options" hidden></slot>
262
+ </label>
263
+ `));
264
+ break;
265
+ case 'menu':
266
+ _a.#templates.set(this.pickerStyle, $(String.raw `
267
+ <label part="root picker-stack">
268
+ <div part="root picker-label-stack">
269
+ <slot name="label"></slot>
270
+ </div>
271
+ <div part="root picker-input-stack">
272
+ <slot></slot>
273
+ </div>
274
+ <slot name="list" hidden></slot>
275
+ <slot name="validity-options" hidden></slot>
276
+ </label>
277
+ `));
278
+ // break
279
+ // case 'compact':
280
+ // PickerView.#templates.set(
281
+ // style,
282
+ // Object.assign(document.createElement('template'), {
283
+ // innerHTML: String.raw`
284
+ // <label part="compact-picker">
285
+ // <input type="text" part="compact-input">
286
+ // </label>
287
+ // `,
288
+ // })
289
+ // )
290
+ // break
291
+ // case 'fancy':
292
+ // PickerView.#templates.set(
293
+ // style,
294
+ // Object.assign(document.createElement('template'), {
295
+ // innerHTML: String.raw`
296
+ // <div part="fancy-picker">
297
+ // <span>Fancy Picker</span>
298
+ // <input type="text" part="fancy-input">
299
+ // </div>
300
+ // `,
301
+ // })
302
+ // )
303
+ break;
304
+ // case 'gg':
305
+ // PickerView.#templates.set(
306
+ // style,
307
+ // Object.assign(document.createElement('template'), {
308
+ // innerHTML: String.raw`
309
+ // <label part="root text-field-stack">
310
+ // <div part="root text-field-label-stack">
311
+ // <slot name="label"></slot>
312
+ // </div>
313
+ // <div part="root text-field-input-stack">
314
+ // <input type="text" part="root input text-field-form-input" list="tickmarks">
315
+ // <datalist id="tickmarks">
316
+ // <option value="0" label="0%"></option>
317
+ // </datalist>
318
+ // </div>
319
+ // <slot name="list" hidden></slot>
320
+ // </label>`,
321
+ // })
322
+ // )
323
+ // break
324
+ case 'inline':
325
+ default:
326
+ _a.#templates.set(this.pickerStyle, $(String.raw `
327
+ <label part="root picker-stack">
328
+ <div part="root picker-label-stack">
329
+ <slot name="label"></slot>
330
+ </div>
331
+ <div part="root picker-input-stack">
332
+ <slot></slot>
333
+ </div>
334
+ <slot name="list" hidden></slot>
335
+ <slot name="validity-options" hidden></slot>
336
+ </label>`));
337
+ break;
338
+ }
339
+ return _a.#templates.get(this.pickerStyle);
340
+ }
341
+ constructor() {
342
+ super();
343
+ this.#shadowRoot = this.attachShadow({ mode: 'closed' });
344
+ }
345
+ connectedCallback() {
346
+ if (devFlags.debug)
347
+ console.debug(`${_a.name} ⚡️ connect`);
348
+ CleanupRegistry.register(this, onoff('localechange', () => {
349
+ this.#renderSlotted([]);
350
+ }, I18n.on).on());
351
+ CleanupRegistry.register(this, onoff('click', this.#handleClick, this).on());
352
+ if (!this.hasAttribute(this.constructor.ATTR.PICKER_STYLE))
353
+ this.#render(); // will be picked up by attr-change!
354
+ // finally
355
+ if (!this.hasAttribute('selection'))
356
+ return;
357
+ this.#selection = this.getAttribute('selection') ?? '';
358
+ this.#sendValueToForm(false);
359
+ }
360
+ disconnectedCallback() {
361
+ if (devFlags.debug)
362
+ console.debug(`${_a.name} ⚡️ disconnect`);
363
+ CleanupRegistry.unregister(this);
364
+ this.#validityObservers.unobserveAll();
365
+ this.#observers.unobserveAll();
366
+ }
367
+ attributeChangedCallback(name, oldValue, newValue) {
368
+ if (devFlags.debug)
369
+ console.debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
370
+ switch (name) {
371
+ case this.constructor.ATTR.PLACEHOLDER:
372
+ this.#reflectPlaceholder(newValue);
373
+ break;
374
+ case this.constructor.ATTR.LABEL:
375
+ this.#reflectLabel(newValue);
376
+ // this.#sendValueToForm()
377
+ break;
378
+ case this.constructor.ATTR.PICKER_STYLE:
379
+ if (oldValue === newValue)
380
+ break;
381
+ this.#render();
382
+ break;
383
+ case this.constructor.ATTR.SEARCHABLE:
384
+ if (oldValue === newValue)
385
+ break;
386
+ this.#renderSlotted([]);
387
+ break;
388
+ case this.constructor.ATTR.CURRENT_VALUE_LABEL:
389
+ // if (oldValue === newValue) break
390
+ this.#reflectCurrentValueLabel();
391
+ break;
392
+ case this.constructor.ATTR.SELECTION:
393
+ // nothing happens
394
+ break;
395
+ }
396
+ }
397
+ get pickerStyle() {
398
+ const attr = this.constructor.ATTR.PICKER_STYLE;
399
+ return pickerStyles.includes(this.getAttribute(attr) ?? '') ? this.getAttribute(attr) : 'automatic';
400
+ }
401
+ #render() {
402
+ if (devFlags.debug)
403
+ console.debug(`${_a.name} ⚡️ render (${this.pickerStyle})`);
404
+ // const style = this.getAttribute((this.constructor as typeof PickerView).ATTR.PICKER_STYLE)
405
+ if (this.#lastRenderedStyle === this.pickerStyle)
406
+ return; // skip if already applied
407
+ this.#lastRenderedStyle = this.pickerStyle;
408
+ // clear shadow DOM
409
+ this.#shadowRoot.replaceChildren(document.importNode(this.template, true));
410
+ CleanupRegistry.unregister(this, 'slots');
411
+ for (const slot of this.#shadowRoot.querySelectorAll('slot'))
412
+ this.#slots?.set(slot.name, slot);
413
+ CleanupRegistry.register(this, () => {
414
+ this.#slots = new Map();
415
+ }, 'slots');
416
+ CleanupRegistry.unregister(this, 'validities');
417
+ CleanupRegistry.register(this, onoff('slotchange', this.#handleValiditiesSlotchange, this.#slots?.get('validity-options')).on(), 'validities');
418
+ CleanupRegistry.unregister(this, 'datalist'); //off1()
419
+ CleanupRegistry.register(this, onoff('slotchange', this.#handleListSlotchange, this.#slots?.get('list')).on(), 'datalist');
420
+ // #renderSlotted should run automatically now by slotchange initial event
421
+ // switch (this.pickerStyle) {
422
+ // }
423
+ }
424
+ #sendValueToForm = (dispatchEvent = true) => {
425
+ // input.value has already been updated/synced !!
426
+ if (this.matches(':disabled'))
427
+ return this.setValidity({});
428
+ if (this.hasAttribute('required')) {
429
+ if (!this.#selection) {
430
+ this.setValidity({ badInput: true }, 'invalid-selection');
431
+ }
432
+ else
433
+ this.setValidity({});
434
+ }
435
+ else
436
+ this.setValidity({});
437
+ const entries = new FormData();
438
+ entries.append(this.name, this.#selection);
439
+ this.#internals.setFormValue(entries);
440
+ if (dispatchEvent)
441
+ this.dispatchEvent(new CustomEvent('selection', { detail: { selection: this.#selection }, bubbles: true, composed: true }));
442
+ };
443
+ #handleTriggerClick = async ({ type, target }) => {
444
+ if (devFlags.debug)
445
+ console.debug(`${_a.name} ⚡️ ${type}`);
446
+ if (!(target instanceof HTMLElement && target))
447
+ return;
448
+ this.#spawn?.remove?.();
449
+ const level0 = this.#spawnPage('sheet' === this.pickerStyle ? 'sheet-view' : 'body-view', this.hasAttribute('searchable'), this.getAttribute('label'));
450
+ if (!level0)
451
+ return;
452
+ const path = new NavigationPath(target)?.hydrate();
453
+ await startViewTransition(target, 'forwards', async () => {
454
+ this.#spawn = level0;
455
+ update(path, level0);
456
+ this.#reflectSelectionOnButtons();
457
+ });
458
+ };
459
+ #handlePageBtnClick = async (evt) => {
460
+ if (devFlags.debug)
461
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
462
+ evt.stopImmediatePropagation();
463
+ evt.preventDefault();
464
+ const { currentTarget: btn } = evt;
465
+ if (!(btn instanceof HTMLElement && btn))
466
+ return;
467
+ // const btn = target.closest('button')
468
+ // if (!btn) return
469
+ const proceed = () => {
470
+ this.#spawn?.remove();
471
+ this.#selection = btn.getAttribute('value') ?? '';
472
+ this.#reflectSelectionOnButtons();
473
+ this.#reflectCurrentValueLabel();
474
+ this.#sendValueToForm();
475
+ };
476
+ const { body } = new NavigationPath(this.#spawn)?.hydrate();
477
+ if (!body)
478
+ return proceed();
479
+ await startViewTransition(body, 'backwards', async () => {
480
+ proceed();
481
+ });
482
+ };
483
+ #handleClick({ type, target }) {
484
+ if (devFlags.debug)
485
+ console.debug(`${_a.name} ⚡️ ${type}`);
486
+ if (!(target instanceof HTMLElement && target))
487
+ return;
488
+ const btn = target.closest('button');
489
+ if (!btn)
490
+ return;
491
+ this.#selection = btn.getAttribute('value') ?? '';
492
+ this.#reflectSelectionOnButtons();
493
+ this.#reflectCurrentValueLabel();
494
+ this.#sendValueToForm();
495
+ }
496
+ #handleValiditiesSlotchange = ({ type, target: slot }) => {
497
+ if (devFlags.debug)
498
+ console.debug(`${_a.name} ⚡️ ${type}`);
499
+ if (!(slot instanceof HTMLSlotElement && slot))
500
+ return;
501
+ const assigned = slot.assignedElements();
502
+ this.#validityObservers.syncObservations(assigned, ['value', 'label']);
503
+ // if (0 < assigned.length)
504
+ this.#renderValidityMsgs([]);
505
+ };
506
+ #handleListSlotchange = ({ type, target: slot }) => {
507
+ if (devFlags.debug)
508
+ console.debug(`${_a.name} ⚡️ ${type}`);
509
+ if (!(slot instanceof HTMLSlotElement && slot))
510
+ return;
511
+ const assigned = slot.assignedElements();
512
+ this.#observers.syncObservations(assigned);
513
+ // if (0 < assigned.length)
514
+ this.#renderSlotted([]);
515
+ };
516
+ static #wrapOptionTag(node) {
517
+ const btn = $(`<button type="button" tabindex="0"><h-stack template="auto spacer"><label-view system-image="check"></label-view></h-stack></button>`, '>1'), hStack = btn.querySelector(':scope>h-stack');
518
+ // chevron = hStack?.querySelector<HTMLElement>(':scope>label-view')
519
+ btn.setAttribute('value', extractTagFromOption(node));
520
+ // if (selection !== btn.getAttribute('value')) chevron?.style.setProperty('visibility', 'hidden')
521
+ const label = $(`<label-view></label-view>`, '>1');
522
+ label.setAttribute('title', extractCurrentValueFromOption(node));
523
+ hStack?.appendChild(label);
524
+ return btn;
525
+ }
526
+ static #wrapOptgroupTag(node) {
527
+ const labelT = `<label-view></label-view>`, summaryT = `<summary>${labelT}</summary>`;
528
+ const group = $(`<details is="disclosure-group">${summaryT}</details>`, '>1'), summary = group.querySelector(':scope>summary') ?? group.appendChild($(summaryT, '>1')), summaryLabel = summary.querySelector(':scope>label-view') ?? summary.appendChild($(labelT, '>1'));
529
+ if (node.hasAttribute('label'))
530
+ summaryLabel.setAttribute('title', node.getAttribute('label') ?? '');
531
+ if (node.hasAttribute('data-system-image'))
532
+ summaryLabel.setAttribute('system-image', node.getAttribute('data-system-image') ?? '');
533
+ return group;
534
+ }
535
+ static #reflectButtons(nodes, container) {
536
+ for (const node of nodes)
537
+ switch (node.tagName) {
538
+ case 'DATALIST': {
539
+ const group = $(`<menu-view tabindex="0"></menu-view>`, '>1'), label = group.querySelector(':scope>label-view[slot=label]') ?? group.appendChild($(`<label-view slot="label"></label-view>`, '>1'));
540
+ if (node.hasAttribute('data-label'))
541
+ label.setAttribute('title', node.getAttribute('data-label') ?? '');
542
+ if (node.hasAttribute('data-system-image'))
543
+ label.setAttribute('system-image', node.getAttribute('data-system-image') ?? '');
544
+ _a.#reflectButtons([...node.children], group);
545
+ container.appendChild(group);
546
+ break;
547
+ }
548
+ case 'OPTGROUP': {
549
+ const group = _a.#wrapOptgroupTag(node);
550
+ _a.#reflectButtons([...node.children], group);
551
+ container.appendChild(group);
552
+ break;
553
+ }
554
+ case 'OPTION':
555
+ default: {
556
+ container.appendChild(_a.#wrapOptionTag(node));
557
+ break;
558
+ }
559
+ }
560
+ }
561
+ #reflectPlaceholder(value) {
562
+ const input = this.#shadowRoot.querySelector('input');
563
+ if (input) {
564
+ if (value)
565
+ input.setAttribute('placeholder', value);
566
+ else
567
+ input.removeAttribute('placeholder');
568
+ }
569
+ }
570
+ #reflectLabel(value) {
571
+ let label = this.querySelector(':scope>label-view[slot=label]');
572
+ if (value) {
573
+ label ??= this.appendChild($(`<label-view slot="label"></label-view>`, '>1'));
574
+ label.setAttribute('foreground', 'secondary');
575
+ label.setAttribute('title', value);
576
+ }
577
+ else
578
+ label?.remove();
579
+ this.#renderSlotted([]);
580
+ }
581
+ #reflectSelectionOnButtons() {
582
+ // walk all rendered buttons (inline has buttons in list, menu has buttons in menu-view)
583
+ for (const el of this.querySelectorAll('button[value]:not([slot])'))
584
+ el.querySelector('label-view[system-image="check"]')?.style.setProperty('visibility', el.getAttribute('value') === this.#selection ? 'visible' : 'hidden');
585
+ // also sync the spawn (sheet/navigation) if open
586
+ if (this.#spawn)
587
+ for (const el of this.#spawn.querySelectorAll('list-view button[value]:not([slot])'))
588
+ el.querySelector('label-view[system-image="check"]')?.style.setProperty('visibility', el.getAttribute('value') === this.#selection ? 'visible' : 'hidden');
589
+ }
590
+ get #currentTag() {
591
+ return this.#slots
592
+ ?.get('list')
593
+ ?.assignedElements({ flatten: true })
594
+ .flatMap((el) => [...(el.matches('option') ? [el] : []), ...el.querySelectorAll('option')])
595
+ .find((el) => this.#selection === extractTagFromOption(el));
596
+ }
597
+ get #currentValueLabel() {
598
+ const cvl = this.#currentTag ? extractCurrentValueFromOption(this.#currentTag) : '';
599
+ return (this.getAttribute('current-value-label') ?? '').replaceAll('{{selection}}', this.#selection).replaceAll('{{currentValueLabel}}', this.#selection) || cvl || this.#selection;
600
+ }
601
+ #reflectCurrentValueLabel() {
602
+ switch (this.pickerStyle) {
603
+ case 'sheet':
604
+ case 'navigation-link': {
605
+ const currentValueLabel = this.querySelector(':scope>label-view:not([slot])');
606
+ currentValueLabel?.setAttribute('system-image', 'dots-three');
607
+ currentValueLabel?.setAttribute('title', this.#currentValueLabel);
608
+ break;
609
+ }
610
+ case 'menu': {
611
+ const currentValueLabel = this.querySelector(':scope>menu-view:not([slot])>label-view[slot=label]');
612
+ currentValueLabel?.setAttribute('system-image', 'dots-three');
613
+ currentValueLabel?.setAttribute('title', this.#currentValueLabel);
614
+ break;
615
+ }
616
+ case 'inline':
617
+ default: {
618
+ //
619
+ break;
620
+ }
621
+ }
622
+ }
623
+ // Optional: form participation properties
624
+ get name() {
625
+ return this.getAttribute('name') ?? this.getAttribute('label') ?? this.querySelector(':scope>[slot=label]')?.textContent ?? '';
626
+ }
627
+ setValidity = (flags, message, anchor) => {
628
+ // let msg
629
+ // if (message)
630
+ for (const k in flags) {
631
+ const key = k; // ✅ type-safe cast
632
+ if (true !== flags[key])
633
+ continue;
634
+ for (const el of this.#slots?.get('validity-options')?.assignedElements({ flatten: true }) ?? []) {
635
+ if (!el.matches('option'))
636
+ continue;
637
+ const option = el;
638
+ if (`${kebabCase(key)}` === option.value) {
639
+ message = option.label;
640
+ break;
641
+ }
642
+ else if (`${kebabCase(key)}:${message}` === option.value) {
643
+ message = option.label;
644
+ break;
645
+ }
646
+ }
647
+ }
648
+ if (!message)
649
+ for (const k in flags) {
650
+ const key = k; // ✅ type-safe cast
651
+ if (true !== flags[key])
652
+ continue;
653
+ message = kebabCase(key);
654
+ break;
655
+ }
656
+ if (devFlags.debug)
657
+ console.debug(`${_a.name} ⚡️ validity-change`);
658
+ return this.#internals.setValidity(flags, this.#customValidity || message, anchor);
659
+ };
660
+ setCustomValidity = (message) => {
661
+ this.#customValidity = message;
662
+ if (this.#customValidity)
663
+ this.#internals.setValidity({ ...this.#internals.validity, customError: true }, message);
664
+ else
665
+ this.#sendValueToForm(false);
666
+ };
667
+ formAssociatedCallback = (form) => {
668
+ this.#sendValueToForm();
669
+ };
670
+ formDisabledCallback = (disabled) => {
671
+ for (const btn of this.#shadowRoot.querySelectorAll('button'))
672
+ btn.toggleAttribute('disabled', !disabled);
673
+ };
674
+ formResetCallback = () => {
675
+ this.#selection = '';
676
+ this.#reflectSelectionOnButtons();
677
+ this.#reflectCurrentValueLabel();
678
+ this.#sendValueToForm();
679
+ };
680
+ }
681
+ _a = PickerView;