@joewinke/jatui 0.37.0 → 0.38.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 (266) hide show
  1. package/dist/artifact-blocks/AttachmentChip.svelte +66 -0
  2. package/dist/artifact-blocks/AttachmentChip.svelte.d.ts +7 -0
  3. package/dist/artifact-blocks/BlockComments.svelte +309 -0
  4. package/dist/artifact-blocks/BlockComments.svelte.d.ts +33 -0
  5. package/dist/artifact-blocks/BlockRenderer.svelte +674 -0
  6. package/dist/artifact-blocks/BlockRenderer.svelte.d.ts +55 -0
  7. package/dist/artifact-blocks/BlockVerdict.svelte +151 -0
  8. package/dist/artifact-blocks/BlockVerdict.svelte.d.ts +13 -0
  9. package/dist/artifact-blocks/BlocksArtifactView.svelte +1616 -0
  10. package/dist/artifact-blocks/BlocksArtifactView.svelte.d.ts +113 -0
  11. package/dist/artifact-blocks/CONTRACT.md +225 -0
  12. package/dist/artifact-blocks/CommentPill.svelte +49 -0
  13. package/dist/artifact-blocks/CommentPill.svelte.d.ts +16 -0
  14. package/dist/artifact-blocks/FoldedRounds.svelte +95 -0
  15. package/dist/artifact-blocks/FoldedRounds.svelte.d.ts +9 -0
  16. package/dist/artifact-blocks/Glyph.svelte +54 -0
  17. package/dist/artifact-blocks/Glyph.svelte.d.ts +10 -0
  18. package/dist/artifact-blocks/HistoryScrubber.svelte +500 -0
  19. package/dist/artifact-blocks/HistoryScrubber.svelte.d.ts +15 -0
  20. package/dist/artifact-blocks/Markdown.svelte +186 -0
  21. package/dist/artifact-blocks/Markdown.svelte.d.ts +30 -0
  22. package/dist/artifact-blocks/NoteComposer.svelte +31 -0
  23. package/dist/artifact-blocks/NoteComposer.svelte.d.ts +8 -0
  24. package/dist/artifact-blocks/PlainComposer.svelte +200 -0
  25. package/dist/artifact-blocks/PlainComposer.svelte.d.ts +15 -0
  26. package/dist/artifact-blocks/SectionTools.svelte +102 -0
  27. package/dist/artifact-blocks/SectionTools.svelte.d.ts +19 -0
  28. package/dist/artifact-blocks/adapter.d.ts +13 -0
  29. package/dist/artifact-blocks/adapter.js +31 -0
  30. package/dist/artifact-blocks/autoSend.d.ts +49 -0
  31. package/dist/artifact-blocks/autoSend.js +103 -0
  32. package/dist/artifact-blocks/blocks/actions/ActionsBlock.svelte +557 -0
  33. package/dist/artifact-blocks/blocks/actions/ActionsBlock.svelte.d.ts +48 -0
  34. package/dist/artifact-blocks/blocks/actions/block.d.ts +8 -0
  35. package/dist/artifact-blocks/blocks/actions/block.js +74 -0
  36. package/dist/artifact-blocks/blocks/actions/requests.d.ts +62 -0
  37. package/dist/artifact-blocks/blocks/actions/requests.js +26 -0
  38. package/dist/artifact-blocks/blocks/actions/schema.d.ts +168 -0
  39. package/dist/artifact-blocks/blocks/actions/schema.js +253 -0
  40. package/dist/artifact-blocks/blocks/callout/CalloutBlock.svelte +779 -0
  41. package/dist/artifact-blocks/blocks/callout/CalloutBlock.svelte.d.ts +40 -0
  42. package/dist/artifact-blocks/blocks/callout/block.d.ts +7 -0
  43. package/dist/artifact-blocks/blocks/callout/block.js +39 -0
  44. package/dist/artifact-blocks/blocks/callout/schema.d.ts +72 -0
  45. package/dist/artifact-blocks/blocks/callout/schema.js +115 -0
  46. package/dist/artifact-blocks/blocks/chart/ChartBlock.svelte +875 -0
  47. package/dist/artifact-blocks/blocks/chart/ChartBlock.svelte.d.ts +59 -0
  48. package/dist/artifact-blocks/blocks/chart/block.d.ts +9 -0
  49. package/dist/artifact-blocks/blocks/chart/block.js +70 -0
  50. package/dist/artifact-blocks/blocks/chart/schema.d.ts +171 -0
  51. package/dist/artifact-blocks/blocks/chart/schema.js +498 -0
  52. package/dist/artifact-blocks/blocks/chart/thumb.d.ts +2 -0
  53. package/dist/artifact-blocks/blocks/chart/thumb.js +201 -0
  54. package/dist/artifact-blocks/blocks/checklist/ChecklistBlock.svelte +1048 -0
  55. package/dist/artifact-blocks/blocks/checklist/ChecklistBlock.svelte.d.ts +16 -0
  56. package/dist/artifact-blocks/blocks/checklist/Icon.svelte +105 -0
  57. package/dist/artifact-blocks/blocks/checklist/Icon.svelte.d.ts +17 -0
  58. package/dist/artifact-blocks/blocks/checklist/block.d.ts +10 -0
  59. package/dist/artifact-blocks/blocks/checklist/block.js +63 -0
  60. package/dist/artifact-blocks/blocks/checklist/itemReview.d.ts +16 -0
  61. package/dist/artifact-blocks/blocks/checklist/itemReview.js +63 -0
  62. package/dist/artifact-blocks/blocks/checklist/labels.d.ts +62 -0
  63. package/dist/artifact-blocks/blocks/checklist/labels.js +96 -0
  64. package/dist/artifact-blocks/blocks/checklist/retest.d.ts +43 -0
  65. package/dist/artifact-blocks/blocks/checklist/retest.js +68 -0
  66. package/dist/artifact-blocks/blocks/checklist/schema.d.ts +84 -0
  67. package/dist/artifact-blocks/blocks/checklist/schema.js +91 -0
  68. package/dist/artifact-blocks/blocks/code/CodeBlock.svelte +128 -0
  69. package/dist/artifact-blocks/blocks/code/CodeBlock.svelte.d.ts +12 -0
  70. package/dist/artifact-blocks/blocks/code/block.d.ts +8 -0
  71. package/dist/artifact-blocks/blocks/code/block.js +31 -0
  72. package/dist/artifact-blocks/blocks/code/highlight.d.ts +34 -0
  73. package/dist/artifact-blocks/blocks/code/highlight.js +280 -0
  74. package/dist/artifact-blocks/blocks/code/schema.d.ts +32 -0
  75. package/dist/artifact-blocks/blocks/code/schema.js +39 -0
  76. package/dist/artifact-blocks/blocks/collage/CollageBlock.svelte +290 -0
  77. package/dist/artifact-blocks/blocks/collage/CollageBlock.svelte.d.ts +29 -0
  78. package/dist/artifact-blocks/blocks/collage/block.d.ts +9 -0
  79. package/dist/artifact-blocks/blocks/collage/block.js +29 -0
  80. package/dist/artifact-blocks/blocks/collage/schema.d.ts +52 -0
  81. package/dist/artifact-blocks/blocks/collage/schema.js +86 -0
  82. package/dist/artifact-blocks/blocks/compare/CompareBlock.svelte +484 -0
  83. package/dist/artifact-blocks/blocks/compare/CompareBlock.svelte.d.ts +25 -0
  84. package/dist/artifact-blocks/blocks/compare/block.d.ts +9 -0
  85. package/dist/artifact-blocks/blocks/compare/block.js +32 -0
  86. package/dist/artifact-blocks/blocks/compare/schema.d.ts +74 -0
  87. package/dist/artifact-blocks/blocks/compare/schema.js +148 -0
  88. package/dist/artifact-blocks/blocks/diagram/DiagramBlock.svelte +392 -0
  89. package/dist/artifact-blocks/blocks/diagram/DiagramBlock.svelte.d.ts +30 -0
  90. package/dist/artifact-blocks/blocks/diagram/block.d.ts +9 -0
  91. package/dist/artifact-blocks/blocks/diagram/block.js +50 -0
  92. package/dist/artifact-blocks/blocks/diagram/constants.d.ts +48 -0
  93. package/dist/artifact-blocks/blocks/diagram/constants.js +53 -0
  94. package/dist/artifact-blocks/blocks/diagram/schema.d.ts +161 -0
  95. package/dist/artifact-blocks/blocks/diagram/schema.js +621 -0
  96. package/dist/artifact-blocks/blocks/diagram/thumb.d.ts +2 -0
  97. package/dist/artifact-blocks/blocks/diagram/thumb.js +157 -0
  98. package/dist/artifact-blocks/blocks/diagram/types.d.ts +74 -0
  99. package/dist/artifact-blocks/blocks/diagram/types.js +1 -0
  100. package/dist/artifact-blocks/blocks/diff/DiffBlock.svelte +81 -0
  101. package/dist/artifact-blocks/blocks/diff/DiffBlock.svelte.d.ts +10 -0
  102. package/dist/artifact-blocks/blocks/diff/block.d.ts +7 -0
  103. package/dist/artifact-blocks/blocks/diff/block.js +36 -0
  104. package/dist/artifact-blocks/blocks/diff/schema.d.ts +18 -0
  105. package/dist/artifact-blocks/blocks/diff/schema.js +35 -0
  106. package/dist/artifact-blocks/blocks/diff-review/DiffReviewBlock.svelte +1055 -0
  107. package/dist/artifact-blocks/blocks/diff-review/DiffReviewBlock.svelte.d.ts +5 -0
  108. package/dist/artifact-blocks/blocks/diff-review/block.d.ts +15 -0
  109. package/dist/artifact-blocks/blocks/diff-review/block.js +64 -0
  110. package/dist/artifact-blocks/blocks/diff-review/decisions.d.ts +57 -0
  111. package/dist/artifact-blocks/blocks/diff-review/decisions.js +80 -0
  112. package/dist/artifact-blocks/blocks/diff-review/schema.d.ts +13 -0
  113. package/dist/artifact-blocks/blocks/diff-review/schema.js +84 -0
  114. package/dist/artifact-blocks/blocks/diff-review/types.d.ts +35 -0
  115. package/dist/artifact-blocks/blocks/diff-review/types.js +1 -0
  116. package/dist/artifact-blocks/blocks/explainer/ExplainerBlock.svelte +145 -0
  117. package/dist/artifact-blocks/blocks/explainer/ExplainerBlock.svelte.d.ts +5 -0
  118. package/dist/artifact-blocks/blocks/explainer/block.d.ts +8 -0
  119. package/dist/artifact-blocks/blocks/explainer/block.js +21 -0
  120. package/dist/artifact-blocks/blocks/explainer/schema.d.ts +26 -0
  121. package/dist/artifact-blocks/blocks/explainer/schema.js +69 -0
  122. package/dist/artifact-blocks/blocks/group-content.d.ts +10 -0
  123. package/dist/artifact-blocks/blocks/group-content.js +16 -0
  124. package/dist/artifact-blocks/blocks/group-data.d.ts +10 -0
  125. package/dist/artifact-blocks/blocks/group-data.js +7 -0
  126. package/dist/artifact-blocks/blocks/group-review.d.ts +10 -0
  127. package/dist/artifact-blocks/blocks/group-review.js +12 -0
  128. package/dist/artifact-blocks/blocks/group-visual.d.ts +17 -0
  129. package/dist/artifact-blocks/blocks/group-visual.js +14 -0
  130. package/dist/artifact-blocks/blocks/map/MapBlock.svelte +413 -0
  131. package/dist/artifact-blocks/blocks/map/MapBlock.svelte.d.ts +53 -0
  132. package/dist/artifact-blocks/blocks/map/block.d.ts +9 -0
  133. package/dist/artifact-blocks/blocks/map/block.js +62 -0
  134. package/dist/artifact-blocks/blocks/map/schema.d.ts +123 -0
  135. package/dist/artifact-blocks/blocks/map/schema.js +113 -0
  136. package/dist/artifact-blocks/blocks/map/thumb.d.ts +2 -0
  137. package/dist/artifact-blocks/blocks/map/thumb.js +69 -0
  138. package/dist/artifact-blocks/blocks/markdown/MarkdownBlock.svelte +33 -0
  139. package/dist/artifact-blocks/blocks/markdown/MarkdownBlock.svelte.d.ts +15 -0
  140. package/dist/artifact-blocks/blocks/markdown/block.d.ts +7 -0
  141. package/dist/artifact-blocks/blocks/markdown/block.js +28 -0
  142. package/dist/artifact-blocks/blocks/markdown/render.d.ts +17 -0
  143. package/dist/artifact-blocks/blocks/markdown/render.js +115 -0
  144. package/dist/artifact-blocks/blocks/markdown/schema.d.ts +10 -0
  145. package/dist/artifact-blocks/blocks/markdown/schema.js +23 -0
  146. package/dist/artifact-blocks/blocks/media-picker/MediaPickerBlock.svelte +2112 -0
  147. package/dist/artifact-blocks/blocks/media-picker/MediaPickerBlock.svelte.d.ts +5 -0
  148. package/dist/artifact-blocks/blocks/media-picker/block.d.ts +24 -0
  149. package/dist/artifact-blocks/blocks/media-picker/block.js +137 -0
  150. package/dist/artifact-blocks/blocks/media-picker/choices.d.ts +28 -0
  151. package/dist/artifact-blocks/blocks/media-picker/choices.js +35 -0
  152. package/dist/artifact-blocks/blocks/media-picker/decisions.d.ts +51 -0
  153. package/dist/artifact-blocks/blocks/media-picker/decisions.js +75 -0
  154. package/dist/artifact-blocks/blocks/media-picker/schema.d.ts +7 -0
  155. package/dist/artifact-blocks/blocks/media-picker/schema.js +199 -0
  156. package/dist/artifact-blocks/blocks/media-picker/types.d.ts +92 -0
  157. package/dist/artifact-blocks/blocks/media-picker/types.js +1 -0
  158. package/dist/artifact-blocks/blocks/media-picker/versions.d.ts +51 -0
  159. package/dist/artifact-blocks/blocks/media-picker/versions.js +118 -0
  160. package/dist/artifact-blocks/blocks/mockup/MockupBlock.svelte +213 -0
  161. package/dist/artifact-blocks/blocks/mockup/MockupBlock.svelte.d.ts +5 -0
  162. package/dist/artifact-blocks/blocks/mockup/block.d.ts +26 -0
  163. package/dist/artifact-blocks/blocks/mockup/block.js +52 -0
  164. package/dist/artifact-blocks/blocks/mockup/doc.d.ts +24 -0
  165. package/dist/artifact-blocks/blocks/mockup/doc.js +44 -0
  166. package/dist/artifact-blocks/blocks/mockup/sandbox.d.ts +21 -0
  167. package/dist/artifact-blocks/blocks/mockup/sandbox.js +27 -0
  168. package/dist/artifact-blocks/blocks/mockup/schema.d.ts +7 -0
  169. package/dist/artifact-blocks/blocks/mockup/schema.js +90 -0
  170. package/dist/artifact-blocks/blocks/mockup/types.d.ts +36 -0
  171. package/dist/artifact-blocks/blocks/mockup/types.js +17 -0
  172. package/dist/artifact-blocks/blocks/program/ProgramBlock.svelte +359 -0
  173. package/dist/artifact-blocks/blocks/program/ProgramBlock.svelte.d.ts +32 -0
  174. package/dist/artifact-blocks/blocks/program/block.d.ts +35 -0
  175. package/dist/artifact-blocks/blocks/program/block.js +68 -0
  176. package/dist/artifact-blocks/blocks/program/schema.d.ts +132 -0
  177. package/dist/artifact-blocks/blocks/program/schema.js +268 -0
  178. package/dist/artifact-blocks/blocks/stats/StatsBlock.svelte +315 -0
  179. package/dist/artifact-blocks/blocks/stats/StatsBlock.svelte.d.ts +24 -0
  180. package/dist/artifact-blocks/blocks/stats/block.d.ts +7 -0
  181. package/dist/artifact-blocks/blocks/stats/block.js +49 -0
  182. package/dist/artifact-blocks/blocks/stats/schema.d.ts +82 -0
  183. package/dist/artifact-blocks/blocks/stats/schema.js +43 -0
  184. package/dist/artifact-blocks/blocks/stats/thumb.d.ts +2 -0
  185. package/dist/artifact-blocks/blocks/stats/thumb.js +102 -0
  186. package/dist/artifact-blocks/blocks/table/TableBlock.svelte +490 -0
  187. package/dist/artifact-blocks/blocks/table/TableBlock.svelte.d.ts +28 -0
  188. package/dist/artifact-blocks/blocks/table/block.d.ts +9 -0
  189. package/dist/artifact-blocks/blocks/table/block.js +100 -0
  190. package/dist/artifact-blocks/blocks/table/schema.d.ts +143 -0
  191. package/dist/artifact-blocks/blocks/table/schema.js +278 -0
  192. package/dist/artifact-blocks/blocks/timeline/TimelineBlock.svelte +347 -0
  193. package/dist/artifact-blocks/blocks/timeline/TimelineBlock.svelte.d.ts +42 -0
  194. package/dist/artifact-blocks/blocks/timeline/block.d.ts +9 -0
  195. package/dist/artifact-blocks/blocks/timeline/block.js +96 -0
  196. package/dist/artifact-blocks/blocks/timeline/constants.d.ts +26 -0
  197. package/dist/artifact-blocks/blocks/timeline/constants.js +27 -0
  198. package/dist/artifact-blocks/blocks/timeline/schema.d.ts +102 -0
  199. package/dist/artifact-blocks/blocks/timeline/schema.js +405 -0
  200. package/dist/artifact-blocks/blocks/timeline/thumb.d.ts +2 -0
  201. package/dist/artifact-blocks/blocks/timeline/thumb.js +117 -0
  202. package/dist/artifact-blocks/blocks/timeline/types.d.ts +66 -0
  203. package/dist/artifact-blocks/blocks/timeline/types.js +1 -0
  204. package/dist/artifact-blocks/blocks/transcript/TranscriptBlock.svelte +169 -0
  205. package/dist/artifact-blocks/blocks/transcript/TranscriptBlock.svelte.d.ts +26 -0
  206. package/dist/artifact-blocks/blocks/transcript/block.d.ts +9 -0
  207. package/dist/artifact-blocks/blocks/transcript/block.js +86 -0
  208. package/dist/artifact-blocks/blocks/transcript/schema.d.ts +114 -0
  209. package/dist/artifact-blocks/blocks/transcript/schema.js +126 -0
  210. package/dist/artifact-blocks/builtins.d.ts +40 -0
  211. package/dist/artifact-blocks/builtins.js +22 -0
  212. package/dist/artifact-blocks/contractBlocks.d.ts +92 -0
  213. package/dist/artifact-blocks/contractBlocks.js +279 -0
  214. package/dist/artifact-blocks/history.d.ts +140 -0
  215. package/dist/artifact-blocks/history.js +363 -0
  216. package/dist/artifact-blocks/index.d.ts +40 -0
  217. package/dist/artifact-blocks/index.js +46 -0
  218. package/dist/artifact-blocks/listen/context.d.ts +30 -0
  219. package/dist/artifact-blocks/listen/context.js +30 -0
  220. package/dist/artifact-blocks/liveData.d.ts +78 -0
  221. package/dist/artifact-blocks/liveData.js +137 -0
  222. package/dist/artifact-blocks/liveDataPoller.d.ts +41 -0
  223. package/dist/artifact-blocks/liveDataPoller.js +140 -0
  224. package/dist/artifact-blocks/openNav.d.ts +46 -0
  225. package/dist/artifact-blocks/openNav.js +106 -0
  226. package/dist/artifact-blocks/pageReviewKeys.d.ts +17 -0
  227. package/dist/artifact-blocks/pageReviewKeys.js +115 -0
  228. package/dist/artifact-blocks/params.d.ts +98 -0
  229. package/dist/artifact-blocks/params.js +159 -0
  230. package/dist/artifact-blocks/registry.d.ts +27 -0
  231. package/dist/artifact-blocks/registry.js +83 -0
  232. package/dist/artifact-blocks/review/BlockIcon.svelte +99 -0
  233. package/dist/artifact-blocks/review/BlockIcon.svelte.d.ts +17 -0
  234. package/dist/artifact-blocks/review/BulkRejectForm.svelte +94 -0
  235. package/dist/artifact-blocks/review/BulkRejectForm.svelte.d.ts +11 -0
  236. package/dist/artifact-blocks/review/BulkUndoBar.svelte +40 -0
  237. package/dist/artifact-blocks/review/BulkUndoBar.svelte.d.ts +9 -0
  238. package/dist/artifact-blocks/review/ItemNote.svelte +193 -0
  239. package/dist/artifact-blocks/review/ItemNote.svelte.d.ts +33 -0
  240. package/dist/artifact-blocks/review/NoteToggle.svelte +52 -0
  241. package/dist/artifact-blocks/review/NoteToggle.svelte.d.ts +12 -0
  242. package/dist/artifact-blocks/review/TeamChip.svelte +71 -0
  243. package/dist/artifact-blocks/review/TeamChip.svelte.d.ts +8 -0
  244. package/dist/artifact-blocks/review/attachments.d.ts +10 -0
  245. package/dist/artifact-blocks/review/attachments.js +37 -0
  246. package/dist/artifact-blocks/review/bulk.d.ts +52 -0
  247. package/dist/artifact-blocks/review/bulk.js +61 -0
  248. package/dist/artifact-blocks/review/itemReview.d.ts +33 -0
  249. package/dist/artifact-blocks/review/itemReview.js +112 -0
  250. package/dist/artifact-blocks/review/roundLines.d.ts +14 -0
  251. package/dist/artifact-blocks/review/roundLines.js +20 -0
  252. package/dist/artifact-blocks/review/rounds.d.ts +86 -0
  253. package/dist/artifact-blocks/review/rounds.js +302 -0
  254. package/dist/artifact-blocks/review/saver.d.ts +23 -0
  255. package/dist/artifact-blocks/review/saver.js +48 -0
  256. package/dist/artifact-blocks/review/team.d.ts +31 -0
  257. package/dist/artifact-blocks/review/team.js +42 -0
  258. package/dist/artifact-blocks/review/visualOrder.d.ts +29 -0
  259. package/dist/artifact-blocks/review/visualOrder.js +66 -0
  260. package/dist/artifact-blocks/review.d.ts +180 -0
  261. package/dist/artifact-blocks/review.js +716 -0
  262. package/dist/artifact-blocks/thumb-kit.d.ts +80 -0
  263. package/dist/artifact-blocks/thumb-kit.js +149 -0
  264. package/dist/artifact-blocks/types.d.ts +513 -0
  265. package/dist/artifact-blocks/types.js +1 -0
  266. package/package.json +11 -2
