@ixfx/components 0.2.4 → 0.2.6

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 (718) hide show
  1. package/bundle/index.d.ts +285 -159
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +3291 -2485
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.d.ts +96 -0
  6. package/dist/ac-text.d.ts.map +1 -0
  7. package/dist/ac-text.js +484 -0
  8. package/dist/ac-text.js.map +1 -0
  9. package/dist/{button/button-styles.js → button-B9ztaKyl.js} +49 -3
  10. package/dist/button-B9ztaKyl.js.map +1 -0
  11. package/dist/button.d.ts +20 -0
  12. package/dist/button.d.ts.map +1 -0
  13. package/dist/button.js +3 -0
  14. package/dist/checkbox.d.ts +26 -57
  15. package/dist/checkbox.d.ts.map +1 -1
  16. package/dist/checkbox.js +74 -88
  17. package/dist/checkbox.js.map +1 -1
  18. package/dist/chunk-pbuEa-1d.js +13 -0
  19. package/dist/colour-C3MQIjFJ-BJV-QC-3.js +4138 -0
  20. package/dist/colour-C3MQIjFJ-BJV-QC-3.js.map +1 -0
  21. package/dist/colour-picker-BNqDz4wK.js +922 -0
  22. package/dist/colour-picker-BNqDz4wK.js.map +1 -0
  23. package/dist/colour-picker.d.ts +2 -0
  24. package/dist/colour-picker.js +2 -0
  25. package/dist/crumbs.d.ts +91 -0
  26. package/dist/crumbs.d.ts.map +1 -0
  27. package/dist/crumbs.js +789 -0
  28. package/dist/crumbs.js.map +1 -0
  29. package/dist/data-display.d.ts +22 -18
  30. package/dist/data-display.d.ts.map +1 -1
  31. package/dist/data-display.js +81 -108
  32. package/dist/data-display.js.map +1 -1
  33. package/dist/decorate-O4m1U4l3.js +25 -0
  34. package/dist/decorate-O4m1U4l3.js.map +1 -0
  35. package/dist/defaults-FEZaGiYZ.js +38 -0
  36. package/dist/defaults-FEZaGiYZ.js.map +1 -0
  37. package/dist/dist-By5URG0Y.js +1290 -0
  38. package/dist/dist-By5URG0Y.js.map +1 -0
  39. package/dist/dist-D7kJgnSE.js +1039 -0
  40. package/dist/dist-D7kJgnSE.js.map +1 -0
  41. package/dist/editable-label.d.ts +71 -0
  42. package/dist/editable-label.d.ts.map +1 -0
  43. package/dist/editable-label.js +279 -0
  44. package/dist/editable-label.js.map +1 -0
  45. package/dist/hex-editor-2_s0Ua5t.d.ts +130 -0
  46. package/dist/hex-editor-2_s0Ua5t.d.ts.map +1 -0
  47. package/dist/hex-editor-gH3mteMr.js +1147 -0
  48. package/dist/hex-editor-gH3mteMr.js.map +1 -0
  49. package/dist/hex.d.ts +2 -0
  50. package/dist/hex.js +2 -0
  51. package/dist/highlight-CAjwQ4GE.js +50 -0
  52. package/dist/highlight-CAjwQ4GE.js.map +1 -0
  53. package/dist/icon-CYACf6o8.js +100 -0
  54. package/dist/icon-CYACf6o8.js.map +1 -0
  55. package/dist/icon-CeTDJhC7.d.ts +35 -0
  56. package/dist/icon-CeTDJhC7.d.ts.map +1 -0
  57. package/dist/icons.d.ts +3 -0
  58. package/dist/icons.js +9 -0
  59. package/dist/icons.js.map +1 -0
  60. package/dist/incr-search-BZawvrfl.js +311 -0
  61. package/dist/incr-search-BZawvrfl.js.map +1 -0
  62. package/dist/incr-search.d.ts +2 -0
  63. package/dist/incr-search.js +3 -0
  64. package/dist/index-B1hNR7Z9.d.ts +36 -0
  65. package/dist/index-B1hNR7Z9.d.ts.map +1 -0
  66. package/dist/index-CnL9krsH.d.ts +1238 -0
  67. package/dist/index-CnL9krsH.d.ts.map +1 -0
  68. package/dist/index-CwGkb9s1.d.ts +395 -0
  69. package/dist/index-CwGkb9s1.d.ts.map +1 -0
  70. package/dist/index-DrQjA8Gs.d.ts +22 -0
  71. package/dist/index-DrQjA8Gs.d.ts.map +1 -0
  72. package/dist/index-V2cJorlA.d.ts +160 -0
  73. package/dist/index-V2cJorlA.d.ts.map +1 -0
  74. package/dist/index-kY5gxbkI.d.ts +182 -0
  75. package/dist/index-kY5gxbkI.d.ts.map +1 -0
  76. package/dist/index.d.ts +540 -53
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +6519 -54
  79. package/dist/index.js.map +1 -1
  80. package/dist/interaction-CQDQJf2Q.js +1 -0
  81. package/dist/keyboard-De_vOHLg.js +20 -0
  82. package/dist/keyboard-De_vOHLg.js.map +1 -0
  83. package/dist/labelled-input-base-BvgH7ldm.js +155 -0
  84. package/dist/labelled-input-base-BvgH7ldm.js.map +1 -0
  85. package/dist/labelled-input-base-D-Y7agky.d.ts +42 -0
  86. package/dist/labelled-input-base-D-Y7agky.d.ts.map +1 -0
  87. package/dist/labelled-radial-input.d.ts +33 -0
  88. package/dist/labelled-radial-input.d.ts.map +1 -0
  89. package/dist/labelled-radial-input.js +188 -0
  90. package/dist/labelled-radial-input.js.map +1 -0
  91. package/dist/labelled-range-input.d.ts +2 -0
  92. package/dist/{labelled-range-input/labelled-range-input.js → labelled-range-input.js} +40 -45
  93. package/dist/labelled-range-input.js.map +1 -0
  94. package/dist/led.d.ts +20 -16
  95. package/dist/led.d.ts.map +1 -1
  96. package/dist/led.js +71 -79
  97. package/dist/led.js.map +1 -1
  98. package/dist/menu-C3eANB5M.js +813 -0
  99. package/dist/menu-C3eANB5M.js.map +1 -0
  100. package/dist/menu-item-6IU5weHi.js +766 -0
  101. package/dist/menu-item-6IU5weHi.js.map +1 -0
  102. package/dist/menu-item-ClQF2DKN.d.ts +127 -0
  103. package/dist/menu-item-ClQF2DKN.d.ts.map +1 -0
  104. package/dist/menu.d.ts +3 -0
  105. package/dist/menu.js +3 -0
  106. package/dist/miller.d.ts +323 -0
  107. package/dist/miller.d.ts.map +1 -0
  108. package/dist/miller.js +1343 -0
  109. package/dist/miller.js.map +1 -0
  110. package/dist/narrowed-text.d.ts +71 -0
  111. package/dist/narrowed-text.d.ts.map +1 -0
  112. package/dist/narrowed-text.js +571 -0
  113. package/dist/narrowed-text.js.map +1 -0
  114. package/dist/panel.d.ts +42 -0
  115. package/dist/panel.d.ts.map +1 -0
  116. package/dist/{panel/panel.js → panel.js} +82 -91
  117. package/dist/panel.js.map +1 -0
  118. package/dist/plots.d.ts +2 -0
  119. package/dist/plots.js +2 -0
  120. package/dist/polar-pad.d.ts +66 -0
  121. package/dist/polar-pad.d.ts.map +1 -0
  122. package/dist/polar-pad.js +537 -0
  123. package/dist/polar-pad.js.map +1 -0
  124. package/dist/popup-Ddx9LCzY.js +24 -0
  125. package/dist/popup-Ddx9LCzY.js.map +1 -0
  126. package/dist/prominence-CreDBdCs.js +98 -0
  127. package/dist/prominence-CreDBdCs.js.map +1 -0
  128. package/dist/radial-input-Dbc6fgCK.js +849 -0
  129. package/dist/radial-input-Dbc6fgCK.js.map +1 -0
  130. package/dist/radial-input-LUSBEycd.d.ts +69 -0
  131. package/dist/radial-input-LUSBEycd.d.ts.map +1 -0
  132. package/dist/radial-input.d.ts +2 -0
  133. package/dist/radial-input.js +2 -0
  134. package/dist/range-input.d.ts +42 -0
  135. package/dist/range-input.d.ts.map +1 -0
  136. package/dist/{range-input/range-input.js → range-input.js} +155 -168
  137. package/dist/range-input.js.map +1 -0
  138. package/dist/range.d.ts +27 -0
  139. package/dist/range.d.ts.map +1 -0
  140. package/dist/range.js +136 -0
  141. package/dist/range.js.map +1 -0
  142. package/dist/registry-CZEB1YI9.js +21 -0
  143. package/dist/registry-CZEB1YI9.js.map +1 -0
  144. package/dist/selecthorizontal.d.ts +12 -8
  145. package/dist/selecthorizontal.d.ts.map +1 -1
  146. package/dist/selecthorizontal.js +20 -24
  147. package/dist/selecthorizontal.js.map +1 -1
  148. package/dist/snap-container.d.ts +49 -0
  149. package/dist/snap-container.d.ts.map +1 -0
  150. package/dist/snap-container.js +297 -0
  151. package/dist/snap-container.js.map +1 -0
  152. package/dist/{split-layout/split-layout.d.ts → split-layout.d.ts} +29 -25
  153. package/dist/split-layout.d.ts.map +1 -0
  154. package/dist/split-layout.js +545 -0
  155. package/dist/split-layout.js.map +1 -0
  156. package/dist/style.css +133 -0
  157. package/dist/swipe.d.ts +48 -0
  158. package/dist/swipe.d.ts.map +1 -0
  159. package/dist/swipe.js +204 -0
  160. package/dist/swipe.js.map +1 -0
  161. package/dist/tab-list-BnqISNvO.d.ts +65 -0
  162. package/dist/tab-list-BnqISNvO.d.ts.map +1 -0
  163. package/dist/tabs.d.ts +2 -0
  164. package/dist/tabs.js +203 -0
  165. package/dist/tabs.js.map +1 -0
  166. package/dist/tickled-controller-Cq1Va0rR.d.ts +218 -0
  167. package/dist/tickled-controller-Cq1Va0rR.d.ts.map +1 -0
  168. package/dist/tickled-styles-Bg3QbcrD.js +327 -0
  169. package/dist/tickled-styles-Bg3QbcrD.js.map +1 -0
  170. package/dist/timeline-B62Sz6J_.js +1748 -0
  171. package/dist/timeline-B62Sz6J_.js.map +1 -0
  172. package/dist/timeline.d.ts +2 -0
  173. package/dist/timeline.js +2 -0
  174. package/dist/tooltip-CwGfb4lp.d.ts +25 -0
  175. package/dist/tooltip-CwGfb4lp.d.ts.map +1 -0
  176. package/dist/{styles/tooltip.js → tooltip-DMxmBNky.js} +6 -2
  177. package/dist/tooltip-DMxmBNky.js.map +1 -0
  178. package/dist/tree-component-CQpoPo4s.d.ts +326 -0
  179. package/dist/tree-component-CQpoPo4s.d.ts.map +1 -0
  180. package/dist/tree-data-model-DGvRVOFY.js +190 -0
  181. package/dist/tree-data-model-DGvRVOFY.js.map +1 -0
  182. package/dist/tree.d.ts +99 -0
  183. package/dist/tree.d.ts.map +1 -0
  184. package/dist/tree.js +1144 -0
  185. package/dist/tree.js.map +1 -0
  186. package/dist/types-BKaqnpwx.d.ts +8 -0
  187. package/dist/types-BKaqnpwx.d.ts.map +1 -0
  188. package/dist/xy-axis-C7fNxDwY.js +6243 -0
  189. package/dist/xy-axis-C7fNxDwY.js.map +1 -0
  190. package/dist/xy-axis-D9uwpGTT.d.ts +140 -0
  191. package/dist/xy-axis-D9uwpGTT.d.ts.map +1 -0
  192. package/dist/xy-pad.d.ts +73 -110
  193. package/dist/xy-pad.d.ts.map +1 -1
  194. package/dist/xy-pad.js +300 -320
  195. package/dist/xy-pad.js.map +1 -1
  196. package/package.json +24 -28
  197. package/dist/ac-text/ac-text.d.ts +0 -99
  198. package/dist/ac-text/ac-text.d.ts.map +0 -1
  199. package/dist/ac-text/ac-text.js +0 -571
  200. package/dist/ac-text/ac-text.js.map +0 -1
  201. package/dist/button/button-styles.d.ts +0 -2
  202. package/dist/button/button-styles.d.ts.map +0 -1
  203. package/dist/button/button-styles.js.map +0 -1
  204. package/dist/button/button.d.ts +0 -16
  205. package/dist/button/button.d.ts.map +0 -1
  206. package/dist/button/button.js +0 -58
  207. package/dist/button/button.js.map +0 -1
  208. package/dist/button/radio-group.d.ts +0 -44
  209. package/dist/button/radio-group.d.ts.map +0 -1
  210. package/dist/button/radio-group.js +0 -385
  211. package/dist/button/radio-group.js.map +0 -1
  212. package/dist/button/split-button.d.ts +0 -59
  213. package/dist/button/split-button.d.ts.map +0 -1
  214. package/dist/button/split-button.js +0 -480
  215. package/dist/button/split-button.js.map +0 -1
  216. package/dist/button/types.d.ts +0 -18
  217. package/dist/button/types.d.ts.map +0 -1
  218. package/dist/button/types.js +0 -2
  219. package/dist/button/types.js.map +0 -1
  220. package/dist/colour-picker/colour-picker-popup.d.ts +0 -102
  221. package/dist/colour-picker/colour-picker-popup.d.ts.map +0 -1
  222. package/dist/colour-picker/colour-picker-popup.js +0 -399
  223. package/dist/colour-picker/colour-picker-popup.js.map +0 -1
  224. package/dist/colour-picker/colour-picker.d.ts +0 -100
  225. package/dist/colour-picker/colour-picker.d.ts.map +0 -1
  226. package/dist/colour-picker/colour-picker.js +0 -567
  227. package/dist/colour-picker/colour-picker.js.map +0 -1
  228. package/dist/colour-picker/index.d.ts +0 -4
  229. package/dist/colour-picker/index.d.ts.map +0 -1
  230. package/dist/colour-picker/index.js +0 -3
  231. package/dist/colour-picker/index.js.map +0 -1
  232. package/dist/colour-picker/styles.d.ts +0 -2
  233. package/dist/colour-picker/styles.d.ts.map +0 -1
  234. package/dist/colour-picker/styles.js +0 -139
  235. package/dist/colour-picker/styles.js.map +0 -1
  236. package/dist/colour-picker/types.d.ts +0 -33
  237. package/dist/colour-picker/types.d.ts.map +0 -1
  238. package/dist/colour-picker/types.js +0 -2
  239. package/dist/colour-picker/types.js.map +0 -1
  240. package/dist/colour-picker/util.d.ts +0 -15
  241. package/dist/colour-picker/util.d.ts.map +0 -1
  242. package/dist/colour-picker/util.js +0 -35
  243. package/dist/colour-picker/util.js.map +0 -1
  244. package/dist/common/searchable.d.ts +0 -9
  245. package/dist/common/searchable.d.ts.map +0 -1
  246. package/dist/common/searchable.js +0 -9
  247. package/dist/common/searchable.js.map +0 -1
  248. package/dist/common/tree-component.d.ts +0 -172
  249. package/dist/common/tree-component.d.ts.map +0 -1
  250. package/dist/common/tree-component.js +0 -8
  251. package/dist/common/tree-component.js.map +0 -1
  252. package/dist/common/tree-data-model.d.ts +0 -100
  253. package/dist/common/tree-data-model.d.ts.map +0 -1
  254. package/dist/common/tree-data-model.js +0 -207
  255. package/dist/common/tree-data-model.js.map +0 -1
  256. package/dist/common/tree-item.d.ts +0 -7
  257. package/dist/common/tree-item.d.ts.map +0 -1
  258. package/dist/common/tree-item.js +0 -2
  259. package/dist/common/tree-item.js.map +0 -1
  260. package/dist/common/types.d.ts +0 -69
  261. package/dist/common/types.d.ts.map +0 -1
  262. package/dist/common/types.js +0 -6
  263. package/dist/common/types.js.map +0 -1
  264. package/dist/crumbs/crumb-navigation.d.ts +0 -96
  265. package/dist/crumbs/crumb-navigation.d.ts.map +0 -1
  266. package/dist/crumbs/crumb-navigation.js +0 -911
  267. package/dist/crumbs/crumb-navigation.js.map +0 -1
  268. package/dist/crumbs/crumb-path-controller.d.ts +0 -18
  269. package/dist/crumbs/crumb-path-controller.d.ts.map +0 -1
  270. package/dist/crumbs/crumb-path-controller.js +0 -81
  271. package/dist/crumbs/crumb-path-controller.js.map +0 -1
  272. package/dist/crumbs/crumb-path.d.ts +0 -65
  273. package/dist/crumbs/crumb-path.d.ts.map +0 -1
  274. package/dist/crumbs/crumb-path.js +0 -691
  275. package/dist/crumbs/crumb-path.js.map +0 -1
  276. package/dist/editable-label/editable-label.d.ts +0 -98
  277. package/dist/editable-label/editable-label.d.ts.map +0 -1
  278. package/dist/editable-label/editable-label.js +0 -348
  279. package/dist/editable-label/editable-label.js.map +0 -1
  280. package/dist/editable-label/editable-number.d.ts +0 -96
  281. package/dist/editable-label/editable-number.d.ts.map +0 -1
  282. package/dist/editable-label/editable-number.js +0 -702
  283. package/dist/editable-label/editable-number.js.map +0 -1
  284. package/dist/hex/colour.d.ts +0 -6
  285. package/dist/hex/colour.d.ts.map +0 -1
  286. package/dist/hex/colour.js +0 -33
  287. package/dist/hex/colour.js.map +0 -1
  288. package/dist/hex/data.d.ts +0 -18
  289. package/dist/hex/data.d.ts.map +0 -1
  290. package/dist/hex/data.js +0 -61
  291. package/dist/hex/data.js.map +0 -1
  292. package/dist/hex/diff.d.ts +0 -14
  293. package/dist/hex/diff.d.ts.map +0 -1
  294. package/dist/hex/diff.js +0 -31
  295. package/dist/hex/diff.js.map +0 -1
  296. package/dist/hex/hex-editor.d.ts +0 -101
  297. package/dist/hex/hex-editor.d.ts.map +0 -1
  298. package/dist/hex/hex-editor.js +0 -894
  299. package/dist/hex/hex-editor.js.map +0 -1
  300. package/dist/hex/selection.d.ts +0 -11
  301. package/dist/hex/selection.d.ts.map +0 -1
  302. package/dist/hex/selection.js +0 -218
  303. package/dist/hex/selection.js.map +0 -1
  304. package/dist/hex/types.d.ts +0 -34
  305. package/dist/hex/types.d.ts.map +0 -1
  306. package/dist/hex/types.js +0 -4
  307. package/dist/hex/types.js.map +0 -1
  308. package/dist/icons/defaults.d.ts +0 -27
  309. package/dist/icons/defaults.d.ts.map +0 -1
  310. package/dist/icons/defaults.js +0 -34
  311. package/dist/icons/defaults.js.map +0 -1
  312. package/dist/icons/icon.d.ts +0 -31
  313. package/dist/icons/icon.d.ts.map +0 -1
  314. package/dist/icons/icon.js +0 -125
  315. package/dist/icons/icon.js.map +0 -1
  316. package/dist/icons/index.d.ts +0 -5
  317. package/dist/icons/index.d.ts.map +0 -1
  318. package/dist/icons/index.js +0 -6
  319. package/dist/icons/index.js.map +0 -1
  320. package/dist/icons/registry.d.ts +0 -11
  321. package/dist/icons/registry.d.ts.map +0 -1
  322. package/dist/icons/registry.js +0 -17
  323. package/dist/icons/registry.js.map +0 -1
  324. package/dist/incr-search/ac-adapter.d.ts +0 -18
  325. package/dist/incr-search/ac-adapter.d.ts.map +0 -1
  326. package/dist/incr-search/ac-adapter.js +0 -29
  327. package/dist/incr-search/ac-adapter.js.map +0 -1
  328. package/dist/incr-search/controller-miller.d.ts +0 -9
  329. package/dist/incr-search/controller-miller.d.ts.map +0 -1
  330. package/dist/incr-search/controller-miller.js +0 -8
  331. package/dist/incr-search/controller-miller.js.map +0 -1
  332. package/dist/incr-search/controller-tree.d.ts +0 -55
  333. package/dist/incr-search/controller-tree.d.ts.map +0 -1
  334. package/dist/incr-search/controller-tree.js +0 -106
  335. package/dist/incr-search/controller-tree.js.map +0 -1
  336. package/dist/incr-search/element-search.d.ts +0 -15
  337. package/dist/incr-search/element-search.d.ts.map +0 -1
  338. package/dist/incr-search/element-search.js +0 -82
  339. package/dist/incr-search/element-search.js.map +0 -1
  340. package/dist/incr-search/fuzzy.d.ts +0 -3
  341. package/dist/incr-search/fuzzy.d.ts.map +0 -1
  342. package/dist/incr-search/fuzzy.js +0 -37
  343. package/dist/incr-search/fuzzy.js.map +0 -1
  344. package/dist/incr-search/highlight.d.ts +0 -5
  345. package/dist/incr-search/highlight.d.ts.map +0 -1
  346. package/dist/incr-search/highlight.js +0 -54
  347. package/dist/incr-search/highlight.js.map +0 -1
  348. package/dist/incr-search/incr-search.d.ts +0 -3
  349. package/dist/incr-search/incr-search.d.ts.map +0 -1
  350. package/dist/incr-search/incr-search.js +0 -73
  351. package/dist/incr-search/incr-search.js.map +0 -1
  352. package/dist/incr-search/index.d.ts +0 -12
  353. package/dist/incr-search/index.d.ts.map +0 -1
  354. package/dist/incr-search/index.js +0 -8
  355. package/dist/incr-search/index.js.map +0 -1
  356. package/dist/incr-search/types.d.ts +0 -59
  357. package/dist/incr-search/types.d.ts.map +0 -1
  358. package/dist/incr-search/types.js +0 -2
  359. package/dist/incr-search/types.js.map +0 -1
  360. package/dist/interaction/index.d.ts +0 -10
  361. package/dist/interaction/index.d.ts.map +0 -1
  362. package/dist/interaction/index.js +0 -10
  363. package/dist/interaction/index.js.map +0 -1
  364. package/dist/interaction/tickled-controller.d.ts +0 -186
  365. package/dist/interaction/tickled-controller.d.ts.map +0 -1
  366. package/dist/interaction/tickled-controller.js +0 -256
  367. package/dist/interaction/tickled-controller.js.map +0 -1
  368. package/dist/interaction/tickled-styles.d.ts +0 -53
  369. package/dist/interaction/tickled-styles.d.ts.map +0 -1
  370. package/dist/interaction/tickled-styles.js +0 -106
  371. package/dist/interaction/tickled-styles.js.map +0 -1
  372. package/dist/interaction/tree-keyboard-controller.d.ts +0 -30
  373. package/dist/interaction/tree-keyboard-controller.d.ts.map +0 -1
  374. package/dist/interaction/tree-keyboard-controller.js +0 -105
  375. package/dist/interaction/tree-keyboard-controller.js.map +0 -1
  376. package/dist/keyboard.d.ts +0 -16
  377. package/dist/keyboard.d.ts.map +0 -1
  378. package/dist/keyboard.js +0 -22
  379. package/dist/keyboard.js.map +0 -1
  380. package/dist/labelled-radial-input/index.d.ts +0 -2
  381. package/dist/labelled-radial-input/index.d.ts.map +0 -1
  382. package/dist/labelled-radial-input/index.js +0 -2
  383. package/dist/labelled-radial-input/index.js.map +0 -1
  384. package/dist/labelled-radial-input/labelled-radial-input.d.ts +0 -77
  385. package/dist/labelled-radial-input/labelled-radial-input.d.ts.map +0 -1
  386. package/dist/labelled-radial-input/labelled-radial-input.js +0 -214
  387. package/dist/labelled-radial-input/labelled-radial-input.js.map +0 -1
  388. package/dist/labelled-range-input/index.d.ts +0 -2
  389. package/dist/labelled-range-input/index.d.ts.map +0 -1
  390. package/dist/labelled-range-input/index.js +0 -2
  391. package/dist/labelled-range-input/index.js.map +0 -1
  392. package/dist/labelled-range-input/labelled-range-input.d.ts +0 -80
  393. package/dist/labelled-range-input/labelled-range-input.d.ts.map +0 -1
  394. package/dist/labelled-range-input/labelled-range-input.js.map +0 -1
  395. package/dist/menu/index.d.ts +0 -14
  396. package/dist/menu/index.d.ts.map +0 -1
  397. package/dist/menu/index.js +0 -13
  398. package/dist/menu/index.js.map +0 -1
  399. package/dist/menu/menu-bar.d.ts +0 -23
  400. package/dist/menu/menu-bar.d.ts.map +0 -1
  401. package/dist/menu/menu-bar.js +0 -110
  402. package/dist/menu/menu-bar.js.map +0 -1
  403. package/dist/menu/menu-check-item.d.ts +0 -33
  404. package/dist/menu/menu-check-item.d.ts.map +0 -1
  405. package/dist/menu/menu-check-item.js +0 -175
  406. package/dist/menu/menu-check-item.js.map +0 -1
  407. package/dist/menu/menu-command-controller.d.ts +0 -14
  408. package/dist/menu/menu-command-controller.d.ts.map +0 -1
  409. package/dist/menu/menu-command-controller.js +0 -22
  410. package/dist/menu/menu-command-controller.js.map +0 -1
  411. package/dist/menu/menu-container.d.ts +0 -36
  412. package/dist/menu/menu-container.d.ts.map +0 -1
  413. package/dist/menu/menu-container.js +0 -351
  414. package/dist/menu/menu-container.js.map +0 -1
  415. package/dist/menu/menu-from-tree.d.ts +0 -17
  416. package/dist/menu/menu-from-tree.d.ts.map +0 -1
  417. package/dist/menu/menu-from-tree.js +0 -103
  418. package/dist/menu/menu-from-tree.js.map +0 -1
  419. package/dist/menu/menu-header.d.ts +0 -12
  420. package/dist/menu/menu-header.d.ts.map +0 -1
  421. package/dist/menu/menu-header.js +0 -36
  422. package/dist/menu/menu-header.js.map +0 -1
  423. package/dist/menu/menu-item.d.ts +0 -41
  424. package/dist/menu/menu-item.d.ts.map +0 -1
  425. package/dist/menu/menu-item.js +0 -240
  426. package/dist/menu/menu-item.js.map +0 -1
  427. package/dist/menu/menu-radio-group.d.ts +0 -24
  428. package/dist/menu/menu-radio-group.d.ts.map +0 -1
  429. package/dist/menu/menu-radio-group.js +0 -71
  430. package/dist/menu/menu-radio-group.js.map +0 -1
  431. package/dist/menu/menu-radio-item.d.ts +0 -22
  432. package/dist/menu/menu-radio-item.d.ts.map +0 -1
  433. package/dist/menu/menu-radio-item.js +0 -116
  434. package/dist/menu/menu-radio-item.js.map +0 -1
  435. package/dist/menu/menu-separator.d.ts +0 -11
  436. package/dist/menu/menu-separator.d.ts.map +0 -1
  437. package/dist/menu/menu-separator.js +0 -29
  438. package/dist/menu/menu-separator.js.map +0 -1
  439. package/dist/menu/menu-sub-trigger.d.ts +0 -46
  440. package/dist/menu/menu-sub-trigger.d.ts.map +0 -1
  441. package/dist/menu/menu-sub-trigger.js +0 -302
  442. package/dist/menu/menu-sub-trigger.js.map +0 -1
  443. package/dist/menu/menu-trigger.d.ts +0 -57
  444. package/dist/menu/menu-trigger.d.ts.map +0 -1
  445. package/dist/menu/menu-trigger.js +0 -351
  446. package/dist/menu/menu-trigger.js.map +0 -1
  447. package/dist/miller/index.d.ts +0 -5
  448. package/dist/miller/index.d.ts.map +0 -1
  449. package/dist/miller/index.js +0 -5
  450. package/dist/miller/index.js.map +0 -1
  451. package/dist/miller/miller-base.d.ts +0 -184
  452. package/dist/miller/miller-base.d.ts.map +0 -1
  453. package/dist/miller/miller-base.js +0 -1249
  454. package/dist/miller/miller-base.js.map +0 -1
  455. package/dist/miller/miller-list.d.ts +0 -30
  456. package/dist/miller/miller-list.d.ts.map +0 -1
  457. package/dist/miller/miller-list.js +0 -192
  458. package/dist/miller/miller-list.js.map +0 -1
  459. package/dist/miller/miller-tree-controller.d.ts +0 -58
  460. package/dist/miller/miller-tree-controller.d.ts.map +0 -1
  461. package/dist/miller/miller-tree-controller.js +0 -134
  462. package/dist/miller/miller-tree-controller.js.map +0 -1
  463. package/dist/miller/types.d.ts +0 -63
  464. package/dist/miller/types.d.ts.map +0 -1
  465. package/dist/miller/types.js +0 -6
  466. package/dist/miller/types.js.map +0 -1
  467. package/dist/mixins/labelled-input-base.d.ts +0 -38
  468. package/dist/mixins/labelled-input-base.d.ts.map +0 -1
  469. package/dist/mixins/labelled-input-base.js +0 -171
  470. package/dist/mixins/labelled-input-base.js.map +0 -1
  471. package/dist/mixins/labelled-input-util.d.ts +0 -3
  472. package/dist/mixins/labelled-input-util.d.ts.map +0 -1
  473. package/dist/mixins/labelled-input-util.js +0 -10
  474. package/dist/mixins/labelled-input-util.js.map +0 -1
  475. package/dist/my-element.d.ts +0 -14
  476. package/dist/my-element.d.ts.map +0 -1
  477. package/dist/my-element.js +0 -44
  478. package/dist/my-element.js.map +0 -1
  479. package/dist/narrowed-text/index.d.ts +0 -3
  480. package/dist/narrowed-text/index.d.ts.map +0 -1
  481. package/dist/narrowed-text/index.js +0 -3
  482. package/dist/narrowed-text/index.js.map +0 -1
  483. package/dist/narrowed-text/narrowed-text.d.ts +0 -48
  484. package/dist/narrowed-text/narrowed-text.d.ts.map +0 -1
  485. package/dist/narrowed-text/narrowed-text.js +0 -668
  486. package/dist/narrowed-text/narrowed-text.js.map +0 -1
  487. package/dist/narrowed-text/types.d.ts +0 -20
  488. package/dist/narrowed-text/types.d.ts.map +0 -1
  489. package/dist/narrowed-text/types.js +0 -2
  490. package/dist/narrowed-text/types.js.map +0 -1
  491. package/dist/panel/panel-group.d.ts +0 -23
  492. package/dist/panel/panel-group.d.ts.map +0 -1
  493. package/dist/panel/panel-group.js +0 -109
  494. package/dist/panel/panel-group.js.map +0 -1
  495. package/dist/panel/panel.d.ts +0 -39
  496. package/dist/panel/panel.d.ts.map +0 -1
  497. package/dist/panel/panel.js.map +0 -1
  498. package/dist/plots/colour-map.d.ts +0 -31
  499. package/dist/plots/colour-map.d.ts.map +0 -1
  500. package/dist/plots/colour-map.js +0 -133
  501. package/dist/plots/colour-map.js.map +0 -1
  502. package/dist/plots/data.d.ts +0 -27
  503. package/dist/plots/data.d.ts.map +0 -1
  504. package/dist/plots/data.js +0 -47
  505. package/dist/plots/data.js.map +0 -1
  506. package/dist/plots/single-axis.d.ts +0 -41
  507. package/dist/plots/single-axis.d.ts.map +0 -1
  508. package/dist/plots/single-axis.js +0 -428
  509. package/dist/plots/single-axis.js.map +0 -1
  510. package/dist/plots/svg-utils.d.ts +0 -12
  511. package/dist/plots/svg-utils.d.ts.map +0 -1
  512. package/dist/plots/svg-utils.js +0 -64
  513. package/dist/plots/svg-utils.js.map +0 -1
  514. package/dist/plots/xy-axis.d.ts +0 -42
  515. package/dist/plots/xy-axis.d.ts.map +0 -1
  516. package/dist/plots/xy-axis.js +0 -307
  517. package/dist/plots/xy-axis.js.map +0 -1
  518. package/dist/polar-pad/polar-pad.d.ts +0 -132
  519. package/dist/polar-pad/polar-pad.d.ts.map +0 -1
  520. package/dist/polar-pad/polar-pad.js +0 -598
  521. package/dist/polar-pad/polar-pad.js.map +0 -1
  522. package/dist/radial-input/radial-input.d.ts +0 -45
  523. package/dist/radial-input/radial-input.d.ts.map +0 -1
  524. package/dist/radial-input/radial-input.js +0 -692
  525. package/dist/radial-input/radial-input.js.map +0 -1
  526. package/dist/radial-input/svg-utils.d.ts +0 -147
  527. package/dist/radial-input/svg-utils.d.ts.map +0 -1
  528. package/dist/radial-input/svg-utils.js +0 -346
  529. package/dist/radial-input/svg-utils.js.map +0 -1
  530. package/dist/radial-input/types.d.ts +0 -25
  531. package/dist/radial-input/types.d.ts.map +0 -1
  532. package/dist/radial-input/types.js +0 -5
  533. package/dist/radial-input/types.js.map +0 -1
  534. package/dist/range/range-multi.d.ts +0 -62
  535. package/dist/range/range-multi.d.ts.map +0 -1
  536. package/dist/range/range-multi.js +0 -652
  537. package/dist/range/range-multi.js.map +0 -1
  538. package/dist/range/range.d.ts +0 -23
  539. package/dist/range/range.d.ts.map +0 -1
  540. package/dist/range/range.js +0 -153
  541. package/dist/range/range.js.map +0 -1
  542. package/dist/range-input/index.d.ts +0 -2
  543. package/dist/range-input/index.d.ts.map +0 -1
  544. package/dist/range-input/index.js +0 -2
  545. package/dist/range-input/index.js.map +0 -1
  546. package/dist/range-input/range-input.d.ts +0 -92
  547. package/dist/range-input/range-input.d.ts.map +0 -1
  548. package/dist/range-input/range-input.js.map +0 -1
  549. package/dist/snap-container/snap-container.d.ts +0 -45
  550. package/dist/snap-container/snap-container.d.ts.map +0 -1
  551. package/dist/snap-container/snap-container.js +0 -352
  552. package/dist/snap-container/snap-container.js.map +0 -1
  553. package/dist/split-layout/split-layout.d.ts.map +0 -1
  554. package/dist/split-layout/split-layout.js +0 -674
  555. package/dist/split-layout/split-layout.js.map +0 -1
  556. package/dist/styles/popup.d.ts +0 -11
  557. package/dist/styles/popup.d.ts.map +0 -1
  558. package/dist/styles/popup.js +0 -20
  559. package/dist/styles/popup.js.map +0 -1
  560. package/dist/styles/prominence.d.ts +0 -58
  561. package/dist/styles/prominence.d.ts.map +0 -1
  562. package/dist/styles/prominence.js +0 -94
  563. package/dist/styles/prominence.js.map +0 -1
  564. package/dist/styles/tooltip.d.ts +0 -2
  565. package/dist/styles/tooltip.d.ts.map +0 -1
  566. package/dist/styles/tooltip.js.map +0 -1
  567. package/dist/svg-edit-label.d.ts +0 -2
  568. package/dist/svg-edit-label.d.ts.map +0 -1
  569. package/dist/svg-edit-label.js +0 -110
  570. package/dist/svg-edit-label.js.map +0 -1
  571. package/dist/swipe/index.d.ts +0 -2
  572. package/dist/swipe/index.d.ts.map +0 -1
  573. package/dist/swipe/index.js +0 -2
  574. package/dist/swipe/index.js.map +0 -1
  575. package/dist/swipe/swipe.d.ts +0 -65
  576. package/dist/swipe/swipe.d.ts.map +0 -1
  577. package/dist/swipe/swipe.js +0 -229
  578. package/dist/swipe/swipe.js.map +0 -1
  579. package/dist/tabs/tab-layout-item.d.ts +0 -10
  580. package/dist/tabs/tab-layout-item.d.ts.map +0 -1
  581. package/dist/tabs/tab-layout-item.js +0 -20
  582. package/dist/tabs/tab-layout-item.js.map +0 -1
  583. package/dist/tabs/tab-layout.d.ts +0 -10
  584. package/dist/tabs/tab-layout.d.ts.map +0 -1
  585. package/dist/tabs/tab-layout.js +0 -25
  586. package/dist/tabs/tab-layout.js.map +0 -1
  587. package/dist/tabs/tab-list-item.d.ts +0 -34
  588. package/dist/tabs/tab-list-item.d.ts.map +0 -1
  589. package/dist/tabs/tab-list-item.js +0 -195
  590. package/dist/tabs/tab-list-item.js.map +0 -1
  591. package/dist/tabs/tab-list.d.ts +0 -31
  592. package/dist/tabs/tab-list.d.ts.map +0 -1
  593. package/dist/tabs/tab-list.js +0 -257
  594. package/dist/tabs/tab-list.js.map +0 -1
  595. package/dist/tabs/tab-panel.d.ts +0 -11
  596. package/dist/tabs/tab-panel.d.ts.map +0 -1
  597. package/dist/tabs/tab-panel.js +0 -30
  598. package/dist/tabs/tab-panel.js.map +0 -1
  599. package/dist/tabs/tab-panels.d.ts +0 -30
  600. package/dist/tabs/tab-panels.d.ts.map +0 -1
  601. package/dist/tabs/tab-panels.js +0 -80
  602. package/dist/tabs/tab-panels.js.map +0 -1
  603. package/dist/timeline/index.d.ts +0 -9
  604. package/dist/timeline/index.d.ts.map +0 -1
  605. package/dist/timeline/index.js +0 -8
  606. package/dist/timeline/index.js.map +0 -1
  607. package/dist/timeline/timeline-controller.d.ts +0 -48
  608. package/dist/timeline/timeline-controller.d.ts.map +0 -1
  609. package/dist/timeline/timeline-controller.js +0 -81
  610. package/dist/timeline/timeline-controller.js.map +0 -1
  611. package/dist/timeline/timeline-draw.d.ts +0 -28
  612. package/dist/timeline/timeline-draw.d.ts.map +0 -1
  613. package/dist/timeline/timeline-draw.js +0 -330
  614. package/dist/timeline/timeline-draw.js.map +0 -1
  615. package/dist/timeline/timeline-element.d.ts +0 -140
  616. package/dist/timeline/timeline-element.d.ts.map +0 -1
  617. package/dist/timeline/timeline-element.js +0 -888
  618. package/dist/timeline/timeline-element.js.map +0 -1
  619. package/dist/timeline/timeline-interactions.d.ts +0 -40
  620. package/dist/timeline/timeline-interactions.d.ts.map +0 -1
  621. package/dist/timeline/timeline-interactions.js +0 -393
  622. package/dist/timeline/timeline-interactions.js.map +0 -1
  623. package/dist/timeline/timeline-styles.d.ts +0 -2
  624. package/dist/timeline/timeline-styles.d.ts.map +0 -1
  625. package/dist/timeline/timeline-styles.js +0 -153
  626. package/dist/timeline/timeline-styles.js.map +0 -1
  627. package/dist/timeline/timeline-track-tabs.d.ts +0 -30
  628. package/dist/timeline/timeline-track-tabs.d.ts.map +0 -1
  629. package/dist/timeline/timeline-track-tabs.js +0 -204
  630. package/dist/timeline/timeline-track-tabs.js.map +0 -1
  631. package/dist/timeline/types.d.ts +0 -144
  632. package/dist/timeline/types.d.ts.map +0 -1
  633. package/dist/timeline/types.js +0 -3
  634. package/dist/timeline/types.js.map +0 -1
  635. package/dist/tree/index.d.ts +0 -5
  636. package/dist/tree/index.d.ts.map +0 -1
  637. package/dist/tree/index.js +0 -5
  638. package/dist/tree/index.js.map +0 -1
  639. package/dist/tree/tree-base.d.ts +0 -70
  640. package/dist/tree/tree-base.d.ts.map +0 -1
  641. package/dist/tree/tree-base.js +0 -1028
  642. package/dist/tree/tree-base.js.map +0 -1
  643. package/dist/tree/tree-controller.d.ts +0 -14
  644. package/dist/tree/tree-controller.d.ts.map +0 -1
  645. package/dist/tree/tree-controller.js +0 -96
  646. package/dist/tree/tree-controller.js.map +0 -1
  647. package/dist/tree/tree-list.d.ts +0 -20
  648. package/dist/tree/tree-list.d.ts.map +0 -1
  649. package/dist/tree/tree-list.js +0 -174
  650. package/dist/tree/tree-list.js.map +0 -1
  651. package/dist/tree/types.d.ts +0 -14
  652. package/dist/tree/types.d.ts.map +0 -1
  653. package/dist/tree/types.js +0 -7
  654. package/dist/tree/types.js.map +0 -1
  655. package/dist/util/checkbox.d.ts +0 -2
  656. package/dist/util/checkbox.d.ts.map +0 -1
  657. package/dist/util/checkbox.js +0 -69
  658. package/dist/util/checkbox.js.map +0 -1
  659. package/dist/util/circle-arc.d.ts +0 -34
  660. package/dist/util/circle-arc.d.ts.map +0 -1
  661. package/dist/util/circle-arc.js +0 -85
  662. package/dist/util/circle-arc.js.map +0 -1
  663. package/dist/util/clamp.d.ts +0 -4
  664. package/dist/util/clamp.d.ts.map +0 -1
  665. package/dist/util/clamp.js +0 -23
  666. package/dist/util/clamp.js.map +0 -1
  667. package/dist/util/compare.d.ts +0 -53
  668. package/dist/util/compare.d.ts.map +0 -1
  669. package/dist/util/compare.js +0 -91
  670. package/dist/util/compare.js.map +0 -1
  671. package/dist/util/content-editable.d.ts +0 -2
  672. package/dist/util/content-editable.d.ts.map +0 -1
  673. package/dist/util/content-editable.js +0 -13
  674. package/dist/util/content-editable.js.map +0 -1
  675. package/dist/util/coordinates.d.ts +0 -3
  676. package/dist/util/coordinates.d.ts.map +0 -1
  677. package/dist/util/coordinates.js +0 -11
  678. package/dist/util/coordinates.js.map +0 -1
  679. package/dist/util/drag.d.ts +0 -16
  680. package/dist/util/drag.d.ts.map +0 -1
  681. package/dist/util/drag.js +0 -20
  682. package/dist/util/drag.js.map +0 -1
  683. package/dist/util/is-numeric.d.ts +0 -2
  684. package/dist/util/is-numeric.d.ts.map +0 -1
  685. package/dist/util/is-numeric.js +0 -9
  686. package/dist/util/is-numeric.js.map +0 -1
  687. package/dist/util/key-value.d.ts +0 -5
  688. package/dist/util/key-value.d.ts.map +0 -1
  689. package/dist/util/key-value.js +0 -29
  690. package/dist/util/key-value.js.map +0 -1
  691. package/dist/util/near.d.ts +0 -2
  692. package/dist/util/near.d.ts.map +0 -1
  693. package/dist/util/near.js +0 -6
  694. package/dist/util/near.js.map +0 -1
  695. package/dist/util/primitive-types.d.ts +0 -6
  696. package/dist/util/primitive-types.d.ts.map +0 -1
  697. package/dist/util/primitive-types.js +0 -2
  698. package/dist/util/primitive-types.js.map +0 -1
  699. package/dist/util/svg-editable-text.d.ts +0 -26
  700. package/dist/util/svg-editable-text.d.ts.map +0 -1
  701. package/dist/util/svg-editable-text.js +0 -119
  702. package/dist/util/svg-editable-text.js.map +0 -1
  703. package/dist/util/time.d.ts +0 -2
  704. package/dist/util/time.d.ts.map +0 -1
  705. package/dist/util/time.js +0 -2
  706. package/dist/util/time.js.map +0 -1
  707. package/dist/util/tooltip-controller.d.ts +0 -10
  708. package/dist/util/tooltip-controller.d.ts.map +0 -1
  709. package/dist/util/tooltip-controller.js +0 -237
  710. package/dist/util/tooltip-controller.js.map +0 -1
  711. package/dist/util/tooltip.d.ts +0 -21
  712. package/dist/util/tooltip.d.ts.map +0 -1
  713. package/dist/util/tooltip.js +0 -98
  714. package/dist/util/tooltip.js.map +0 -1
  715. package/dist/util/value-drag.d.ts +0 -33
  716. package/dist/util/value-drag.d.ts.map +0 -1
  717. package/dist/util/value-drag.js +0 -154
  718. package/dist/util/value-drag.js.map +0 -1
