@swiftwc/ui 0.0.0-dev.2 → 0.0.0-dev.20

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 (277) hide show
  1. package/README.md +15 -0
  2. package/generated/client/index.d.ts +16 -2
  3. package/generated/client/index.js +290 -8
  4. package/generated/components/body-view.d.ts +5 -0
  5. package/generated/components/body-view.js +11 -0
  6. package/generated/components/bordered-button.d.ts +7 -0
  7. package/generated/components/bordered-button.js +20 -0
  8. package/generated/components/bordered-prominent-button.d.ts +7 -0
  9. package/generated/components/bordered-prominent-button.js +20 -0
  10. package/generated/components/borderless-button.d.ts +9 -0
  11. package/generated/components/borderless-button.js +35 -0
  12. package/generated/components/confirmation-dialog.d.ts +9 -0
  13. package/generated/components/confirmation-dialog.js +102 -0
  14. package/generated/components/content-unavailable-view.d.ts +24 -0
  15. package/generated/components/content-unavailable-view.js +78 -0
  16. package/generated/components/date-picker.d.ts +46 -0
  17. package/generated/components/date-picker.js +428 -0
  18. package/generated/components/disclosure-group.d.ts +9 -0
  19. package/generated/components/disclosure-group.js +51 -0
  20. package/generated/components/form-view.d.ts +6 -0
  21. package/generated/components/form-view.js +58 -0
  22. package/generated/components/glass-button.d.ts +6 -0
  23. package/generated/components/glass-button.js +17 -0
  24. package/generated/components/glass-prominent-button.d.ts +6 -0
  25. package/generated/components/glass-prominent-button.js +17 -0
  26. package/generated/components/index.d.ts +38 -1
  27. package/generated/components/index.js +38 -6
  28. package/generated/components/label-view.d.ts +9 -0
  29. package/generated/components/label-view.js +83 -0
  30. package/generated/components/list-view.d.ts +5 -0
  31. package/generated/components/list-view.js +29 -0
  32. package/generated/components/menu-view.d.ts +9 -0
  33. package/generated/components/menu-view.js +133 -0
  34. package/generated/components/navigation-large-title.d.ts +6 -0
  35. package/generated/components/navigation-large-title.js +177 -0
  36. package/generated/components/navigation-split-view.d.ts +10 -0
  37. package/generated/components/navigation-split-view.js +21 -0
  38. package/generated/components/navigation-stack.d.ts +10 -0
  39. package/generated/components/navigation-stack.js +27 -0
  40. package/generated/components/navigation-title.d.ts +8 -0
  41. package/generated/components/navigation-title.js +66 -0
  42. package/generated/components/picker-view.d.ts +27 -0
  43. package/generated/components/picker-view.js +442 -0
  44. package/generated/components/plain-button.d.ts +7 -0
  45. package/generated/components/plain-button.js +20 -0
  46. package/generated/components/screen-view.d.ts +5 -0
  47. package/generated/components/screen-view.js +9 -0
  48. package/generated/components/scroll-view-proxy.d.ts +8 -0
  49. package/generated/components/scroll-view-proxy.js +14 -0
  50. package/generated/components/scroll-view.d.ts +10 -0
  51. package/generated/components/scroll-view.js +187 -0
  52. package/generated/components/section-view.d.ts +9 -0
  53. package/generated/components/section-view.js +81 -0
  54. package/generated/components/sheet-view.d.ts +9 -0
  55. package/generated/components/sheet-view.js +69 -0
  56. package/generated/components/sidebar-toggle.d.ts +7 -0
  57. package/generated/components/sidebar-toggle.js +80 -0
  58. package/generated/components/sidebar-view.d.ts +7 -0
  59. package/generated/components/sidebar-view.js +29 -0
  60. package/generated/components/sticky-container.d.ts +6 -0
  61. package/generated/components/sticky-container.js +22 -0
  62. package/generated/components/tab-bar.d.ts +10 -0
  63. package/generated/components/tab-bar.js +36 -0
  64. package/generated/components/tab-item.d.ts +7 -0
  65. package/generated/components/tab-item.js +123 -0
  66. package/generated/components/tab-view.d.ts +22 -0
  67. package/generated/components/tab-view.js +256 -0
  68. package/generated/components/table-view.d.ts +7 -0
  69. package/generated/components/table-view.js +175 -0
  70. package/generated/components/text-field.d.ts +29 -0
  71. package/generated/components/text-field.js +473 -0
  72. package/generated/components/tool-bar-item-group.d.ts +5 -0
  73. package/generated/components/tool-bar-item-group.js +11 -0
  74. package/generated/components/tool-bar-item.d.ts +5 -0
  75. package/generated/components/tool-bar-item.js +19 -0
  76. package/generated/components/tool-bar.d.ts +7 -0
  77. package/generated/components/tool-bar.js +77 -0
  78. package/generated/components/v-keyboard.d.ts +11 -0
  79. package/generated/components/v-keyboard.js +81 -0
  80. package/generated/components/v-stack.d.ts +5 -0
  81. package/generated/components/v-stack.js +11 -0
  82. package/generated/confirmation-dialog/index.d.ts +1 -0
  83. package/generated/confirmation-dialog/index.js +1 -0
  84. package/generated/css/index.css +7503 -0
  85. package/generated/events/confirmation-dialog.d.ts +9 -0
  86. package/generated/events/confirmation-dialog.js +1 -0
  87. package/generated/events/date-picker.d.ts +8 -0
  88. package/generated/events/date-picker.js +1 -0
  89. package/generated/events/index.d.ts +7 -0
  90. package/generated/events/index.js +7 -0
  91. package/generated/events/lifecycle-observer.d.ts +10 -0
  92. package/generated/events/lifecycle-observer.js +1 -0
  93. package/generated/events/picker-view.d.ts +8 -0
  94. package/generated/events/picker-view.js +1 -0
  95. package/generated/events/scroll-view.d.ts +10 -0
  96. package/generated/events/scroll-view.js +1 -0
  97. package/generated/events/tab-view.d.ts +24 -0
  98. package/generated/events/tab-view.js +1 -0
  99. package/generated/events/text-field.d.ts +8 -0
  100. package/generated/events/text-field.js +1 -0
  101. package/generated/i18n/index.d.ts +34 -0
  102. package/generated/i18n/index.js +167 -0
  103. package/generated/i18n/locales/el.d.ts +8 -0
  104. package/generated/i18n/locales/el.js +8 -0
  105. package/generated/i18n/locales/en.d.ts +8 -0
  106. package/generated/i18n/locales/en.js +8 -0
  107. package/generated/i18n/locales/index.d.ts +4 -0
  108. package/generated/i18n/locales/index.js +4 -0
  109. package/generated/index.js +1 -1
  110. package/generated/internal/class/cleanup-registry.d.ts +5 -0
  111. package/generated/internal/class/cleanup-registry.js +38 -0
  112. package/generated/internal/class/css-style-observer.d.ts +8 -0
  113. package/generated/internal/class/css-style-observer.js +25 -0
  114. package/generated/internal/class/form-associated-base.d.ts +20 -0
  115. package/generated/internal/class/form-associated-base.js +93 -0
  116. package/generated/internal/class/mutation-observer-singleton.d.ts +10 -0
  117. package/generated/internal/class/mutation-observer-singleton.js +46 -0
  118. package/generated/internal/class/navigation-path.d.ts +15 -0
  119. package/generated/internal/class/navigation-path.js +84 -0
  120. package/generated/internal/class/navigation-view.d.ts +8 -0
  121. package/generated/internal/class/navigation-view.js +77 -0
  122. package/generated/internal/class/resize-observer-singleton.d.ts +7 -0
  123. package/generated/internal/class/resize-observer-singleton.js +22 -0
  124. package/generated/internal/decorators/custom-element.d.ts +5 -0
  125. package/generated/internal/decorators/custom-element.js +4 -0
  126. package/generated/internal/privateNamespace.d.ts +4 -0
  127. package/generated/internal/privateNamespace.js +1 -0
  128. package/generated/internal/utils/add.d.ts +1 -0
  129. package/generated/internal/utils/add.js +7 -0
  130. package/generated/internal/utils/cash/ancestors.d.ts +1 -0
  131. package/generated/internal/utils/cash/ancestors.js +27 -0
  132. package/generated/internal/utils/cash/index.d.ts +22 -0
  133. package/generated/internal/utils/cash/index.js +23 -0
  134. package/generated/internal/utils/cash/next-all.d.ts +1 -0
  135. package/generated/internal/utils/cash/next-all.js +10 -0
  136. package/generated/internal/utils/cash/next.d.ts +1 -0
  137. package/generated/internal/utils/cash/next.js +9 -0
  138. package/generated/internal/utils/cash/prev-all.d.ts +1 -0
  139. package/generated/internal/utils/cash/prev-all.js +10 -0
  140. package/generated/internal/utils/cash/prev.d.ts +1 -0
  141. package/generated/internal/utils/cash/prev.js +9 -0
  142. package/generated/internal/utils/cash/prop.d.ts +18 -0
  143. package/generated/internal/utils/cash/prop.js +30 -0
  144. package/generated/internal/utils/cash/siblings.d.ts +1 -0
  145. package/generated/internal/utils/cash/siblings.js +10 -0
  146. package/generated/internal/utils/clamp.d.ts +1 -0
  147. package/generated/internal/utils/clamp.js +4 -0
  148. package/generated/internal/utils/compare-big-decimals.d.ts +1 -0
  149. package/generated/internal/utils/compare-big-decimals.js +90 -0
  150. package/generated/internal/utils/css-time.d.ts +1 -0
  151. package/generated/internal/utils/css-time.js +3 -0
  152. package/generated/internal/utils/debounce.d.ts +1 -0
  153. package/generated/internal/utils/debounce.js +13 -0
  154. package/generated/internal/utils/frame.d.ts +1 -0
  155. package/generated/internal/utils/frame.js +6 -0
  156. package/generated/internal/utils/index.d.ts +17 -1
  157. package/generated/internal/utils/index.js +18 -1
  158. package/generated/internal/utils/kebab-case.d.ts +1 -1
  159. package/generated/internal/utils/kebab-case.js +3 -3
  160. package/generated/internal/utils/list-active.d.ts +7 -0
  161. package/generated/internal/utils/list-active.js +73 -0
  162. package/generated/internal/utils/microtask.d.ts +1 -0
  163. package/generated/internal/utils/microtask.js +3 -0
  164. package/generated/internal/utils/onoff.d.ts +45 -0
  165. package/generated/internal/utils/onoff.js +31 -0
  166. package/generated/internal/utils/set.d.ts +1 -0
  167. package/generated/internal/utils/set.js +7 -0
  168. package/generated/internal/utils/sleep.d.ts +1 -0
  169. package/generated/internal/utils/sleep.js +3 -0
  170. package/generated/internal/utils/slow-hide-show.d.ts +1 -0
  171. package/generated/internal/utils/slow-hide-show.js +16 -0
  172. package/generated/internal/utils/timeout.d.ts +5 -0
  173. package/generated/internal/utils/timeout.js +16 -0
  174. package/generated/internal/utils/touch-glass.d.ts +7 -0
  175. package/generated/internal/utils/touch-glass.js +19 -0
  176. package/generated/lifecycle-observer/index.d.ts +1 -0
  177. package/generated/lifecycle-observer/index.js +1 -0
  178. package/generated/namespace-browser/base.d.ts +36 -0
  179. package/generated/namespace-browser/base.js +92 -0
  180. package/generated/namespace-browser/index.d.ts +7 -0
  181. package/generated/namespace-browser/index.js +1 -0
  182. package/generated/snapshot/index.d.ts +7 -0
  183. package/generated/snapshot/index.js +37 -0
  184. package/package.json +33 -9
  185. package/scss/_base.scss +5 -0
  186. package/scss/_components.scss +77 -0
  187. package/scss/_final.scss +1 -0
  188. package/scss/_functions.scss +21 -0
  189. package/scss/_mixins.scss +3 -0
  190. package/scss/_placeholders.scss +3 -0
  191. package/scss/_transitions.scss +27 -0
  192. package/scss/_utils.scss +9 -0
  193. package/scss/_vars.scss +174 -3
  194. package/scss/base/_layout.scss +56 -0
  195. package/scss/base/_reboot.scss +160 -0
  196. package/scss/base/_root.scss +396 -0
  197. package/scss/colors/_index.scss +635 -0
  198. package/scss/components/_body-view.scss +17 -0
  199. package/scss/components/_bordered-button.scss +30 -0
  200. package/scss/components/_bordered-prominent-button.scss +27 -0
  201. package/scss/components/_borderless-button.scss +27 -0
  202. package/scss/components/_components.scss +76 -0
  203. package/scss/components/_confirmation-dialog.scss +110 -0
  204. package/scss/components/_content-unavailable-view.scss +45 -0
  205. package/scss/components/_date-picker.scss +30 -0
  206. package/scss/components/_detail-placeholder.scss +153 -0
  207. package/scss/components/_disclosure-group.scss +128 -0
  208. package/scss/components/_form-view.scss +195 -0
  209. package/scss/components/_full-screen.scss +15 -0
  210. package/scss/components/_glass-button.scss +32 -0
  211. package/scss/components/_glass-prominent-button.scss +32 -0
  212. package/scss/components/_h-divider.scss +13 -0
  213. package/scss/components/_h-flex-stack.scss +23 -0
  214. package/scss/components/_h-stack.scss +39 -0
  215. package/scss/components/_index.scss +245 -0
  216. package/scss/components/_label-view.scss +393 -0
  217. package/scss/components/_labeled-content.scss +9 -0
  218. package/scss/components/_list-view.scss +229 -0
  219. package/scss/components/_menu-view.scss +188 -0
  220. package/scss/components/_navigation-large-title.scss +27 -0
  221. package/scss/components/_navigation-split-view.scss +424 -0
  222. package/scss/components/_navigation-stack.scss +11 -0
  223. package/scss/components/_navigation-title.scss +10 -0
  224. package/scss/components/_picker-view.scss +122 -0
  225. package/scss/components/_plain-button.scss +18 -0
  226. package/scss/components/_scroll-view-proxy.scss +79 -0
  227. package/scss/components/_scroll-view-toolbars.scss +126 -0
  228. package/scss/components/_scroll-view.scss +130 -0
  229. package/scss/components/_section-view.scss +119 -0
  230. package/scss/components/_sheet-view.scss +92 -0
  231. package/scss/components/_sidebar-toggle.scss +121 -0
  232. package/scss/components/_sidebar-view.scss +53 -0
  233. package/scss/components/_sticky-container.scss +42 -0
  234. package/scss/components/_tab-bar.scss +255 -0
  235. package/scss/components/_tab-item.scss +25 -0
  236. package/scss/components/_tab-view.scss +312 -0
  237. package/scss/components/_table-column.scss +52 -0
  238. package/scss/components/_table-row.scss +172 -0
  239. package/scss/components/_table-view.scss +223 -0
  240. package/scss/components/_text-field.scss +37 -0
  241. package/scss/components/_tool-bar-item-group.scss +48 -0
  242. package/scss/components/_tool-bar-item.scss +145 -0
  243. package/scss/components/_tool-bar.scss +128 -0
  244. package/scss/components/_v-divider.scss +13 -0
  245. package/scss/components/_v-flex-stack.scss +29 -0
  246. package/scss/components/_v-keyboard.scss +14 -0
  247. package/scss/components/_v-stack.scss +35 -0
  248. package/scss/final/_touch-glass.scss +84 -0
  249. package/scss/index.scss +15 -6
  250. package/scss/mixins/_dialog.scss +89 -0
  251. package/scss/mixins/_index.scss +405 -0
  252. package/scss/placeholders/_buttons.scss +83 -0
  253. package/scss/placeholders/_lists.scss +561 -0
  254. package/scss/transitions/_bwd.navbar.scss +19 -0
  255. package/scss/transitions/_bwd.scss +39 -0
  256. package/scss/transitions/_confirmation-dialog.scss +19 -0
  257. package/scss/transitions/_dialog.scss +28 -0
  258. package/scss/transitions/_disclosure-group.scss +35 -0
  259. package/scss/transitions/_fwd.navbar.scss +41 -0
  260. package/scss/transitions/_fwd.scss +24 -0
  261. package/scss/transitions/_glass-button.scss +12 -0
  262. package/scss/transitions/_glass-prominent-button.scss +12 -0
  263. package/scss/transitions/_index.scss +74 -0
  264. package/scss/transitions/_menu-view.scss +26 -0
  265. package/scss/transitions/_navigation-split-view.scss +23 -0
  266. package/scss/transitions/_sidebar-view.scss +36 -0
  267. package/scss/transitions/_tab-bar.scss +19 -0
  268. package/scss/utils/_frame.scss +84 -0
  269. package/scss/utils/_index.scss +68 -0
  270. package/scss/utils/_scroll-view.scss +14 -0
  271. package/scss/utils/_spacing.scss +25 -0
  272. package/scss/utils/_stacks.scss +247 -0
  273. package/web-components.html-data/en.json +346 -0
  274. package/generated/internal/snapshot.d.ts +0 -5
  275. package/generated/internal/snapshot.js +0 -23
  276. package/generated/styles.css +0 -8
  277. package/scss/_reboot.scss +0 -11