@@ -0,0 +1,500 @@
1
+ <script lang="ts">
2
+ /**
3
+ * HistoryScrubber (origin mos-p9m3g, living artifacts phase 4) — "what did
4
+ * this page look like yesterday at 9am?"
5
+ *
6
+ * A collapsed "History" control on a blocks page. On mount it loads the
7
+ * timeline through the host's HistoryService (layout versions + data
8
+ * snapshots) and renders NOTHING until there is something to scrub: a page
9
+ * with one version and no data trail (or a failed load) shows no control.
10
+ * Opened, a slider walks the timeline stop by stop, ending at "Now". At any
11
+ * past stop it shows:
12
+ *
13
+ * - which layout version and which data snapshot were live then;
14
+ * - the diff of that data against now — KPI deltas for stats-shaped
15
+ * values, added / removed / changed rows for tables, changed leaves for
16
+ * anything else (history.ts diffData);
17
+ * - the page itself as it was, rendered read-only by BlockRenderer from
18
+ * the past spec + past data.
19
+ *
20
+ * "Compare with" swaps "now" for a second stop: diff A → B.
21
+ *
22
+ * Self-contained by design: the view mounts it with the artifact id, the
23
+ * live data it is already polling and the host's HistoryService; no
24
+ * service → it is not mounted.
25
+ */
26
+ import BlockRenderer from "./BlockRenderer.svelte"
27
+ import {
28
+ buildTimeline,
29
+ diffData,
30
+ formatDelta,
31
+ HISTORY_RETENTION,
32
+ type DataDiff,
33
+ type HistorySnapshot,
34
+ type HistoryVersion,
35
+ type TimelinePoint,
36
+ } from "./history.js"
37
+ import type { HistoryPastState, HistoryService } from "./types.js"
38
+
39
+ interface Props {
40
+ artifactId: string
41
+ /** The live data the host is showing now (its poller's blob). */
42
+ currentData: Record<string, unknown>
43
+ /** The layout version live now. */
44
+ currentVersion: number
45
+ /** The host's history reads (HostAdapter.history). */
46
+ service: HistoryService
47
+ /** Start expanded once there is a trail (tests, deep links). */
48
+ open?: boolean
49
+ }
50
+
51
+ let {
52
+ artifactId,
53
+ currentData,
54
+ currentVersion,
55
+ service,
56
+ open = $bindable(false),
57
+ }: Props = $props()
58
+
59
+ type PastState = HistoryPastState
60
+
61
+ /** A stop on the slider: a timeline point, or the synthetic "Now" end. */
62
+ type Stop = TimelinePoint | { kind: "now"; at: null; ms: number }
63
+
64
+ let loadState = $state<"idle" | "loading" | "ready" | "error">("idle")
65
+ let versions: HistoryVersion[] = $state([])
66
+ let snapshots: HistorySnapshot[] = $state([])
67
+ let trailStartAt: string | null = $state(null)
68
+
69
+ const stops: Stop[] = $derived([
70
+ ...buildTimeline(versions, snapshots),
71
+ { kind: "now", at: null, ms: Infinity },
72
+ ])
73
+
74
+ /** Selected stop (A), and the compare-with stop (B) in compare mode. */
75
+ let index = $state(0)
76
+ let compare = $state(false)
77
+ let compareIndex = $state(0)
78
+
79
+ const stateCache = new Map<string, PastState>()
80
+ let selected = $state<PastState | null>(null)
81
+ let compared = $state<PastState | null>(null)
82
+ let stateError = $state("")
83
+ let fetching = $state(false)
84
+
85
+ const dateFmt = new Intl.DateTimeFormat(undefined, {
86
+ dateStyle: "medium",
87
+ timeStyle: "short",
88
+ })
89
+
90
+ function fmt(iso: string | null): string {
91
+ if (!iso) return "now"
92
+ const d = new Date(iso)
93
+ return Number.isNaN(d.getTime()) ? iso : dateFmt.format(d)
94
+ }
95
+
96
+ function stopLabel(s: Stop): string {
97
+ if (s.kind === "now") return "Now (live)"
98
+ if (s.kind === "version") return `${fmt(s.at)} · layout v${s.version}`
99
+ return `${fmt(s.at)} · data update`
100
+ }
101
+
102
+ async function loadTimeline() {
103
+ loadState = "loading"
104
+ try {
105
+ const body = (await service.timeline({ artifactId })) as {
106
+ versions?: HistoryVersion[]
107
+ snapshots?: HistorySnapshot[]
108
+ trailStart?: string | null
109
+ }
110
+ versions = Array.isArray(body.versions) ? body.versions : []
111
+ snapshots = Array.isArray(body.snapshots) ? body.snapshots : []
112
+ trailStartAt = body.trailStart ?? null
113
+ index = stops.length - 1
114
+ compareIndex = stops.length - 1
115
+ loadState = "ready"
116
+ } catch {
117
+ // History is an optional affordance: a page whose trail cannot be read
118
+ // simply shows no control, never an error the viewer cannot act on.
119
+ loadState = "error"
120
+ }
121
+ }
122
+
123
+ $effect(() => {
124
+ if (loadState === "idle") void loadTimeline()
125
+ })
126
+
127
+ /** Something to scrub: more than the single layout version + "Now". */
128
+ const hasTrail = $derived(loadState === "ready" && stops.length > 2)
129
+
130
+ async function fetchState(s: Stop): Promise<PastState | null> {
131
+ if (s.kind === "now") return null
132
+ const hit = stateCache.get(s.at)
133
+ if (hit) return hit
134
+ const body = await service.at({ artifactId, at: s.at })
135
+ stateCache.set(s.at, body)
136
+ return body
137
+ }
138
+
139
+ // Resolve the selected (and compared) stops. Debounced so dragging the
140
+ // slider asks for the stop it lands on, not every stop it crosses; a
141
+ // stale response never overwrites a newer selection.
142
+ let ticket = 0
143
+ $effect(() => {
144
+ if (loadState !== "ready") return
145
+ const a = stops[index]
146
+ const b = compare ? stops[compareIndex] : undefined
147
+ const mine = ++ticket
148
+ const run = async () => {
149
+ fetching = true
150
+ stateError = ""
151
+ try {
152
+ const [sa, sb] = await Promise.all([
153
+ a ? fetchState(a) : null,
154
+ b ? fetchState(b) : null,
155
+ ])
156
+ if (mine !== ticket) return
157
+ selected = sa
158
+ compared = sb
159
+ } catch {
160
+ if (mine === ticket) stateError = "Could not load that point in time."
161
+ } finally {
162
+ if (mine === ticket) fetching = false
163
+ }
164
+ }
165
+ const t = setTimeout(run, 150)
166
+ return () => clearTimeout(t)
167
+ })
168
+
169
+ const atNow = $derived(stops[index]?.kind === "now")
170
+ const bAtNow = $derived(!compare || stops[compareIndex]?.kind === "now")
171
+
172
+ /** A's data and B's data (B = now unless comparing). */
173
+ const fromData = $derived(atNow ? currentData : (selected?.data ?? null))
174
+ const toData = $derived(bAtNow ? currentData : (compared?.data ?? null))
175
+ const fromVersion = $derived(atNow ? currentVersion : selected?.version)
176
+ const toVersion = $derived(bAtNow ? currentVersion : compared?.version)
177
+
178
+ const diff: DataDiff | null = $derived(
179
+ fromData && toData && !(atNow && bAtNow)
180
+ ? diffData(fromData, toData)
181
+ : null,
182
+ )
183
+ const changed = $derived(
184
+ diff ? diff.keys.filter((k) => k.status !== "same") : [],
185
+ )
186
+
187
+ function step(delta: number) {
188
+ index = Math.min(stops.length - 1, Math.max(0, index + delta))
189
+ }
190
+
191
+ // Change is shown by sign, never by color: whether "up" is good is the
192
+ // metric's business (a stats card's goodDirection), not the diff's.
193
+
194
+ function num(v: number | null): string {
195
+ return v === null
196
+ ? "-"
197
+ : v.toLocaleString(undefined, { maximumFractionDigits: 2 })
198
+ }
199
+
200
+ function leafText(v: unknown): string {
201
+ if (v === undefined) return "-"
202
+ const s = typeof v === "string" ? v : JSON.stringify(v)
203
+ return s.length > 60 ? `${s.slice(0, 59)}…` : s
204
+ }
205
+
206
+ const toLabel = $derived(
207
+ bAtNow ? "now" : fmt(stops[compareIndex]?.at ?? null),
208
+ )
209
+ </script>
210
+
211
+ {#if hasTrail}
212
+ <!-- mos-8fvt9: collapsed, one quiet line (no card, no comment pill);
213
+ opened, the scrubber's card. -->
214
+ <section
215
+ class={open
216
+ ? "border-base-content/10 bg-base-100 rounded-box mb-4 border"
217
+ : "mb-2"}
218
+ aria-label="Page history"
219
+ data-history-scrubber
220
+ >
221
+ <button
222
+ type="button"
223
+ class={open
224
+ ? "btn btn-ghost btn-sm rounded-field w-full justify-between"
225
+ : "btn btn-ghost btn-xs rounded-field text-base-content/60 -ml-2 gap-1.5 font-normal"}
226
+ aria-expanded={open}
227
+ onclick={() => (open = !open)}
228
+ >
229
+ {#if open}
230
+ <span>History</span>
231
+ <span class="text-base-content/60 text-xs font-normal">Hide</span>
232
+ {:else}
233
+ <!-- History glyph (lucide "history" path), inline: no icon dependency. -->
234
+ <svg
235
+ width="14"
236
+ height="14"
237
+ viewBox="0 0 24 24"
238
+ fill="none"
239
+ stroke="currentColor"
240
+ stroke-width="2"
241
+ stroke-linecap="round"
242
+ stroke-linejoin="round"
243
+ aria-hidden="true"
244
+ ><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" /><path
245
+ d="M3 3v5h5"
246
+ /><path d="M12 7v5l4 2" /></svg
247
+ >
248
+ <span>History</span>
249
+ <span class="text-base-content/40"
250
+ >· see this page at an earlier time</span
251
+ >
252
+ {/if}
253
+ </button>
254
+
255
+ {#if open}
256
+ <div class="border-base-content/10 space-y-4 border-t p-3 sm:p-4">
257
+ <div class="space-y-2">
258
+ <label
259
+ class="block text-sm font-medium"
260
+ for="history-at-{artifactId}"
261
+ >
262
+ {compare ? "Compare from" : "Show the page as it was at"}
263
+ </label>
264
+ <input
265
+ id="history-at-{artifactId}"
266
+ type="range"
267
+ class="range range-sm range-primary w-full"
268
+ min="0"
269
+ max={stops.length - 1}
270
+ step="1"
271
+ bind:value={index}
272
+ aria-valuetext={stopLabel(stops[index])}
273
+ />
274
+ <div class="flex flex-wrap items-center gap-2">
275
+ <button
276
+ type="button"
277
+ class="btn btn-ghost btn-xs rounded-field"
278
+ disabled={index === 0}
279
+ onclick={() => step(-1)}
280
+ aria-label="Earlier point">← Earlier</button
281
+ >
282
+ <button
283
+ type="button"
284
+ class="btn btn-ghost btn-xs rounded-field"
285
+ disabled={index === stops.length - 1}
286
+ onclick={() => step(1)}
287
+ aria-label="Later point">Later →</button
288
+ >
289
+ <button
290
+ type="button"
291
+ class="btn btn-ghost btn-xs rounded-field"
292
+ disabled={atNow}
293
+ onclick={() => (index = stops.length - 1)}>Back to now</button
294
+ >
295
+ <label class="label ml-auto cursor-pointer gap-2 text-sm">
296
+ <input
297
+ type="checkbox"
298
+ class="toggle toggle-sm"
299
+ bind:checked={compare}
300
+ />
301
+ Compare with…
302
+ </label>
303
+ </div>
304
+ <p class="text-sm" aria-live="polite" data-history-selected>
305
+ <span class="font-medium">{stopLabel(stops[index])}</span>
306
+ <span class="text-base-content/60">
307
+ · {index + 1} of {stops.length}</span
308
+ >
309
+ </p>
310
+
311
+ {#if compare}
312
+ <label
313
+ class="block pt-2 text-sm font-medium"
314
+ for="history-to-{artifactId}">Compare to</label
315
+ >
316
+ <input
317
+ id="history-to-{artifactId}"
318
+ type="range"
319
+ class="range range-sm range-secondary w-full"
320
+ min="0"
321
+ max={stops.length - 1}
322
+ step="1"
323
+ bind:value={compareIndex}
324
+ aria-valuetext={stopLabel(stops[compareIndex])}
325
+ />
326
+ <p class="text-sm" data-history-compared>
327
+ <span class="font-medium">{stopLabel(stops[compareIndex])}</span>
328
+ </p>
329
+ {/if}
330
+ </div>
331
+
332
+ {#if trailStartAt}
333
+ <p class="text-base-content/60 text-xs">
334
+ Data history starts {fmt(trailStartAt)}. Up to {HISTORY_RETENTION.maxSnapshots}
335
+ updates from the last {HISTORY_RETENTION.maxAgeDays} days are kept.
336
+ </p>
337
+ {/if}
338
+
339
+ {#if stateError}
340
+ <div
341
+ role="alert"
342
+ class="border-error/30 bg-error/10 text-error-content rounded-box border p-3 text-sm"
343
+ >
344
+ {stateError}
345
+ </div>
346
+ {:else if atNow && bAtNow}
347
+ <p class="text-base-content/70 text-sm">
348
+ You are looking at the live page. Move the slider back to see an
349
+ earlier state and what changed since.
350
+ </p>
351
+ {:else if fetching && !diff}
352
+ <p class="text-base-content/70 text-sm" role="status">Loading…</p>
353
+ {:else if diff}
354
+ <div class="space-y-3" data-history-diff>
355
+ <h3 class="text-sm font-semibold">
356
+ What changed, {atNow ? "now" : fmt(stops[index]?.at ?? null)} → {toLabel}
357
+ </h3>
358
+ {#if fromVersion !== undefined && toVersion !== undefined && fromVersion !== toVersion}
359
+ <p class="text-sm">
360
+ Layout changed: v{fromVersion} → v{toVersion}
361
+ </p>
362
+ {/if}
363
+ {#if selected?.beforeTrail && !atNow}
364
+ <p
365
+ class="bg-warning/10 text-warning-content rounded-box p-2 text-xs"
366
+ >
367
+ This point is older than the retained data history; the page
368
+ shows its built-in numbers, which may differ from what was on
369
+ screen then.
370
+ </p>
371
+ {/if}
372
+ {#if changed.length === 0}
373
+ <p class="text-base-content/70 text-sm">No data changed.</p>
374
+ {/if}
375
+ {#each changed as k (k.key)}
376
+ <div class="border-base-content/10 rounded-box border p-2">
377
+ <p class="text-sm font-medium">
378
+ <code class="text-xs">{k.key}</code>
379
+ {#if k.status === "added"}
380
+ <span class="badge badge-success badge-sm ml-1">added</span>
381
+ {:else if k.status === "removed"}
382
+ <span class="badge badge-error badge-sm ml-1">removed</span>
383
+ {/if}
384
+ </p>
385
+ {#if k.status === "changed" && k.shape === "kpi"}
386
+ <div class="overflow-x-auto">
387
+ <table class="table table-xs mt-1">
388
+ <thead>
389
+ <tr>
390
+ <th scope="col">Metric</th>
391
+ <th scope="col" class="text-right">Then</th>
392
+ <th scope="col" class="text-right">Now</th>
393
+ <th scope="col" class="text-right">Change</th>
394
+ </tr>
395
+ </thead>
396
+ <tbody>
397
+ {#each k.kpis as kpi (kpi.label)}
398
+ <tr>
399
+ <th scope="row" class="font-normal">{kpi.label}</th>
400
+ <td class="text-right tabular-nums"
401
+ >{num(kpi.then)}</td
402
+ >
403
+ <td class="text-right tabular-nums"
404
+ >{num(kpi.now)}</td
405
+ >
406
+ <td class="text-right font-medium tabular-nums">
407
+ {kpi.delta === null
408
+ ? "-"
409
+ : formatDelta(kpi.delta, kpi.pct)}
410
+ </td>
411
+ </tr>
412
+ {/each}
413
+ </tbody>
414
+ </table>
415
+ </div>
416
+ {:else if k.status === "changed" && k.shape === "table"}
417
+ <p class="text-sm">
418
+ <span class="text-success">{k.added.length} added</span>
419
+ · <span class="text-error">{k.removed.length} removed</span>
420
+ · <span>{k.changed.length} changed</span>
421
+ {#if k.truncated}
422
+ <span class="text-base-content/60">
423
+ (+{k.truncated} more)</span
424
+ >
425
+ {/if}
426
+ </p>
427
+ <ul class="mt-1 space-y-0.5 text-xs">
428
+ {#each k.added as r (`a-${r.key}`)}
429
+ <li><span class="text-success">+</span> {r.key}</li>
430
+ {/each}
431
+ {#each k.removed as r (`r-${r.key}`)}
432
+ <li><span class="text-error">−</span> {r.key}</li>
433
+ {/each}
434
+ {#each k.changed as r (`c-${r.key}`)}
435
+ <li>
436
+ <span class="text-base-content/60">~</span>
437
+ {r.key}:
438
+ <span class="text-base-content/70"
439
+ >{r.fields.join(", ")}</span
440
+ >
441
+ </li>
442
+ {/each}
443
+ </ul>
444
+ {:else if k.status === "changed" && k.shape === "value"}
445
+ <ul class="mt-1 space-y-0.5 text-xs">
446
+ {#each k.leaves as l (l.path)}
447
+ <li class="break-words">
448
+ <code>{l.path}</code>:
449
+ {leafText(l.then)} → {leafText(l.now)}
450
+ {#if l.delta !== null}
451
+ <span class="font-medium"
452
+ >({formatDelta(l.delta)})</span
453
+ >
454
+ {/if}
455
+ </li>
456
+ {/each}
457
+ {#if k.truncated}
458
+ <li class="text-base-content/60">+{k.truncated} more</li>
459
+ {/if}
460
+ </ul>
461
+ {/if}
462
+ </div>
463
+ {/each}
464
+ </div>
465
+ {/if}
466
+
467
+ {#if !compare && !atNow && selected}
468
+ <div
469
+ class="border-base-content/10 rounded-box border"
470
+ data-history-past-page
471
+ >
472
+ <p
473
+ class="bg-base-200 text-base-content/80 rounded-t-box border-base-content/10 border-b px-3 py-2 text-xs"
474
+ >
475
+ The page as it was {fmt(selected.at)}: layout v{selected.version}{selected.dataAt
476
+ ? `, data from ${fmt(selected.dataAt)}`
477
+ : ""}. Read-only.
478
+ </p>
479
+ <div class="p-3">
480
+ {#if selected.spec}
481
+ <BlockRenderer
482
+ spec={selected.spec}
483
+ {artifactId}
484
+ version={selected.version}
485
+ data={selected.data}
486
+ readonly
487
+ />
488
+ {:else}
489
+ <p class="text-base-content/70 text-sm">
490
+ Version {selected.version} is not a blocks page, so it cannot be
491
+ shown here.
492
+ </p>
493
+ {/if}
494
+ </div>
495
+ </div>
496
+ {/if}
497
+ </div>
498
+ {/if}
499
+ </section>
500
+ {/if}
@@ -0,0 +1,15 @@
1
+ import type { HistoryService } from "./types.js";
2
+ interface Props {
3
+ artifactId: string;
4
+ /** The live data the host is showing now (its poller's blob). */
5
+ currentData: Record<string, unknown>;
6
+ /** The layout version live now. */
7
+ currentVersion: number;
8
+ /** The host's history reads (HostAdapter.history). */
9
+ service: HistoryService;
10
+ /** Start expanded once there is a trail (tests, deep links). */
11
+ open?: boolean;
12
+ }
13
+ declare const HistoryScrubber: import("svelte").Component<Props, {}, "open">;
14
+ type HistoryScrubber = ReturnType<typeof HistoryScrubber>;
15
+ export default HistoryScrubber;
@@ -0,0 +1,186 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Markdown (jatui-vsuzi) — the ONE rich-prose surface of artifact blocks:
4
+ * source → the shared sanitized renderer (blocks/markdown/render.ts) →
5
+ * {@html}, with the prose styles carried HERE rather than borrowed from a
6
+ * host's typography plugin. A host without `@tailwindcss/typography` (the
7
+ * jat IDE) rendered MOS markdown as flat text with invisible links
8
+ * (PARAMS-SPEC §4); these scoped styles make headings, lists, tables,
9
+ * code and — above all — links visible everywhere.
10
+ *
11
+ * Token-only theming (DaisyUI `--color-*` → jatui radius tokens), light +
12
+ * dark by construction, phone-safe (tables scroll inside the block, long
13
+ * words wrap). Paragraphs and list items cap near 70ch.
14
+ *
15
+ * The {@html} here is the contract's sanctioned path: the HTML has passed
16
+ * marked + DOMPurify with the blocks URL policy.
17
+ */
18
+ import type { Snippet } from "svelte"
19
+ import {
20
+ renderBlockMarkdown,
21
+ renderBlockMarkdownInline,
22
+ } from "./blocks/markdown/render.js"
23
+
24
+ interface Props {
25
+ source: string | null | undefined
26
+ /** Inline only: no paragraphs/headings (labels, option details). */
27
+ inline?: boolean
28
+ /** Smaller body text (card sections, comment threads). */
29
+ size?: "base" | "sm"
30
+ class?: string
31
+ /** Rendered before the prose (SectionTools floats here). */
32
+ children?: Snippet
33
+ }
34
+
35
+ let {
36
+ source,
37
+ inline = false,
38
+ size = "base",
39
+ class: className = "",
40
+ children,
41
+ }: Props = $props()
42
+
43
+ const html = $derived(
44
+ inline ? renderBlockMarkdownInline(source) : renderBlockMarkdown(source),
45
+ )
46
+ </script>
47
+
48
+ {#if inline}
49
+ <span class="ab-md ab-md-inline {className}">{@html html}</span>
50
+ {:else}
51
+ <div class="ab-md flow-root text-base-content {className}" class:ab-md-sm={size === "sm"}>
52
+ {@render children?.()}
53
+ {@html html}
54
+ </div>
55
+ {/if}
56
+
57
+ <style>
58
+ .ab-md {
59
+ min-width: 0;
60
+ max-width: 100%;
61
+ font-size: 1rem;
62
+ line-height: 1.65;
63
+ overflow-wrap: anywhere;
64
+ }
65
+ .ab-md-sm {
66
+ font-size: 0.875rem;
67
+ line-height: 1.6;
68
+ }
69
+ .ab-md :global(:where(p, ul, ol, blockquote, pre, hr, .md-table)) {
70
+ margin-block: 0.75em;
71
+ }
72
+ .ab-md :global(:where(p, li)) {
73
+ max-width: 70ch;
74
+ }
75
+ .ab-md > :global(:first-child),
76
+ .ab-md :global(:where(li) > :first-child) {
77
+ margin-top: 0;
78
+ }
79
+ .ab-md > :global(:last-child) {
80
+ margin-bottom: 0;
81
+ }
82
+ .ab-md :global(:where(h1, h2, h3, h4, h5, h6)) {
83
+ font-weight: 600;
84
+ letter-spacing: -0.01em;
85
+ line-height: 1.3;
86
+ margin-block: 1.4em 0.5em;
87
+ }
88
+ .ab-md :global(h1) {
89
+ font-size: 1.5em;
90
+ }
91
+ .ab-md :global(h2) {
92
+ font-size: 1.25em;
93
+ }
94
+ .ab-md :global(h3) {
95
+ font-size: 1.1em;
96
+ }
97
+ .ab-md :global(:where(h4, h5, h6)) {
98
+ font-size: 1em;
99
+ }
100
+ .ab-md :global(:where(strong, b)) {
101
+ font-weight: 600;
102
+ }
103
+ /* Links are VISIBLE: primary hue + underline, never inherited body text. */
104
+ .ab-md :global(a[href]) {
105
+ color: var(--color-primary);
106
+ text-decoration: underline;
107
+ text-decoration-thickness: from-font;
108
+ text-underline-offset: 0.15em;
109
+ }
110
+ .ab-md :global(a[href]:hover) {
111
+ text-decoration-thickness: 2px;
112
+ }
113
+ .ab-md :global(a[href]:focus-visible) {
114
+ outline: 2px solid var(--color-primary);
115
+ outline-offset: 2px;
116
+ border-radius: var(--jatui-radius-field, 0.25rem);
117
+ }
118
+ .ab-md :global(ul) {
119
+ list-style: disc;
120
+ padding-left: 1.4em;
121
+ }
122
+ .ab-md :global(ol) {
123
+ list-style: decimal;
124
+ padding-left: 1.6em;
125
+ }
126
+ .ab-md :global(li) {
127
+ margin-block: 0.25em;
128
+ }
129
+ .ab-md :global(li::marker) {
130
+ color: color-mix(in oklab, var(--color-base-content) 50%, transparent);
131
+ }
132
+ .ab-md :global(blockquote) {
133
+ border-left: 3px solid
134
+ color-mix(in oklab, var(--color-base-content) 20%, transparent);
135
+ padding-left: 0.9em;
136
+ color: color-mix(in oklab, var(--color-base-content) 75%, transparent);
137
+ }
138
+ .ab-md :global(hr) {
139
+ border: 0;
140
+ border-top: 1px solid
141
+ color-mix(in oklab, var(--color-base-content) 15%, transparent);
142
+ }
143
+ .ab-md :global(:not(pre) > code) {
144
+ font-size: 0.875em;
145
+ padding: 0.1em 0.4em;
146
+ border-radius: var(--jatui-radius-field, 0.25rem);
147
+ background: color-mix(in oklab, var(--color-base-content) 10%, transparent);
148
+ }
149
+ .ab-md :global(pre) {
150
+ overflow-x: auto;
151
+ padding: 0.8em 1em;
152
+ border-radius: var(--jatui-radius-box, 0.5rem);
153
+ background: color-mix(in oklab, var(--color-base-content) 8%, transparent);
154
+ font-size: 0.875em;
155
+ line-height: 1.5;
156
+ overflow-wrap: normal;
157
+ }
158
+ .ab-md :global(.md-table) {
159
+ overflow-x: auto;
160
+ }
161
+ .ab-md :global(table) {
162
+ border-collapse: collapse;
163
+ font-size: 0.875em;
164
+ min-width: 100%;
165
+ }
166
+ .ab-md :global(:where(th, td)) {
167
+ padding: 0.4em 0.75em;
168
+ border-bottom: 1px solid
169
+ color-mix(in oklab, var(--color-base-content) 12%, transparent);
170
+ text-align: left;
171
+ font-variant-numeric: tabular-nums;
172
+ overflow-wrap: normal;
173
+ }
174
+ .ab-md :global(th) {
175
+ font-weight: 600;
176
+ }
177
+ .ab-md :global(img) {
178
+ max-width: 100%;
179
+ height: auto;
180
+ border-radius: var(--jatui-radius-box, 0.5rem);
181
+ }
182
+ .ab-md-inline :global(p) {
183
+ display: inline;
184
+ margin: 0;
185
+ }
186
+ </style>