tyrell-components 1.0.0-RC13 → 1.0.0-RC15

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 (358) hide show
  1. package/README.md +10 -2
  2. package/css/tyrell-theme.css +192 -180
  3. package/css/tyrell.css +23 -0
  4. package/dist/tyrell-colors-static.css +1 -316
  5. package/dist/tyrell-theme.css +1 -1454
  6. package/dist/tyrell.css +1 -1371
  7. package/dist/tyrell.js +1 -1
  8. package/lib/base/ty-component.d.ts +20 -10
  9. package/lib/base/ty-component.js +196 -319
  10. package/lib/components/button.d.ts +3 -17
  11. package/lib/components/button.js +261 -295
  12. package/lib/components/calendar-month.d.ts +4 -50
  13. package/lib/components/calendar-month.js +443 -582
  14. package/lib/components/calendar-navigation.d.ts +3 -48
  15. package/lib/components/calendar-navigation.js +239 -362
  16. package/lib/components/calendar.d.ts +8 -83
  17. package/lib/components/calendar.js +616 -829
  18. package/lib/components/checkbox.d.ts +5 -72
  19. package/lib/components/checkbox.js +273 -416
  20. package/lib/components/copy.d.ts +4 -57
  21. package/lib/components/copy.js +280 -397
  22. package/lib/components/date-picker.d.ts +21 -163
  23. package/lib/components/date-picker.js +1143 -1674
  24. package/lib/components/file-upload.d.ts +9 -15
  25. package/lib/components/file-upload.js +404 -426
  26. package/lib/components/icon.d.ts +3 -24
  27. package/lib/components/icon.js +141 -230
  28. package/lib/components/input.d.ts +8 -108
  29. package/lib/components/input.js +593 -784
  30. package/lib/components/modal.d.ts +17 -26
  31. package/lib/components/modal.js +340 -484
  32. package/lib/components/option.d.ts +2 -9
  33. package/lib/components/option.js +168 -216
  34. package/lib/components/popup.d.ts +2 -17
  35. package/lib/components/popup.js +249 -380
  36. package/lib/components/radio.d.ts +5 -25
  37. package/lib/components/radio.js +407 -461
  38. package/lib/components/resize-observer.d.ts +3 -30
  39. package/lib/components/resize-observer.js +69 -103
  40. package/lib/components/scroll-container.d.ts +2 -12
  41. package/lib/components/scroll-container.js +293 -338
  42. package/lib/components/select.d.ts +87 -159
  43. package/lib/components/select.js +1609 -2090
  44. package/lib/components/selected-tags.d.ts +5 -48
  45. package/lib/components/selected-tags.js +188 -276
  46. package/lib/components/step.d.ts +1 -6
  47. package/lib/components/step.js +62 -68
  48. package/lib/components/switch.d.ts +1 -12
  49. package/lib/components/switch.js +214 -247
  50. package/lib/components/tab.d.ts +1 -6
  51. package/lib/components/tab.js +62 -69
  52. package/lib/components/tabs.d.ts +6 -63
  53. package/lib/components/tabs.js +545 -777
  54. package/lib/components/tag.d.ts +3 -37
  55. package/lib/components/tag.js +236 -335
  56. package/lib/components/textarea.d.ts +7 -87
  57. package/lib/components/textarea.js +457 -627
  58. package/lib/components/tooltip.d.ts +3 -11
  59. package/lib/components/tooltip.js +307 -443
  60. package/lib/components/wizard.d.ts +6 -54
  61. package/lib/components/wizard.js +405 -618
  62. package/lib/icons/fontawesome/brands.d.ts +0 -1
  63. package/lib/icons/fontawesome/brands.js +0 -8
  64. package/lib/icons/fontawesome/regular.d.ts +0 -1
  65. package/lib/icons/fontawesome/regular.js +0 -8
  66. package/lib/icons/fontawesome/solid.d.ts +0 -1
  67. package/lib/icons/fontawesome/solid.js +0 -8
  68. package/lib/icons/heroicons/micro.d.ts +0 -1
  69. package/lib/icons/heroicons/micro.js +392 -400
  70. package/lib/icons/heroicons/mini.d.ts +0 -1
  71. package/lib/icons/heroicons/mini.js +382 -390
  72. package/lib/icons/heroicons/outline.d.ts +0 -1
  73. package/lib/icons/heroicons/outline.js +337 -345
  74. package/lib/icons/heroicons/solid.d.ts +0 -1
  75. package/lib/icons/heroicons/solid.js +407 -415
  76. package/lib/icons/lucide.d.ts +0 -1
  77. package/lib/icons/lucide.js +24479 -26351
  78. package/lib/icons/material/filled.d.ts +0 -1
  79. package/lib/icons/material/filled.js +9653 -9663
  80. package/lib/icons/material/outlined.d.ts +0 -1
  81. package/lib/icons/material/outlined.js +10271 -10281
  82. package/lib/icons/material/round.d.ts +0 -1
  83. package/lib/icons/material/round.js +10495 -10505
  84. package/lib/icons/material/sharp.d.ts +0 -1
  85. package/lib/icons/material/sharp.js +9905 -9915
  86. package/lib/icons/material/two-tone.d.ts +0 -1
  87. package/lib/icons/material/two-tone.js +12792 -12802
  88. package/lib/index.d.ts +0 -1
  89. package/lib/index.js +21 -41
  90. package/lib/styles/button.d.ts +2 -20
  91. package/lib/styles/button.js +202 -404
  92. package/lib/styles/calendar-month.d.ts +1 -5
  93. package/lib/styles/calendar-month.js +127 -244
  94. package/lib/styles/calendar-navigation.d.ts +2 -6
  95. package/lib/styles/calendar-navigation.js +64 -104
  96. package/lib/styles/calendar.d.ts +1 -2
  97. package/lib/styles/calendar.js +9 -22
  98. package/lib/styles/checkbox.d.ts +0 -1
  99. package/lib/styles/checkbox.js +45 -94
  100. package/lib/styles/copy.d.ts +0 -1
  101. package/lib/styles/copy.js +67 -106
  102. package/lib/styles/custom-scrollbar.d.ts +1 -2
  103. package/lib/styles/custom-scrollbar.js +80 -115
  104. package/lib/styles/date-picker.d.ts +1 -5
  105. package/lib/styles/date-picker.js +261 -335
  106. package/lib/styles/field-size.d.ts +6 -0
  107. package/lib/styles/field-size.js +91 -0
  108. package/lib/styles/file-upload.d.ts +1 -2
  109. package/lib/styles/file-upload.js +143 -188
  110. package/lib/styles/icon.d.ts +2 -6
  111. package/lib/styles/icon.js +92 -170
  112. package/lib/styles/input.d.ts +1 -6
  113. package/lib/styles/input.js +125 -290
  114. package/lib/styles/modal.d.ts +1 -2
  115. package/lib/styles/modal.js +71 -108
  116. package/lib/styles/option.d.ts +2 -6
  117. package/lib/styles/option.js +49 -64
  118. package/lib/styles/popup.d.ts +1 -2
  119. package/lib/styles/popup.js +42 -77
  120. package/lib/styles/radio.d.ts +0 -1
  121. package/lib/styles/radio.js +69 -110
  122. package/lib/styles/resize-observer.d.ts +1 -2
  123. package/lib/styles/resize-observer.js +2 -12
  124. package/lib/styles/scroll-container.d.ts +1 -2
  125. package/lib/styles/scroll-container.js +100 -149
  126. package/lib/styles/select-base.d.ts +0 -1
  127. package/lib/styles/select-base.js +597 -785
  128. package/lib/styles/select.d.ts +1 -2
  129. package/lib/styles/select.js +140 -236
  130. package/lib/styles/step.d.ts +1 -2
  131. package/lib/styles/step.js +22 -33
  132. package/lib/styles/switch.d.ts +0 -1
  133. package/lib/styles/switch.js +34 -73
  134. package/lib/styles/tab.d.ts +1 -2
  135. package/lib/styles/tab.js +22 -34
  136. package/lib/styles/tabs.d.ts +3 -11
  137. package/lib/styles/tabs.js +190 -222
  138. package/lib/styles/tag.d.ts +1 -5
  139. package/lib/styles/tag.js +136 -218
  140. package/lib/styles/textarea.d.ts +1 -2
  141. package/lib/styles/textarea.js +210 -319
  142. package/lib/styles/tooltip.d.ts +0 -1
  143. package/lib/styles/tooltip.js +3 -13
  144. package/lib/styles/wizard.d.ts +5 -21
  145. package/lib/styles/wizard.js +170 -306
  146. package/lib/types/common.d.ts +2 -2
  147. package/lib/types/common.js +6 -17
  148. package/lib/utils/calendar-utils.d.ts +4 -21
  149. package/lib/utils/calendar-utils.js +100 -273
  150. package/lib/utils/custom-scrollbar.d.ts +6 -20
  151. package/lib/utils/custom-scrollbar.js +273 -317
  152. package/lib/utils/flavor-sheet.d.ts +0 -1
  153. package/lib/utils/flavor-sheet.js +14 -37
  154. package/lib/utils/icon-registry.d.ts +0 -2
  155. package/lib/utils/icon-registry.js +137 -243
  156. package/lib/utils/icons.d.ts +0 -1
  157. package/lib/utils/icons.js +0 -9
  158. package/lib/utils/loader-registry.d.ts +0 -1
  159. package/lib/utils/loader-registry.js +3 -35
  160. package/lib/utils/locale.d.ts +2 -23
  161. package/lib/utils/locale.js +34 -120
  162. package/lib/utils/mobile.d.ts +0 -1
  163. package/lib/utils/mobile.js +1 -18
  164. package/lib/utils/number-format.d.ts +6 -3
  165. package/lib/utils/number-format.js +54 -110
  166. package/lib/utils/positioning.d.ts +50 -7
  167. package/lib/utils/positioning.js +224 -234
  168. package/lib/utils/property-capture.d.ts +5 -27
  169. package/lib/utils/property-capture.js +36 -144
  170. package/lib/utils/property-manager.d.ts +0 -1
  171. package/lib/utils/property-manager.js +126 -196
  172. package/lib/utils/resize-observer.d.ts +0 -1
  173. package/lib/utils/resize-observer.js +23 -59
  174. package/lib/utils/scroll-lock.d.ts +4 -11
  175. package/lib/utils/scroll-lock.js +65 -172
  176. package/lib/utils/styles.d.ts +0 -1
  177. package/lib/utils/styles.js +17 -41
  178. package/lib/version.d.ts +1 -2
  179. package/lib/version.js +1 -11
  180. package/package.json +4 -4
  181. package/lib/base/ty-component.d.ts.map +0 -1
  182. package/lib/base/ty-component.js.map +0 -1
  183. package/lib/components/button.d.ts.map +0 -1
  184. package/lib/components/button.js.map +0 -1
  185. package/lib/components/calendar-month.d.ts.map +0 -1
  186. package/lib/components/calendar-month.js.map +0 -1
  187. package/lib/components/calendar-navigation.d.ts.map +0 -1
  188. package/lib/components/calendar-navigation.js.map +0 -1
  189. package/lib/components/calendar.d.ts.map +0 -1
  190. package/lib/components/calendar.js.map +0 -1
  191. package/lib/components/checkbox.d.ts.map +0 -1
  192. package/lib/components/checkbox.js.map +0 -1
  193. package/lib/components/copy.d.ts.map +0 -1
  194. package/lib/components/copy.js.map +0 -1
  195. package/lib/components/date-picker.d.ts.map +0 -1
  196. package/lib/components/date-picker.js.map +0 -1
  197. package/lib/components/file-upload.d.ts.map +0 -1
  198. package/lib/components/file-upload.js.map +0 -1
  199. package/lib/components/icon.d.ts.map +0 -1
  200. package/lib/components/icon.js.map +0 -1
  201. package/lib/components/input.d.ts.map +0 -1
  202. package/lib/components/input.js.map +0 -1
  203. package/lib/components/modal.d.ts.map +0 -1
  204. package/lib/components/modal.js.map +0 -1
  205. package/lib/components/option.d.ts.map +0 -1
  206. package/lib/components/option.js.map +0 -1
  207. package/lib/components/popup.d.ts.map +0 -1
  208. package/lib/components/popup.js.map +0 -1
  209. package/lib/components/radio.d.ts.map +0 -1
  210. package/lib/components/radio.js.map +0 -1
  211. package/lib/components/resize-observer.d.ts.map +0 -1
  212. package/lib/components/resize-observer.js.map +0 -1
  213. package/lib/components/scroll-container.d.ts.map +0 -1
  214. package/lib/components/scroll-container.js.map +0 -1
  215. package/lib/components/select.d.ts.map +0 -1
  216. package/lib/components/select.js.map +0 -1
  217. package/lib/components/selected-tags.d.ts.map +0 -1
  218. package/lib/components/selected-tags.js.map +0 -1
  219. package/lib/components/step.d.ts.map +0 -1
  220. package/lib/components/step.js.map +0 -1
  221. package/lib/components/switch.d.ts.map +0 -1
  222. package/lib/components/switch.js.map +0 -1
  223. package/lib/components/tab.d.ts.map +0 -1
  224. package/lib/components/tab.js.map +0 -1
  225. package/lib/components/tabs.d.ts.map +0 -1
  226. package/lib/components/tabs.js.map +0 -1
  227. package/lib/components/tag.d.ts.map +0 -1
  228. package/lib/components/tag.js.map +0 -1
  229. package/lib/components/textarea.d.ts.map +0 -1
  230. package/lib/components/textarea.js.map +0 -1
  231. package/lib/components/tooltip.d.ts.map +0 -1
  232. package/lib/components/tooltip.js.map +0 -1
  233. package/lib/components/wizard.d.ts.map +0 -1
  234. package/lib/components/wizard.js.map +0 -1
  235. package/lib/icons/fontawesome/brands.d.ts.map +0 -1
  236. package/lib/icons/fontawesome/brands.js.map +0 -1
  237. package/lib/icons/fontawesome/regular.d.ts.map +0 -1
  238. package/lib/icons/fontawesome/regular.js.map +0 -1
  239. package/lib/icons/fontawesome/solid.d.ts.map +0 -1
  240. package/lib/icons/fontawesome/solid.js.map +0 -1
  241. package/lib/icons/heroicons/micro.d.ts.map +0 -1
  242. package/lib/icons/heroicons/micro.js.map +0 -1
  243. package/lib/icons/heroicons/mini.d.ts.map +0 -1
  244. package/lib/icons/heroicons/mini.js.map +0 -1
  245. package/lib/icons/heroicons/outline.d.ts.map +0 -1
  246. package/lib/icons/heroicons/outline.js.map +0 -1
  247. package/lib/icons/heroicons/solid.d.ts.map +0 -1
  248. package/lib/icons/heroicons/solid.js.map +0 -1
  249. package/lib/icons/lucide.d.ts.map +0 -1
  250. package/lib/icons/lucide.js.map +0 -1
  251. package/lib/icons/material/filled.d.ts.map +0 -1
  252. package/lib/icons/material/filled.js.map +0 -1
  253. package/lib/icons/material/outlined.d.ts.map +0 -1
  254. package/lib/icons/material/outlined.js.map +0 -1
  255. package/lib/icons/material/round.d.ts.map +0 -1
  256. package/lib/icons/material/round.js.map +0 -1
  257. package/lib/icons/material/sharp.d.ts.map +0 -1
  258. package/lib/icons/material/sharp.js.map +0 -1
  259. package/lib/icons/material/two-tone.d.ts.map +0 -1
  260. package/lib/icons/material/two-tone.js.map +0 -1
  261. package/lib/index.d.ts.map +0 -1
  262. package/lib/index.js.map +0 -1
  263. package/lib/styles/button.d.ts.map +0 -1
  264. package/lib/styles/button.js.map +0 -1
  265. package/lib/styles/calendar-month.d.ts.map +0 -1
  266. package/lib/styles/calendar-month.js.map +0 -1
  267. package/lib/styles/calendar-navigation.d.ts.map +0 -1
  268. package/lib/styles/calendar-navigation.js.map +0 -1
  269. package/lib/styles/calendar.d.ts.map +0 -1
  270. package/lib/styles/calendar.js.map +0 -1
  271. package/lib/styles/checkbox.d.ts.map +0 -1
  272. package/lib/styles/checkbox.js.map +0 -1
  273. package/lib/styles/copy.d.ts.map +0 -1
  274. package/lib/styles/copy.js.map +0 -1
  275. package/lib/styles/custom-scrollbar.d.ts.map +0 -1
  276. package/lib/styles/custom-scrollbar.js.map +0 -1
  277. package/lib/styles/date-picker.d.ts.map +0 -1
  278. package/lib/styles/date-picker.js.map +0 -1
  279. package/lib/styles/file-upload.d.ts.map +0 -1
  280. package/lib/styles/file-upload.js.map +0 -1
  281. package/lib/styles/icon.d.ts.map +0 -1
  282. package/lib/styles/icon.js.map +0 -1
  283. package/lib/styles/input.d.ts.map +0 -1
  284. package/lib/styles/input.js.map +0 -1
  285. package/lib/styles/modal.d.ts.map +0 -1
  286. package/lib/styles/modal.js.map +0 -1
  287. package/lib/styles/multiselect.d.ts +0 -8
  288. package/lib/styles/multiselect.d.ts.map +0 -1
  289. package/lib/styles/multiselect.js +0 -849
  290. package/lib/styles/multiselect.js.map +0 -1
  291. package/lib/styles/option.d.ts.map +0 -1
  292. package/lib/styles/option.js.map +0 -1
  293. package/lib/styles/popup.d.ts.map +0 -1
  294. package/lib/styles/popup.js.map +0 -1
  295. package/lib/styles/radio.d.ts.map +0 -1
  296. package/lib/styles/radio.js.map +0 -1
  297. package/lib/styles/resize-observer.d.ts.map +0 -1
  298. package/lib/styles/resize-observer.js.map +0 -1
  299. package/lib/styles/scroll-container.d.ts.map +0 -1
  300. package/lib/styles/scroll-container.js.map +0 -1
  301. package/lib/styles/select-base.d.ts.map +0 -1
  302. package/lib/styles/select-base.js.map +0 -1
  303. package/lib/styles/select.d.ts.map +0 -1
  304. package/lib/styles/select.js.map +0 -1
  305. package/lib/styles/step.d.ts.map +0 -1
  306. package/lib/styles/step.js.map +0 -1
  307. package/lib/styles/switch.d.ts.map +0 -1
  308. package/lib/styles/switch.js.map +0 -1
  309. package/lib/styles/tab.d.ts.map +0 -1
  310. package/lib/styles/tab.js.map +0 -1
  311. package/lib/styles/tabs.d.ts.map +0 -1
  312. package/lib/styles/tabs.js.map +0 -1
  313. package/lib/styles/tag.d.ts.map +0 -1
  314. package/lib/styles/tag.js.map +0 -1
  315. package/lib/styles/textarea.d.ts.map +0 -1
  316. package/lib/styles/textarea.js.map +0 -1
  317. package/lib/styles/tooltip.d.ts.map +0 -1
  318. package/lib/styles/tooltip.js.map +0 -1
  319. package/lib/styles/wizard.d.ts.map +0 -1
  320. package/lib/styles/wizard.js.map +0 -1
  321. package/lib/types/common.d.ts.map +0 -1
  322. package/lib/types/common.js.map +0 -1
  323. package/lib/utils/calendar-utils.d.ts.map +0 -1
  324. package/lib/utils/calendar-utils.js.map +0 -1
  325. package/lib/utils/custom-scrollbar.d.ts.map +0 -1
  326. package/lib/utils/custom-scrollbar.js.map +0 -1
  327. package/lib/utils/flavor-sheet.d.ts.map +0 -1
  328. package/lib/utils/flavor-sheet.js.map +0 -1
  329. package/lib/utils/icon-registry.d.ts.map +0 -1
  330. package/lib/utils/icon-registry.js.map +0 -1
  331. package/lib/utils/icons.d.ts.map +0 -1
  332. package/lib/utils/icons.js.map +0 -1
  333. package/lib/utils/loader-registry.d.ts.map +0 -1
  334. package/lib/utils/loader-registry.js.map +0 -1
  335. package/lib/utils/locale.d.ts.map +0 -1
  336. package/lib/utils/locale.js.map +0 -1
  337. package/lib/utils/mobile.d.ts.map +0 -1
  338. package/lib/utils/mobile.js.map +0 -1
  339. package/lib/utils/number-format.d.ts.map +0 -1
  340. package/lib/utils/number-format.js.map +0 -1
  341. package/lib/utils/parse-boolean.d.ts +0 -39
  342. package/lib/utils/parse-boolean.d.ts.map +0 -1
  343. package/lib/utils/parse-boolean.js +0 -58
  344. package/lib/utils/parse-boolean.js.map +0 -1
  345. package/lib/utils/positioning.d.ts.map +0 -1
  346. package/lib/utils/positioning.js.map +0 -1
  347. package/lib/utils/property-capture.d.ts.map +0 -1
  348. package/lib/utils/property-capture.js.map +0 -1
  349. package/lib/utils/property-manager.d.ts.map +0 -1
  350. package/lib/utils/property-manager.js.map +0 -1
  351. package/lib/utils/resize-observer.d.ts.map +0 -1
  352. package/lib/utils/resize-observer.js.map +0 -1
  353. package/lib/utils/scroll-lock.d.ts.map +0 -1
  354. package/lib/utils/scroll-lock.js.map +0 -1
  355. package/lib/utils/styles.d.ts.map +0 -1
  356. package/lib/utils/styles.js.map +0 -1
  357. package/lib/version.d.ts.map +0 -1
  358. package/lib/version.js.map +0 -1
