@graview/core 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 (327) hide show
  1. package/LICENSE +96 -0
  2. package/README.md +35 -0
  3. package/dist/app.d.ts +294 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +49 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/arrange.d.ts +185 -0
  8. package/dist/arrange.d.ts.map +1 -0
  9. package/dist/arrange.js +456 -0
  10. package/dist/arrange.js.map +1 -0
  11. package/dist/beginning.d.ts +65 -0
  12. package/dist/beginning.d.ts.map +1 -0
  13. package/dist/beginning.js +94 -0
  14. package/dist/beginning.js.map +1 -0
  15. package/dist/bind.d.ts +42 -0
  16. package/dist/bind.d.ts.map +1 -0
  17. package/dist/bind.js +26 -0
  18. package/dist/bind.js.map +1 -0
  19. package/dist/city.d.ts +93 -0
  20. package/dist/city.d.ts.map +1 -0
  21. package/dist/city.js +160 -0
  22. package/dist/city.js.map +1 -0
  23. package/dist/cli/check/arrangement.d.ts +13 -0
  24. package/dist/cli/check/arrangement.d.ts.map +1 -0
  25. package/dist/cli/check/arrangement.js +63 -0
  26. package/dist/cli/check/arrangement.js.map +1 -0
  27. package/dist/cli/check/beginnings.d.ts +16 -0
  28. package/dist/cli/check/beginnings.d.ts.map +1 -0
  29. package/dist/cli/check/beginnings.js +53 -0
  30. package/dist/cli/check/beginnings.js.map +1 -0
  31. package/dist/cli/check/brand.d.ts +17 -0
  32. package/dist/cli/check/brand.d.ts.map +1 -0
  33. package/dist/cli/check/brand.js +153 -0
  34. package/dist/cli/check/brand.js.map +1 -0
  35. package/dist/cli/check/city.d.ts +17 -0
  36. package/dist/cli/check/city.d.ts.map +1 -0
  37. package/dist/cli/check/city.js +58 -0
  38. package/dist/cli/check/city.js.map +1 -0
  39. package/dist/cli/check/context.d.ts +50 -0
  40. package/dist/cli/check/context.d.ts.map +1 -0
  41. package/dist/cli/check/context.js +37 -0
  42. package/dist/cli/check/context.js.map +1 -0
  43. package/dist/cli/check/fields.d.ts +16 -0
  44. package/dist/cli/check/fields.d.ts.map +1 -0
  45. package/dist/cli/check/fields.js +237 -0
  46. package/dist/cli/check/fields.js.map +1 -0
  47. package/dist/cli/check/index.d.ts +14 -0
  48. package/dist/cli/check/index.d.ts.map +1 -0
  49. package/dist/cli/check/index.js +14 -0
  50. package/dist/cli/check/index.js.map +1 -0
  51. package/dist/cli/check/intelligence.d.ts +17 -0
  52. package/dist/cli/check/intelligence.d.ts.map +1 -0
  53. package/dist/cli/check/intelligence.js +136 -0
  54. package/dist/cli/check/intelligence.js.map +1 -0
  55. package/dist/cli/check/lenses.d.ts +17 -0
  56. package/dist/cli/check/lenses.d.ts.map +1 -0
  57. package/dist/cli/check/lenses.js +239 -0
  58. package/dist/cli/check/lenses.js.map +1 -0
  59. package/dist/cli/check/migrations.d.ts +16 -0
  60. package/dist/cli/check/migrations.d.ts.map +1 -0
  61. package/dist/cli/check/migrations.js +43 -0
  62. package/dist/cli/check/migrations.js.map +1 -0
  63. package/dist/cli/check/modules.d.ts +16 -0
  64. package/dist/cli/check/modules.d.ts.map +1 -0
  65. package/dist/cli/check/modules.js +123 -0
  66. package/dist/cli/check/modules.js.map +1 -0
  67. package/dist/cli/check/policy.d.ts +16 -0
  68. package/dist/cli/check/policy.d.ts.map +1 -0
  69. package/dist/cli/check/policy.js +90 -0
  70. package/dist/cli/check/policy.js.map +1 -0
  71. package/dist/cli/check/relations.d.ts +29 -0
  72. package/dist/cli/check/relations.d.ts.map +1 -0
  73. package/dist/cli/check/relations.js +279 -0
  74. package/dist/cli/check/relations.js.map +1 -0
  75. package/dist/cli/check/routes.d.ts +16 -0
  76. package/dist/cli/check/routes.d.ts.map +1 -0
  77. package/dist/cli/check/routes.js +31 -0
  78. package/dist/cli/check/routes.js.map +1 -0
  79. package/dist/cli/check/settings.d.ts +16 -0
  80. package/dist/cli/check/settings.d.ts.map +1 -0
  81. package/dist/cli/check/settings.js +81 -0
  82. package/dist/cli/check/settings.js.map +1 -0
  83. package/dist/cli/check.d.ts +36 -0
  84. package/dist/cli/check.d.ts.map +1 -0
  85. package/dist/cli/check.js +76 -0
  86. package/dist/cli/check.js.map +1 -0
  87. package/dist/cli/create.d.ts +20 -0
  88. package/dist/cli/create.d.ts.map +1 -0
  89. package/dist/cli/create.js +251 -0
  90. package/dist/cli/create.js.map +1 -0
  91. package/dist/cli/describe.d.ts +35 -0
  92. package/dist/cli/describe.d.ts.map +1 -0
  93. package/dist/cli/describe.js +230 -0
  94. package/dist/cli/describe.js.map +1 -0
  95. package/dist/cli/docs.d.ts +11 -0
  96. package/dist/cli/docs.d.ts.map +1 -0
  97. package/dist/cli/docs.js +152 -0
  98. package/dist/cli/docs.js.map +1 -0
  99. package/dist/cli/index.d.ts +18 -0
  100. package/dist/cli/index.d.ts.map +1 -0
  101. package/dist/cli/index.js +281 -0
  102. package/dist/cli/index.js.map +1 -0
  103. package/dist/extend.d.ts +23 -0
  104. package/dist/extend.d.ts.map +1 -0
  105. package/dist/extend.js +53 -0
  106. package/dist/extend.js.map +1 -0
  107. package/dist/graph/diff.d.ts +31 -0
  108. package/dist/graph/diff.d.ts.map +1 -0
  109. package/dist/graph/diff.js +71 -0
  110. package/dist/graph/diff.js.map +1 -0
  111. package/dist/graph/graph.d.ts +69 -0
  112. package/dist/graph/graph.d.ts.map +1 -0
  113. package/dist/graph/graph.js +284 -0
  114. package/dist/graph/graph.js.map +1 -0
  115. package/dist/graph/primitives.d.ts +52 -0
  116. package/dist/graph/primitives.d.ts.map +1 -0
  117. package/dist/graph/primitives.js +62 -0
  118. package/dist/graph/primitives.js.map +1 -0
  119. package/dist/graph/tracked.d.ts +31 -0
  120. package/dist/graph/tracked.d.ts.map +1 -0
  121. package/dist/graph/tracked.js +69 -0
  122. package/dist/graph/tracked.js.map +1 -0
  123. package/dist/graph/types.d.ts +34 -0
  124. package/dist/graph/types.d.ts.map +1 -0
  125. package/dist/graph/types.js +0 -0
  126. package/dist/graph/types.js.map +1 -0
  127. package/dist/index.d.ts +100 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +90 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/installation.d.ts +112 -0
  132. package/dist/installation.d.ts.map +1 -0
  133. package/dist/installation.js +193 -0
  134. package/dist/installation.js.map +1 -0
  135. package/dist/intelligence-bridge.d.ts +73 -0
  136. package/dist/intelligence-bridge.d.ts.map +1 -0
  137. package/dist/intelligence-bridge.js +31 -0
  138. package/dist/intelligence-bridge.js.map +1 -0
  139. package/dist/invariants/engine.d.ts +36 -0
  140. package/dist/invariants/engine.d.ts.map +1 -0
  141. package/dist/invariants/engine.js +88 -0
  142. package/dist/invariants/engine.js.map +1 -0
  143. package/dist/invariants/types.d.ts +75 -0
  144. package/dist/invariants/types.d.ts.map +1 -0
  145. package/dist/invariants/types.js +2 -0
  146. package/dist/invariants/types.js.map +1 -0
  147. package/dist/modules.d.ts +75 -0
  148. package/dist/modules.d.ts.map +1 -0
  149. package/dist/modules.js +87 -0
  150. package/dist/modules.js.map +1 -0
  151. package/dist/mutations/decidable.d.ts +26 -0
  152. package/dist/mutations/decidable.d.ts.map +1 -0
  153. package/dist/mutations/decidable.js +39 -0
  154. package/dist/mutations/decidable.js.map +1 -0
  155. package/dist/mutations/define-mutation.d.ts +32 -0
  156. package/dist/mutations/define-mutation.d.ts.map +1 -0
  157. package/dist/mutations/define-mutation.js +181 -0
  158. package/dist/mutations/define-mutation.js.map +1 -0
  159. package/dist/mutations/derive-edits.d.ts +75 -0
  160. package/dist/mutations/derive-edits.d.ts.map +1 -0
  161. package/dist/mutations/derive-edits.js +240 -0
  162. package/dist/mutations/derive-edits.js.map +1 -0
  163. package/dist/mutations/form.d.ts +63 -0
  164. package/dist/mutations/form.d.ts.map +1 -0
  165. package/dist/mutations/form.js +113 -0
  166. package/dist/mutations/form.js.map +1 -0
  167. package/dist/mutations/node-ref.d.ts +83 -0
  168. package/dist/mutations/node-ref.d.ts.map +1 -0
  169. package/dist/mutations/node-ref.js +113 -0
  170. package/dist/mutations/node-ref.js.map +1 -0
  171. package/dist/mutations/types.d.ts +136 -0
  172. package/dist/mutations/types.d.ts.map +1 -0
  173. package/dist/mutations/types.js +2 -0
  174. package/dist/mutations/types.js.map +1 -0
  175. package/dist/ops/log.d.ts +35 -0
  176. package/dist/ops/log.d.ts.map +1 -0
  177. package/dist/ops/log.js +103 -0
  178. package/dist/ops/log.js.map +1 -0
  179. package/dist/ops/types.d.ts +52 -0
  180. package/dist/ops/types.d.ts.map +1 -0
  181. package/dist/ops/types.js +2 -0
  182. package/dist/ops/types.js.map +1 -0
  183. package/dist/ops/undo.d.ts +33 -0
  184. package/dist/ops/undo.d.ts.map +1 -0
  185. package/dist/ops/undo.js +65 -0
  186. package/dist/ops/undo.js.map +1 -0
  187. package/dist/permissions/policy.d.ts +68 -0
  188. package/dist/permissions/policy.d.ts.map +1 -0
  189. package/dist/permissions/policy.js +191 -0
  190. package/dist/permissions/policy.js.map +1 -0
  191. package/dist/permissions/types.d.ts +78 -0
  192. package/dist/permissions/types.d.ts.map +1 -0
  193. package/dist/permissions/types.js +17 -0
  194. package/dist/permissions/types.js.map +1 -0
  195. package/dist/persistence/memory.d.ts +6 -0
  196. package/dist/persistence/memory.d.ts.map +1 -0
  197. package/dist/persistence/memory.js +31 -0
  198. package/dist/persistence/memory.js.map +1 -0
  199. package/dist/persistence/sqlite.d.ts +59 -0
  200. package/dist/persistence/sqlite.d.ts.map +1 -0
  201. package/dist/persistence/sqlite.js +131 -0
  202. package/dist/persistence/sqlite.js.map +1 -0
  203. package/dist/persistence/types.d.ts +22 -0
  204. package/dist/persistence/types.d.ts.map +1 -0
  205. package/dist/persistence/types.js +2 -0
  206. package/dist/persistence/types.js.map +1 -0
  207. package/dist/presence.d.ts +38 -0
  208. package/dist/presence.d.ts.map +1 -0
  209. package/dist/presence.js +50 -0
  210. package/dist/presence.js.map +1 -0
  211. package/dist/scaffold/domain.d.ts +8 -0
  212. package/dist/scaffold/domain.d.ts.map +1 -0
  213. package/dist/scaffold/domain.js +331 -0
  214. package/dist/scaffold/domain.js.map +1 -0
  215. package/dist/scaffold/index.d.ts +66 -0
  216. package/dist/scaffold/index.d.ts.map +1 -0
  217. package/dist/scaffold/index.js +142 -0
  218. package/dist/scaffold/index.js.map +1 -0
  219. package/dist/scaffold/lens.d.ts +31 -0
  220. package/dist/scaffold/lens.d.ts.map +1 -0
  221. package/dist/scaffold/lens.js +176 -0
  222. package/dist/scaffold/lens.js.map +1 -0
  223. package/dist/scaffold/names.d.ts +44 -0
  224. package/dist/scaffold/names.d.ts.map +1 -0
  225. package/dist/scaffold/names.js +69 -0
  226. package/dist/scaffold/names.js.map +1 -0
  227. package/dist/scaffold/project.d.ts +41 -0
  228. package/dist/scaffold/project.d.ts.map +1 -0
  229. package/dist/scaffold/project.js +604 -0
  230. package/dist/scaffold/project.js.map +1 -0
  231. package/dist/scaffold/ui.d.ts +15 -0
  232. package/dist/scaffold/ui.d.ts.map +1 -0
  233. package/dist/scaffold/ui.js +536 -0
  234. package/dist/scaffold/ui.js.map +1 -0
  235. package/dist/schema/define-node.d.ts +132 -0
  236. package/dist/schema/define-node.d.ts.map +1 -0
  237. package/dist/schema/define-node.js +254 -0
  238. package/dist/schema/define-node.js.map +1 -0
  239. package/dist/schema/figures.d.ts +42 -0
  240. package/dist/schema/figures.d.ts.map +1 -0
  241. package/dist/schema/figures.js +220 -0
  242. package/dist/schema/figures.js.map +1 -0
  243. package/dist/schema/json-schema.d.ts +39 -0
  244. package/dist/schema/json-schema.d.ts.map +1 -0
  245. package/dist/schema/json-schema.js +74 -0
  246. package/dist/schema/json-schema.js.map +1 -0
  247. package/dist/schema/schema.d.ts +43 -0
  248. package/dist/schema/schema.d.ts.map +1 -0
  249. package/dist/schema/schema.js +102 -0
  250. package/dist/schema/schema.js.map +1 -0
  251. package/dist/schema/types.d.ts +201 -0
  252. package/dist/schema/types.d.ts.map +1 -0
  253. package/dist/schema/types.js +2 -0
  254. package/dist/schema/types.js.map +1 -0
  255. package/dist/search.d.ts +215 -0
  256. package/dist/search.d.ts.map +1 -0
  257. package/dist/search.js +449 -0
  258. package/dist/search.js.map +1 -0
  259. package/dist/settings.d.ts +30 -0
  260. package/dist/settings.d.ts.map +1 -0
  261. package/dist/settings.js +74 -0
  262. package/dist/settings.js.map +1 -0
  263. package/dist/store.d.ts +284 -0
  264. package/dist/store.d.ts.map +1 -0
  265. package/dist/store.js +660 -0
  266. package/dist/store.js.map +1 -0
  267. package/dist/studio-door.d.ts +187 -0
  268. package/dist/studio-door.d.ts.map +1 -0
  269. package/dist/studio-door.js +20 -0
  270. package/dist/studio-door.js.map +1 -0
  271. package/dist/sync/conflict.d.ts +37 -0
  272. package/dist/sync/conflict.d.ts.map +1 -0
  273. package/dist/sync/conflict.js +56 -0
  274. package/dist/sync/conflict.js.map +1 -0
  275. package/dist/sync/engine.d.ts +118 -0
  276. package/dist/sync/engine.d.ts.map +1 -0
  277. package/dist/sync/engine.js +341 -0
  278. package/dist/sync/engine.js.map +1 -0
  279. package/dist/sync/google-calendar.d.ts +54 -0
  280. package/dist/sync/google-calendar.d.ts.map +1 -0
  281. package/dist/sync/google-calendar.js +167 -0
  282. package/dist/sync/google-calendar.js.map +1 -0
  283. package/dist/sync/types.d.ts +125 -0
  284. package/dist/sync/types.d.ts.map +1 -0
  285. package/dist/sync/types.js +6 -0
  286. package/dist/sync/types.js.map +1 -0
  287. package/dist/temporal/effectivity.d.ts +75 -0
  288. package/dist/temporal/effectivity.d.ts.map +1 -0
  289. package/dist/temporal/effectivity.js +89 -0
  290. package/dist/temporal/effectivity.js.map +1 -0
  291. package/dist/testing.d.ts +63 -0
  292. package/dist/testing.d.ts.map +1 -0
  293. package/dist/testing.js +194 -0
  294. package/dist/testing.js.map +1 -0
  295. package/dist/theme/contrast.d.ts +47 -0
  296. package/dist/theme/contrast.d.ts.map +1 -0
  297. package/dist/theme/contrast.js +172 -0
  298. package/dist/theme/contrast.js.map +1 -0
  299. package/dist/theme/derive.d.ts +81 -0
  300. package/dist/theme/derive.d.ts.map +1 -0
  301. package/dist/theme/derive.js +171 -0
  302. package/dist/theme/derive.js.map +1 -0
  303. package/dist/theme/kit.d.ts +106 -0
  304. package/dist/theme/kit.d.ts.map +1 -0
  305. package/dist/theme/kit.js +84 -0
  306. package/dist/theme/kit.js.map +1 -0
  307. package/dist/theme/palettes.d.ts +32 -0
  308. package/dist/theme/palettes.d.ts.map +1 -0
  309. package/dist/theme/palettes.js +96 -0
  310. package/dist/theme/palettes.js.map +1 -0
  311. package/dist/theme/types.d.ts +131 -0
  312. package/dist/theme/types.d.ts.map +1 -0
  313. package/dist/theme/types.js +23 -0
  314. package/dist/theme/types.js.map +1 -0
  315. package/dist/views/types.d.ts +89 -0
  316. package/dist/views/types.d.ts.map +1 -0
  317. package/dist/views/types.js +88 -0
  318. package/dist/views/types.js.map +1 -0
  319. package/dist/watched.d.ts +33 -0
  320. package/dist/watched.d.ts.map +1 -0
  321. package/dist/watched.js +50 -0
  322. package/dist/watched.js.map +1 -0
  323. package/dist/who.d.ts +26 -0
  324. package/dist/who.d.ts.map +1 -0
  325. package/dist/who.js +20 -0
  326. package/dist/who.js.map +1 -0
  327. package/package.json +77 -0
