@contraagent/elements 0.0.0-stage → 0.1.0

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 (609) hide show
  1. package/README.md +72 -2
  2. package/custom-elements.json +4260 -0
  3. package/dist/charts/bar-chart.d.ts +32 -0
  4. package/dist/charts/bar-chart.d.ts.map +1 -0
  5. package/dist/charts/bar-chart.js +70 -0
  6. package/dist/charts/bar-chart.js.map +1 -0
  7. package/dist/charts/base.d.ts +48 -0
  8. package/dist/charts/base.d.ts.map +1 -0
  9. package/dist/charts/base.js +203 -0
  10. package/dist/charts/base.js.map +1 -0
  11. package/dist/charts/column-chart.d.ts +42 -0
  12. package/dist/charts/column-chart.d.ts.map +1 -0
  13. package/dist/charts/column-chart.js +146 -0
  14. package/dist/charts/column-chart.js.map +1 -0
  15. package/dist/charts/heatmap.d.ts +42 -0
  16. package/dist/charts/heatmap.d.ts.map +1 -0
  17. package/dist/charts/heatmap.js +124 -0
  18. package/dist/charts/heatmap.js.map +1 -0
  19. package/dist/charts/index.d.ts +9 -0
  20. package/dist/charts/index.d.ts.map +1 -0
  21. package/dist/charts/index.js +11 -0
  22. package/dist/charts/index.js.map +1 -0
  23. package/dist/charts/line-chart.d.ts +36 -0
  24. package/dist/charts/line-chart.d.ts.map +1 -0
  25. package/dist/charts/line-chart.js +118 -0
  26. package/dist/charts/line-chart.js.map +1 -0
  27. package/dist/charts/scale.d.ts +32 -0
  28. package/dist/charts/scale.d.ts.map +1 -0
  29. package/dist/charts/scale.js +50 -0
  30. package/dist/charts/scale.js.map +1 -0
  31. package/dist/charts/state-grid.d.ts +64 -0
  32. package/dist/charts/state-grid.d.ts.map +1 -0
  33. package/dist/charts/state-grid.js +223 -0
  34. package/dist/charts/state-grid.js.map +1 -0
  35. package/dist/charts/types.d.ts +34 -0
  36. package/dist/charts/types.d.ts.map +1 -0
  37. package/dist/charts/types.js +11 -0
  38. package/dist/charts/types.js.map +1 -0
  39. package/dist/checks/check-table.d.ts +32 -0
  40. package/dist/checks/check-table.d.ts.map +1 -0
  41. package/dist/checks/check-table.js +94 -0
  42. package/dist/checks/check-table.js.map +1 -0
  43. package/dist/checks/index.d.ts +4 -0
  44. package/dist/checks/index.d.ts.map +1 -0
  45. package/dist/checks/index.js +6 -0
  46. package/dist/checks/index.js.map +1 -0
  47. package/dist/checks/styles.d.ts +5 -0
  48. package/dist/checks/styles.d.ts.map +1 -0
  49. package/dist/checks/styles.js +30 -0
  50. package/dist/checks/styles.js.map +1 -0
  51. package/dist/checks/types.d.ts +35 -0
  52. package/dist/checks/types.d.ts.map +1 -0
  53. package/dist/checks/types.js +12 -0
  54. package/dist/checks/types.js.map +1 -0
  55. package/dist/core/clock.d.ts +20 -0
  56. package/dist/core/clock.d.ts.map +1 -0
  57. package/dist/core/clock.js +45 -0
  58. package/dist/core/clock.js.map +1 -0
  59. package/dist/core/define.d.ts +3 -0
  60. package/dist/core/define.d.ts.map +1 -0
  61. package/dist/core/define.js +8 -0
  62. package/dist/core/define.js.map +1 -0
  63. package/dist/core/events.d.ts +78 -0
  64. package/dist/core/events.d.ts.map +1 -0
  65. package/dist/core/events.js +8 -0
  66. package/dist/core/events.js.map +1 -0
  67. package/dist/core/format.d.ts +8 -0
  68. package/dist/core/format.d.ts.map +1 -0
  69. package/dist/core/format.js +28 -0
  70. package/dist/core/format.js.map +1 -0
  71. package/dist/core/frame.d.ts +4 -0
  72. package/dist/core/frame.d.ts.map +1 -0
  73. package/dist/core/frame.js +5 -0
  74. package/dist/core/frame.js.map +1 -0
  75. package/dist/core/strings.d.ts +3 -0
  76. package/dist/core/strings.d.ts.map +1 -0
  77. package/dist/core/strings.js +14 -0
  78. package/dist/core/strings.js.map +1 -0
  79. package/dist/core/tone.d.ts +8 -0
  80. package/dist/core/tone.d.ts.map +1 -0
  81. package/dist/core/tone.js +9 -0
  82. package/dist/core/tone.js.map +1 -0
  83. package/dist/count/count.d.ts +22 -0
  84. package/dist/count/count.d.ts.map +1 -0
  85. package/dist/count/count.js +60 -0
  86. package/dist/count/count.js.map +1 -0
  87. package/dist/count/elapsed.d.ts +18 -0
  88. package/dist/count/elapsed.d.ts.map +1 -0
  89. package/dist/count/elapsed.js +33 -0
  90. package/dist/count/elapsed.js.map +1 -0
  91. package/dist/count/index.d.ts +3 -0
  92. package/dist/count/index.d.ts.map +1 -0
  93. package/dist/count/index.js +5 -0
  94. package/dist/count/index.js.map +1 -0
  95. package/dist/define/all.d.ts +13 -0
  96. package/dist/define/all.d.ts.map +1 -0
  97. package/dist/define/all.js +14 -0
  98. package/dist/define/all.js.map +1 -0
  99. package/dist/define/charts.d.ts +8 -0
  100. package/dist/define/charts.d.ts.map +1 -0
  101. package/dist/define/charts.js +15 -0
  102. package/dist/define/charts.js.map +1 -0
  103. package/dist/define/check-table.d.ts +4 -0
  104. package/dist/define/check-table.d.ts.map +1 -0
  105. package/dist/define/check-table.js +7 -0
  106. package/dist/define/check-table.js.map +1 -0
  107. package/dist/define/count.d.ts +5 -0
  108. package/dist/define/count.d.ts.map +1 -0
  109. package/dist/define/count.js +9 -0
  110. package/dist/define/count.js.map +1 -0
  111. package/dist/define/data-table.d.ts +4 -0
  112. package/dist/define/data-table.d.ts.map +1 -0
  113. package/dist/define/data-table.js +7 -0
  114. package/dist/define/data-table.js.map +1 -0
  115. package/dist/define/graph.d.ts +6 -0
  116. package/dist/define/graph.d.ts.map +1 -0
  117. package/dist/define/graph.js +9 -0
  118. package/dist/define/graph.js.map +1 -0
  119. package/dist/define/json-tree.d.ts +4 -0
  120. package/dist/define/json-tree.d.ts.map +1 -0
  121. package/dist/define/json-tree.js +7 -0
  122. package/dist/define/json-tree.js.map +1 -0
  123. package/dist/define/lanes.d.ts +4 -0
  124. package/dist/define/lanes.d.ts.map +1 -0
  125. package/dist/define/lanes.js +7 -0
  126. package/dist/define/lanes.js.map +1 -0
  127. package/dist/define/markdown.d.ts +4 -0
  128. package/dist/define/markdown.d.ts.map +1 -0
  129. package/dist/define/markdown.js +7 -0
  130. package/dist/define/markdown.js.map +1 -0
  131. package/dist/define/matrix.d.ts +4 -0
  132. package/dist/define/matrix.d.ts.map +1 -0
  133. package/dist/define/matrix.js +7 -0
  134. package/dist/define/matrix.js.map +1 -0
  135. package/dist/define/segmented.d.ts +4 -0
  136. package/dist/define/segmented.d.ts.map +1 -0
  137. package/dist/define/segmented.js +7 -0
  138. package/dist/define/segmented.js.map +1 -0
  139. package/dist/define/tiles.d.ts +5 -0
  140. package/dist/define/tiles.d.ts.map +1 -0
  141. package/dist/define/tiles.js +9 -0
  142. package/dist/define/tiles.js.map +1 -0
  143. package/dist/define/transcript.d.ts +4 -0
  144. package/dist/define/transcript.d.ts.map +1 -0
  145. package/dist/define/transcript.js +7 -0
  146. package/dist/define/transcript.js.map +1 -0
  147. package/dist/graph/arrange.d.ts +43 -0
  148. package/dist/graph/arrange.d.ts.map +1 -0
  149. package/dist/graph/arrange.js +390 -0
  150. package/dist/graph/arrange.js.map +1 -0
  151. package/dist/graph/card.d.ts +71 -0
  152. package/dist/graph/card.d.ts.map +1 -0
  153. package/dist/graph/card.js +185 -0
  154. package/dist/graph/card.js.map +1 -0
  155. package/dist/graph/host.d.ts +82 -0
  156. package/dist/graph/host.d.ts.map +1 -0
  157. package/dist/graph/host.js +21 -0
  158. package/dist/graph/host.js.map +1 -0
  159. package/dist/graph/icons.d.ts +7 -0
  160. package/dist/graph/icons.d.ts.map +1 -0
  161. package/dist/graph/icons.js +18 -0
  162. package/dist/graph/icons.js.map +1 -0
  163. package/dist/graph/index.d.ts +15 -0
  164. package/dist/graph/index.d.ts.map +1 -0
  165. package/dist/graph/index.js +17 -0
  166. package/dist/graph/index.js.map +1 -0
  167. package/dist/graph/layered-graph.d.ts +226 -0
  168. package/dist/graph/layered-graph.d.ts.map +1 -0
  169. package/dist/graph/layered-graph.js +396 -0
  170. package/dist/graph/layered-graph.js.map +1 -0
  171. package/dist/graph/layout.d.ts +80 -0
  172. package/dist/graph/layout.d.ts.map +1 -0
  173. package/dist/graph/layout.js +264 -0
  174. package/dist/graph/layout.js.map +1 -0
  175. package/dist/graph/marks.d.ts +24 -0
  176. package/dist/graph/marks.d.ts.map +1 -0
  177. package/dist/graph/marks.js +38 -0
  178. package/dist/graph/marks.js.map +1 -0
  179. package/dist/graph/nav.d.ts +14 -0
  180. package/dist/graph/nav.d.ts.map +1 -0
  181. package/dist/graph/nav.js +14 -0
  182. package/dist/graph/nav.js.map +1 -0
  183. package/dist/graph/pan-zoom.d.ts +80 -0
  184. package/dist/graph/pan-zoom.d.ts.map +1 -0
  185. package/dist/graph/pan-zoom.js +191 -0
  186. package/dist/graph/pan-zoom.js.map +1 -0
  187. package/dist/graph/paths.d.ts +9 -0
  188. package/dist/graph/paths.d.ts.map +1 -0
  189. package/dist/graph/paths.js +44 -0
  190. package/dist/graph/paths.js.map +1 -0
  191. package/dist/graph/place-card.d.ts +36 -0
  192. package/dist/graph/place-card.d.ts.map +1 -0
  193. package/dist/graph/place-card.js +68 -0
  194. package/dist/graph/place-card.js.map +1 -0
  195. package/dist/graph/strings.d.ts +50 -0
  196. package/dist/graph/strings.d.ts.map +1 -0
  197. package/dist/graph/strings.js +37 -0
  198. package/dist/graph/strings.js.map +1 -0
  199. package/dist/graph/styles.d.ts +2 -0
  200. package/dist/graph/styles.d.ts.map +1 -0
  201. package/dist/graph/styles.js +203 -0
  202. package/dist/graph/styles.js.map +1 -0
  203. package/dist/graph/types.d.ts +184 -0
  204. package/dist/graph/types.d.ts.map +1 -0
  205. package/dist/graph/types.js +2 -0
  206. package/dist/graph/types.js.map +1 -0
  207. package/dist/graph/view.d.ts +17 -0
  208. package/dist/graph/view.d.ts.map +1 -0
  209. package/dist/graph/view.js +21 -0
  210. package/dist/graph/view.js.map +1 -0
  211. package/dist/graph/views/dag.d.ts +10 -0
  212. package/dist/graph/views/dag.d.ts.map +1 -0
  213. package/dist/graph/views/dag.js +292 -0
  214. package/dist/graph/views/dag.js.map +1 -0
  215. package/dist/graph/views/foot.d.ts +8 -0
  216. package/dist/graph/views/foot.d.ts.map +1 -0
  217. package/dist/graph/views/foot.js +103 -0
  218. package/dist/graph/views/foot.js.map +1 -0
  219. package/dist/graph/views/node-table.d.ts +17 -0
  220. package/dist/graph/views/node-table.d.ts.map +1 -0
  221. package/dist/graph/views/node-table.js +80 -0
  222. package/dist/graph/views/node-table.js.map +1 -0
  223. package/dist/index.d.ts +22 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +26 -0
  226. package/dist/index.js.map +1 -0
  227. package/dist/json/index.d.ts +2 -0
  228. package/dist/json/index.d.ts.map +1 -0
  229. package/dist/json/index.js +3 -0
  230. package/dist/json/index.js.map +1 -0
  231. package/dist/json/json-tree.d.ts +21 -0
  232. package/dist/json/json-tree.d.ts.map +1 -0
  233. package/dist/json/json-tree.js +51 -0
  234. package/dist/json/json-tree.js.map +1 -0
  235. package/dist/lanes/index.d.ts +5 -0
  236. package/dist/lanes/index.d.ts.map +1 -0
  237. package/dist/lanes/index.js +7 -0
  238. package/dist/lanes/index.js.map +1 -0
  239. package/dist/lanes/lanes.d.ts +56 -0
  240. package/dist/lanes/lanes.d.ts.map +1 -0
  241. package/dist/lanes/lanes.js +160 -0
  242. package/dist/lanes/lanes.js.map +1 -0
  243. package/dist/lanes/stack.d.ts +26 -0
  244. package/dist/lanes/stack.d.ts.map +1 -0
  245. package/dist/lanes/stack.js +43 -0
  246. package/dist/lanes/stack.js.map +1 -0
  247. package/dist/lanes/styles.d.ts +2 -0
  248. package/dist/lanes/styles.d.ts.map +1 -0
  249. package/dist/lanes/styles.js +30 -0
  250. package/dist/lanes/styles.js.map +1 -0
  251. package/dist/lanes/types.d.ts +41 -0
  252. package/dist/lanes/types.d.ts.map +1 -0
  253. package/dist/lanes/types.js +6 -0
  254. package/dist/lanes/types.js.map +1 -0
  255. package/dist/markdown/cae-markdown.d.ts +37 -0
  256. package/dist/markdown/cae-markdown.d.ts.map +1 -0
  257. package/dist/markdown/cae-markdown.js +68 -0
  258. package/dist/markdown/cae-markdown.js.map +1 -0
  259. package/dist/markdown/highlight.d.ts +5 -0
  260. package/dist/markdown/highlight.d.ts.map +1 -0
  261. package/dist/markdown/highlight.js +86 -0
  262. package/dist/markdown/highlight.js.map +1 -0
  263. package/dist/markdown/index.d.ts +4 -0
  264. package/dist/markdown/index.d.ts.map +1 -0
  265. package/dist/markdown/index.js +6 -0
  266. package/dist/markdown/index.js.map +1 -0
  267. package/dist/markdown/markdown.d.ts +4 -0
  268. package/dist/markdown/markdown.d.ts.map +1 -0
  269. package/dist/markdown/markdown.js +105 -0
  270. package/dist/markdown/markdown.js.map +1 -0
  271. package/dist/matrix/grid-step.d.ts +8 -0
  272. package/dist/matrix/grid-step.d.ts.map +1 -0
  273. package/dist/matrix/grid-step.js +69 -0
  274. package/dist/matrix/grid-step.js.map +1 -0
  275. package/dist/matrix/index.d.ts +5 -0
  276. package/dist/matrix/index.d.ts.map +1 -0
  277. package/dist/matrix/index.js +7 -0
  278. package/dist/matrix/index.js.map +1 -0
  279. package/dist/matrix/mark-matrix.d.ts +97 -0
  280. package/dist/matrix/mark-matrix.d.ts.map +1 -0
  281. package/dist/matrix/mark-matrix.js +272 -0
  282. package/dist/matrix/mark-matrix.js.map +1 -0
  283. package/dist/matrix/styles.d.ts +4 -0
  284. package/dist/matrix/styles.d.ts.map +1 -0
  285. package/dist/matrix/styles.js +47 -0
  286. package/dist/matrix/styles.js.map +1 -0
  287. package/dist/matrix/types.d.ts +79 -0
  288. package/dist/matrix/types.d.ts.map +1 -0
  289. package/dist/matrix/types.js +5 -0
  290. package/dist/matrix/types.js.map +1 -0
  291. package/dist/primitives/fact-line.d.ts +14 -0
  292. package/dist/primitives/fact-line.d.ts.map +1 -0
  293. package/dist/primitives/fact-line.js +18 -0
  294. package/dist/primitives/fact-line.js.map +1 -0
  295. package/dist/primitives/icon.d.ts +14 -0
  296. package/dist/primitives/icon.d.ts.map +1 -0
  297. package/dist/primitives/icon.js +19 -0
  298. package/dist/primitives/icon.js.map +1 -0
  299. package/dist/primitives/index.d.ts +10 -0
  300. package/dist/primitives/index.d.ts.map +1 -0
  301. package/dist/primitives/index.js +13 -0
  302. package/dist/primitives/index.js.map +1 -0
  303. package/dist/primitives/legend.d.ts +28 -0
  304. package/dist/primitives/legend.d.ts.map +1 -0
  305. package/dist/primitives/legend.js +28 -0
  306. package/dist/primitives/legend.js.map +1 -0
  307. package/dist/primitives/pill.d.ts +23 -0
  308. package/dist/primitives/pill.d.ts.map +1 -0
  309. package/dist/primitives/pill.js +40 -0
  310. package/dist/primitives/pill.js.map +1 -0
  311. package/dist/primitives/roving-focus.d.ts +47 -0
  312. package/dist/primitives/roving-focus.d.ts.map +1 -0
  313. package/dist/primitives/roving-focus.js +111 -0
  314. package/dist/primitives/roving-focus.js.map +1 -0
  315. package/dist/primitives/segmented.d.ts +41 -0
  316. package/dist/primitives/segmented.d.ts.map +1 -0
  317. package/dist/primitives/segmented.js +88 -0
  318. package/dist/primitives/segmented.js.map +1 -0
  319. package/dist/primitives/share-bar.d.ts +37 -0
  320. package/dist/primitives/share-bar.d.ts.map +1 -0
  321. package/dist/primitives/share-bar.js +69 -0
  322. package/dist/primitives/share-bar.js.map +1 -0
  323. package/dist/primitives/states.d.ts +19 -0
  324. package/dist/primitives/states.d.ts.map +1 -0
  325. package/dist/primitives/states.js +11 -0
  326. package/dist/primitives/states.js.map +1 -0
  327. package/dist/primitives/window.d.ts +24 -0
  328. package/dist/primitives/window.d.ts.map +1 -0
  329. package/dist/primitives/window.js +56 -0
  330. package/dist/primitives/window.js.map +1 -0
  331. package/dist/styles/chips.d.ts +2 -0
  332. package/dist/styles/chips.d.ts.map +1 -0
  333. package/dist/styles/chips.js +18 -0
  334. package/dist/styles/chips.js.map +1 -0
  335. package/dist/styles/facts.d.ts +2 -0
  336. package/dist/styles/facts.d.ts.map +1 -0
  337. package/dist/styles/facts.js +7 -0
  338. package/dist/styles/facts.js.map +1 -0
  339. package/dist/styles/index.d.ts +16 -0
  340. package/dist/styles/index.d.ts.map +1 -0
  341. package/dist/styles/index.js +15 -0
  342. package/dist/styles/index.js.map +1 -0
  343. package/dist/styles/layout.d.ts +2 -0
  344. package/dist/styles/layout.d.ts.map +1 -0
  345. package/dist/styles/layout.js +33 -0
  346. package/dist/styles/layout.js.map +1 -0
  347. package/dist/styles/marks.d.ts +2 -0
  348. package/dist/styles/marks.d.ts.map +1 -0
  349. package/dist/styles/marks.js +30 -0
  350. package/dist/styles/marks.js.map +1 -0
  351. package/dist/styles/meter.d.ts +3 -0
  352. package/dist/styles/meter.d.ts.map +1 -0
  353. package/dist/styles/meter.js +9 -0
  354. package/dist/styles/meter.js.map +1 -0
  355. package/dist/styles/motion.d.ts +2 -0
  356. package/dist/styles/motion.d.ts.map +1 -0
  357. package/dist/styles/motion.js +27 -0
  358. package/dist/styles/motion.js.map +1 -0
  359. package/dist/styles/prose.d.ts +3 -0
  360. package/dist/styles/prose.d.ts.map +1 -0
  361. package/dist/styles/prose.js +59 -0
  362. package/dist/styles/prose.js.map +1 -0
  363. package/dist/styles/reset.d.ts +2 -0
  364. package/dist/styles/reset.d.ts.map +1 -0
  365. package/dist/styles/reset.js +13 -0
  366. package/dist/styles/reset.js.map +1 -0
  367. package/dist/styles/status.d.ts +2 -0
  368. package/dist/styles/status.d.ts.map +1 -0
  369. package/dist/styles/status.js +52 -0
  370. package/dist/styles/status.js.map +1 -0
  371. package/dist/styles/text.d.ts +2 -0
  372. package/dist/styles/text.d.ts.map +1 -0
  373. package/dist/styles/text.js +21 -0
  374. package/dist/styles/text.js.map +1 -0
  375. package/dist/styles/tokens.d.ts +8 -0
  376. package/dist/styles/tokens.d.ts.map +1 -0
  377. package/dist/styles/tokens.js +32 -0
  378. package/dist/styles/tokens.js.map +1 -0
  379. package/dist/table/data-table.d.ts +106 -0
  380. package/dist/table/data-table.d.ts.map +1 -0
  381. package/dist/table/data-table.js +408 -0
  382. package/dist/table/data-table.js.map +1 -0
  383. package/dist/table/index.d.ts +4 -0
  384. package/dist/table/index.d.ts.map +1 -0
  385. package/dist/table/index.js +6 -0
  386. package/dist/table/index.js.map +1 -0
  387. package/dist/table/styles.d.ts +2 -0
  388. package/dist/table/styles.d.ts.map +1 -0
  389. package/dist/table/styles.js +32 -0
  390. package/dist/table/styles.js.map +1 -0
  391. package/dist/table/types.d.ts +48 -0
  392. package/dist/table/types.d.ts.map +1 -0
  393. package/dist/table/types.js +30 -0
  394. package/dist/table/types.js.map +1 -0
  395. package/dist/themes/boot.d.ts +7 -0
  396. package/dist/themes/boot.d.ts.map +1 -0
  397. package/dist/themes/boot.js +14 -0
  398. package/dist/themes/boot.js.map +1 -0
  399. package/dist/themes/choice.d.ts +16 -0
  400. package/dist/themes/choice.d.ts.map +1 -0
  401. package/dist/themes/choice.js +45 -0
  402. package/dist/themes/choice.js.map +1 -0
  403. package/dist/themes/data.d.ts +43 -0
  404. package/dist/themes/data.d.ts.map +1 -0
  405. package/dist/themes/data.js +408 -0
  406. package/dist/themes/data.js.map +1 -0
  407. package/dist/themes/index.d.ts +7 -0
  408. package/dist/themes/index.d.ts.map +1 -0
  409. package/dist/themes/index.js +11 -0
  410. package/dist/themes/index.js.map +1 -0
  411. package/dist/themes/sheet.d.ts +16 -0
  412. package/dist/themes/sheet.d.ts.map +1 -0
  413. package/dist/themes/sheet.js +28 -0
  414. package/dist/themes/sheet.js.map +1 -0
  415. package/dist/themes/token-meanings.d.ts +3 -0
  416. package/dist/themes/token-meanings.d.ts.map +1 -0
  417. package/dist/themes/token-meanings.js +67 -0
  418. package/dist/themes/token-meanings.js.map +1 -0
  419. package/dist/themes/tokens-list.d.ts +14 -0
  420. package/dist/themes/tokens-list.d.ts.map +1 -0
  421. package/dist/themes/tokens-list.js +69 -0
  422. package/dist/themes/tokens-list.js.map +1 -0
  423. package/dist/tiles/index.d.ts +4 -0
  424. package/dist/tiles/index.d.ts.map +1 -0
  425. package/dist/tiles/index.js +6 -0
  426. package/dist/tiles/index.js.map +1 -0
  427. package/dist/tiles/stat-tiles.d.ts +40 -0
  428. package/dist/tiles/stat-tiles.d.ts.map +1 -0
  429. package/dist/tiles/stat-tiles.js +99 -0
  430. package/dist/tiles/stat-tiles.js.map +1 -0
  431. package/dist/tiles/styles.d.ts +2 -0
  432. package/dist/tiles/styles.d.ts.map +1 -0
  433. package/dist/tiles/styles.js +23 -0
  434. package/dist/tiles/styles.js.map +1 -0
  435. package/dist/tiles/types.d.ts +22 -0
  436. package/dist/tiles/types.d.ts.map +1 -0
  437. package/dist/tiles/types.js +2 -0
  438. package/dist/tiles/types.js.map +1 -0
  439. package/dist/transcript/follow-scroll.d.ts +21 -0
  440. package/dist/transcript/follow-scroll.d.ts.map +1 -0
  441. package/dist/transcript/follow-scroll.js +76 -0
  442. package/dist/transcript/follow-scroll.js.map +1 -0
  443. package/dist/transcript/index.d.ts +5 -0
  444. package/dist/transcript/index.d.ts.map +1 -0
  445. package/dist/transcript/index.js +7 -0
  446. package/dist/transcript/index.js.map +1 -0
  447. package/dist/transcript/styles.d.ts +2 -0
  448. package/dist/transcript/styles.d.ts.map +1 -0
  449. package/dist/transcript/styles.js +114 -0
  450. package/dist/transcript/styles.js.map +1 -0
  451. package/dist/transcript/tags.d.ts +6 -0
  452. package/dist/transcript/tags.d.ts.map +1 -0
  453. package/dist/transcript/tags.js +13 -0
  454. package/dist/transcript/tags.js.map +1 -0
  455. package/dist/transcript/tool-card.d.ts +16 -0
  456. package/dist/transcript/tool-card.d.ts.map +1 -0
  457. package/dist/transcript/tool-card.js +87 -0
  458. package/dist/transcript/tool-card.js.map +1 -0
  459. package/dist/transcript/transcript.d.ts +103 -0
  460. package/dist/transcript/transcript.d.ts.map +1 -0
  461. package/dist/transcript/transcript.js +397 -0
  462. package/dist/transcript/transcript.js.map +1 -0
  463. package/dist/transcript/types.d.ts +161 -0
  464. package/dist/transcript/types.d.ts.map +1 -0
  465. package/dist/transcript/types.js +25 -0
  466. package/dist/transcript/types.js.map +1 -0
  467. package/docs/charts.md +58 -0
  468. package/docs/check-table.md +40 -0
  469. package/docs/data-table.md +57 -0
  470. package/docs/examples/charts.ts +61 -0
  471. package/docs/examples/check-table.ts +19 -0
  472. package/docs/examples/ci-pipeline.ts +271 -0
  473. package/docs/examples/data-table.ts +39 -0
  474. package/docs/examples/graph.ts +57 -0
  475. package/docs/examples/lanes.ts +40 -0
  476. package/docs/examples/matrix.ts +56 -0
  477. package/docs/examples/page.css +34 -0
  478. package/docs/examples/segmented.ts +18 -0
  479. package/docs/examples/status.ts +30 -0
  480. package/docs/examples/theme.css +54 -0
  481. package/docs/examples/tiles.ts +27 -0
  482. package/docs/examples/transcript.ts +59 -0
  483. package/docs/graph.md +112 -0
  484. package/docs/lanes.md +48 -0
  485. package/docs/matrix.md +34 -0
  486. package/docs/page.md +87 -0
  487. package/docs/primitives.md +57 -0
  488. package/docs/strings.md +16 -0
  489. package/docs/theming.md +147 -0
  490. package/docs/tiles.md +40 -0
  491. package/docs/transcript.md +73 -0
  492. package/docs/tsconfig.json +20 -0
  493. package/package.json +161 -4
  494. package/src/charts/bar-chart.ts +74 -0
  495. package/src/charts/base.ts +188 -0
  496. package/src/charts/column-chart.ts +153 -0
  497. package/src/charts/heatmap.ts +129 -0
  498. package/src/charts/index.ts +10 -0
  499. package/src/charts/line-chart.ts +128 -0
  500. package/src/charts/scale.ts +61 -0
  501. package/src/charts/state-grid.ts +245 -0
  502. package/src/charts/types.ts +48 -0
  503. package/src/checks/check-table.ts +85 -0
  504. package/src/checks/index.ts +5 -0
  505. package/src/checks/styles.ts +31 -0
  506. package/src/checks/types.ts +48 -0
  507. package/src/core/clock.ts +46 -0
  508. package/src/core/define.ts +7 -0
  509. package/src/core/events.ts +89 -0
  510. package/src/core/format.ts +25 -0
  511. package/src/core/frame.ts +5 -0
  512. package/src/core/strings.ts +11 -0
  513. package/src/core/tone.ts +14 -0
  514. package/src/count/count.ts +54 -0
  515. package/src/count/elapsed.ts +33 -0
  516. package/src/count/index.ts +4 -0
  517. package/src/define/all.ts +13 -0
  518. package/src/define/charts.ts +17 -0
  519. package/src/define/check-table.ts +9 -0
  520. package/src/define/count.ts +11 -0
  521. package/src/define/data-table.ts +9 -0
  522. package/src/define/graph.ts +11 -0
  523. package/src/define/json-tree.ts +9 -0
  524. package/src/define/lanes.ts +9 -0
  525. package/src/define/markdown.ts +9 -0
  526. package/src/define/matrix.ts +9 -0
  527. package/src/define/segmented.ts +9 -0
  528. package/src/define/tiles.ts +11 -0
  529. package/src/define/transcript.ts +9 -0
  530. package/src/graph/arrange.ts +399 -0
  531. package/src/graph/card.ts +209 -0
  532. package/src/graph/host.ts +100 -0
  533. package/src/graph/icons.ts +23 -0
  534. package/src/graph/index.ts +16 -0
  535. package/src/graph/layered-graph.ts +417 -0
  536. package/src/graph/layout.ts +331 -0
  537. package/src/graph/marks.ts +42 -0
  538. package/src/graph/nav.ts +19 -0
  539. package/src/graph/pan-zoom.ts +219 -0
  540. package/src/graph/paths.ts +41 -0
  541. package/src/graph/place-card.ts +93 -0
  542. package/src/graph/strings.ts +86 -0
  543. package/src/graph/styles.ts +204 -0
  544. package/src/graph/types.ts +202 -0
  545. package/src/graph/view.ts +28 -0
  546. package/src/graph/views/dag.ts +294 -0
  547. package/src/graph/views/foot.ts +109 -0
  548. package/src/graph/views/node-table.ts +90 -0
  549. package/src/index.ts +25 -0
  550. package/src/json/index.ts +2 -0
  551. package/src/json/json-tree.ts +49 -0
  552. package/src/lanes/index.ts +6 -0
  553. package/src/lanes/lanes.ts +143 -0
  554. package/src/lanes/stack.ts +51 -0
  555. package/src/lanes/styles.ts +30 -0
  556. package/src/lanes/types.ts +51 -0
  557. package/src/markdown/cae-markdown.ts +64 -0
  558. package/src/markdown/highlight.ts +94 -0
  559. package/src/markdown/index.ts +5 -0
  560. package/src/markdown/markdown.ts +110 -0
  561. package/src/matrix/grid-step.ts +58 -0
  562. package/src/matrix/index.ts +6 -0
  563. package/src/matrix/mark-matrix.ts +285 -0
  564. package/src/matrix/styles.ts +48 -0
  565. package/src/matrix/types.ts +83 -0
  566. package/src/primitives/fact-line.ts +26 -0
  567. package/src/primitives/icon.ts +26 -0
  568. package/src/primitives/index.ts +12 -0
  569. package/src/primitives/legend.ts +56 -0
  570. package/src/primitives/pill.ts +58 -0
  571. package/src/primitives/roving-focus.ts +138 -0
  572. package/src/primitives/segmented.ts +92 -0
  573. package/src/primitives/share-bar.ts +94 -0
  574. package/src/primitives/states.ts +28 -0
  575. package/src/primitives/window.ts +65 -0
  576. package/src/styles/chips.ts +18 -0
  577. package/src/styles/facts.ts +7 -0
  578. package/src/styles/index.ts +19 -0
  579. package/src/styles/layout.ts +33 -0
  580. package/src/styles/marks.ts +30 -0
  581. package/src/styles/meter.ts +9 -0
  582. package/src/styles/motion.ts +27 -0
  583. package/src/styles/prose.ts +59 -0
  584. package/src/styles/reset.ts +13 -0
  585. package/src/styles/status.ts +52 -0
  586. package/src/styles/text.ts +21 -0
  587. package/src/styles/tokens.ts +35 -0
  588. package/src/table/data-table.ts +367 -0
  589. package/src/table/index.ts +5 -0
  590. package/src/table/styles.ts +32 -0
  591. package/src/table/types.ts +73 -0
  592. package/src/themes/boot.ts +14 -0
  593. package/src/themes/choice.ts +47 -0
  594. package/src/themes/data.ts +433 -0
  595. package/src/themes/index.ts +10 -0
  596. package/src/themes/sheet.ts +29 -0
  597. package/src/themes/token-meanings.ts +67 -0
  598. package/src/themes/tokens-list.ts +82 -0
  599. package/src/tiles/index.ts +5 -0
  600. package/src/tiles/stat-tiles.ts +92 -0
  601. package/src/tiles/styles.ts +23 -0
  602. package/src/tiles/types.ts +20 -0
  603. package/src/transcript/follow-scroll.ts +72 -0
  604. package/src/transcript/index.ts +6 -0
  605. package/src/transcript/styles.ts +114 -0
  606. package/src/transcript/tags.ts +18 -0
  607. package/src/transcript/tool-card.ts +103 -0
  608. package/src/transcript/transcript.ts +358 -0
  609. package/src/transcript/types.ts +167 -0
