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
@@ -1,429 +1,286 @@
1
- /**
2
- * TyCheckbox Web Component
3
- *
4
- * "Just the box" primitive — renders only the checkbox visual + state.
5
- * Label, required asterisk, and error display are the consumer's
6
- * responsibility — wrap in a `<label>` for click delegation.
7
- *
8
- * - Boolean checked state, form-associated
9
- * - Keyboard accessibility (Space/Enter)
10
- * - Sizes (xs, sm, md, lg, xl) and semantic flavors
11
- *
12
- * @example
13
- * <label>
14
- * <ty-checkbox name="terms" required></ty-checkbox>
15
- * I agree to the <a href="/terms">terms</a>
16
- * </label>
17
- */
1
+ import { DEFAULT_SIZE } from "../types/common.js";
18
2
  import { TyComponent } from "../base/ty-component.js";
19
3
  import { ensureStyles } from "../utils/styles.js";
20
4
  import { syncCustomFlavorSheet } from "../utils/flavor-sheet.js";
21
5
  import { checkboxStyles, checkboxCustomFlavorCss } from "../styles/checkbox.js";
22
- /**
23
- * Checkmark icon (Lucide `check`, same glyph as ty-option's selected check;
24
- * stroke-width 3 for presence at 16px — it replaces a heavy fill glyph).
25
- * Same glyph for checked and unchecked — checked shows it at full color,
26
- * unchecked at faint color (see styles).
27
- */
28
6
  const CHECK_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>`;
29
- /**
30
- * Dash icon (Lucide `minus`) — shown while indeterminate.
31
- */
32
7
  const DASH_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/></svg>`;