@@ -40,13 +40,7 @@ export declare abstract class TyComponent<T = any> extends HTMLElement {
40
40
  * Sync property value to HTML attribute
41
41
  */
42
42
  private _syncPropertyToAttribute;
43
- /**
44
- * Convert camelCase to kebab-case
45
- */
46
43
  private _toKebabCase;
47
- /**
48
- * Convert kebab-case to camelCase
49
- */
50
44
  private _toCamelCase;
51
45
  /**
52
46
  * Attribute changed callback - unified for all components
@@ -126,9 +120,26 @@ export declare abstract class TyComponent<T = any> extends HTMLElement {
126
120
  * the role element as aria-label, giving it an accessible name.
127
121
  */
128
122
  protected applyLabelName(roleEl: HTMLElement): void;
129
- /**
130
- * Form reset callback - called when form.reset() is invoked
131
- * Resets component to its default value
123
+ private _handlingActivationClick;
124
+ /**
125
+ * Guard for click-driven toggle handlers (checkbox/switch) on components
126
+ * whose whole host is the click target AND that expect a wrapping
127
+ * <label> to delegate to them. Some browsers still forward a label's own
128
+ * synthetic click to the associated control even when the original click
129
+ * already targeted that control directly, firing 'click' twice for one
130
+ * user gesture. Both arrive synchronously in the same task, so a flag
131
+ * cleared on the next microtask catches only the spurious duplicate —
132
+ * two genuinely separate clicks are always in different tasks.
133
+ */
134
+ protected isDuplicateActivationClick(): boolean;
135
+ private _resetDefaults;
136
+ /**
137
+ * Form reset callback - called when form.reset() is invoked.
138
+ * Restores every formValue-bearing property to its attribute-declared
139
+ * default captured at first connect (native defaultValue/defaultChecked
140
+ * semantics). Non-form state (e.g. a checkbox's submission `value`, a
141
+ * ty-radio's option `value`) is deliberately left alone — the old
142
+ * blanket 'value' reset corrupted radio groups by wiping child values.
132
143
  */
133
144
  formResetCallback(): void;
134
145
  /**
@@ -137,4 +148,3 @@ export declare abstract class TyComponent<T = any> extends HTMLElement {
137
148
  */
138
149
  protected onFormReset(): void;
139
150
  }
