@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.
- package/LICENSE +96 -0
- package/README.md +35 -0
- package/dist/app.d.ts +294 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +49 -0
- package/dist/app.js.map +1 -0
- package/dist/arrange.d.ts +185 -0
- package/dist/arrange.d.ts.map +1 -0
- package/dist/arrange.js +456 -0
- package/dist/arrange.js.map +1 -0
- package/dist/beginning.d.ts +65 -0
- package/dist/beginning.d.ts.map +1 -0
- package/dist/beginning.js +94 -0
- package/dist/beginning.js.map +1 -0
- package/dist/bind.d.ts +42 -0
- package/dist/bind.d.ts.map +1 -0
- package/dist/bind.js +26 -0
- package/dist/bind.js.map +1 -0
- package/dist/city.d.ts +93 -0
- package/dist/city.d.ts.map +1 -0
- package/dist/city.js +160 -0
- package/dist/city.js.map +1 -0
- package/dist/cli/check/arrangement.d.ts +13 -0
- package/dist/cli/check/arrangement.d.ts.map +1 -0
- package/dist/cli/check/arrangement.js +63 -0
- package/dist/cli/check/arrangement.js.map +1 -0
- package/dist/cli/check/beginnings.d.ts +16 -0
- package/dist/cli/check/beginnings.d.ts.map +1 -0
- package/dist/cli/check/beginnings.js +53 -0
- package/dist/cli/check/beginnings.js.map +1 -0
- package/dist/cli/check/brand.d.ts +17 -0
- package/dist/cli/check/brand.d.ts.map +1 -0
- package/dist/cli/check/brand.js +153 -0
- package/dist/cli/check/brand.js.map +1 -0
- package/dist/cli/check/city.d.ts +17 -0
- package/dist/cli/check/city.d.ts.map +1 -0
- package/dist/cli/check/city.js +58 -0
- package/dist/cli/check/city.js.map +1 -0
- package/dist/cli/check/context.d.ts +50 -0
- package/dist/cli/check/context.d.ts.map +1 -0
- package/dist/cli/check/context.js +37 -0
- package/dist/cli/check/context.js.map +1 -0
- package/dist/cli/check/fields.d.ts +16 -0
- package/dist/cli/check/fields.d.ts.map +1 -0
- package/dist/cli/check/fields.js +237 -0
- package/dist/cli/check/fields.js.map +1 -0
- package/dist/cli/check/index.d.ts +14 -0
- package/dist/cli/check/index.d.ts.map +1 -0
- package/dist/cli/check/index.js +14 -0
- package/dist/cli/check/index.js.map +1 -0
- package/dist/cli/check/intelligence.d.ts +17 -0
- package/dist/cli/check/intelligence.d.ts.map +1 -0
- package/dist/cli/check/intelligence.js +136 -0
- package/dist/cli/check/intelligence.js.map +1 -0
- package/dist/cli/check/lenses.d.ts +17 -0
- package/dist/cli/check/lenses.d.ts.map +1 -0
- package/dist/cli/check/lenses.js +239 -0
- package/dist/cli/check/lenses.js.map +1 -0
- package/dist/cli/check/migrations.d.ts +16 -0
- package/dist/cli/check/migrations.d.ts.map +1 -0
- package/dist/cli/check/migrations.js +43 -0
- package/dist/cli/check/migrations.js.map +1 -0
- package/dist/cli/check/modules.d.ts +16 -0
- package/dist/cli/check/modules.d.ts.map +1 -0
- package/dist/cli/check/modules.js +123 -0
- package/dist/cli/check/modules.js.map +1 -0
- package/dist/cli/check/policy.d.ts +16 -0
- package/dist/cli/check/policy.d.ts.map +1 -0
- package/dist/cli/check/policy.js +90 -0
- package/dist/cli/check/policy.js.map +1 -0
- package/dist/cli/check/relations.d.ts +29 -0
- package/dist/cli/check/relations.d.ts.map +1 -0
- package/dist/cli/check/relations.js +279 -0
- package/dist/cli/check/relations.js.map +1 -0
- package/dist/cli/check/routes.d.ts +16 -0
- package/dist/cli/check/routes.d.ts.map +1 -0
- package/dist/cli/check/routes.js +31 -0
- package/dist/cli/check/routes.js.map +1 -0
- package/dist/cli/check/settings.d.ts +16 -0
- package/dist/cli/check/settings.d.ts.map +1 -0
- package/dist/cli/check/settings.js +81 -0
- package/dist/cli/check/settings.js.map +1 -0
- package/dist/cli/check.d.ts +36 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +76 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/create.d.ts +20 -0
- package/dist/cli/create.d.ts.map +1 -0
- package/dist/cli/create.js +251 -0
- package/dist/cli/create.js.map +1 -0
- package/dist/cli/describe.d.ts +35 -0
- package/dist/cli/describe.d.ts.map +1 -0
- package/dist/cli/describe.js +230 -0
- package/dist/cli/describe.js.map +1 -0
- package/dist/cli/docs.d.ts +11 -0
- package/dist/cli/docs.d.ts.map +1 -0
- package/dist/cli/docs.js +152 -0
- package/dist/cli/docs.js.map +1 -0
- package/dist/cli/index.d.ts +18 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +281 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/extend.d.ts +23 -0
- package/dist/extend.d.ts.map +1 -0
- package/dist/extend.js +53 -0
- package/dist/extend.js.map +1 -0
- package/dist/graph/diff.d.ts +31 -0
- package/dist/graph/diff.d.ts.map +1 -0
- package/dist/graph/diff.js +71 -0
- package/dist/graph/diff.js.map +1 -0
- package/dist/graph/graph.d.ts +69 -0
- package/dist/graph/graph.d.ts.map +1 -0
- package/dist/graph/graph.js +284 -0
- package/dist/graph/graph.js.map +1 -0
- package/dist/graph/primitives.d.ts +52 -0
- package/dist/graph/primitives.d.ts.map +1 -0
- package/dist/graph/primitives.js +62 -0
- package/dist/graph/primitives.js.map +1 -0
- package/dist/graph/tracked.d.ts +31 -0
- package/dist/graph/tracked.d.ts.map +1 -0
- package/dist/graph/tracked.js +69 -0
- package/dist/graph/tracked.js.map +1 -0
- package/dist/graph/types.d.ts +34 -0
- package/dist/graph/types.d.ts.map +1 -0
- package/dist/graph/types.js +0 -0
- package/dist/graph/types.js.map +1 -0
- package/dist/index.d.ts +100 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/index.js.map +1 -0
- package/dist/installation.d.ts +112 -0
- package/dist/installation.d.ts.map +1 -0
- package/dist/installation.js +193 -0
- package/dist/installation.js.map +1 -0
- package/dist/intelligence-bridge.d.ts +73 -0
- package/dist/intelligence-bridge.d.ts.map +1 -0
- package/dist/intelligence-bridge.js +31 -0
- package/dist/intelligence-bridge.js.map +1 -0
- package/dist/invariants/engine.d.ts +36 -0
- package/dist/invariants/engine.d.ts.map +1 -0
- package/dist/invariants/engine.js +88 -0
- package/dist/invariants/engine.js.map +1 -0
- package/dist/invariants/types.d.ts +75 -0
- package/dist/invariants/types.d.ts.map +1 -0
- package/dist/invariants/types.js +2 -0
- package/dist/invariants/types.js.map +1 -0
- package/dist/modules.d.ts +75 -0
- package/dist/modules.d.ts.map +1 -0
- package/dist/modules.js +87 -0
- package/dist/modules.js.map +1 -0
- package/dist/mutations/decidable.d.ts +26 -0
- package/dist/mutations/decidable.d.ts.map +1 -0
- package/dist/mutations/decidable.js +39 -0
- package/dist/mutations/decidable.js.map +1 -0
- package/dist/mutations/define-mutation.d.ts +32 -0
- package/dist/mutations/define-mutation.d.ts.map +1 -0
- package/dist/mutations/define-mutation.js +181 -0
- package/dist/mutations/define-mutation.js.map +1 -0
- package/dist/mutations/derive-edits.d.ts +75 -0
- package/dist/mutations/derive-edits.d.ts.map +1 -0
- package/dist/mutations/derive-edits.js +240 -0
- package/dist/mutations/derive-edits.js.map +1 -0
- package/dist/mutations/form.d.ts +63 -0
- package/dist/mutations/form.d.ts.map +1 -0
- package/dist/mutations/form.js +113 -0
- package/dist/mutations/form.js.map +1 -0
- package/dist/mutations/node-ref.d.ts +83 -0
- package/dist/mutations/node-ref.d.ts.map +1 -0
- package/dist/mutations/node-ref.js +113 -0
- package/dist/mutations/node-ref.js.map +1 -0
- package/dist/mutations/types.d.ts +136 -0
- package/dist/mutations/types.d.ts.map +1 -0
- package/dist/mutations/types.js +2 -0
- package/dist/mutations/types.js.map +1 -0
- package/dist/ops/log.d.ts +35 -0
- package/dist/ops/log.d.ts.map +1 -0
- package/dist/ops/log.js +103 -0
- package/dist/ops/log.js.map +1 -0
- package/dist/ops/types.d.ts +52 -0
- package/dist/ops/types.d.ts.map +1 -0
- package/dist/ops/types.js +2 -0
- package/dist/ops/types.js.map +1 -0
- package/dist/ops/undo.d.ts +33 -0
- package/dist/ops/undo.d.ts.map +1 -0
- package/dist/ops/undo.js +65 -0
- package/dist/ops/undo.js.map +1 -0
- package/dist/permissions/policy.d.ts +68 -0
- package/dist/permissions/policy.d.ts.map +1 -0
- package/dist/permissions/policy.js +191 -0
- package/dist/permissions/policy.js.map +1 -0
- package/dist/permissions/types.d.ts +78 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/persistence/memory.d.ts +6 -0
- package/dist/persistence/memory.d.ts.map +1 -0
- package/dist/persistence/memory.js +31 -0
- package/dist/persistence/memory.js.map +1 -0
- package/dist/persistence/sqlite.d.ts +59 -0
- package/dist/persistence/sqlite.d.ts.map +1 -0
- package/dist/persistence/sqlite.js +131 -0
- package/dist/persistence/sqlite.js.map +1 -0
- package/dist/persistence/types.d.ts +22 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +2 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/presence.d.ts +38 -0
- package/dist/presence.d.ts.map +1 -0
- package/dist/presence.js +50 -0
- package/dist/presence.js.map +1 -0
- package/dist/scaffold/domain.d.ts +8 -0
- package/dist/scaffold/domain.d.ts.map +1 -0
- package/dist/scaffold/domain.js +331 -0
- package/dist/scaffold/domain.js.map +1 -0
- package/dist/scaffold/index.d.ts +66 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +142 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/lens.d.ts +31 -0
- package/dist/scaffold/lens.d.ts.map +1 -0
- package/dist/scaffold/lens.js +176 -0
- package/dist/scaffold/lens.js.map +1 -0
- package/dist/scaffold/names.d.ts +44 -0
- package/dist/scaffold/names.d.ts.map +1 -0
- package/dist/scaffold/names.js +69 -0
- package/dist/scaffold/names.js.map +1 -0
- package/dist/scaffold/project.d.ts +41 -0
- package/dist/scaffold/project.d.ts.map +1 -0
- package/dist/scaffold/project.js +604 -0
- package/dist/scaffold/project.js.map +1 -0
- package/dist/scaffold/ui.d.ts +15 -0
- package/dist/scaffold/ui.d.ts.map +1 -0
- package/dist/scaffold/ui.js +536 -0
- package/dist/scaffold/ui.js.map +1 -0
- package/dist/schema/define-node.d.ts +132 -0
- package/dist/schema/define-node.d.ts.map +1 -0
- package/dist/schema/define-node.js +254 -0
- package/dist/schema/define-node.js.map +1 -0
- package/dist/schema/figures.d.ts +42 -0
- package/dist/schema/figures.d.ts.map +1 -0
- package/dist/schema/figures.js +220 -0
- package/dist/schema/figures.js.map +1 -0
- package/dist/schema/json-schema.d.ts +39 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +74 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/schema.d.ts +43 -0
- package/dist/schema/schema.d.ts.map +1 -0
- package/dist/schema/schema.js +102 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/types.d.ts +201 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +2 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/search.d.ts +215 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +449 -0
- package/dist/search.js.map +1 -0
- package/dist/settings.d.ts +30 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +74 -0
- package/dist/settings.js.map +1 -0
- package/dist/store.d.ts +284 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +660 -0
- package/dist/store.js.map +1 -0
- package/dist/studio-door.d.ts +187 -0
- package/dist/studio-door.d.ts.map +1 -0
- package/dist/studio-door.js +20 -0
- package/dist/studio-door.js.map +1 -0
- package/dist/sync/conflict.d.ts +37 -0
- package/dist/sync/conflict.d.ts.map +1 -0
- package/dist/sync/conflict.js +56 -0
- package/dist/sync/conflict.js.map +1 -0
- package/dist/sync/engine.d.ts +118 -0
- package/dist/sync/engine.d.ts.map +1 -0
- package/dist/sync/engine.js +341 -0
- package/dist/sync/engine.js.map +1 -0
- package/dist/sync/google-calendar.d.ts +54 -0
- package/dist/sync/google-calendar.d.ts.map +1 -0
- package/dist/sync/google-calendar.js +167 -0
- package/dist/sync/google-calendar.js.map +1 -0
- package/dist/sync/types.d.ts +125 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +6 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/temporal/effectivity.d.ts +75 -0
- package/dist/temporal/effectivity.d.ts.map +1 -0
- package/dist/temporal/effectivity.js +89 -0
- package/dist/temporal/effectivity.js.map +1 -0
- package/dist/testing.d.ts +63 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +194 -0
- package/dist/testing.js.map +1 -0
- package/dist/theme/contrast.d.ts +47 -0
- package/dist/theme/contrast.d.ts.map +1 -0
- package/dist/theme/contrast.js +172 -0
- package/dist/theme/contrast.js.map +1 -0
- package/dist/theme/derive.d.ts +81 -0
- package/dist/theme/derive.d.ts.map +1 -0
- package/dist/theme/derive.js +171 -0
- package/dist/theme/derive.js.map +1 -0
- package/dist/theme/kit.d.ts +106 -0
- package/dist/theme/kit.d.ts.map +1 -0
- package/dist/theme/kit.js +84 -0
- package/dist/theme/kit.js.map +1 -0
- package/dist/theme/palettes.d.ts +32 -0
- package/dist/theme/palettes.d.ts.map +1 -0
- package/dist/theme/palettes.js +96 -0
- package/dist/theme/palettes.js.map +1 -0
- package/dist/theme/types.d.ts +131 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +23 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/views/types.d.ts +89 -0
- package/dist/views/types.d.ts.map +1 -0
- package/dist/views/types.js +88 -0
- package/dist/views/types.js.map +1 -0
- package/dist/watched.d.ts +33 -0
- package/dist/watched.d.ts.map +1 -0
- package/dist/watched.js +50 -0
- package/dist/watched.js.map +1 -0
- package/dist/who.d.ts +26 -0
- package/dist/who.d.ts.map +1 -0
- package/dist/who.js +20 -0
- package/dist/who.js.map +1 -0
- 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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"}
|