@swiftwc/ui 1.0.0-canary.0 → 1.0.0-canary.2

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 (262) 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 +30 -0
  10. package/generated/client/index.js +278 -0
  11. package/generated/components/alert-dialog.d.ts +11 -0
  12. package/generated/components/alert-dialog.js +94 -0
  13. package/generated/components/bordered-button.d.ts +17 -0
  14. package/generated/components/bordered-button.js +53 -0
  15. package/generated/components/bordered-prominent-button.d.ts +17 -0
  16. package/generated/components/bordered-prominent-button.js +53 -0
  17. package/generated/components/borderless-button.d.ts +17 -0
  18. package/generated/components/borderless-button.js +53 -0
  19. package/generated/components/color-scheme.d.ts +12 -0
  20. package/generated/components/color-scheme.js +51 -0
  21. package/generated/components/confirmation-dialog.d.ts +12 -0
  22. package/generated/components/confirmation-dialog.js +108 -0
  23. package/generated/components/content-unavailable.d.ts +30 -0
  24. package/generated/components/content-unavailable.js +79 -0
  25. package/generated/components/content-view.d.ts +13 -0
  26. package/generated/components/content-view.js +15 -0
  27. package/generated/components/date-picker.d.ts +52 -0
  28. package/generated/components/date-picker.js +468 -0
  29. package/generated/components/detail-placeholder.d.ts +11 -0
  30. package/generated/components/detail-placeholder.js +15 -0
  31. package/generated/components/disclosure-group.d.ts +17 -0
  32. package/generated/components/disclosure-group.js +62 -0
  33. package/generated/components/fine-tooltip.d.ts +15 -0
  34. package/generated/components/fine-tooltip.js +108 -0
  35. package/generated/components/form-view.d.ts +16 -0
  36. package/generated/components/form-view.js +63 -0
  37. package/generated/components/glass-button.d.ts +16 -0
  38. package/generated/components/glass-button.js +50 -0
  39. package/generated/components/glass-prominent-button.d.ts +16 -0
  40. package/generated/components/glass-prominent-button.js +50 -0
  41. package/generated/components/h-divider.d.ts +11 -0
  42. package/generated/components/h-divider.js +15 -0
  43. package/generated/components/h-flex-stack.d.ts +16 -0
  44. package/generated/components/h-flex-stack.js +18 -0
  45. package/generated/components/h-stack.d.ts +22 -0
  46. package/generated/components/h-stack.js +24 -0
  47. package/generated/components/image-view.d.ts +18 -0
  48. package/generated/components/image-view.js +65 -0
  49. package/generated/components/index.d.ts +53 -0
  50. package/generated/components/index.js +53 -0
  51. package/generated/components/label-view.d.ts +27 -0
  52. package/generated/components/label-view.js +84 -0
  53. package/generated/components/labeled-content.d.ts +33 -0
  54. package/generated/components/labeled-content.js +160 -0
  55. package/generated/components/list-view.d.ts +19 -0
  56. package/generated/components/list-view.js +24 -0
  57. package/generated/components/menu-view.d.ts +20 -0
  58. package/generated/components/menu-view.js +131 -0
  59. package/generated/components/navigation-large-title.d.ts +17 -0
  60. package/generated/components/navigation-large-title.js +183 -0
  61. package/generated/components/navigation-split-view.d.ts +15 -0
  62. package/generated/components/navigation-split-view.js +22 -0
  63. package/generated/components/navigation-stack.d.ts +15 -0
  64. package/generated/components/navigation-stack.js +26 -0
  65. package/generated/components/navigation-title.d.ts +18 -0
  66. package/generated/components/navigation-title.js +69 -0
  67. package/generated/components/picker-view.d.ts +51 -0
  68. package/generated/components/picker-view.js +1201 -0
  69. package/generated/components/plain-button.d.ts +7 -0
  70. package/generated/components/plain-button.js +20 -0
  71. package/generated/components/progress-view.d.ts +20 -0
  72. package/generated/components/progress-view.js +120 -0
  73. package/generated/components/screen-view.d.ts +5 -0
  74. package/generated/components/screen-view.js +10 -0
  75. package/generated/components/scroll-view-proxy.d.ts +13 -0
  76. package/generated/components/scroll-view-proxy.js +15 -0
  77. package/generated/components/scroll-view.d.ts +22 -0
  78. package/generated/components/scroll-view.js +230 -0
  79. package/generated/components/search-view.d.ts +12 -0
  80. package/generated/components/search-view.js +24 -0
  81. package/generated/components/section-view.d.ts +21 -0
  82. package/generated/components/section-view.js +61 -0
  83. package/generated/components/sheet-view.d.ts +11 -0
  84. package/generated/components/sheet-view.js +40 -0
  85. package/generated/components/sidebar-toggle.d.ts +15 -0
  86. package/generated/components/sidebar-toggle.js +84 -0
  87. package/generated/components/sidebar-view.d.ts +10 -0
  88. package/generated/components/sidebar-view.js +36 -0
  89. package/generated/components/sticky-container.d.ts +11 -0
  90. package/generated/components/sticky-container.js +24 -0
  91. package/generated/components/tab-bar.d.ts +10 -0
  92. package/generated/components/tab-bar.js +37 -0
  93. package/generated/components/tab-item.d.ts +10 -0
  94. package/generated/components/tab-item.js +127 -0
  95. package/generated/components/tab-view.d.ts +31 -0
  96. package/generated/components/tab-view.js +194 -0
  97. package/generated/components/table-view.d.ts +26 -0
  98. package/generated/components/table-view.js +156 -0
  99. package/generated/components/text-field.d.ts +42 -0
  100. package/generated/components/text-field.js +517 -0
  101. package/generated/components/text-view.d.ts +11 -0
  102. package/generated/components/text-view.js +16 -0
  103. package/generated/components/toggle-view.d.ts +43 -0
  104. package/generated/components/toggle-view.js +366 -0
  105. package/generated/components/tool-bar-item-group.d.ts +13 -0
  106. package/generated/components/tool-bar-item-group.js +29 -0
  107. package/generated/components/tool-bar-item.d.ts +16 -0
  108. package/generated/components/tool-bar-item.js +66 -0
  109. package/generated/components/tool-bar.d.ts +26 -0
  110. package/generated/components/tool-bar.js +92 -0
  111. package/generated/components/v-divider.d.ts +11 -0
  112. package/generated/components/v-divider.js +15 -0
  113. package/generated/components/v-flex-stack.d.ts +16 -0
  114. package/generated/components/v-flex-stack.js +18 -0
  115. package/generated/components/v-keyboard.d.ts +20 -0
  116. package/generated/components/v-keyboard.js +85 -0
  117. package/generated/components/v-stack.d.ts +25 -0
  118. package/generated/components/v-stack.js +27 -0
  119. package/generated/css/index.css +10964 -0
  120. package/generated/events/alert-dialog.d.ts +13 -0
  121. package/generated/events/alert-dialog.js +1 -0
  122. package/generated/events/confirmation-dialog.d.ts +14 -0
  123. package/generated/events/confirmation-dialog.js +1 -0
  124. package/generated/events/date-picker.d.ts +13 -0
  125. package/generated/events/date-picker.js +1 -0
  126. package/generated/events/index.d.ts +9 -0
  127. package/generated/events/index.js +9 -0
  128. package/generated/events/lifecycle-observer.d.ts +18 -0
  129. package/generated/events/lifecycle-observer.js +1 -0
  130. package/generated/events/picker-view.d.ts +29 -0
  131. package/generated/events/picker-view.js +1 -0
  132. package/generated/events/scroll-view.d.ts +18 -0
  133. package/generated/events/scroll-view.js +1 -0
  134. package/generated/events/tab-view.d.ts +54 -0
  135. package/generated/events/tab-view.js +1 -0
  136. package/generated/events/text-field.d.ts +13 -0
  137. package/generated/events/text-field.js +1 -0
  138. package/generated/events/toggle-view.d.ts +14 -0
  139. package/generated/events/toggle-view.js +1 -0
  140. package/generated/i18n/index.d.ts +33 -0
  141. package/generated/i18n/index.js +164 -0
  142. package/generated/i18n/locales/el.d.ts +16 -0
  143. package/generated/i18n/locales/el.js +16 -0
  144. package/generated/i18n/locales/en.d.ts +16 -0
  145. package/generated/i18n/locales/en.js +16 -0
  146. package/generated/i18n/locales/index.d.ts +4 -0
  147. package/generated/i18n/locales/index.js +4 -0
  148. package/generated/index.d.ts +2 -0
  149. package/generated/index.js +3 -0
  150. package/generated/internal/class/cleanup-registry.d.ts +5 -0
  151. package/generated/internal/class/cleanup-registry.js +38 -0
  152. package/generated/internal/class/css-style-observer.d.ts +8 -0
  153. package/generated/internal/class/css-style-observer.js +25 -0
  154. package/generated/internal/class/form-associated-base.d.ts +16 -0
  155. package/generated/internal/class/form-associated-base.js +76 -0
  156. package/generated/internal/class/mutation-observer-set.d.ts +9 -0
  157. package/generated/internal/class/mutation-observer-set.js +42 -0
  158. package/generated/internal/class/mutation-observer-singleton.d.ts +10 -0
  159. package/generated/internal/class/mutation-observer-singleton.js +64 -0
  160. package/generated/internal/class/navigation-path.d.ts +15 -0
  161. package/generated/internal/class/navigation-path.js +84 -0
  162. package/generated/internal/class/navigation-view.d.ts +8 -0
  163. package/generated/internal/class/navigation-view.js +70 -0
  164. package/generated/internal/class/resize-observer-singleton.d.ts +7 -0
  165. package/generated/internal/class/resize-observer-singleton.js +22 -0
  166. package/generated/internal/decorators/adaptive-slot.d.ts +1 -0
  167. package/generated/internal/decorators/adaptive-slot.js +47 -0
  168. package/generated/internal/decorators/custom-element.d.ts +5 -0
  169. package/generated/internal/decorators/custom-element.js +5 -0
  170. package/generated/internal/decorators/index.d.ts +6 -0
  171. package/generated/internal/decorators/index.js +6 -0
  172. package/generated/internal/decorators/microtask-on-connected.d.ts +39 -0
  173. package/generated/internal/decorators/microtask-on-connected.js +67 -0
  174. package/generated/internal/dev-flags.d.ts +4 -0
  175. package/generated/internal/dev-flags.js +1 -0
  176. package/generated/internal/privateNamespace.d.ts +14 -0
  177. package/generated/internal/privateNamespace.js +159 -0
  178. package/generated/internal/utils/$.d.ts +9 -0
  179. package/generated/internal/utils/$.js +11 -0
  180. package/generated/internal/utils/add.d.ts +1 -0
  181. package/generated/internal/utils/add.js +7 -0
  182. package/generated/internal/utils/ancestors.d.ts +1 -0
  183. package/generated/internal/utils/ancestors.js +27 -0
  184. package/generated/internal/utils/clamp.d.ts +1 -0
  185. package/generated/internal/utils/clamp.js +4 -0
  186. package/generated/internal/utils/compare-big-decimals.d.ts +1 -0
  187. package/generated/internal/utils/compare-big-decimals.js +80 -0
  188. package/generated/internal/utils/css-time.d.ts +1 -0
  189. package/generated/internal/utils/css-time.js +3 -0
  190. package/generated/internal/utils/debounce.d.ts +1 -0
  191. package/generated/internal/utils/debounce.js +13 -0
  192. package/generated/internal/utils/debug.d.ts +1 -0
  193. package/generated/internal/utils/debug.js +4 -0
  194. package/generated/internal/utils/define-translations.d.ts +1 -0
  195. package/generated/internal/utils/define-translations.js +3 -0
  196. package/generated/internal/utils/ensure-placeholder.d.ts +1 -0
  197. package/generated/internal/utils/ensure-placeholder.js +41 -0
  198. package/generated/internal/utils/frame.d.ts +1 -0
  199. package/generated/internal/utils/frame.js +6 -0
  200. package/generated/internal/utils/index.d.ts +54 -0
  201. package/generated/internal/utils/index.js +54 -0
  202. package/generated/internal/utils/is-inside.d.ts +1 -0
  203. package/generated/internal/utils/is-inside.js +4 -0
  204. package/generated/internal/utils/kebab-case.d.ts +1 -0
  205. package/generated/internal/utils/kebab-case.js +8 -0
  206. package/generated/internal/utils/list-active.d.ts +7 -0
  207. package/generated/internal/utils/list-active.js +83 -0
  208. package/generated/internal/utils/microtask.d.ts +1 -0
  209. package/generated/internal/utils/microtask.js +3 -0
  210. package/generated/internal/utils/next-all.d.ts +1 -0
  211. package/generated/internal/utils/next-all.js +10 -0
  212. package/generated/internal/utils/next.d.ts +1 -0
  213. package/generated/internal/utils/next.js +9 -0
  214. package/generated/internal/utils/onoff.d.ts +45 -0
  215. package/generated/internal/utils/onoff.js +31 -0
  216. package/generated/internal/utils/prev-all.d.ts +1 -0
  217. package/generated/internal/utils/prev-all.js +10 -0
  218. package/generated/internal/utils/prev.d.ts +1 -0
  219. package/generated/internal/utils/prev.js +9 -0
  220. package/generated/internal/utils/prop.d.ts +18 -0
  221. package/generated/internal/utils/prop.js +30 -0
  222. package/generated/internal/utils/set.d.ts +1 -0
  223. package/generated/internal/utils/set.js +7 -0
  224. package/generated/internal/utils/siblings.d.ts +1 -0
  225. package/generated/internal/utils/siblings.js +10 -0
  226. package/generated/internal/utils/sleep.d.ts +1 -0
  227. package/generated/internal/utils/sleep.js +3 -0
  228. package/generated/internal/utils/slow-hide-show.d.ts +1 -0
  229. package/generated/internal/utils/slow-hide-show.js +16 -0
  230. package/generated/internal/utils/timeout.d.ts +5 -0
  231. package/generated/internal/utils/timeout.js +16 -0
  232. package/generated/internal/utils/touch-glass.d.ts +7 -0
  233. package/generated/internal/utils/touch-glass.js +19 -0
  234. package/generated/internal/vendor/morphdom.d.ts +6 -0
  235. package/generated/internal/vendor/morphdom.js +720 -0
  236. package/generated/morphdom/index.d.ts +8 -0
  237. package/generated/morphdom/index.js +8 -0
  238. package/generated/morphdom/morph.d.ts +4 -0
  239. package/generated/morphdom/morph.js +10 -0
  240. package/generated/morphdom/query-morph.d.ts +5 -0
  241. package/generated/morphdom/query-morph.js +12 -0
  242. package/generated/morphdom/render-to-string.d.ts +12 -0
  243. package/generated/morphdom/render-to-string.js +48 -0
  244. package/generated/morphdom/unsafe-html.d.ts +2 -0
  245. package/generated/morphdom/unsafe-html.js +4 -0
  246. package/generated/namespace-browser/base.d.ts +45 -0
  247. package/generated/namespace-browser/base.js +115 -0
  248. package/generated/namespace-browser/event.d.ts +10 -0
  249. package/generated/namespace-browser/event.js +1 -0
  250. package/generated/namespace-browser/index.d.ts +7 -0
  251. package/generated/namespace-browser/index.js +1 -0
  252. package/generated/snapshot/index.d.ts +9 -0
  253. package/generated/snapshot/index.js +58 -0
  254. package/generated/tpl/html.d.ts +5 -0
  255. package/generated/tpl/html.js +7 -0
  256. package/generated/tpl/index.d.ts +6 -0
  257. package/generated/tpl/index.js +6 -0
  258. package/generated/tpl/is-template-result.d.ts +3 -0
  259. package/generated/tpl/is-template-result.js +1 -0
  260. package/generated/tpl/render.d.ts +2 -0
  261. package/generated/tpl/render.js +132 -0
  262. package/package.json +19 -18