33
- /**
34
- * Ty Checkbox Component
35
- *
36
- * @example
37
- * ```html
38
- * <!-- Basic checkbox -->
39
- * <ty-checkbox>Subscribe to newsletter</ty-checkbox>
40
- *
41
- * <!-- Pre-checked with custom value -->
42
- * <ty-checkbox
43
- * checked
44
- * value="accepted"
45
- * required>
46
- * Accept terms
47
- * </ty-checkbox>
48
- *
49
- * <!-- With error state -->
50
- * <ty-checkbox
51
- * required
52
- * error="You must agree to continue"
53
- * flavor="danger">
54
- * Agree to terms
55
- * </ty-checkbox>
56
- *
57
- * <!-- Different sizes -->
58
- * <ty-checkbox size="sm">Small</ty-checkbox>
59
- * <ty-checkbox size="lg">Large</ty-checkbox>
60
- *
61
- * <!-- Semantic flavors -->
62
- * <ty-checkbox flavor="primary" checked>Primary</ty-checkbox>
63
- * <ty-checkbox flavor="success" checked>Success</ty-checkbox>
64
- *
65
- * <!-- Rich content (with icon) -->
66
- * <ty-checkbox checked>
67
- * <ty-icon name="star"></ty-icon>
68
- * Premium feature
69
- * </ty-checkbox>
70
- * ```
71
- */
72
8
  export class TyCheckbox extends TyComponent {
73
- constructor() {
74
- super(); // TyComponent handles attachInternals() and attachShadow()
75
- // ============================================================================
76
- // INTERNAL STATE - Not managed by PropertyManager
77
- // NOTE: _internals provided by TyComponent base class
78
- // ============================================================================
79
- this._customFlavorSheet = null;
80
- this._listenersSetup = false;
81
- // Store references to handlers for cleanup
82
- this._clickHandler = null;
83
- this._keydownHandler = null;
84
- this._focusHandler = null;
85
- this._blurHandler = null;
86
- // Apply styles to shadow root
87
- const shadow = this.shadowRoot;
88
- ensureStyles(shadow, { css: checkboxStyles, id: "ty-checkbox" });
89
- }
90
- // observedAttributes auto-generated by TyComponent from properties config
91
- // ============================================================================
92
- // TYCOMPONENT LIFECYCLE HOOKS
93
- // ============================================================================
94
- /**
95
- * Called when component connects to DOM
96
- * TyComponent already handled pre-connection property capture
97
- */
98
- onConnect() {
99
- // Re-arm listeners on RE-connect: the base class skips render() when
100
- // already rendered, and onDisconnect removed the listeners. No-ops on
101
- // first connect (no container yet — render() attaches them).
102
- this.setupEventListeners();
103
- this._syncCustomFlavor();
104
- }
105
- /** Custom (non-built-in) flavors — see utils/flavor-sheet.ts. */
106
- _syncCustomFlavor() {
107
- this._customFlavorSheet = syncCustomFlavorSheet(this.shadowRoot, this._customFlavorSheet, this.flavor, ({ base }) => checkboxCustomFlavorCss(base));
108
- }
109
- /**
110
- * Called when component disconnects from DOM
111
- */
112
- onDisconnect() {
113
- // Clean up event listeners when component is removed from DOM
114
- this.removeEventListeners();
115
- }
116
- /**
117
- * Handle property changes - called BEFORE render
118
- */
119
- onPropertiesChanged(changes) {
120
- if (changes.some((c) => c.name === "flavor")) {
121
- this._syncCustomFlavor();
122
- }
123
- }
124
- /**
125
- * Override form value to return value when checked, null when unchecked
126
- */
127
- getFormValue() {
128
- return this.checked ? this.value : null;
129
- }
130
- // Removed old attributeChangedCallback, initializeCheckboxState, validateFlavor - handled by TyComponent
131
- /**
132
- * Build CSS class list for checkbox container
133
- */
134
- buildClassList() {
135
- const classes = [this.size];
136
- if (this.disabled)
137
- classes.push("disabled");
138
- if (this.required)
139
- classes.push("required");
140
- return classes.join(" ");
141
- }
142
- /**
143
- * Handle checkbox click event - standards compliant approach
144
- */
145
- handleCheckboxClick(e) {
146
- if (this.disabled)
147
- return;
148
- // Native semantics: clicking an indeterminate checkbox resolves to checked
149
- const newValue = this.indeterminate ? true : !this.checked;
150
- if (this.indeterminate)
151
- this.indeterminate = false;
152
- this.checked = newValue; // Uses setProperty which handles everything
153
- // Emit custom events after property update
154
- setTimeout(() => {
155
- const eventDetail = {
156
- value: newValue,
157
- checked: newValue,
158
- formValue: newValue ? this.value : null,
159
- originalEvent: e,
160
- };
161
- this.dispatchEvent(new CustomEvent("input", {
162
- detail: eventDetail,
163
- bubbles: true,
164
- composed: true,
165
- }));
166
- this.dispatchEvent(new CustomEvent("change", {
167
- detail: eventDetail,
168
- bubbles: true,
169
- composed: true,
170
- }));
171
- }, 0);
172
- }
173
- /**
174
- * Handle checkbox keyboard events - space/enter to toggle
175
- */
176
- handleCheckboxKeydown(e) {
177
- if (this.disabled)
178
- return;
179
- if (["Space", " ", "Enter"].includes(e.key)) {
180
- e.preventDefault(); // Prevent default for keyboard to avoid page scroll
181
- e.stopPropagation();
182
- this.handleCheckboxClick(e);
183
- }
184
- }
185
- /**
186
- * Remove event listeners for cleanup
187
- */
188
- removeEventListeners() {
189
- if (!this._listenersSetup)
190
- return;
191
- // Click lives on the HOST (label delegation + full-element trigger) —
192
- // remove it before the shadow-container guard below.
193
- if (this._clickHandler) {
194
- this.removeEventListener("click", this._clickHandler);
195
- this._clickHandler = null;
196
- }
197
- const shadow = this.shadowRoot;
198
- if (!shadow)
199
- return;
200
- const checkboxEl = shadow.querySelector(".checkbox-container");
201
- if (!checkboxEl) {
202
- this._listenersSetup = false;
203
- return;
204
- }
205
- if (this._keydownHandler) {
206
- checkboxEl.removeEventListener("keydown", this._keydownHandler);
207
- this._keydownHandler = null;
208
- }
209
- if (this._focusHandler) {
210
- checkboxEl.removeEventListener("focus", this._focusHandler);
211
- this._focusHandler = null;
212
- }
213
- if (this._blurHandler) {
214
- checkboxEl.removeEventListener("blur", this._blurHandler);
215
- this._blurHandler = null;
216
- }
217
- this._listenersSetup = false;
218
- }
219
- /**
220
- * Setup event listeners for checkbox functionality
221
- * IMPORTANT: Only called ONCE, not on every render
222
- */
223
- setupEventListeners() {
224
- if (this._listenersSetup)
225
- return;
226
- const shadow = this.shadowRoot;
227
- const checkboxEl = shadow.querySelector(".checkbox-container");
228
- if (!checkboxEl)
229
- return;
230
- // Create and store handler references for cleanup
231
- this._clickHandler = (e) => {
232
- this.handleCheckboxClick(e);
233
- };
234
- this._keydownHandler = (e) => {
235
- this.handleCheckboxKeydown(e);
236
- };
237
- this._focusHandler = () => {
238
- checkboxEl.classList.add("focused");
239
- };
240
- this._blurHandler = () => {
241
- checkboxEl.classList.remove("focused");
242
- };
243
- // Click on the HOST: makes the whole element a trigger and lets a wrapping
244
- // <label> delegate (the synthetic click lands on the host, not the shadow).
245
- // Keyboard/focus stay on the focusable container.
246
- this.addEventListener("click", this._clickHandler);
247
- checkboxEl.addEventListener("keydown", this._keydownHandler);
248
- checkboxEl.addEventListener("focus", this._focusHandler);
249
- checkboxEl.addEventListener("blur", this._blurHandler);
250
- this._listenersSetup = true;
251
- }
252
- /**
253
- * Render the checkbox — just the box visual.
254
- * Label, required asterisk, and error UI are the consumer's responsibility.
255
- */
256
- render() {
257
- const shadow = this.shadowRoot;
258
- let checkboxEl = shadow.querySelector(".checkbox-container");
259
- const classes = this.buildClassList();
260
- const ariaChecked = this.indeterminate ? "mixed" : String(this.checked);
261
- if (!checkboxEl) {
262
- checkboxEl = document.createElement("div");
263
- checkboxEl.className = "checkbox-container " + classes;
264
- checkboxEl.tabIndex = this.disabled ? -1 : 0;
265
- checkboxEl.setAttribute("role", "checkbox");
266
- checkboxEl.setAttribute("aria-checked", ariaChecked);
267
- checkboxEl.setAttribute("aria-disabled", String(this.disabled));
268
- checkboxEl.setAttribute("aria-required", String(this.required));
269
- const checkboxIcon = document.createElement("div");
270
- checkboxIcon.className = "checkbox-icon";
271
- checkboxEl.appendChild(checkboxIcon);
272
- shadow.appendChild(checkboxEl);
273
- }
274
- else {
275
- checkboxEl.className = "checkbox-container " + classes;
276
- checkboxEl.tabIndex = this.disabled ? -1 : 0;
277
- checkboxEl.setAttribute("aria-checked", ariaChecked);
278
- checkboxEl.setAttribute("aria-disabled", String(this.disabled));
279
- checkboxEl.setAttribute("aria-required", String(this.required));
280
- }
281
- // Dash while indeterminate, tick otherwise (tick's color/opacity carries
282
- // the checked/unchecked distinction via CSS).
283
- const icon = checkboxEl.querySelector(".checkbox-icon");
284
- icon.innerHTML = this.indeterminate ? DASH_ICON : CHECK_ICON;
285
- // (Re)attach listeners — onDisconnect removes them, so a reconnected
286
- // element needs them again even though the container already exists.
287
- this.setupEventListeners();
288
- // a11y: role="checkbox" lives on this inner element, but the associated
289
- // <label> names the (form-associated) host. Mirror that name onto the role
290
- // element so it has an accessible name.
291
- this.applyLabelName(checkboxEl);
292
- // Reflect constraint validation to the owning <form> (required was cosmetic).
293
- this.updateValidity();
294
- }
295
- /** required + unchecked => valueMissing; otherwise valid. */
296
- updateValidity() {
297
- const anchor = this.shadowRoot?.querySelector(".checkbox-container");
298
- if (this.disabled) {
299
- this._internals.setValidity({});
300
- return;
301
- }
302
- if (this.required && !this.checked) {
303
- this._internals.setValidity({ valueMissing: true }, "Please check this box", anchor ?? undefined);
304
- }
305
- else {
306
- this._internals.setValidity({});
307
- }
308
- }
309
- // ============================================================================
310
- // PROPERTY ACCESSORS - Simple wrappers (no logic!)
311
- // ============================================================================
312
- get checked() {
313
- return this.getProperty("checked");
314
- }
315
- set checked(value) {
316
- this.setProperty("checked", value);
317
- }
318
- get indeterminate() {
319
- return this.getProperty("indeterminate");
320
- }
321
- set indeterminate(value) {
322
- this.setProperty("indeterminate", value);
323
- }
324
- get value() {
325
- return this.getProperty("value");
326
- }
327
- set value(val) {
328
- this.setProperty("value", val);
329
- }
330
- get name() {
331
- return this.getProperty("name");
332
- }
333
- set name(val) {
334
- this.setProperty("name", val);
335
- }
336
- get disabled() {
337
- return this.getProperty("disabled");
338
- }
339
- set disabled(value) {
340
- this.setProperty("disabled", value);
341
- }
342
- get required() {
343
- return this.getProperty("required");
344
- }
345
- set required(value) {
346
- this.setProperty("required", value);
347
- }
348
- get size() {
349
- return this.getProperty("size");
350
- }
351
- set size(value) {
352
- this.setProperty("size", value);
353
- }
354
- get flavor() {
355
- return this.getProperty("flavor");
356
- }
357
- set flavor(value) {
358
- this.setProperty("flavor", value);
359
- }
360
- get form() {
361
- return this._internals.form;
362
- }
9
+ constructor() {
10
+ super();
11
+ this._customFlavorSheet = null;
12
+ this._listenersSetup = false;
13
+ this._clickHandler = null;
14
+ this._keydownHandler = null;
15
+ this._focusHandler = null;
16
+ this._blurHandler = null;
17
+ const shadow = this.shadowRoot;
18
+ ensureStyles(shadow, { css: checkboxStyles, id: "ty-checkbox" });
19
+ }
20
+ onConnect() {
21
+ this.setupEventListeners();
22
+ this._syncCustomFlavor();
23
+ }
24
+ _syncCustomFlavor() {
25
+ this._customFlavorSheet = syncCustomFlavorSheet(this.shadowRoot, this._customFlavorSheet, this.flavor, ({ base }) => checkboxCustomFlavorCss(base));
26
+ }
27
+ onDisconnect() {
28
+ this.removeEventListeners();
29
+ }
30
+ onPropertiesChanged(changes) {
31
+ if (changes.some((c) => c.name === "flavor")) {
32
+ this._syncCustomFlavor();
33
+ }
34
+ }
35
+ getFormValue() {
36
+ return this.checked ? this.value : null;
37
+ }
38
+ buildClassList() {
39
+ const classes = [this.size];
40
+ if (this.disabled)
41
+ classes.push("disabled");
42
+ if (this.required)
43
+ classes.push("required");
44
+ return classes.join(" ");
45
+ }
46
+ handleCheckboxClick(e) {
47
+ if (this.disabled)
48
+ return;
49
+ if (this.isDuplicateActivationClick())
50
+ return;
51
+ const newValue = this.indeterminate ? true : !this.checked;
52
+ if (this.indeterminate)
53
+ this.indeterminate = false;
54
+ this.checked = newValue;
55
+ setTimeout(() => {
56
+ const eventDetail = {
57
+ value: newValue,
58
+ checked: newValue,
59
+ formValue: newValue ? this.value : null,
60
+ originalEvent: e,
61
+ };
62
+ this.dispatchEvent(new CustomEvent("input", {
63
+ detail: eventDetail,
64
+ bubbles: true,
65
+ composed: true,
66
+ }));
67
+ this.dispatchEvent(new CustomEvent("change", {
68
+ detail: eventDetail,
69
+ bubbles: true,
70
+ composed: true,
71
+ }));
72
+ }, 0);
73
+ }
74
+ handleCheckboxKeydown(e) {
75
+ if (this.disabled)
76
+ return;
77
+ if (["Space", " ", "Enter"].includes(e.key)) {
78
+ e.preventDefault();
79
+ e.stopPropagation();
80
+ this.handleCheckboxClick(e);
81
+ }
82
+ }
83
+ removeEventListeners() {
84
+ if (!this._listenersSetup)
85
+ return;
86
+ if (this._clickHandler) {
87
+ this.removeEventListener("click", this._clickHandler);
88
+ this._clickHandler = null;
89
+ }
90
+ const shadow = this.shadowRoot;
91
+ if (!shadow)
92
+ return;
93
+ const checkboxEl = shadow.querySelector(".checkbox-container");
94
+ if (!checkboxEl) {
95
+ this._listenersSetup = false;
96
+ return;
97
+ }
98
+ if (this._keydownHandler) {
99
+ checkboxEl.removeEventListener("keydown", this._keydownHandler);
100
+ this._keydownHandler = null;
101
+ }
102
+ if (this._focusHandler) {
103
+ checkboxEl.removeEventListener("focus", this._focusHandler);
104
+ this._focusHandler = null;
105
+ }
106
+ if (this._blurHandler) {
107
+ checkboxEl.removeEventListener("blur", this._blurHandler);
108
+ this._blurHandler = null;
109
+ }
110
+ this._listenersSetup = false;
111
+ }
112
+ setupEventListeners() {
113
+ if (this._listenersSetup)
114
+ return;
115
+ const shadow = this.shadowRoot;
116
+ const checkboxEl = shadow.querySelector(".checkbox-container");
117
+ if (!checkboxEl)
118
+ return;
119
+ this._clickHandler = (e) => {
120
+ this.handleCheckboxClick(e);
121
+ };
122
+ this._keydownHandler = (e) => {
123
+ this.handleCheckboxKeydown(e);
124
+ };
125
+ this._focusHandler = () => {
126
+ checkboxEl.classList.add("focused");
127
+ };
128
+ this._blurHandler = () => {
129
+ checkboxEl.classList.remove("focused");
130
+ };
131
+ this.addEventListener("click", this._clickHandler);
132
+ checkboxEl.addEventListener("keydown", this._keydownHandler);
133
+ checkboxEl.addEventListener("focus", this._focusHandler);
134
+ checkboxEl.addEventListener("blur", this._blurHandler);
135
+ this._listenersSetup = true;
136
+ }
137
+ render() {
138
+ const shadow = this.shadowRoot;
139
+ let checkboxEl = shadow.querySelector(".checkbox-container");
140
+ const classes = this.buildClassList();
141
+ const ariaChecked = this.indeterminate ? "mixed" : String(this.checked);
142
+ if (!checkboxEl) {
143
+ checkboxEl = document.createElement("div");
144
+ checkboxEl.className = "checkbox-container " + classes;
145
+ checkboxEl.tabIndex = this.disabled ? -1 : 0;
146
+ checkboxEl.setAttribute("role", "checkbox");
147
+ checkboxEl.setAttribute("aria-checked", ariaChecked);
148
+ checkboxEl.setAttribute("aria-disabled", String(this.disabled));
149
+ checkboxEl.setAttribute("aria-required", String(this.required));
150
+ const checkboxIcon = document.createElement("div");
151
+ checkboxIcon.className = "checkbox-icon";
152
+ checkboxEl.appendChild(checkboxIcon);
153
+ shadow.appendChild(checkboxEl);
154
+ }
155
+ else {
156
+ checkboxEl.className = "checkbox-container " + classes;
157
+ checkboxEl.tabIndex = this.disabled ? -1 : 0;
158
+ checkboxEl.setAttribute("aria-checked", ariaChecked);
159
+ checkboxEl.setAttribute("aria-disabled", String(this.disabled));
160
+ checkboxEl.setAttribute("aria-required", String(this.required));
161
+ }
162
+ const icon = checkboxEl.querySelector(".checkbox-icon");
163
+ icon.innerHTML = this.indeterminate ? DASH_ICON : CHECK_ICON;
164
+ this.setupEventListeners();
165
+ this.applyLabelName(checkboxEl);
166
+ this.updateValidity();
167
+ }
168
+ updateValidity() {
169
+ const anchor = this.shadowRoot?.querySelector(".checkbox-container");
170
+ if (this.disabled) {
171
+ this._internals.setValidity({});
172
+ return;
173
+ }
174
+ if (this.required && !this.checked) {
175
+ this._internals.setValidity({ valueMissing: true }, "Please check this box", anchor ?? undefined);
176
+ }
177
+ else {
178
+ this._internals.setValidity({});
179
+ }
180
+ }
181
+ get checked() {
182
+ return this.getProperty("checked");
183
+ }
184
+ set checked(value) {
185
+ this.setProperty("checked", value);
186
+ }
187
+ get indeterminate() {
188
+ return this.getProperty("indeterminate");
189
+ }
190
+ set indeterminate(value) {
191
+ this.setProperty("indeterminate", value);
192
+ }
193
+ get value() {
194
+ return this.getProperty("value");
195
+ }
196
+ set value(val) {
197
+ this.setProperty("value", val);
198
+ }
199
+ get name() {
200
+ return this.getProperty("name");
201
+ }
202
+ set name(val) {
203
+ this.setProperty("name", val);
204
+ }
205
+ get disabled() {
206
+ return this.getProperty("disabled");
207
+ }
208
+ set disabled(value) {
209
+ this.setProperty("disabled", value);
210
+ }
211
+ get required() {
212
+ return this.getProperty("required");
213
+ }
214
+ set required(value) {
215
+ this.setProperty("required", value);
216
+ }
217
+ get size() {
218
+ return this.getProperty("size");
219
+ }
220
+ set size(value) {
221
+ this.setProperty("size", value);
222
+ }
223
+ get flavor() {
224
+ return this.getProperty("flavor");
225
+ }
226
+ set flavor(value) {
227
+ this.setProperty("flavor", value);
228
+ }
229
+ get form() {
230
+ return this._internals.form;
231
+ }
363
232
  }
