@graview/pages 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 +47 -0
- package/dist/ask.d.ts +21 -0
- package/dist/ask.d.ts.map +1 -0
- package/dist/ask.js +109 -0
- package/dist/ask.js.map +1 -0
- package/dist/face-controls.d.ts +68 -0
- package/dist/face-controls.d.ts.map +1 -0
- package/dist/face-controls.js +231 -0
- package/dist/face-controls.js.map +1 -0
- package/dist/face-placed.d.ts +16 -0
- package/dist/face-placed.d.ts.map +1 -0
- package/dist/face-placed.js +34 -0
- package/dist/face-placed.js.map +1 -0
- package/dist/facts.d.ts +115 -0
- package/dist/facts.d.ts.map +1 -0
- package/dist/facts.js +180 -0
- package/dist/facts.js.map +1 -0
- package/dist/form.d.ts +53 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +183 -0
- package/dist/form.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/page-context.d.ts +74 -0
- package/dist/page-context.d.ts.map +1 -0
- package/dist/page-context.js +38 -0
- package/dist/page-context.js.map +1 -0
- package/dist/page-home.d.ts +19 -0
- package/dist/page-home.d.ts.map +1 -0
- package/dist/page-home.js +67 -0
- package/dist/page-home.js.map +1 -0
- package/dist/page-list.d.ts +23 -0
- package/dist/page-list.d.ts.map +1 -0
- package/dist/page-list.js +196 -0
- package/dist/page-list.js.map +1 -0
- package/dist/page-map.d.ts +20 -0
- package/dist/page-map.d.ts.map +1 -0
- package/dist/page-map.js +71 -0
- package/dist/page-map.js.map +1 -0
- package/dist/page-places.d.ts +72 -0
- package/dist/page-places.d.ts.map +1 -0
- package/dist/page-places.js +304 -0
- package/dist/page-places.js.map +1 -0
- package/dist/page-problems.d.ts +58 -0
- package/dist/page-problems.d.ts.map +1 -0
- package/dist/page-problems.js +113 -0
- package/dist/page-problems.js.map +1 -0
- package/dist/page-record.d.ts +14 -0
- package/dist/page-record.d.ts.map +1 -0
- package/dist/page-record.js +111 -0
- package/dist/page-record.js.map +1 -0
- package/dist/page-search.d.ts +50 -0
- package/dist/page-search.d.ts.map +1 -0
- package/dist/page-search.js +108 -0
- package/dist/page-search.js.map +1 -0
- package/dist/page-shell.d.ts +43 -0
- package/dist/page-shell.d.ts.map +1 -0
- package/dist/page-shell.js +171 -0
- package/dist/page-shell.js.map +1 -0
- package/dist/page-typography.d.ts +54 -0
- package/dist/page-typography.d.ts.map +1 -0
- package/dist/page-typography.js +166 -0
- package/dist/page-typography.js.map +1 -0
- package/dist/pages.d.ts +19 -0
- package/dist/pages.d.ts.map +1 -0
- package/dist/pages.js +19 -0
- package/dist/pages.js.map +1 -0
- package/dist/registry.d.ts +111 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +105 -0
- package/dist/registry.js.map +1 -0
- package/dist/router.d.ts +35 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +155 -0
- package/dist/router.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createContext, useContext, useLayoutEffect, useSyncExternalStore } from "react";
|
|
2
|
+
export const FaceControls = createContext(null);
|
|
3
|
+
export function createPlaced() {
|
|
4
|
+
const counts = new Map();
|
|
5
|
+
const listeners = new Set();
|
|
6
|
+
const tell = () => {
|
|
7
|
+
for (const listener of listeners)
|
|
8
|
+
listener();
|
|
9
|
+
};
|
|
10
|
+
return {
|
|
11
|
+
count: (control) => counts.get(control) ?? 0,
|
|
12
|
+
place(control) {
|
|
13
|
+
counts.set(control, (counts.get(control) ?? 0) + 1);
|
|
14
|
+
tell();
|
|
15
|
+
return () => {
|
|
16
|
+
counts.set(control, (counts.get(control) ?? 1) - 1);
|
|
17
|
+
tell();
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
subscribe(listener) {
|
|
21
|
+
listeners.add(listener);
|
|
22
|
+
return () => listeners.delete(listener);
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** A control a shell drew itself: the face's root then draws no second one. */
|
|
27
|
+
export function usePlacedOnTheFace(control) {
|
|
28
|
+
const placed = useContext(FaceControls);
|
|
29
|
+
useLayoutEffect(() => placed?.place(control), [placed, control]);
|
|
30
|
+
}
|
|
31
|
+
export function usePlaced(placed, control) {
|
|
32
|
+
return useSyncExternalStore(placed.subscribe, () => placed.count(control) > 0, () => false);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=face-placed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"face-placed.js","sourceRoot":"","sources":["../src/face-placed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAczF,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAgB,IAAI,CAAC,CAAC;AAE/D,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IACxC,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,KAAK,MAAM,QAAQ,IAAI,SAAS;YAAE,QAAQ,EAAE,CAAC;IAC/C,CAAC,CAAC;IACF,OAAO;QACL,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QAC5C,KAAK,CAAC,OAAO;YACX,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACpD,IAAI,EAAE,CAAC;YACP,OAAO,GAAG,EAAE;gBACV,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACpD,IAAI,EAAE,CAAC;YACT,CAAC,CAAC;QACJ,CAAC;QACD,SAAS,CAAC,QAAQ;YAChB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,OAAoB;IACrD,MAAM,MAAM,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACxC,eAAe,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,OAAoB;IAC5D,OAAO,oBAAoB,CACzB,MAAM,CAAC,SAAS,EAChB,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAC/B,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;AACJ,CAAC"}
|
package/dist/facts.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { type AnySchema, type Principal, type ReadableField, type Repair, type Store, type Violation } from "@graview/core";
|
|
2
|
+
import { type AffordanceSet } from "@graview/tools";
|
|
3
|
+
/**
|
|
4
|
+
* Everything a record page says, derived ONCE.
|
|
5
|
+
*
|
|
6
|
+
* The parity contract: a record page and the spatial detail of the same node
|
|
7
|
+
* must state identical facts, and the only way that stays true is if there
|
|
8
|
+
* is exactly one derivation for the page to render — the same label helper,
|
|
9
|
+
* the same readable fields, the same violation filter, the same affordance
|
|
10
|
+
* set the strip uses. This module composes those sources; it invents nothing.
|
|
11
|
+
*/
|
|
12
|
+
export interface RecordLinkGroup {
|
|
13
|
+
readonly edgeKind: string;
|
|
14
|
+
readonly direction: "out" | "in";
|
|
15
|
+
/** The edge declaration's own description, when it has one. */
|
|
16
|
+
readonly description?: string;
|
|
17
|
+
/**
|
|
18
|
+
* `apart` is what tells a target from another of the same name in this
|
|
19
|
+
* group — a vehicle's two "Check engine light on" appointments, by when.
|
|
20
|
+
*/
|
|
21
|
+
readonly targets: readonly {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
readonly kind: string;
|
|
24
|
+
readonly label: string;
|
|
25
|
+
readonly apart?: string;
|
|
26
|
+
}[];
|
|
27
|
+
}
|
|
28
|
+
export interface RecordFacts {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly kind: string;
|
|
31
|
+
readonly label: string;
|
|
32
|
+
readonly fields: readonly ReadableField[];
|
|
33
|
+
readonly links: readonly RecordLinkGroup[];
|
|
34
|
+
readonly violations: readonly Violation[];
|
|
35
|
+
readonly actions: AffordanceSet;
|
|
36
|
+
}
|
|
37
|
+
export interface FactsOptions {
|
|
38
|
+
readonly principal?: Principal;
|
|
39
|
+
readonly context?: Readonly<Record<string, unknown>>;
|
|
40
|
+
}
|
|
41
|
+
export declare function recordFacts<S extends AnySchema>(store: Store<S>, id: string, options?: FactsOptions): RecordFacts | undefined;
|
|
42
|
+
export interface KindFacts {
|
|
43
|
+
readonly kind: string;
|
|
44
|
+
readonly members: readonly {
|
|
45
|
+
readonly id: string;
|
|
46
|
+
readonly kind: string;
|
|
47
|
+
}[];
|
|
48
|
+
/**
|
|
49
|
+
* The acts that can BEGIN this kind, as the derivation offers them — and
|
|
50
|
+
* the ones this seat may not take, with the policy's own sentence.
|
|
51
|
+
*/
|
|
52
|
+
readonly actions: AffordanceSet;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Everything a LIST page says about a kind, derived once — the sibling of
|
|
56
|
+
* `recordFacts` for the surface that is about a kind rather than a node.
|
|
57
|
+
*
|
|
58
|
+
* The list page had no derivation to ask, so it filtered `store.allMutations()`
|
|
59
|
+
* by `creates` and checked `store.permits` — which is the exact thing
|
|
60
|
+
* `graview-pages` tells an app's own page not to do, done by the framework's
|
|
61
|
+
* own page. The two answers differ: the derivation also drops an act it
|
|
62
|
+
* cannot ASK for. A creating act that needs a node reference with no
|
|
63
|
+
* candidates — "add an item for someone", with nobody yet — is withheld in
|
|
64
|
+
* the scene and was offered on the list page as a live form whose picker was
|
|
65
|
+
* empty and whose submit could only refuse.
|
|
66
|
+
*
|
|
67
|
+
* Same call the scene makes for a selected district: an empty selection,
|
|
68
|
+
* with the kind named.
|
|
69
|
+
*/
|
|
70
|
+
export declare function kindFacts<S extends AnySchema>(store: Store<S>, kind: string, options?: FactsOptions): KindFacts;
|
|
71
|
+
/**
|
|
72
|
+
* A RULE'S REPAIRS IN THE ONE ORDER THE DERIVATION RANKED THEM.
|
|
73
|
+
*
|
|
74
|
+
* A rule that implicates five late tasks names ten repairs in a single
|
|
75
|
+
* violation, in whatever order it walked its subjects — so a record page
|
|
76
|
+
* rendering `violation.repairs` straight led the page about the fifth task
|
|
77
|
+
* with the first task's repair. The derivation already knows better: asked
|
|
78
|
+
* with this record as its focus, it puts the record's own repairs at the
|
|
79
|
+
* front. This reads that answer back rather than sorting again, so the page,
|
|
80
|
+
* the strip and the pointer menu cannot arrive at different firsts.
|
|
81
|
+
*
|
|
82
|
+
* Repairs the derivation did not produce — withheld for reasons other than
|
|
83
|
+
* permission, or named by a violation this set was not derived from — keep
|
|
84
|
+
* their declared order at the end rather than being dropped.
|
|
85
|
+
*/
|
|
86
|
+
export declare function rankedRepairs(actions: AffordanceSet, repairs: readonly Repair[]): readonly Repair[];
|
|
87
|
+
/** One declared relation between two kinds, with how many of it there are. */
|
|
88
|
+
export interface KindRelation {
|
|
89
|
+
readonly edgeKind: string;
|
|
90
|
+
readonly from: string;
|
|
91
|
+
/** The kind at the far end — or "*" when the declaration allows any. */
|
|
92
|
+
readonly to: string;
|
|
93
|
+
/** How the edge reads from the kind that declares it. */
|
|
94
|
+
readonly description?: string;
|
|
95
|
+
/** How it reads from the other end. */
|
|
96
|
+
readonly inverse?: string;
|
|
97
|
+
readonly count: number;
|
|
98
|
+
}
|
|
99
|
+
export interface KindMap {
|
|
100
|
+
readonly kinds: readonly {
|
|
101
|
+
readonly kind: string;
|
|
102
|
+
readonly plural: string;
|
|
103
|
+
readonly count: number;
|
|
104
|
+
}[];
|
|
105
|
+
readonly relations: readonly KindRelation[];
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* HOW THE KINDS FIT TOGETHER, derived once: every kind with how many of it
|
|
109
|
+
* there are, and every declared edge between kinds with its own words and
|
|
110
|
+
* the live count — the routed face's roads and relation key. A declaration
|
|
111
|
+
* that allows any kind at the far end ("*") is listed once per kind the
|
|
112
|
+
* graph actually joins it to, and once as "*" when it joins none yet.
|
|
113
|
+
*/
|
|
114
|
+
export declare function kindMap<S extends AnySchema>(store: Store<S>): KindMap;
|
|
115
|
+
//# sourceMappingURL=facts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facts.d.ts","sourceRoot":"","sources":["../src/facts.ts"],"names":[],"mappings":"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"}
|
package/dist/facts.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { labelOf, readableFields, tellApart, violationsTouching, } from "@graview/core";
|
|
2
|
+
import { deriveAffordances } from "@graview/tools";
|
|
3
|
+
export function recordFacts(store, id, options = {}) {
|
|
4
|
+
const node = store.graph.getNode(id);
|
|
5
|
+
if (!node)
|
|
6
|
+
return undefined;
|
|
7
|
+
const definition = store.schema.tryDefinition(node.kind);
|
|
8
|
+
const name = (candidate) => labelOf(store.schema.tryDefinition(candidate.kind), candidate);
|
|
9
|
+
const groups = new Map();
|
|
10
|
+
for (const edge of store.graph.allEdges()) {
|
|
11
|
+
const direction = edge.from === id ? "out" : edge.to === id ? "in" : null;
|
|
12
|
+
if (!direction)
|
|
13
|
+
continue;
|
|
14
|
+
const otherId = direction === "out" ? edge.to : edge.from;
|
|
15
|
+
const other = store.graph.getNode(otherId);
|
|
16
|
+
if (!other)
|
|
17
|
+
continue;
|
|
18
|
+
const key = `${edge.kind}|${direction}`;
|
|
19
|
+
/*
|
|
20
|
+
* The caption, from the end that declared the edge — its `description`
|
|
21
|
+
* read from the declaring side, its `inverse` read from the other end,
|
|
22
|
+
* because one sentence does not work in both places ("the tasks on this
|
|
23
|
+
* list" is not what a task is to its list). Without an inverse, the
|
|
24
|
+
* declaring side's words are still better than none.
|
|
25
|
+
*/
|
|
26
|
+
const declaredOn = direction === "out" ? definition : store.schema.tryDefinition(other.kind);
|
|
27
|
+
const declaration = declaredOn?.edges?.[edge.kind];
|
|
28
|
+
const description = direction === "in" ? (declaration?.inverse ?? declaration?.description) : declaration?.description;
|
|
29
|
+
const group = groups.get(key) ??
|
|
30
|
+
(() => {
|
|
31
|
+
const made = {
|
|
32
|
+
edgeKind: edge.kind,
|
|
33
|
+
direction,
|
|
34
|
+
...(description ? { description } : {}),
|
|
35
|
+
targets: [],
|
|
36
|
+
};
|
|
37
|
+
groups.set(key, made);
|
|
38
|
+
return made;
|
|
39
|
+
})();
|
|
40
|
+
group.targets.push({ id: other.id, kind: other.kind, label: name(other) });
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
id,
|
|
44
|
+
kind: node.kind,
|
|
45
|
+
label: name(node),
|
|
46
|
+
fields: readableFields(node, definition),
|
|
47
|
+
violations: violationsTouching(store.violations(options.context), [id]),
|
|
48
|
+
/*
|
|
49
|
+
* The record IS the focus: a page about one task leads with that task's
|
|
50
|
+
* own repair, not with the first repair a rule implicating six of them
|
|
51
|
+
* happened to list. Same rank the strip and the pointer menu read.
|
|
52
|
+
*/
|
|
53
|
+
actions: deriveAffordances(store, [id], {
|
|
54
|
+
focus: id,
|
|
55
|
+
...(options.principal ? { principal: options.principal } : {}),
|
|
56
|
+
...(options.context ? { context: options.context } : {}),
|
|
57
|
+
}),
|
|
58
|
+
links: [...groups.values()].map((group) => {
|
|
59
|
+
const apart = tellApart(group.targets.flatMap((target) => {
|
|
60
|
+
const other = store.graph.getNode(target.id);
|
|
61
|
+
return other ? [other] : [];
|
|
62
|
+
}), (kind) => store.schema.tryDefinition(kind));
|
|
63
|
+
return {
|
|
64
|
+
...group,
|
|
65
|
+
targets: [...group.targets]
|
|
66
|
+
.map((target) => (apart.has(target.id) ? { ...target, apart: apart.get(target.id) } : target))
|
|
67
|
+
.sort((a, b) => a.label.localeCompare(b.label)),
|
|
68
|
+
};
|
|
69
|
+
}),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Everything a LIST page says about a kind, derived once — the sibling of
|
|
74
|
+
* `recordFacts` for the surface that is about a kind rather than a node.
|
|
75
|
+
*
|
|
76
|
+
* The list page had no derivation to ask, so it filtered `store.allMutations()`
|
|
77
|
+
* by `creates` and checked `store.permits` — which is the exact thing
|
|
78
|
+
* `graview-pages` tells an app's own page not to do, done by the framework's
|
|
79
|
+
* own page. The two answers differ: the derivation also drops an act it
|
|
80
|
+
* cannot ASK for. A creating act that needs a node reference with no
|
|
81
|
+
* candidates — "add an item for someone", with nobody yet — is withheld in
|
|
82
|
+
* the scene and was offered on the list page as a live form whose picker was
|
|
83
|
+
* empty and whose submit could only refuse.
|
|
84
|
+
*
|
|
85
|
+
* Same call the scene makes for a selected district: an empty selection,
|
|
86
|
+
* with the kind named.
|
|
87
|
+
*/
|
|
88
|
+
export function kindFacts(store, kind, options = {}) {
|
|
89
|
+
return {
|
|
90
|
+
kind,
|
|
91
|
+
members: store.graph.nodesOfKind(kind),
|
|
92
|
+
actions: deriveAffordances(store, [], {
|
|
93
|
+
kindSelection: [kind],
|
|
94
|
+
...(options.principal ? { principal: options.principal } : {}),
|
|
95
|
+
...(options.context ? { context: options.context } : {}),
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* A RULE'S REPAIRS IN THE ONE ORDER THE DERIVATION RANKED THEM.
|
|
101
|
+
*
|
|
102
|
+
* A rule that implicates five late tasks names ten repairs in a single
|
|
103
|
+
* violation, in whatever order it walked its subjects — so a record page
|
|
104
|
+
* rendering `violation.repairs` straight led the page about the fifth task
|
|
105
|
+
* with the first task's repair. The derivation already knows better: asked
|
|
106
|
+
* with this record as its focus, it puts the record's own repairs at the
|
|
107
|
+
* front. This reads that answer back rather than sorting again, so the page,
|
|
108
|
+
* the strip and the pointer menu cannot arrive at different firsts.
|
|
109
|
+
*
|
|
110
|
+
* Repairs the derivation did not produce — withheld for reasons other than
|
|
111
|
+
* permission, or named by a violation this set was not derived from — keep
|
|
112
|
+
* their declared order at the end rather than being dropped.
|
|
113
|
+
*/
|
|
114
|
+
export function rankedRepairs(actions, repairs) {
|
|
115
|
+
const key = (mutation, args) => `${mutation}|${JSON.stringify(args)}`;
|
|
116
|
+
const ranks = new Map();
|
|
117
|
+
for (const affordance of [...actions.affordances, ...actions.withheld]) {
|
|
118
|
+
if (affordance.provider !== "invariant")
|
|
119
|
+
continue;
|
|
120
|
+
const at = key(affordance.mutation, affordance.args);
|
|
121
|
+
if (!ranks.has(at))
|
|
122
|
+
ranks.set(at, affordance.rank ?? Number.MAX_SAFE_INTEGER);
|
|
123
|
+
}
|
|
124
|
+
const unranked = Number.MAX_SAFE_INTEGER;
|
|
125
|
+
return [...repairs]
|
|
126
|
+
.map((repair, declared) => ({ repair, declared }))
|
|
127
|
+
.sort((a, b) => (ranks.get(key(a.repair.mutation, a.repair.args ?? {})) ?? unranked) -
|
|
128
|
+
(ranks.get(key(b.repair.mutation, b.repair.args ?? {})) ?? unranked) ||
|
|
129
|
+
a.declared - b.declared)
|
|
130
|
+
.map((entry) => entry.repair);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* HOW THE KINDS FIT TOGETHER, derived once: every kind with how many of it
|
|
134
|
+
* there are, and every declared edge between kinds with its own words and
|
|
135
|
+
* the live count — the routed face's roads and relation key. A declaration
|
|
136
|
+
* that allows any kind at the far end ("*") is listed once per kind the
|
|
137
|
+
* graph actually joins it to, and once as "*" when it joins none yet.
|
|
138
|
+
*/
|
|
139
|
+
export function kindMap(store) {
|
|
140
|
+
const kinds = store.schema.kinds.map((kind) => ({
|
|
141
|
+
kind,
|
|
142
|
+
plural: store.schema.tryDefinition(kind)?.plural ?? kind,
|
|
143
|
+
count: store.graph.nodesOfKind(kind).length,
|
|
144
|
+
}));
|
|
145
|
+
const counts = new Map();
|
|
146
|
+
for (const edge of store.graph.allEdges()) {
|
|
147
|
+
const from = store.graph.getNode(edge.from);
|
|
148
|
+
const to = store.graph.getNode(edge.to);
|
|
149
|
+
if (!from || !to)
|
|
150
|
+
continue;
|
|
151
|
+
const key = `${edge.kind}|${from.kind}|${to.kind}`;
|
|
152
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
153
|
+
}
|
|
154
|
+
const relations = [];
|
|
155
|
+
for (const { kind } of kinds) {
|
|
156
|
+
const declared = (store.schema.tryDefinition(kind)?.edges ?? {});
|
|
157
|
+
for (const [edgeKind, declaration] of Object.entries(declared)) {
|
|
158
|
+
const targets = declaration.to === "*" || declaration.to === undefined
|
|
159
|
+
? (() => {
|
|
160
|
+
const seen = [...counts.keys()]
|
|
161
|
+
.filter((key) => key.startsWith(`${edgeKind}|${kind}|`))
|
|
162
|
+
.map((key) => key.split("|")[2]);
|
|
163
|
+
return seen.length > 0 ? seen : ["*"];
|
|
164
|
+
})()
|
|
165
|
+
: declaration.to;
|
|
166
|
+
for (const to of targets) {
|
|
167
|
+
relations.push({
|
|
168
|
+
edgeKind,
|
|
169
|
+
from: kind,
|
|
170
|
+
to,
|
|
171
|
+
...(declaration.description ? { description: declaration.description } : {}),
|
|
172
|
+
...(declaration.inverse ? { inverse: declaration.inverse } : {}),
|
|
173
|
+
count: counts.get(`${edgeKind}|${kind}|${to}`) ?? 0,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return { kinds, relations };
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=facts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facts.js","sourceRoot":"","sources":["../src/facts.ts"],"names":[],"mappings":"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"}
|
package/dist/form.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type AnySchema, type Principal, type Store } from "@graview/core";
|
|
2
|
+
import type { AnyMutationDefinition } from "@graview/core";
|
|
3
|
+
import type { OpenParameter } from "@graview/tools";
|
|
4
|
+
export interface DerivedFormProps<S extends AnySchema> {
|
|
5
|
+
readonly store: Store<S>;
|
|
6
|
+
readonly mutation: AnyMutationDefinition<S>;
|
|
7
|
+
/** Arguments already decided — a record page's own id, a repair's args. */
|
|
8
|
+
readonly prefilled?: Readonly<Record<string, unknown>>;
|
|
9
|
+
/**
|
|
10
|
+
* The affordance's open parameters, when this form is an act the interface
|
|
11
|
+
* derived. Their `candidates` are the only honest answers for a node
|
|
12
|
+
* reference here; without them the form falls back to every node of the
|
|
13
|
+
* kind, which is what a repair's blank and a list page's creating act get.
|
|
14
|
+
*/
|
|
15
|
+
readonly open?: readonly OpenParameter[];
|
|
16
|
+
readonly onDone?: () => void;
|
|
17
|
+
/**
|
|
18
|
+
* Where the fields START, still editable — unlike `prefilled`, which is
|
|
19
|
+
* decided and not asked. Search-to-create begins "A task called “zzz”"
|
|
20
|
+
* with the words already in the name, and the person may still fix the
|
|
21
|
+
* typo that found nothing.
|
|
22
|
+
*/
|
|
23
|
+
readonly initial?: Readonly<Record<string, unknown>>;
|
|
24
|
+
/**
|
|
25
|
+
* WHO IS SUBMITTING. The store judges every change against its author
|
|
26
|
+
* and the log attributes to it; a form that applied with no author acted
|
|
27
|
+
* as the anonymous human — who, under a policy, may do nothing — so on
|
|
28
|
+
* the routed face every permitted act was refused on press while the
|
|
29
|
+
* derivation beside it had offered it live. The same principal the page
|
|
30
|
+
* asked "may I?" with is the one that presses submit.
|
|
31
|
+
*/
|
|
32
|
+
readonly principal?: Principal;
|
|
33
|
+
/**
|
|
34
|
+
* What the submit button says, when the form is an act offered from where
|
|
35
|
+
* the page stands. An act that `connects` is offered from both ends, and
|
|
36
|
+
* its `title` is written from the subject's: on a song's page the form
|
|
37
|
+
* for putting it in an era was headed "Place it in an era" — the
|
|
38
|
+
* affordance's words from the song's end — and its button said "Put it in
|
|
39
|
+
* the era", the era's. Hand it the affordance's label and they agree.
|
|
40
|
+
*/
|
|
41
|
+
readonly label?: string;
|
|
42
|
+
/**
|
|
43
|
+
* The arguments to ASK, when the form answers a question somebody else
|
|
44
|
+
* posed — a repair's `missing`. Everything else is left as the act has it.
|
|
45
|
+
* A repair asking "when did the single come out?" through the derived edit
|
|
46
|
+
* act drew every field the act can change, the name first, and the date
|
|
47
|
+
* typed into the first box renamed the single to "2023-04-14".
|
|
48
|
+
*/
|
|
49
|
+
readonly only?: readonly string[];
|
|
50
|
+
}
|
|
51
|
+
/** The submit path is the ordinary one: `store.apply`, refusals shown. */
|
|
52
|
+
export declare function DerivedForm<S extends AnySchema>({ store, mutation, prefilled, open, onDone, principal, initial, label, only, }: DerivedFormProps<S>): import("react").JSX.Element;
|
|
53
|
+
//# sourceMappingURL=form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EAEd,KAAK,SAAS,EACd,KAAK,KAAK,EACX,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAuVpD,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,SAAS;IACnD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC5C,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,EAC/C,KAAK,EACL,QAAQ,EACR,SAAc,EACd,IAAS,EACT,MAAM,EACN,SAAS,EACT,OAAO,EACP,KAAK,EACL,IAAI,GACL,EAAE,gBAAgB,CAAC,CAAC,CAAC,+BA+CrB"}
|
package/dist/form.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { formFields, humaniseField, nounOf, labelOf, tellApart, } from "@graview/core";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
/**
|
|
5
|
+
* A form, walked off the mutation's own declaration.
|
|
6
|
+
*
|
|
7
|
+
* No page writes a form by hand: the mutation input already says every
|
|
8
|
+
* argument's control — a discriminated union is a type picker followed by
|
|
9
|
+
* that arm's fields, an array is repeatable rows, a node reference is a
|
|
10
|
+
* picker over the real nodes of its kinds. The strip's prompts read the
|
|
11
|
+
* same shapes; this is those shapes given room.
|
|
12
|
+
*/
|
|
13
|
+
const field = {
|
|
14
|
+
display: "grid",
|
|
15
|
+
// A track the width it was given: see the note on `column` in pages.tsx.
|
|
16
|
+
gridTemplateColumns: "minmax(0, 1fr)",
|
|
17
|
+
minWidth: 0,
|
|
18
|
+
gap: 4,
|
|
19
|
+
};
|
|
20
|
+
const labelStyle = {
|
|
21
|
+
fontSize: "0.8125rem",
|
|
22
|
+
color: "var(--graview-ink-muted)",
|
|
23
|
+
};
|
|
24
|
+
const controlStyle = {
|
|
25
|
+
font: "inherit",
|
|
26
|
+
/*
|
|
27
|
+
* A TARGET IN EVERY ENGINE, not only in the one it was measured in.
|
|
28
|
+
*
|
|
29
|
+
* Padding and line height alone came to 24 in Chromium and to 22 in
|
|
30
|
+
* WebKit, which has its own intrinsic metrics for a `select` and rounds
|
|
31
|
+
* nothing up for anybody. So every picker on the routed face was under
|
|
32
|
+
* the WCAG 2.2 minimum in the browser iOS ships, and the check that says
|
|
33
|
+
* so (`verify-pages`' `bigEnoughToHit`) only ever ran there through
|
|
34
|
+
* `pnpm engines`.
|
|
35
|
+
*/
|
|
36
|
+
minHeight: 24,
|
|
37
|
+
/*
|
|
38
|
+
* NEVER WIDER THAN ITS FIELD. A select is as wide as its longest option,
|
|
39
|
+
* and a picker over 320 vehicles ("2027 Mercedes-Benz GLE AMG 53 4MATIC+
|
|
40
|
+
* Coupe") was 618 pixels on a 390 phone, and the whole page scrolled
|
|
41
|
+
* sideways. It shrinks to its track and cuts the option inside its box.
|
|
42
|
+
*/
|
|
43
|
+
minWidth: 0,
|
|
44
|
+
maxWidth: "100%",
|
|
45
|
+
textOverflow: "ellipsis",
|
|
46
|
+
boxSizing: "border-box",
|
|
47
|
+
padding: "7px 10px",
|
|
48
|
+
borderRadius: 8,
|
|
49
|
+
border: "1px solid var(--graview-edge)",
|
|
50
|
+
background: "var(--graview-panel)",
|
|
51
|
+
color: "var(--graview-ink)",
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A PICKER THAT STILL LOOKS LIKE ONE.
|
|
55
|
+
*
|
|
56
|
+
* WebKit ignores an author's padding and minimum height on a `select` while
|
|
57
|
+
* the native appearance is on — so every picker on the routed face came out
|
|
58
|
+
* 22 pixels tall in the browser iOS ships, under the 24 WCAG 2.2 asks for,
|
|
59
|
+
* while the same element measured 35 in Chromium. Turning the appearance off
|
|
60
|
+
* is what makes the box the size it was asked to be, and it takes the
|
|
61
|
+
* platform's chevron with it; this puts one back, in the ink the scheme is
|
|
62
|
+
* already using.
|
|
63
|
+
*/
|
|
64
|
+
const pickerStyle = { ...controlStyle, appearance: "none", paddingRight: 28 };
|
|
65
|
+
function Picker({ children }) {
|
|
66
|
+
return (_jsxs("span", { style: { position: "relative", display: "grid", minWidth: 0 }, children: [children, _jsx("span", { "aria-hidden": "true", style: {
|
|
67
|
+
position: "absolute",
|
|
68
|
+
right: 10,
|
|
69
|
+
top: "50%",
|
|
70
|
+
transform: "translateY(-50%)",
|
|
71
|
+
fontSize: "0.75rem",
|
|
72
|
+
lineHeight: 1,
|
|
73
|
+
color: "var(--graview-ink-muted)",
|
|
74
|
+
pointerEvents: "none",
|
|
75
|
+
}, children: "\u25BE" })] }));
|
|
76
|
+
}
|
|
77
|
+
function Control({ store, spec, value, onChange, prefilled, open, }) {
|
|
78
|
+
// An argument the caller already answered — a subject id, a repair's own
|
|
79
|
+
// args — is stated, not asked again.
|
|
80
|
+
if (spec.name in prefilled && spec.control !== "group" && spec.control !== "variant") {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
/*
|
|
84
|
+
* A node picker is labelled by what it PICKS — "List", not "List id": the
|
|
85
|
+
* argument's name is an implementation detail, and the kinds it accepts
|
|
86
|
+
* are the declaration's own word for the thing.
|
|
87
|
+
*/
|
|
88
|
+
const named = spec.control === "node" && !spec.kinds.includes("*")
|
|
89
|
+
? spec.kinds.map((kind) => humaniseField(nounOf(store.schema.tryDefinition(kind), kind))).join(" or ")
|
|
90
|
+
: humaniseField(spec.name);
|
|
91
|
+
const title = named + (spec.optional ? "" : " *");
|
|
92
|
+
switch (spec.control) {
|
|
93
|
+
case "text":
|
|
94
|
+
case "date":
|
|
95
|
+
return (_jsxs("label", { style: field, children: [_jsx("span", { style: labelStyle, children: title }), _jsx("input", { type: spec.control === "date" ? (spec.time ? "datetime-local" : "date") : "text", name: spec.name, required: !spec.optional, value: typeof value === "string" ? value : "", onChange: (event) => onChange(event.target.value), style: controlStyle })] }));
|
|
96
|
+
case "number":
|
|
97
|
+
return (_jsxs("label", { style: field, children: [_jsx("span", { style: labelStyle, children: title }), _jsx("input", { type: "number", name: spec.name, required: !spec.optional, ...(spec.min === undefined ? {} : { min: spec.min }), ...(spec.max === undefined ? {} : { max: spec.max }), value: typeof value === "number" ? value : "", onChange: (event) => onChange(event.target.value === "" ? undefined : Number(event.target.value)), style: controlStyle })] }));
|
|
98
|
+
case "boolean":
|
|
99
|
+
return (_jsxs("label", { style: { ...field, gridAutoFlow: "column", justifyContent: "start", alignItems: "center" }, children: [_jsx("input", { type: "checkbox", name: spec.name, checked: value === true, onChange: (event) => onChange(event.target.checked) }), _jsx("span", { style: labelStyle, children: title })] }));
|
|
100
|
+
case "choice":
|
|
101
|
+
return (_jsxs("label", { style: field, children: [_jsx("span", { style: labelStyle, children: title }), _jsx(Picker, { children: _jsxs("select", { name: spec.name, required: !spec.optional, value: typeof value === "string" ? value : "", onChange: (event) => onChange(event.target.value || undefined), style: pickerStyle, children: [_jsx("option", { value: "", children: "\u2014" }), (spec.options ?? []).map((option) => (_jsx("option", { value: option, children: option }, option)))] }) })] }));
|
|
102
|
+
case "node": {
|
|
103
|
+
/*
|
|
104
|
+
* THE CANDIDATES THE DERIVATION WORKED OUT, when there are any.
|
|
105
|
+
*
|
|
106
|
+
* The affordance already knows which ids are honest answers here: a
|
|
107
|
+
* connecting act offers only who is NOT already on, a severing act
|
|
108
|
+
* only what is attached, and neither ever offers the record itself.
|
|
109
|
+
* This form listed every node of the kind instead, so the same act
|
|
110
|
+
* asked a narrower question in the strip than on the page — and a
|
|
111
|
+
* record's own "Depends on" offered the record.
|
|
112
|
+
*
|
|
113
|
+
* With no affordance to ask (a rule's repair, a creating act on a list
|
|
114
|
+
* page), every node of the kind is still the honest answer — EXCEPT
|
|
115
|
+
* the one the form is already about. A page that pins the subject in
|
|
116
|
+
* `prefilled` and lets this fall back listed that subject as an answer
|
|
117
|
+
* to its own edge, which for a self-referential kind was the ONLY
|
|
118
|
+
* answer: "Make it depend on something" whose only something was
|
|
119
|
+
* itself. The act then has to guard against it and the guard is
|
|
120
|
+
* invisible, so the one press anyone could make did nothing.
|
|
121
|
+
*/
|
|
122
|
+
const narrowed = open.find((parameter) => parameter.name === spec.name)?.candidates;
|
|
123
|
+
const pinned = new Set(Object.values(prefilled).filter((held) => typeof held === "string"));
|
|
124
|
+
const all = (spec.kinds.includes("*")
|
|
125
|
+
? [...store.graph.allNodes()]
|
|
126
|
+
: spec.kinds.flatMap((kind) => store.graph.nodesOfKind(kind))).filter((node) => !pinned.has(node.id));
|
|
127
|
+
const candidates = narrowed
|
|
128
|
+
? narrowed
|
|
129
|
+
.map((id) => store.graph.getNode(id))
|
|
130
|
+
.filter((node) => node !== undefined)
|
|
131
|
+
: all;
|
|
132
|
+
const told = tellApart(candidates, (kind) => store.schema.tryDefinition(kind));
|
|
133
|
+
return (_jsxs("label", { style: field, children: [_jsx("span", { style: labelStyle, children: title }), _jsx(Picker, { children: _jsxs("select", { name: spec.name, required: !spec.optional, value: typeof value === "string" ? value : "", onChange: (event) => onChange(event.target.value || undefined), style: pickerStyle, children: [_jsx("option", { value: "", children: "\u2014" }), candidates.map((candidate) => {
|
|
134
|
+
// Two releases called "Blue Hour" are told apart by what differs.
|
|
135
|
+
const apart = told.get(candidate.id);
|
|
136
|
+
return (_jsxs("option", { value: candidate.id, children: [labelOf(store.schema.tryDefinition(candidate.kind), candidate), apart ? ` · ${apart}` : ""] }, candidate.id));
|
|
137
|
+
})] }) })] }));
|
|
138
|
+
}
|
|
139
|
+
case "group": {
|
|
140
|
+
const held = (value ?? {});
|
|
141
|
+
return (_jsxs("fieldset", { style: { display: "grid", gap: 10, border: "1px solid var(--graview-edge)", borderRadius: 10, padding: 12 }, children: [_jsx("legend", { style: labelStyle, children: title }), spec.fields.map((child) => (_jsx(Control, { store: store, spec: child, value: held[child.name], onChange: (next) => onChange({ ...held, [child.name]: next }), prefilled: prefilled, open: open }, child.name)))] }));
|
|
142
|
+
}
|
|
143
|
+
case "variant": {
|
|
144
|
+
const held = (value ?? {});
|
|
145
|
+
const chosen = typeof held[spec.tag] === "string" ? held[spec.tag] : "";
|
|
146
|
+
const arm = spec.options.find((option) => option.value === chosen);
|
|
147
|
+
return (_jsxs("fieldset", { style: { display: "grid", gap: 10, border: "1px solid var(--graview-edge)", borderRadius: 10, padding: 12 }, children: [_jsx("legend", { style: labelStyle, children: title }), _jsxs("label", { style: field, children: [_jsx("span", { style: labelStyle, children: humaniseField(spec.tag) }), _jsxs("select", { value: chosen, onChange: (event) => onChange({ [spec.tag]: event.target.value }), style: controlStyle, children: [_jsx("option", { value: "", children: "\u2014" }), spec.options.map((option) => (_jsx("option", { value: option.value, children: humaniseField(option.value) }, option.value)))] })] }), arm?.fields.map((child) => (_jsx(Control, { store: store, spec: child, value: held[child.name], onChange: (next) => onChange({ ...held, [child.name]: next }), prefilled: prefilled, open: open }, child.name)))] }));
|
|
148
|
+
}
|
|
149
|
+
case "list": {
|
|
150
|
+
const items = Array.isArray(value) ? value : [];
|
|
151
|
+
return (_jsxs("fieldset", { style: { display: "grid", gap: 8, border: "1px solid var(--graview-edge)", borderRadius: 10, padding: 12 }, children: [_jsx("legend", { style: labelStyle, children: title }), items.map((item, index) => (_jsxs("div", { style: { display: "flex", gap: 8, alignItems: "end" }, children: [_jsx("div", { style: { flex: 1 }, children: _jsx(Control, { store: store, spec: { ...spec.item, optional: false }, value: item, onChange: (next) => onChange(items.map((held, at) => (at === index ? next : held))), prefilled: prefilled, open: open }) }), _jsx("button", { type: "button", onClick: () => onChange(items.filter((_, at) => at !== index)), children: "remove" })] }, index))), _jsx("button", { type: "button", onClick: () => onChange([...items, undefined]), style: { justifySelf: "start" }, children: "add another" })] }));
|
|
152
|
+
}
|
|
153
|
+
case "opaque":
|
|
154
|
+
// Named rather than silently dropped: an argument the form cannot
|
|
155
|
+
// honestly render is a missing control to build, not a hidden field.
|
|
156
|
+
return (_jsxs("p", { style: { ...labelStyle, margin: 0 }, children: ["\u201C", humaniseField(spec.name), "\u201D needs a structured answer this form cannot ask for yet."] }));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** The submit path is the ordinary one: `store.apply`, refusals shown. */
|
|
160
|
+
export function DerivedForm({ store, mutation, prefilled = {}, open = [], onDone, principal, initial, label, only, }) {
|
|
161
|
+
const [values, setValues] = useState(() => ({ ...initial }));
|
|
162
|
+
const [failed, setFailed] = useState(null);
|
|
163
|
+
const fields = formFields(mutation.input).filter((spec) => only === undefined || only.includes(spec.name));
|
|
164
|
+
return (_jsxs("form", { "data-testid": `form-${mutation.name}`, onSubmit: (event) => {
|
|
165
|
+
event.preventDefault();
|
|
166
|
+
try {
|
|
167
|
+
store.apply({ name: mutation.name, args: { ...values, ...prefilled } }, principal ? { author: principal } : {});
|
|
168
|
+
setFailed(null);
|
|
169
|
+
setValues({});
|
|
170
|
+
onDone?.();
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
// A refusal is a result, on a page exactly as in the strip.
|
|
174
|
+
setFailed(error instanceof Error ? error.message : String(error));
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
// A form is a grid item of the section above it and a grid container
|
|
178
|
+
// for the fields below: both halves have to be allowed to be narrower
|
|
179
|
+
// than what is in them, or a big enough text size pushes the page
|
|
180
|
+
// sideways. See the note on `column` in pages.tsx.
|
|
181
|
+
style: { display: "grid", gridTemplateColumns: "minmax(0, 1fr)", minWidth: 0, gap: 12 }, children: [fields.map((spec) => (_jsx(Control, { store: store, spec: spec, value: values[spec.name], onChange: (next) => setValues((current) => ({ ...current, [spec.name]: next })), prefilled: prefilled, open: open }, spec.name))), failed ? (_jsx("p", { "data-testid": "refused", role: "alert", style: { margin: 0, color: "var(--graview-warn)", fontSize: "0.875rem" }, children: failed })) : null, _jsx("button", { type: "submit", style: { justifySelf: "start" }, children: label ?? mutation.title ?? mutation.name })] }));
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=form.js.map
|
package/dist/form.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.tsx"],"names":[],"mappings":"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"}
|