@@ -0,0 +1,468 @@
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 { $, clamp, debug, kebabCase, onoff, set } from '../internal/utils';
7
+ import { queryMorph } from '../morphdom';
8
+ import { html } from '../tpl';
9
+ const datePickerStyles = ['graphical', 'field', 'automatic'];
10
+ /**
11
+ * @summary A control that selects an absolute date.
12
+ */
13
+ export class DatePicker extends FormAssociatedBase {
14
+ static get observedAttributes() {
15
+ return [
16
+ /**
17
+ * The style of this element
18
+ * @type {"graphical"|"field"|"automatic"}
19
+ */
20
+ 'date-picker-style',
21
+ /**
22
+ * @type {boolean}
23
+ */
24
+ 'required',
25
+ 'prompt',
26
+ 'label',
27
+ 'name',
28
+ 'selection',
29
+ /**
30
+ * @type {boolean}
31
+ */
32
+ 'disabled',
33
+ 'minimum',
34
+ 'maximum',
35
+ ];
36
+ }
37
+ static #templates = new Map();
38
+ // #lastRenderedStyle?: DatePickerStyle //string | null
39
+ #renderValidityMsgs = (entries) => {
40
+ debug(`${_a.name} ⚡️ mutation`);
41
+ this.setValidity(this.validity, this.validationMessage);
42
+ };
43
+ #shadowRoot;
44
+ #customValidity = '';
45
+ #slots = new Map();
46
+ #validityObservers = new MutationObserverSet(this.#renderValidityMsgs);
47
+ // #validitiesSlot?: HTMLSlotElement
48
+ #inputs = [];
49
+ get #internals() {
50
+ return getInternals(this);
51
+ }
52
+ get template() {
53
+ if (!_a.#templates.has(this.datePickerStyle))
54
+ switch (this.datePickerStyle) {
55
+ default:
56
+ _a.#templates.set(this.datePickerStyle, $(html `<label part="root date-picker-stack">
57
+ <div part="root date-picker-label-stack">
58
+ <slot name="label"></slot>
59
+ </div>
60
+ <div part="root date-picker-input-stack">
61
+ <input type="text" name="month" inputmode="numeric" pattern="d*" minlength="1" maxlength="2" min="1" max="12" part="root input date-picker-form-input" />
62
+ <span part="root date-picker-separator"></span>
63
+ <input type="text" name="day" inputmode="numeric" pattern="d*" minlength="1" maxlength="2" min="1" max="31" part="root input date-picker-form-input" />
64
+ <span part="root date-picker-separator"></span>
65
+ <input type="text" name="year" inputmode="numeric" pattern="d*" minlength="4" maxlength="4" min="0" max="9999" part="root input date-picker-form-input" />
66
+ </div>
67
+ <slot name="validity-options" hidden></slot>
68
+ </label>`));
69
+ break;
70
+ }
71
+ return _a.#templates.get(this.datePickerStyle);
72
+ }
73
+ constructor() {
74
+ super();
75
+ this.#shadowRoot = this.attachShadow({ mode: 'closed' });
76
+ }
77
+ attributeChangedCallback(name, oldValue, newValue) {
78
+ debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
79
+ switch (name) {
80
+ case 'selection':
81
+ // nothing happens// const [y = '', m = '', d = ''] = (newValue ?? '').split(/\D+/)
82
+ // this.#selectedDate = { year: y, month: m, day: d }
83
+ break;
84
+ case 'required':
85
+ for (const input of this.#inputs)
86
+ input.setAttribute(name, newValue ?? ''); // else this.#input?.removeAttribute(name)
87
+ this.#sendValueToForm();
88
+ break;
89
+ case 'name':
90
+ case 'minimum':
91
+ case 'maximum':
92
+ this.#sendValueToForm(false);
93
+ break;
94
+ case 'prompt':
95
+ const [py = '', pm = '', pd = ''] = (newValue ?? '').split(/\D+/), map = { year: py, month: pm, day: pd };
96
+ for (const input of this.#inputs)
97
+ input.setAttribute('placeholder', map[input.name] ?? '');
98
+ break;
99
+ case 'label':
100
+ queryMorph('[slot=label]', html `<label-view slot="label" foreground="secondary">${newValue ? html `<span>${newValue}</span>` : null}</label-view>`, this);
101
+ // this.#sendValueToForm()
102
+ break;
103
+ case 'disabled':
104
+ for (const input of this.#inputs)
105
+ input.toggleAttribute('disabled', !newValue);
106
+ break;
107
+ }
108
+ }
109
+ disconnectedCallback() {
110
+ super.disconnectedCallback();
111
+ this.#validityObservers.unobserveAll();
112
+ }
113
+ connectedCallback() {
114
+ super.connectedCallback();
115
+ CleanupRegistry.register(this, onoff('click', this.#handleClick, this).on());
116
+ this.#render();
117
+ CleanupRegistry.register(this, onoff('localechange', () => {
118
+ this.#render();
119
+ }, I18n.on).on());
120
+ // finally
121
+ if (!this.hasAttribute('selection'))
122
+ return;
123
+ const [y = '', m = '', d = ''] = (this.getAttribute('selection') ?? '').split(/\D+/);
124
+ this.#selectedDate = { year: y, month: m, day: d };
125
+ this.#sendValueToForm(false);
126
+ }
127
+ get datePickerStyle() {
128
+ return datePickerStyles.includes(this.getAttribute('date-picker-style') ?? '') ? this.getAttribute('date-picker-style') : 'automatic';
129
+ }
130
+ #render() {
131
+ debug(`${_a.name} ⚡️ #render (${this.datePickerStyle})`);
132
+ // if (this.#lastRenderedStyle === this.datePickerStyle) return // skip if already applied
133
+ // this.#lastRenderedStyle = this.datePickerStyle
134
+ // clear shadow DOM
135
+ this.#shadowRoot.replaceChildren(document.importNode(this.template, true));
136
+ CleanupRegistry.unregister(this, 'slots');
137
+ for (const slot of this.#shadowRoot.querySelectorAll('slot'))
138
+ this.#slots?.set(slot.name, slot);
139
+ CleanupRegistry.register(this, () => {
140
+ this.#slots = new Map();
141
+ }, 'slots');
142
+ CleanupRegistry.unregister(this, 'validities');
143
+ CleanupRegistry.register(this, onoff('slotchange', this.#handleValiditiesSlotchange, this.#slots?.get('validity-options')).on(), 'validities');
144
+ switch (this.datePickerStyle) {
145
+ default:
146
+ const [yyyy = '', mm = '', dd = ''] = new Date().toISOString().split('T').shift()?.split('-') ?? [], map = { year: yyyy, month: mm, day: dd };
147
+ this.#inputs = [...this.#shadowRoot.querySelectorAll('input')]
148
+ .sort((a, b) => I18n.dateOrder.indexOf(a.name) - I18n.dateOrder.indexOf(b.name))
149
+ .map((input, i) => {
150
+ input.style.order = `${i * 2}`;
151
+ input.tabIndex = i + 1;
152
+ input.setAttribute('placeholder', map[input.name]);
153
+ return input;
154
+ });
155
+ for (const span of this.#shadowRoot.querySelectorAll('input~span')) {
156
+ const prevOrder = Number(span.previousElementSibling?.style.getPropertyValue('order'));
157
+ span.style.setProperty('order', `${prevOrder + 1}`);
158
+ span.textContent = I18n.dateSeparator;
159
+ }
160
+ CleanupRegistry.unregister(this, 'inputs:*');
161
+ for (const input of this.#inputs) {
162
+ CleanupRegistry.register(this, onoff([
163
+ { types: 'focus', listener: this.#handleInputFocus },
164
+ { types: 'blur', listener: this.#handleInputBlur },
165
+ { types: 'input', listener: this.#handleInputInput },
166
+ { types: 'beforeinput', listener: this.#handleInputBeforeinput },
167
+ { types: 'paste', listener: this.#handleInputPaste },
168
+ { types: 'keydown', listener: this.#handleInputKeydown },
169
+ ], input).on(), `inputs:${input.name}`);
170
+ }
171
+ break;
172
+ }
173
+ }
174
+ #handleValiditiesSlotchange = ({ type, target: slot }) => {
175
+ debug(`${_a.name} ⚡️ ${type}`);
176
+ if (!(slot instanceof HTMLSlotElement))
177
+ return;
178
+ const assigned = slot.assignedElements();
179
+ this.#validityObservers.syncObservations(assigned, ['value', 'label']);
180
+ // if (0 < assigned.length)
181
+ this.#renderValidityMsgs([]);
182
+ };
183
+ get #selectedDate() {
184
+ const map = Object.fromEntries(this.#inputs.map(({ name, value }) => [name, value]));
185
+ return {
186
+ year: map.year ?? '',
187
+ month: map.month ?? '',
188
+ day: map.day ?? '',
189
+ };
190
+ }
191
+ set #selectedDate(v) {
192
+ for (const input of this.#inputs) {
193
+ const nv = v[input.name] ?? '', pattern = /^(\d+)?$/;
194
+ let finalValue = pattern.test(nv) ? nv : '', parsedValue = parseInt(finalValue);
195
+ if (_a.#min(input) > parsedValue)
196
+ finalValue = '';
197
+ else if (_a.#max(input) < parsedValue)
198
+ finalValue = '';
199
+ input.value = finalValue;
200
+ }
201
+ }
202
+ #handleClick = (evt) => {
203
+ debug(`${_a.name} ⚡️ ${evt?.type}`);
204
+ const { target } = evt;
205
+ if (!(target instanceof HTMLElement))
206
+ return;
207
+ const input = target.closest('input');
208
+ if (input)
209
+ return;
210
+ this.#shadowRoot.querySelector('input.focus')?.focus?.();
211
+ evt.stopImmediatePropagation();
212
+ evt.preventDefault();
213
+ evt.stopPropagation();
214
+ };
215
+ #sendValueToForm = (dispatchEvent = true) => {
216
+ // input.value has already been updated/synced !!
217
+ if (this.matches(':disabled'))
218
+ return this.setValidity({});
219
+ if (this.#inputs.some((el) => el.matches(':invalid'))) {
220
+ for (const input of this.#inputs) {
221
+ if (input.matches(':invalid'))
222
+ this.setValidity(input.validity, input.validationMessage, input);
223
+ }
224
+ }
225
+ else if (null === this.valueAsDate) {
226
+ this.setValidity({ badInput: true }, 'invalid-date');
227
+ }
228
+ else {
229
+ const parts = ['year', 'month', 'day'], input = (name) => this.#inputs.find((el) => el.name === name);
230
+ const underflow = this.minimum && parts.find((p) => parseInt(this.minimum[p]) > parseInt(this.value[p])), overflow = this.maximum && parts.find((p) => parseInt(this.maximum[p]) < parseInt(this.value[p]));
231
+ if (underflow)
232
+ this.setValidity({ rangeUnderflow: true }, `${underflow}-underflow`, input(underflow));
233
+ else if (overflow)
234
+ this.setValidity({ rangeOverflow: true }, `${overflow}-overflow`, input(overflow));
235
+ else
236
+ this.setValidity({});
237
+ }
238
+ const selection = `${this.#selectedDate.year}-${this.#selectedDate.month}-${this.#selectedDate.day}`;
239
+ const entries = new FormData();
240
+ entries.append(this.name, selection);
241
+ this.#internals.setFormValue(entries);
242
+ if (dispatchEvent)
243
+ this.dispatchEvent(new CustomEvent('selection', { detail: { selection }, bubbles: true, composed: true }));
244
+ };
245
+ #handleInputPaste = (evt) => {
246
+ debug(`${_a.name} ⚡️ ${evt?.type}`);
247
+ const { target: input } = evt;
248
+ if (!(input instanceof HTMLInputElement))
249
+ return;
250
+ evt.preventDefault();
251
+ const data = [...`${(evt.clipboardData?.getData('text') ?? '').trim()}`].reduce((acc, ch, i) => {
252
+ if (/\d/.test(ch))
253
+ return `${acc}${ch}`;
254
+ else
255
+ return acc; // skip everything else
256
+ }, ''); // number is now sanitized but contains edge cases like '+' and also global one separator that could be wither dot or decimal.
257
+ if (0 === data.length)
258
+ return this.shake(); //.then(this.reportValidity) // nothing to paste
259
+ const start = input.selectionStart ?? 0, end = input.selectionEnd ?? 0, before = input.value.slice(0, start), after = input.value.slice(end), newText = `${before}${data}${after}`;
260
+ if (-1 < input.maxLength && input.maxLength < newText.length)
261
+ return this.shake(); //.then(this.reportValidity) // exceeding maxlength
262
+ input.value = newText;
263
+ const newCaret = start + data.length;
264
+ input.setSelectionRange(newCaret, newCaret); // move caret after inserted char
265
+ this.#sendValueToForm();
266
+ };
267
+ #handleInputBeforeinput = (evt) => {
268
+ debug(`${_a.name} ⚡️ ${evt?.type}`);
269
+ const { target: input } = evt;
270
+ if (!(input instanceof HTMLInputElement))
271
+ return;
272
+ if ('insertText' !== evt.inputType)
273
+ return;
274
+ const data = evt.data ?? '';
275
+ if (-1 < input.maxLength && 0 === data.length) {
276
+ evt.preventDefault();
277
+ return this.shake(); //.then(this.reportValidity)
278
+ } // nothing to add
279
+ const start = input.selectionStart ?? 0, end = input.selectionEnd ?? 0, before = input.value.slice(0, start), after = input.value.slice(end), newText = `${before}${data}${after}`;
280
+ if (0 === newText.length)
281
+ return;
282
+ switch (input.getAttribute('inputmode')) {
283
+ case 'numeric':
284
+ if (/^(\d+)?$/.test(newText))
285
+ break; // allow only digits
286
+ evt.preventDefault();
287
+ return this.shake(); //.then(this.reportValidity)
288
+ }
289
+ };
290
+ #handleInputKeydown = ({ type, target, key }) => {
291
+ debug(`${_a.name} ⚡️ ${type}`);
292
+ if (!(target instanceof HTMLInputElement))
293
+ return;
294
+ const input = target;
295
+ if (!input)
296
+ return;
297
+ const currentIndex = this.#inputs.indexOf(input);
298
+ let index = currentIndex;
299
+ if (key === 'ArrowRight' && input.value.length === input.selectionStart) {
300
+ if (-1 < currentIndex && currentIndex < this.#inputs.length - 1)
301
+ index++;
302
+ }
303
+ else if (key === 'ArrowLeft' && 0 === input.selectionStart) {
304
+ if (0 < currentIndex)
305
+ index -= 1;
306
+ }
307
+ this.#inputs[index]?.focus();
308
+ };
309
+ #handleInputFocus = (evt) => {
310
+ debug(`${_a.name} ⚡️ ${evt?.type}`);
311
+ for (const input of this.#inputs)
312
+ input.classList.toggle('focus', input === evt.target);
313
+ };
314
+ #handleInputBlur = ({ target, type }) => {
315
+ debug(`${_a.name} ⚡️ ${type}`);
316
+ if (!(target instanceof HTMLInputElement))
317
+ return;
318
+ const input = target;
319
+ if (0 === input.value.length)
320
+ return;
321
+ const finalText = `${clamp(this.value[input.name] ?? '0', _a.#min(input), _a.#max(input))}`.padStart(parseInt(input.getAttribute('maxlength') ?? '0'), '0');
322
+ if (!set(input, 'value', finalText))
323
+ return;
324
+ // this.selection = this.selection
325
+ this.#sendValueToForm();
326
+ };
327
+ #handleInputInput = (evt) => {
328
+ debug(`${_a.name} ⚡️ ${evt?.type}`);
329
+ this.#sendValueToForm();
330
+ };
331
+ /**
332
+ * Form participation property
333
+ */
334
+ get name() {
335
+ return this.getAttribute('name') ?? this.getAttribute('label') ?? this.querySelector(':scope>[slot=label]')?.textContent ?? '';
336
+ }
337
+ get value() {
338
+ // text allows special edge cases, like '0' for day and generally might be invalid day/month/year.
339
+ // here we make sure it is date-like, to be used in date operations.
340
+ const map = Object.fromEntries(this.#inputs.map(({ name, value }) => [name, value]));
341
+ return {
342
+ year: (map.year ?? '').padStart(4, '0'),
343
+ month: (map.month ?? '').padStart(2, '0'),
344
+ day: (map.day ?? '').padStart(2, '0'),
345
+ };
346
+ }
347
+ /**
348
+ * Returns the value as a Date object.
349
+ * @type {Date|null}
350
+ */
351
+ get valueAsDate() {
352
+ try {
353
+ const d = new Date(`${this.value.year}-${this.value.month}-${this.value.day}`);
354
+ if (!(d instanceof Date) || isNaN(d.getTime()))
355
+ return null;
356
+ return d;
357
+ }
358
+ catch {
359
+ return null;
360
+ }
361
+ }
362
+ static #min(input) {
363
+ if (!input?.hasAttribute('min'))
364
+ return -Infinity;
365
+ const number = Number(input.getAttribute('min'));
366
+ if (Number.isNaN(number))
367
+ return -Infinity;
368
+ return number;
369
+ }
370
+ static #max(input) {
371
+ if (!input?.hasAttribute('max'))
372
+ return Infinity;
373
+ const number = Number(input.getAttribute('max'));
374
+ if (Number.isNaN(number))
375
+ return Infinity;
376
+ return number;
377
+ }
378
+ get minimum() {
379
+ if (!this.hasAttribute('minimum'))
380
+ return null;
381
+ try {
382
+ new Date(this.getAttribute('minimum') ?? '');
383
+ const [y = '', m = '', d = ''] = (this.getAttribute('minimum') ?? '').split(/\D+/);
384
+ return {
385
+ year: y.padStart(4, '0'),
386
+ month: m.padStart(2, '0'),
387
+ day: d.padStart(2, '0'),
388
+ };
389
+ }
390
+ catch {
391
+ return null;
392
+ }
393
+ }
394
+ get maximum() {
395
+ if (!this.hasAttribute('maximum'))
396
+ return null;
397
+ try {
398
+ new Date(this.getAttribute('maximum') ?? '');
399
+ const [y = '', m = '', d = ''] = (this.getAttribute('maximum') ?? '').split(/\D+/);
400
+ return {
401
+ year: y.padStart(4, '0'),
402
+ month: m.padStart(2, '0'),
403
+ day: d.padStart(2, '0'),
404
+ };
405
+ }
406
+ catch {
407
+ return null;
408
+ }
409
+ }
410
+ setValidity = (flags, message, anchor) => {
411
+ // let msg
412
+ // if (message)
413
+ for (const k in flags) {
414
+ const key = k; // ✅ type-safe cast
415
+ if (true !== flags[key])
416
+ continue;
417
+ for (const el of this.#slots?.get('validity-options')?.assignedElements({ flatten: true }) ?? []) {
418
+ if (!el.matches('option'))
419
+ continue;
420
+ const { label, value } = el;
421
+ if (`${kebabCase(key)}` === value) {
422
+ message = label;
423
+ break;
424
+ }
425
+ else if (`${kebabCase(key)}:${message}` === value) {
426
+ message = label;
427
+ break;
428
+ }
429
+ }
430
+ }
431
+ if (!message)
432
+ for (const k in flags) {
433
+ const key = k; // ✅ type-safe cast
434
+ if (true !== flags[key])
435
+ continue;
436
+ message = kebabCase(key);
437
+ break;
438
+ }
439
+ debug(`${_a.name} ⚡️ validity-change`);
440
+ return this.#internals.setValidity(flags, this.#customValidity || message, anchor ?? this.#inputs.at(0));
441
+ };
442
+ setCustomValidity = (message) => {
443
+ this.#customValidity = message;
444
+ if (this.#customValidity)
445
+ this.#internals.setValidity({ ...this.#internals.validity, customError: true }, message);
446
+ else
447
+ this.#sendValueToForm(false);
448
+ };
449
+ formStateRestoreCallback(state, reason) {
450
+ //
451
+ }
452
+ formAssociatedCallback(form) {
453
+ this.#sendValueToForm(false);
454
+ }
455
+ formDisabledCallback(disabled) {
456
+ for (const input of this.#inputs)
457
+ input.toggleAttribute('disabled', !disabled);
458
+ }
459
+ formResetCallback() {
460
+ this.#selectedDate = {
461
+ year: '',
462
+ month: '',
463
+ day: '',
464
+ };
465
+ this.#sendValueToForm(false);
466
+ }
467
+ }
468
+ _a = DatePicker;
@@ -0,0 +1,11 @@
1
+ export declare class DetailPlaceholder extends HTMLElement {
2
+ constructor();
3
+ connectedCallback(): void;
4
+ disconnectedCallback(): void;
5
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
6
+ }
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ 'detail-placeholder': DetailPlaceholder;
10
+ }
11
+ }
@@ -0,0 +1,15 @@
1
+ import { debug } from '../internal/utils';
2
+ export class DetailPlaceholder extends HTMLElement {
3
+ constructor() {
4
+ super();
5
+ }
6
+ connectedCallback() {
7
+ debug(`${DetailPlaceholder.name} ⚡️ connect`);
8
+ }
9
+ disconnectedCallback() {
10
+ debug(`${DetailPlaceholder.name} ⚡️ disconnect`);
11
+ }
12
+ attributeChangedCallback(name, oldValue, newValue) {
13
+ debug(`${DetailPlaceholder.name} ⚡️ attr-change [${name}]`);
14
+ }
15
+ }
@@ -0,0 +1,17 @@
1
+ import { DetailsBase } from '../namespace-browser/base';
2
+ /**
3
+ * @summary A view that shows or hides another view when the user opens or closes it.
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
+ *
7
+ * @fires is-expanded
8
+ * @fires is-collapsed
9
+ */
10
+ export declare class DisclosureGroup extends DetailsBase {
11
+ #private;
12
+ static get observedAttributes(): string[];
13
+ constructor();
14
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
15
+ static polyfillDisconnectedCallback(el: DisclosureGroup): void;
16
+ static polyfillConnectedCallback(el: DisclosureGroup): void;
17
+ }
@@ -0,0 +1,62 @@
1
+ import { CleanupRegistry } from '../internal/class/cleanup-registry';
2
+ import { cssTime, debug, onoff, timeout } from '../internal/utils';
3
+ import { DetailsBase } from '../namespace-browser/base';
4
+ const toggleTimers = new WeakMap();
5
+ /**
6
+ * @summary A view that shows or hides another view when the user opens or closes it.
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
+ *
10
+ * @fires is-expanded
11
+ * @fires is-collapsed
12
+ */
13
+ export class DisclosureGroup extends DetailsBase {
14
+ static get observedAttributes() {
15
+ return [
16
+ /**
17
+ * The status of this element
18
+ * @type {boolean}
19
+ */
20
+ 'open',
21
+ ];
22
+ }
23
+ constructor() {
24
+ super();
25
+ }
26
+ attributeChangedCallback(name, oldValue, newValue) {
27
+ debug(`${DisclosureGroup.name} ⚡️ attr-change [${name}]`);
28
+ // if (CSS.supports('interpolate-size', 'allow-keywords')) return
29
+ }
30
+ static polyfillDisconnectedCallback(el) {
31
+ debug(`${DisclosureGroup.name} ⚡️ disconnect`);
32
+ CleanupRegistry.unregister(el);
33
+ }
34
+ static polyfillConnectedCallback(el) {
35
+ debug(`${DisclosureGroup.name} ⚡️ connect`);
36
+ const newValue = el.open ? 'open' : 'closed';
37
+ if (newValue !== el.dataset.state)
38
+ el.dataset.state = newValue;
39
+ CleanupRegistry.register(el, onoff('toggle', DisclosureGroup.#handleToggle, el).on());
40
+ CleanupRegistry.register(el, () => {
41
+ toggleTimers.get(el)?.cancel();
42
+ toggleTimers.delete(el);
43
+ });
44
+ }
45
+ static #handleToggle = async ({ type, currentTarget: details }) => {
46
+ debug(`${DisclosureGroup.name} ⚡️ ${type}`);
47
+ if (!(details instanceof HTMLDetailsElement))
48
+ return;
49
+ const newValue = details.open ? 'opening' : 'closing';
50
+ if (newValue !== details.dataset.state)
51
+ details.dataset.state = newValue;
52
+ if (!toggleTimers.has(details))
53
+ toggleTimers.set(details, timeout()); //if (!toggleTimeouts.has(details)) toggleTimeouts.set(details, null)
54
+ // Cancel previous timeout for this instance
55
+ //if (toggleTimeouts.has(details) && toggleTimeouts.get(details)) self.clearTimeout(toggleTimeouts.get(details))
56
+ // Schedule a new hook
57
+ toggleTimers.get(details).next(() => {
58
+ details.dataset.state = details.open ? 'open' : 'closed';
59
+ details?.dispatchEvent(new CustomEvent(`is-${details.open ? 'expanded' : 'collapsed'}`, { bubbles: true, composed: true }));
60
+ }, cssTime(`${details.computedStyleMap().get('--disclosure-group-animation-duration')}`));
61
+ };
62
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @summary A tooltip that shows an unobtrusive helpful message on pointer:fine screens. Use it by adding a `help` attribute to any element.
3
+ */
4
+ export declare class FineTooltip extends HTMLElement {
5
+ #private;
6
+ constructor();
7
+ connectedCallback(): void;
8
+ disconnectedCallback(): void;
9
+ hidePopover(): void;
10
+ }
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ 'fine-tooltip': FineTooltip;
14
+ }
15
+ }