@fusion.dev/helix-headless 0.0.0-dev

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 (424) hide show
  1. package/LICENSE +21 -0
  2. package/custom-elements.json +75202 -0
  3. package/dist/accordion/index.d.ts +2 -0
  4. package/dist/accordion/index.js +2 -0
  5. package/dist/accordion/item/accordion-item.d.ts +141 -0
  6. package/dist/accordion/item/accordion-item.js +214 -0
  7. package/dist/accordion/root/accordion-root.d.ts +57 -0
  8. package/dist/accordion/root/accordion-root.js +96 -0
  9. package/dist/announcement/index.d.ts +1 -0
  10. package/dist/announcement/index.js +1 -0
  11. package/dist/announcement/root/announcement-root.d.ts +106 -0
  12. package/dist/announcement/root/announcement-root.js +144 -0
  13. package/dist/app-header/index.d.ts +1 -0
  14. package/dist/app-header/index.js +1 -0
  15. package/dist/app-header/root/app-header-root.d.ts +113 -0
  16. package/dist/app-header/root/app-header-root.js +147 -0
  17. package/dist/avatar/group/avatar-group.d.ts +116 -0
  18. package/dist/avatar/group/avatar-group.js +136 -0
  19. package/dist/avatar/index.d.ts +2 -0
  20. package/dist/avatar/index.js +2 -0
  21. package/dist/avatar/root/avatar-root.d.ts +71 -0
  22. package/dist/avatar/root/avatar-root.js +147 -0
  23. package/dist/badge/index.d.ts +1 -0
  24. package/dist/badge/index.js +1 -0
  25. package/dist/badge/root/badge-root.d.ts +61 -0
  26. package/dist/badge/root/badge-root.js +121 -0
  27. package/dist/bar-chart/index.d.ts +1 -0
  28. package/dist/bar-chart/index.js +1 -0
  29. package/dist/bar-chart/root/bar-chart-root.d.ts +266 -0
  30. package/dist/bar-chart/root/bar-chart-root.js +515 -0
  31. package/dist/blockquote/index.d.ts +1 -0
  32. package/dist/blockquote/index.js +1 -0
  33. package/dist/blockquote/root/blockquote-root.d.ts +51 -0
  34. package/dist/blockquote/root/blockquote-root.js +84 -0
  35. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +104 -0
  36. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +137 -0
  37. package/dist/breadcrumbs/index.d.ts +2 -0
  38. package/dist/breadcrumbs/index.js +2 -0
  39. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +77 -0
  40. package/dist/breadcrumbs/root/breadcrumbs-root.js +94 -0
  41. package/dist/button/index.d.ts +1 -0
  42. package/dist/button/index.js +1 -0
  43. package/dist/button/root/button-root.d.ts +251 -0
  44. package/dist/button/root/button-root.js +401 -0
  45. package/dist/button-group/index.d.ts +1 -0
  46. package/dist/button-group/index.js +1 -0
  47. package/dist/button-group/root/button-group-root.d.ts +62 -0
  48. package/dist/button-group/root/button-group-root.js +62 -0
  49. package/dist/callout/index.d.ts +1 -0
  50. package/dist/callout/index.js +1 -0
  51. package/dist/callout/root/callout-root.d.ts +72 -0
  52. package/dist/callout/root/callout-root.js +90 -0
  53. package/dist/card/index.d.ts +1 -0
  54. package/dist/card/index.js +1 -0
  55. package/dist/card/root/card-root.d.ts +54 -0
  56. package/dist/card/root/card-root.js +71 -0
  57. package/dist/carousel/index.d.ts +1 -0
  58. package/dist/carousel/index.js +1 -0
  59. package/dist/carousel/root/carousel-root.d.ts +399 -0
  60. package/dist/carousel/root/carousel-root.js +723 -0
  61. package/dist/chat/composer/chat-composer.d.ts +160 -0
  62. package/dist/chat/composer/chat-composer.js +273 -0
  63. package/dist/chat/index.d.ts +3 -0
  64. package/dist/chat/index.js +3 -0
  65. package/dist/chat/message/chat-message.d.ts +170 -0
  66. package/dist/chat/message/chat-message.js +271 -0
  67. package/dist/chat/root/chat-root.d.ts +216 -0
  68. package/dist/chat/root/chat-root.js +389 -0
  69. package/dist/checkbox/index.d.ts +1 -0
  70. package/dist/checkbox/index.js +1 -0
  71. package/dist/checkbox/root/checkbox-root.d.ts +108 -0
  72. package/dist/checkbox/root/checkbox-root.js +207 -0
  73. package/dist/checkbox-group/index.d.ts +1 -0
  74. package/dist/checkbox-group/index.js +1 -0
  75. package/dist/checkbox-group/root/checkbox-group-root.d.ts +155 -0
  76. package/dist/checkbox-group/root/checkbox-group-root.js +293 -0
  77. package/dist/code/index.d.ts +1 -0
  78. package/dist/code/index.js +1 -0
  79. package/dist/code/root/code-root.d.ts +36 -0
  80. package/dist/code/root/code-root.js +43 -0
  81. package/dist/code-block/index.d.ts +1 -0
  82. package/dist/code-block/index.js +1 -0
  83. package/dist/code-block/root/code-block-root.d.ts +112 -0
  84. package/dist/code-block/root/code-block-root.js +155 -0
  85. package/dist/color-input/index.d.ts +1 -0
  86. package/dist/color-input/index.js +1 -0
  87. package/dist/color-input/root/color-input-root.d.ts +227 -0
  88. package/dist/color-input/root/color-input-root.js +456 -0
  89. package/dist/color-picker/color.d.ts +74 -0
  90. package/dist/color-picker/color.js +238 -0
  91. package/dist/color-picker/index.d.ts +2 -0
  92. package/dist/color-picker/index.js +2 -0
  93. package/dist/color-picker/root/color-picker-root.d.ts +303 -0
  94. package/dist/color-picker/root/color-picker-root.js +576 -0
  95. package/dist/combobox/index.d.ts +1 -0
  96. package/dist/combobox/index.js +1 -0
  97. package/dist/combobox/root/combobox-root.d.ts +396 -0
  98. package/dist/combobox/root/combobox-root.js +808 -0
  99. package/dist/command/index.d.ts +1 -0
  100. package/dist/command/index.js +1 -0
  101. package/dist/command/root/command-root.d.ts +166 -0
  102. package/dist/command/root/command-root.js +353 -0
  103. package/dist/copy-button/index.d.ts +1 -0
  104. package/dist/copy-button/index.js +1 -0
  105. package/dist/copy-button/root/copy-button-root.d.ts +154 -0
  106. package/dist/copy-button/root/copy-button-root.js +225 -0
  107. package/dist/data-table/index.d.ts +2 -0
  108. package/dist/data-table/index.js +2 -0
  109. package/dist/data-table/root/data-table-root.d.ts +392 -0
  110. package/dist/data-table/root/data-table-root.js +729 -0
  111. package/dist/data-table/root/order.d.ts +116 -0
  112. package/dist/data-table/root/order.js +175 -0
  113. package/dist/date-input/index.d.ts +1 -0
  114. package/dist/date-input/index.js +1 -0
  115. package/dist/date-input/root/date-input-root.d.ts +361 -0
  116. package/dist/date-input/root/date-input-root.js +791 -0
  117. package/dist/date-picker/index.d.ts +1 -0
  118. package/dist/date-picker/index.js +1 -0
  119. package/dist/date-picker/root/date-picker-root.d.ts +361 -0
  120. package/dist/date-picker/root/date-picker-root.js +837 -0
  121. package/dist/dialog/index.d.ts +1 -0
  122. package/dist/dialog/index.js +1 -0
  123. package/dist/dialog/root/dialog-root.d.ts +185 -0
  124. package/dist/dialog/root/dialog-root.js +319 -0
  125. package/dist/divider/index.d.ts +1 -0
  126. package/dist/divider/index.js +1 -0
  127. package/dist/divider/root/divider-root.d.ts +68 -0
  128. package/dist/divider/root/divider-root.js +116 -0
  129. package/dist/donut-chart/index.d.ts +1 -0
  130. package/dist/donut-chart/index.js +1 -0
  131. package/dist/donut-chart/root/donut-chart-root.d.ts +209 -0
  132. package/dist/donut-chart/root/donut-chart-root.js +395 -0
  133. package/dist/drawer/index.d.ts +1 -0
  134. package/dist/drawer/index.js +1 -0
  135. package/dist/drawer/root/drawer-root.d.ts +144 -0
  136. package/dist/drawer/root/drawer-root.js +222 -0
  137. package/dist/drilldown/index.d.ts +2 -0
  138. package/dist/drilldown/index.js +2 -0
  139. package/dist/drilldown/item/drilldown-item.d.ts +87 -0
  140. package/dist/drilldown/item/drilldown-item.js +152 -0
  141. package/dist/drilldown/root/drilldown-root.d.ts +115 -0
  142. package/dist/drilldown/root/drilldown-root.js +263 -0
  143. package/dist/element-events.generated.d.ts +1 -0
  144. package/dist/element-events.generated.js +125 -0
  145. package/dist/empty/index.d.ts +1 -0
  146. package/dist/empty/index.js +1 -0
  147. package/dist/empty/root/empty-root.d.ts +47 -0
  148. package/dist/empty/root/empty-root.js +68 -0
  149. package/dist/file-input/index.d.ts +1 -0
  150. package/dist/file-input/index.js +1 -0
  151. package/dist/file-input/root/file-input-root.d.ts +196 -0
  152. package/dist/file-input/root/file-input-root.js +488 -0
  153. package/dist/format-date/index.d.ts +1 -0
  154. package/dist/format-date/index.js +1 -0
  155. package/dist/format-date/root/format-date-root.d.ts +151 -0
  156. package/dist/format-date/root/format-date-root.js +266 -0
  157. package/dist/heatmap/index.d.ts +2 -0
  158. package/dist/heatmap/index.js +2 -0
  159. package/dist/heatmap/root/buckets.d.ts +62 -0
  160. package/dist/heatmap/root/buckets.js +85 -0
  161. package/dist/heatmap/root/heatmap-root.d.ts +330 -0
  162. package/dist/heatmap/root/heatmap-root.js +526 -0
  163. package/dist/icon/index.d.ts +1 -0
  164. package/dist/icon/index.js +1 -0
  165. package/dist/icon/root/icon-root.d.ts +53 -0
  166. package/dist/icon/root/icon-root.js +93 -0
  167. package/dist/icon-button/index.d.ts +1 -0
  168. package/dist/icon-button/index.js +1 -0
  169. package/dist/icon-button/root/icon-button-root.d.ts +40 -0
  170. package/dist/icon-button/root/icon-button-root.js +46 -0
  171. package/dist/image/index.d.ts +1 -0
  172. package/dist/image/index.js +1 -0
  173. package/dist/image/root/image-root.d.ts +213 -0
  174. package/dist/image/root/image-root.js +335 -0
  175. package/dist/index.d.ts +99 -0
  176. package/dist/index.js +99 -0
  177. package/dist/input/index.d.ts +1 -0
  178. package/dist/input/index.js +1 -0
  179. package/dist/input/root/input-root.d.ts +281 -0
  180. package/dist/input/root/input-root.js +472 -0
  181. package/dist/kbd/index.d.ts +1 -0
  182. package/dist/kbd/index.js +1 -0
  183. package/dist/kbd/root/kbd-root.d.ts +98 -0
  184. package/dist/kbd/root/kbd-root.js +230 -0
  185. package/dist/legend/index.d.ts +1 -0
  186. package/dist/legend/index.js +1 -0
  187. package/dist/legend/root/legend-root.d.ts +83 -0
  188. package/dist/legend/root/legend-root.js +125 -0
  189. package/dist/line-chart/index.d.ts +1 -0
  190. package/dist/line-chart/index.js +1 -0
  191. package/dist/line-chart/root/line-chart-root.d.ts +238 -0
  192. package/dist/line-chart/root/line-chart-root.js +365 -0
  193. package/dist/list/index.d.ts +2 -0
  194. package/dist/list/index.js +2 -0
  195. package/dist/list/item/list-item.d.ts +95 -0
  196. package/dist/list/item/list-item.js +148 -0
  197. package/dist/list/root/list-root.d.ts +72 -0
  198. package/dist/list/root/list-root.js +61 -0
  199. package/dist/listbox/index.d.ts +1 -0
  200. package/dist/listbox/index.js +1 -0
  201. package/dist/listbox/root/listbox-root.d.ts +357 -0
  202. package/dist/listbox/root/listbox-root.js +890 -0
  203. package/dist/loader/index.d.ts +1 -0
  204. package/dist/loader/index.js +1 -0
  205. package/dist/loader/root/loader-root.d.ts +52 -0
  206. package/dist/loader/root/loader-root.js +74 -0
  207. package/dist/megamenu/index.d.ts +1 -0
  208. package/dist/megamenu/index.js +1 -0
  209. package/dist/megamenu/root/megamenu-root.d.ts +254 -0
  210. package/dist/megamenu/root/megamenu-root.js +526 -0
  211. package/dist/menu/index.d.ts +2 -0
  212. package/dist/menu/index.js +2 -0
  213. package/dist/menu/item/menu-item.d.ts +231 -0
  214. package/dist/menu/item/menu-item.js +405 -0
  215. package/dist/menu/root/menu-root.d.ts +158 -0
  216. package/dist/menu/root/menu-root.js +422 -0
  217. package/dist/meter/index.d.ts +1 -0
  218. package/dist/meter/index.js +1 -0
  219. package/dist/meter/root/meter-root.d.ts +234 -0
  220. package/dist/meter/root/meter-root.js +316 -0
  221. package/dist/navigation/index.d.ts +1 -0
  222. package/dist/navigation/index.js +1 -0
  223. package/dist/navigation/root/navigation-root.d.ts +55 -0
  224. package/dist/navigation/root/navigation-root.js +130 -0
  225. package/dist/notifications/index.d.ts +2 -0
  226. package/dist/notifications/index.js +2 -0
  227. package/dist/notifications/notification/notification.d.ts +181 -0
  228. package/dist/notifications/notification/notification.js +305 -0
  229. package/dist/notifications/root/notifications-root.d.ts +168 -0
  230. package/dist/notifications/root/notifications-root.js +291 -0
  231. package/dist/number-input/index.d.ts +1 -0
  232. package/dist/number-input/index.js +1 -0
  233. package/dist/number-input/root/number-input-root.d.ts +282 -0
  234. package/dist/number-input/root/number-input-root.js +592 -0
  235. package/dist/option/group/option-group.d.ts +38 -0
  236. package/dist/option/group/option-group.js +58 -0
  237. package/dist/option/index.d.ts +2 -0
  238. package/dist/option/index.js +2 -0
  239. package/dist/option/root/option-root.d.ts +194 -0
  240. package/dist/option/root/option-root.js +247 -0
  241. package/dist/outline/index.d.ts +1 -0
  242. package/dist/outline/index.js +1 -0
  243. package/dist/outline/root/outline-root.d.ts +237 -0
  244. package/dist/outline/root/outline-root.js +519 -0
  245. package/dist/pagination/index.d.ts +3 -0
  246. package/dist/pagination/index.js +3 -0
  247. package/dist/pagination/root/pagination-root.d.ts +390 -0
  248. package/dist/pagination/root/pagination-root.js +695 -0
  249. package/dist/pagination/size/pagination-size.d.ts +127 -0
  250. package/dist/pagination/size/pagination-size.js +232 -0
  251. package/dist/pagination/summary/pagination-summary.d.ts +90 -0
  252. package/dist/pagination/summary/pagination-summary.js +145 -0
  253. package/dist/pin-input/index.d.ts +1 -0
  254. package/dist/pin-input/index.js +1 -0
  255. package/dist/pin-input/root/pin-input-root.d.ts +292 -0
  256. package/dist/pin-input/root/pin-input-root.js +553 -0
  257. package/dist/popover/index.d.ts +1 -0
  258. package/dist/popover/index.js +1 -0
  259. package/dist/popover/root/popover-root.d.ts +108 -0
  260. package/dist/popover/root/popover-root.js +231 -0
  261. package/dist/progress/index.d.ts +1 -0
  262. package/dist/progress/index.js +1 -0
  263. package/dist/progress/root/progress-root.d.ts +125 -0
  264. package/dist/progress/root/progress-root.js +212 -0
  265. package/dist/qr-code/index.d.ts +1 -0
  266. package/dist/qr-code/index.js +1 -0
  267. package/dist/qr-code/root/qr-code-root.d.ts +93 -0
  268. package/dist/qr-code/root/qr-code-root.js +233 -0
  269. package/dist/quote/index.d.ts +1 -0
  270. package/dist/quote/index.js +1 -0
  271. package/dist/quote/root/quote-root.d.ts +36 -0
  272. package/dist/quote/root/quote-root.js +50 -0
  273. package/dist/radio/group/radio-group.d.ts +84 -0
  274. package/dist/radio/group/radio-group.js +170 -0
  275. package/dist/radio/index.d.ts +2 -0
  276. package/dist/radio/index.js +2 -0
  277. package/dist/radio/root/radio-root.d.ts +102 -0
  278. package/dist/radio/root/radio-root.js +151 -0
  279. package/dist/rating/index.d.ts +1 -0
  280. package/dist/rating/index.js +1 -0
  281. package/dist/rating/root/rating-root.d.ts +242 -0
  282. package/dist/rating/root/rating-root.js +484 -0
  283. package/dist/scroll-area/index.d.ts +1 -0
  284. package/dist/scroll-area/index.js +1 -0
  285. package/dist/scroll-area/root/scroll-area-root.d.ts +96 -0
  286. package/dist/scroll-area/root/scroll-area-root.js +215 -0
  287. package/dist/select/index.d.ts +1 -0
  288. package/dist/select/index.js +1 -0
  289. package/dist/select/root/select-root.d.ts +170 -0
  290. package/dist/select/root/select-root.js +419 -0
  291. package/dist/skeleton/index.d.ts +1 -0
  292. package/dist/skeleton/index.js +1 -0
  293. package/dist/skeleton/root/skeleton-root.d.ts +31 -0
  294. package/dist/skeleton/root/skeleton-root.js +42 -0
  295. package/dist/slider/index.d.ts +1 -0
  296. package/dist/slider/index.js +1 -0
  297. package/dist/slider/root/slider-root.d.ts +235 -0
  298. package/dist/slider/root/slider-root.js +488 -0
  299. package/dist/sparkline/index.d.ts +1 -0
  300. package/dist/sparkline/index.js +1 -0
  301. package/dist/sparkline/root/sparkline-root.d.ts +147 -0
  302. package/dist/sparkline/root/sparkline-root.js +278 -0
  303. package/dist/speed-dial/index.d.ts +2 -0
  304. package/dist/speed-dial/index.js +2 -0
  305. package/dist/speed-dial/item/speed-dial-item.d.ts +71 -0
  306. package/dist/speed-dial/item/speed-dial-item.js +113 -0
  307. package/dist/speed-dial/root/speed-dial-root.d.ts +122 -0
  308. package/dist/speed-dial/root/speed-dial-root.js +251 -0
  309. package/dist/splitter/index.d.ts +1 -0
  310. package/dist/splitter/index.js +1 -0
  311. package/dist/splitter/root/splitter-root.d.ts +491 -0
  312. package/dist/splitter/root/splitter-root.js +1030 -0
  313. package/dist/stat/group/stat-group.d.ts +30 -0
  314. package/dist/stat/group/stat-group.js +47 -0
  315. package/dist/stat/index.d.ts +2 -0
  316. package/dist/stat/index.js +2 -0
  317. package/dist/stat/root/stat-root.d.ts +62 -0
  318. package/dist/stat/root/stat-root.js +51 -0
  319. package/dist/steps/index.d.ts +2 -0
  320. package/dist/steps/index.js +2 -0
  321. package/dist/steps/root/steps-root.d.ts +110 -0
  322. package/dist/steps/root/steps-root.js +130 -0
  323. package/dist/steps/step/step.d.ts +139 -0
  324. package/dist/steps/step/step.js +215 -0
  325. package/dist/switch/index.d.ts +1 -0
  326. package/dist/switch/index.js +1 -0
  327. package/dist/switch/root/switch-root.d.ts +74 -0
  328. package/dist/switch/root/switch-root.js +153 -0
  329. package/dist/table/cell/table-cell.d.ts +34 -0
  330. package/dist/table/cell/table-cell.js +52 -0
  331. package/dist/table/column/table-column.d.ts +165 -0
  332. package/dist/table/column/table-column.js +222 -0
  333. package/dist/table/index.d.ts +4 -0
  334. package/dist/table/index.js +4 -0
  335. package/dist/table/root/table-root.d.ts +98 -0
  336. package/dist/table/root/table-root.js +161 -0
  337. package/dist/table/row/table-row.d.ts +27 -0
  338. package/dist/table/row/table-row.js +42 -0
  339. package/dist/tabs/index.d.ts +3 -0
  340. package/dist/tabs/index.js +3 -0
  341. package/dist/tabs/panel/tab-panel.d.ts +67 -0
  342. package/dist/tabs/panel/tab-panel.js +98 -0
  343. package/dist/tabs/root/tabs-root.d.ts +123 -0
  344. package/dist/tabs/root/tabs-root.js +217 -0
  345. package/dist/tabs/tab/tab.d.ts +64 -0
  346. package/dist/tabs/tab/tab.js +116 -0
  347. package/dist/tag/index.d.ts +1 -0
  348. package/dist/tag/index.js +1 -0
  349. package/dist/tag/root/tag-root.d.ts +41 -0
  350. package/dist/tag/root/tag-root.js +67 -0
  351. package/dist/textarea/index.d.ts +1 -0
  352. package/dist/textarea/index.js +1 -0
  353. package/dist/textarea/root/textarea-root.d.ts +215 -0
  354. package/dist/textarea/root/textarea-root.js +380 -0
  355. package/dist/time-input/index.d.ts +1 -0
  356. package/dist/time-input/index.js +1 -0
  357. package/dist/time-input/root/time-input-root.d.ts +322 -0
  358. package/dist/time-input/root/time-input-root.js +661 -0
  359. package/dist/time-picker/index.d.ts +1 -0
  360. package/dist/time-picker/index.js +1 -0
  361. package/dist/time-picker/root/time-picker-root.d.ts +380 -0
  362. package/dist/time-picker/root/time-picker-root.js +669 -0
  363. package/dist/timeline/index.d.ts +2 -0
  364. package/dist/timeline/index.js +2 -0
  365. package/dist/timeline/item/timeline-item.d.ts +81 -0
  366. package/dist/timeline/item/timeline-item.js +128 -0
  367. package/dist/timeline/root/timeline-root.d.ts +52 -0
  368. package/dist/timeline/root/timeline-root.js +72 -0
  369. package/dist/toast/index.d.ts +2 -0
  370. package/dist/toast/index.js +2 -0
  371. package/dist/toast/item/toast-item.d.ts +183 -0
  372. package/dist/toast/item/toast-item.js +345 -0
  373. package/dist/toast/root/toast-root.d.ts +72 -0
  374. package/dist/toast/root/toast-root.js +87 -0
  375. package/dist/toggle/group/toggle-group.d.ts +140 -0
  376. package/dist/toggle/group/toggle-group.js +278 -0
  377. package/dist/toggle/index.d.ts +2 -0
  378. package/dist/toggle/index.js +2 -0
  379. package/dist/toggle/root/toggle-root.d.ts +99 -0
  380. package/dist/toggle/root/toggle-root.js +146 -0
  381. package/dist/toolbar/index.d.ts +1 -0
  382. package/dist/toolbar/index.js +1 -0
  383. package/dist/toolbar/root/toolbar-root.d.ts +105 -0
  384. package/dist/toolbar/root/toolbar-root.js +260 -0
  385. package/dist/tooltip/index.d.ts +1 -0
  386. package/dist/tooltip/index.js +1 -0
  387. package/dist/tooltip/root/tooltip-root.d.ts +388 -0
  388. package/dist/tooltip/root/tooltip-root.js +707 -0
  389. package/dist/tour/index.d.ts +2 -0
  390. package/dist/tour/index.js +2 -0
  391. package/dist/tour/root/tour-root.d.ts +161 -0
  392. package/dist/tour/root/tour-root.js +351 -0
  393. package/dist/tour/stop/tour-stop.d.ts +131 -0
  394. package/dist/tour/stop/tour-stop.js +249 -0
  395. package/dist/tree/index.d.ts +2 -0
  396. package/dist/tree/index.js +2 -0
  397. package/dist/tree/item/tree-item.d.ts +208 -0
  398. package/dist/tree/item/tree-item.js +381 -0
  399. package/dist/tree/root/tree-root.d.ts +88 -0
  400. package/dist/tree/root/tree-root.js +287 -0
  401. package/dist/trend/index.d.ts +1 -0
  402. package/dist/trend/index.js +1 -0
  403. package/dist/trend/root/trend-root.d.ts +67 -0
  404. package/dist/trend/root/trend-root.js +106 -0
  405. package/dist/video/index.d.ts +1 -0
  406. package/dist/video/index.js +1 -0
  407. package/dist/video/root/video-root.d.ts +711 -0
  408. package/dist/video/root/video-root.js +1821 -0
  409. package/dist/video-playlist/index.d.ts +3 -0
  410. package/dist/video-playlist/index.js +3 -0
  411. package/dist/video-playlist/item/video-playlist-item.d.ts +101 -0
  412. package/dist/video-playlist/item/video-playlist-item.js +162 -0
  413. package/dist/video-playlist/menu/video-playlist-menu.d.ts +121 -0
  414. package/dist/video-playlist/menu/video-playlist-menu.js +237 -0
  415. package/dist/video-playlist/root/video-playlist-root.d.ts +108 -0
  416. package/dist/video-playlist/root/video-playlist-root.js +218 -0
  417. package/dist/virtual-list/index.d.ts +1 -0
  418. package/dist/virtual-list/index.js +1 -0
  419. package/dist/virtual-list/root/virtual-list-root.d.ts +121 -0
  420. package/dist/virtual-list/root/virtual-list-root.js +221 -0
  421. package/jsx.d.ts +49767 -0
  422. package/package.json +77 -0
  423. package/svelte.d.ts +129 -0
  424. package/vue.d.ts +9242 -0
