@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,3 @@
1
+ export * from './item/video-playlist-item.js';
2
+ export * from './menu/video-playlist-menu.js';
3
+ export * from './root/video-playlist-root.js';
@@ -0,0 +1,3 @@
1
+ export * from './item/video-playlist-item.js';
2
+ export * from './menu/video-playlist-menu.js';
3
+ export * from './root/video-playlist-root.js';
@@ -0,0 +1,101 @@
1
+ import { HelixElement } from '@fusion.dev/helix-core';
2
+ import { type TemplateResult } from 'lit';
3
+ /**
4
+ * @summary One entry in a video playlist.
5
+ *
6
+ * @description
7
+ * **It holds what the player needs and nothing about playing.** A source, a
8
+ * poster and a name: the entry knows which file it stands for, and the playlist
9
+ * is what hands that to a player. Nothing here touches a `<video>`, which is
10
+ * what keeps a playlist usable with a player the consumer configured
11
+ * themselves.
12
+ *
13
+ * **A real `<button>`, in a `listitem`.** A playlist is a list of things to
14
+ * choose, and the list roles are the honest ones: `list` and `listitem` say how
15
+ * many there are and where you are in them, which `listbox` would too, at the
16
+ * cost of the pattern a listbox obliges. `Option` records that trap in full,
17
+ * that a listbox has to keep focus elsewhere and say which item is current with
18
+ * `aria-activedescendant`. Nothing here needs that, because focus really moves
19
+ * to the button.
20
+ *
21
+ * `aria-current` rather than `aria-selected`, which belongs to the roles that
22
+ * have a selection. What is true of the entry playing now is that it is the one
23
+ * the player is on.
24
+ *
25
+ * @since 0.1.0
26
+ * @status experimental
27
+ * @category media
28
+ * @documentation https://helix.fusion.dev/components/video-playlist
29
+ *
30
+ * @slot - The entry's name.
31
+ * @slot media - A thumbnail. Falls back to an image of `poster`.
32
+ * @slot meta - After the name. A duration, or a date.
33
+ *
34
+ * @event {HelixSelectEvent} helix-select - Fired when the entry is chosen. Cancelable: refusing it takes the decision and nothing moves.
35
+ *
36
+ * @csspart container - The `listitem`, which the button sits in.
37
+ * @csspart item - The row, which is a button.
38
+ * @csspart label - The name and whatever follows it.
39
+ * @csspart media - The leading column.
40
+ * @csspart thumbnail - The image `poster` falls back to.
41
+ */
42
+ export declare class HelixHeadlessVideoPlaylistItem extends HelixElement {
43
+ /**
44
+ * What identifies the entry, and what `active` is compared against.
45
+ */
46
+ value: string;
47
+ /**
48
+ * The file this entry plays.
49
+ */
50
+ src: string;
51
+ /**
52
+ * What covers the picture before this entry plays, and the row's thumbnail.
53
+ *
54
+ * One property doing both, because they are the same picture: the frame that
55
+ * stands for the clip stands for it in the list too. It is the `media` slot's
56
+ * fallback rather than something drawn beside it, which is this library's rule
57
+ * for a content property, so a consumer with something better to show slots it
58
+ * and the two can never both appear.
59
+ */
60
+ poster: string;
61
+ /**
62
+ * Whether the entry can be chosen.
63
+ */
64
+ disabled: boolean;
65
+ /**
66
+ * Whether the player is on this entry.
67
+ *
68
+ * Written by the playlist rather than by the entry, the way an option's
69
+ * selection is: an entry that made itself current would be a second answer to
70
+ * which one is playing.
71
+ */
72
+ current: boolean;
73
+ /**
74
+ * The entry's name, which is the words and not everything in it.
75
+ *
76
+ * `textContent` was what this used, and it takes the whole subtree: a row with
77
+ * a duration in `meta` reported "His Girl Friday0:06", and that string went to
78
+ * the player and on to the lock screen. Only the nodes the consumer left
79
+ * unslotted are the name; anything named is a column beside it.
80
+ *
81
+ * Light DOM rather than `assignedNodes`, so it answers on the server too,
82
+ * where there is no slot to ask. `Option.text` reads its own the same way.
83
+ */
84
+ get text(): string;
85
+ private readonly choose;
86
+ /**
87
+ * What stands for the row: a thumbnail where there is one, and nothing where
88
+ * there is not.
89
+ *
90
+ * A seam rather than inline, so a tier can draw a duration badge over it or
91
+ * a placeholder in its place without reimplementing the row. A consumer
92
+ * slots `media` for the same reasons and neither has to know about the other.
93
+ */
94
+ protected renderMedia(): TemplateResult;
95
+ protected render(): TemplateResult;
96
+ }
97
+ declare global {
98
+ interface HTMLElementTagNameMap {
99
+ 'helix-headless-video-playlist-item': HelixHeadlessVideoPlaylistItem;
100
+ }
101
+ }
@@ -0,0 +1,162 @@
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, HelixElement, HelixSelectEvent } from '@fusion.dev/helix-core';
8
+ import { html, nothing } from 'lit';
9
+ import { property } from 'lit/decorators.js';
10
+ /**
11
+ * @summary One entry in a video playlist.
12
+ *
13
+ * @description
14
+ * **It holds what the player needs and nothing about playing.** A source, a
15
+ * poster and a name: the entry knows which file it stands for, and the playlist
16
+ * is what hands that to a player. Nothing here touches a `<video>`, which is
17
+ * what keeps a playlist usable with a player the consumer configured
18
+ * themselves.
19
+ *
20
+ * **A real `<button>`, in a `listitem`.** A playlist is a list of things to
21
+ * choose, and the list roles are the honest ones: `list` and `listitem` say how
22
+ * many there are and where you are in them, which `listbox` would too, at the
23
+ * cost of the pattern a listbox obliges. `Option` records that trap in full,
24
+ * that a listbox has to keep focus elsewhere and say which item is current with
25
+ * `aria-activedescendant`. Nothing here needs that, because focus really moves
26
+ * to the button.
27
+ *
28
+ * `aria-current` rather than `aria-selected`, which belongs to the roles that
29
+ * have a selection. What is true of the entry playing now is that it is the one
30
+ * the player is on.
31
+ *
32
+ * @since 0.1.0
33
+ * @status experimental
34
+ * @category media
35
+ * @documentation https://helix.fusion.dev/components/video-playlist
36
+ *
37
+ * @slot - The entry's name.
38
+ * @slot media - A thumbnail. Falls back to an image of `poster`.
39
+ * @slot meta - After the name. A duration, or a date.
40
+ *
41
+ * @event {HelixSelectEvent} helix-select - Fired when the entry is chosen. Cancelable: refusing it takes the decision and nothing moves.
42
+ *
43
+ * @csspart container - The `listitem`, which the button sits in.
44
+ * @csspart item - The row, which is a button.
45
+ * @csspart label - The name and whatever follows it.
46
+ * @csspart media - The leading column.
47
+ * @csspart thumbnail - The image `poster` falls back to.
48
+ */
49
+ let HelixHeadlessVideoPlaylistItem = class HelixHeadlessVideoPlaylistItem extends HelixElement {
50
+ constructor() {
51
+ super(...arguments);
52
+ /**
53
+ * What identifies the entry, and what `active` is compared against.
54
+ */
55
+ this.value = '';
56
+ /**
57
+ * The file this entry plays.
58
+ */
59
+ this.src = '';
60
+ /**
61
+ * What covers the picture before this entry plays, and the row's thumbnail.
62
+ *
63
+ * One property doing both, because they are the same picture: the frame that
64
+ * stands for the clip stands for it in the list too. It is the `media` slot's
65
+ * fallback rather than something drawn beside it, which is this library's rule
66
+ * for a content property, so a consumer with something better to show slots it
67
+ * and the two can never both appear.
68
+ */
69
+ this.poster = '';
70
+ /**
71
+ * Whether the entry can be chosen.
72
+ */
73
+ this.disabled = false;
74
+ /**
75
+ * Whether the player is on this entry.
76
+ *
77
+ * Written by the playlist rather than by the entry, the way an option's
78
+ * selection is: an entry that made itself current would be a second answer to
79
+ * which one is playing.
80
+ */
81
+ this.current = false;
82
+ this.choose = () => {
83
+ if (this.disabled) {
84
+ return;
85
+ }
86
+ this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
87
+ };
88
+ }
89
+ /**
90
+ * The entry's name, which is the words and not everything in it.
91
+ *
92
+ * `textContent` was what this used, and it takes the whole subtree: a row with
93
+ * a duration in `meta` reported "His Girl Friday0:06", and that string went to
94
+ * the player and on to the lock screen. Only the nodes the consumer left
95
+ * unslotted are the name; anything named is a column beside it.
96
+ *
97
+ * Light DOM rather than `assignedNodes`, so it answers on the server too,
98
+ * where there is no slot to ask. `Option.text` reads its own the same way.
99
+ */
100
+ get text() {
101
+ return [...this.childNodes]
102
+ .filter((node) => !(node instanceof Element) || !node.hasAttribute('slot'))
103
+ .map((node) => node.textContent ?? '')
104
+ .join('')
105
+ .trim();
106
+ }
107
+ /**
108
+ * What stands for the row: a thumbnail where there is one, and nothing where
109
+ * there is not.
110
+ *
111
+ * A seam rather than inline, so a tier can draw a duration badge over it or
112
+ * a placeholder in its place without reimplementing the row. A consumer
113
+ * slots `media` for the same reasons and neither has to know about the other.
114
+ */
115
+ renderMedia() {
116
+ return html `<slot name="media">
117
+ ${
118
+ // `alt=""`, because the row's own words already name it and a
119
+ // thumbnail repeating them is the same thing said twice.
120
+ this.poster === '' ? nothing : html `<img part="thumbnail" alt="" src=${this.poster} />`}
121
+ </slot>`;
122
+ }
123
+ render() {
124
+ /* `aria-current="true"`, and absent rather than `"false"` otherwise. A
125
+ reader is told which one is playing; being told about each of the others
126
+ that it is not playing is the same fact eleven times. */
127
+ return html `<div part="container" role="listitem">
128
+ <button
129
+ part="item"
130
+ type="button"
131
+ aria-current=${this.current ? 'true' : nothing}
132
+ ?disabled=${this.disabled}
133
+ @click=${this.choose}
134
+ >
135
+ <span part="media">${this.renderMedia()}</span>
136
+ <span part="label">
137
+ <slot></slot>
138
+ <slot name="meta"></slot>
139
+ </span>
140
+ </button>
141
+ </div>`;
142
+ }
143
+ };
144
+ __decorate([
145
+ property()
146
+ ], HelixHeadlessVideoPlaylistItem.prototype, "value", void 0);
147
+ __decorate([
148
+ property()
149
+ ], HelixHeadlessVideoPlaylistItem.prototype, "src", void 0);
150
+ __decorate([
151
+ property()
152
+ ], HelixHeadlessVideoPlaylistItem.prototype, "poster", void 0);
153
+ __decorate([
154
+ property({ reflect: true, type: Boolean })
155
+ ], HelixHeadlessVideoPlaylistItem.prototype, "disabled", void 0);
156
+ __decorate([
157
+ property({ attribute: false })
158
+ ], HelixHeadlessVideoPlaylistItem.prototype, "current", void 0);
159
+ HelixHeadlessVideoPlaylistItem = __decorate([
160
+ customElement('helix-headless-video-playlist-item')
161
+ ], HelixHeadlessVideoPlaylistItem);
162
+ export { HelixHeadlessVideoPlaylistItem };
@@ -0,0 +1,121 @@
1
+ import { HelixElement } from '@fusion.dev/helix-core';
2
+ import { type TemplateResult } from 'lit';
3
+ import '../../menu/index.js';
4
+ /**
5
+ * @summary The playlist's entries, as a menu inside the player's control bar.
6
+ *
7
+ * @description
8
+ * The entries again, reachable without leaving the picture. A playlist beside
9
+ * the player is a list a reader scrolls to; the same list in the control bar is
10
+ * one they open over the video, which is what a full-screen player has and what
11
+ * a phone has room for.
12
+ *
13
+ * **It is placed by the consumer, not rendered by the playlist**, and that is
14
+ * forced rather than chosen. A shadow root cannot project into a sibling's
15
+ * light DOM, so nothing the playlist renders can land inside the player's
16
+ * control bar. What can is an element the consumer writes there, which is what
17
+ * `Video`'s `controls` slot is for:
18
+ *
19
+ * ```html
20
+ * <helix-video-playlist>
21
+ * <helix-video slot="player" controls>
22
+ * <helix-video-playlist-menu slot="controls"></helix-video-playlist-menu>
23
+ * </helix-video>
24
+ * <helix-video-playlist-item value="one" src="/one.mp4">One</helix-video-playlist-item>
25
+ * </helix-video-playlist>
26
+ * ```
27
+ *
28
+ * So it finds its playlist upward rather than being handed one, and that chain
29
+ * crosses a shadow boundary in the ordinary arrangement, which is why it is
30
+ * `closestInstance` and not `closest`.
31
+ *
32
+ * **Choosing dispatches `helix-select`, the same event an entry dispatches.**
33
+ * It never writes `active` on the playlist, which looks like the shorter path
34
+ * and would latch the controlled contract: a playlist assigned `active` once
35
+ * goes quiet and waits for a consumer who was never there. Announcing is what
36
+ * an entry does, the playlist already listens for it, and a consumer refusing a
37
+ * selection gets `preventDefault()` on one event rather than two paths that
38
+ * behave differently.
39
+ *
40
+ * @since 0.1.0
41
+ * @status experimental
42
+ * @category media
43
+ * @aliases Episode Menu, Queue Menu, Up Next
44
+ * @documentation https://helix.fusion.dev/components/video-playlist
45
+ *
46
+ * @slot trigger - Replaces the button that opens the menu.
47
+ *
48
+ * @event {HelixSelectEvent} helix-select - Fired with the chosen entry's value. The playlist listens for it. Cancelable: refusing it takes the decision and nothing moves.
49
+ *
50
+ * @csspart entry - One entry in the menu.
51
+ * @csspart entry-item - The row, which is an `<a>` where `href` is set.
52
+ * @csspart entry-mark - The trailing mark: a tick when checked, a caret when it opens
53
+ * @csspart entry-start - The leading column, which is a slot and is always there.
54
+ * @csspart icon - The glyph on the trigger.
55
+ * @csspart menu - The menu that holds the entries.
56
+ * @csspart menu-back - The control that returns from a submenu.
57
+ * @csspart menu-back-mark - The glyph on the back control of a submenu.
58
+ * @csspart menu-empty - Shown when there are no items to show.
59
+ * @csspart menu-header - The bar above a submenu, holding the way back and its name.
60
+ * @csspart menu-loading - Shown while the items are still on their way.
61
+ * @csspart menu-surface - The floating panel the menu is drawn on.
62
+ * @csspart menu-title - The name of the submenu that is showing.
63
+ * @csspart poster - An entry's still, where it has one.
64
+ * @csspart trigger - The button that opens it.
65
+ */
66
+ export declare class HelixHeadlessVideoPlaylistMenu extends HelixElement {
67
+ #private;
68
+ /**
69
+ * The menu's accessible name, and its trigger's.
70
+ *
71
+ * "Episodes" suits a series and is wrong for a set of camera angles, and the
72
+ * component cannot know which one it is in.
73
+ */
74
+ label: string;
75
+ /**
76
+ * Where the menu opens relative to its trigger.
77
+ *
78
+ * `top-end` because a control bar sits at the foot of the picture, and a menu
79
+ * opening downward from there opens off the player.
80
+ */
81
+ placement: string;
82
+ connectedCallback(): void;
83
+ disconnectedCallback(): void;
84
+ /** The playlist this menu belongs to, found upward through the slots. */
85
+ private get playlist();
86
+ /** The playlist's entries, in the order it holds them. */
87
+ private get entries();
88
+ /**
89
+ * Watches the playlist for entries arriving, and re-reads it on every open.
90
+ *
91
+ * Two signals rather than one, because the two facts change on different
92
+ * clocks and only one of them is observable.
93
+ *
94
+ * **Which entries exist** is the playlist's light DOM, and a `MutationObserver`
95
+ * sees it directly.
96
+ *
97
+ * **Which entry is current** is `active`, a property with no attribute, so
98
+ * there is nothing to observe: events travel up from the playlist and this
99
+ * element is below it, and mirroring `active` to a `data-` name is ruled out
100
+ * on its own merits, `active` being a payload rather than a boolean fact.
101
+ * Mirroring it was written and reverted here: it put `data-active` onto every
102
+ * host, which `tree-root.ssr.spec.ts` caught, and the rule it broke was the
103
+ * one that stops a copied host coming back frozen.
104
+ *
105
+ * So it is re-read at the moment it is looked at. `helix-before-open` comes from the
106
+ * menu in this element's own shadow root, which is the one direction events
107
+ * do arrive from, and a closed menu showing a stale mark is a thing nobody
108
+ * can see.
109
+ */
110
+ private watch;
111
+ private readonly reread;
112
+ private readonly choose;
113
+ protected render(): TemplateResult;
114
+ /** The menu itself, behind a method so a styled tier can render another one. */
115
+ protected renderMenu(): TemplateResult;
116
+ }
117
+ declare global {
118
+ interface HTMLElementTagNameMap {
119
+ 'helix-headless-video-playlist-menu': HelixHeadlessVideoPlaylistMenu;
120
+ }
121
+ }
@@ -0,0 +1,237 @@
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 { closestInstance, customElement, drawIcon, HelixElement, HelixSelectEvent, } from '@fusion.dev/helix-core';
8
+ import { list } from '@fusion.dev/helix-icons';
9
+ import { nothing } from 'lit';
10
+ import { property } from 'lit/decorators.js';
11
+ import { html } from 'lit/static-html.js';
12
+ import { HelixHeadlessVideoPlaylist } from '../root/video-playlist-root.js';
13
+ import '../../menu/index.js';
14
+ const ITEMS = 'helix-video-playlist-item, helix-headless-video-playlist-item';
15
+ /**
16
+ * @summary The playlist's entries, as a menu inside the player's control bar.
17
+ *
18
+ * @description
19
+ * The entries again, reachable without leaving the picture. A playlist beside
20
+ * the player is a list a reader scrolls to; the same list in the control bar is
21
+ * one they open over the video, which is what a full-screen player has and what
22
+ * a phone has room for.
23
+ *
24
+ * **It is placed by the consumer, not rendered by the playlist**, and that is
25
+ * forced rather than chosen. A shadow root cannot project into a sibling's
26
+ * light DOM, so nothing the playlist renders can land inside the player's
27
+ * control bar. What can is an element the consumer writes there, which is what
28
+ * `Video`'s `controls` slot is for:
29
+ *
30
+ * ```html
31
+ * <helix-video-playlist>
32
+ * <helix-video slot="player" controls>
33
+ * <helix-video-playlist-menu slot="controls"></helix-video-playlist-menu>
34
+ * </helix-video>
35
+ * <helix-video-playlist-item value="one" src="/one.mp4">One</helix-video-playlist-item>
36
+ * </helix-video-playlist>
37
+ * ```
38
+ *
39
+ * So it finds its playlist upward rather than being handed one, and that chain
40
+ * crosses a shadow boundary in the ordinary arrangement, which is why it is
41
+ * `closestInstance` and not `closest`.
42
+ *
43
+ * **Choosing dispatches `helix-select`, the same event an entry dispatches.**
44
+ * It never writes `active` on the playlist, which looks like the shorter path
45
+ * and would latch the controlled contract: a playlist assigned `active` once
46
+ * goes quiet and waits for a consumer who was never there. Announcing is what
47
+ * an entry does, the playlist already listens for it, and a consumer refusing a
48
+ * selection gets `preventDefault()` on one event rather than two paths that
49
+ * behave differently.
50
+ *
51
+ * @since 0.1.0
52
+ * @status experimental
53
+ * @category media
54
+ * @aliases Episode Menu, Queue Menu, Up Next
55
+ * @documentation https://helix.fusion.dev/components/video-playlist
56
+ *
57
+ * @slot trigger - Replaces the button that opens the menu.
58
+ *
59
+ * @event {HelixSelectEvent} helix-select - Fired with the chosen entry's value. The playlist listens for it. Cancelable: refusing it takes the decision and nothing moves.
60
+ *
61
+ * @csspart entry - One entry in the menu.
62
+ * @csspart entry-item - The row, which is an `<a>` where `href` is set.
63
+ * @csspart entry-mark - The trailing mark: a tick when checked, a caret when it opens
64
+ * @csspart entry-start - The leading column, which is a slot and is always there.
65
+ * @csspart icon - The glyph on the trigger.
66
+ * @csspart menu - The menu that holds the entries.
67
+ * @csspart menu-back - The control that returns from a submenu.
68
+ * @csspart menu-back-mark - The glyph on the back control of a submenu.
69
+ * @csspart menu-empty - Shown when there are no items to show.
70
+ * @csspart menu-header - The bar above a submenu, holding the way back and its name.
71
+ * @csspart menu-loading - Shown while the items are still on their way.
72
+ * @csspart menu-surface - The floating panel the menu is drawn on.
73
+ * @csspart menu-title - The name of the submenu that is showing.
74
+ * @csspart poster - An entry's still, where it has one.
75
+ * @csspart trigger - The button that opens it.
76
+ */
77
+ let HelixHeadlessVideoPlaylistMenu = class HelixHeadlessVideoPlaylistMenu extends HelixElement {
78
+ constructor() {
79
+ super(...arguments);
80
+ /**
81
+ * The menu's accessible name, and its trigger's.
82
+ *
83
+ * "Episodes" suits a series and is wrong for a set of camera angles, and the
84
+ * component cannot know which one it is in.
85
+ */
86
+ this.label = 'Episodes';
87
+ /**
88
+ * Where the menu opens relative to its trigger.
89
+ *
90
+ * `top-end` because a control bar sits at the foot of the picture, and a menu
91
+ * opening downward from there opens off the player.
92
+ */
93
+ this.placement = 'top-end';
94
+ /* `requestUpdate` rather than a counter held in `@state`.
95
+ *
96
+ * The entries are the playlist's light DOM rather than this element's, so
97
+ * nothing about them schedules an update here: an entry added, removed, or
98
+ * made current changes a tree this element only looks at. A bumped field is
99
+ * the usual way to say "render again", and here it is a field nothing reads,
100
+ * which the linter is right to call out. Asking directly says the same thing
101
+ * with nothing to explain. */
102
+ this.reread = () => {
103
+ this.requestUpdate();
104
+ };
105
+ this.choose = (value) => {
106
+ this.dispatchEvent(new HelixSelectEvent({ value }));
107
+ };
108
+ }
109
+ #observer;
110
+ connectedCallback() {
111
+ super.connectedCallback();
112
+ /* After the first update, because the playlist is found by walking the tree
113
+ and the server has no tree to walk. */
114
+ this.updateComplete.then(() => this.watch());
115
+ }
116
+ disconnectedCallback() {
117
+ super.disconnectedCallback();
118
+ this.removeEventListener('helix-before-open', this.reread);
119
+ this.#observer?.disconnect();
120
+ this.#observer = undefined;
121
+ }
122
+ /* Resolved once, on the client, and never during a render.
123
+ *
124
+ * `render` reached for this through `closestInstance` at first, which walks
125
+ * `parentNode` and steps across a `ShadowRoot` by following its `host`. That
126
+ * names `ShadowRoot`, which the server has no global for, so every SSR of
127
+ * this element threw `ReferenceError: Can't find variable: ShadowRoot` from
128
+ * inside Lit's own result collector, three frames from anything recognisable.
129
+ *
130
+ * Which is the tree-inspection rule arriving as a crash rather than as a
131
+ * wrong answer: a component that walks the tree to render cannot render on a
132
+ * server, and the server has no tree to walk anyway. Held here instead, set
133
+ * after the first update, and `undefined` on the server, where an empty menu
134
+ * is the honest output. */
135
+ #playlist;
136
+ /** The playlist this menu belongs to, found upward through the slots. */
137
+ get playlist() {
138
+ return this.#playlist;
139
+ }
140
+ /** The playlist's entries, in the order it holds them. */
141
+ get entries() {
142
+ const playlist = this.playlist;
143
+ return playlist ? [...playlist.querySelectorAll(ITEMS)] : [];
144
+ }
145
+ /**
146
+ * Watches the playlist for entries arriving, and re-reads it on every open.
147
+ *
148
+ * Two signals rather than one, because the two facts change on different
149
+ * clocks and only one of them is observable.
150
+ *
151
+ * **Which entries exist** is the playlist's light DOM, and a `MutationObserver`
152
+ * sees it directly.
153
+ *
154
+ * **Which entry is current** is `active`, a property with no attribute, so
155
+ * there is nothing to observe: events travel up from the playlist and this
156
+ * element is below it, and mirroring `active` to a `data-` name is ruled out
157
+ * on its own merits, `active` being a payload rather than a boolean fact.
158
+ * Mirroring it was written and reverted here: it put `data-active` onto every
159
+ * host, which `tree-root.ssr.spec.ts` caught, and the rule it broke was the
160
+ * one that stops a copied host coming back frozen.
161
+ *
162
+ * So it is re-read at the moment it is looked at. `helix-before-open` comes from the
163
+ * menu in this element's own shadow root, which is the one direction events
164
+ * do arrive from, and a closed menu showing a stale mark is a thing nobody
165
+ * can see.
166
+ */
167
+ watch() {
168
+ this.#playlist ??= closestInstance(this, HelixHeadlessVideoPlaylist) ?? undefined;
169
+ const playlist = this.#playlist;
170
+ if (!playlist || this.#observer) {
171
+ return;
172
+ }
173
+ this.addEventListener('helix-before-open', this.reread);
174
+ this.#observer = new MutationObserver(this.reread);
175
+ this.#observer.observe(playlist, { childList: true, subtree: true });
176
+ this.reread();
177
+ }
178
+ render() {
179
+ return this.renderMenu();
180
+ }
181
+ /** The menu itself, behind a method so a styled tier can render another one. */
182
+ renderMenu() {
183
+ const active = this.playlist?.active;
184
+ return html `<${this.tag('menu')} part="menu"
185
+ exportparts="back: menu-back, back-mark: menu-back-mark, empty: menu-empty, header: menu-header,
186
+ loading: menu-loading, surface: menu-surface, title: menu-title" label=${this.label} placement=${this.placement}>
187
+ <slot name="trigger" slot="trigger">
188
+ <button part="trigger" type="button" aria-label=${this.label}>${drawIcon(list)}</button>
189
+ </slot>
190
+ ${this.entries.map((entry) => html `<${this.tag('menu-item')}
191
+ part="entry"
192
+ exportparts="item: entry-item, mark: entry-mark, start: entry-start"
193
+ value=${entry.value}
194
+ aria-checked=${entry.value === active ? 'true' : 'false'}
195
+ ?disabled=${entry.disabled}
196
+ role="menuitemradio"
197
+ @helix-select=${(event) => {
198
+ /* Stopped and re-announced from the host rather than let through.
199
+ What travels up is then this element's own event, so a consumer
200
+ listening on the menu sees what the playlist sees, and
201
+ `preventDefault()` refuses the selection in one place. */
202
+ event.stopPropagation();
203
+ this.choose(entry.value);
204
+ }}
205
+ >
206
+ ${
207
+ /* The still, where there is one, for the reason the list beside the
208
+ player shows one: a reader picks an episode by recognising it
209
+ faster than by reading its title, and this menu opens over the
210
+ picture where reading is hardest.
211
+ *
212
+ * In `start`, which is free: `Menu.Item` renders its tick *after*
213
+ * the label as `part="mark"`, so the leading column has nothing to
214
+ * collide with. `alt=""`, because the name is in the same row and a
215
+ * still repeating it is the same thing said twice, which is what
216
+ * `Video.Playlist.Item` already decided about its own thumbnail.
217
+ *
218
+ * Omitted rather than empty where there is no poster, an `<img>`
219
+ * with no `src` being a broken-image glyph in every engine. */
220
+ entry.poster === ''
221
+ ? nothing
222
+ : html `<img alt="" part="poster" slot="start" src=${entry.poster} />`}
223
+ ${entry.text}
224
+ </${this.tag('menu-item')}>`)}
225
+ </${this.tag('menu')}>`;
226
+ }
227
+ };
228
+ __decorate([
229
+ property()
230
+ ], HelixHeadlessVideoPlaylistMenu.prototype, "label", void 0);
231
+ __decorate([
232
+ property()
233
+ ], HelixHeadlessVideoPlaylistMenu.prototype, "placement", void 0);
234
+ HelixHeadlessVideoPlaylistMenu = __decorate([
235
+ customElement('helix-headless-video-playlist-menu')
236
+ ], HelixHeadlessVideoPlaylistMenu);
237
+ export { HelixHeadlessVideoPlaylistMenu };