@joewinke/jatui 0.36.3 → 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 (271) 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/dist/components/Button.svelte +8 -0
  267. package/dist/components/TextInput.svelte +39 -6
  268. package/dist/components/TextInput.svelte.d.ts +15 -7
  269. package/dist/components/basic/Checkbox.svelte +52 -14
  270. package/dist/components/basic/Checkbox.svelte.d.ts +11 -1
  271. package/package.json +11 -2
@@ -0,0 +1,363 @@
1
+ /**
2
+ * History scrubber model (mos-p9m3g, living artifacts phase 4).
3
+ *
4
+ * "What did this page look like yesterday at 9am?" A blocks page has two
5
+ * clocks, and the state at any instant is one reading of each:
6
+ *
7
+ * LAYOUT the artifact_versions row live at that instant (the highest
8
+ * version created at or before it);
9
+ * DATA the artifact_data_history snapshot live at that instant (the
10
+ * newest recorded at or before it — migration 20272490000210
11
+ * captures every change of artifacts.data by trigger).
12
+ *
13
+ * This module is PURE (no db, no fetch): the history route resolves an
14
+ * instant with it on the server, and HistoryScrubber builds its timeline and
15
+ * diffs with it in the browser.
16
+ *
17
+ * Diffs are SHAPE-AWARE but never shape-dependent: a stats-shaped value
18
+ * (`cards[]` with label + numeric value) diffs as KPI deltas, a table-shaped
19
+ * value (`rows[]`) diffs as added / removed / changed rows, and anything
20
+ * else diffs as its changed numeric and text leaves. Data is untrusted: every
21
+ * reader here tolerates any JSON and caps what it reports.
22
+ */
23
+ /** Mirrors the trigger's prune rule in drizzle/20272490000210 — keep both in
24
+ * step. The scrubber names where the trail ends with these. */
25
+ export const HISTORY_RETENTION = {
26
+ maxSnapshots: 500,
27
+ maxAgeDays: 30,
28
+ maxBytes: 32 * 1024 * 1024,
29
+ };
30
+ function toMs(iso) {
31
+ const ms = Date.parse(iso);
32
+ return Number.isFinite(ms) ? ms : NaN;
33
+ }
34
+ /**
35
+ * Merge versions and snapshots into one chronological list (oldest first).
36
+ * Entries with an unparseable timestamp are dropped — a point the scrubber
37
+ * cannot place is a point it cannot honestly show. At equal instants a
38
+ * version sorts before a data change (a republish then a data push in the
39
+ * same second reads in that order).
40
+ */
41
+ export function buildTimeline(versions, snapshots) {
42
+ const points = [];
43
+ for (const v of versions) {
44
+ const ms = toMs(v.createdAt);
45
+ if (Number.isFinite(ms))
46
+ points.push({ kind: "version", at: v.createdAt, ms, version: v.version });
47
+ }
48
+ for (const s of snapshots) {
49
+ const ms = toMs(s.at);
50
+ if (Number.isFinite(ms))
51
+ points.push({ kind: "data", at: s.at, ms, snapshotId: s.id });
52
+ }
53
+ return points.sort((a, b) => a.ms - b.ms ||
54
+ (a.kind === b.kind ? 0 : a.kind === "version" ? -1 : 1) ||
55
+ (a.version ?? 0) - (b.version ?? 0));
56
+ }
57
+ /**
58
+ * The page state live at `atMs`: the newest version created at or before it
59
+ * and the newest snapshot recorded at or before it. Before the first
60
+ * snapshot, snapshotId is null — the page showed its inline params (or the
61
+ * trail was pruned; the caller says which via `trailStart`).
62
+ */
63
+ export function stateAt(versions, snapshots, atMs) {
64
+ let version = null;
65
+ let versionMs = -Infinity;
66
+ for (const v of versions) {
67
+ const ms = toMs(v.createdAt);
68
+ if (!(ms <= atMs))
69
+ continue;
70
+ if (ms > versionMs || (ms === versionMs && v.version > (version ?? 0))) {
71
+ version = v.version;
72
+ versionMs = ms;
73
+ }
74
+ }
75
+ let snap = null;
76
+ let snapMs = -Infinity;
77
+ // Snapshots arrive newest-first from the route; equal instants keep the
78
+ // first seen (the newest by seq).
79
+ for (const s of snapshots) {
80
+ const ms = toMs(s.at);
81
+ if (!(ms <= atMs))
82
+ continue;
83
+ if (ms > snapMs) {
84
+ snap = s;
85
+ snapMs = ms;
86
+ }
87
+ }
88
+ return {
89
+ version,
90
+ snapshotId: snap?.id ?? null,
91
+ dataAt: snap?.at ?? null,
92
+ };
93
+ }
94
+ /** The oldest instant the trail can answer for, or null with no snapshots. */
95
+ export function trailStart(snapshots) {
96
+ let best = null;
97
+ let bestMs = Infinity;
98
+ for (const s of snapshots) {
99
+ const ms = toMs(s.at);
100
+ if (ms < bestMs) {
101
+ best = s.at;
102
+ bestMs = ms;
103
+ }
104
+ }
105
+ return best;
106
+ }
107
+ // ---------------------------------------------------------------------------
108
+ // Diffs
109
+ // ---------------------------------------------------------------------------
110
+ /** Most entries any one diff list reports — the rest are counted, not listed. */
111
+ const MAX_DIFF_ENTRIES = 50;
112
+ function isRecord(v) {
113
+ return typeof v === "object" && v !== null && !Array.isArray(v);
114
+ }
115
+ function own(obj, k) {
116
+ return Object.prototype.hasOwnProperty.call(obj, k) ? obj[k] : undefined;
117
+ }
118
+ /** Order-insensitive structural equality over plain JSON. */
119
+ function jsonEqual(a, b) {
120
+ if (a === b)
121
+ return true;
122
+ if (typeof a !== typeof b || a === null || b === null)
123
+ return false;
124
+ if (Array.isArray(a)) {
125
+ if (!Array.isArray(b) || a.length !== b.length)
126
+ return false;
127
+ return a.every((el, i) => jsonEqual(el, b[i]));
128
+ }
129
+ if (isRecord(a) && isRecord(b)) {
130
+ const ka = Object.keys(a);
131
+ const kb = Object.keys(b);
132
+ if (ka.length !== kb.length)
133
+ return false;
134
+ return ka.every((k) => own(b, k) !== undefined && jsonEqual(a[k], b[k]));
135
+ }
136
+ return false;
137
+ }
138
+ function finite(v) {
139
+ return typeof v === "number" && Number.isFinite(v) ? v : null;
140
+ }
141
+ function kpiCards(v) {
142
+ if (!isRecord(v))
143
+ return null;
144
+ const cards = own(v, "cards");
145
+ if (!Array.isArray(cards))
146
+ return null;
147
+ const out = new Map();
148
+ for (const c of cards) {
149
+ if (!isRecord(c))
150
+ return null;
151
+ const label = own(c, "label");
152
+ if (typeof label !== "string" || !label)
153
+ return null;
154
+ if (!out.has(label))
155
+ out.set(label, finite(own(c, "value")));
156
+ }
157
+ return out;
158
+ }
159
+ function diffKpis(then, now) {
160
+ const labels = [...now.keys(), ...[...then.keys()].filter((l) => !now.has(l))];
161
+ return labels.slice(0, MAX_DIFF_ENTRIES).map((label) => {
162
+ const t = then.has(label) ? (then.get(label) ?? null) : null;
163
+ const n = now.has(label) ? (now.get(label) ?? null) : null;
164
+ const delta = t !== null && n !== null ? n - t : null;
165
+ const pct = delta !== null && t !== null && t !== 0 ? delta / Math.abs(t) : null;
166
+ return { label, then: t, now: n, delta, pct };
167
+ });
168
+ }
169
+ /** Preferred identity columns for a table row, in order. */
170
+ const ROW_KEY_CANDIDATES = ["id", "key", "slug", "name", "label", "title"];
171
+ function tableRows(v) {
172
+ if (!isRecord(v))
173
+ return null;
174
+ const rows = own(v, "rows");
175
+ if (!Array.isArray(rows) || !rows.every(isRecord))
176
+ return null;
177
+ const cols = own(v, "columns");
178
+ const columns = Array.isArray(cols)
179
+ ? cols
180
+ .map((c) => (isRecord(c) ? own(c, "key") : undefined))
181
+ .filter((k) => typeof k === "string")
182
+ : [];
183
+ return { rows: rows, columns };
184
+ }
185
+ /** The column that identifies a row across both sides: the first candidate
186
+ * (then the first declared column) whose values are present and unique on
187
+ * BOTH sides. Null → rows are matched by position. */
188
+ function rowKeyColumn(a, b, columns) {
189
+ const unique = (rows, col) => {
190
+ const seen = new Set();
191
+ for (const r of rows) {
192
+ const v = own(r, col);
193
+ if (typeof v !== "string" && typeof v !== "number")
194
+ return false;
195
+ const s = String(v);
196
+ if (seen.has(s))
197
+ return false;
198
+ seen.add(s);
199
+ }
200
+ return true;
201
+ };
202
+ for (const col of [...ROW_KEY_CANDIDATES, ...columns.slice(0, 1)]) {
203
+ if (unique(a, col) && unique(b, col))
204
+ return col;
205
+ }
206
+ return null;
207
+ }
208
+ function diffTable(then, now) {
209
+ const columns = now.columns.length ? now.columns : then.columns;
210
+ const col = rowKeyColumn(then.rows, now.rows, columns);
211
+ const keyOf = (r, i) => col ? String(own(r, col)) : `#${i + 1}`;
212
+ const thenMap = new Map(then.rows.map((r, i) => [keyOf(r, i), r]));
213
+ const nowMap = new Map(now.rows.map((r, i) => [keyOf(r, i), r]));
214
+ const added = [];
215
+ const removed = [];
216
+ const changed = [];
217
+ for (const [k, r] of nowMap) {
218
+ const old = thenMap.get(k);
219
+ if (!old) {
220
+ added.push({ key: k, fields: [] });
221
+ continue;
222
+ }
223
+ const fields = [
224
+ ...new Set([...Object.keys(old), ...Object.keys(r)]),
225
+ ].filter((f) => !jsonEqual(own(old, f), own(r, f)));
226
+ if (fields.length)
227
+ changed.push({ key: k, fields });
228
+ }
229
+ for (const k of thenMap.keys()) {
230
+ if (!nowMap.has(k))
231
+ removed.push({ key: k, fields: [] });
232
+ }
233
+ const total = added.length + removed.length + changed.length;
234
+ let budget = MAX_DIFF_ENTRIES;
235
+ const take = (list) => {
236
+ const out = list.slice(0, Math.max(0, budget));
237
+ budget -= out.length;
238
+ return out;
239
+ };
240
+ return {
241
+ added: take(added),
242
+ removed: take(removed),
243
+ changed: take(changed),
244
+ truncated: Math.max(0, total - MAX_DIFF_ENTRIES),
245
+ };
246
+ }
247
+ function leaves(v, path, out, depth = 0) {
248
+ if (out.size > 2000 || depth > 12)
249
+ return;
250
+ if (v === null || ["string", "number", "boolean"].includes(typeof v)) {
251
+ out.set(path || "$", v);
252
+ }
253
+ else if (Array.isArray(v)) {
254
+ v.forEach((el, i) => leaves(el, `${path}[${i}]`, out, depth + 1));
255
+ }
256
+ else if (isRecord(v)) {
257
+ for (const k of Object.keys(v))
258
+ leaves(v[k], path ? `${path}.${k}` : k, out, depth + 1);
259
+ }
260
+ }
261
+ function diffLeaves(then, now) {
262
+ const a = new Map();
263
+ const b = new Map();
264
+ leaves(then, "", a);
265
+ leaves(now, "", b);
266
+ const all = [];
267
+ for (const p of new Set([...b.keys(), ...a.keys()])) {
268
+ const t = a.get(p);
269
+ const n = b.get(p);
270
+ if (t === n)
271
+ continue;
272
+ const tn = finite(t);
273
+ const nn = finite(n);
274
+ all.push({
275
+ path: p,
276
+ then: t,
277
+ now: n,
278
+ delta: tn !== null && nn !== null ? nn - tn : null,
279
+ });
280
+ }
281
+ return {
282
+ leaves: all.slice(0, MAX_DIFF_ENTRIES),
283
+ truncated: Math.max(0, all.length - MAX_DIFF_ENTRIES),
284
+ };
285
+ }
286
+ /**
287
+ * Diff two live-data blobs key by key (`then` → `now`). Keys are reported in
288
+ * `now`'s order, then keys only `then` had. A non-object side reads as {}.
289
+ */
290
+ export function diffData(then, now) {
291
+ const a = isRecord(then) ? then : {};
292
+ const b = isRecord(now) ? now : {};
293
+ const keys = [
294
+ ...Object.keys(b),
295
+ ...Object.keys(a).filter((k) => own(b, k) === undefined),
296
+ ];
297
+ const out = [];
298
+ for (const key of keys) {
299
+ const t = own(a, key);
300
+ const n = own(b, key);
301
+ if (t === undefined) {
302
+ out.push({ key, status: "added" });
303
+ }
304
+ else if (n === undefined) {
305
+ out.push({ key, status: "removed" });
306
+ }
307
+ else if (jsonEqual(t, n)) {
308
+ out.push({ key, status: "same" });
309
+ }
310
+ else {
311
+ const kt = kpiCards(t);
312
+ const kn = kpiCards(n);
313
+ const tt = tableRows(t);
314
+ const tn = tableRows(n);
315
+ if (kt && kn) {
316
+ out.push({
317
+ key,
318
+ status: "changed",
319
+ shape: "kpi",
320
+ kpis: diffKpis(kt, kn),
321
+ });
322
+ }
323
+ else if (tt && tn) {
324
+ out.push({
325
+ key,
326
+ status: "changed",
327
+ shape: "table",
328
+ ...diffTable(tt, tn),
329
+ });
330
+ }
331
+ else {
332
+ out.push({
333
+ key,
334
+ status: "changed",
335
+ shape: "value",
336
+ ...diffLeaves(t, n),
337
+ });
338
+ }
339
+ }
340
+ }
341
+ return {
342
+ keys: out,
343
+ changedKeys: out.filter((d) => d.status !== "same").length,
344
+ };
345
+ }
346
+ /** "+4.2%", "−1,203", "0" — a signed delta for display (U+2212 minus). */
347
+ export function formatDelta(delta, pct = null) {
348
+ const sign = delta > 0 ? "+" : delta < 0 ? "−" : "";
349
+ const abs = Math.abs(delta);
350
+ const num = abs.toLocaleString("en-US", { maximumFractionDigits: 2 });
351
+ const p = pct === null
352
+ ? ""
353
+ : ` (${sign}${Math.abs(pct * 100).toLocaleString("en-US", { maximumFractionDigits: 1 })}%)`;
354
+ return `${sign}${num}${p}`;
355
+ }
356
+ /** Parse a `?at=` query value: ISO-8601 or epoch ms. NaN when neither. */
357
+ export function parseInstant(raw) {
358
+ if (raw === null || raw.trim() === "")
359
+ return NaN;
360
+ if (/^\d{10,16}$/.test(raw.trim()))
361
+ return Number(raw.trim());
362
+ return Date.parse(raw);
363
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `jatui/artifact-blocks` — ONE renderer for blocks artifacts, shared by MOS
3
+ * and the jat IDE (epic jatui-936iz; core jatui-vsuzi).
4
+ *
5
+ * <BlocksArtifactView {artifactId} {version} {title} {summary} {byline}
6
+ * {spec} adapter={host} {savedBlocks} {onSaveBlock} … />
7
+ *
8
+ * or the renderer alone: `<BlockRenderer {spec} {artifactId} {version}
9
+ * adapter={host} />`. Everything host-specific is the `HostAdapter`
10
+ * (types.ts); the contract is CONTRACT.md in this folder.
11
+ */
12
+ export { default as BlocksArtifactView } from "./BlocksArtifactView.svelte";
13
+ export { default as BlockRenderer } from "./BlockRenderer.svelte";
14
+ export { default as BlockVerdict } from "./BlockVerdict.svelte";
15
+ export { default as BlockComments } from "./BlockComments.svelte";
16
+ export { default as CommentPill } from "./CommentPill.svelte";
17
+ export { default as SectionTools } from "./SectionTools.svelte";
18
+ export { default as FoldedRounds } from "./FoldedRounds.svelte";
19
+ export { default as HistoryScrubber } from "./HistoryScrubber.svelte";
20
+ export { default as Markdown } from "./Markdown.svelte";
21
+ export { default as NoteComposer } from "./NoteComposer.svelte";
22
+ export { default as PlainComposer } from "./PlainComposer.svelte";
23
+ export { default as AttachmentChip } from "./AttachmentChip.svelte";
24
+ export { registerBlocks, blockDef, allBlockDefs, validateBlocksSpec, } from "./registry.js";
25
+ export { BUILTIN_BLOCKS, PENDING_BLOCK_TYPES, BLOCK_GROUPS } from "./builtins.js";
26
+ export { default as markdownBlock } from "./blocks/markdown/block.js";
27
+ export { markdownSchema, type MarkdownParams } from "./blocks/markdown/schema.js";
28
+ export { urlSchema, optionalUrlSchema, linkUrlSchema, isSafeLinkUrl, isSafeResourceUrl, toneSchema, TONE_TOKENS, shortTextSchema, longTextSchema, isoDateSchema, shortTextList, type ToneToken, } from "./params.js";
29
+ export { normalizeContractBlocks, blockLinkErrors, blockTasksOf, decisionExtras, decisionMetaSchema, decisionSectionsSchema, decisionPrimaryActionSchema, decisionTitleSchema, blockGroupSchema, DECISION_BODY_BUDGET, } from "./contractBlocks.js";
30
+ export { renderBlockMarkdown, renderBlockMarkdownInline, looksLikeMarkdown, } from "./blocks/markdown/render.js";
31
+ export { coerceBlocksSpec, reviewKey, ITEM_REVIEW_BLOCK_TYPES, isItemReviewBlock, isDecisionBlock, takesBlockVerdict, OTHER_ID, decisionCardsOf, verdictsFromBlocks, blockReviewStateOf, reviewItemsOf, BLOCKS_VOCABULARY, wordFor, countReviewUnits, pageReviewProgress, openReviewUnits, itemVerdictsOf, coerceSentAnswer, changedSinceSend, sentAnswerLine, type DecisionCard, type DecisionOption, type ReviewUnitLine, type ReviewUnitCounts, type ReviewProgressProps, type PageReviewProgress, type OpenReviewUnit, type ChangedSinceSend, } from "./review.js";
32
+ export { resolveBlockParams, formatDataAge, normalizeDataPublish, serializedBytes, MAX_DATA_BYTES, type DataPublishMode, type ResolvedBlockParams, } from "./liveData.js";
33
+ export { createLiveDataPoller, dataAgeLine, dataAgeTitle, type LiveDataPoller, } from "./liveDataPoller.js";
34
+ export * from "./history.js";
35
+ export { createOpenNav, revealUnit, type JumpUnit } from "./openNav.js";
36
+ export { createPageReviewKeys, isPageChromeTarget } from "./pageReviewKeys.js";
37
+ export { AUTO_SEND_DELAY_MS, createAutoSend } from "./autoSend.js";
38
+ export { provideHostAdapter, hostAdapter, hostServices, HOST_ADAPTER_KEY, } from "./adapter.js";
39
+ export { provideBlockListen, blockListen, BLOCK_LISTEN_KEY, type BlockListenContext, } from "./listen/context.js";
40
+ export type * from "./types.js";
@@ -0,0 +1,46 @@
1
+ /**
2
+ * `jatui/artifact-blocks` — ONE renderer for blocks artifacts, shared by MOS
3
+ * and the jat IDE (epic jatui-936iz; core jatui-vsuzi).
4
+ *
5
+ * <BlocksArtifactView {artifactId} {version} {title} {summary} {byline}
6
+ * {spec} adapter={host} {savedBlocks} {onSaveBlock} … />
7
+ *
8
+ * or the renderer alone: `<BlockRenderer {spec} {artifactId} {version}
9
+ * adapter={host} />`. Everything host-specific is the `HostAdapter`
10
+ * (types.ts); the contract is CONTRACT.md in this folder.
11
+ */
12
+ // Views
13
+ export { default as BlocksArtifactView } from "./BlocksArtifactView.svelte";
14
+ export { default as BlockRenderer } from "./BlockRenderer.svelte";
15
+ export { default as BlockVerdict } from "./BlockVerdict.svelte";
16
+ export { default as BlockComments } from "./BlockComments.svelte";
17
+ export { default as CommentPill } from "./CommentPill.svelte";
18
+ export { default as SectionTools } from "./SectionTools.svelte";
19
+ export { default as FoldedRounds } from "./FoldedRounds.svelte";
20
+ export { default as HistoryScrubber } from "./HistoryScrubber.svelte";
21
+ export { default as Markdown } from "./Markdown.svelte";
22
+ export { default as NoteComposer } from "./NoteComposer.svelte";
23
+ export { default as PlainComposer } from "./PlainComposer.svelte";
24
+ export { default as AttachmentChip } from "./AttachmentChip.svelte";
25
+ // Catalog
26
+ export { registerBlocks, blockDef, allBlockDefs, validateBlocksSpec, } from "./registry.js";
27
+ export { BUILTIN_BLOCKS, PENDING_BLOCK_TYPES, BLOCK_GROUPS } from "./builtins.js";
28
+ export { default as markdownBlock } from "./blocks/markdown/block.js";
29
+ export { markdownSchema } from "./blocks/markdown/schema.js";
30
+ // Params + the provider contract
31
+ export { urlSchema, optionalUrlSchema, linkUrlSchema, isSafeLinkUrl, isSafeResourceUrl, toneSchema, TONE_TOKENS, shortTextSchema, longTextSchema, isoDateSchema, shortTextList, } from "./params.js";
32
+ export { normalizeContractBlocks, blockLinkErrors, blockTasksOf, decisionExtras, decisionMetaSchema, decisionSectionsSchema, decisionPrimaryActionSchema, decisionTitleSchema, blockGroupSchema, DECISION_BODY_BUDGET, } from "./contractBlocks.js";
33
+ // Markdown
34
+ export { renderBlockMarkdown, renderBlockMarkdownInline, looksLikeMarkdown, } from "./blocks/markdown/render.js";
35
+ // Review math
36
+ export { coerceBlocksSpec, reviewKey, ITEM_REVIEW_BLOCK_TYPES, isItemReviewBlock, isDecisionBlock, takesBlockVerdict, OTHER_ID, decisionCardsOf, verdictsFromBlocks, blockReviewStateOf, reviewItemsOf, BLOCKS_VOCABULARY, wordFor, countReviewUnits, pageReviewProgress, openReviewUnits, itemVerdictsOf, coerceSentAnswer, changedSinceSend, sentAnswerLine, } from "./review.js";
37
+ // Live data, history, navigation, keys
38
+ export { resolveBlockParams, formatDataAge, normalizeDataPublish, serializedBytes, MAX_DATA_BYTES, } from "./liveData.js";
39
+ export { createLiveDataPoller, dataAgeLine, dataAgeTitle, } from "./liveDataPoller.js";
40
+ export * from "./history.js";
41
+ export { createOpenNav, revealUnit } from "./openNav.js";
42
+ export { createPageReviewKeys, isPageChromeTarget } from "./pageReviewKeys.js";
43
+ export { AUTO_SEND_DELAY_MS, createAutoSend } from "./autoSend.js";
44
+ // Host wiring
45
+ export { provideHostAdapter, hostAdapter, hostServices, HOST_ADAPTER_KEY, } from "./adapter.js";
46
+ export { provideBlockListen, blockListen, BLOCK_LISTEN_KEY, } from "./listen/context.js";
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Artifact blocks — the Listen context (origin mos-8vdg9; jatui-vsuzi).
3
+ *
4
+ * A block's own Listen control must know WHICH surface its segments live in,
5
+ * but blocks are generic components: the host owns that. In jatui the host
6
+ * hands its Listen control over as a snippet — `HostAdapter.listen` — which
7
+ * SectionTools renders with the block's coordinates ({ group, label,
8
+ * anchor }). jatui's own ListenControl fits inside it; MOS keeps its
9
+ * coordinate-based player.
10
+ *
11
+ * The adapter's `listen` is the default source; a host that wants Listen
12
+ * for only PART of a page (or a test mounting one block) can override it
13
+ * below any point with provideBlockListen(). Neither → no Listen control
14
+ * (share link, print).
15
+ */
16
+ import { type Snippet } from "svelte";
17
+ import type { BlockListenArgs } from "../types.js";
18
+ export interface BlockListenContext {
19
+ /** Renders the host's Listen control for one block; null = none here. */
20
+ render: Snippet<[BlockListenArgs]> | null;
21
+ }
22
+ /**
23
+ * The context key itself, exported for tests that mount a block directly
24
+ * (mount(Component, { context: new Map([[BLOCK_LISTEN_KEY, …]]) })).
25
+ */
26
+ export declare const BLOCK_LISTEN_KEY: symbol;
27
+ /** Host-side: publish the Listen renderer to every block below. */
28
+ export declare function provideBlockListen(ctx: BlockListenContext): void;
29
+ /** Block-side: the Listen renderer, or null when this host offers none. */
30
+ export declare function blockListen(): BlockListenContext | null;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Artifact blocks — the Listen context (origin mos-8vdg9; jatui-vsuzi).
3
+ *
4
+ * A block's own Listen control must know WHICH surface its segments live in,
5
+ * but blocks are generic components: the host owns that. In jatui the host
6
+ * hands its Listen control over as a snippet — `HostAdapter.listen` — which
7
+ * SectionTools renders with the block's coordinates ({ group, label,
8
+ * anchor }). jatui's own ListenControl fits inside it; MOS keeps its
9
+ * coordinate-based player.
10
+ *
11
+ * The adapter's `listen` is the default source; a host that wants Listen
12
+ * for only PART of a page (or a test mounting one block) can override it
13
+ * below any point with provideBlockListen(). Neither → no Listen control
14
+ * (share link, print).
15
+ */
16
+ import { getContext, setContext } from "svelte";
17
+ const KEY = Symbol("artifact-blocks-listen");
18
+ /**
19
+ * The context key itself, exported for tests that mount a block directly
20
+ * (mount(Component, { context: new Map([[BLOCK_LISTEN_KEY, …]]) })).
21
+ */
22
+ export const BLOCK_LISTEN_KEY = KEY;
23
+ /** Host-side: publish the Listen renderer to every block below. */
24
+ export function provideBlockListen(ctx) {
25
+ setContext(KEY, ctx);
26
+ }
27
+ /** Block-side: the Listen renderer, or null when this host offers none. */
28
+ export function blockListen() {
29
+ return getContext(KEY) ?? null;
30
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Live data for blocks artifacts (origin mos-0ninw, phase 3 of MOS epic
3
+ * mos-m1qrx).
4
+ *
5
+ * A blocks page publishes LAYOUT once; its NUMBERS move without a
6
+ * republish. The host keeps a per-artifact key→value data map (MOS:
7
+ * `artifacts.data`, `mos-artifact data`) — version-independent, so a cron
8
+ * or generator can refresh a dashboard while its layout stays put.
9
+ *
10
+ * The binding, on the HOST side (BlockRenderer):
11
+ *
12
+ * - a block whose def declares `dataParam: "dataKey"` and whose params
13
+ * set that key (e.g. `dataKey: "soak"`) renders from `data.soak`
14
+ * INSTEAD of its inline params, once a value exists for that key;
15
+ * - before the first data publish (or with the key absent), the block
16
+ * renders its inline params — a fresh page is never blank, and a
17
+ * publisher can push data at their own pace;
18
+ * - the live value REPLACES the params object wholesale, then goes
19
+ * through the same zod schema as publish-time params. Data is as
20
+ * untrusted as params are: a value that fails the schema renders the
21
+ * block's error card naming the dataKey — never a silent fallback to
22
+ * stale inline numbers.
23
+ *
24
+ * This module is PURE (no db import): BlockRenderer renders it into the
25
+ * browser, a host's service and routes import it on the server. Storage is
26
+ * the host's.
27
+ */
28
+ import type { ArtifactBlockDef } from "./types";
29
+ /**
30
+ * Largest serialized artifacts.data accepted after a write. Generous for a
31
+ * real dashboard (thousands of table rows), small enough that a runaway
32
+ * generator cannot balloon a page's poll payload. The service enforces it
33
+ * inside the UPDATE itself — a write that would exceed the cap changes
34
+ * NOTHING (no partial merge, no data_updated_at bump).
35
+ */
36
+ export declare const MAX_DATA_BYTES: number;
37
+ export declare function serializedBytes(v: unknown): number;
38
+ export type DataPublishMode = "merge" | "key" | "replace";
39
+ interface NormalizedDataPublish {
40
+ mode: DataPublishMode;
41
+ key: string | null;
42
+ /** The value to store: the whole blob (merge/replace) or the key's value. */
43
+ value: unknown;
44
+ }
45
+ /**
46
+ * Validate + normalize a data publish. Throws with a message an agent can
47
+ * act on; the route turns that into a 400. `undefined` incoming data is a
48
+ * programmer error (the body always parses to something) and is refused like
49
+ * any other invalid input.
50
+ */
51
+ export declare function normalizeDataPublish(input: {
52
+ data: unknown;
53
+ key?: unknown;
54
+ replace?: unknown;
55
+ }): NormalizedDataPublish;
56
+ export interface ResolvedBlockParams {
57
+ /** What the block renders: the live value when one exists, else inline. */
58
+ params: unknown;
59
+ /** The dataKey the block ASKED for (null when it did not opt in). */
60
+ dataKey: string | null;
61
+ /** True when the rendered params ARE the live value. */
62
+ fromData: boolean;
63
+ }
64
+ /**
65
+ * The dataParam binding. `def.dataParam` names the params field holding the
66
+ * data key; when that field names a key WITH a published value, the live
67
+ * value replaces the params wholesale. Everything else renders inline:
68
+ * no opt-in, no published value, or a key that exists only on the prototype
69
+ * chain (hasOwn guard).
70
+ */
71
+ export declare function resolveBlockParams(def: Pick<ArtifactBlockDef, "dataParam"> | undefined, rawParams: unknown, data: Record<string, unknown>): ResolvedBlockParams;
72
+ /**
73
+ * The subtle freshness line: "just now" → "42s ago" → "2m ago" → "3h ago" →
74
+ * "5d ago". Empty string when there is no data yet (the line does not render
75
+ * at all).
76
+ */
77
+ export declare function formatDataAge(updatedAt: string | number | Date | null | undefined, now: number | Date): string;
78
+ export {};