@@ -0,0 +1,1748 @@
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
2
+ import { LitElement, css, html, nothing } from "lit";
3
+ import { property, state } from "lit/decorators.js";
4
+ import "@clinth/vcanvas";
5
+ //#region src/timeline/timeline-draw.ts
6
+ const NICE_STEPS = [
7
+ 1,
8
+ 2,
9
+ 5,
10
+ 10
11
+ ];
12
+ /**
13
+ * Dispatch to adaptive or fixed grid mode.
14
+ */
15
+ const resolveGrid = (viewRange, userScale, viewportWidth, mode = `adaptive`, fixedMinorStep, ppu) => {
16
+ if (mode === `fixed` && fixedMinorStep !== void 0 && ppu !== void 0) return resolveFixedGrid(fixedMinorStep, ppu);
17
+ return resolveAdaptiveGrid(viewRange, userScale, viewportWidth);
18
+ };
19
+ /**
20
+ * Compute a nice major/minor grid resolution for the current view.
21
+ * Uses a 1-2-5-10 "nice number" algorithm.
22
+ */
23
+ const resolveAdaptiveGrid = (viewRange, userScale, viewportWidth) => {
24
+ const span = viewRange.max - viewRange.min;
25
+ if (span <= 0 || viewportWidth <= 0) return {
26
+ majorStep: 100,
27
+ minorDivisions: 4,
28
+ minorStep: 25
29
+ };
30
+ const targetPx = 80 * scaleMultiplier(userScale);
31
+ const rawStep = span / Math.max(2, Math.floor(viewportWidth / targetPx));
32
+ const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));
33
+ let bestStep = magnitude;
34
+ for (const n of NICE_STEPS) {
35
+ const candidate = n * magnitude;
36
+ if (candidate >= rawStep * .8) {
37
+ bestStep = candidate;
38
+ break;
39
+ }
40
+ }
41
+ const normalised = bestStep / magnitude;
42
+ const minorDivisions = normalised === 5 || normalised === 10 ? 5 : 4;
43
+ const minorStep = bestStep / minorDivisions;
44
+ return {
45
+ majorStep: bestStep,
46
+ minorDivisions,
47
+ minorStep
48
+ };
49
+ };
50
+ /**
51
+ * Fixed grid: user specifies a base minor step in logical units.
52
+ * If the minor step at current zoom would produce lines < 5px apart,
53
+ * double the effective step until they're >= 5px.
54
+ * Major = 4× effective minor.
55
+ */
56
+ const resolveFixedGrid = (baseMinorStep, ppu) => {
57
+ const MIN_PX_BETWEEN = 5;
58
+ let effectiveMinor = baseMinorStep;
59
+ while (effectiveMinor * ppu < MIN_PX_BETWEEN && effectiveMinor < 0xe8d4a51000) effectiveMinor *= 2;
60
+ const minorDivisions = 4;
61
+ return {
62
+ majorStep: effectiveMinor * minorDivisions,
63
+ minorDivisions,
64
+ minorStep: effectiveMinor
65
+ };
66
+ };
67
+ const scaleMultiplier = (scale) => {
68
+ switch (scale) {
69
+ case `x-wide`: return 2;
70
+ case `wide`: return 1.5;
71
+ case `normal`: return 1;
72
+ case `slim`: return .7;
73
+ case `x-slim`: return .5;
74
+ default: return 1;
75
+ }
76
+ };
77
+ const drawMajorMinorGrid = (ctx, region, resolution, altMajorBg, vars, ppu) => {
78
+ const { majorStep, minorStep } = resolution;
79
+ if (majorStep <= 0) return;
80
+ const regionEnd = region.x + region.width;
81
+ if (altMajorBg) {
82
+ ctx.fillStyle = vars[`--timeline-alt-major-bg`] ?? `rgba(255,255,255,0.03)`;
83
+ const firstMajor = Math.floor(region.x / majorStep);
84
+ for (let i = firstMajor; i * majorStep < regionEnd; i++) if (i % 2 !== 0) {
85
+ const x = i * majorStep * ppu;
86
+ ctx.fillRect(x, region.y, majorStep * ppu, region.height);
87
+ }
88
+ }
89
+ if (minorStep > 0) {
90
+ ctx.strokeStyle = vars[`--timeline-grid-minor-color`] ?? `rgba(255,255,255,0.05)`;
91
+ ctx.lineWidth = parseFloat(vars[`--timeline-grid-minor-width`] ?? `0.5`);
92
+ ctx.beginPath();
93
+ const firstMinor = Math.floor(region.x / minorStep) * minorStep;
94
+ for (let val = firstMinor; val < regionEnd; val += minorStep) {
95
+ if (Math.abs(val % majorStep) < minorStep * .01) continue;
96
+ const px = val * ppu;
97
+ ctx.moveTo(px, region.y);
98
+ ctx.lineTo(px, region.y + region.height);
99
+ }
100
+ ctx.stroke();
101
+ }
102
+ ctx.strokeStyle = vars[`--timeline-grid-major-color`] ?? `rgba(255,255,255,0.12)`;
103
+ ctx.lineWidth = parseFloat(vars[`--timeline-grid-major-width`] ?? `1`);
104
+ ctx.beginPath();
105
+ const firstMajor = Math.floor(region.x / majorStep) * majorStep;
106
+ for (let val = firstMajor; val < regionEnd; val += majorStep) {
107
+ const px = val * ppu;
108
+ ctx.moveTo(px, region.y);
109
+ ctx.lineTo(px, region.y + region.height);
110
+ }
111
+ ctx.stroke();
112
+ };
113
+ /**
114
+ * Draw the axis header band. With 2D virtualization the axis is "sticky" —
115
+ * it is always drawn at the current vertical scroll position (`scrollTop`)
116
+ * so it appears fixed at the viewport top.
117
+ */
118
+ const drawAxis = (ctx, region, resolution, axisHeight, formatLabel, vars, ppu, scrollTop = 0) => {
119
+ const { majorStep } = resolution;
120
+ if (majorStep <= 0 || axisHeight <= 0) return;
121
+ const axisTop = scrollTop;
122
+ const axisBottom = scrollTop + axisHeight;
123
+ if (region.y + region.height < axisTop || region.y > axisBottom) return;
124
+ const regionEnd = region.x + region.width;
125
+ const bgHeight = axisHeight - 6;
126
+ ctx.fillStyle = vars[`--timeline-bg`] ?? `#111`;
127
+ const bgLeft = region.x * ppu;
128
+ ctx.fillRect(bgLeft, axisTop, region.width * ppu, bgHeight);
129
+ ctx.strokeStyle = vars[`--timeline-grid-major-color`] ?? `rgba(255,255,255,0.12)`;
130
+ ctx.lineWidth = parseFloat(vars[`--timeline-grid-major-width`] ?? `1`);
131
+ ctx.beginPath();
132
+ const firstMajor = Math.ceil(region.x / majorStep) * majorStep;
133
+ for (let val = firstMajor; val < regionEnd; val += majorStep) {
134
+ const px = val * ppu;
135
+ ctx.moveTo(px, axisTop + bgHeight);
136
+ ctx.lineTo(px, axisBottom);
137
+ }
138
+ ctx.stroke();
139
+ ctx.strokeStyle = vars[`--timeline-grid-major-color`] ?? `rgba(255,255,255,0.12)`;
140
+ ctx.lineWidth = 1;
141
+ ctx.beginPath();
142
+ ctx.moveTo(bgLeft, axisBottom);
143
+ ctx.lineTo(bgLeft + region.width * ppu, axisBottom);
144
+ ctx.stroke();
145
+ ctx.fillStyle = vars[`--timeline-axis-label-color`] ?? `rgba(255,255,255,0.5)`;
146
+ ctx.font = `11px system-ui, sans-serif`;
147
+ ctx.textBaseline = `middle`;
148
+ ctx.textAlign = `left`;
149
+ const labelPadding = 4;
150
+ for (let val = firstMajor; val < regionEnd; val += majorStep) {
151
+ const px = val * ppu;
152
+ ctx.fillText(formatLabel(val), px + labelPadding, axisTop + bgHeight / 2);
153
+ }
154
+ ctx.textAlign = `start`;
155
+ };
156
+ const drawTrackBackgrounds = (ctx, region, trackLayout, tracks, vars, ppu) => {
157
+ const bgDefault = vars[`--timeline-track-bg`] ?? `#1a1a1a`;
158
+ const bgAlt = vars[`--timeline-track-bg-alt`] ?? `#1e1e1e`;
159
+ for (let i = 0; i < trackLayout.length; i++) {
160
+ const layout = trackLayout[i];
161
+ if (layout.y + layout.height < region.y) continue;
162
+ if (layout.y > region.y + region.height) break;
163
+ const track = tracks.find((t) => t.key === layout.trackKey);
164
+ ctx.fillStyle = track?.color ? track.color + `22` : i % 2 === 0 ? bgDefault : bgAlt;
165
+ ctx.fillRect(region.x * ppu, layout.y, region.width * ppu, layout.height);
166
+ ctx.strokeStyle = vars[`--timeline-grid-major-color`] ?? `rgba(255,255,255,0.12)`;
167
+ ctx.lineWidth = .5;
168
+ ctx.beginPath();
169
+ ctx.moveTo(region.x * ppu, layout.y + layout.height);
170
+ ctx.lineTo((region.x + region.width) * ppu, layout.y + layout.height);
171
+ ctx.stroke();
172
+ }
173
+ };
174
+ const drawEventRects = (ctx, region, events, trackLayout, selectedIds, tickledId, drag, vars, ppu) => {
175
+ const eventBg = vars[`--timeline-event-bg`] ?? `#3498db`;
176
+ const eventSelectedBg = vars[`--timeline-event-selected-bg`] ?? `#5dade2`;
177
+ const eventTickledBg = vars[`--timeline-event-tickled-bg`] ?? `#444`;
178
+ const eventLabelColor = vars[`--timeline-event-label-color`] ?? `#fff`;
179
+ const radius = parseFloat(vars[`--timeline-event-radius`] ?? `4`);
180
+ const regionEnd = region.x + region.width;
181
+ const padding = 3;
182
+ for (const evt of events) {
183
+ if (evt.end < region.x || evt.start > regionEnd) continue;
184
+ const layout = trackLayout.find((l) => l.trackKey === evt.trackKey);
185
+ if (!layout) continue;
186
+ if (layout.y + layout.height < region.y) continue;
187
+ if (layout.y > region.y + region.height) continue;
188
+ let isDragging = false;
189
+ if (drag.kind === `event-move` && drag.eventId === evt.id) isDragging = true;
190
+ else if (drag.kind === `event-start` && drag.eventId === evt.id) isDragging = true;
191
+ else if (drag.kind === `event-end` && drag.eventId === evt.id) isDragging = true;
192
+ const x = evt.start * ppu;
193
+ const w = (evt.end - evt.start) * ppu;
194
+ const y = layout.y + padding;
195
+ const h = layout.height - padding * 2;
196
+ if (w < 1) continue;
197
+ const isSelected = selectedIds.has(evt.id);
198
+ const isTickled = tickledId === evt.id;
199
+ let fill;
200
+ if (isSelected) fill = eventSelectedBg;
201
+ else if (isTickled) fill = eventTickledBg;
202
+ else fill = evt.color ?? eventBg;
203
+ ctx.fillStyle = fill;
204
+ ctx.beginPath();
205
+ drawRoundRect(ctx, x, y, w, h, Math.min(radius, w / 2, h / 2));
206
+ ctx.fill();
207
+ if (isDragging) {
208
+ ctx.strokeStyle = `#fff`;
209
+ ctx.lineWidth = 1.5;
210
+ ctx.beginPath();
211
+ drawRoundRect(ctx, x, y, w, h, Math.min(radius, w / 2, h / 2));
212
+ ctx.stroke();
213
+ }
214
+ if (isSelected && !isDragging) {
215
+ ctx.strokeStyle = eventSelectedBg;
216
+ ctx.lineWidth = 1;
217
+ ctx.beginPath();
218
+ drawRoundRect(ctx, x, y, w, h, Math.min(radius, w / 2, h / 2));
219
+ ctx.stroke();
220
+ }
221
+ if (w >= 40 && evt.label) {
222
+ ctx.fillStyle = eventLabelColor;
223
+ ctx.font = `11px system-ui, sans-serif`;
224
+ ctx.textBaseline = `middle`;
225
+ ctx.save();
226
+ ctx.beginPath();
227
+ ctx.rect(x + 4, y, w - 8, h);
228
+ ctx.clip();
229
+ ctx.fillText(evt.label, x + 6, y + h / 2);
230
+ ctx.restore();
231
+ }
232
+ }
233
+ };
234
+ const drawMarquee = (ctx, drag, ppu) => {
235
+ if (drag.kind !== `marquee`) return;
236
+ const x1 = Math.min(drag.startLogicalX, drag.currentLogicalX) * ppu;
237
+ const x2 = Math.max(drag.startLogicalX, drag.currentLogicalX) * ppu;
238
+ const y1 = Math.min(drag.startY, drag.currentY);
239
+ const y2 = Math.max(drag.startY, drag.currentY);
240
+ ctx.fillStyle = `rgba(100, 150, 255, 0.15)`;
241
+ ctx.fillRect(x1, y1, x2 - x1, y2 - y1);
242
+ ctx.strokeStyle = `rgba(100, 150, 255, 0.6)`;
243
+ ctx.lineWidth = 1;
244
+ ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
245
+ };
246
+ const drawRoundRect = (ctx, x, y, w, h, r) => {
247
+ r = Math.max(0, r);
248
+ ctx.moveTo(x + r, y);
249
+ ctx.arcTo(x + w, y, x + w, y + h, r);
250
+ ctx.arcTo(x + w, y + h, x, y + h, r);
251
+ ctx.arcTo(x, y + h, x, y, r);
252
+ ctx.arcTo(x, y, x + w, y, r);
253
+ ctx.closePath();
254
+ };
255
+ const TIMELINE_CSS_VARS = [
256
+ `--timeline-bg`,
257
+ `--timeline-track-bg`,
258
+ `--timeline-track-bg-alt`,
259
+ `--timeline-alt-major-bg`,
260
+ `--timeline-grid-major-color`,
261
+ `--timeline-grid-minor-color`,
262
+ `--timeline-grid-major-width`,
263
+ `--timeline-grid-minor-width`,
264
+ `--timeline-event-bg`,
265
+ `--timeline-event-selected-bg`,
266
+ `--timeline-event-tickled-bg`,
267
+ `--timeline-event-label-color`,
268
+ `--timeline-event-radius`,
269
+ `--timeline-axis-label-color`
270
+ ];
271
+ const resolveCssVars = (host) => {
272
+ const computed = getComputedStyle(host);
273
+ const vars = {};
274
+ for (const v of TIMELINE_CSS_VARS) vars[v] = computed.getPropertyValue(v).trim();
275
+ return vars;
276
+ };
277
+ //#endregion
278
+ //#region src/timeline/timeline-interactions.ts
279
+ /** Hit zone near the edge of an event (px in screen space) */
280
+ const EDGE_HIT_PX = 8;
281
+ /**
282
+ * Convert a vcanvas logical (pixel) coordinate to timeline logical units.
283
+ * vcanvas pixel coordinates are in the 1:1 pixel space; divide by ppu then add min.
284
+ */
285
+ const canvasToTimeline = (canvasX, ppu, min) => canvasX / ppu + min;
286
+ /**
287
+ * Convert screen-space pixel distance to timeline logical units.
288
+ * Used for edge hit threshold: how many logical units does EDGE_HIT_PX correspond to.
289
+ */
290
+ const pxToLogicalUnits = (ppu) => ppu > 0 ? 1 / ppu : 1;
291
+ const hitTest = (logicalX, y, events, trackLayout, ppu) => {
292
+ const track = trackLayout.find((tl) => y >= tl.y && y < tl.y + tl.height);
293
+ if (!track) return {
294
+ kind: `empty`,
295
+ logicalX,
296
+ y,
297
+ trackKey: void 0
298
+ };
299
+ const edgeThreshold = EDGE_HIT_PX * pxToLogicalUnits(ppu);
300
+ const trackEvents = events.filter((e) => e.trackKey === track.trackKey);
301
+ for (const evt of trackEvents) {
302
+ if (logicalX < evt.start || logicalX > evt.end) continue;
303
+ if (logicalX <= evt.start + edgeThreshold) return {
304
+ kind: `event-start`,
305
+ eventId: evt.id
306
+ };
307
+ if (logicalX >= evt.end - edgeThreshold) return {
308
+ kind: `event-end`,
309
+ eventId: evt.id
310
+ };
311
+ return {
312
+ kind: `event-move`,
313
+ eventId: evt.id,
314
+ trackKey: track.trackKey,
315
+ offsetX: logicalX - evt.start
316
+ };
317
+ }
318
+ return {
319
+ kind: `empty`,
320
+ logicalX,
321
+ y,
322
+ trackKey: track.trackKey
323
+ };
324
+ };
325
+ const trackAtY = (y, trackLayout) => {
326
+ return trackLayout.find((tl) => y >= tl.y && y < tl.y + tl.height)?.trackKey;
327
+ };
328
+ /** Sensitivity: how many pixels of vertical drag = 1 e-fold of zoom */
329
+ const ZOOM_SENSITIVITY_PX = 100;
330
+ /**
331
+ * Subtract a deadzone from a value.
332
+ * Returns 0 if |value| <= deadzone, otherwise value shifted toward zero by deadzone.
333
+ */
334
+ const applyDeadzone = (value, deadzone) => Math.abs(value) > deadzone ? value - Math.sign(value) * deadzone : 0;
335
+ /**
336
+ * Compute new ppu + viewMin from an axis-zoom drag.
337
+ * Vertical delta (dy) controls zoom (up = zoom in, down = zoom out), anchored at `anchorUnit`.
338
+ * Horizontal delta (dx) controls pan.
339
+ *
340
+ * Returns { ppu, viewMin } — the caller uses host.setZoomPan() to apply.
341
+ */
342
+ const computeAxisZoom = (startViewMin, startPpu, anchorUnit, dx, dy) => {
343
+ const newPpu = startPpu * Math.exp(-dy / ZOOM_SENSITIVITY_PX);
344
+ let newMin = anchorUnit - (anchorUnit - startViewMin) * startPpu / newPpu;
345
+ if (newPpu > 0) newMin += -dx / newPpu;
346
+ return {
347
+ ppu: newPpu,
348
+ viewMin: newMin
349
+ };
350
+ };
351
+ /**
352
+ * Compute new vertical view range from a v-axis-zoom drag.
353
+ * Horizontal delta (dx) controls zoom (right = zoom in, left = zoom out),
354
+ * anchored at `anchorBaseY` (a position in base-height units).
355
+ * Vertical delta (dy) controls pan (drag down = scroll down through tracks).
356
+ *
357
+ * Returns { vMin, vMax } — the caller uses host.setVerticalZoomPan() to apply.
358
+ */
359
+ const computeVerticalAxisZoom = (startVMin, startVMax, startVScale, anchorBaseY, dx, dy) => {
360
+ const startSpan = startVMax - startVMin;
361
+ const newSpan = startSpan * Math.exp(-dx / ZOOM_SENSITIVITY_PX);
362
+ let newMin = anchorBaseY - (startSpan > 0 ? (anchorBaseY - startVMin) / startSpan : .5) * newSpan;
363
+ if (startVScale > 0) newMin += dy / startVScale;
364
+ return {
365
+ vMin: newMin,
366
+ vMax: newMin + newSpan
367
+ };
368
+ };
369
+ /**
370
+ * Attaches pointer and keyboard interaction handlers to the timeline.
371
+ * Returns a cleanup function.
372
+ */
373
+ const attachTimelineInteractions = (host, vcanvasEl) => {
374
+ const ac = new AbortController();
375
+ const signal = ac.signal;
376
+ vcanvasEl.addEventListener(`pointerdown`, (e) => {
377
+ const ppu = host.pxPerUnit;
378
+ const canvasCoord = vcanvasEl.convertFromViewportToCanvas(e.offsetX, e.offsetY);
379
+ const lx = canvasToTimeline(canvasCoord.x, ppu, host.min);
380
+ const ly = canvasCoord.y;
381
+ const axisTop = vcanvasEl.logicalScrollTop;
382
+ if (ly >= axisTop && ly < axisTop + host.axisHeight) {
383
+ vcanvasEl.setPointerCapture(e.pointerId);
384
+ host._drag = {
385
+ kind: `axis-zoom`,
386
+ anchorUnit: lx,
387
+ startScreenX: e.screenX,
388
+ startScreenY: e.screenY,
389
+ startViewMin: host._viewRange.min,
390
+ startPpu: ppu
391
+ };
392
+ return;
393
+ }
394
+ const hit = hitTest(lx, ly, host._internalEvents, host._trackLayout, ppu);
395
+ if (e.shiftKey && hit.kind === `event-move`) {
396
+ toggleSelection(host, hit.eventId);
397
+ return;
398
+ }
399
+ if (hit.kind === `event-move`) {
400
+ vcanvasEl.setPointerCapture(e.pointerId);
401
+ host._drag = {
402
+ kind: `event-move`,
403
+ eventId: hit.eventId,
404
+ originTrackKey: hit.trackKey,
405
+ offsetX: hit.offsetX
406
+ };
407
+ return;
408
+ }
409
+ if (hit.kind === `event-start`) {
410
+ vcanvasEl.setPointerCapture(e.pointerId);
411
+ host._drag = {
412
+ kind: `event-start`,
413
+ eventId: hit.eventId
414
+ };
415
+ return;
416
+ }
417
+ if (hit.kind === `event-end`) {
418
+ vcanvasEl.setPointerCapture(e.pointerId);
419
+ host._drag = {
420
+ kind: `event-end`,
421
+ eventId: hit.eventId
422
+ };
423
+ return;
424
+ }
425
+ if (hit.kind === `empty`) {
426
+ vcanvasEl.setPointerCapture(e.pointerId);
427
+ host._drag = {
428
+ kind: `marquee`,
429
+ startLogicalX: lx,
430
+ startY: ly,
431
+ currentLogicalX: lx,
432
+ currentY: ly
433
+ };
434
+ return;
435
+ }
436
+ }, { signal });
437
+ vcanvasEl.addEventListener(`pointermove`, (e) => {
438
+ const drag = host._drag;
439
+ if (drag.kind === `none`) {
440
+ handleHover(host, vcanvasEl, e);
441
+ return;
442
+ }
443
+ const ppu = host.pxPerUnit;
444
+ const canvasCoord = vcanvasEl.convertFromViewportToCanvas(e.offsetX, e.offsetY);
445
+ const lx = canvasToTimeline(canvasCoord.x, ppu, host.min);
446
+ const ly = canvasCoord.y;
447
+ if (drag.kind === `axis-zoom`) {
448
+ const rawDx = e.screenX - drag.startScreenX;
449
+ const rawDy = e.screenY - drag.startScreenY;
450
+ if (Math.abs(rawDx) + Math.abs(rawDy) < 5) return;
451
+ const dx = applyDeadzone(rawDx, 4);
452
+ const dy = applyDeadzone(rawDy, 4);
453
+ const result = computeAxisZoom(drag.startViewMin, drag.startPpu, drag.anchorUnit, dx, dy);
454
+ host.setZoomPan(result.viewMin, result.ppu);
455
+ return;
456
+ }
457
+ if (drag.kind === `marquee`) {
458
+ host._drag = {
459
+ ...drag,
460
+ currentLogicalX: lx,
461
+ currentY: ly
462
+ };
463
+ vcanvasEl.invalidateAll();
464
+ return;
465
+ }
466
+ if (drag.kind === `event-move`) {
467
+ const evt = host._internalEvents.find((ev) => ev.id === drag.eventId);
468
+ if (!evt) return;
469
+ const duration = evt.end - evt.start;
470
+ const rawLx = lx;
471
+ const rawLy = ly;
472
+ const newStart = lx - drag.offsetX;
473
+ const newEnd = newStart + duration;
474
+ const newTrackKey = trackAtY(ly, host._trackLayout) ?? evt.trackKey;
475
+ const ppu = host.pxPerUnit;
476
+ const grid = resolveGrid(host._viewRange, host.userScale, vcanvasEl.viewportWidth, host.gridMode, host.minorStep, ppu);
477
+ const snapped = host.processDrag(drag.eventId, rawLx, rawLy, newStart, newEnd, newTrackKey, drag.originTrackKey, grid);
478
+ host._internalEvents = host._internalEvents.map((ev) => ev.id === drag.eventId ? {
479
+ ...ev,
480
+ start: snapped.start,
481
+ end: snapped.end,
482
+ trackKey: snapped.trackKey
483
+ } : ev);
484
+ vcanvasEl.invalidateAll();
485
+ return;
486
+ }
487
+ if (drag.kind === `event-start`) {
488
+ const evt = host._internalEvents.find((ev) => ev.id === drag.eventId);
489
+ if (!evt) return;
490
+ const newStart = Math.min(lx, evt.end - 1);
491
+ host._internalEvents = host._internalEvents.map((ev) => ev.id === drag.eventId ? {
492
+ ...ev,
493
+ start: newStart
494
+ } : ev);
495
+ vcanvasEl.invalidateAll();
496
+ return;
497
+ }
498
+ if (drag.kind === `event-end`) {
499
+ const evt = host._internalEvents.find((ev) => ev.id === drag.eventId);
500
+ if (!evt) return;
501
+ const newEnd = Math.max(lx, evt.start + 1);
502
+ host._internalEvents = host._internalEvents.map((ev) => ev.id === drag.eventId ? {
503
+ ...ev,
504
+ end: newEnd
505
+ } : ev);
506
+ vcanvasEl.invalidateAll();
507
+ return;
508
+ }
509
+ }, { signal });
510
+ vcanvasEl.addEventListener(`pointerup`, (e) => {
511
+ const drag = host._drag;
512
+ vcanvasEl.releasePointerCapture(e.pointerId);
513
+ if (drag.kind === `axis-zoom`) {
514
+ host._drag = { kind: `none` };
515
+ return;
516
+ }
517
+ if (drag.kind === `marquee`) {
518
+ const x1 = Math.min(drag.startLogicalX, drag.currentLogicalX);
519
+ const x2 = Math.max(drag.startLogicalX, drag.currentLogicalX);
520
+ const y1 = Math.min(drag.startY, drag.currentY);
521
+ const y2 = Math.max(drag.startY, drag.currentY);
522
+ if (Math.abs(x2 - x1) < 2 && Math.abs(y2 - y1) < 2) {
523
+ host._selectedIds = /* @__PURE__ */ new Set();
524
+ fireSelectionChange(host);
525
+ } else {
526
+ const selected = /* @__PURE__ */ new Set();
527
+ for (const evt of host._internalEvents) {
528
+ const layout = host._trackLayout.find((l) => l.trackKey === evt.trackKey);
529
+ if (!layout) continue;
530
+ const evtTop = layout.y + 3;
531
+ const evtBottom = layout.y + layout.height - 3;
532
+ if (evt.end >= x1 && evt.start <= x2 && evtBottom >= y1 && evtTop <= y2) selected.add(evt.id);
533
+ }
534
+ host._selectedIds = selected;
535
+ fireSelectionChange(host);
536
+ }
537
+ host._drag = { kind: `none` };
538
+ vcanvasEl.invalidateAll();
539
+ return;
540
+ }
541
+ if (drag.kind === `event-move`) {
542
+ const evt = host._internalEvents.find((ev) => ev.id === drag.eventId);
543
+ if (evt) host.dispatchEvent(new CustomEvent(`event-move`, {
544
+ detail: {
545
+ eventId: evt.id,
546
+ fromTrackKey: drag.originTrackKey,
547
+ toTrackKey: evt.trackKey,
548
+ start: evt.start,
549
+ end: evt.end
550
+ },
551
+ bubbles: true,
552
+ composed: true
553
+ }));
554
+ host._drag = { kind: `none` };
555
+ return;
556
+ }
557
+ if (drag.kind === `event-start` || drag.kind === `event-end`) {
558
+ const evt = host._internalEvents.find((ev) => ev.id === drag.eventId);
559
+ if (evt) host.dispatchEvent(new CustomEvent(`event-resize`, {
560
+ detail: {
561
+ eventId: evt.id,
562
+ start: evt.start,
563
+ end: evt.end
564
+ },
565
+ bubbles: true,
566
+ composed: true
567
+ }));
568
+ host._drag = { kind: `none` };
569
+ return;
570
+ }
571
+ host._drag = { kind: `none` };
572
+ }, { signal });
573
+ vcanvasEl.addEventListener(`pointerleave`, () => {
574
+ if (host._tickledId !== void 0) {
575
+ host._tickledId = void 0;
576
+ vcanvasEl.invalidateAll();
577
+ }
578
+ }, { signal });
579
+ return () => ac.abort();
580
+ };
581
+ const handleHover = (host, vcanvasEl, e) => {
582
+ const ppu = host.pxPerUnit;
583
+ const canvasCoord = vcanvasEl.convertFromViewportToCanvas(e.offsetX, e.offsetY);
584
+ const lx = canvasToTimeline(canvasCoord.x, ppu, host.min);
585
+ const ly = canvasCoord.y;
586
+ const axisTop = vcanvasEl.logicalScrollTop;
587
+ if (ly >= axisTop && ly < axisTop + host.axisHeight) {
588
+ vcanvasEl.style.cursor = `col-resize`;
589
+ if (host._tickledId !== void 0) {
590
+ host._tickledId = void 0;
591
+ vcanvasEl.invalidateAll();
592
+ }
593
+ return;
594
+ }
595
+ const hit = hitTest(lx, ly, host._internalEvents, host._trackLayout, ppu);
596
+ let newTickledId;
597
+ if (hit.kind === `event-move` || hit.kind === `event-start` || hit.kind === `event-end`) newTickledId = hit.eventId;
598
+ if (hit.kind === `event-start` || hit.kind === `event-end`) vcanvasEl.style.cursor = `ew-resize`;
599
+ else if (hit.kind === `event-move`) vcanvasEl.style.cursor = `grab`;
600
+ else vcanvasEl.style.cursor = `crosshair`;
601
+ if (newTickledId !== host._tickledId) {
602
+ host._tickledId = newTickledId;
603
+ vcanvasEl.invalidateAll();
604
+ }
605
+ };
606
+ const toggleSelection = (host, eventId) => {
607
+ const next = new Set(host._selectedIds);
608
+ if (next.has(eventId)) next.delete(eventId);
609
+ else next.add(eventId);
610
+ host._selectedIds = next;
611
+ fireSelectionChange(host);
612
+ host.getVCanvas()?.invalidateAll();
613
+ };
614
+ const fireSelectionChange = (host) => {
615
+ host.dispatchEvent(new CustomEvent(`selection-change`, {
616
+ detail: { selectedIds: [...host._selectedIds] },
617
+ bubbles: true,
618
+ composed: true
619
+ }));
620
+ };
621
+ //#endregion
622
+ //#region src/timeline/timeline-styles.ts
623
+ const timelineStyles = css`
624
+ :host {
625
+ /* Layout */
626
+ --timeline-axis-height: 24px;
627
+ --timeline-tab-width: 120px;
628
+
629
+ /* Backgrounds */
630
+ --timeline-bg: var(--content, #111);
631
+ --timeline-track-bg: var(--surface-2);
632
+ --timeline-track-bg-alt: var(--surface-3);
633
+ --timeline-alt-major-bg: color-mix(in oklch, var(--surface-3) 40%, transparent);
634
+ --timeline-meta-bg: var(--surface-2);
635
+
636
+ /* Grid */
637
+ --timeline-grid-major-color: var(--surface-5);
638
+ --timeline-grid-minor-color: var(--surface-4);
639
+ --timeline-grid-major-width: 1px;
640
+ --timeline-grid-minor-width: 0.5px;
641
+
642
+ /* Events */
643
+ --timeline-event-bg: var(--accent);
644
+ --timeline-event-selected-bg: color-mix(in oklch, var(--accent) 80%, white);
645
+ --timeline-event-tickled-bg: var(--surface-6);
646
+ --timeline-event-label-color: var(--accent-text);
647
+ --timeline-event-radius: var(--radius-s, 4px);
648
+
649
+ /* Tabs */
650
+ --timeline-tab-bg: var(--surface-3);
651
+ --timeline-tab-text: var(--surface-3-text);
652
+ --timeline-tab-selected-bg: var(--accent);
653
+
654
+ /* Axis */
655
+ --timeline-axis-label-color: var(--surface-muted-text);
656
+
657
+ /* Resizer */
658
+ --timeline-resizer-color: var(--surface-5);
659
+
660
+ display: grid;
661
+ grid-template-rows: 1fr auto auto auto;
662
+ background: var(--timeline-bg);
663
+ overflow: hidden;
664
+ position: relative;
665
+ }
666
+
667
+ /* ── Content wrapper ───────────────────────────────────────────────── */
668
+
669
+ .content-wrapper {
670
+ display: grid;
671
+ grid-template-columns: 1fr auto;
672
+ overflow: hidden;
673
+ min-height: 0;
674
+ }
675
+
676
+ /* ── Vertical zoom (right sidebar) ─────────────────────────────────── */
677
+
678
+ .v-zoom {
679
+ padding: 6px 4px;
680
+ padding-top: var(--timeline-axis-height);
681
+ display: flex;
682
+ align-items: stretch;
683
+ width: 30px;
684
+ box-sizing: content-box;
685
+ }
686
+
687
+ .v-zoom ixfx-range-multi {
688
+ height: 100%;
689
+ width: 100%;
690
+ }
691
+
692
+ /* ── Content area ──────────────────────────────────────────────────── */
693
+
694
+ .content-area {
695
+ position: relative;
696
+ display: grid;
697
+ grid-template-columns: var(--timeline-tab-width) 1fr;
698
+ overflow: hidden;
699
+ min-height: 0;
700
+ }
701
+
702
+ /* ── Tab column (sits beside vcanvas) ────────────────────────────── */
703
+
704
+ .tab-column {
705
+ position: relative;
706
+ overflow: hidden;
707
+ z-index: 2;
708
+ }
709
+
710
+ .tab-column ixfx-timeline-track-tab {
711
+ position: absolute;
712
+ left: 0;
713
+ width: 100%;
714
+ box-sizing: border-box;
715
+ pointer-events: auto;
716
+ }
717
+
718
+ /* ── Vertical axis interaction zone ─────────────────────────────────── */
719
+
720
+ .v-axis-zone {
721
+ position: absolute;
722
+ top: 0;
723
+ left: 0;
724
+ width: var(--timeline-tab-width);
725
+ height: 100%;
726
+ cursor: ns-resize;
727
+ z-index: 3;
728
+ }
729
+
730
+ /* ── VCanvas ───────────────────────────────────────────────────────── */
731
+
732
+ .content-area x-vcanvas {
733
+ width: 100%;
734
+ height: 100%;
735
+ display: block;
736
+ --scrollbar-width: none;
737
+ }
738
+
739
+ /* ── Horizontal zoom ───────────────────────────────────────────────── */
740
+
741
+ .h-zoom {
742
+ padding: 4px 8px;
743
+ padding-left: var(--timeline-tab-width);
744
+ padding-right: 38px; /* align with v-zoom column (30px + 2×4px padding) */
745
+ }
746
+
747
+ .h-zoom ixfx-range-multi {
748
+ width: 100%;
749
+ }
750
+
751
+ /* ── Meta area ─────────────────────────────────────────────────────── */
752
+
753
+ .meta-resizer {
754
+ display: none;
755
+ height: 6px;
756
+ cursor: ns-resize;
757
+ background: var(--timeline-resizer-color);
758
+ }
759
+
760
+ .meta-resizer.visible {
761
+ display: block;
762
+ }
763
+
764
+ .meta-area {
765
+ display: none;
766
+ background: var(--timeline-meta-bg);
767
+ overflow: hidden;
768
+ }
769
+
770
+ .meta-area.visible {
771
+ display: block;
772
+ }
773
+ `;
774
+ //#endregion
775
+ //#region src/timeline/timeline-track-tabs.ts
776
+ /** Minimum track height in px */
777
+ const MIN_TRACK_HEIGHT = 24;
778
+ /** How close to the bottom edge the pointer must be (px) to trigger resize */
779
+ const EDGE_ZONE_PX = 6;
780
+ let TimelineTrackTabElement = class TimelineTrackTabElement extends LitElement {
781
+ constructor(..._args) {
782
+ super(..._args);
783
+ this.label = ``;
784
+ this.trackKey = ``;
785
+ this.selected = false;
786
+ this.reorderable = false;
787
+ this.resizable = false;
788
+ this.#dragging = false;
789
+ this.#startScreenY = 0;
790
+ this.#startHeight = 0;
791
+ this.#pointerId = void 0;
792
+ this.#onPointerMove = (e) => {
793
+ if (this.#dragging) {
794
+ const dy = e.screenY - this.#startScreenY;
795
+ const newHeight = Math.max(MIN_TRACK_HEIGHT, this.#startHeight + dy);
796
+ this.#fireResizeEvent(`track-resize-move`, newHeight);
797
+ return;
798
+ }
799
+ if (this.#isInResizeZone(e)) this.style.cursor = `ns-resize`;
800
+ else this.style.cursor = ``;
801
+ };
802
+ this.#onPointerDown = (e) => {
803
+ if (!this.#isInResizeZone(e)) return;
804
+ e.stopPropagation();
805
+ e.preventDefault();
806
+ this.#dragging = true;
807
+ this.#startScreenY = e.screenY;
808
+ this.#startHeight = this.offsetHeight;
809
+ this.#pointerId = e.pointerId;
810
+ this.setPointerCapture(e.pointerId);
811
+ };
812
+ this.#onPointerUp = (e) => {
813
+ if (!this.#dragging) return;
814
+ const dy = e.screenY - this.#startScreenY;
815
+ const finalHeight = Math.max(MIN_TRACK_HEIGHT, this.#startHeight + dy);
816
+ this.#fireResizeEvent(`track-resize`, finalHeight);
817
+ this.#resetDrag(e.pointerId);
818
+ };
819
+ this.#onPointerCancel = (_e) => {
820
+ if (!this.#dragging) return;
821
+ this.#resetDrag(this.#pointerId);
822
+ };
823
+ }
824
+ static {
825
+ this.styles = css`
826
+ :host {
827
+ display: flex;
828
+ align-items: center;
829
+ background: color-mix(in oklch, var(--timeline-tab-bg, #2a2a2a) 70%, transparent);
830
+ backdrop-filter: blur(8px);
831
+ -webkit-backdrop-filter: blur(8px);
832
+ color: var(--timeline-tab-text, #ccc);
833
+ font-size: 0.75rem;
834
+ overflow: hidden;
835
+ white-space: nowrap;
836
+ text-overflow: ellipsis;
837
+ cursor: pointer;
838
+ user-select: none;
839
+ border-bottom: 1px solid var(--timeline-grid-major-color, rgba(255,255,255,0.12));
840
+ box-sizing: border-box;
841
+ position: relative;
842
+ }
843
+
844
+ :host([selected]) {
845
+ background: color-mix(in oklch, var(--timeline-tab-selected-bg, #3498db) 75%, transparent);
846
+ color: white;
847
+ }
848
+
849
+ .handle {
850
+ display: none;
851
+ cursor: grab;
852
+ padding: 0 4px;
853
+ opacity: 0.5;
854
+ font-size: 0.65rem;
855
+ }
856
+
857
+ :host([reorderable]) .handle {
858
+ display: block;
859
+ }
860
+
861
+ .label {
862
+ flex: 1;
863
+ overflow: hidden;
864
+ text-overflow: ellipsis;
865
+ padding: 0 8px;
866
+ }
867
+ `;
868
+ }
869
+ #dragging;
870
+ #startScreenY;
871
+ #startHeight;
872
+ #pointerId;
873
+ connectedCallback() {
874
+ super.connectedCallback();
875
+ this.addEventListener(`pointermove`, this.#onPointerMove);
876
+ this.addEventListener(`pointerdown`, this.#onPointerDown);
877
+ this.addEventListener(`pointerup`, this.#onPointerUp);
878
+ this.addEventListener(`pointercancel`, this.#onPointerCancel);
879
+ this.addEventListener(`lostpointercapture`, this.#onPointerCancel);
880
+ }
881
+ disconnectedCallback() {
882
+ super.disconnectedCallback();
883
+ this.removeEventListener(`pointermove`, this.#onPointerMove);
884
+ this.removeEventListener(`pointerdown`, this.#onPointerDown);
885
+ this.removeEventListener(`pointerup`, this.#onPointerUp);
886
+ this.removeEventListener(`pointercancel`, this.#onPointerCancel);
887
+ this.removeEventListener(`lostpointercapture`, this.#onPointerCancel);
888
+ this.#dragging = false;
889
+ }
890
+ render() {
891
+ return html`
892
+ <span class="handle">\u2630</span>
893
+ <span class="label">${this.label}</span>
894
+ `;
895
+ }
896
+ /** Is the pointer within the bottom edge zone? */
897
+ #isInResizeZone(e) {
898
+ if (!this.resizable) return false;
899
+ const rect = this.getBoundingClientRect();
900
+ return e.clientY >= rect.bottom - EDGE_ZONE_PX;
901
+ }
902
+ #fireResizeEvent(eventName, height) {
903
+ this.dispatchEvent(new CustomEvent(eventName, {
904
+ detail: {
905
+ trackKey: this.trackKey,
906
+ height
907
+ },
908
+ bubbles: true,
909
+ composed: true
910
+ }));
911
+ }
912
+ #onPointerMove;
913
+ #onPointerDown;
914
+ #onPointerUp;
915
+ #onPointerCancel;
916
+ #resetDrag(pointerId) {
917
+ this.#dragging = false;
918
+ this.#startScreenY = 0;
919
+ this.#startHeight = 0;
920
+ if (pointerId !== void 0) try {
921
+ this.releasePointerCapture(pointerId);
922
+ } catch {}
923
+ this.#pointerId = void 0;
924
+ this.style.cursor = ``;
925
+ }
926
+ };
927
+ __decorate([property({ type: String })], TimelineTrackTabElement.prototype, "label", void 0);
928
+ __decorate([property({
929
+ type: String,
930
+ attribute: `track-key`
931
+ })], TimelineTrackTabElement.prototype, "trackKey", void 0);
932
+ __decorate([property({
933
+ type: Boolean,
934
+ reflect: true
935
+ })], TimelineTrackTabElement.prototype, "selected", void 0);
936
+ __decorate([property({
937
+ type: Boolean,
938
+ reflect: true
939
+ })], TimelineTrackTabElement.prototype, "reorderable", void 0);
940
+ __decorate([property({
941
+ type: Boolean,
942
+ reflect: true
943
+ })], TimelineTrackTabElement.prototype, "resizable", void 0);
944
+ TimelineTrackTabElement = __decorate([safeCustomElement(`ixfx-timeline-track-tab`)], TimelineTrackTabElement);
945
+ //#endregion
946
+ //#region src/timeline/timeline-element.ts
947
+ /** Reasonable maximum ppu to prevent infinite zoom-in */
948
+ const MAX_PPU = 1e4;
949
+ /** Minimum rendered track height (~1.5em) at max zoom-out */
950
+ const MIN_TRACK_RENDER_HEIGHT = 24;
951
+ let IxfxTimelineElement = class IxfxTimelineElement extends LitElement {
952
+ constructor(..._args) {
953
+ super(..._args);
954
+ this.tracks = [];
955
+ this.events = [];
956
+ this.min = 0;
957
+ this.max = 1e3;
958
+ this.trackHeight = `fixed`;
959
+ this.userScale = `normal`;
960
+ this.reorderable = false;
961
+ this.metaEnabled = false;
962
+ this.altMajorBg = false;
963
+ this.defaultTrackHeight = 48;
964
+ this.gridMode = `adaptive`;
965
+ this.minorStep = 10;
966
+ this.onDragging = null;
967
+ this.formatLabel = String;
968
+ this._ppu = 1;
969
+ this._viewRange = {
970
+ min: 0,
971
+ max: 4e3
972
+ };
973
+ this._vViewRange = {
974
+ min: 0,
975
+ max: 1
976
+ };
977
+ this._vScale = 1;
978
+ this._selectedIds = /* @__PURE__ */ new Set();
979
+ this._tickledId = void 0;
980
+ this._drag = { kind: `none` };
981
+ this._metaHeight = 120;
982
+ this._trackHeightOverrides = /* @__PURE__ */ new Map();
983
+ this._trackLayout = [];
984
+ this._internalEvents = [];
985
+ this._internalTracks = [];
986
+ this.#vcanvas = null;
987
+ this.#cssVarsCache = {};
988
+ this.#cleanupInteractions = null;
989
+ this.#axisHeight = 24;
990
+ this.#prevTickledId = void 0;
991
+ this.#resizeObserver = null;
992
+ this.#pendingVerticalZoomToFit = false;
993
+ this.#hasInitializedZoom = false;
994
+ this.#onResize = (_entries) => {
995
+ if (!this.#hasInitializedZoom) {
996
+ this.#hasInitializedZoom = true;
997
+ this.#initZoomToFit();
998
+ this.#initVerticalZoomToFit();
999
+ this.#recomputeTrackLayout();
1000
+ } else {
1001
+ this._viewRange = this.#deriveViewRange(this._viewRange.min, this._ppu);
1002
+ this.#deriveVerticalZoom(this._vViewRange.min, this._vViewRange.max);
1003
+ }
1004
+ this.#syncVCanvas();
1005
+ this.#invalidateCanvas();
1006
+ };
1007
+ this.#drawCallback = (ctx, region, _signal) => {
1008
+ const ppu = this._ppu;
1009
+ const logicalRegion = {
1010
+ x: region.x / ppu + this.min,
1011
+ y: region.y,
1012
+ width: region.width / ppu,
1013
+ height: region.height
1014
+ };
1015
+ this.#cssVarsCache = resolveCssVars(this);
1016
+ const grid = resolveGrid(this._viewRange, this.userScale, this.#getViewportWidth(), this.gridMode, this.minorStep, ppu);
1017
+ const trackInfos = this._internalTracks.map((t) => ({
1018
+ key: t.key,
1019
+ color: t.color
1020
+ }));
1021
+ drawTrackBackgrounds(ctx, logicalRegion, this._trackLayout, trackInfos, this.#cssVarsCache, ppu);
1022
+ drawMajorMinorGrid(ctx, logicalRegion, grid, this.altMajorBg, this.#cssVarsCache, ppu);
1023
+ drawEventRects(ctx, logicalRegion, this._internalEvents, this._trackLayout, this._selectedIds, this._tickledId, this._drag, this.#cssVarsCache, ppu);
1024
+ drawMarquee(ctx, this._drag, ppu);
1025
+ const scrollTop = this.#vcanvas?.logicalScrollTop ?? 0;
1026
+ drawAxis(ctx, logicalRegion, grid, this.#axisHeight, this.formatLabel, this.#cssVarsCache, ppu, scrollTop);
1027
+ };
1028
+ this.#onScrollVirtual = (e) => {
1029
+ const detail = e.detail;
1030
+ if (detail.userGesture === false) return;
1031
+ const ppu = this._ppu;
1032
+ if (ppu <= 0) return;
1033
+ const viewMin = detail.logicalScrollLeft / ppu + this.min;
1034
+ this._viewRange = this.#deriveViewRange(viewMin, ppu);
1035
+ if (this._vScale > 0) {
1036
+ const span = this._vViewRange.max - this._vViewRange.min;
1037
+ const newVMin = detail.logicalScrollTop / this._vScale;
1038
+ this.#deriveVerticalZoom(newVMin, newVMin + span);
1039
+ }
1040
+ };
1041
+ this.#onHZoomInput = (e) => {
1042
+ const detail = e.detail;
1043
+ const span = detail.b - detail.a;
1044
+ const vpWidth = this.#getViewportWidth();
1045
+ if (span > 0) this._ppu = Math.max(this.#minPpu(), Math.min(vpWidth / span, MAX_PPU));
1046
+ this._viewRange = this.#deriveViewRange(detail.a, this._ppu);
1047
+ this.#syncVCanvas();
1048
+ };
1049
+ this.#onVZoomInput = (e) => {
1050
+ const detail = e.detail;
1051
+ this.#deriveVerticalZoom(detail.a, detail.b);
1052
+ };
1053
+ this.#onVAxisPointerDown = (e) => {
1054
+ const zone = e.currentTarget;
1055
+ zone.setPointerCapture(e.pointerId);
1056
+ e.stopPropagation();
1057
+ e.preventDefault();
1058
+ const rect = zone.getBoundingClientRect();
1059
+ const clickFrac = rect.height > 0 ? (e.clientY - rect.top) / rect.height : .5;
1060
+ const span = this._vViewRange.max - this._vViewRange.min;
1061
+ const anchorBaseY = this._vViewRange.min + clickFrac * span;
1062
+ this._drag = {
1063
+ kind: `v-axis-zoom`,
1064
+ anchorBaseY,
1065
+ startScreenX: e.screenX,
1066
+ startScreenY: e.screenY,
1067
+ startVMin: this._vViewRange.min,
1068
+ startVMax: this._vViewRange.max,
1069
+ startVScale: this._vScale
1070
+ };
1071
+ };
1072
+ this.#onVAxisPointerMove = (e) => {
1073
+ if (this._drag.kind !== `v-axis-zoom`) return;
1074
+ const drag = this._drag;
1075
+ const rawDx = e.screenX - drag.startScreenX;
1076
+ const rawDy = e.screenY - drag.startScreenY;
1077
+ if (Math.abs(rawDx) + Math.abs(rawDy) < 5) return;
1078
+ const dx = applyDeadzone(rawDx, 4);
1079
+ const dy = applyDeadzone(rawDy, 4);
1080
+ const result = computeVerticalAxisZoom(drag.startVMin, drag.startVMax, drag.startVScale, drag.anchorBaseY, dx, dy);
1081
+ this.setVerticalZoomPan(result.vMin, result.vMax);
1082
+ };
1083
+ this.#onVAxisPointerUp = (e) => {
1084
+ if (this._drag.kind !== `v-axis-zoom`) return;
1085
+ e.currentTarget.releasePointerCapture(e.pointerId);
1086
+ this._drag = { kind: `none` };
1087
+ };
1088
+ this.#onTrackResizeMove = (e) => {
1089
+ const { trackKey, height } = e.detail;
1090
+ this.#applyTrackResize(trackKey, height);
1091
+ };
1092
+ this.#onTrackResizeEnd = (e) => {
1093
+ const { trackKey, height } = e.detail;
1094
+ this.#applyTrackResize(trackKey, height);
1095
+ this.dispatchEvent(new CustomEvent(`track-resize`, {
1096
+ detail: {
1097
+ trackKey,
1098
+ height
1099
+ },
1100
+ bubbles: true,
1101
+ composed: true
1102
+ }));
1103
+ };
1104
+ }
1105
+ static {
1106
+ this.styles = [timelineStyles];
1107
+ }
1108
+ #vcanvas;
1109
+ #cssVarsCache;
1110
+ #cleanupInteractions;
1111
+ #axisHeight;
1112
+ #prevTickledId;
1113
+ #resizeObserver;
1114
+ #pendingVerticalZoomToFit;
1115
+ #hasInitializedZoom;
1116
+ /** Pixels per logical unit — the zoom level */
1117
+ get pxPerUnit() {
1118
+ return this._ppu;
1119
+ }
1120
+ /** Height of the axis header band in pixels */
1121
+ get axisHeight() {
1122
+ return this.#axisHeight;
1123
+ }
1124
+ /** Width of the track tab area in pixels (from --timeline-tab-width CSS var) */
1125
+ get tabWidth() {
1126
+ return this.#tabWidth;
1127
+ }
1128
+ #getViewportWidth() {
1129
+ return this.#vcanvas?.viewportWidth ?? this.#vcanvas?.clientWidth ?? 800;
1130
+ }
1131
+ /** Minimum ppu: fits the full total range into the viewport */
1132
+ #minPpu() {
1133
+ const totalSpan = this.max - this.min;
1134
+ if (totalSpan <= 0) return 1;
1135
+ return this.#getViewportWidth() / totalSpan;
1136
+ }
1137
+ /** Available vertical pixels for track content (excludes axis) */
1138
+ #getViewportHeight() {
1139
+ return this.#vcanvas?.viewportHeight ?? this.#vcanvas?.clientHeight ?? 300;
1140
+ }
1141
+ /**
1142
+ * Total base height: sum of all visible track base heights (before vScale).
1143
+ * This is the "total range" for the vertical slider.
1144
+ */
1145
+ #getTotalBaseHeight() {
1146
+ let total = 0;
1147
+ for (const track of this._internalTracks) {
1148
+ if (track.hidden) continue;
1149
+ const override = this._trackHeightOverrides.get(track.key);
1150
+ total += override ?? track.height ?? this.defaultTrackHeight;
1151
+ }
1152
+ return total || 1;
1153
+ }
1154
+ /** Smallest base height among visible tracks (before vScale) */
1155
+ #getSmallestBaseTrackHeight() {
1156
+ let smallest = Infinity;
1157
+ for (const track of this._internalTracks) {
1158
+ if (track.hidden) continue;
1159
+ const h = this._trackHeightOverrides.get(track.key) ?? track.height ?? this.defaultTrackHeight;
1160
+ if (h < smallest) smallest = h;
1161
+ }
1162
+ return smallest === Infinity ? this.defaultTrackHeight : smallest;
1163
+ }
1164
+ /** Largest base height among visible tracks (before vScale) */
1165
+ #getLargestBaseTrackHeight() {
1166
+ let largest = 0;
1167
+ for (const track of this._internalTracks) {
1168
+ if (track.hidden) continue;
1169
+ const h = this._trackHeightOverrides.get(track.key) ?? track.height ?? this.defaultTrackHeight;
1170
+ if (h > largest) largest = h;
1171
+ }
1172
+ return largest || this.defaultTrackHeight;
1173
+ }
1174
+ /**
1175
+ * Derive vScale and vViewRange from a given vertical view range.
1176
+ * viewportHeight / span = scale factor applied to base track heights.
1177
+ * The axis header takes up fixed space, so available height for tracks is reduced.
1178
+ */
1179
+ #deriveVerticalZoom(vMin, vMax) {
1180
+ const totalBase = this.#getTotalBaseHeight();
1181
+ const vpHeight = this.#getViewportHeight() - this.#axisHeight;
1182
+ let a = vMin;
1183
+ let b = vMax;
1184
+ const largestBase = this.#getLargestBaseTrackHeight();
1185
+ const minSpan = Math.max(largestBase, totalBase * .05);
1186
+ const smallestBase = this.#getSmallestBaseTrackHeight();
1187
+ const maxSpanFromMinHeight = vpHeight > 0 ? vpHeight * smallestBase / MIN_TRACK_RENDER_HEIGHT : totalBase;
1188
+ const maxSpan = Math.min(totalBase, maxSpanFromMinHeight);
1189
+ let span = b - a;
1190
+ if (span < minSpan) {
1191
+ const center = (a + b) / 2;
1192
+ a = center - minSpan / 2;
1193
+ b = center + minSpan / 2;
1194
+ span = minSpan;
1195
+ }
1196
+ if (span > maxSpan) {
1197
+ const center = (a + b) / 2;
1198
+ a = center - maxSpan / 2;
1199
+ b = center + maxSpan / 2;
1200
+ span = maxSpan;
1201
+ }
1202
+ if (b > totalBase) {
1203
+ b = totalBase;
1204
+ a = Math.max(0, b - span);
1205
+ }
1206
+ if (a < 0) {
1207
+ a = 0;
1208
+ b = Math.min(totalBase, a + span);
1209
+ }
1210
+ this._vViewRange = {
1211
+ min: a,
1212
+ max: b
1213
+ };
1214
+ this._vScale = vpHeight > 0 ? vpHeight / (b - a) : 1;
1215
+ }
1216
+ /** Reset vertical zoom to fit all tracks */
1217
+ #initVerticalZoomToFit() {
1218
+ const totalBase = this.#getTotalBaseHeight();
1219
+ this.#deriveVerticalZoom(0, totalBase);
1220
+ }
1221
+ /** Pixel offset to scroll the content area */
1222
+ get #vScrollOffset() {
1223
+ return this._vViewRange.min * this._vScale;
1224
+ }
1225
+ /**
1226
+ * Derive viewRange from ppu + viewMin, clamped to [min, max].
1227
+ * Returns a new ViewRange.
1228
+ */
1229
+ #deriveViewRange(viewMin, ppu) {
1230
+ const vpWidth = this.#getViewportWidth();
1231
+ const viewSpan = ppu > 0 ? vpWidth / ppu : this.max - this.min;
1232
+ let newMin = viewMin;
1233
+ let newMax = newMin + viewSpan;
1234
+ if (newMax > this.max) {
1235
+ newMax = this.max;
1236
+ newMin = Math.max(this.min, newMax - viewSpan);
1237
+ }
1238
+ if (newMin < this.min) {
1239
+ newMin = this.min;
1240
+ newMax = Math.min(this.max, newMin + viewSpan);
1241
+ }
1242
+ return {
1243
+ min: newMin,
1244
+ max: newMax
1245
+ };
1246
+ }
1247
+ /** Set the zoom level (pixels per logical unit) */
1248
+ setPpu(ppu) {
1249
+ this._ppu = Math.max(this.#minPpu(), Math.min(ppu, MAX_PPU));
1250
+ this._viewRange = this.#deriveViewRange(this._viewRange.min, this._ppu);
1251
+ }
1252
+ /**
1253
+ * Set the view range. ppu is back-computed from the span.
1254
+ * Use for programmatic view changes (e.g. TimelineController).
1255
+ */
1256
+ setViewRange(range) {
1257
+ const vpWidth = this.#getViewportWidth();
1258
+ const span = range.max - range.min;
1259
+ if (span > 0) this._ppu = Math.max(this.#minPpu(), Math.min(vpWidth / span, MAX_PPU));
1260
+ this._viewRange = this.#deriveViewRange(range.min, this._ppu);
1261
+ }
1262
+ /**
1263
+ * Set zoom + pan atomically. Used by axis-zoom interaction.
1264
+ * viewMin is the left edge in timeline units; ppu is the new zoom level.
1265
+ */
1266
+ setZoomPan(viewMin, ppu) {
1267
+ this._ppu = Math.max(this.#minPpu(), Math.min(ppu, MAX_PPU));
1268
+ this._viewRange = this.#deriveViewRange(viewMin, this._ppu);
1269
+ }
1270
+ /**
1271
+ * Set vertical zoom + pan atomically. Used by v-axis-zoom interaction.
1272
+ * vMin/vMax define the vertical view range in base-height units.
1273
+ */
1274
+ setVerticalZoomPan(vMin, vMax) {
1275
+ this.#deriveVerticalZoom(vMin, vMax);
1276
+ }
1277
+ selectAll() {
1278
+ this._selectedIds = new Set(this._internalEvents.map((e) => e.id));
1279
+ this.#fireSelectionChange();
1280
+ this.#invalidateCanvas();
1281
+ }
1282
+ deselectAll() {
1283
+ this._selectedIds = /* @__PURE__ */ new Set();
1284
+ this.#fireSelectionChange();
1285
+ this.#invalidateCanvas();
1286
+ }
1287
+ getTrackEvents(trackKey) {
1288
+ return this._internalEvents.filter((e) => e.trackKey === trackKey);
1289
+ }
1290
+ get selectedIds() {
1291
+ return [...this._selectedIds];
1292
+ }
1293
+ set selectedIds(ids) {
1294
+ this._selectedIds = new Set(ids);
1295
+ this.#fireSelectionChange();
1296
+ this.#invalidateCanvas();
1297
+ }
1298
+ selectTrack(key, shiftKey = false) {
1299
+ this.dispatchEvent(new CustomEvent(`track-select`, {
1300
+ detail: {
1301
+ trackKey: key,
1302
+ shiftKey
1303
+ },
1304
+ bubbles: true,
1305
+ composed: true
1306
+ }));
1307
+ }
1308
+ /** Resets all track height overrides to the default height and resets vertical zoom. */
1309
+ resetTrackHeights() {
1310
+ this._trackHeightOverrides = /* @__PURE__ */ new Map();
1311
+ this.#pendingVerticalZoomToFit = true;
1312
+ }
1313
+ static {
1314
+ this.defaultDragSnapping = () => ({});
1315
+ }
1316
+ static {
1317
+ this.gridSnapping = (detail) => {
1318
+ const { gridResolution, currentStart, currentEnd } = detail;
1319
+ const { minorStep } = gridResolution;
1320
+ return {
1321
+ start: Math.round(currentStart / minorStep) * minorStep,
1322
+ end: Math.round(currentEnd / minorStep) * minorStep
1323
+ };
1324
+ };
1325
+ }
1326
+ /**
1327
+ * Called by timeline-interactions during drag.
1328
+ * Applies onDragging callback if set, then fires 'dragging' event.
1329
+ * Returns constrained values.
1330
+ */
1331
+ processDrag(eventId, rawLogicalX, rawY, currentStart, currentEnd, currentTrackKey, originTrackKey, gridResolution) {
1332
+ let constrainedStart = currentStart;
1333
+ let constrainedEnd = currentEnd;
1334
+ let constrainedTrackKey = currentTrackKey;
1335
+ if (this.onDragging) {
1336
+ const result = this.onDragging({
1337
+ eventId,
1338
+ rawLogicalX,
1339
+ rawY,
1340
+ currentStart,
1341
+ currentEnd,
1342
+ currentTrackKey,
1343
+ gridResolution,
1344
+ originTrackKey
1345
+ });
1346
+ constrainedStart = result.start ?? currentStart;
1347
+ constrainedEnd = result.end ?? currentEnd;
1348
+ constrainedTrackKey = result.trackKey ?? currentTrackKey;
1349
+ }
1350
+ this.dispatchEvent(new CustomEvent(`dragging`, {
1351
+ detail: {
1352
+ eventId,
1353
+ start: constrainedStart,
1354
+ end: constrainedEnd,
1355
+ trackKey: constrainedTrackKey,
1356
+ rawLogicalX,
1357
+ rawY,
1358
+ originTrackKey
1359
+ },
1360
+ bubbles: true,
1361
+ composed: true
1362
+ }));
1363
+ return {
1364
+ start: constrainedStart,
1365
+ end: constrainedEnd,
1366
+ trackKey: constrainedTrackKey
1367
+ };
1368
+ }
1369
+ /** Returns the vcanvas element (for timeline-interactions) */
1370
+ getVCanvas() {
1371
+ return this.#vcanvas;
1372
+ }
1373
+ /** Returns the currently hovered (tickled) event, or null if none. */
1374
+ get tickledEvent() {
1375
+ if (this._tickledId === void 0) return null;
1376
+ return this._internalEvents.find((e) => e.id === this._tickledId) ?? null;
1377
+ }
1378
+ firstUpdated() {
1379
+ this.#vcanvas = this.shadowRoot?.querySelector(`x-vcanvas`);
1380
+ if (this.#vcanvas) {
1381
+ this.#vcanvas.drawCallback = this.#drawCallback;
1382
+ this.#vcanvas.addEventListener(`scroll-virtual`, this.#onScrollVirtual);
1383
+ this.#cleanupInteractions = attachTimelineInteractions(this, this.#vcanvas);
1384
+ this.#resizeObserver = new ResizeObserver(this.#onResize);
1385
+ this.#resizeObserver.observe(this.#vcanvas);
1386
+ }
1387
+ }
1388
+ disconnectedCallback() {
1389
+ super.disconnectedCallback();
1390
+ this.#cleanupInteractions?.();
1391
+ this.#cleanupInteractions = null;
1392
+ this.#resizeObserver?.disconnect();
1393
+ this.#resizeObserver = null;
1394
+ }
1395
+ /**
1396
+ * willUpdate runs before render — safe to set @state() properties here
1397
+ * without triggering an additional update cycle. All state derivation
1398
+ * (internal copies, track layout, vertical zoom) happens here.
1399
+ */
1400
+ willUpdate(changedProps) {
1401
+ let needsLayoutRecompute = false;
1402
+ let needsVerticalZoomReset = false;
1403
+ let needsHorizontalZoomToFit = false;
1404
+ if (changedProps.has(`tracks`)) {
1405
+ this._internalTracks = [...this.tracks];
1406
+ needsLayoutRecompute = true;
1407
+ needsVerticalZoomReset = true;
1408
+ }
1409
+ if (changedProps.has(`events`)) this._internalEvents = [...this.events];
1410
+ if (changedProps.has(`trackHeight`)) {
1411
+ if (this.trackHeight !== `free` && this._trackHeightOverrides.size > 0) this._trackHeightOverrides = /* @__PURE__ */ new Map();
1412
+ needsLayoutRecompute = true;
1413
+ needsVerticalZoomReset = true;
1414
+ }
1415
+ if (changedProps.has(`_vScale`) || changedProps.has(`defaultTrackHeight`) || changedProps.has(`_trackHeightOverrides`)) needsLayoutRecompute = true;
1416
+ if (changedProps.has(`min`) || changedProps.has(`max`)) needsHorizontalZoomToFit = true;
1417
+ if (this.#pendingVerticalZoomToFit) {
1418
+ this.#pendingVerticalZoomToFit = false;
1419
+ needsVerticalZoomReset = true;
1420
+ }
1421
+ if (needsHorizontalZoomToFit) this.#initZoomToFit();
1422
+ if (needsVerticalZoomReset) this.#initVerticalZoomToFit();
1423
+ if (needsLayoutRecompute) this.#recomputeTrackLayout();
1424
+ }
1425
+ /**
1426
+ * updated runs after render — for DOM side-effects only (syncing vcanvas,
1427
+ * scrolling, invalidating canvas, dispatching events).
1428
+ */
1429
+ updated(changedProps) {
1430
+ if (changedProps.has(`_ppu`) || changedProps.has(`_viewRange`) || changedProps.has(`min`) || changedProps.has(`max`)) {
1431
+ this.#syncVCanvas();
1432
+ this.#invalidateCanvas();
1433
+ }
1434
+ if (changedProps.has(`events`) || changedProps.has(`userScale`) || changedProps.has(`altMajorBg`) || changedProps.has(`gridMode`) || changedProps.has(`minorStep`)) this.#invalidateCanvas();
1435
+ if (changedProps.has(`_trackLayout`)) {
1436
+ this.#syncVCanvasVertical();
1437
+ this.#positionTabs();
1438
+ this.#invalidateCanvas();
1439
+ }
1440
+ if (changedProps.has(`_vViewRange`) || changedProps.has(`_vScale`)) {
1441
+ this.#syncVerticalScroll();
1442
+ this.#invalidateCanvas();
1443
+ }
1444
+ if (this._tickledId !== this.#prevTickledId) {
1445
+ this.#prevTickledId = this._tickledId;
1446
+ this.dispatchEvent(new CustomEvent(`tickle-change`, {
1447
+ detail: { event: this.tickledEvent },
1448
+ bubbles: true,
1449
+ composed: true
1450
+ }));
1451
+ }
1452
+ }
1453
+ render() {
1454
+ const totalBaseHeight = this.#getTotalBaseHeight();
1455
+ return html`
1456
+ <div class="content-wrapper">
1457
+ <div class="content-area">
1458
+ <div class="v-axis-zone"
1459
+ @pointerdown=${this.#onVAxisPointerDown}
1460
+ @pointermove=${this.#onVAxisPointerMove}
1461
+ @pointerup=${this.#onVAxisPointerUp}
1462
+ @pointercancel=${this.#onVAxisPointerUp}
1463
+ ></div>
1464
+ <div class="tab-column">
1465
+ ${this._internalTracks.filter((t) => !t.hidden).map((t) => {
1466
+ if (!this._trackLayout.find((l) => l.trackKey === t.key)) return nothing;
1467
+ return html`
1468
+ <ixfx-timeline-track-tab
1469
+ .label=${t.label}
1470
+ track-key="${t.key}"
1471
+ ?resizable=${this.trackHeight !== `none`}
1472
+ ?reorderable=${this.reorderable}
1473
+ @click=${(e) => this.selectTrack(t.key, e.shiftKey)}
1474
+ @track-resize-move=${this.#onTrackResizeMove}
1475
+ @track-resize=${this.#onTrackResizeEnd}
1476
+ ></ixfx-timeline-track-tab>
1477
+ `;
1478
+ })}
1479
+ </div>
1480
+ <x-vcanvas></x-vcanvas>
1481
+ </div>
1482
+ <div class="v-zoom">
1483
+ <ixfx-range-multi
1484
+ orientation="vertical"
1485
+ min="0"
1486
+ max="${totalBaseHeight}"
1487
+ a="${this._vViewRange.min}"
1488
+ b="${this._vViewRange.max}"
1489
+ step="any"
1490
+ crossover="stop"
1491
+ resize-mode="bipolar-flex"
1492
+ @input=${this.#onVZoomInput}
1493
+ ></ixfx-range-multi>
1494
+ </div>
1495
+ </div>
1496
+
1497
+ <div class="h-zoom">
1498
+ <ixfx-range-multi
1499
+ min="${this.min}"
1500
+ max="${this.max}"
1501
+ a="${this._viewRange.min}"
1502
+ b="${this._viewRange.max}"
1503
+ crossover="stop"
1504
+ resize-mode="bipolar-flex"
1505
+ @input=${this.#onHZoomInput}
1506
+ ></ixfx-range-multi>
1507
+ </div>
1508
+
1509
+ <div class="meta-resizer ${this.metaEnabled ? `visible` : ``}"></div>
1510
+ <div class="meta-area ${this.metaEnabled ? `visible` : ``}" style="height:${this._metaHeight}px"></div>
1511
+ `;
1512
+ }
1513
+ /** Compute initial ppu to fit 80% of the range, then derive viewRange */
1514
+ #initZoomToFit() {
1515
+ const vpWidth = this.#getViewportWidth();
1516
+ const totalSpan = this.max - this.min;
1517
+ const zoomFactor = .8;
1518
+ this._ppu = totalSpan > 0 ? vpWidth / (totalSpan * zoomFactor) : 1;
1519
+ this._viewRange = {
1520
+ min: this.min,
1521
+ max: this.min + totalSpan * zoomFactor
1522
+ };
1523
+ this.#syncVCanvas();
1524
+ }
1525
+ #syncVCanvas() {
1526
+ if (!this.#vcanvas) return;
1527
+ const totalSpan = this.max - this.min;
1528
+ this.#vcanvas.logicalWidth = totalSpan * this._ppu;
1529
+ this.#syncVCanvasVertical();
1530
+ this.#syncVCanvasScroll();
1531
+ }
1532
+ /** Sync logicalHeight and logicalScrollTop to the vcanvas */
1533
+ #syncVCanvasVertical() {
1534
+ if (!this.#vcanvas) return;
1535
+ const totalHeight = this._trackLayout.reduce((sum, tl) => sum + tl.height, 0);
1536
+ const canvasHeight = Math.max(totalHeight, 40) + this.#axisHeight;
1537
+ this.#vcanvas.logicalHeight = canvasHeight;
1538
+ this.#vcanvas.logicalScrollTop = this.#vScrollOffset;
1539
+ }
1540
+ #syncVCanvasScroll() {
1541
+ if (!this.#vcanvas) return;
1542
+ this.#vcanvas.logicalScrollLeft = (this._viewRange.min - this.min) * this._ppu;
1543
+ }
1544
+ #invalidateCanvas() {
1545
+ this.#vcanvas?.invalidateAll();
1546
+ }
1547
+ /** Called by ResizeObserver when vcanvas/content-area changes size */
1548
+ #onResize;
1549
+ #drawCallback;
1550
+ #onScrollVirtual;
1551
+ #recomputeTrackLayout() {
1552
+ const layout = [];
1553
+ let y = this.#axisHeight;
1554
+ for (const track of this._internalTracks) {
1555
+ if (track.hidden) continue;
1556
+ const baseHeight = this._trackHeightOverrides.get(track.key) ?? track.height ?? this.defaultTrackHeight;
1557
+ const height = Math.round(baseHeight * this._vScale);
1558
+ layout.push({
1559
+ trackKey: track.key,
1560
+ y,
1561
+ height
1562
+ });
1563
+ y += height;
1564
+ }
1565
+ this._trackLayout = layout;
1566
+ }
1567
+ /**
1568
+ * Range slider handler.
1569
+ * Slider controls zoom (via span) + pan (via position).
1570
+ * Derive ppu from the span the slider produces.
1571
+ */
1572
+ #onHZoomInput;
1573
+ /**
1574
+ * Vertical range slider handler.
1575
+ * Slider controls vertical zoom (via span) + vertical pan (via position).
1576
+ * Derive _vScale from the span the slider produces.
1577
+ */
1578
+ #onVZoomInput;
1579
+ #onVAxisPointerDown;
1580
+ #onVAxisPointerMove;
1581
+ #onVAxisPointerUp;
1582
+ /** Sync vertical scroll position to vcanvas logicalScrollTop */
1583
+ #syncVerticalScroll() {
1584
+ this.#syncVCanvasVertical();
1585
+ this.#positionTabs();
1586
+ }
1587
+ /**
1588
+ * Position track tabs in the .tab-column via absolute CSS positioning.
1589
+ * Applies a vertical translateY to offset for the current vertical scroll.
1590
+ */
1591
+ #positionTabs() {
1592
+ const tabColumn = this.shadowRoot?.querySelector(`.tab-column`);
1593
+ if (!tabColumn) return;
1594
+ const scrollTop = this.#vcanvas?.logicalScrollTop ?? 0;
1595
+ tabColumn.style.transform = `translateY(${-scrollTop}px)`;
1596
+ for (const layout of this._trackLayout) {
1597
+ const tab = tabColumn.querySelector(`ixfx-timeline-track-tab[track-key="${layout.trackKey}"]`);
1598
+ if (!tab) continue;
1599
+ tab.style.top = `${layout.y}px`;
1600
+ tab.style.height = `${layout.height}px`;
1601
+ }
1602
+ }
1603
+ /** Read the tab width from the CSS custom property */
1604
+ get #tabWidth() {
1605
+ const raw = getComputedStyle(this).getPropertyValue(`--timeline-tab-width`).trim();
1606
+ return Number.parseInt(raw, 10) || 120;
1607
+ }
1608
+ /** Live preview during drag — update heights but don't fire public event */
1609
+ #onTrackResizeMove;
1610
+ /** Final resize on pointerup — apply height and fire public event */
1611
+ #onTrackResizeEnd;
1612
+ /**
1613
+ * Apply track height based on the current `trackHeight` mode.
1614
+ * - `fixed`: sets `defaultTrackHeight` (all tracks change uniformly)
1615
+ * - `free`: sets per-track override in `_trackHeightOverrides`
1616
+ * - `none`: should never be called (resize is disabled)
1617
+ */
1618
+ #applyTrackResize(trackKey, height) {
1619
+ if (this.trackHeight === `fixed`) this.defaultTrackHeight = height;
1620
+ else if (this.trackHeight === `free`) {
1621
+ const next = new Map(this._trackHeightOverrides);
1622
+ next.set(trackKey, height);
1623
+ this._trackHeightOverrides = next;
1624
+ }
1625
+ }
1626
+ #fireSelectionChange() {
1627
+ this.dispatchEvent(new CustomEvent(`selection-change`, {
1628
+ detail: { selectedIds: [...this._selectedIds] },
1629
+ bubbles: true,
1630
+ composed: true
1631
+ }));
1632
+ }
1633
+ };
1634
+ __decorate([property({ type: Array })], IxfxTimelineElement.prototype, "tracks", void 0);
1635
+ __decorate([property({ type: Array })], IxfxTimelineElement.prototype, "events", void 0);
1636
+ __decorate([property({ type: Number })], IxfxTimelineElement.prototype, "min", void 0);
1637
+ __decorate([property({ type: Number })], IxfxTimelineElement.prototype, "max", void 0);
1638
+ __decorate([property({
1639
+ type: String,
1640
+ attribute: `track-height`
1641
+ })], IxfxTimelineElement.prototype, "trackHeight", void 0);
1642
+ __decorate([property({
1643
+ type: String,
1644
+ attribute: `user-scale`
1645
+ })], IxfxTimelineElement.prototype, "userScale", void 0);
1646
+ __decorate([property({ type: Boolean })], IxfxTimelineElement.prototype, "reorderable", void 0);
1647
+ __decorate([property({
1648
+ type: Boolean,
1649
+ attribute: `meta`
1650
+ })], IxfxTimelineElement.prototype, "metaEnabled", void 0);
1651
+ __decorate([property({
1652
+ type: Boolean,
1653
+ attribute: `alt-major-bg`
1654
+ })], IxfxTimelineElement.prototype, "altMajorBg", void 0);
1655
+ __decorate([property({
1656
+ type: Number,
1657
+ attribute: `default-track-height`
1658
+ })], IxfxTimelineElement.prototype, "defaultTrackHeight", void 0);
1659
+ __decorate([property({
1660
+ type: String,
1661
+ attribute: `grid-mode`
1662
+ })], IxfxTimelineElement.prototype, "gridMode", void 0);
1663
+ __decorate([property({
1664
+ type: Number,
1665
+ attribute: `minor-step`
1666
+ })], IxfxTimelineElement.prototype, "minorStep", void 0);
1667
+ __decorate([property({ type: Object })], IxfxTimelineElement.prototype, "onDragging", void 0);
1668
+ __decorate([state()], IxfxTimelineElement.prototype, "_ppu", void 0);
1669
+ __decorate([state()], IxfxTimelineElement.prototype, "_viewRange", void 0);
1670
+ __decorate([state()], IxfxTimelineElement.prototype, "_vViewRange", void 0);
1671
+ __decorate([state()], IxfxTimelineElement.prototype, "_vScale", void 0);
1672
+ __decorate([state()], IxfxTimelineElement.prototype, "_selectedIds", void 0);
1673
+ __decorate([state()], IxfxTimelineElement.prototype, "_tickledId", void 0);
1674
+ __decorate([state()], IxfxTimelineElement.prototype, "_drag", void 0);
1675
+ __decorate([state()], IxfxTimelineElement.prototype, "_metaHeight", void 0);
1676
+ __decorate([state()], IxfxTimelineElement.prototype, "_trackHeightOverrides", void 0);
1677
+ __decorate([state()], IxfxTimelineElement.prototype, "_trackLayout", void 0);
1678
+ __decorate([state()], IxfxTimelineElement.prototype, "_internalEvents", void 0);
1679
+ __decorate([state()], IxfxTimelineElement.prototype, "_internalTracks", void 0);
1680
+ IxfxTimelineElement = __decorate([safeCustomElement(`ixfx-timeline`)], IxfxTimelineElement);
1681
+ //#endregion
1682
+ //#region src/timeline/timeline-controller.ts
1683
+ /**
1684
+ * External adapter class that can configure a timeline element
1685
+ * with musical time, custom label formatting, etc.
1686
+ *
1687
+ * The controller has no import of any timeline element type.
1688
+ * Users create a controller, pass it the component instance,
1689
+ * and the controller calls the component's public API.
1690
+ */
1691
+ var TimelineController = class {
1692
+ #host;
1693
+ #config;
1694
+ #bpm = 120;
1695
+ #timeSignatureNumerator = 4;
1696
+ #timeSignatureDenominator = 4;
1697
+ constructor(timeline, config) {
1698
+ this.#host = timeline;
1699
+ this.#config = config;
1700
+ timeline.min = config.logicalMin;
1701
+ timeline.max = config.logicalMax;
1702
+ if (config.labelFormatter) timeline.formatLabel = config.labelFormatter;
1703
+ timeline.addEventListener(`track-select`, this.#onTrackSelect);
1704
+ }
1705
+ /** Update the tempo (BPM) for musical time calculations. */
1706
+ setTempo(bpm) {
1707
+ this.#bpm = bpm;
1708
+ this.#updateFormatLabel();
1709
+ }
1710
+ /** Update the time signature for musical time calculations. */
1711
+ setTimeSignature(numerator, denominator) {
1712
+ this.#timeSignatureNumerator = numerator;
1713
+ this.#timeSignatureDenominator = denominator;
1714
+ this.#updateFormatLabel();
1715
+ }
1716
+ /** Set the visible view range on the timeline. */
1717
+ setViewRange(range) {
1718
+ this.#host.setViewRange(range);
1719
+ }
1720
+ /** Clean up any resources held by the controller. */
1721
+ dispose() {
1722
+ this.#host.removeEventListener(`track-select`, this.#onTrackSelect);
1723
+ }
1724
+ #onTrackSelect = (e) => {
1725
+ const detail = e.detail;
1726
+ const trackEventIds = this.#host.getTrackEvents(detail.trackKey).map((e) => e.id);
1727
+ if (detail.shiftKey) {
1728
+ const current = new Set(this.#host.selectedIds);
1729
+ for (const id of trackEventIds) if (current.has(id)) current.delete(id);
1730
+ else current.add(id);
1731
+ this.#host.selectedIds = [...current];
1732
+ } else this.#host.selectedIds = trackEventIds;
1733
+ };
1734
+ #updateFormatLabel() {
1735
+ if (this.#config.labelFormatter) return;
1736
+ this.#bpm;
1737
+ const num = this.#timeSignatureNumerator;
1738
+ this.#host.formatLabel = (v) => {
1739
+ const beatsPerBar = num;
1740
+ const totalBeats = v;
1741
+ return `${Math.floor(totalBeats / beatsPerBar) + 1}.${Math.floor(totalBeats % beatsPerBar) + 1}`;
1742
+ };
1743
+ }
1744
+ };
1745
+ //#endregion
1746
+ export { attachTimelineInteractions as a, timelineStyles as i, IxfxTimelineElement as n, resolveCssVars as o, TimelineTrackTabElement as r, resolveGrid as s, TimelineController as t };
1747
+
1748
+ //# sourceMappingURL=timeline-B62Sz6J_.js.map