@@ -0,0 +1,473 @@
1
+ var _a;
2
+ import { I18n } from '../i18n';
3
+ import { CleanupRegistry } from '../internal/class/cleanup-registry';
4
+ import { FormAssociatedBase, getInternals, makeSlotchangeHandler } from '../internal/class/form-associated-base';
5
+ import { $, compareBigDecimals, kebabCase, onoff, set } from '../internal/utils';
6
+ const keyboardTypes = ['decimal-pad', 'number-pad', 'default'];
7
+ /**
8
+ * @slot label
9
+ * @slot validity-options
10
+ */
11
+ export class TextField extends FormAssociatedBase {
12
+ static get observedAttributes() {
13
+ return ['prompt', 'minimum', 'maximum', 'min-length', 'max-length', 'label', 'name', 'text', 'text-input-autocapitalization', 'disable-autocorrection', 'keyboard-type', 'required', 'disabled'];
14
+ }
15
+ static #template;
16
+ static get template() {
17
+ return (this.#template ??= $(String.raw `
18
+ <label part="root text-field-stack">
19
+ <div part="root text-field-label-stack">
20
+ <slot name="label"></slot>
21
+ </div>
22
+ <div part="root text-field-input-stack">
23
+ <input type="text" part="root input text-field-form-input">
24
+ </div>
25
+ <slot name="validity-options" hidden></slot>
26
+ </label>`, ''));
27
+ }
28
+ #shadowRoot;
29
+ // #internals: ElementInternals
30
+ #customValidity = '';
31
+ #validitiesSlot;
32
+ #input;
33
+ get #internals() {
34
+ return getInternals(this);
35
+ }
36
+ constructor() {
37
+ super();
38
+ this.#shadowRoot = this.attachShadow({ mode: 'closed' });
39
+ this.#shadowRoot.appendChild(document.importNode(this.constructor.template, true));
40
+ this.#validitiesSlot = this.#shadowRoot.querySelector('slot[name=validity-options]') ?? undefined;
41
+ CleanupRegistry.unregister(this, 'validities');
42
+ CleanupRegistry.register(this, onoff(makeSlotchangeHandler(this), this.#validitiesSlot).on(), 'validities');
43
+ this.#input = this.#shadowRoot.querySelector('input') ?? undefined;
44
+ CleanupRegistry.register(this, onoff([{ types: 'focusin', listener: this.#handleFocusin }], this).on());
45
+ CleanupRegistry.register(this, onoff([
46
+ { types: 'blur', listener: this.#handleInputBlur },
47
+ { types: 'input', listener: this.#handleInputInput },
48
+ { types: 'beforeinput', listener: this.#handleInputBeforeinput },
49
+ { types: 'paste', listener: this.#handleInputPaste },
50
+ ], this.#input).on());
51
+ CleanupRegistry.register(this, onoff('localechange', () => {
52
+ this.text = this.text;
53
+ }, I18n.on).on());
54
+ }
55
+ connectedCallback() {
56
+ super.connectedCallback();
57
+ // finally
58
+ if (!this.hasAttribute('text'))
59
+ return;
60
+ this.text = this.getAttribute('text') ?? ''; // this.#input.value = this.getAttribute('text') ?? ''
61
+ this.#sendValueToForm(false);
62
+ }
63
+ disconnectedCallback() {
64
+ super.disconnectedCallback();
65
+ }
66
+ attributeChangedCallback(name, oldValue, newValue) {
67
+ console.debug(`${_a.name} ⚡️ attr-change [${name}] ("${oldValue}" → "${newValue}")`);
68
+ switch (name) {
69
+ case 'keyboard-type':
70
+ switch (newValue) {
71
+ case 'decimal-pad':
72
+ this.#input?.setAttribute('inputmode', 'decimal');
73
+ break;
74
+ case 'number-pad':
75
+ this.#input?.setAttribute('inputmode', 'numeric');
76
+ break;
77
+ case 'default':
78
+ default:
79
+ this.#input?.removeAttribute('inputmode');
80
+ break;
81
+ }
82
+ this.#sendValueToForm();
83
+ break;
84
+ case 'text-input-autocapitalization':
85
+ switch (newValue) {
86
+ case 'never':
87
+ this.#input?.setAttribute('autocapitalize', 'off');
88
+ break;
89
+ case 'characters':
90
+ this.#input?.setAttribute('autocapitalize', newValue);
91
+ break;
92
+ case 'words':
93
+ this.#input?.setAttribute('autocapitalize', newValue);
94
+ break;
95
+ default:
96
+ case 'sentences':
97
+ this.#input?.setAttribute('autocapitalize', 'on');
98
+ break;
99
+ }
100
+ break;
101
+ case 'disable-autocorrection':
102
+ if ('' === newValue)
103
+ for (const [k, v] of [
104
+ ['autocomplete', 'off'],
105
+ ['autocorrect', 'off'],
106
+ ['spellcheck', 'false'],
107
+ ])
108
+ this.#input?.setAttribute(k, v);
109
+ else
110
+ for (const k of ['autocomplete', 'autocorrect', 'spellcheck'])
111
+ this.#input?.removeAttribute(k);
112
+ break;
113
+ case 'text':
114
+ // if (this.#input) this.#input.value = newValue ?? ''
115
+ this.text = newValue ?? '';
116
+ break;
117
+ case 'required':
118
+ this.#input?.setAttribute(name, newValue ?? ''); // else this.#input?.removeAttribute(name)
119
+ this.#sendValueToForm();
120
+ break;
121
+ case 'name':
122
+ case 'minimum':
123
+ case 'maximum':
124
+ this.#sendValueToForm();
125
+ break;
126
+ case 'prompt':
127
+ this.#input?.setAttribute('placeholder', newValue ?? ''); // else this.#input?.removeAttribute(name)
128
+ break;
129
+ case 'min-length':
130
+ this.#input?.setAttribute('minlength', newValue ?? '');
131
+ this.#sendValueToForm();
132
+ break;
133
+ case 'max-length':
134
+ this.#input?.setAttribute('maxlength', newValue ?? '');
135
+ this.#sendValueToForm();
136
+ break;
137
+ case 'label':
138
+ let label = this.querySelector(':scope>[slot=label]');
139
+ if (newValue) {
140
+ label ??= this.appendChild($(`<span slot="label" foreground="secondary"></span>`));
141
+ label.textContent = newValue;
142
+ }
143
+ else
144
+ label?.remove();
145
+ this.#sendValueToForm();
146
+ break;
147
+ case 'disabled':
148
+ for (const el of this.#shadowRoot.querySelectorAll('input'))
149
+ el.toggleAttribute('disabled', !newValue);
150
+ break;
151
+ }
152
+ // render pattern
153
+ switch (this.keyboardType) {
154
+ case 'decimal-pad':
155
+ const allowedSignsRegex2 = String.raw `[+\-]?|[+\-]?(\d+([.,]\d*)?|[.,]\d*)`, // allow single '+' or '-', then allow only one ',' or '.' and finally only digits
156
+ digitsDecimalsOnlyRegex = String.raw `(\d+([.,]\d*)?|[.,]\d*)?`; // allow only one ',' or '.' and finally only digits
157
+ this.#input?.setAttribute('pattern', this.negativeNumbersAllowed ? allowedSignsRegex2 : digitsDecimalsOnlyRegex);
158
+ break;
159
+ case 'number-pad':
160
+ const allowedSignsRegex = String.raw `([+\-]|\d+|[+\-]\d+)?`, // allow single '+' or '-', then allow only digits
161
+ digitsOnlyRegex = String.raw `\d*`; // allow only digits
162
+ this.#input?.setAttribute('pattern', this.negativeNumbersAllowed ? allowedSignsRegex : digitsOnlyRegex);
163
+ break;
164
+ default:
165
+ this.#input?.removeAttribute('pattern');
166
+ break;
167
+ }
168
+ }
169
+ get keyboardType() {
170
+ return keyboardTypes.includes(this.getAttribute('keyboard-type') ?? '') ? this.getAttribute('keyboard-type') : 'default';
171
+ }
172
+ get text() {
173
+ return this.#input?.value ?? '';
174
+ }
175
+ set text(v) {
176
+ if (!this.#input)
177
+ return;
178
+ const nv = this.#patternTest(v) ? v : '';
179
+ set(this.#input, 'value', nv);
180
+ // this.text AND this.value have NOW been updated to new values
181
+ // if user is NOT interacting replace new-text/input.value with the formatted version of the new-text/input.value!
182
+ if (document.activeElement !== this && 0 < this.#input.value.length) {
183
+ const finalText = this.value.replace(/[.,]/g, I18n.decimalSeparator);
184
+ set(this.#input, 'value', finalText); // if (this.text !== finalText) this.#input.value = finalText
185
+ }
186
+ }
187
+ #handleFocusin = (evt) => {
188
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
189
+ if (evt.target === this)
190
+ this.#input?.focus();
191
+ };
192
+ #sendValueToForm = (dispatchEvent = true) => {
193
+ // input.value has already been updated/synced !!
194
+ if (this.matches(':disabled'))
195
+ return this.setValidity({});
196
+ // if (this.hasAttribute('required')) {
197
+ if (this.#input?.matches(':invalid')) {
198
+ this.setValidity(this.#input?.validity, this.#input?.validationMessage);
199
+ }
200
+ else if (['number-pad', 'decimal-pad'].includes(this.keyboardType) && (this.hasAttribute('minimum') || this.hasAttribute('maximum'))) {
201
+ const underflow = compareBigDecimals(this.value, this.getAttribute('minimum') ?? '-Infinity'), overflow = compareBigDecimals(this.value, this.getAttribute('maximum') ?? 'Infinity');
202
+ if (0 > underflow)
203
+ this.setValidity({ rangeUnderflow: true });
204
+ else if (0 < overflow)
205
+ this.setValidity({ rangeOverflow: true });
206
+ else
207
+ this.setValidity({});
208
+ }
209
+ else {
210
+ this.setValidity({});
211
+ }
212
+ const entries = new FormData();
213
+ entries.append(this.name, this.text);
214
+ this.#internals.setFormValue(entries);
215
+ if (dispatchEvent)
216
+ this.dispatchEvent(new CustomEvent('commit', { detail: { text: this.text }, bubbles: true, composed: true }));
217
+ };
218
+ #handleInputPaste = (evt) => {
219
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
220
+ const input = evt.target;
221
+ if (!input)
222
+ return;
223
+ evt.preventDefault();
224
+ const data = this.#identity(evt.clipboardData?.getData('text') ?? ''); // number is now sanitized but contains edge cases like '+' and also global one separator that could be wither dot or decimal.
225
+ if (0 === data.length)
226
+ return this.shake(); //.then(this.reportValidity) // nothing to paste
227
+ const start = input.selectionStart ?? 0, end = input.selectionEnd ?? 0, before = input.value.slice(0, start), after = input.value.slice(end), newText = `${before}${data}${after}`;
228
+ if (-1 < input.maxLength && input.maxLength < newText.length)
229
+ return this.shake(); //.then(this.reportValidity) // exceeding maxlength
230
+ input.value = newText;
231
+ const newCaret = start + data.length;
232
+ input.setSelectionRange(newCaret, newCaret); // move caret after inserted char
233
+ this.#sendValueToForm(); // input.dispatchEvent(new InputEvent('input', { bubbles: true })) // Manually trigger input event so listeners react
234
+ };
235
+ // NOTE: identity MUST always pass beforeinput checks
236
+ #identity = (str) => {
237
+ // 'ab-1.2.3.4x yz ' // "-1.234"
238
+ // '++12..34 ' // "+12.34"
239
+ // '-+5.6.7.8 ' // "-5.678"
240
+ // ' -+5.6,7.8 ' // "-5.678"
241
+ // 'foo123bar ' // "123"
242
+ // '.12.3 ' // ".123"
243
+ // ' http://localhost:5173/input.html' // "5173."
244
+ // ' http://localhost:51,73/input.html' // "51,73"
245
+ // ' +- 0000.' // "+0000."
246
+ // ' +' // "+"
247
+ // ' +0000234' // "+0000234"
248
+ // ' +-1.2.3.4x yz ' // "+1.234"
249
+ let seenSign = false;
250
+ switch (this.keyboardType) {
251
+ case 'decimal-pad': // allow only ^+- and then only one instance of ., finally remove all non digit rest appearances
252
+ let seenDot = false;
253
+ return [...`${str.trim()}`].reduce((acc, ch, i) => {
254
+ // +- signs are allowed
255
+ if (this.negativeNumbersAllowed)
256
+ if (!seenSign && (ch === '+' || ch === '-')) {
257
+ seenSign = true;
258
+ return `${acc}${ch}`;
259
+ }
260
+ if ((ch === '.' || ch === ',') && !seenDot) {
261
+ seenDot = true;
262
+ return `${acc}${ch}`;
263
+ }
264
+ if (/\d/.test(ch))
265
+ return `${acc}${ch}`;
266
+ return acc; // skip everything else
267
+ }, '');
268
+ case 'number-pad': // allow only ^+- finally remove all non digit rest appearances
269
+ return [...`${str.trim()}`].reduce((acc, ch, i) => {
270
+ // +- signs are allowed
271
+ if (this.negativeNumbersAllowed)
272
+ if (!seenSign && (ch === '+' || ch === '-')) {
273
+ seenSign = true;
274
+ return `${acc}${ch}`;
275
+ }
276
+ if (/\d/.test(ch))
277
+ return `${acc}${ch}`;
278
+ return acc; // skip everything else
279
+ }, '');
280
+ default:
281
+ return `${str}`;
282
+ }
283
+ };
284
+ #patternTest = (str) => {
285
+ switch (this.keyboardType) {
286
+ case 'decimal-pad':
287
+ const allowedSignsRegex2 = /^[+-]?$|^[+-]?(\d+([.,]\d*)?|[.,]\d*)$/, // allow single '+' or '-', then allow only one ',' or '.' and finally only digits
288
+ digitsDecimalsOnlyRegex = /^(\d+([.,]\d*)?|[.,]\d*)?$/; // allow only one ',' or '.' and finally only digits
289
+ return (this.negativeNumbersAllowed ? allowedSignsRegex2 : digitsDecimalsOnlyRegex).test(str);
290
+ // // console.log(isValidDecimal("")); // true
291
+ // // console.log(isValidDecimal("+")); // true
292
+ // // console.log(isValidDecimal("-")); // true
293
+ // // console.log(isValidDecimal("123")); // true
294
+ // // console.log(isValidDecimal("+123")); // true
295
+ // // console.log(isValidDecimal("-456")); // true
296
+ // // console.log(isValidDecimal("12.34")); // true
297
+ // // console.log(isValidDecimal("-0,56")); // true
298
+ // // console.log(isValidDecimal(".78")); // true
299
+ // // console.log(isValidDecimal(",9")); // true
300
+ // // console.log(isValidDecimal("12.3.4")); // false
301
+ // // console.log(isValidDecimal("12,3,4")); // false
302
+ // // console.log(isValidDecimal("12-3")); // false
303
+ // // console.log(isValidDecimal("12a")); // false
304
+ case 'number-pad':
305
+ const allowedSignsRegex = /^([+-]|\d+|[+-]\d+)?$/, // allow single '+' or '-', then allow only digits
306
+ digitsOnlyRegex = /^(\d+)?$/; // allow only digits
307
+ return (this.negativeNumbersAllowed ? allowedSignsRegex : digitsOnlyRegex).test(str);
308
+ // // console.log(isValidInteger("")); // true
309
+ // // console.log(isValidInteger("+")); // true
310
+ // // console.log(isValidInteger("-")); // true
311
+ // // console.log(isValidInteger("123")); // true
312
+ // // console.log(isValidInteger("+123")); // true
313
+ // // console.log(isValidInteger("-456")); // true
314
+ // // console.log(isValidInteger("12-3")); // false
315
+ // // console.log(isValidInteger("++123")); // false
316
+ // // console.log(isValidInteger("123a")); // false
317
+ default:
318
+ return true;
319
+ }
320
+ };
321
+ #handleInputBeforeinput = (evt) => {
322
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
323
+ const input = evt.target;
324
+ if (!input)
325
+ return;
326
+ if ('insertText' !== evt.inputType)
327
+ return;
328
+ const data = evt.data ?? '';
329
+ if (-1 < input.maxLength && 0 === data.length) {
330
+ evt.preventDefault();
331
+ return this.shake(); //.then(this.reportValidity)
332
+ } // nothing to add
333
+ const start = input.selectionStart ?? 0, end = input.selectionEnd ?? 0, before = this.text.slice(0, start), after = this.text.slice(end), newText = `${before}${data}${after}`;
334
+ if (0 === newText.length)
335
+ return;
336
+ switch (input.getAttribute('inputmode')) {
337
+ case 'decimal':
338
+ // const allowedSignsRegex2 = /^[+-]?$|^[+-]?(\d+([.,]\d*)?|[.,]\d*)$/, // allow single '+' or '-', then allow only one ',' or '.' and finally only digits
339
+ // digitsDecimalsOnlyRegex = /^(\d+([.,]\d*)?|[.,]\d*)?$/ // allow only one ',' or '.' and finally only digits
340
+ // if ((this.min < 0 ? allowedSignsRegex2 : digitsDecimalsOnlyRegex).test(newText)) break
341
+ if (this.#patternTest(newText))
342
+ break;
343
+ evt.preventDefault();
344
+ return this.shake(); //.then(this.reportValidity)
345
+ case 'numeric':
346
+ // const allowedSignsRegex = /^([+-]|\d+|[+-]\d+)?$/, // allow single '+' or '-', then allow only digits
347
+ // digitsOnlyRegex = /^(\d+)?$/ // allow only digits
348
+ // if ((this.min < 0 ? allowedSignsRegex : digitsOnlyRegex).test(newText)) break
349
+ if (this.#patternTest(newText))
350
+ break;
351
+ evt.preventDefault();
352
+ return this.shake(); //.then(this.reportValidity)
353
+ // this.setValidity(prevValidity, prevValiditationMessage) // restore
354
+ }
355
+ };
356
+ #handleInputBlur = (evt) => {
357
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
358
+ const input = evt.target;
359
+ if (!input)
360
+ return;
361
+ if (0 === input.value.length)
362
+ return;
363
+ const finalText = this.value.replace(/[.,]/g, I18n.decimalSeparator);
364
+ if (!set(input, 'value', finalText))
365
+ return;
366
+ this.#sendValueToForm();
367
+ };
368
+ #handleInputInput = (evt) => {
369
+ console.debug(`${_a.name} ⚡️ ${evt?.type}`);
370
+ this.#sendValueToForm();
371
+ };
372
+ // Optional: form participation properties
373
+ get name() {
374
+ return this.getAttribute('name') ?? this.getAttribute('label') ?? this.querySelector(':scope>[slot=label]')?.textContent ?? '';
375
+ }
376
+ get value() {
377
+ // text allows special edge cases, like '-.' or '+' and generally might be invalid number. It might also be localized and not US based.
378
+ // here we make sure it is number-like, to be used in number operations.
379
+ switch (this.keyboardType) {
380
+ case 'decimal-pad':
381
+ case 'number-pad':
382
+ if ('string' !== typeof this.text)
383
+ return '0';
384
+ const value = this.text.replace(/[.,]/g, '.');
385
+ // Capture optional leading sign
386
+ const sign = value.startsWith('-') ? '-' : '';
387
+ // Strip sign for processing
388
+ let s = value.replace(/^[+-]/, '');
389
+ // Split on dot (take only first two parts in case of multiple dots — though
390
+ // your input guarantees one, this is defensive)
391
+ const [intPart = '', fracPart = ''] = s.split('.'), hasDot = s.includes('.');
392
+ // Remove leading zeros from integer part, keep at least '0'
393
+ const cleanInt = intPart.replace(/^0+/, '') || '0';
394
+ // Remove trailing zeros from fractional part
395
+ const cleanFrac = fracPart.replace(/0+$/, '');
396
+ // Build result
397
+ const result = hasDot && cleanFrac.length > 0 ? `${sign}${cleanInt}.${cleanFrac}` : `${sign}${cleanInt}`;
398
+ return result.replace(/^-0(\.0+)?$/, '0');
399
+ default:
400
+ return this.text;
401
+ }
402
+ }
403
+ get valueAsNumber() {
404
+ switch (this.keyboardType) {
405
+ case 'decimal-pad':
406
+ case 'number-pad':
407
+ return Number(this.value);
408
+ default:
409
+ return '';
410
+ }
411
+ }
412
+ get negativeNumbersAllowed() {
413
+ // switch (this.keyboardType) {
414
+ // case 'decimal-pad':
415
+ // case 'number-pad':
416
+ const min = this.getAttribute('minimum') ?? '-Infinity', max = this.getAttribute('maximum') ?? 'Infinity';
417
+ return compareBigDecimals('0', min) >= 0 && compareBigDecimals('0', max) <= 0;
418
+ // default:
419
+ // return false
420
+ // }
421
+ }
422
+ setValidity = (flags, message, anchor) => {
423
+ // let msg
424
+ // if (message)
425
+ for (const k in flags) {
426
+ const key = k; // ✅ type-safe cast
427
+ if (true !== flags[key])
428
+ continue;
429
+ for (const el of this.#validitiesSlot?.assignedElements({ flatten: true }) ?? []) {
430
+ if (!el.matches('option'))
431
+ continue;
432
+ const option = el;
433
+ if (`${kebabCase(key)}` === option.value) {
434
+ message = option.label;
435
+ break;
436
+ }
437
+ else if (`${kebabCase(key)}:${message}` === option.value) {
438
+ message = option.label;
439
+ break;
440
+ }
441
+ }
442
+ }
443
+ if (!message)
444
+ for (const k in flags) {
445
+ const key = k; // ✅ type-safe cast
446
+ if (true !== flags[key])
447
+ continue;
448
+ message = kebabCase(key);
449
+ break;
450
+ }
451
+ console.debug(`${_a.name} ⚡️ validity-change`);
452
+ return this.#internals.setValidity(flags, this.#customValidity || message, anchor ?? this.#input);
453
+ };
454
+ setCustomValidity = (message) => {
455
+ this.#customValidity = message;
456
+ if (this.#customValidity)
457
+ this.#internals.setValidity({ ...this.#internals.validity, customError: true }, message);
458
+ else
459
+ this.#sendValueToForm(false);
460
+ };
461
+ formAssociatedCallback = (form) => {
462
+ this.#sendValueToForm();
463
+ };
464
+ formDisabledCallback = (disabled) => {
465
+ for (const el of this.#shadowRoot.querySelectorAll('input'))
466
+ el.toggleAttribute('disabled', !disabled);
467
+ };
468
+ formResetCallback = () => {
469
+ this.text = '';
470
+ this.#sendValueToForm();
471
+ };
472
+ }
473
+ _a = TextField;
@@ -0,0 +1,5 @@
1
+ export declare class ToolBarItemGroup extends HTMLElement {
2
+ constructor();
3
+ connectedCallback(): void;
4
+ disconnectedCallback(): void;
5
+ }
@@ -0,0 +1,11 @@
1
+ export class ToolBarItemGroup extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ }
5
+ connectedCallback() {
6
+ console.debug(`${ToolBarItemGroup.name} ⚡️ connect`);
7
+ }
8
+ disconnectedCallback() {
9
+ console.debug(`${ToolBarItemGroup.name} ⚡️ disconnect`);
10
+ }
11
+ }
@@ -0,0 +1,5 @@
1
+ export declare class ToolBarItem extends HTMLElement {
2
+ constructor();
3
+ connectedCallback(): void;
4
+ disconnectedCallback(): void;
5
+ }
@@ -0,0 +1,19 @@
1
+ import { CleanupRegistry } from '../internal/class/cleanup-registry';
2
+ import { onoff, touchGlass } from '../internal/utils';
3
+ export class ToolBarItem extends HTMLElement {
4
+ constructor() {
5
+ super();
6
+ }
7
+ connectedCallback() {
8
+ console.debug(`${ToolBarItem.name} ⚡️ connect`);
9
+ CleanupRegistry.register(this, onoff(touchGlass(this, (t) => t.closest('tool-bar-item-group') ?? t, (evt) => {
10
+ if (evt.target.closest('menu-view[open]'))
11
+ return false;
12
+ return true;
13
+ }), this).on());
14
+ }
15
+ disconnectedCallback() {
16
+ console.debug(`${ToolBarItem.name} ⚡️ disconnect`);
17
+ CleanupRegistry.unregister(this);
18
+ }
19
+ }
@@ -0,0 +1,7 @@
1
+ export declare class ToolBar extends HTMLElement {
2
+ #private;
3
+ static get template(): DocumentFragment;
4
+ constructor();
5
+ connectedCallback(): void;
6
+ disconnectedCallback(): void;
7
+ }
@@ -0,0 +1,77 @@
1
+ var _a;
2
+ import { ResizeObserverSingleton } from '../internal/class/resize-observer-singleton';
3
+ import { $ } from '../internal/utils';
4
+ const observers = new ResizeObserverSingleton();
5
+ export class ToolBar extends HTMLElement {
6
+ static #template;
7
+ static get template() {
8
+ // <!--exportparts="toolbar-leading-stack,toolbar-principal-stack,toolbar-trailing-stack"-->
9
+ return (this.#template ??= $(String.raw `
10
+ <div part="root top-bar">
11
+ <div part="root toolbar-leading-stack">
12
+ <slot name="top-bar-leading"></slot>
13
+ </div>
14
+ <div part="root toolbar-principal-stack">
15
+ <slot name="top-bar-principal"></slot>
16
+ </div>
17
+ <div part="root toolbar-trailing-stack">
18
+ <slot name="top-bar-trailing"></slot>
19
+ </div>
20
+ </div>
21
+ <div part="root bottom-bar">
22
+ <div part="root toolbar-leading-stack">
23
+ <slot name="bottom-bar-leading"></slot>
24
+ </div>
25
+ <div part="root toolbar-principal-stack">
26
+ <slot name="bottom-bar-principal"></slot>
27
+ </div>
28
+ <div part="root toolbar-trailing-stack">
29
+ <slot name="bottom-bar-trailing"></slot>
30
+ </div>
31
+ </div>`, ''));
32
+ }
33
+ #shadowRoot;
34
+ get #scrollView() {
35
+ return this.parentElement?.querySelector(':scope > scroll-view') ?? undefined; //this.previousElementSibling ?? undefined
36
+ }
37
+ constructor() {
38
+ super();
39
+ this.#shadowRoot = this.attachShadow({ mode: 'closed' });
40
+ // NOTE: wait for config
41
+ // Snapshot.waitReady.then(() => {
42
+ this.#shadowRoot.appendChild(document.importNode(this.constructor.template, true));
43
+ // })
44
+ }
45
+ connectedCallback() {
46
+ console.debug(`${_a.name} ⚡️ connect`);
47
+ // NOTE: wait for config
48
+ // Snapshot.waitReady.then(() => {
49
+ for (const el of this.#shadowRoot.querySelectorAll(`[part*="toolbar-leading-stack"],[part*="toolbar-trailing-stack"]`))
50
+ observers.observe(el, this.#measureStacks.bind(this));
51
+ // })
52
+ }
53
+ disconnectedCallback() {
54
+ console.debug(`${_a.name} ⚡️ disconnect`);
55
+ observers.unobserve(this);
56
+ }
57
+ #measureStacks(entry) {
58
+ console.debug(`${_a.name} ⚡️ measure`);
59
+ if (this.closest('[hidden]'))
60
+ return;
61
+ const leading = 'toolbar-leading-stack', trailing = 'toolbar-trailing-stack';
62
+ const parentMap = {
63
+ 'top-bar': 'navbar',
64
+ 'bottom-bar': 'toolbar', //'bottombar',
65
+ };
66
+ const { contentRect, target } = entry;
67
+ const parentPart = target.parentElement?.part.contains('top-bar') ? 'top-bar' : target.parentElement?.part.contains('bottom-bar') ? 'bottom-bar' : null;
68
+ if (!parentPart)
69
+ return;
70
+ const side = target.part.contains(leading) ? 'inline-start' : target.part.contains(trailing) ? 'inline-end' : null;
71
+ if (!side)
72
+ return;
73
+ const prop = `--${parentMap[parentPart]}-padding-${side}`;
74
+ $.prop(prop, `${Math.round(contentRect.width)}px`, this.#scrollView); //;(this.#scrollView as HTMLElement)?.style?.setProperty(prop, `${Math.round(contentRect.width)}px`)
75
+ }
76
+ }
77
+ _a = ToolBar;
@@ -1,2 +1,13 @@
1
+ /**
2
+ * BUG: Safari on IOS reports inaccurate innerHeight (which is what we really want) on orientationchange.
3
+ * So we live with a pescy body-scrollbar that shows up on resize on desktops.
4
+ *
5
+ * @summary Required component, must be BODY tag
6
+ */
1
7
  export declare class VKeyboard extends HTMLElement {
8
+ #private;
9
+ constructor();
10
+ disconnectedCallback(): void;
11
+ connectedCallback(): void;
12
+ set shouldKeyboardBeOpen(fn: () => boolean);
2
13
  }