@@ -0,0 +1,52 @@
1
+ // A status, by tone (core/tone.ts, primitives/pill.ts): one rule per tone, and
2
+ // the status elements that take it (a mark, a pill, a word, a dot, a spinner).
3
+ import { css } from 'lit';
4
+
5
+ export const statusStyles = css`
6
+ /*
7
+ * data-tone names its status colour, which each kind of status element below takes as
8
+ * --tone (the colour) and --tone-bg (its tint). No data-tone: neutral.
9
+ */
10
+ [data-tone='failed'] { --tone: var(--status-failed); --tone-bg: var(--status-failed-bg); }
11
+ [data-tone='attention'] { --tone: var(--status-attention); --tone-bg: var(--status-attention-bg); }
12
+ [data-tone='done'] { --tone: var(--status-done); --tone-bg: var(--status-done-bg); }
13
+ [data-tone='running'] { --tone: var(--status-running); --tone-bg: var(--status-running-bg); }
14
+ [data-tone='muted'] { --tone: var(--status-muted); --tone-bg: var(--status-muted-bg); }
15
+
16
+ /*
17
+ * A status mark before a status word (data-mark): ✓ done, ✕ failed, ◌ not started or waiting.
18
+ * The shape keeps the meaning without colour; screen readers read the word only.
19
+ */
20
+ [data-mark]::before { margin-right: 0.35em; font-weight: 700; }
21
+ [data-mark='done']::before { content: '✓'; content: '✓' / ''; color: var(--status-done); }
22
+ [data-mark='failed']::before { content: '✕'; content: '✕' / ''; }
23
+ [data-mark='pending']::before { content: '◌'; content: '◌' / ''; }
24
+
25
+ /* text in a status colour: only on a status that applies (a count above 0 of a problem, a status word) */
26
+ .tone-text[data-tone] { color: var(--tone); }
27
+
28
+ /*
29
+ * A status as a pill, always with its word. A problem is tinted and marked (✕ failed, ◌ not started);
30
+ * done is quiet (a ✓ and the word): it is the usual case, and the problems are what stand out.
31
+ */
32
+ .pill { border-radius: var(--radius-pill); padding: 1px 10px; font-size: var(--font-size-sm); font-weight: 500; background: var(--raise); color: var(--text-2); white-space: nowrap; }
33
+ .pill[data-tone] { background: var(--tone-bg); color: var(--tone); }
34
+ .pill[data-tone='done'] { background: none; padding-left: 2px; color: var(--text-2); }
35
+
36
+ /* a status as a word in a row (History, Problems, Outputs): coloured for a problem, done quiet with its ✓ */
37
+ .jstop { font-weight: 600; }
38
+ .jstop[data-tone='failed'], .jstop[data-tone='attention'] { color: var(--tone); }
39
+ .jstop[data-tone='done'] { color: var(--text-2); font-weight: 500; }
40
+
41
+ /*
42
+ * A status as a dot (a run in the header and the run list). The shape carries it too:
43
+ * round done, square failed, diamond attention, a breathing ring running.
44
+ */
45
+ .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line2); flex: none; display: inline-block; }
46
+ .dot[data-tone] { background: var(--tone); }
47
+ .dot[data-tone='running'] { animation: breathe 1.8s ease-in-out infinite; }
48
+ .dot[data-tone='attention'] { border-radius: 1px; transform: rotate(45deg) scale(0.86); }
49
+ .dot[data-tone='failed'] { border-radius: 1.5px; }
50
+ .spin { width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--status-running-bg);
51
+ border-top-color: var(--status-running); animation: turn 0.9s linear infinite; flex: none; display: inline-block; }
52
+ `;
@@ -0,0 +1,21 @@
1
+ // Text: code, captions, words read only by screen readers, line breaks in a
2
+ // tight box, links.
3
+ import { css } from 'lit';
4
+
5
+ export const textStyles = css`
6
+ .jmono, code, .mono { font-family: var(--mono); }
7
+ /* read by screen readers, not shown: the word beside a status mark or an icon */
8
+ .sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
9
+ .jmono { font-size: 11.5px; }
10
+ .meta { color: var(--text-muted); font-size: var(--font-size-sm); }
11
+ /* a label in a tight box: it wraps at spaces and between phrases, never inside a word (Japanese included) */
12
+ .words { word-break: keep-all; overflow-wrap: break-word; line-break: strict; }
13
+ /* one fact of a row in .words (factLine): the line breaks between facts first, inside one only when it is wider than the box */
14
+ .words .f { display: inline-block; max-width: 100%; }
15
+ @supports (word-break: auto-phrase) {
16
+ .words:lang(ja) { word-break: auto-phrase; }
17
+ }
18
+ .mut, .jdim { color: var(--text-muted); }
19
+ a.lnk { color: var(--accent); cursor: pointer; text-decoration: none; }
20
+ a.lnk:hover { text-decoration: underline; }
21
+ `;
@@ -0,0 +1,35 @@
1
+ // The design tokens as an element's custom properties: each reads its `--ca-*`
2
+ // property, which `data-ca-theme` on an ancestor sets (themes/data.ts) and a
3
+ // `--ca-*` property of the page's own, set on the element or nearer to it,
4
+ // overrides.
5
+ import { css, unsafeCSS } from 'lit';
6
+ import { DEFAULT_THEME, THEMES, type ThemeToken } from '../themes/data.js';
7
+ import { TOKENS } from '../themes/tokens-list.js';
8
+
9
+ const fallback = THEMES[DEFAULT_THEME].tokens as Record<string, string>;
10
+
11
+ /** One token: its `--ca-*` property (a theme's value or the page's own), else the default theme's (or its derivation). */
12
+ const declaration = (t: (typeof TOKENS)[number]): string =>
13
+ t.derive
14
+ ? `--${t.name}: var(${t.prop}, ${t.derive});`
15
+ : `--${t.name}: var(${t.prop}, ${fallback[t.name as ThemeToken]});`;
16
+
17
+ /**
18
+ * The design tokens (`TOKENS` in themes/tokens-list.ts, with their meanings). A
19
+ * colour means one thing: text and surfaces are neutral, a status colour marks a
20
+ * status (only where it applies), the accent marks what can be clicked or is
21
+ * selected, and identity colours are small cues (an icon, a thin edge, a legend).
22
+ */
23
+ export const tokenStyles = css`
24
+ :host {
25
+ ${unsafeCSS(TOKENS.map(declaration).join('\n '))}
26
+ --sans: var(--ca-sans, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif);
27
+ --mono: var(--ca-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace);
28
+ --ease: cubic-bezier(0.2, 0.8, 0.2, 1);
29
+ color-scheme: var(--ca-color-scheme, ${unsafeCSS(THEMES[DEFAULT_THEME].scheme)});
30
+ color: var(--text);
31
+ }
32
+ :host([hidden]) {
33
+ display: none !important;
34
+ }
35
+ `;
@@ -0,0 +1,367 @@
1
+ import { LitElement, adoptStyles, html, nothing, type CSSResult, type PropertyValues, type TemplateResult } from 'lit';
2
+ import { property, state } from 'lit/decorators.js';
3
+ import { Directive, directive, PartType, type ElementPart, type PartInfo } from 'lit/directive.js';
4
+ import { repeat } from 'lit/directives/repeat.js';
5
+ import { emit } from '../core/events.js';
6
+ import { withDefaults } from '../core/strings.js';
7
+ import { toneAttr, type Tone } from '../core/tone.js';
8
+ import { RovingFocusController } from '../primitives/roving-focus.js';
9
+ import { rowOffsets, windowRowsAt, type RowWindow } from '../primitives/window.js';
10
+ import { base } from '../styles/index.js';
11
+ import { dataTableStyles } from './styles.js';
12
+ import { DEFAULT_DATA_TABLE_STRINGS, isSortable, type DataColumn, type DataTableStrings, type SortState } from './types.js';
13
+
14
+ /** Sets the attributes of a map on an element, and removes those it set before that the map no longer has. */
15
+ class AttrsDirective extends Directive {
16
+ private names: string[] = [];
17
+
18
+ constructor(part: PartInfo) {
19
+ super(part);
20
+ if (part.type !== PartType.ELEMENT) throw new Error('attrs() goes on an element');
21
+ }
22
+
23
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars -- the argument update() reads
24
+ render(_map: Readonly<Record<string, string>> | undefined) {
25
+ return nothing;
26
+ }
27
+
28
+ override update(part: ElementPart, [map]: [Readonly<Record<string, string>> | undefined]) {
29
+ const el = part.element;
30
+ const next = Object.keys(map ?? {});
31
+ for (const n of this.names) if (!next.includes(n)) el.removeAttribute(n);
32
+ for (const n of next) if (el.getAttribute(n) !== map![n]) el.setAttribute(n, map![n]!);
33
+ this.names = next;
34
+ return nothing;
35
+ }
36
+ }
37
+ const attrs = directive(AttrsDirective);
38
+
39
+ /** Interactive content inside a cell: a click on it is its own, not the row's. */
40
+ const INTERACTIVE = new Set(['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA', 'SUMMARY', 'LABEL']);
41
+
42
+ /** The rows drawn before the first measure of the viewport. */
43
+ const FIRST_ROWS = 60;
44
+
45
+ /**
46
+ * A table of rows, one per item, in a real `<table>`: a header cell per column
47
+ * (`scope="col"`), the first `rowHeader` column as the row's header. The rows
48
+ * are one tab stop: the arrow keys, Home and End move between them, and Enter or
49
+ * a click is the row's primary action (`cae-activate`), or chooses it as the
50
+ * selection when the table is not `activatable` (`cae-select`). A sortable
51
+ * header sends `cae-sort`; the host orders the rows (`sortRows`) and sets them.
52
+ * Above `windowAt` rows, only the rows on screen are drawn, and a spacer stands
53
+ * for the others: as high as those rows were when drawn, or, for a row not drawn
54
+ * yet, as the rows drawn are on average. Rows may differ in height.
55
+ *
56
+ * Its look: `--cae-data-table-gap` (between the columns), `--cae-data-table-row-padding`,
57
+ * the parts, and `cellStyles` (styles for what the cells draw, added to the
58
+ * table's own).
59
+ *
60
+ * @tagname cae-data-table
61
+ * @fires cae-activate - `{id}`: a row's primary action (a click or Enter, when `activatable`)
62
+ * @fires cae-select - `{id}`: a row chosen as the selection (a click or Enter, when not `activatable`)
63
+ * @fires cae-sort - `{id, direction}`: a sortable header was clicked
64
+ * @csspart table - the `<table>`
65
+ * @csspart caption - the caption
66
+ * @csspart head - the header row's group
67
+ * @csspart header-cell - each header cell
68
+ * @csspart row - each row
69
+ * @csspart row-selected - the selected row
70
+ * @csspart cell - each cell
71
+ * @csspart empty - the cell that stands for no rows
72
+ * @slot caption - the caption, instead of `caption`
73
+ * @slot empty - what the table shows with no rows, instead of `strings.empty`
74
+ */
75
+ export class CaeDataTable<R = unknown> extends LitElement {
76
+ static override styles = [base, dataTableStyles];
77
+
78
+ @property({ attribute: false }) columns: readonly DataColumn<R>[] = [];
79
+ @property({ attribute: false }) rows: readonly R[] = [];
80
+ /** A row's id: unique among the rows (`data-key`, the `id` of the events). By default its `id`. */
81
+ @property({ attribute: false }) rowKey: (row: R) => string = (row) => {
82
+ const id = (row as { id?: unknown }).id;
83
+ return typeof id === 'string' || typeof id === 'number' ? String(id) : '';
84
+ };
85
+ /** A row's tone (`data-tone` on the row). */
86
+ @property({ attribute: false }) rowTone?: (row: R) => Tone | undefined;
87
+ /** More attributes on a row (`data-*`), for the host's styles and tests. */
88
+ @property({ attribute: false }) rowAttrs?: (row: R) => Readonly<Record<string, string>>;
89
+ /** A click or Enter on a row is its primary action (`cae-activate`); otherwise it selects the row (`cae-select`). */
90
+ @property({ type: Boolean }) activatable = true;
91
+ /** The id of the selected row. */
92
+ @property() selected: string | null = null;
93
+ /** The column the rows are ordered by: shown in its header (`aria-sort`). The host orders the rows. */
94
+ @property({ attribute: false }) sort: SortState | null = null;
95
+ /** Above this many rows, only the rows on screen are drawn. */
96
+ @property({ type: Number }) windowAt = 200;
97
+ /** A row's height in px, until rows are measured. */
98
+ @property({ type: Number }) rowHeight = 32;
99
+ /** The table's caption (its accessible name). */
100
+ @property() caption = '';
101
+ @property({ attribute: false }) strings: Partial<DataTableStrings> = {};
102
+ /** Styles for what the cells draw, added after the table's own (the rows are `tr`, the cells `th` and `td`). */
103
+ @property({ attribute: false }) cellStyles: readonly CSSResult[] = [];
104
+
105
+ /** The rows drawn, when windowed. */
106
+ @state() private range: { from: number; to: number } = { from: 0, to: FIRST_ROWS };
107
+ /** Each drawn row's height, by its key: what stands for it while it is not drawn. */
108
+ private heights = new Map<string, number>();
109
+ /** Where each row starts (`rowOffsets`), for the rows as they are; null: to work out again. */
110
+ private offsets: number[] | null = null;
111
+ /** The row that holds the tab stop. */
112
+ private focusKey: string | null = null;
113
+ private scroller: HTMLElement | Window | null = null;
114
+ private resized: ResizeObserver | null = null;
115
+ private frame = 0;
116
+ /** The next update keeps `range` as set (Home and End set it before the scroller reports). */
117
+ private held = false;
118
+
119
+ private readonly roving = new RovingFocusController(this, {
120
+ items: () => [...this.renderRoot.querySelectorAll<HTMLElement>('tbody tr[data-key]')],
121
+ layout: 'vertical',
122
+ onMove: (el) => (this.focusKey = el.dataset['key'] ?? null),
123
+ });
124
+
125
+ private get windowed(): boolean {
126
+ return this.rows.length > this.windowAt;
127
+ }
128
+
129
+ override disconnectedCallback(): void {
130
+ super.disconnectedCallback();
131
+ this.unwatch();
132
+ }
133
+
134
+ /** Where each row starts: its measured height, else the drawn rows' average. */
135
+ private rowStarts(): number[] {
136
+ if (this.offsets) return this.offsets;
137
+ let sum = 0;
138
+ for (const h of this.heights.values()) sum += h;
139
+ const typical = this.heights.size ? sum / this.heights.size : this.rowHeight;
140
+ return (this.offsets = rowOffsets(this.rows.length, (i) => this.heights.get(this.rowKey(this.rows[i]!)) ?? typical));
141
+ }
142
+
143
+ /** The rows on screen, from where the table's body is in its scroller. */
144
+ private visible(): RowWindow {
145
+ const starts = this.rowStarts();
146
+ const body = this.renderRoot.querySelector('tbody');
147
+ // Before the first measure of the view: the first rows, about FIRST_ROWS of them.
148
+ if (!body || !this.scroller) return windowRowsAt(starts, 0, (starts.at(-1)! / Math.max(1, this.rows.length)) * FIRST_ROWS, 0);
149
+ const view =
150
+ this.scroller instanceof HTMLElement
151
+ ? { top: this.scroller.getBoundingClientRect().top, height: this.scroller.clientHeight }
152
+ : { top: 0, height: this.scroller.innerHeight };
153
+ return windowRowsAt(starts, view.top - body.getBoundingClientRect().top, view.height);
154
+ }
155
+
156
+ /** Scrolls the body's first row (or its last, `last`) into the scroller's view. */
157
+ private scrollToEnd(last: boolean): void {
158
+ const body = this.renderRoot.querySelector('tbody');
159
+ const s = this.scroller;
160
+ if (!body || !s) return;
161
+ const r = body.getBoundingClientRect();
162
+ const view = s instanceof HTMLElement ? s.getBoundingClientRect() : { top: 0, bottom: s.innerHeight };
163
+ const by = last ? r.bottom - view.bottom : r.top - view.top;
164
+ if (s instanceof HTMLElement) s.scrollTop += by;
165
+ else s.scrollBy(0, by);
166
+ }
167
+
168
+ private reframe(): void {
169
+ const w = this.visible();
170
+ if (w.from !== this.range.from || w.to !== this.range.to) this.range = { from: w.from, to: w.to };
171
+ }
172
+
173
+ private readonly onScroll = (): void => {
174
+ if (this.frame) return;
175
+ this.frame = requestAnimationFrame(() => {
176
+ this.frame = 0;
177
+ this.reframe();
178
+ });
179
+ };
180
+
181
+ /** The nearest ancestor that scrolls the table vertically, across shadow roots; the window when none does. */
182
+ private findScroller(): HTMLElement | Window {
183
+ let n: Node | null = this.parentNode;
184
+ while (n) {
185
+ if (n instanceof HTMLElement) {
186
+ const o = getComputedStyle(n).overflowY;
187
+ if ((o === 'auto' || o === 'scroll' || o === 'overlay') && n.scrollHeight > n.clientHeight + 1) return n;
188
+ }
189
+ n = n instanceof ShadowRoot ? n.host : n.parentNode;
190
+ }
191
+ return window;
192
+ }
193
+
194
+ private watch(): void {
195
+ if (this.scroller) return;
196
+ this.scroller = this.findScroller();
197
+ this.scroller.addEventListener('scroll', this.onScroll, { passive: true });
198
+ // Its height decides how many rows show: the window's when the page scrolls, else the scroller's own.
199
+ if (!(this.scroller instanceof HTMLElement)) window.addEventListener('resize', this.onScroll, { passive: true });
200
+ else if (typeof ResizeObserver !== 'undefined') (this.resized ??= new ResizeObserver(this.onScroll)).observe(this.scroller);
201
+ }
202
+
203
+ private unwatch(): void {
204
+ cancelAnimationFrame(this.frame);
205
+ this.frame = 0;
206
+ this.scroller?.removeEventListener('scroll', this.onScroll);
207
+ window.removeEventListener('resize', this.onScroll);
208
+ this.resized?.disconnect();
209
+ this.scroller = null;
210
+ }
211
+
212
+ override willUpdate(changed: PropertyValues<this>): void {
213
+ if (changed.has('rows') || changed.has('rowHeight')) this.offsets = null;
214
+ if (changed.has('rows') || changed.has('windowAt')) {
215
+ if (this.windowed && this.hasUpdated) {
216
+ const w = this.visible();
217
+ this.range = { from: w.from, to: w.to };
218
+ } else if (!this.windowed) this.unwatch();
219
+ }
220
+ // The tab stop stays on its row while the rows drawn change.
221
+ const keys = this.shown().map(this.rowKey);
222
+ const i = this.focusKey === null ? -1 : keys.indexOf(this.focusKey);
223
+ this.roving.current = Math.max(0, i);
224
+ }
225
+
226
+ override updated(changed: PropertyValues<this>): void {
227
+ if (changed.has('cellStyles') && this.renderRoot instanceof ShadowRoot)
228
+ adoptStyles(this.renderRoot, [...(this.constructor as typeof LitElement).elementStyles, ...this.cellStyles]);
229
+ if (!this.windowed) return;
230
+ this.watch();
231
+ // Measure the drawn rows: each stands for itself while it is not drawn. A row keeps its
232
+ // height, so the spacers settle as the rows are drawn once each.
233
+ let moved = false;
234
+ for (const tr of this.renderRoot.querySelectorAll<HTMLElement>('tbody tr[data-key]')) {
235
+ const h = tr.getBoundingClientRect().height;
236
+ const key = tr.dataset['key']!;
237
+ if (h > 0 && Math.abs(h - (this.heights.get(key) ?? -1)) > 0.5) {
238
+ this.heights.set(key, h);
239
+ moved = true;
240
+ }
241
+ }
242
+ if (moved) this.offsets = null;
243
+ if (this.held) this.held = false;
244
+ // On the next frame, never in this update: a window that changes the measures and so
245
+ // the window again then gives the page a frame, and the reader's input, each time.
246
+ else this.onScroll();
247
+ }
248
+
249
+ /** The rows drawn now. */
250
+ private shown(): readonly R[] {
251
+ if (!this.windowed) return this.rows;
252
+ return this.rows.slice(this.range.from, Math.min(this.rows.length, this.range.to));
253
+ }
254
+
255
+ /** The row of an event, and its id. */
256
+ private rowOf(e: Event): { tr: HTMLElement; id: string } | null {
257
+ for (const t of e.composedPath()) {
258
+ if (!(t instanceof HTMLElement)) continue;
259
+ if (INTERACTIVE.has(t.tagName)) return null;
260
+ if (t.tagName === 'TR' && t.dataset['key'] !== undefined) return { tr: t, id: t.dataset['key'] };
261
+ if (t === this) break;
262
+ }
263
+ return null;
264
+ }
265
+
266
+ private act(id: string): void {
267
+ if (this.activatable) {
268
+ emit(this, 'cae-activate', { id });
269
+ return;
270
+ }
271
+ this.selected = id;
272
+ emit(this, 'cae-select', { id });
273
+ }
274
+
275
+ private readonly onClick = (e: MouseEvent): void => {
276
+ const r = this.rowOf(e);
277
+ if (r) this.act(r.id);
278
+ };
279
+
280
+ private readonly onFocusIn = (e: FocusEvent): void => {
281
+ const r = this.rowOf(e);
282
+ if (r) this.focusKey = r.id;
283
+ };
284
+
285
+ private readonly onKey = (e: KeyboardEvent): void => {
286
+ const t = e.composedPath()[0];
287
+ if (!(t instanceof HTMLElement) || t.tagName !== 'TR' || t.dataset['key'] === undefined) return;
288
+ if (e.key === 'Enter') {
289
+ e.preventDefault();
290
+ this.act(t.dataset['key']);
291
+ return;
292
+ }
293
+ // Windowed, the first and last rows may not be drawn: draw them, then move there.
294
+ if (this.windowed && (e.key === 'Home' || e.key === 'End')) {
295
+ e.preventDefault();
296
+ e.stopPropagation();
297
+ const last = e.key === 'End';
298
+ const row = this.rows[last ? this.rows.length - 1 : 0];
299
+ if (row === undefined) return;
300
+ this.focusKey = this.rowKey(row);
301
+ const n = this.rows.length;
302
+ const span = Math.max(1, this.range.to - this.range.from);
303
+ this.scrollToEnd(last);
304
+ // Drawn at once, before the scroll reports where the view is.
305
+ this.range = last ? { from: Math.max(0, n - span), to: n } : { from: 0, to: span };
306
+ this.held = true;
307
+ void this.updateComplete.then(() => this.renderRoot.querySelector<HTMLElement>(`tbody tr[data-key="${CSS.escape(this.focusKey ?? '')}"]`)?.focus());
308
+ }
309
+ };
310
+
311
+ private header(c: DataColumn<R>, s: DataTableStrings): TemplateResult {
312
+ const on = this.sort?.id === c.id ? this.sort.direction : null;
313
+ const sort = on === 'asc' ? 'ascending' : on === 'desc' ? 'descending' : nothing;
314
+ const label = isSortable(c)
315
+ ? html`<button type="button" class="sort" title=${on === 'asc' ? s.sortDescending : s.sortAscending}
316
+ @click=${() => emit(this, 'cae-sort', { id: c.id, direction: on === 'asc' ? 'desc' : 'asc' })}>${c.header}${on
317
+ ? html`<span class="arrow" aria-hidden="true">${on === 'asc' ? '▲' : '▼'}</span>`
318
+ : nothing}</button>`
319
+ : c.header;
320
+ return html`<th scope="col" role="columnheader" part="header-cell" data-col=${c.id} data-align=${c.align ?? nothing} aria-sort=${sort}
321
+ title=${c.tip || nothing}>${label}</th>`;
322
+ }
323
+
324
+ private row(r: R, index: number, head: string | undefined): TemplateResult {
325
+ const id = this.rowKey(r);
326
+ const sel = this.selected !== null && this.selected === id;
327
+ return html`<tr role="row" part=${sel ? 'row row-selected' : 'row'} data-key=${id} data-tone=${toneAttr(this.rowTone?.(r))}
328
+ aria-current=${sel ? 'true' : nothing} aria-rowindex=${this.windowed ? index + 2 : nothing} ${attrs(this.rowAttrs?.(r))}>
329
+ ${this.columns.map((c) =>
330
+ c.id === head
331
+ ? html`<th scope="row" role="rowheader" part="cell" data-col=${c.id} data-align=${c.align ?? nothing}>${c.cell(r, index)}</th>`
332
+ : html`<td role="cell" part="cell" data-col=${c.id} data-align=${c.align ?? nothing}>${c.cell(r, index)}</td>`,
333
+ )}
334
+ </tr>`;
335
+ }
336
+
337
+ override render() {
338
+ const s = withDefaults(DEFAULT_DATA_TABLE_STRINGS, this.strings);
339
+ const n = this.rows.length;
340
+ const tracks = this.columns.map((c) => c.width ?? 'minmax(0, 1fr)').join(' ');
341
+ const head = this.columns.find((c) => c.rowHeader)?.id;
342
+ const from = this.windowed ? this.range.from : 0;
343
+ const shown = this.shown();
344
+ const starts = this.windowed ? this.rowStarts() : null;
345
+ const padTop = starts ? starts[from]! : 0;
346
+ const padBottom = starts ? starts[n]! - starts[from + shown.length]! : 0;
347
+ return html`<table part="table" data-scroll="x" role="table" class=${this.activatable ? '' : 'passive'} style="--cae-data-table-columns: ${tracks}"
348
+ aria-rowcount=${this.windowed ? n + 1 : nothing}>
349
+ <caption part="caption"><slot name="caption">${this.caption}</slot></caption>
350
+ <thead part="head" role="rowgroup"><tr role="row">${this.columns.map((c) => this.header(c, s))}</tr></thead>
351
+ <tbody role="rowgroup" @click=${this.onClick} @keydown=${this.onKey} @focusin=${this.onFocusIn}>
352
+ ${padTop > 0 ? html`<tr class="spacer" aria-hidden="true" style="height: ${padTop}px"></tr>` : nothing}
353
+ ${repeat(shown, this.rowKey, (r, i) => this.row(r, from + i, head))}
354
+ ${padBottom > 0 ? html`<tr class="spacer" aria-hidden="true" style="height: ${padBottom}px"></tr>` : nothing}
355
+ ${n
356
+ ? nothing
357
+ : html`<tr class="empty" role="row"><td part="empty" role="cell" colspan=${this.columns.length || 1}><slot name="empty">${s.empty}</slot></td></tr>`}
358
+ </tbody>
359
+ </table>`;
360
+ }
361
+ }
362
+
363
+ declare global {
364
+ interface HTMLElementTagNameMap {
365
+ 'cae-data-table': CaeDataTable;
366
+ }
367
+ }
@@ -0,0 +1,5 @@
1
+ // A table of rows: `@contraagent/elements/data-table`. `CaeDataTable` is
2
+ // registered by `@contraagent/elements/data-table/define`.
3
+ export * from './types.js';
4
+ export * from './styles.js';
5
+ export * from './data-table.js';
@@ -0,0 +1,32 @@
1
+ // The look of `<cae-data-table>`. A row is a grid of the columns' tracks
2
+ // (`--cae-data-table-columns`, set from the columns' widths), so every row
3
+ // lines up with the header without a table layout pass. Rows wider than the
4
+ // host scroll sideways inside the table; the host is a container, so the
5
+ // host's `cellStyles` can drop or narrow columns by its width (`@container`).
6
+ import { css } from 'lit';
7
+
8
+ export const dataTableStyles = css`
9
+ :host { display: block; container-type: inline-size; }
10
+ table { display: block; width: 100%; border-collapse: collapse; overflow-x: auto; }
11
+ caption { display: block; text-align: start; }
12
+ thead, tbody { display: block; }
13
+ tr { display: grid; grid-template-columns: var(--cae-data-table-columns); column-gap: var(--cae-data-table-gap, 12px);
14
+ align-items: center; padding: var(--cae-data-table-row-padding, 6px 12px); }
15
+ th, td { display: block; min-width: 0; padding: 0; text-align: start; font-weight: inherit; }
16
+ [data-align='end'] { text-align: end; font-variant-numeric: tabular-nums; }
17
+ thead tr { color: var(--text-muted); font-size: var(--font-size-sm); border-bottom: 1px solid var(--line); }
18
+ tbody tr { border-bottom: 1px solid var(--line); }
19
+ tbody tr[data-key] { cursor: pointer; }
20
+ table.passive tbody tr[data-key] { cursor: default; }
21
+ tbody tr[data-key]:hover { background: var(--raise); }
22
+ tbody tr[data-key]:focus-visible { outline-offset: -2px; }
23
+ tbody tr[aria-current='true'] { background: var(--accent-bg); }
24
+ tbody tr[data-tone='running'] { background: var(--status-running-bg); }
25
+ tbody tr[data-tone='failed'] { background: color-mix(in srgb, var(--status-failed) 6%, transparent); box-shadow: inset 3px 0 0 var(--status-failed); }
26
+ tr.spacer { display: block; padding: 0; border: 0; }
27
+ tr.empty { display: block; border: 0; padding: 0; }
28
+ tr.empty td { color: var(--text-muted); padding: 8px; }
29
+ .sort { display: inline-flex; align-items: center; gap: 4px; padding: 0; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; }
30
+ .sort:hover { color: var(--text); }
31
+ .arrow { font-size: 0.85em; }
32
+ `;
@@ -0,0 +1,73 @@
1
+ // The data a `<cae-data-table>` shows: its columns, each a function of a row,
2
+ // and its words.
3
+
4
+ /** A column: its header, its width, and what a cell shows for a row. */
5
+ export interface DataColumn<R> {
6
+ /** Unique among the columns: `data-col` on its cells, the `id` of `cae-sort`. */
7
+ id: string;
8
+ header: string;
9
+ /** The header's tooltip. */
10
+ tip?: string;
11
+ /** `end` for numbers: right-aligned, tabular figures. */
12
+ align?: 'start' | 'end';
13
+ /** A CSS grid track: '72px', 'minmax(0, 1fr)' (the default). */
14
+ width?: string;
15
+ /** The cell: a template, a string or a number. */
16
+ cell: (row: R, index: number) => unknown;
17
+ /** The cell as plain text: what `sortRows` orders by when the column has no `compare`. */
18
+ text?: (row: R) => string;
19
+ /** The order of two rows by this column, ascending. */
20
+ compare?: (a: R, b: R) => number;
21
+ /**
22
+ * The header is a button that sends `cae-sort` (true when the column has `compare`).
23
+ * Without `compare` and `text`, `sortRows` orders by the cell when it is a string or a number.
24
+ */
25
+ sortable?: boolean;
26
+ /** The cell names its row (`<th scope="row">`): the first such column does. */
27
+ rowHeader?: boolean;
28
+ }
29
+
30
+ /** The column the rows are ordered by. */
31
+ export interface SortState {
32
+ id: string;
33
+ direction: 'asc' | 'desc';
34
+ }
35
+
36
+ export interface DataTableStrings {
37
+ /** The table has no rows. */
38
+ empty: string;
39
+ /** A sortable header's tooltip: the click orders the rows ascending. */
40
+ sortAscending: string;
41
+ /** A sortable header's tooltip: the click orders the rows descending. */
42
+ sortDescending: string;
43
+ }
44
+
45
+ export const DEFAULT_DATA_TABLE_STRINGS: Readonly<DataTableStrings> = {
46
+ empty: 'No rows',
47
+ sortAscending: 'Sort ascending',
48
+ sortDescending: 'Sort descending',
49
+ };
50
+
51
+ /** Whether a column's header sorts. */
52
+ export const isSortable = <R>(c: DataColumn<R>): boolean => c.sortable ?? !!c.compare;
53
+
54
+ /**
55
+ * `rows` ordered by the column `sort` names: by its `compare`, else its `text`, else
56
+ * its cell when that is a string or a number; equal rows keep their order. The rows
57
+ * as they are when no column matches.
58
+ */
59
+ export function sortRows<R>(rows: readonly R[], columns: readonly DataColumn<R>[], sort: SortState | null): R[] {
60
+ const c = sort && columns.find((x) => x.id === sort.id);
61
+ if (!sort || !c) return [...rows];
62
+ const sign = sort.direction === 'desc' ? -1 : 1;
63
+ const { compare, text } = c;
64
+ // A cell that is neither a string nor a number (a template) keeps its place.
65
+ const value = (r: R, i: number) => {
66
+ const v = text ? text(r) : c.cell(r, i);
67
+ return typeof v === 'number' || typeof v === 'string' ? v : '';
68
+ };
69
+ const keyed = rows.map((r, i) => ({ r, i, v: compare ? 0 : value(r, i) }));
70
+ const cmp = (a: (typeof keyed)[number], b: (typeof keyed)[number]) =>
71
+ compare ? compare(a.r, b.r) : typeof a.v === 'number' && typeof b.v === 'number' ? a.v - b.v : String(a.v).localeCompare(String(b.v), undefined, { numeric: true });
72
+ return keyed.sort((a, b) => sign * cmp(a, b) || a.i - b.i).map((x) => x.r);
73
+ }
@@ -0,0 +1,14 @@
1
+ // The page's theme before the first paint.
2
+ import { THEME_STORE_KEY } from './choice.js';
3
+ import { DEFAULT_THEME, SYSTEM_THEMES, THEME_CHOICES, THEME_NAMES } from './data.js';
4
+
5
+ /**
6
+ * A script for a page's `<head>`: it sets `data-ca-theme` on `<html>` from the
7
+ * reader's choice before the first paint, as `resolveTheme(preferredTheme(), prefersLight())`
8
+ * does. With `themeRules` in a `<style>` beside it, the page opens in its theme.
9
+ */
10
+ export const themeBootScript = `(function(){var c=null;try{c=localStorage.getItem(${JSON.stringify(THEME_STORE_KEY)})}catch(e){}
11
+ var names=${JSON.stringify(THEME_NAMES)},choices=${JSON.stringify(THEME_CHOICES)};
12
+ if(choices.indexOf(c)<0)c=${JSON.stringify(DEFAULT_THEME)};
13
+ if(c==="system")c=window.matchMedia&&matchMedia("(prefers-color-scheme: light)").matches?${JSON.stringify(SYSTEM_THEMES.light)}:${JSON.stringify(SYSTEM_THEMES.dark)};
14
+ if(names.indexOf(c)>=0)document.documentElement.setAttribute("data-ca-theme",c);})();`;
@@ -0,0 +1,47 @@
1
+ // The reader's choice of a theme: which theme it shows, and remembering it in
2
+ // this browser.
3
+ import { DEFAULT_THEME, SYSTEM_THEMES, THEME_CHOICES, THEME_NAMES, type ThemeChoice, type ThemeName } from './data.js';
4
+
5
+ export const isThemeName = (x: unknown): x is ThemeName => (THEME_NAMES as readonly unknown[]).includes(x);
6
+ export const isThemeChoice = (x: unknown): x is ThemeChoice => (THEME_CHOICES as readonly unknown[]).includes(x);
7
+
8
+ /** The theme a choice shows: `system` by the system's colour scheme; anything else not a theme, the default. */
9
+ export function resolveTheme(choice: unknown, prefersLight: boolean): ThemeName {
10
+ if (choice === 'system') return prefersLight ? SYSTEM_THEMES.light : SYSTEM_THEMES.dark;
11
+ return isThemeName(choice) ? choice : DEFAULT_THEME;
12
+ }
13
+
14
+ /** Where the reader's choice is kept (this browser only). */
15
+ export const THEME_STORE_KEY = 'contraagent:theme';
16
+
17
+ type Store = Pick<Storage, 'getItem' | 'setItem'>;
18
+ const storage = (): Store | undefined => {
19
+ try {
20
+ return globalThis.localStorage;
21
+ } catch {
22
+ return undefined;
23
+ }
24
+ };
25
+
26
+ /** The reader's choice from an earlier visit, else the default theme. */
27
+ export function preferredTheme(store: Store | undefined = storage()): ThemeChoice {
28
+ try {
29
+ const saved = store?.getItem(THEME_STORE_KEY);
30
+ if (isThemeChoice(saved)) return saved;
31
+ } catch {
32
+ /* storage blocked: the default */
33
+ }
34
+ return DEFAULT_THEME;
35
+ }
36
+
37
+ /** Remember the reader's choice for the next visit. */
38
+ export function rememberTheme(choice: ThemeChoice, store: Store | undefined = storage()): void {
39
+ try {
40
+ store?.setItem(THEME_STORE_KEY, choice);
41
+ } catch {
42
+ /* storage blocked: the choice lasts for this page */
43
+ }
44
+ }
45
+
46
+ /** Whether the system asks for a light colour scheme. */
47
+ export const prefersLight = (): boolean => globalThis.matchMedia?.('(prefers-color-scheme: light)').matches ?? false;