364
233
  TyCheckbox.formAssociated = true;
365
- // ============================================================================
366
- // PROPERTY CONFIGURATION - Declarative property lifecycle
367
- // ============================================================================
368
234
  TyCheckbox.properties = {
369
- // Core boolean state
370
- checked: {
371
- type: "boolean",
372
- visual: true,
373
- formValue: true, // Triggers form value update
374
- emitChange: true, // Emits 'prop:change' event
375
- default: false,
376
- },
377
- // Visual/ARIA "mixed" state (native semantics: no form-value effect,
378
- // clicking resolves to checked)
379
- indeterminate: {
380
- type: "boolean",
381
- visual: true,
382
- default: false,
383
- },
384
- // Form submission value (when checked)
385
- value: {
386
- type: "string",
387
- default: "on",
388
- },
389
- name: {
390
- type: "string",
391
- default: "",
392
- },
393
- disabled: {
394
- type: "boolean",
395
- visual: true,
396
- default: false,
397
- },
398
- required: {
399
- type: "boolean",
400
- visual: true,
401
- default: false,
402
- },
403
- size: {
404
- type: "string",
405
- visual: true,
406
- default: "md",
407
- validate: (v) => ["xs", "sm", "md", "lg", "xl"].includes(v),
408
- coerce: (v) => {
409
- if (!["xs", "sm", "md", "lg", "xl"].includes(v)) {
410
- console.warn(`[ty-checkbox] Invalid size '${v}'. Using 'md'.`);
411
- return "md";
412
- }
413
- return v;
414
- },
415
- },
416
- // Any string is accepted: built-ins get static CSS, other identifiers
417
- // become custom flavors (see _syncCustomFlavor), garbage degrades to
418
- // the default look.
419
- flavor: {
420
- type: "string",
421
- visual: true,
422
- default: "neutral",
423
- },
235
+ checked: {
236
+ type: "boolean",
237
+ visual: true,
238
+ formValue: true,
239
+ emitChange: true,
240
+ default: false,
241
+ },
242
+ indeterminate: {
243
+ type: "boolean",
244
+ visual: true,
245
+ default: false,
246
+ },
247
+ value: {
248
+ type: "string",
249
+ default: "on",
250
+ },
251
+ name: {
252
+ type: "string",
253
+ default: "",
254
+ },
255
+ disabled: {
256
+ type: "boolean",
257
+ visual: true,
258
+ default: false,
259
+ },
260
+ required: {
261
+ type: "boolean",
262
+ visual: true,
263
+ default: false,
264
+ },
265
+ size: {
266
+ type: "string",
267
+ visual: true,
268
+ default: DEFAULT_SIZE,
269
+ validate: (v) => ["xs", "sm", "md", "lg", "xl"].includes(v),
270
+ coerce: (v) => {
271
+ if (!["xs", "sm", "md", "lg", "xl"].includes(v)) {
272
+ console.warn(`[ty-checkbox] Invalid size '${v}'. Using '${DEFAULT_SIZE}'.`);
273
+ return DEFAULT_SIZE;
274
+ }
275
+ return v;
276
+ },
277
+ },
278
+ flavor: {
279
+ type: "string",
280
+ visual: true,
281
+ default: "neutral",
282
+ },
424
283
  };
425
- // Register the custom element
426
284
  if (!customElements.get("ty-checkbox")) {
427
- customElements.define("ty-checkbox", TyCheckbox);
285
+ customElements.define("ty-checkbox", TyCheckbox);
428
286
  }
429
- //# sourceMappingURL=checkbox.js.map