@@ -0,0 +1,536 @@
1
+ import { escapeHtml, escapeString, escapeTemplate } from "./names.js";
2
+ /*
3
+ * THE FACES A NEW PROJECT HAS: the page, the embed, the scene, the pages
4
+ * face and the entry that opens the store and mounts it.
5
+ */
6
+ export function indexHtml(ids) {
7
+ return `<!doctype html>
8
+ <html lang="en">
9
+ <meta charset="utf-8" />
10
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
11
+ <title>${escapeHtml(ids.name)}</title>
12
+ <style>
13
+ /* The theme is injected by src/main.tsx from the declared brand; this is
14
+ only the pre-paint ground so the page never flashes white. */
15
+ html, body { margin: 0; background: #0b0d0b; color: #eaf0ea; }
16
+ </style>
17
+ <div id="root"></div>
18
+ <script type="module" src="/src/main.tsx"></script>
19
+ `;
20
+ }
21
+ /**
22
+ * SOMEBODY ELSE'S PAGE. The `graview-embed` skill, shipped
23
+ * as a page rather than as a paragraph — so a project has a place to put an
24
+ * embed, and so the project's own `pnpm typecheck` covers the embed surface.
25
+ * Delete both files if the app is never going anywhere but its own address.
26
+ */
27
+ export function embedHtml(ids) {
28
+ return `<!doctype html>
29
+ <html lang="en">
30
+ <meta charset="utf-8" />
31
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
32
+ <title>${escapeHtml(ids.name)}, on somebody else's page</title>
33
+ <style>
34
+ /* THE HOST PAGE'S OWN LOOK. Nothing here is ${escapeHtml(ids.name)}'s, and
35
+ nothing ${escapeHtml(ids.name)} draws may reach out and change it: the
36
+ embed themes itself inside its own element. */
37
+ body {
38
+ margin: 0 auto;
39
+ max-width: 44rem;
40
+ padding: 3rem 1.25rem 6rem;
41
+ background: #fbfaf7;
42
+ color: #1c1b19;
43
+ font: 17px/1.7 Georgia, "Times New Roman", serif;
44
+ }
45
+ h1 { font-size: 2rem; line-height: 1.15; margin: 0 0 1.2rem; }
46
+ p { margin: 0 0 1.2rem; }
47
+ .figure { margin: 1.5rem 0 2rem; height: 520px; }
48
+ </style>
49
+
50
+ <!-- The HOST page's own landmark. The embed brings a named region of its
51
+ own and deliberately no <main>: the page it lands on owns that, and two
52
+ mains is one landmark said twice. -->
53
+ <main>
54
+ <h1>An ordinary page</h1>
55
+ <p>
56
+ Written in its own typeface, on its own paper. The picture below is
57
+ ${escapeHtml(ids.name)}, mounted into one element of it.
58
+ </p>
59
+ <div class="figure" id="here"></div>
60
+ <p>
61
+ And the page carries on afterwards, untouched.
62
+ </p>
63
+ </main>
64
+
65
+ <script type="module" src="/src/embed.tsx"></script>
66
+ `;
67
+ }
68
+ export function embedTsx(ids) {
69
+ return `import { mount } from "@graview/embed";
70
+ import { ${ids.appVar}, createStore } from "./domain/app.js";
71
+ import { views } from "./ui/views.js";
72
+
73
+ /**
74
+ * ${escapeTemplate(ids.name).toUpperCase()} ON SOMEBODY ELSE'S PAGE.
75
+ *
76
+ * The embed brings its own strip, its own theme scoped to the element it is
77
+ * given, and this app's named places — no Shell, nothing on the host page
78
+ * touched. Pass \`seats\` once a policy exists and the reader can sit in each
79
+ * one: the strip, the pages and the acts all narrow together.
80
+ */
81
+ const store = createStore();
82
+
83
+ mount(document.getElementById("here")!, {
84
+ app: ${ids.appVar},
85
+ store,
86
+ // The app's own registry, in the app's own schema — no casts.
87
+ views,
88
+ scheme: "auto",
89
+ stop: "#overview=1",
90
+ label: "${escapeString(ids.name)}",
91
+ });
92
+ `;
93
+ }
94
+ /* ------------------------------------------------------------------- ui */
95
+ export function viewsTsx(ids) {
96
+ return `import { createViews } from "@graview/react";
97
+ import { registerDefaultViews } from "@graview/primitives";
98
+ import { ${ids.schemaVar} } from "../domain/schema.js";
99
+
100
+ /**
101
+ * Nothing custom yet, on purpose. \`registerDefaultViews\` renders every kind
102
+ * at every fidelity from the declaration alone. Write a view for a kind when
103
+ * the generic one is genuinely wrong, not on principle — see the framework's
104
+ * \`apps/todo/src/ui/views.tsx\` for one that earns its place. Give a group
105
+ * view a title and it is a PLACE, listed by name in the bar:
106
+ *
107
+ * .register("${ids.kind}", { cardinality: "many", fidelity: "full" }, lens.View, { title: "…" })
108
+ */
109
+ export function views() {
110
+ return registerDefaultViews(${ids.schemaVar}, createViews(${ids.schemaVar}));
111
+ }
112
+ `;
113
+ }
114
+ export function uiAppTsx(ids) {
115
+ return `import { EMPTY_VIEW, type ViewState } from "@graview/layout";
116
+ import { GraviewProvider, useGraph, useGraview, type Scheme } from "@graview/react";
117
+ import { AgentSeat, Shell } from "@graview/primitives";
118
+ import { StudioPlace } from "@graview/studio";
119
+ import { templateIntelligence, type ToolCall } from "@graview/tools";
120
+ import { useMemo, useState } from "react";
121
+ import { ${ids.appVar}, createStore, type ${ids.StoreType} } from "../domain/app.js";
122
+ import { ${ids.brandVar} } from "../domain/brand.js";
123
+ import type { ${ids.SchemaType} } from "../domain/schema.js";
124
+ import { views } from "./views.js";
125
+
126
+ type S = ${ids.SchemaType};
127
+
128
+ /**
129
+ * The app opens from ALTITUDE: every kind a district, each saying how many
130
+ * it holds — or "none yet", which is an invitation rather than a void.
131
+ */
132
+ export const INITIAL_VIEW: ViewState = { ...EMPTY_VIEW, overview: true };
133
+
134
+ export interface ${ids.AppComponent}Props {
135
+ readonly store?: ${ids.StoreType};
136
+ readonly initialView?: ViewState;
137
+ readonly syncUrl?: boolean;
138
+ readonly initialScheme?: Scheme;
139
+ readonly onSchemeChange?: (scheme: Scheme) => void;
140
+ /** Whether the store behind this app is remembered in the browser (see main.tsx). */
141
+ readonly remembers?: boolean;
142
+ }
143
+
144
+ /**
145
+ * The whole application. \`Shell\` is the command bar, the scene, the
146
+ * inspector and the rail, derived; what ${escapeTemplate(ids.name)} adds is a
147
+ * sentence for when nothing is wrong and a seat for an agent. If this file
148
+ * grows, ask whether the declaration should have grown instead.
149
+ */
150
+ export function ${ids.AppComponent}({
151
+ store,
152
+ initialView = INITIAL_VIEW,
153
+ syncUrl = false,
154
+ initialScheme = "light",
155
+ onSchemeChange,
156
+ remembers = false,
157
+ }: ${ids.AppComponent}Props) {
158
+ const created = useMemo(() => store ?? createStore(), [store]);
159
+ const registry = useMemo(() => views(), []);
160
+ const [scheme, setScheme] = useState<Scheme>(initialScheme);
161
+
162
+ return (
163
+ <GraviewProvider
164
+ store={created}
165
+ views={registry}
166
+ initialView={initialView}
167
+ scheme={scheme}
168
+ brand={${ids.brandVar}}
169
+ settings={${ids.appVar}.settings ?? []}
170
+ >
171
+ <Shell<S>
172
+ standing="Everything is in order"
173
+ /*
174
+ * THE APP'S OWN DECLARATION, one press away and in place. The
175
+ * kinds, fields, edges, acts and rules of \`src/domain\` are a graph
176
+ * here: change one with the ordinary acts, watch the checker judge
177
+ * it, and apply to get the files to write back. Offered to the seat
178
+ * that administers where there is one, and to whoever is here where
179
+ * there is not — which is this project, today.
180
+ */
181
+ studio={<StudioPlace app={${ids.appVar}} />}
182
+ seat={(onCall) => <Starter onCall={onCall} />}
183
+ remembers={remembers}
184
+ syncUrl={syncUrl}
185
+ scheme={scheme}
186
+ onScheme={(next) => {
187
+ setScheme(next);
188
+ onSchemeChange?.(next);
189
+ }}
190
+ />
191
+ </GraviewProvider>
192
+ );
193
+ }
194
+
195
+ /**
196
+ * The seat at zero. An empty graph plus a seat that proposes starter data is
197
+ * the "describe your domain, get a working app" moment. Every proposal is an
198
+ * ordinary mutation through the derived tool surface — logged, attributed to
199
+ * the seat, reviewable, undoable.
200
+ */
201
+ function Starter({ onCall }: { onCall: (call: ToolCall) => void }) {
202
+ const { store } = useGraview<S>();
203
+ const nodes = useGraph();
204
+ const empty = nodes.length === 0;
205
+ return (
206
+ <AgentSeat<S>
207
+ who="starter"
208
+ testId="agent-starter"
209
+ count={empty ? 1 : 0}
210
+ gate="add-${ids.kind}"
211
+ label={() => "Add some starter data"}
212
+ busyLabel="Adding…"
213
+ idle="There is something here already"
214
+ onCall={onCall}
215
+ run={async (agent) => {
216
+ const starter = templateIntelligence<S>();
217
+ for (const proposal of await starter.propose(store)) {
218
+ await agent.run(proposal.mutation, { ...proposal.args });
219
+ }
220
+ }}
221
+ />
222
+ );
223
+ }
224
+ `;
225
+ }
226
+ export function pagesTsx(ids) {
227
+ return `import { isCurrent } from "@graview/core";
228
+ import { Begin } from "@graview/primitives";
229
+ import {
230
+ createPageRegistry,
231
+ DefaultHomePage,
232
+ DerivedForm,
233
+ PageMain,
234
+ pageStyles,
235
+ recordFacts,
236
+ recordPath,
237
+ Repairs,
238
+ spatialHref,
239
+ useStoreTick,
240
+ type PageComponent,
241
+ type PageContext,
242
+ } from "@graview/pages";
243
+ import { Link, useParams } from "react-router-dom";
244
+ import { ${ids.schemaVar}, type ${ids.SchemaType} } from "../domain/schema.js";
245
+
246
+ type S = ${ids.SchemaType};
247
+
248
+ /**
249
+ * THE OTHER FACE, IN YOUR OWN WORDS. /pages is an ordinary routed web
250
+ * application derived from the declaration: a list and a record per kind,
251
+ * forms from the mutations, a problems page from the rules. Every one of
252
+ * those can be replaced per kind — or per surface: shell, home, problems —
253
+ * with a page you write. This is the ${ids.spoken}'s record page; delete it
254
+ * and the derived page takes over again. Everything it shows still comes
255
+ * from the same derivations (\`recordFacts\`, \`DerivedForm\`), so a page
256
+ * you write cannot drift from what the graph says.
257
+ */
258
+ function ${ids.KindPascal}Page({ context }: { context: PageContext<S> }) {
259
+ const { store, principal, invariantContext } = context;
260
+ useStoreTick(store);
261
+ const id = decodeURIComponent(useParams()["id"] ?? "");
262
+ const facts = recordFacts(store, id, {
263
+ ...(principal ? { principal } : {}),
264
+ ...(invariantContext ? { context: invariantContext } : {}),
265
+ });
266
+ const node = store.graph.getNode(id);
267
+ if (!facts || !node) {
268
+ return (
269
+ <PageMain context={context}>
270
+ <h1 style={pageStyles.h1}>Nothing lives at this address.</h1>
271
+ </PageMain>
272
+ );
273
+ }
274
+ /*
275
+ * THE TIES, AS THE DECLARATION READS THEM.
276
+ *
277
+ * \`facts.links\` is every edge on this record, both directions, each
278
+ * carrying the caption the declaration gives THAT end. Asking the graph
279
+ * for one edge by name here instead — \`out(id, "depends-on")\` — is a
280
+ * page that stops telling the truth the day the schema grows a second
281
+ * edge, which is the first thing every project does.
282
+ */
283
+ const ties = facts.links;
284
+ /*
285
+ * THE ACTS AS THE DERIVATION OFFERS THEM, not as the declaration lists
286
+ * them. Reaching for a mutation by name gets an act that is always there;
287
+ * an affordance is an act that can actually be taken RIGHT NOW, and it
288
+ * carries its candidates — everything not already tied, and never this
289
+ * record itself. With one ${ids.spoken} in the graph there is nothing to
290
+ * point at, so there is no form, rather than a heading over a picker with
291
+ * one wrong answer in it.
292
+ */
293
+ const connecting = facts.actions.affordances.filter((affordance) => affordance.ties === true);
294
+
295
+ return (
296
+ <PageMain context={context} data-testid="${ids.kind}-page">
297
+ <header style={{ display: "grid", gap: 10 }}>
298
+ <p style={pageStyles.eyebrow}>${ids.ASpoken} in ${escapeTemplate(ids.name)}</p>
299
+ <h1 style={pageStyles.h1}>{facts.label}</h1>
300
+ {/*
301
+ * WHERE IT IS ON THE HORIZON, asked of the declaration's own
302
+ * lifecycle rather than of a status word written here: rename the
303
+ * states, or retire by a date, and this still tells the truth.
304
+ */}
305
+ <p style={pageStyles.lede}>
306
+ {isCurrent(store.schema.tryDefinition(node.kind), node) ? "Current." : "In the past: out of the picture, never out of the record."}{" "}
307
+ {ties.length === 0 ? "Connected to nothing yet." : null}
308
+ </p>
309
+ <a href={spatialHref(id)} style={{ ...pageStyles.link, ...pageStyles.quiet }} data-testid="spatial-link">
310
+ See it in the scene ↗
311
+ </a>
312
+ </header>
313
+ {facts.violations.length > 0 ? (
314
+ <section style={{ ...pageStyles.rule, display: "grid", gap: 10 }} data-testid="record-violations">
315
+ {facts.violations.map((violation, index) => (
316
+ <div key={index} style={{ display: "grid", gap: 8 }}>
317
+ <p style={{ margin: 0, color: "var(--graview-warn)", fontWeight: 550 }}>{violation.message}</p>
318
+ {/*
319
+ * A repair that needs nothing is one press; one that still has
320
+ * an argument to choose is an ask. \`Repairs\` is the same
321
+ * component the derived problems page uses, so a page you
322
+ * write cannot get this wrong on its own.
323
+ */}
324
+ <Repairs<S> store={store} repairs={violation.repairs} {...(principal ? { principal } : {})} />
325
+ </div>
326
+ ))}
327
+ </section>
328
+ ) : null}
329
+ {/*
330
+ * THE FACTS, as the derivation reads them — every field that is not
331
+ * the name, formatted as the declaration says. A page that dropped
332
+ * them looked finished on the one-kind scaffold, where the only
333
+ * field is the name, and hid the price of every vehicle a day later.
334
+ */}
335
+ {facts.fields.length > 0 ? (
336
+ <dl style={{ ...pageStyles.rule, margin: 0, display: "grid", gridTemplateColumns: "minmax(0, max-content) minmax(0, 1fr)", gap: "6px 18px" }} data-testid="record-fields">
337
+ {facts.fields.map((field) => (
338
+ <div key={field.key} style={{ display: "contents" }}>
339
+ <dt style={pageStyles.quiet}>{field.label}</dt>
340
+ <dd style={{ margin: 0, overflowWrap: "anywhere" }}>{field.value}</dd>
341
+ </div>
342
+ ))}
343
+ </dl>
344
+ ) : null}
345
+ {ties.length > 0 ? (
346
+ <section style={{ ...pageStyles.rule, display: "grid", gap: 14 }} data-testid="record-ties">
347
+ {ties.map((group) => (
348
+ <div key={\`\${group.edgeKind}|\${group.direction}\`} style={{ display: "grid", gap: 6 }}>
349
+ {/* The edge's own words for THIS end — its description read
350
+ from the end that declared it, its inverse read from the
351
+ other. */}
352
+ <h2 style={pageStyles.h2}>
353
+ {(group.description ?? group.edgeKind).replace(/^./, (first) => first.toUpperCase())}
354
+ </h2>
355
+ {/* Each a link, and two of one name told apart (\`apart\`): a list of words cannot be followed. */}
356
+ <ul style={{ margin: 0, padding: 0, listStyle: "none", display: "grid", gap: 4 }}>
357
+ {group.targets.map((target) => (
358
+ <li key={target.id}>
359
+ <Link to={recordPath(${ids.schemaVar}, target.kind, target.id)} style={pageStyles.link}>
360
+ {target.label}
361
+ {target.apart ? <span style={pageStyles.quiet}> · {target.apart}</span> : null}
362
+ </Link>
363
+ </li>
364
+ ))}
365
+ </ul>
366
+ </div>
367
+ ))}
368
+ </section>
369
+ ) : null}
370
+ {/*
371
+ * WITHHELD, NOT HIDDEN. The affordances above are what this seat may
372
+ * do; an act the policy refuses is in withheld, carrying the policy's
373
+ * own sentence. Dropping it teaches a person the software is broken —
374
+ * they watched a colleague do this yesterday and now the control is
375
+ * gone — so it is drawn struck through with the reason beside it, the
376
+ * way the derived pages and the scene's strip both draw it.
377
+ */}
378
+ {facts.actions.withheld.length > 0 ? (
379
+ <section style={{ ...pageStyles.rule, display: "grid", gap: 8 }} data-testid="record-withheld">
380
+ {facts.actions.withheld.map((withheld) => (
381
+ <p key={withheld.id} style={{ margin: 0, ...pageStyles.quiet }}>
382
+ <s>{withheld.label}</s> — {withheld.refusal.message}
383
+ </p>
384
+ ))}
385
+ </section>
386
+ ) : null}
387
+ {connecting.length > 0 ? (
388
+ <section style={{ ...pageStyles.rule, display: "grid", gap: 14 }} data-testid="record-actions">
389
+ {connecting.map((affordance) => {
390
+ const act = store.allMutations().find((mutation) => mutation.name === affordance.mutation);
391
+ return act ? (
392
+ <div key={affordance.id} style={{ display: "grid", gap: 10 }}>
393
+ {/* The act's own title, and the arguments the derivation
394
+ already settled — never a subject name written out here. */}
395
+ <h2 style={pageStyles.h2}>{affordance.label}</h2>
396
+ <DerivedForm<S> store={store} mutation={act} prefilled={affordance.args} open={affordance.open} label={affordance.label} {...(principal ? { principal } : {})} />
397
+ </div>
398
+ ) : null;
399
+ })}
400
+ </section>
401
+ ) : null}
402
+ </PageMain>
403
+ );
404
+ }
405
+
406
+ /**
407
+ * THE WAY IN, on the home page, until there is a way past it.
408
+ *
409
+ * Every product ships empty once and it is the state its author never sees —
410
+ * your own graph has had data in it since the first afternoon. \`Begin\` is
411
+ * derived: it reads the chain your declaration already states (which acts
412
+ * \`create\` which kinds, and what those acts must be handed first), offers
413
+ * the ones that can run now, and says what everything else is waiting for.
414
+ * It stands down on its own once every kind has something in it, which is
415
+ * why the derived home is what it hands back to.
416
+ */
417
+ function Home({ context }: { context: PageContext<S> }) {
418
+ useStoreTick(context.store);
419
+ return (
420
+ // The routed face has no provider around it, so the store is handed over.
421
+ <Begin
422
+ store={context.store}
423
+ {...(context.principal ? { principal: context.principal } : {})}
424
+ // The derived home is a whole page — the gallery, at a page's width,
425
+ // in its own landmark — and comes back exactly as given.
426
+ whenFull={<DefaultHomePage context={context} />}
427
+ // The door alone gets a page's column and landmark around it.
428
+ frame={(door) => (
429
+ <PageMain context={context} data-testid="home">
430
+ {door}
431
+ </PageMain>
432
+ )}
433
+ />
434
+ );
435
+ }
436
+
437
+ /** Your pages: every derived page, with the ${ids.spoken}'s record in your own words. */
438
+ export function pages() {
439
+ return createPageRegistry<S, PageComponent<S>>(${ids.schemaVar})
440
+ .register("${ids.kind}", "record", ${ids.KindPascal}Page as PageComponent<S>)
441
+ .surface("home", Home as PageComponent<S>);
442
+ }
443
+ `;
444
+ }
445
+ export function mainTsx(ids) {
446
+ return `import { PagesApp } from "@graview/pages";
447
+ import { themeCss, type Scheme } from "@graview/primitives";
448
+ import { browserStartsFresh, createBrowserAdapter, forgetFreshParam, openStore } from "@graview/ship/browser";
449
+ import { createRoot } from "react-dom/client";
450
+ import { ${ids.appVar} } from "./domain/app.js";
451
+ import { ${ids.brandVar} } from "./domain/brand.js";
452
+ import { ${ids.AppComponent} } from "./ui/app.js";
453
+ import { pages } from "./ui/pages.js";
454
+ import { views } from "./ui/views.js";
455
+
456
+ const sheet = new CSSStyleSheet();
457
+ document.adoptedStyleSheets = [sheet];
458
+
459
+ const STORED = "graview:scheme";
460
+
461
+ function initialScheme(): Scheme {
462
+ const asked = new URLSearchParams(window.location.search).get("theme");
463
+ if (asked === "light" || asked === "dark") return asked;
464
+ try {
465
+ const stored = localStorage.getItem(STORED);
466
+ if (stored === "light" || stored === "dark") return stored;
467
+ } catch {
468
+ // A scheme that cannot be remembered still applies for this visit.
469
+ }
470
+ return window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
471
+ }
472
+
473
+ function applyScheme(scheme: Scheme): void {
474
+ sheet.replaceSync(themeCss(scheme, ${ids.brandVar}));
475
+ document.documentElement.dataset["graviewScheme"] = scheme;
476
+ try {
477
+ localStorage.setItem(STORED, scheme);
478
+ } catch {
479
+ // Same again: not being able to remember is not a reason to fail.
480
+ }
481
+ }
482
+
483
+ const scheme = initialScheme();
484
+ applyScheme(scheme);
485
+
486
+ const root = document.getElementById("root");
487
+ if (!root) throw new Error("no #root");
488
+
489
+ /*
490
+ * THE APP REMEMBERS. Persistence is the op log; \`openStore\` is the lifecycle
491
+ * every deployment repeats. Here it is the browser adapter, so an edit
492
+ * survives a reload, attributed and undoable. \`?fresh=1\` returns to empty;
493
+ * a driven browser starts fresh unless it asks to remember (\`?remember=1\`),
494
+ * so a harness specifies the app rather than its own residue.
495
+ */
496
+ const opened = await openStore({
497
+ app: ${ids.appVar},
498
+ adapter: createBrowserAdapter(),
499
+ fresh: browserStartsFresh(),
500
+ });
501
+ forgetFreshParam();
502
+
503
+ if (window.location.pathname.startsWith("/pages")) {
504
+ // The routed, responsive face: same store, same ids, one app.
505
+ createRoot(root).render(
506
+ <PagesApp
507
+ basename="/pages"
508
+ context={{
509
+ store: opened.store,
510
+ brand: ${ids.brandVar},
511
+ sceneHref: "/",
512
+ remembers: true,
513
+ /*
514
+ * THE SAME PICTURES ON BOTH FACES. Handed the registry the scene
515
+ * draws from, the pages land on a gallery of them — every kind as
516
+ * a card until you title a lens, then the lens by its name — with
517
+ * the map of the kinds and the seat on every route.
518
+ */
519
+ views: views(),
520
+ settings: ${ids.appVar}.settings ?? [],
521
+ }}
522
+ // Your own pages over the derived ones: see ui/pages.tsx.
523
+ registry={pages()}
524
+ />,
525
+ );
526
+ } else {
527
+ createRoot(root).render(
528
+ <${ids.AppComponent} store={opened.store} remembers syncUrl initialScheme={scheme} onSchemeChange={applyScheme} />,
529
+ );
530
+ }
531
+
532
+ // A flag a harness can wait for, rather than a timer and a hope.
533
+ (window as unknown as Record<string, unknown>)["__graviewReady"] = { scheme };
534
+ `;
535
+ }
536
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/scaffold/ui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ import type { z } from "zod";
2
+ import type { AnyNodeDefinition, EdgeMap, EmptyEdgeMap, NodeDefinition, NodeDefinitionSpec } from "./types.js";
3
+ /**
4
+ * The single declaration everything else derives from. Views, agent tool
5
+ * schemas, drag legality, aggregate contents and accessibility labels all
6
+ * read this — nothing is sealed, every derived value stays inspectable.
7
+ */
8
+ export declare function defineNode<const K extends string, F extends z.ZodObject<z.ZodRawShape>, const E extends EdgeMap = EmptyEdgeMap>(kind: K, spec: NodeDefinitionSpec<F, E>): NodeDefinition<K, F, E>;
9
+ /**
10
+ * Whether a node is CURRENT under its kind's declared lifecycle.
11
+ *
12
+ * True when the kind declares no lifecycle — currency is opt-in, and a kind
13
+ * that never retires anything should not pay for the concept. `today` is
14
+ * injectable so a test (or a view pinned to a survey date) can ask about a
15
+ * different day; it defaults to the real one.
16
+ */
17
+ export declare function isCurrent(definition: AnyNodeDefinition | undefined, node: {
18
+ id: string;
19
+ kind: string;
20
+ } & Record<string, unknown>, today?: string): boolean;
21
+ /**
22
+ * WHAT TELLS TWO SAME-NAMED THINGS APART, among the nodes a person is
23
+ * choosing from. A single and its album are both "Blue Hour", and every
24
+ * picker, every ask and the Find strip listed "Blue Hour, Blue Hour": a
25
+ * choice nobody could make. For each node whose name another in the list
26
+ * shares, the first fact that differs between them — "single" and "album",
27
+ * or the dates — else its kind, else its id. Nodes with a name of their
28
+ * own get nothing.
29
+ */
30
+ export declare function tellApart(nodes: readonly ({
31
+ id: string;
32
+ kind: string;
33
+ } & Record<string, unknown>)[], definitionOf: (kind: string) => AnyNodeDefinition | undefined): Map<string, string>;
34
+ /** Resolves a node's display label, honouring the declaration's override. */
35
+ export declare function labelOf(definition: AnyNodeDefinition | undefined, node: {
36
+ id: string;
37
+ kind: string;
38
+ } & Record<string, unknown>): string;
39
+ /**
40
+ * Prose, shortened to a length, at a WORD BOUNDARY.
41
+ *
42
+ * Every app here had `text.slice(0, 60)` in its label function, and every one
43
+ * of them produced headings like "Hold the banked hour for a night s" — cut
44
+ * mid-word, with no ellipsis, in the largest type on the page. It is the
45
+ * obvious thing to write and it is wrong every time, so the framework should
46
+ * own it rather than leaving each app to discover it.
47
+ *
48
+ * A single word longer than the limit is still cut, because the alternative
49
+ * is a heading that ignores the limit it was given.
50
+ */
51
+ export declare function summarise(text: string, max?: number): string;
52
+ /** Resolves a node's prose description, used for a11y and tool text. */
53
+ export declare function describeNode(definition: AnyNodeDefinition | undefined, node: {
54
+ id: string;
55
+ kind: string;
56
+ } & Record<string, unknown>): string;
57
+ /** One field, as a person sees it. */
58
+ export interface ReadableField {
59
+ readonly key: string;
60
+ /** The field name in words, after `display.labels` and humanising. */
61
+ readonly label: string;
62
+ /** The value in words, after `display.format` and the built-in defaults. */
63
+ readonly value: string;
64
+ /**
65
+ * The value as it reads WITHOUT its label beside it — on a chip, in a
66
+ * list line, on a card at summary. A word says what it is ("released");
67
+ * a number or a yes/no does not, so it carries the label: "Track 8",
68
+ * "Length 4:27", "Explicit: yes". A song's card read "8 · 4:27 · Yes",
69
+ * which is three facts and no sentence.
70
+ */
71
+ readonly alone: string;
72
+ }
73
+ /** `effectiveFrom` shown to a person is a schema leaking through a surface. */
74
+ export declare function humaniseField(field: string): string;
75
+ /**
76
+ * A field in words, as the declaration says it: its `display.labels` entry,
77
+ * else the key spoken. Every sentence that names a field — "Nothing
78
+ * declared writes the planned time", a tooltip, a refusal — reads it here,
79
+ * so `plannedAt` never reaches a person from one surface while another says
80
+ * "Planned at".
81
+ */
82
+ export declare function fieldWords(definition: {
83
+ readonly display?: {
84
+ readonly labels?: Readonly<Record<string, string>>;
85
+ };
86
+ } | undefined, key: string): string;
87
+ /** "a" or "an", by how the word SOUNDS. */
88
+ export declare function article(word: string): "a" | "an";
89
+ /**
90
+ * A kind in words, with its article: "an item", "a work order".
91
+ *
92
+ * Takes the declared id and speaks it — the hyphen in `work-order` is a
93
+ * identifier's punctuation, not a word's.
94
+ */
95
+ export declare function withArticle(word: string): string;
96
+ /**
97
+ * What one of a kind is called: its declared `noun`, else its id spoken.
98
+ * Every sentence about ONE of them — "Change the staff member", "a staff
99
+ * member called …", "Remove the staff member" — reads this, never the id.
100
+ */
101
+ export declare function nounOf(definition: {
102
+ readonly noun?: string;
103
+ } | undefined, kind: string): string;
104
+ /**
105
+ * WHICH of a node's fields a person sees, and HOW each one reads.
106
+ *
107
+ * One implementation, because there were two: the record on a page and the
108
+ * summary on a card each decided this for themselves, and every rule — hide an
109
+ * ordering key, format minutes as a time, render a boolean as a word, drop a
110
+ * value the heading already said — had to be written into both and kept in
111
+ * step by hand. They diverged the day the second one was written, which is how
112
+ * a summary card ended up showing a list's ordering key as a chip reading "0"
113
+ * while the page beside it did not.
114
+ *
115
+ * `said` is what the surrounding view has already put on screen. A value the
116
+ * heading already carries is not information twice, it is the same sentence
117
+ * twice — and where the heading is a SHORTENED form of a field, an exact
118
+ * comparison never catches it, so the summary's stem is compared too.
119
+ */
120
+ export declare function readableFields(node: Record<string, unknown>, definition: AnyNodeDefinition | undefined, options?: {
121
+ readonly limit?: number;
122
+ readonly said?: readonly (string | undefined)[];
123
+ /**
124
+ * A GLANCE drops a value the heading already says as a WORD, not only as
125
+ * the whole heading: a vehicle's summary is headed "2027 Subaru Forester
126
+ * Sport", and "Year 2027 · Subaru" under it spent two of its three facts
127
+ * saying the heading again while the price never appeared. A record's
128
+ * full facts keep every field — that is where each is changed.
129
+ */
130
+ readonly glance?: boolean;
131
+ }): readonly ReadableField[];
132
+ //# sourceMappingURL=define-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-node.d.ts","sourceRoot":"","sources":["../../src/schema/define-node.ts"],"names":[],"mappings":"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"}