140
- //# sourceMappingURL=ty-component.d.ts.map
@@ -1,324 +1,201 @@
1
- /**
2
- * TyComponent - Base class for all Ty web components
3
- *
4
- * Provides unified property/attribute lifecycle management:
5
- * - Single code path for all property updates
6
- * - Declarative property configuration
7
- * - Predictable rendering behavior
8
- * - Form association support
9
- * - Property change events via 'prop:change' (separate from user 'change' events)
10
- */
11
1
  import { PropertyManager } from '../utils/property-manager.js';
12
- /**
13
- * Base class for all Ty components with unified property lifecycle
14
- */
15
2
  export class TyComponent extends HTMLElement {
16
- constructor() {
17
- super();
18
- // Track if component is connected
19
- this._connected = false;
20
- // Track if initial render happened
21
- this._rendered = false;
22
- // Initialize property manager
23
- const ctor = this.constructor;
24
- this.props = new PropertyManager(ctor.properties);
25
- // Form association
26
- this._internals = this.attachInternals();
27
- // Setup shadow DOM (subclasses can override by checking if shadowRoot exists)
28
- if (!this.shadowRoot) {
29
- this.attachShadow({ mode: 'open' });
30
- }
31
- }
32
- /**
33
- * Define which attributes to observe
34
- * Auto-generated from property configuration
35
- * Returns kebab-case attribute names (e.g., 'minHeight' -> 'min-height')
36
- */
37
- static get observedAttributes() {
38
- const attrs = [];
39
- for (const [name, config] of Object.entries(this.properties)) {
40
- attrs.push(name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase());
41
- // Include alias names so attributeChangedCallback fires for them
42
- if (config.aliases) {
43
- for (const alias of Object.keys(config.aliases)) {
44
- attrs.push(alias);
45
- }
46
- }
47
- }
48
- return attrs;
49
- }
50
- /**
51
- * Unified property setter
52
- * Use this in your property setters instead of direct field assignment
53
- */
54
- setProperty(name, value) {
55
- const change = this.props.updateProperty(name, value, 'property');
56
- if (change) {
57
- // Sync to attribute (kebab-case)
58
- this._syncPropertyToAttribute(change);
59
- // Handle the change through unified lifecycle
60
- this._handlePropertyChanges([change]);
61
- }
62
- }
63
- /**
64
- * Unified property getter
65
- * Use this in your property getters
66
- */
67
- getProperty(name) {
68
- return this.props.get(name);
69
- }
70
- /**
71
- * Sync property value to HTML attribute
72
- */
73
- _syncPropertyToAttribute(change) {
74
- const { name, newValue } = change;
75
- const config = this.props.getConfig(name);
76
- if (!config)
77
- return;
78
- // Convert to kebab-case for attribute
79
- const attrName = this._toKebabCase(name);
80
- // Handle different types
81
- if (config.type === 'boolean') {
82
- if (newValue) {
83
- this.setAttribute(attrName, '');
84
- }
85
- else {
86
- this.removeAttribute(attrName);
87
- }
88
- }
89
- else if (newValue === null || newValue === undefined) {
90
- this.removeAttribute(attrName);
91
- }
92
- else if (typeof newValue === 'object') {
93
- this.setAttribute(attrName, JSON.stringify(newValue));
94
- }
95
- else {
96
- this.setAttribute(attrName, String(newValue));
97
- }
98
- }
99
- /**
100
- * Convert camelCase to kebab-case
101
- */
102
- _toKebabCase(str) {
103
- return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
104
- }
105
- /**
106
- * Convert kebab-case to camelCase
107
- */
108
- _toCamelCase(str) {
109
- return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
110
- }
111
- /**
112
- * Attribute changed callback - unified for all components
113
- */
114
- attributeChangedCallback(name, oldValue, newValue) {
115
- if (oldValue === newValue)
116
- return;
117
- // Check if this is an alias (e.g., not-clearable)
118
- let change = this.props.handleAlias(name, newValue);
119
- if (!change) {
120
- // Properties may be registered with kebab-case (e.g., 'display-month')
121
- // or camelCase. Try the attribute name as-is first, then camelCase.
122
- const camelName = this._toCamelCase(name);
123
- const propName = this.props.hasConfig(name) ? name : camelName;
124
- change = this.props.updateProperty(propName, newValue, 'attribute');
125
- }
126
- if (change) {
127
- this._handlePropertyChanges([change]);
128
- }
129
- }
130
- /**
131
- * Connected callback - handle pre-set properties
132
- */
133
- connectedCallback() {
134
- this._connected = true;
135
- // Capture pre-set properties (React/Vue/Reagent pattern)
136
- const preSetProps = this._capturePreSetProperties();
137
- // Batch process all pre-set properties
138
- if (preSetProps.length > 0) {
139
- this._handlePropertyChanges(preSetProps);
140
- }
141
- // Initialize component (subclass hook)
142
- this.onConnect();
143
- // Initial render
144
- if (!this._rendered) {
145
- this.render();
146
- this._rendered = true;
147
- }
148
- }
149
- /**
150
- * Disconnected callback
151
- */
152
- disconnectedCallback() {
153
- this._connected = false;
154
- this.onDisconnect();
155
- }
156
- /**
157
- * Capture properties that were set before connectedCallback
158
- * (React, Vue, Reagent set properties before element is connected)
159
- */
160
- _capturePreSetProperties() {
161
- const changes = [];
162
- const ctor = this.constructor;
163
- for (const propName of Object.keys(ctor.properties)) {
164
- // Check if property was set on the element before connection
165
- const descriptor = Object.getOwnPropertyDescriptor(this, propName);
166
- if (descriptor && descriptor.value !== undefined) {
167
- const change = this.props.updateProperty(propName, descriptor.value, 'property');
168
- if (change) {
169
- changes.push(change);
170
- }
171
- }
172
- }
173
- return changes;
174
- }
175
- /**
176
- * THE CORE LIFECYCLE METHOD
177
- * All property changes flow through here
178
- *
179
- * Lifecycle order:
180
- * 1. Update internal state (onPropertiesChanged hook)
181
- * 2. Sync form value (if formValue property changed)
182
- * 3. Render (if visual property changed)
183
- * 4. Emit events (if emitChange property changed)
184
- */
185
- _handlePropertyChanges(changes) {
186
- if (changes.length === 0)
187
- return;
188
- // 1. Update internal state (subclass-specific)
189
- this.onPropertiesChanged(changes);
190
- // 2. Sync form value if needed
191
- const formValueChanged = changes.some(c => this.props.isFormValue(c.name));
192
- if (formValueChanged) {
193
- this.updateFormValue();
194
- }
195
- // 3. Render only if visual properties changed AND component is connected
196
- const visualChanged = changes.some(c => this.props.isVisual(c.name));
197
- if (visualChanged && this._connected) {
198
- this.render();
199
- }
200
- // 4. Emit change events if configured
201
- this._emitChangeEvents(changes);
202
- }
203
- /**
204
- * Emit property change events for properties that require it
205
- * Uses 'prop:change' event to avoid conflicts with user interaction 'change' events
206
- */
207
- _emitChangeEvents(changes) {
208
- for (const change of changes) {
209
- if (this.props.shouldEmitChange(change.name)) {
210
- this.dispatchEvent(new CustomEvent('prop:change', {
211
- detail: {
212
- property: change.name,
213
- oldValue: change.oldValue,
214
- newValue: change.newValue
215
- },
216
- bubbles: true,
217
- composed: true
218
- }));
219
- }
220
- }
221
- }
222
- /**
223
- * Update form value via ElementInternals
224
- * Subclasses can override to customize form value
225
- */
226
- updateFormValue() {
227
- const formValue = this.getFormValue();
228
- this._internals.setFormValue(formValue);
229
- }
230
- /**
231
- * Get the form value for this component
232
- * Default: return 'value' property
233
- * Override for custom behavior
234
- */
235
- getFormValue() {
236
- return this.props.get('value') ?? null;
237
- }
238
- /**
239
- * Hook: Called when properties change
240
- * Subclasses can override to update internal state
241
- *
242
- * This is called BEFORE rendering, so you can update
243
- * internal state here and it will be reflected in the render
244
- */
245
- onPropertiesChanged(changes) {
246
- // Default: no-op
247
- // Subclasses can override to update _state, _config, etc.
248
- }
249
- /**
250
- * Hook: Called when component is connected
251
- * Use this instead of overriding connectedCallback
252
- */
253
- onConnect() {
254
- // Default: no-op
255
- }
256
- /**
257
- * Hook: Called when component is disconnected
258
- * Use this for cleanup instead of overriding disconnectedCallback
259
- */
260
- onDisconnect() {
261
- // Default: no-op
262
- }
263
- /**
264
- * Get the form element this component is associated with
265
- */
266
- get form() {
267
- return this._internals.form;
268
- }
269
- /**
270
- * a11y helper for components whose ARIA role lives on an inner shadow element
271
- * (checkbox/switch/radio). A wrapping <label> names the form-associated HOST,
272
- * not the inner role element — so mirror the host's associated label text onto
273
- * the role element as aria-label, giving it an accessible name.
274
- */
275
- applyLabelName(roleEl) {
276
- let text = Array.from(this._internals.labels ?? [])
277
- .map((l) => l.textContent?.trim())
278
- .filter(Boolean)
279
- .join(' ');
280
- if (!text) {
281
- // Non-form-associated controls (e.g. ty-radio) aren't labelable, so the
282
- // wrapping <label> never appears in internals.labels — read it directly,
283
- // stripping this element's own subtree from the text.
284
- const lbl = this.closest('label');
285
- if (lbl) {
286
- const clone = lbl.cloneNode(true);
287
- clone.querySelectorAll(this.tagName.toLowerCase()).forEach((n) => n.remove());
288
- text = clone.textContent?.trim() ?? '';
289
- }
290
- }
291
- if (text)
292
- roleEl.setAttribute('aria-label', text);
293
- else
294
- roleEl.removeAttribute('aria-label');
295
- }
296
- /**
297
- * Form reset callback - called when form.reset() is invoked
298
- * Resets component to its default value
299
- */
300
- formResetCallback() {
301
- // Get the default value from property configuration
302
- const ctor = this.constructor;
303
- const valueConfig = ctor.properties['value'];
304
- if (valueConfig) {
305
- const defaultValue = valueConfig.default ?? '';
306
- // Reset the value property through setProperty to trigger lifecycle
307
- this.setProperty('value', defaultValue);
308
- }
309
- // Call subclass hook for custom reset behavior
310
- this.onFormReset();
311
- }
312
- /**
313
- * Hook: Called when form is reset
314
- * Subclasses can override to perform additional reset actions
315
- */
316
- onFormReset() {
317
- // Default: no-op
318
- // Subclasses can override to reset additional state
319
- }
3
+ constructor() {
4
+ super();
5
+ this._connected = false;
6
+ this._rendered = false;
7
+ this._handlingActivationClick = false;
8
+ this._resetDefaults = null;
9
+ const ctor = this.constructor;
10
+ this.props = new PropertyManager(ctor.properties);
11
+ this._internals = this.attachInternals();
12
+ if (!this.shadowRoot) {
13
+ this.attachShadow({ mode: 'open' });
14
+ }
15
+ }
16
+ static get observedAttributes() {
17
+ const attrs = [];
18
+ for (const [name, config] of Object.entries(this.properties)) {
19
+ attrs.push(name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase());
20
+ if (config.aliases) {
21
+ for (const alias of Object.keys(config.aliases)) {
22
+ attrs.push(alias);
23
+ }
24
+ }
25
+ }
26
+ return attrs;
27
+ }
28
+ setProperty(name, value) {
29
+ const change = this.props.updateProperty(name, value, 'property');
30
+ if (change) {
31
+ this._syncPropertyToAttribute(change);
32
+ this._handlePropertyChanges([change]);
33
+ }
34
+ }
35
+ getProperty(name) {
36
+ return this.props.get(name);
37
+ }
38
+ _syncPropertyToAttribute(change) {
39
+ const { name, newValue } = change;
40
+ const config = this.props.getConfig(name);
41
+ if (!config)
42
+ return;
43
+ const attrName = this._toKebabCase(name);
44
+ if (config.type === 'boolean') {
45
+ if (newValue) {
46
+ this.setAttribute(attrName, '');
47
+ }
48
+ else {
49
+ this.removeAttribute(attrName);
50
+ }
51
+ }
52
+ else if (newValue === null || newValue === undefined) {
53
+ this.removeAttribute(attrName);
54
+ }
55
+ else if (typeof newValue === 'object') {
56
+ this.setAttribute(attrName, JSON.stringify(newValue));
57
+ }
58
+ else {
59
+ this.setAttribute(attrName, String(newValue));
60
+ }
61
+ }
62
+ _toKebabCase(str) {
63
+ return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
64
+ }
65
+ _toCamelCase(str) {
66
+ return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
67
+ }
68
+ attributeChangedCallback(name, oldValue, newValue) {
69
+ if (oldValue === newValue)
70
+ return;
71
+ let change = this.props.handleAlias(name, newValue);
72
+ if (!change) {
73
+ const camelName = this._toCamelCase(name);
74
+ const propName = this.props.hasConfig(name) ? name : camelName;
75
+ change = this.props.updateProperty(propName, newValue, 'attribute');
76
+ }
77
+ if (change) {
78
+ this._handlePropertyChanges([change]);
79
+ }
80
+ }
81
+ connectedCallback() {
82
+ this._connected = true;
83
+ if (!this._resetDefaults) {
84
+ this._resetDefaults = new Map();
85
+ const ctor = this.constructor;
86
+ for (const [name, config] of Object.entries(ctor.properties)) {
87
+ if (!config.formValue)
88
+ continue;
89
+ const attr = this.getAttribute(this._toKebabCase(name));
90
+ this._resetDefaults.set(name, attr ?? config.default ?? null);
91
+ }
92
+ }
93
+ const preSetProps = this._capturePreSetProperties();
94
+ if (preSetProps.length > 0) {
95
+ this._handlePropertyChanges(preSetProps);
96
+ }
97
+ this.onConnect();
98
+ if (!this._rendered) {
99
+ this.render();
100
+ this._rendered = true;
101
+ }
102
+ }
103
+ disconnectedCallback() {
104
+ this._connected = false;
105
+ this.onDisconnect();
106
+ }
107
+ _capturePreSetProperties() {
108
+ const changes = [];
109
+ const ctor = this.constructor;
110
+ for (const propName of Object.keys(ctor.properties)) {
111
+ const descriptor = Object.getOwnPropertyDescriptor(this, propName);
112
+ if (descriptor && descriptor.value !== undefined) {
113
+ const change = this.props.updateProperty(propName, descriptor.value, 'property');
114
+ if (change) {
115
+ changes.push(change);
116
+ }
117
+ }
118
+ }
119
+ return changes;
120
+ }
121
+ _handlePropertyChanges(changes) {
122
+ if (changes.length === 0)
123
+ return;
124
+ this.onPropertiesChanged(changes);
125
+ const formValueChanged = changes.some(c => this.props.isFormValue(c.name));
126
+ if (formValueChanged) {
127
+ this.updateFormValue();
128
+ }
129
+ const visualChanged = changes.some(c => this.props.isVisual(c.name));
130
+ if (visualChanged && this._connected) {
131
+ this.render();
132
+ }
133
+ this._emitChangeEvents(changes);
134
+ }
135
+ _emitChangeEvents(changes) {
136
+ for (const change of changes) {
137
+ if (this.props.shouldEmitChange(change.name)) {
138
+ this.dispatchEvent(new CustomEvent('prop:change', {
139
+ detail: {
140
+ property: change.name,
141
+ oldValue: change.oldValue,
142
+ newValue: change.newValue
143
+ },
144
+ bubbles: true,
145
+ composed: true
146
+ }));
147
+ }
148
+ }
149
+ }
150
+ updateFormValue() {
151
+ const formValue = this.getFormValue();
152
+ this._internals.setFormValue(formValue);
153
+ }
154
+ getFormValue() {
155
+ return this.props.get('value') ?? null;
156
+ }
157
+ onPropertiesChanged(changes) {
158
+ }
159
+ onConnect() {
160
+ }
161
+ onDisconnect() {
162
+ }
163
+ get form() {
164
+ return this._internals.form;
165
+ }
166
+ applyLabelName(roleEl) {
167
+ let text = Array.from(this._internals.labels ?? [])
168
+ .map((l) => l.textContent?.trim())
169
+ .filter(Boolean)
170
+ .join(' ');
171
+ if (!text) {
172
+ const lbl = this.closest('label');
173
+ if (lbl) {
174
+ const clone = lbl.cloneNode(true);
175
+ clone.querySelectorAll(this.tagName.toLowerCase()).forEach((n) => n.remove());
176
+ text = clone.textContent?.trim() ?? '';
177
+ }
178
+ }
179
+ if (text)
180
+ roleEl.setAttribute('aria-label', text);
181
+ else
182
+ roleEl.removeAttribute('aria-label');
183
+ }
184
+ isDuplicateActivationClick() {
185
+ if (this._handlingActivationClick)
186
+ return true;
187
+ this._handlingActivationClick = true;
188
+ queueMicrotask(() => { this._handlingActivationClick = false; });
189
+ return false;
190
+ }
191
+ formResetCallback() {
192
+ for (const [name, def] of this._resetDefaults ?? []) {
193
+ this.setProperty(name, def);
194
+ }
195
+ this.onFormReset();
196
+ }
197
+ onFormReset() {
198
+ }
320
199
  }
