tyrell-components 1.0.0-RC10

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 (344) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +221 -0
  3. package/css/tyrell-brand.css +767 -0
  4. package/css/tyrell.css +1679 -0
  5. package/dist/tyrell-brand.css +767 -0
  6. package/dist/tyrell.css +1679 -0
  7. package/dist/tyrell.js +2 -0
  8. package/lib/base/ty-component.d.ts +133 -0
  9. package/lib/base/ty-component.d.ts.map +1 -0
  10. package/lib/base/ty-component.js +297 -0
  11. package/lib/base/ty-component.js.map +1 -0
  12. package/lib/components/button.d.ts +135 -0
  13. package/lib/components/button.d.ts.map +1 -0
  14. package/lib/components/button.js +277 -0
  15. package/lib/components/button.js.map +1 -0
  16. package/lib/components/calendar-month.d.ts +132 -0
  17. package/lib/components/calendar-month.d.ts.map +1 -0
  18. package/lib/components/calendar-month.js +440 -0
  19. package/lib/components/calendar-month.js.map +1 -0
  20. package/lib/components/calendar-navigation.d.ts +137 -0
  21. package/lib/components/calendar-navigation.d.ts.map +1 -0
  22. package/lib/components/calendar-navigation.js +366 -0
  23. package/lib/components/calendar-navigation.js.map +1 -0
  24. package/lib/components/calendar.d.ts +166 -0
  25. package/lib/components/calendar.d.ts.map +1 -0
  26. package/lib/components/calendar.js +774 -0
  27. package/lib/components/calendar.js.map +1 -0
  28. package/lib/components/checkbox.d.ts +189 -0
  29. package/lib/components/checkbox.d.ts.map +1 -0
  30. package/lib/components/checkbox.js +400 -0
  31. package/lib/components/checkbox.js.map +1 -0
  32. package/lib/components/copy.d.ts +180 -0
  33. package/lib/components/copy.d.ts.map +1 -0
  34. package/lib/components/copy.js +393 -0
  35. package/lib/components/copy.js.map +1 -0
  36. package/lib/components/date-picker.d.ts +379 -0
  37. package/lib/components/date-picker.d.ts.map +1 -0
  38. package/lib/components/date-picker.js +1586 -0
  39. package/lib/components/date-picker.js.map +1 -0
  40. package/lib/components/dropdown.d.ts +424 -0
  41. package/lib/components/dropdown.d.ts.map +1 -0
  42. package/lib/components/dropdown.js +1640 -0
  43. package/lib/components/dropdown.js.map +1 -0
  44. package/lib/components/file-upload.d.ts +121 -0
  45. package/lib/components/file-upload.d.ts.map +1 -0
  46. package/lib/components/file-upload.js +441 -0
  47. package/lib/components/file-upload.js.map +1 -0
  48. package/lib/components/icon.d.ts +118 -0
  49. package/lib/components/icon.d.ts.map +1 -0
  50. package/lib/components/icon.js +245 -0
  51. package/lib/components/icon.js.map +1 -0
  52. package/lib/components/input.d.ts +270 -0
  53. package/lib/components/input.d.ts.map +1 -0
  54. package/lib/components/input.js +721 -0
  55. package/lib/components/input.js.map +1 -0
  56. package/lib/components/modal.d.ts +78 -0
  57. package/lib/components/modal.d.ts.map +1 -0
  58. package/lib/components/modal.js +497 -0
  59. package/lib/components/modal.js.map +1 -0
  60. package/lib/components/multiselect.d.ts +397 -0
  61. package/lib/components/multiselect.d.ts.map +1 -0
  62. package/lib/components/multiselect.js +1595 -0
  63. package/lib/components/multiselect.js.map +1 -0
  64. package/lib/components/option.d.ts +66 -0
  65. package/lib/components/option.d.ts.map +1 -0
  66. package/lib/components/option.js +314 -0
  67. package/lib/components/option.js.map +1 -0
  68. package/lib/components/popup.d.ts +43 -0
  69. package/lib/components/popup.d.ts.map +1 -0
  70. package/lib/components/popup.js +380 -0
  71. package/lib/components/popup.js.map +1 -0
  72. package/lib/components/radio.d.ts +198 -0
  73. package/lib/components/radio.d.ts.map +1 -0
  74. package/lib/components/radio.js +437 -0
  75. package/lib/components/radio.js.map +1 -0
  76. package/lib/components/resize-observer.d.ts +48 -0
  77. package/lib/components/resize-observer.d.ts.map +1 -0
  78. package/lib/components/resize-observer.js +108 -0
  79. package/lib/components/resize-observer.js.map +1 -0
  80. package/lib/components/scroll-container.d.ts +51 -0
  81. package/lib/components/scroll-container.d.ts.map +1 -0
  82. package/lib/components/scroll-container.js +239 -0
  83. package/lib/components/scroll-container.js.map +1 -0
  84. package/lib/components/step.d.ts +26 -0
  85. package/lib/components/step.d.ts.map +1 -0
  86. package/lib/components/step.js +75 -0
  87. package/lib/components/step.js.map +1 -0
  88. package/lib/components/switch.d.ts +111 -0
  89. package/lib/components/switch.d.ts.map +1 -0
  90. package/lib/components/switch.js +240 -0
  91. package/lib/components/switch.js.map +1 -0
  92. package/lib/components/tab.d.ts +23 -0
  93. package/lib/components/tab.d.ts.map +1 -0
  94. package/lib/components/tab.js +76 -0
  95. package/lib/components/tab.js.map +1 -0
  96. package/lib/components/tabs.d.ts +93 -0
  97. package/lib/components/tabs.d.ts.map +1 -0
  98. package/lib/components/tabs.js +653 -0
  99. package/lib/components/tabs.js.map +1 -0
  100. package/lib/components/tag.d.ts +144 -0
  101. package/lib/components/tag.d.ts.map +1 -0
  102. package/lib/components/tag.js +316 -0
  103. package/lib/components/tag.js.map +1 -0
  104. package/lib/components/textarea.d.ts +241 -0
  105. package/lib/components/textarea.d.ts.map +1 -0
  106. package/lib/components/textarea.js +585 -0
  107. package/lib/components/textarea.js.map +1 -0
  108. package/lib/components/tooltip.d.ts +40 -0
  109. package/lib/components/tooltip.d.ts.map +1 -0
  110. package/lib/components/tooltip.js +439 -0
  111. package/lib/components/tooltip.js.map +1 -0
  112. package/lib/components/wizard.d.ts +86 -0
  113. package/lib/components/wizard.d.ts.map +1 -0
  114. package/lib/components/wizard.js +636 -0
  115. package/lib/components/wizard.js.map +1 -0
  116. package/lib/icons/fontawesome/brands.d.ts +557 -0
  117. package/lib/icons/fontawesome/brands.d.ts.map +1 -0
  118. package/lib/icons/fontawesome/brands.js +557 -0
  119. package/lib/icons/fontawesome/brands.js.map +1 -0
  120. package/lib/icons/fontawesome/regular.d.ts +281 -0
  121. package/lib/icons/fontawesome/regular.d.ts.map +1 -0
  122. package/lib/icons/fontawesome/regular.js +281 -0
  123. package/lib/icons/fontawesome/regular.js.map +1 -0
  124. package/lib/icons/fontawesome/solid.d.ts +1992 -0
  125. package/lib/icons/fontawesome/solid.d.ts.map +1 -0
  126. package/lib/icons/fontawesome/solid.js +1992 -0
  127. package/lib/icons/fontawesome/solid.js.map +1 -0
  128. package/lib/icons/heroicons/micro.d.ts +324 -0
  129. package/lib/icons/heroicons/micro.d.ts.map +1 -0
  130. package/lib/icons/heroicons/micro.js +1032 -0
  131. package/lib/icons/heroicons/micro.js.map +1 -0
  132. package/lib/icons/heroicons/mini.d.ts +332 -0
  133. package/lib/icons/heroicons/mini.d.ts.map +1 -0
  134. package/lib/icons/heroicons/mini.js +1038 -0
  135. package/lib/icons/heroicons/mini.js.map +1 -0
  136. package/lib/icons/heroicons/outline.d.ts +332 -0
  137. package/lib/icons/heroicons/outline.d.ts.map +1 -0
  138. package/lib/icons/heroicons/outline.js +993 -0
  139. package/lib/icons/heroicons/outline.js.map +1 -0
  140. package/lib/icons/heroicons/solid.d.ts +332 -0
  141. package/lib/icons/heroicons/solid.d.ts.map +1 -0
  142. package/lib/icons/heroicons/solid.js +1063 -0
  143. package/lib/icons/heroicons/solid.js.map +1 -0
  144. package/lib/icons/lucide.d.ts +1872 -0
  145. package/lib/icons/lucide.d.ts.map +1 -0
  146. package/lib/icons/lucide.js +28212 -0
  147. package/lib/icons/lucide.js.map +1 -0
  148. package/lib/icons/material/filled.d.ts +2180 -0
  149. package/lib/icons/material/filled.d.ts.map +1 -0
  150. package/lib/icons/material/filled.js +14003 -0
  151. package/lib/icons/material/filled.js.map +1 -0
  152. package/lib/icons/material/outlined.d.ts +2142 -0
  153. package/lib/icons/material/outlined.d.ts.map +1 -0
  154. package/lib/icons/material/outlined.js +14545 -0
  155. package/lib/icons/material/outlined.js.map +1 -0
  156. package/lib/icons/material/round.d.ts +2147 -0
  157. package/lib/icons/material/round.d.ts.map +1 -0
  158. package/lib/icons/material/round.js +14779 -0
  159. package/lib/icons/material/round.js.map +1 -0
  160. package/lib/icons/material/sharp.d.ts +2147 -0
  161. package/lib/icons/material/sharp.d.ts.map +1 -0
  162. package/lib/icons/material/sharp.js +14189 -0
  163. package/lib/icons/material/sharp.js.map +1 -0
  164. package/lib/icons/material/two-tone.d.ts +2185 -0
  165. package/lib/icons/material/two-tone.d.ts.map +1 -0
  166. package/lib/icons/material/two-tone.js +17152 -0
  167. package/lib/icons/material/two-tone.js.map +1 -0
  168. package/lib/index.d.ts +86 -0
  169. package/lib/index.d.ts.map +1 -0
  170. package/lib/index.js +78 -0
  171. package/lib/index.js.map +1 -0
  172. package/lib/styles/button.d.ts +14 -0
  173. package/lib/styles/button.d.ts.map +1 -0
  174. package/lib/styles/button.js +498 -0
  175. package/lib/styles/button.js.map +1 -0
  176. package/lib/styles/calendar-month.d.ts +6 -0
  177. package/lib/styles/calendar-month.d.ts.map +1 -0
  178. package/lib/styles/calendar-month.js +275 -0
  179. package/lib/styles/calendar-month.js.map +1 -0
  180. package/lib/styles/calendar-navigation.d.ts +6 -0
  181. package/lib/styles/calendar-navigation.d.ts.map +1 -0
  182. package/lib/styles/calendar-navigation.js +143 -0
  183. package/lib/styles/calendar-navigation.js.map +1 -0
  184. package/lib/styles/calendar.d.ts +6 -0
  185. package/lib/styles/calendar.d.ts.map +1 -0
  186. package/lib/styles/calendar.js +28 -0
  187. package/lib/styles/calendar.js.map +1 -0
  188. package/lib/styles/checkbox.d.ts +9 -0
  189. package/lib/styles/checkbox.d.ts.map +1 -0
  190. package/lib/styles/checkbox.js +19 -0
  191. package/lib/styles/checkbox.js.map +1 -0
  192. package/lib/styles/copy.d.ts +7 -0
  193. package/lib/styles/copy.d.ts.map +1 -0
  194. package/lib/styles/copy.js +94 -0
  195. package/lib/styles/copy.js.map +1 -0
  196. package/lib/styles/custom-scrollbar.d.ts +6 -0
  197. package/lib/styles/custom-scrollbar.d.ts.map +1 -0
  198. package/lib/styles/custom-scrollbar.js +157 -0
  199. package/lib/styles/custom-scrollbar.js.map +1 -0
  200. package/lib/styles/date-picker.d.ts +6 -0
  201. package/lib/styles/date-picker.d.ts.map +1 -0
  202. package/lib/styles/date-picker.js +438 -0
  203. package/lib/styles/date-picker.js.map +1 -0
  204. package/lib/styles/dropdown.d.ts +12 -0
  205. package/lib/styles/dropdown.d.ts.map +1 -0
  206. package/lib/styles/dropdown.js +1081 -0
  207. package/lib/styles/dropdown.js.map +1 -0
  208. package/lib/styles/file-upload.d.ts +2 -0
  209. package/lib/styles/file-upload.d.ts.map +1 -0
  210. package/lib/styles/file-upload.js +241 -0
  211. package/lib/styles/file-upload.js.map +1 -0
  212. package/lib/styles/icon.d.ts +6 -0
  213. package/lib/styles/icon.d.ts.map +1 -0
  214. package/lib/styles/icon.js +241 -0
  215. package/lib/styles/icon.js.map +1 -0
  216. package/lib/styles/input.d.ts +7 -0
  217. package/lib/styles/input.d.ts.map +1 -0
  218. package/lib/styles/input.js +685 -0
  219. package/lib/styles/input.js.map +1 -0
  220. package/lib/styles/modal.d.ts +8 -0
  221. package/lib/styles/modal.d.ts.map +1 -0
  222. package/lib/styles/modal.js +134 -0
  223. package/lib/styles/modal.js.map +1 -0
  224. package/lib/styles/multiselect.d.ts +6 -0
  225. package/lib/styles/multiselect.d.ts.map +1 -0
  226. package/lib/styles/multiselect.js +825 -0
  227. package/lib/styles/multiselect.js.map +1 -0
  228. package/lib/styles/option.d.ts +6 -0
  229. package/lib/styles/option.d.ts.map +1 -0
  230. package/lib/styles/option.js +116 -0
  231. package/lib/styles/option.js.map +1 -0
  232. package/lib/styles/popup.d.ts +8 -0
  233. package/lib/styles/popup.d.ts.map +1 -0
  234. package/lib/styles/popup.js +95 -0
  235. package/lib/styles/popup.js.map +1 -0
  236. package/lib/styles/radio.d.ts +8 -0
  237. package/lib/styles/radio.d.ts.map +1 -0
  238. package/lib/styles/radio.js +160 -0
  239. package/lib/styles/radio.js.map +1 -0
  240. package/lib/styles/resize-observer.d.ts +6 -0
  241. package/lib/styles/resize-observer.d.ts.map +1 -0
  242. package/lib/styles/resize-observer.js +18 -0
  243. package/lib/styles/resize-observer.js.map +1 -0
  244. package/lib/styles/scroll-container.d.ts +6 -0
  245. package/lib/styles/scroll-container.d.ts.map +1 -0
  246. package/lib/styles/scroll-container.js +198 -0
  247. package/lib/styles/scroll-container.js.map +1 -0
  248. package/lib/styles/step.d.ts +5 -0
  249. package/lib/styles/step.d.ts.map +1 -0
  250. package/lib/styles/step.js +50 -0
  251. package/lib/styles/step.js.map +1 -0
  252. package/lib/styles/switch.d.ts +9 -0
  253. package/lib/styles/switch.d.ts.map +1 -0
  254. package/lib/styles/switch.js +100 -0
  255. package/lib/styles/switch.js.map +1 -0
  256. package/lib/styles/tab.d.ts +5 -0
  257. package/lib/styles/tab.d.ts.map +1 -0
  258. package/lib/styles/tab.js +51 -0
  259. package/lib/styles/tab.js.map +1 -0
  260. package/lib/styles/tabs.d.ts +13 -0
  261. package/lib/styles/tabs.d.ts.map +1 -0
  262. package/lib/styles/tabs.js +184 -0
  263. package/lib/styles/tabs.js.map +1 -0
  264. package/lib/styles/tag.d.ts +6 -0
  265. package/lib/styles/tag.d.ts.map +1 -0
  266. package/lib/styles/tag.js +409 -0
  267. package/lib/styles/tag.js.map +1 -0
  268. package/lib/styles/textarea.d.ts +6 -0
  269. package/lib/styles/textarea.d.ts.map +1 -0
  270. package/lib/styles/textarea.js +350 -0
  271. package/lib/styles/textarea.js.map +1 -0
  272. package/lib/styles/tooltip.d.ts +9 -0
  273. package/lib/styles/tooltip.d.ts.map +1 -0
  274. package/lib/styles/tooltip.js +133 -0
  275. package/lib/styles/tooltip.js.map +1 -0
  276. package/lib/styles/wizard.d.ts +25 -0
  277. package/lib/styles/wizard.d.ts.map +1 -0
  278. package/lib/styles/wizard.js +348 -0
  279. package/lib/styles/wizard.js.map +1 -0
  280. package/lib/types/common.d.ts +143 -0
  281. package/lib/types/common.d.ts.map +1 -0
  282. package/lib/types/common.js +5 -0
  283. package/lib/types/common.js.map +1 -0
  284. package/lib/utils/calendar-utils.d.ts +176 -0
  285. package/lib/utils/calendar-utils.d.ts.map +1 -0
  286. package/lib/utils/calendar-utils.js +370 -0
  287. package/lib/utils/calendar-utils.js.map +1 -0
  288. package/lib/utils/custom-scrollbar.d.ts +82 -0
  289. package/lib/utils/custom-scrollbar.d.ts.map +1 -0
  290. package/lib/utils/custom-scrollbar.js +320 -0
  291. package/lib/utils/custom-scrollbar.js.map +1 -0
  292. package/lib/utils/icon-registry.d.ts +78 -0
  293. package/lib/utils/icon-registry.d.ts.map +1 -0
  294. package/lib/utils/icon-registry.js +304 -0
  295. package/lib/utils/icon-registry.js.map +1 -0
  296. package/lib/utils/loader-registry.d.ts +35 -0
  297. package/lib/utils/loader-registry.d.ts.map +1 -0
  298. package/lib/utils/loader-registry.js +43 -0
  299. package/lib/utils/loader-registry.js.map +1 -0
  300. package/lib/utils/locale.d.ts +136 -0
  301. package/lib/utils/locale.d.ts.map +1 -0
  302. package/lib/utils/locale.js +213 -0
  303. package/lib/utils/locale.js.map +1 -0
  304. package/lib/utils/mobile.d.ts +14 -0
  305. package/lib/utils/mobile.d.ts.map +1 -0
  306. package/lib/utils/mobile.js +21 -0
  307. package/lib/utils/mobile.js.map +1 -0
  308. package/lib/utils/number-format.d.ts +83 -0
  309. package/lib/utils/number-format.d.ts.map +1 -0
  310. package/lib/utils/number-format.js +143 -0
  311. package/lib/utils/number-format.js.map +1 -0
  312. package/lib/utils/parse-boolean.d.ts +39 -0
  313. package/lib/utils/parse-boolean.d.ts.map +1 -0
  314. package/lib/utils/parse-boolean.js +58 -0
  315. package/lib/utils/parse-boolean.js.map +1 -0
  316. package/lib/utils/positioning.d.ts +143 -0
  317. package/lib/utils/positioning.d.ts.map +1 -0
  318. package/lib/utils/positioning.js +308 -0
  319. package/lib/utils/positioning.js.map +1 -0
  320. package/lib/utils/property-capture.d.ts +132 -0
  321. package/lib/utils/property-capture.d.ts.map +1 -0
  322. package/lib/utils/property-capture.js +152 -0
  323. package/lib/utils/property-capture.js.map +1 -0
  324. package/lib/utils/property-manager.d.ts +90 -0
  325. package/lib/utils/property-manager.d.ts.map +1 -0
  326. package/lib/utils/property-manager.js +197 -0
  327. package/lib/utils/property-manager.js.map +1 -0
  328. package/lib/utils/resize-observer.d.ts +42 -0
  329. package/lib/utils/resize-observer.d.ts.map +1 -0
  330. package/lib/utils/resize-observer.js +71 -0
  331. package/lib/utils/resize-observer.js.map +1 -0
  332. package/lib/utils/scroll-lock.d.ts +79 -0
  333. package/lib/utils/scroll-lock.d.ts.map +1 -0
  334. package/lib/utils/scroll-lock.js +197 -0
  335. package/lib/utils/scroll-lock.js.map +1 -0
  336. package/lib/utils/styles.d.ts +27 -0
  337. package/lib/utils/styles.d.ts.map +1 -0
  338. package/lib/utils/styles.js +53 -0
  339. package/lib/utils/styles.js.map +1 -0
  340. package/lib/version.d.ts +8 -0
  341. package/lib/version.d.ts.map +1 -0
  342. package/lib/version.js +11 -0
  343. package/lib/version.js.map +1 -0
  344. package/package.json +163 -0
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Locale Resolution Utilities
3
+ *
4
+ * Provides a cascade system for resolving locale/language preferences:
5
+ * 1. Component's explicit `locale` attribute (highest priority)
6
+ * 2. Closest ancestor's `lang` attribute
7
+ * 3. Document root's `lang` attribute
8
+ * 4. Browser's language preference
9
+ * 5. 'en-US' fallback (lowest priority)
10
+ *
11
+ * This allows developers to set locale at any level:
12
+ * - Per-component: <ty-input locale="fr-FR">
13
+ * - Per-section: <div lang="de-DE"><ty-input></ty-input></div>
14
+ * - Per-page: <html lang="es-ES">
15
+ * - Browser default: Uses navigator.language
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // In a component
20
+ * class TyInput extends HTMLElement {
21
+ * get locale(): string {
22
+ * return getEffectiveLocale(this, this.getAttribute('locale'));
23
+ * }
24
+ * }
25
+ * ```
26
+ */
27
+ /**
28
+ * Get the effective locale for an element using the resolution cascade.
29
+ *
30
+ * Resolution order:
31
+ * 1. Explicit locale attribute on the element
32
+ * 2. Closest ancestor element with a `lang` attribute
33
+ * 3. Document root element's `lang` attribute
34
+ * 4. Browser's navigator.language
35
+ * 5. Fallback to 'en-US'
36
+ *
37
+ * @param element - The element to get locale for
38
+ * @param explicitLocale - Optional explicit locale value (from component's locale attribute)
39
+ * @returns The resolved locale string (e.g., 'en-US', 'fr-FR')
40
+ *
41
+ * @example
42
+ * ```html
43
+ * <html lang="en-US">
44
+ * <div lang="fr-FR">
45
+ * <ty-input></ty-input> <!-- Uses 'fr-FR' -->
46
+ * <ty-input locale="de-DE"></ty-input> <!-- Uses 'de-DE' -->
47
+ * </div>
48
+ * <ty-input></ty-input> <!-- Uses 'en-US' -->
49
+ * </html>
50
+ * ```
51
+ */
52
+ export function getEffectiveLocale(element, explicitLocale) {
53
+ // 1. Explicit locale attribute takes highest priority
54
+ if (explicitLocale) {
55
+ return explicitLocale;
56
+ }
57
+ // 2. Check closest ancestor with lang attribute
58
+ // This allows per-section locale overrides
59
+ const langElement = element.closest('[lang]');
60
+ if (langElement) {
61
+ const lang = langElement.getAttribute('lang');
62
+ if (lang)
63
+ return lang;
64
+ }
65
+ // 3. Check document root (html element)
66
+ if (document.documentElement.lang) {
67
+ return document.documentElement.lang;
68
+ }
69
+ // 4. Use browser's language preference
70
+ if (navigator.language) {
71
+ return navigator.language;
72
+ }
73
+ // 5. Ultimate fallback
74
+ return 'en-US';
75
+ }
76
+ /**
77
+ * Normalize a locale string to BCP 47 format.
78
+ * Handles common variations and ensures consistency.
79
+ *
80
+ * @param locale - The locale string to normalize
81
+ * @returns Normalized locale string
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * normalizeLocale('en') // 'en'
86
+ * normalizeLocale('en_US') // 'en-US'
87
+ * normalizeLocale('EN-us') // 'en-US'
88
+ * ```
89
+ */
90
+ export function normalizeLocale(locale) {
91
+ if (!locale)
92
+ return 'en-US';
93
+ // Replace underscores with hyphens (en_US -> en-US)
94
+ let normalized = locale.replace(/_/g, '-');
95
+ // Split into parts
96
+ const parts = normalized.split('-');
97
+ if (parts.length === 0)
98
+ return 'en-US';
99
+ // Lowercase language code (EN -> en)
100
+ parts[0] = parts[0].toLowerCase();
101
+ // Uppercase country code if present (us -> US)
102
+ if (parts.length > 1) {
103
+ parts[1] = parts[1].toUpperCase();
104
+ }
105
+ return parts.join('-');
106
+ }
107
+ /**
108
+ * Check if a locale string is valid BCP 47 format.
109
+ *
110
+ * @param locale - The locale string to validate
111
+ * @returns true if valid, false otherwise
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * isValidLocale('en-US') // true
116
+ * isValidLocale('fr') // true
117
+ * isValidLocale('invalid!') // false
118
+ * ```
119
+ */
120
+ export function isValidLocale(locale) {
121
+ if (!locale)
122
+ return false;
123
+ // BCP 47 language tag pattern
124
+ // Simplified: allows language-region format
125
+ const pattern = /^[a-z]{2,3}(-[A-Z]{2})?$/;
126
+ return pattern.test(locale);
127
+ }
128
+ /**
129
+ * Get the language code from a locale (e.g., 'en' from 'en-US').
130
+ *
131
+ * @param locale - The locale string
132
+ * @returns The language code
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * getLanguageCode('en-US') // 'en'
137
+ * getLanguageCode('fr-FR') // 'fr'
138
+ * getLanguageCode('de') // 'de'
139
+ * ```
140
+ */
141
+ export function getLanguageCode(locale) {
142
+ if (!locale)
143
+ return 'en';
144
+ return locale.split('-')[0].toLowerCase();
145
+ }
146
+ /**
147
+ * Get the region/country code from a locale (e.g., 'US' from 'en-US').
148
+ *
149
+ * @param locale - The locale string
150
+ * @returns The region code, or undefined if not present
151
+ *
152
+ * @example
153
+ * ```typescript
154
+ * getRegionCode('en-US') // 'US'
155
+ * getRegionCode('fr-FR') // 'FR'
156
+ * getRegionCode('de') // undefined
157
+ * ```
158
+ */
159
+ export function getRegionCode(locale) {
160
+ if (!locale)
161
+ return undefined;
162
+ const parts = locale.split('-');
163
+ return parts.length > 1 ? parts[1].toUpperCase() : undefined;
164
+ }
165
+ /**
166
+ * Create a MutationObserver to watch for lang attribute changes.
167
+ * Useful for components that need to react to dynamic locale changes.
168
+ *
169
+ * @param element - The element to observe
170
+ * @param callback - Function to call when lang changes
171
+ * @returns Cleanup function to disconnect the observer
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * class TyInput extends HTMLElement {
176
+ * private _localeObserver?: () => void;
177
+ *
178
+ * connectedCallback() {
179
+ * this._localeObserver = observeLocaleChanges(this, () => {
180
+ * this.render(); // Re-render when locale changes
181
+ * });
182
+ * }
183
+ *
184
+ * disconnectedCallback() {
185
+ * this._localeObserver?.();
186
+ * }
187
+ * }
188
+ * ```
189
+ */
190
+ export function observeLocaleChanges(element, callback) {
191
+ let currentLocale = getEffectiveLocale(element);
192
+ // Create observer for lang attribute changes on ancestors
193
+ const observer = new MutationObserver((mutations) => {
194
+ for (const mutation of mutations) {
195
+ if (mutation.type === 'attributes' && mutation.attributeName === 'lang') {
196
+ const newLocale = getEffectiveLocale(element);
197
+ if (newLocale !== currentLocale) {
198
+ currentLocale = newLocale;
199
+ callback(newLocale);
200
+ }
201
+ }
202
+ }
203
+ });
204
+ // Observe document and all ancestors
205
+ observer.observe(document.documentElement, {
206
+ attributes: true,
207
+ attributeFilter: ['lang'],
208
+ subtree: true
209
+ });
210
+ // Return cleanup function
211
+ return () => observer.disconnect();
212
+ }
213
+ //# sourceMappingURL=locale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale.js","sourceRoot":"","sources":["../../src/utils/locale.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Mobile detection utility
3
+ *
4
+ * Uses CSS media query via matchMedia for reliable detection:
5
+ * - `pointer: coarse` identifies touch-primary devices (not laptops with touchscreens)
6
+ * - Breakpoint is evaluated by the browser, always in sync with CSS
7
+ * - Called on each use (not cached), so it responds to viewport changes and rotation
8
+ */
9
+ /**
10
+ * Detect mobile touch devices.
11
+ * Returns true when the primary pointer is coarse (touch) AND viewport is narrow.
12
+ */
13
+ export declare function isMobileTouch(breakpoint?: number): boolean;
14
+ //# sourceMappingURL=mobile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile.d.ts","sourceRoot":"","sources":["../../src/utils/mobile.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,UAAU,GAAE,MAA0B,GAAG,OAAO,CAE7E"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Mobile detection utility
3
+ *
4
+ * Uses CSS media query via matchMedia for reliable detection:
5
+ * - `pointer: coarse` identifies touch-primary devices (not laptops with touchscreens)
6
+ * - Breakpoint is evaluated by the browser, always in sync with CSS
7
+ * - Called on each use (not cached), so it responds to viewport changes and rotation
8
+ */
9
+ /**
10
+ * Default mobile breakpoint (px).
11
+ * Matches phones in portrait and most phones in landscape.
12
+ */
13
+ const MOBILE_BREAKPOINT = 768;
14
+ /**
15
+ * Detect mobile touch devices.
16
+ * Returns true when the primary pointer is coarse (touch) AND viewport is narrow.
17
+ */
18
+ export function isMobileTouch(breakpoint = MOBILE_BREAKPOINT) {
19
+ return window.matchMedia(`(pointer: coarse) and (max-width: ${breakpoint}px)`).matches;
20
+ }
21
+ //# sourceMappingURL=mobile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile.js","sourceRoot":"","sources":["../../src/utils/mobile.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;GAGG;AACH,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,aAAqB,iBAAiB;IAClE,OAAO,MAAM,CAAC,UAAU,CAAC,qCAAqC,UAAU,KAAK,CAAC,CAAC,OAAO,CAAC;AACzF,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Number Formatting Utilities
3
+ * PORTED FROM: clj/ty/i18n/number.cljs
4
+ *
5
+ * Uses native Intl.NumberFormat for locale-aware number formatting
6
+ * Supports currency, percent, compact notation, and custom precision
7
+ */
8
+ export type NumberFormatType = 'number' | 'currency' | 'percent' | 'compact';
9
+ export interface FormatConfig {
10
+ type: NumberFormatType;
11
+ locale?: string;
12
+ currency?: string;
13
+ precision?: number;
14
+ }
15
+ /**
16
+ * Format a number based on configuration
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * formatNumber(1234.56, { type: 'currency', currency: 'USD', locale: 'en-US' })
21
+ * // Returns: "$1,234.56"
22
+ *
23
+ * formatNumber(0.15, { type: 'percent', precision: 2 })
24
+ * // Returns: "15.00%"
25
+ *
26
+ * formatNumber(1234567, { type: 'compact' })
27
+ * // Returns: "1.2M"
28
+ * ```
29
+ */
30
+ export declare function formatNumber(value: number, config: FormatConfig): string;
31
+ /**
32
+ * Parse a numeric string to a number
33
+ *
34
+ * Simple rule: the last occurring . or , is the decimal separator.
35
+ * Everything else is stripped. This works for both US (1,234.56) and
36
+ * European (1.234,56) input, and for mobile keyboards that use , as decimal.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * parseNumericValue("1,234.56") // 1234.56 (last separator is .)
41
+ * parseNumericValue("1.234,56") // 1234.56 (last separator is ,)
42
+ * parseNumericValue("12,50") // 12.5 (last separator is ,)
43
+ * parseNumericValue("12.50") // 12.5 (last separator is .)
44
+ * parseNumericValue("1234") // 1234
45
+ * parseNumericValue("$1,234") // 1234
46
+ * parseNumericValue("15%") // 15
47
+ * parseNumericValue("") // null
48
+ * ```
49
+ */
50
+ export declare function parseNumericValue(value: string): number | null;
51
+ /**
52
+ * Check if input type requires numeric formatting
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * shouldFormat('currency') // true
57
+ * shouldFormat('percent') // true
58
+ * shouldFormat('text') // false
59
+ * ```
60
+ */
61
+ export declare function shouldFormat(type: string): boolean;
62
+ /**
63
+ * Format currency with locale
64
+ * Convenience function for currency formatting
65
+ */
66
+ export declare function formatCurrency(value: number, currency?: string, locale?: string): string;
67
+ /**
68
+ * Format percent with locale
69
+ * Convenience function for percent formatting
70
+ *
71
+ * Note: Expects value as 0.15 for 15%
72
+ */
73
+ export declare function formatPercent(value: number, locale?: string, precision?: number): string;
74
+ /**
75
+ * Format compact notation
76
+ * Convenience function for compact formatting
77
+ *
78
+ * @example
79
+ * formatCompact(1234567) // "1.2M"
80
+ * formatCompact(1234) // "1.2K"
81
+ */
82
+ export declare function formatCompact(value: number, locale?: string): string;
83
+ //# sourceMappingURL=number-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-format.d.ts","sourceRoot":"","sources":["../../src/utils/number-format.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAA;AAE5E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,YAAY,GACnB,MAAM,CA4CR;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA2B9D;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,MAAc,EACxB,MAAM,GAAE,MAAgB,GACvB,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAgB,EACxB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAER;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAgB,GACvB,MAAM,CAER"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Number Formatting Utilities
3
+ * PORTED FROM: clj/ty/i18n/number.cljs
4
+ *
5
+ * Uses native Intl.NumberFormat for locale-aware number formatting
6
+ * Supports currency, percent, compact notation, and custom precision
7
+ */
8
+ /**
9
+ * Format a number based on configuration
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * formatNumber(1234.56, { type: 'currency', currency: 'USD', locale: 'en-US' })
14
+ * // Returns: "$1,234.56"
15
+ *
16
+ * formatNumber(0.15, { type: 'percent', precision: 2 })
17
+ * // Returns: "15.00%"
18
+ *
19
+ * formatNumber(1234567, { type: 'compact' })
20
+ * // Returns: "1.2M"
21
+ * ```
22
+ */
23
+ export function formatNumber(value, config) {
24
+ const { type, locale = 'en-US', currency = 'USD', precision } = config;
25
+ const options = {};
26
+ // Add precision if specified
27
+ if (precision !== undefined) {
28
+ options.minimumFractionDigits = precision;
29
+ options.maximumFractionDigits = precision;
30
+ }
31
+ // Configure based on type
32
+ switch (type) {
33
+ case 'currency':
34
+ options.style = 'currency';
35
+ options.currency = currency;
36
+ break;
37
+ case 'percent':
38
+ options.style = 'percent';
39
+ // Note: Intl.NumberFormat expects decimal (0.15 for 15%)
40
+ // We'll handle the division in the input component
41
+ break;
42
+ case 'compact':
43
+ options.notation = 'compact';
44
+ options.compactDisplay = 'short';
45
+ break;
46
+ case 'number':
47
+ default:
48
+ options.style = 'decimal';
49
+ break;
50
+ }
51
+ const formatter = new Intl.NumberFormat(locale, options);
52
+ const formatted = formatter.format(value);
53
+ // Normalize Unicode spaces for better HTML input compatibility
54
+ // Replace narrow no-break space (U+202F) and thin space (U+2009) with regular non-breaking space (U+00A0)
55
+ // This ensures proper rendering in HTML input elements
56
+ return formatted
57
+ .replace(/\u202F/g, '\u00A0') // Narrow no-break space → non-breaking space
58
+ .replace(/\u2009/g, '\u00A0'); // Thin space → non-breaking space
59
+ }
60
+ /**
61
+ * Parse a numeric string to a number
62
+ *
63
+ * Simple rule: the last occurring . or , is the decimal separator.
64
+ * Everything else is stripped. This works for both US (1,234.56) and
65
+ * European (1.234,56) input, and for mobile keyboards that use , as decimal.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * parseNumericValue("1,234.56") // 1234.56 (last separator is .)
70
+ * parseNumericValue("1.234,56") // 1234.56 (last separator is ,)
71
+ * parseNumericValue("12,50") // 12.5 (last separator is ,)
72
+ * parseNumericValue("12.50") // 12.5 (last separator is .)
73
+ * parseNumericValue("1234") // 1234
74
+ * parseNumericValue("$1,234") // 1234
75
+ * parseNumericValue("15%") // 15
76
+ * parseNumericValue("") // null
77
+ * ```
78
+ */
79
+ export function parseNumericValue(value) {
80
+ if (!value || value.trim() === '')
81
+ return null;
82
+ // Strip everything except digits, dots, commas, and minus
83
+ let stripped = value
84
+ .replace(/[^\d.,-]/g, '')
85
+ .trim();
86
+ if (stripped === '' || stripped === '-')
87
+ return null;
88
+ // Find the last occurring . or , — that's the decimal separator
89
+ const lastComma = stripped.lastIndexOf(',');
90
+ const lastDot = stripped.lastIndexOf('.');
91
+ const lastSep = Math.max(lastComma, lastDot);
92
+ if (lastSep === -1) {
93
+ // No separators — pure integer
94
+ const parsed = parseFloat(stripped);
95
+ return isNaN(parsed) ? null : parsed;
96
+ }
97
+ // Split at the last separator
98
+ const intPart = stripped.slice(0, lastSep).replace(/[.,]/g, '');
99
+ const decPart = stripped.slice(lastSep + 1);
100
+ const parsed = parseFloat(intPart + '.' + decPart);
101
+ return isNaN(parsed) ? null : parsed;
102
+ }
103
+ /**
104
+ * Check if input type requires numeric formatting
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * shouldFormat('currency') // true
109
+ * shouldFormat('percent') // true
110
+ * shouldFormat('text') // false
111
+ * ```
112
+ */
113
+ export function shouldFormat(type) {
114
+ return ['number', 'currency', 'percent', 'compact'].includes(type);
115
+ }
116
+ /**
117
+ * Format currency with locale
118
+ * Convenience function for currency formatting
119
+ */
120
+ export function formatCurrency(value, currency = 'USD', locale = 'en-US') {
121
+ return formatNumber(value, { type: 'currency', currency, locale });
122
+ }
123
+ /**
124
+ * Format percent with locale
125
+ * Convenience function for percent formatting
126
+ *
127
+ * Note: Expects value as 0.15 for 15%
128
+ */
129
+ export function formatPercent(value, locale = 'en-US', precision) {
130
+ return formatNumber(value, { type: 'percent', locale, precision });
131
+ }
132
+ /**
133
+ * Format compact notation
134
+ * Convenience function for compact formatting
135
+ *
136
+ * @example
137
+ * formatCompact(1234567) // "1.2M"
138
+ * formatCompact(1234) // "1.2K"
139
+ */
140
+ export function formatCompact(value, locale = 'en-US') {
141
+ return formatNumber(value, { type: 'compact', locale });
142
+ }
143
+ //# sourceMappingURL=number-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-format.js","sourceRoot":"","sources":["../../src/utils/number-format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Parse a value as a boolean following web standards
3
+ *
4
+ * This utility helps web components handle boolean attributes consistently:
5
+ * - HTML5 boolean attributes: presence = true, absence = false, empty string = true
6
+ * - Framework boolean values: true/false/"true"/"false"
7
+ * - Numeric boolean values: 1/0/"1"/"0"
8
+ *
9
+ * @param value - The attribute value to parse
10
+ * @returns boolean - The parsed boolean value
11
+ *
12
+ * @example
13
+ * parseBoolean(null) // false - attribute not present
14
+ * parseBoolean('') // true - HTML boolean attribute (present but empty)
15
+ * parseBoolean('true') // true
16
+ * parseBoolean('false') // false
17
+ * parseBoolean('TRUE') // true - case insensitive
18
+ * parseBoolean('1') // true
19
+ * parseBoolean('0') // false
20
+ * parseBoolean('yes') // true - any other non-empty string
21
+ * parseBoolean('anything') // true - truthy by default unless explicitly false
22
+ */
23
+ export declare function parseBoolean(value: string | null): boolean;
24
+ /**
25
+ * Check if a value looks like a boolean string
26
+ * Used to determine if an attribute should be treated as a boolean
27
+ *
28
+ * @param value - The value to check
29
+ * @returns boolean - True if value represents a boolean
30
+ *
31
+ * @example
32
+ * isBooleanString('true') // true
33
+ * isBooleanString('false') // true
34
+ * isBooleanString('1') // true
35
+ * isBooleanString('0') // true
36
+ * isBooleanString('custom') // false
37
+ */
38
+ export declare function isBooleanString(value: string | null): boolean;
39
+ //# sourceMappingURL=parse-boolean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-boolean.d.ts","sourceRoot":"","sources":["../../src/utils/parse-boolean.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAe1D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAI7D"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Parse a value as a boolean following web standards
3
+ *
4
+ * This utility helps web components handle boolean attributes consistently:
5
+ * - HTML5 boolean attributes: presence = true, absence = false, empty string = true
6
+ * - Framework boolean values: true/false/"true"/"false"
7
+ * - Numeric boolean values: 1/0/"1"/"0"
8
+ *
9
+ * @param value - The attribute value to parse
10
+ * @returns boolean - The parsed boolean value
11
+ *
12
+ * @example
13
+ * parseBoolean(null) // false - attribute not present
14
+ * parseBoolean('') // true - HTML boolean attribute (present but empty)
15
+ * parseBoolean('true') // true
16
+ * parseBoolean('false') // false
17
+ * parseBoolean('TRUE') // true - case insensitive
18
+ * parseBoolean('1') // true
19
+ * parseBoolean('0') // false
20
+ * parseBoolean('yes') // true - any other non-empty string
21
+ * parseBoolean('anything') // true - truthy by default unless explicitly false
22
+ */
23
+ export function parseBoolean(value) {
24
+ // No attribute or null = false (HTML standard)
25
+ if (value === null)
26
+ return false;
27
+ // Empty string = true (HTML boolean attribute pattern: <input checked>)
28
+ if (value === '')
29
+ return true;
30
+ // Normalize to lowercase for case-insensitive comparison
31
+ const normalized = value.toLowerCase().trim();
32
+ // Explicit false values
33
+ if (normalized === 'false' || normalized === '0')
34
+ return false;
35
+ // Everything else is truthy (follows HTML/JavaScript conventions)
36
+ return true;
37
+ }
38
+ /**
39
+ * Check if a value looks like a boolean string
40
+ * Used to determine if an attribute should be treated as a boolean
41
+ *
42
+ * @param value - The value to check
43
+ * @returns boolean - True if value represents a boolean
44
+ *
45
+ * @example
46
+ * isBooleanString('true') // true
47
+ * isBooleanString('false') // true
48
+ * isBooleanString('1') // true
49
+ * isBooleanString('0') // true
50
+ * isBooleanString('custom') // false
51
+ */
52
+ export function isBooleanString(value) {
53
+ if (value === null || value === '')
54
+ return false;
55
+ const normalized = value.toLowerCase().trim();
56
+ return ['true', 'false', '1', '0'].includes(normalized);
57
+ }
58
+ //# sourceMappingURL=parse-boolean.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-boolean.js","sourceRoot":"","sources":["../../src/utils/parse-boolean.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,YAAY,CAAC,KAAoB;IAC/C,+CAA+C;IAC/C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IAEhC,wEAAwE;IACxE,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,IAAI,CAAA;IAE7B,yDAAyD;IACzD,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IAE7C,wBAAwB;IACxB,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,GAAG;QAAE,OAAO,KAAK,CAAA;IAE9D,kEAAkE;IAClE,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,KAAoB;IAClD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,CAAA;IAChD,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAA;IAC7C,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;AACzD,CAAC"}