@@ -0,0 +1,207 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { AriaForwardController, customElement, HelixFormElement, MixinControllerChecked, MixinField, } from '@fusion.dev/helix-core';
8
+ import { html, nothing } from 'lit';
9
+ import { property } from 'lit/decorators.js';
10
+ /**
11
+ * @summary A box that is ticked, or not, or neither.
12
+ *
13
+ * @description
14
+ * Renders a real `<input type="checkbox">`, so the space key, the focus ring,
15
+ * and the indeterminate glyph come from the platform. `delegatesFocus` puts
16
+ * focus on it, and it serializes into the server's markup, so the control is
17
+ * reachable before any script loads.
18
+ *
19
+ * **The input inside a shadow root submits nothing**, because the form is on
20
+ * the other side of the boundary. The host is form-associated instead and
21
+ * reports its own value through `ElementInternals`, which is also what carries
22
+ * validity and what answers a form reset.
23
+ *
24
+ * A checked box submits its `value`, and an unchecked one submits nothing at
25
+ * all. That is what a native checkbox does, and a form built around one reads
26
+ * the absence rather than a `false`.
27
+ *
28
+ * `indeterminate` is presentation and nothing else. It is neither checked nor
29
+ * unchecked to a reader, it never submits, and the first click resolves it: a
30
+ * third state that survives interaction is a control nobody can finish.
31
+ *
32
+ * @since 0.1.0
33
+ * @status experimental
34
+ * @category forms
35
+ * @aliases Tickbox, Toggle
36
+ * @documentation https://helix.fusion.dev/components/checkbox
37
+ *
38
+ * @slot - The label.
39
+ *
40
+ * @event {Event} change - Relayed from the input once the state has changed.
41
+ * @event {HelixBeforeToggleEvent} helix-before-toggle - Fired before the state changes, and cancelable.
42
+ * @event {Event} input - Announced once the state has moved.
43
+ *
44
+ * @csspart box - The frame the input is painted as, and the mark sits over.
45
+ * @csspart control - The input.
46
+ * @csspart feedback - What is wrong with it.
47
+ * @csspart field - The row the box and its label share, and the surface the card appearance draws.
48
+ * @csspart hint - Help under the control, while nothing is wrong.
49
+ * @csspart label - The label beside it.
50
+ * @csspart mark - The tick, or the dash when the box is indeterminate.
51
+ */
52
+ let HelixHeadlessCheckbox = class HelixHeadlessCheckbox extends MixinControllerChecked(MixinField(HelixFormElement)) {
53
+ constructor() {
54
+ super(...arguments);
55
+ /* A consumer's `aria-describedby` names ids in their own tree and the control
56
+ is in this shadow root, so the reference has to be carried down as an
57
+ element rather than copied as an id. See `AriaForwardController`: measured
58
+ in Chrome's own tree, the host held the description and the control the
59
+ reader is actually on was exposed without it. */
60
+ this.aria = new AriaForwardController(this, {
61
+ target: () => this.renderRoot?.querySelector('[part="control"]') ?? null,
62
+ });
63
+ /**
64
+ * Value submitted when the box is checked.
65
+ */
66
+ this.value = 'on';
67
+ /**
68
+ * Whether the box shows as neither checked nor unchecked.
69
+ *
70
+ * Presentation only. It never submits, and the first change resolves it.
71
+ */
72
+ this.indeterminate = false;
73
+ this.handleChange = (event) => {
74
+ const input = event.target;
75
+ // The input has already flipped itself. Where the change is refused, or the
76
+ // element is controlled, it is put back to whatever the element resolves
77
+ // to, so the box never shows a state the element does not hold.
78
+ const next = input.checked;
79
+ /* The dash goes only where the change is taken.
80
+ *
81
+ * It was cleared first and unconditionally, so a consumer calling
82
+ * `preventDefault()` on the change kept the checked state and lost the
83
+ * third one: the box came back neither ticked nor dashed, which is a state
84
+ * nobody asked for and the element did not hold. Refusing a change should
85
+ * leave everything as it was, which is the argument the line below already
86
+ * makes for `checked`. */
87
+ if (this.requestChecked(next)) {
88
+ this.indeterminate = false;
89
+ }
90
+ input.checked = this.checked;
91
+ this.relayNativeEvent(event);
92
+ };
93
+ /**
94
+ * Whether there is a label to leave room for, written to the host.
95
+ *
96
+ * The row is a flex line with a gap in it, so a label span rendered empty is
97
+ * still a box and still takes that gap: an unlabelled box came out with eight
98
+ * pixels of nothing after it. The input answers this by not rendering the
99
+ * element, which cannot work here, because a checkbox is named by its own
100
+ * content and the property is only that slot's fallback. Gating on the
101
+ * property would unlabel every `<helix-checkbox>Text</helix-checkbox>` ever
102
+ * written.
103
+ *
104
+ * So the slot is asked instead, the same way `Tooltip` asks its own: with
105
+ * `flatten`, because here the fallback counts, being where the property
106
+ * renders. Client only, so a server-rendered unlabelled checkbox carries the
107
+ * gap for one frame. That is a control with no accessible name, which has a
108
+ * worse problem than its spacing.
109
+ */
110
+ this.handleLabelChange = () => {
111
+ this.syncLabelPresence();
112
+ };
113
+ }
114
+ /** Focus is delegated to the input, so the host is never the focus target. */
115
+ static { this.shadowRootOptions = {
116
+ ...HelixFormElement.shadowRootOptions,
117
+ delegatesFocus: true,
118
+ }; }
119
+ /** Reports the value and the validity the host stands behind. */
120
+ sync() {
121
+ this.internals.setFormValue(this.checked ? this.value : null);
122
+ this.reportRequired(!this.checked, 'Tick this box to continue.', 'control');
123
+ }
124
+ /** Returns the box to the state its markup declared. */
125
+ formResetCallback() {
126
+ this.indeterminate = false;
127
+ // `resetChecked` drops both halves now, the consumer's and the element's,
128
+ // so there is nothing to clear before it.
129
+ this.resetChecked();
130
+ }
131
+ willUpdate(changed) {
132
+ super.willUpdate(changed);
133
+ this.internals.ariaRequired = this.required ? 'true' : null;
134
+ }
135
+ updated(changed) {
136
+ super.updated(changed);
137
+ this.sync();
138
+ this.syncLabelPresence();
139
+ }
140
+ /**
141
+ * Asks the slot, and records the answer as a state.
142
+ *
143
+ * Called on `slotchange` and after every update, and the second is not
144
+ * belt-and-braces: **`slotchange` does not fire when nothing is assigned.**
145
+ * So a checkbox labeled only by its property, which is most of them, never
146
+ * heard about its own label and rendered without one. Caught by the spec that
147
+ * asks a labeled row to be wider than a bare one.
148
+ *
149
+ * **`:state(has-label)` and not `data-has-label`, since 27 Aug 2026.** This
150
+ * one could never have been in server output whatever it was called, the
151
+ * answer coming from `assignedNodes` and a server having no tree to ask, so
152
+ * it was an attribute that appeared on every labeled checkbox the instant it
153
+ * upgraded and on none that any server sent. See `HelixElement.toggleState`.
154
+ */
155
+ syncLabelPresence() {
156
+ const slot = this.renderRoot.querySelector('[part="label"] slot');
157
+ const filled = (slot?.assignedNodes({ flatten: true }) ?? []).some((node) => node.textContent?.trim() !== '' || node.nodeType === Node.ELEMENT_NODE);
158
+ this.toggleState('has-label', filled);
159
+ /* And `hidden` on the region itself, because the state is on the host and
160
+ this tier has no sheet to turn one into the other: a checkbox with no
161
+ label kept an empty label box beside it. The styled rule stays, since it
162
+ hides through a descendant selector this cannot replace. */
163
+ this.renderRoot.querySelector('[part="label"]')?.toggleAttribute('hidden', !filled);
164
+ }
165
+ render() {
166
+ /* A real `<label>` around both, which is the whole of what makes the text a
167
+ target. It was a `<span>` beside the input, so pressing the words did
168
+ nothing: the styled tier's own description claimed the pair behaved like
169
+ a native label wrapping a checkbox, and nothing was doing that work.
170
+
171
+ Labeling is behavior, which is what earns an element here rather than a
172
+ bare slot: the wrapper is not decoration and there is no other way to get
173
+ it. The browser handles the forwarding, so there is no click handler to
174
+ write and none to get wrong.
175
+
176
+ The one line of description goes under that row, which is where a field
177
+ puts it too. */
178
+ return html `<label part="field">
179
+ <span part="box">
180
+ <input
181
+ part="control"
182
+ type="checkbox"
183
+ .checked=${this.checked}
184
+ .indeterminate=${this.indeterminate}
185
+ ?disabled=${this.isDisabled}
186
+ ?required=${this.required}
187
+ aria-describedby=${this.describedBy ?? nothing}
188
+ @change=${this.handleChange}
189
+ @input=${this.stopInner}
190
+ />
191
+ <span part="mark" aria-hidden="true"></span>
192
+ </span>
193
+ <span part="label"><slot @slotchange=${this.handleLabelChange}>${this.label}</slot></span>
194
+ </label>
195
+ ${this.renderHint()}${this.renderFeedback()}`;
196
+ }
197
+ };
198
+ __decorate([
199
+ property()
200
+ ], HelixHeadlessCheckbox.prototype, "value", void 0);
201
+ __decorate([
202
+ property({ reflect: true, type: Boolean })
203
+ ], HelixHeadlessCheckbox.prototype, "indeterminate", void 0);
204
+ HelixHeadlessCheckbox = __decorate([
205
+ customElement('helix-headless-checkbox')
206
+ ], HelixHeadlessCheckbox);
207
+ export { HelixHeadlessCheckbox };
@@ -0,0 +1 @@
1
+ export * from './root/checkbox-group-root.js';
@@ -0,0 +1 @@
1
+ export * from './root/checkbox-group-root.js';
@@ -0,0 +1,155 @@
1
+ import { DisabledCascadeController, HelixFormElement } from '@fusion.dev/helix-core';
2
+ import { type PropertyValues, type TemplateResult } from 'lit';
3
+ import { HelixHeadlessCheckbox } from '../../checkbox/root/checkbox-root.js';
4
+ declare const HelixHeadlessCheckboxGroup_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
5
+ /**
6
+ * @summary Groups related checkboxes, and reports them as one set.
7
+ *
8
+ * @description
9
+ * The host is the group, so `role="group"` sits on it through internals and
10
+ * `label` names it. A run of checkboxes with no name is announced as separate
11
+ * controls, which is what the grouping exists to say it is not.
12
+ *
13
+ * **Each checkbox still submits itself.** They are form-associated already and
14
+ * a native group is several inputs sharing a name, so this adds no form value
15
+ * of its own: it would submit the same answers twice. What it adds is the
16
+ * grouping, a shared `name` so it is written once, and one place to read and
17
+ * write the whole set.
18
+ *
19
+ * `value` is the checked values, comma separated, in the order the boxes are
20
+ * written. Setting it ticks exactly those and unticks the rest.
21
+ *
22
+ * **Its message is always given, never derived.** Every form-related member of
23
+ * `ElementInternals` throws on an element that is not form-associated, and this
24
+ * one is not, on purpose: the boxes submit themselves. So `feedback` is what
25
+ * shows here, and the browser has nothing to say about a set it does not know
26
+ * is a set.
27
+ *
28
+ * @since 0.1.0
29
+ * @status stable
30
+ * @category forms
31
+ * @aliases Checkbox list, Multi-select
32
+ * @documentation https://helix.fusion.dev/components/checkbox-group
33
+ *
34
+ * @slot - The checkboxes.
35
+ * @slot hint - Richer than a string.
36
+ * @slot label - Richer than a string, where the label is more than one.
37
+ *
38
+ * @event {Event} change - Announced once the value has moved.
39
+ * @event {HelixBeforeChangeEvent} helix-before-change - Fired before any box changes, with the whole set. Cancelable: refusing it takes the decision and nothing moves.
40
+ * @event {Event} input - Announced once the value has moved.
41
+ *
42
+ * @csspart feedback - What is wrong with it.
43
+ * @csspart hint - Help under the set.
44
+ * @csspart items - The list itself, which is what `orientation` lays out.
45
+ * @csspart label - The group's name, over the set.
46
+ */
47
+ export declare class HelixHeadlessCheckboxGroup extends HelixHeadlessCheckboxGroup_base {
48
+ /**
49
+ * The checked values, comma separated.
50
+ */
51
+ value: string;
52
+ protected readonly cascade: DisabledCascadeController;
53
+ /** The boxes, in light-DOM order. Client only: the server has no tree. */
54
+ get boxes(): HelixHeadlessCheckbox[];
55
+ /**
56
+ * Pushes the group's name and value onto the boxes.
57
+ *
58
+ * As properties rather than attributes. A `name` written onto a box is a
59
+ * change to markup the consumer rendered, which a React consumer's hydration
60
+ * reports and does not patch up. A box that names itself keeps its own.
61
+ */
62
+ private sync;
63
+ /**
64
+ * Reads the boxes' own state into `value`, once, before anything is pushed.
65
+ *
66
+ * `sync` used to refuse to write anything while `value` was empty, and the
67
+ * guard was there for this: a group written with no `value` and boxes that
68
+ * declare their own `checked` would have had them all cleared on the first
69
+ * update. What it also did was make `group.value = ''` do nothing at all, so
70
+ * the obvious way to clear a group silently did not, and the last box could
71
+ * not be unticked through the group either.
72
+ *
73
+ * Seeding is the honest version of the same intent. The markup decides the
74
+ * starting set, exactly as before, and from then on `value` is what the boxes
75
+ * follow, including when it is empty. The group's `value` is a derived read
76
+ * of the boxes rather than state it owns, so reading it out of them at the
77
+ * start is what it already means.
78
+ */
79
+ private seed;
80
+ /**
81
+ * Reads a box's requested change into `value`, and says so once.
82
+ *
83
+ * The box is found from the event's target, which does two things. It tells
84
+ * the group which box asked, where the detail carries only the shared name.
85
+ * And it ignores the group's own dispatch, which lands on this same listener
86
+ * because the group is what it is dispatched from: without the guard the
87
+ * group answers itself until the stack gives out.
88
+ *
89
+ * The requested state comes from the event rather than from the box. Driving
90
+ * the boxes from `value` makes them controlled, so a controlled box applies
91
+ * nothing on its own and reports what it was asked for. Reading `checked`
92
+ * here would read the state it still holds and nothing would ever change.
93
+ */
94
+ private readonly handleToggle;
95
+ /**
96
+ * Stops a box's own announcement, for the reason the request above is stopped.
97
+ *
98
+ * **The split gave the requests two names and left the notifications sharing
99
+ * one.** A box announces `input` and `change` from its own host now, which is
100
+ * what makes `onChange` work on a checkbox, and both bubble up through this
101
+ * group: measured, one click produced `change` from the group and `input` and
102
+ * `change` from the box, all three at a consumer listening here, two of them
103
+ * describing one box rather than the set. That is exactly the collision the
104
+ * comment on `handleToggle` describes, arriving by the other route.
105
+ *
106
+ * `stopImmediatePropagation` and not `stopPropagation`, and for the same
107
+ * reason it gives: the box's event and this group's own carry one name from
108
+ * what a consumer sees as one element, so stopping propagation alone still
109
+ * leaves every other listener on this host receiving both.
110
+ *
111
+ * A listener on the box itself is unaffected, which is where per-box handling
112
+ * belongs. Each box is form-associated and submits itself; what this stops is
113
+ * one box answering a question asked of the set.
114
+ */
115
+ private readonly handleMemberNative;
116
+ connectedCallback(): void;
117
+ disconnectedCallback(): void;
118
+ protected willUpdate(changed: PropertyValues): void;
119
+ protected firstUpdated(changed: PropertyValues): void;
120
+ /**
121
+ * Refuses an empty set where one was required, which nothing did.
122
+ *
123
+ * `required` arrives with `MixinField`, reflects, and paints the asterisk
124
+ * through the composed field sheet, and enforced nothing at all: no validity,
125
+ * no message, and nothing cascading to the boxes. A group marked required
126
+ * submitted empty.
127
+ *
128
+ * **The group is form-associated, and submits nothing.** It was not, on the
129
+ * reasoning that its boxes are the controls and each submits itself, which is
130
+ * still true: nothing here calls `setFormValue`, so the set that reaches the
131
+ * server is exactly the boxes it always was. What form association buys is the
132
+ * other half of participation, validity, and there is no other mechanism for
133
+ * it: `setValidity` throws `NotSupportedError` on an element the platform does
134
+ * not know is a control.
135
+ *
136
+ * So the fix that was written for "a group marked required submitted empty"
137
+ * threw on every update in a real browser, and happy-dom's shim does not
138
+ * throw, so the specs passed and the behavior never worked. Eleven of them
139
+ * failed the moment they were run in Chromium. It is also what makes the rest
140
+ * work: the form now refuses to submit, which fires `invalid`, which is what
141
+ * marks the field touched and puts the message on screen.
142
+ *
143
+ * Anchored on the list, because the browser needs somewhere to point the
144
+ * bubble.
145
+ */
146
+ private validate;
147
+ protected updated(changed: PropertyValues): void;
148
+ protected render(): TemplateResult;
149
+ }
150
+ declare global {
151
+ interface HTMLElementTagNameMap {
152
+ 'helix-headless-checkbox-group': HelixHeadlessCheckboxGroup;
153
+ }
154
+ }
155
+ export {};
@@ -0,0 +1,293 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { customElement, DisabledCascadeController, HelixBeforeChangeEvent, HelixFormElement, hostAria, MixinField, } from '@fusion.dev/helix-core';
8
+ import { html } from 'lit';
9
+ import { property } from 'lit/decorators.js';
10
+ import { HelixHeadlessCheckbox } from '../../checkbox/root/checkbox-root.js';
11
+ /**
12
+ * @summary Groups related checkboxes, and reports them as one set.
13
+ *
14
+ * @description
15
+ * The host is the group, so `role="group"` sits on it through internals and
16
+ * `label` names it. A run of checkboxes with no name is announced as separate
17
+ * controls, which is what the grouping exists to say it is not.
18
+ *
19
+ * **Each checkbox still submits itself.** They are form-associated already and
20
+ * a native group is several inputs sharing a name, so this adds no form value
21
+ * of its own: it would submit the same answers twice. What it adds is the
22
+ * grouping, a shared `name` so it is written once, and one place to read and
23
+ * write the whole set.
24
+ *
25
+ * `value` is the checked values, comma separated, in the order the boxes are
26
+ * written. Setting it ticks exactly those and unticks the rest.
27
+ *
28
+ * **Its message is always given, never derived.** Every form-related member of
29
+ * `ElementInternals` throws on an element that is not form-associated, and this
30
+ * one is not, on purpose: the boxes submit themselves. So `feedback` is what
31
+ * shows here, and the browser has nothing to say about a set it does not know
32
+ * is a set.
33
+ *
34
+ * @since 0.1.0
35
+ * @status stable
36
+ * @category forms
37
+ * @aliases Checkbox list, Multi-select
38
+ * @documentation https://helix.fusion.dev/components/checkbox-group
39
+ *
40
+ * @slot - The checkboxes.
41
+ * @slot hint - Richer than a string.
42
+ * @slot label - Richer than a string, where the label is more than one.
43
+ *
44
+ * @event {Event} change - Announced once the value has moved.
45
+ * @event {HelixBeforeChangeEvent} helix-before-change - Fired before any box changes, with the whole set. Cancelable: refusing it takes the decision and nothing moves.
46
+ * @event {Event} input - Announced once the value has moved.
47
+ *
48
+ * @csspart feedback - What is wrong with it.
49
+ * @csspart hint - Help under the set.
50
+ * @csspart items - The list itself, which is what `orientation` lays out.
51
+ * @csspart label - The group's name, over the set.
52
+ */
53
+ let HelixHeadlessCheckboxGroup = class HelixHeadlessCheckboxGroup extends MixinField(HelixFormElement) {
54
+ constructor() {
55
+ /* `name` is inherited. It arrives with `HelixFormElement` reflected and with
56
+ the converter that makes an empty one absent rather than `name=""`, which
57
+ the copy declared here had neither of. What it means differs slightly and
58
+ the property does not: the group submits nothing under it, and hands it to
59
+ every box that has none. */
60
+ super(...arguments);
61
+ /**
62
+ * The checked values, comma separated.
63
+ */
64
+ this.value = '';
65
+ /* Stated once, and the group never thinks about it again. See the
66
+ controller: the cascade was four hand calls from four different
67
+ methods, so which paths reached it differed by component and a fifth
68
+ group would have got none at all. */
69
+ this.cascade = new DisabledCascadeController(this, {
70
+ items: () => this.boxes,
71
+ });
72
+ /**
73
+ * Reads a box's requested change into `value`, and says so once.
74
+ *
75
+ * The box is found from the event's target, which does two things. It tells
76
+ * the group which box asked, where the detail carries only the shared name.
77
+ * And it ignores the group's own dispatch, which lands on this same listener
78
+ * because the group is what it is dispatched from: without the guard the
79
+ * group answers itself until the stack gives out.
80
+ *
81
+ * The requested state comes from the event rather than from the box. Driving
82
+ * the boxes from `value` makes them controlled, so a controlled box applies
83
+ * nothing on its own and reports what it was asked for. Reading `checked`
84
+ * here would read the state it still holds and nothing would ever change.
85
+ */
86
+ this.handleToggle = (event) => {
87
+ const target = event.target;
88
+ const changed = this.boxes.find((box) => box === target);
89
+ if (!changed) {
90
+ return;
91
+ }
92
+ /* Still stopped, though the names no longer collide. A box's `helix-toggle`
93
+ bubbles, and the group is the single voice for the set: a consumer
94
+ listening here wants the whole answer, not one box's half of it. Before
95
+ the split this had to be `stopImmediatePropagation` rather than
96
+ `stopPropagation`, because the box's event and the group's own carried
97
+ the same name from the same host and the other listeners on it would have
98
+ received both. */
99
+ event.stopImmediatePropagation();
100
+ const wanted = event.detail.checked;
101
+ /* Announced before it is written, which is the way round it was not: the
102
+ group set its value and then dispatched, so `preventDefault()` refused a
103
+ set that had already changed.
104
+
105
+ Hand-rolled rather than through `MixinControllerValue`, and that is the
106
+ decision rather than an omission. The group is deliberately not
107
+ form-associated: its boxes are the form controls and each submits itself,
108
+ so the mixin, which is constrained to `HelixFormElement`, does not apply
109
+ to it. Its `value` is a derived read of the boxes rather than state it
110
+ owns, which is also why it is not controllable and why that is written
111
+ down rather than fixed.
112
+
113
+ The boxes have already moved either way. Each answered the reader before
114
+ this ran, so refusing here stops the group's value from following, and
115
+ the honest limit of that is recorded with the decision. */
116
+ const next = this.boxes
117
+ .filter((box) => (box === changed ? wanted : box.checked))
118
+ .map((box) => box.value)
119
+ .join(',');
120
+ if (!this.dispatchEvent(new HelixBeforeChangeEvent({ value: next }))) {
121
+ return;
122
+ }
123
+ this.value = next;
124
+ /* Under the platform's own name, after the value has moved, so a consumer
125
+ binding `onChange` reads the group's new value off the target.
126
+
127
+ `input` beside it, because this is a discrete control and that is the
128
+ pair a native `<select>` sends and the pair every other discrete control
129
+ here sends through `MixinControllerValue`. The group had only `change`,
130
+ so a consumer binding `onInput` on the set heard the boxes and never the
131
+ group. */
132
+ this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
133
+ this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
134
+ };
135
+ /**
136
+ * Stops a box's own announcement, for the reason the request above is stopped.
137
+ *
138
+ * **The split gave the requests two names and left the notifications sharing
139
+ * one.** A box announces `input` and `change` from its own host now, which is
140
+ * what makes `onChange` work on a checkbox, and both bubble up through this
141
+ * group: measured, one click produced `change` from the group and `input` and
142
+ * `change` from the box, all three at a consumer listening here, two of them
143
+ * describing one box rather than the set. That is exactly the collision the
144
+ * comment on `handleToggle` describes, arriving by the other route.
145
+ *
146
+ * `stopImmediatePropagation` and not `stopPropagation`, and for the same
147
+ * reason it gives: the box's event and this group's own carry one name from
148
+ * what a consumer sees as one element, so stopping propagation alone still
149
+ * leaves every other listener on this host receiving both.
150
+ *
151
+ * A listener on the box itself is unaffected, which is where per-box handling
152
+ * belongs. Each box is form-associated and submits itself; what this stops is
153
+ * one box answering a question asked of the set.
154
+ */
155
+ this.handleMemberNative = (event) => {
156
+ if (event.target !== this) {
157
+ event.stopImmediatePropagation();
158
+ }
159
+ };
160
+ }
161
+ /** The boxes, in light-DOM order. Client only: the server has no tree. */
162
+ get boxes() {
163
+ return [...this.children].filter((child) => child instanceof HelixHeadlessCheckbox);
164
+ }
165
+ /**
166
+ * Pushes the group's name and value onto the boxes.
167
+ *
168
+ * As properties rather than attributes. A `name` written onto a box is a
169
+ * change to markup the consumer rendered, which a React consumer's hydration
170
+ * reports and does not patch up. A box that names itself keeps its own.
171
+ */
172
+ sync() {
173
+ const wanted = new Set(this.value
174
+ .split(',')
175
+ .map((entry) => entry.trim())
176
+ .filter(Boolean));
177
+ for (const box of this.boxes) {
178
+ if (this.name !== '' && box.name === '') {
179
+ box.name = this.name;
180
+ }
181
+ box.checked = wanted.has(box.value);
182
+ }
183
+ }
184
+ /**
185
+ * Reads the boxes' own state into `value`, once, before anything is pushed.
186
+ *
187
+ * `sync` used to refuse to write anything while `value` was empty, and the
188
+ * guard was there for this: a group written with no `value` and boxes that
189
+ * declare their own `checked` would have had them all cleared on the first
190
+ * update. What it also did was make `group.value = ''` do nothing at all, so
191
+ * the obvious way to clear a group silently did not, and the last box could
192
+ * not be unticked through the group either.
193
+ *
194
+ * Seeding is the honest version of the same intent. The markup decides the
195
+ * starting set, exactly as before, and from then on `value` is what the boxes
196
+ * follow, including when it is empty. The group's `value` is a derived read
197
+ * of the boxes rather than state it owns, so reading it out of them at the
198
+ * start is what it already means.
199
+ */
200
+ seed() {
201
+ const checked = this.boxes.filter((box) => box.checked).map((box) => box.value);
202
+ if (checked.length > 0) {
203
+ this.value = checked.join(',');
204
+ }
205
+ }
206
+ connectedCallback() {
207
+ super.connectedCallback();
208
+ this.addEventListener('helix-before-toggle', this.handleToggle);
209
+ this.addEventListener('change', this.handleMemberNative);
210
+ this.addEventListener('input', this.handleMemberNative);
211
+ }
212
+ disconnectedCallback() {
213
+ super.disconnectedCallback();
214
+ this.removeEventListener('helix-before-toggle', this.handleToggle);
215
+ this.removeEventListener('change', this.handleMemberNative);
216
+ this.removeEventListener('input', this.handleMemberNative);
217
+ }
218
+ willUpdate(changed) {
219
+ super.willUpdate(changed);
220
+ /* The string half, which is what a server can write. `linkHost` adds the
221
+ element references on the client, and those win where a consumer slotted
222
+ a label richer than a string. */
223
+ hostAria(this.internals, { label: this.label, role: 'group' });
224
+ this.internals.ariaRequired = this.required ? 'true' : null;
225
+ }
226
+ firstUpdated(changed) {
227
+ super.firstUpdated(changed);
228
+ /* Before the first `sync`, and only ever once: after this the group's value
229
+ is what the boxes follow. Client only, the server having no boxes to
230
+ read. */
231
+ if (this.value === '') {
232
+ this.seed();
233
+ }
234
+ }
235
+ /**
236
+ * Refuses an empty set where one was required, which nothing did.
237
+ *
238
+ * `required` arrives with `MixinField`, reflects, and paints the asterisk
239
+ * through the composed field sheet, and enforced nothing at all: no validity,
240
+ * no message, and nothing cascading to the boxes. A group marked required
241
+ * submitted empty.
242
+ *
243
+ * **The group is form-associated, and submits nothing.** It was not, on the
244
+ * reasoning that its boxes are the controls and each submits itself, which is
245
+ * still true: nothing here calls `setFormValue`, so the set that reaches the
246
+ * server is exactly the boxes it always was. What form association buys is the
247
+ * other half of participation, validity, and there is no other mechanism for
248
+ * it: `setValidity` throws `NotSupportedError` on an element the platform does
249
+ * not know is a control.
250
+ *
251
+ * So the fix that was written for "a group marked required submitted empty"
252
+ * threw on every update in a real browser, and happy-dom's shim does not
253
+ * throw, so the specs passed and the behavior never worked. Eleven of them
254
+ * failed the moment they were run in Chromium. It is also what makes the rest
255
+ * work: the form now refuses to submit, which fires `invalid`, which is what
256
+ * marks the field touched and puts the message on screen.
257
+ *
258
+ * Anchored on the list, because the browser needs somewhere to point the
259
+ * bubble.
260
+ */
261
+ validate() {
262
+ this.reportRequired(this.value === '', 'Choose at least one to continue.', 'items');
263
+ }
264
+ updated(changed) {
265
+ super.updated(changed);
266
+ this.validate();
267
+ this.sync();
268
+ this.linkHost();
269
+ }
270
+ render() {
271
+ /* The list is an element of its own, because the label and the hint are the
272
+ host's children too and `orientation` lays out whatever is in the flex
273
+ container. On the host, a horizontal group would have put its own label
274
+ in the row beside the first box. */
275
+ return html `${this.renderGroupLabel()}
276
+ <div part="items">
277
+ ${
278
+ /* A box arriving after first render got neither the shared name nor
279
+ the value's checked state, because nothing was listening: both
280
+ sibling groups wire this and this one did not. */
281
+ ''}
282
+ <slot @slotchange=${() => this.requestUpdate()}></slot>
283
+ </div>
284
+ ${this.renderHint()}${this.renderFeedback()}`;
285
+ }
286
+ };
287
+ __decorate([
288
+ property()
289
+ ], HelixHeadlessCheckboxGroup.prototype, "value", void 0);
290
+ HelixHeadlessCheckboxGroup = __decorate([
291
+ customElement('helix-headless-checkbox-group')
292
+ ], HelixHeadlessCheckboxGroup);
293
+ export { HelixHeadlessCheckboxGroup };
@@ -0,0 +1 @@
1
+ export * from './root/code-root.js';
@@ -0,0 +1 @@
1
+ export * from './root/code-root.js';