321
200
  TyComponent.formAssociated = true;
322
- // Subclasses must define their property configuration
323
201
  TyComponent.properties = {};
324
- //# sourceMappingURL=ty-component.js.map
@@ -1,12 +1,6 @@
1
1
  /**
2
- * TyButton Web Component
3
- *
4
- * Three appearance variants × six flavors × three tones (+/base/-).
5
- * appearance="solid" saturated brand fill (default)
6
- * appearance="outlined" transparent bg, text === border
7
- * appearance="ghost" text only, hover bg
8
- *
9
- * Append `+` or `-` to a flavor for stronger/softer tone (e.g. "primary+").
2
+ * TyButton Web Component — three appearances (solid/outlined/ghost) × six
3
+ * flavors × three tones. Append `+`/`-` to a flavor for stronger/softer tone.
10
4
  */
11
5
  import type { Flavor, Size, TyButtonElement } from "../types/common.js";
12
6
  import { TyComponent } from "../base/ty-component.js";
@@ -27,13 +21,6 @@ interface ButtonState {
27
21
  }
28
22
  /**
29
23
  * Ty Button Component
30
- *
31
- * @example
32
- * ```html
33
- * <ty-button flavor="primary">Default solid</ty-button>
34
- * <ty-button appearance="outlined" flavor="danger">Outlined</ty-button>
35
- * <ty-button appearance="ghost" flavor="success+">Ghost stronger</ty-button>
36
- * ```
37
24
  */
38
25
  export declare class TyButton extends TyComponent<ButtonState> implements TyButtonElement {
39
26
  static formAssociated: boolean;
@@ -46,7 +33,7 @@ export declare class TyButton extends TyComponent<ButtonState> implements TyButt
46
33
  size: {
47
34
  type: "string";
48
35
  visual: boolean;
49
- default: string;
36
+ default: Size;
50
37
  validate: (v: any) => boolean;
51
38
  coerce: (v: any) => any;
52
39
  };
@@ -147,4 +134,3 @@ export declare class TyButton extends TyComponent<ButtonState> implements TyButt
147
134
  protected render(): void;
148
135
  }
149
136
  export {};
150
- //# sourceMappingURL=button.d.ts.map