@graview/primitives 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 (207) hide show
  1. package/LICENSE +96 -0
  2. package/README.md +25 -0
  3. package/dist/arrange-bar.d.ts +49 -0
  4. package/dist/arrange-bar.d.ts.map +1 -0
  5. package/dist/arrange-bar.js +264 -0
  6. package/dist/arrange-bar.js.map +1 -0
  7. package/dist/chat.d.ts +46 -0
  8. package/dist/chat.d.ts.map +1 -0
  9. package/dist/chat.js +343 -0
  10. package/dist/chat.js.map +1 -0
  11. package/dist/companion.d.ts +58 -0
  12. package/dist/companion.d.ts.map +1 -0
  13. package/dist/companion.js +433 -0
  14. package/dist/companion.js.map +1 -0
  15. package/dist/connections.d.ts +23 -0
  16. package/dist/connections.d.ts.map +1 -0
  17. package/dist/connections.js +100 -0
  18. package/dist/connections.js.map +1 -0
  19. package/dist/default-views.d.ts +35 -0
  20. package/dist/default-views.d.ts.map +1 -0
  21. package/dist/default-views.js +605 -0
  22. package/dist/default-views.js.map +1 -0
  23. package/dist/editable.d.ts +71 -0
  24. package/dist/editable.d.ts.map +1 -0
  25. package/dist/editable.js +225 -0
  26. package/dist/editable.js.map +1 -0
  27. package/dist/figure.d.ts +30 -0
  28. package/dist/figure.d.ts.map +1 -0
  29. package/dist/figure.js +66 -0
  30. package/dist/figure.js.map +1 -0
  31. package/dist/find.d.ts +5 -0
  32. package/dist/find.d.ts.map +1 -0
  33. package/dist/find.js +252 -0
  34. package/dist/find.js.map +1 -0
  35. package/dist/index.d.ts +51 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +44 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/installation.d.ts +17 -0
  40. package/dist/installation.d.ts.map +1 -0
  41. package/dist/installation.js +37 -0
  42. package/dist/installation.js.map +1 -0
  43. package/dist/ladder.d.ts +2 -0
  44. package/dist/ladder.d.ts.map +1 -0
  45. package/dist/ladder.js +53 -0
  46. package/dist/ladder.js.map +1 -0
  47. package/dist/lens/arranging.d.ts +41 -0
  48. package/dist/lens/arranging.d.ts.map +1 -0
  49. package/dist/lens/arranging.js +38 -0
  50. package/dist/lens/arranging.js.map +1 -0
  51. package/dist/lens/board.d.ts +146 -0
  52. package/dist/lens/board.d.ts.map +1 -0
  53. package/dist/lens/board.js +658 -0
  54. package/dist/lens/board.js.map +1 -0
  55. package/dist/lens/calendar-dates.d.ts +19 -0
  56. package/dist/lens/calendar-dates.d.ts.map +1 -0
  57. package/dist/lens/calendar-dates.js +55 -0
  58. package/dist/lens/calendar-dates.js.map +1 -0
  59. package/dist/lens/calendar-drawing.d.ts +59 -0
  60. package/dist/lens/calendar-drawing.d.ts.map +1 -0
  61. package/dist/lens/calendar-drawing.js +229 -0
  62. package/dist/lens/calendar-drawing.js.map +1 -0
  63. package/dist/lens/calendar-options.d.ts +107 -0
  64. package/dist/lens/calendar-options.d.ts.map +1 -0
  65. package/dist/lens/calendar-options.js +19 -0
  66. package/dist/lens/calendar-options.js.map +1 -0
  67. package/dist/lens/calendar-placing.d.ts +35 -0
  68. package/dist/lens/calendar-placing.d.ts.map +1 -0
  69. package/dist/lens/calendar-placing.js +113 -0
  70. package/dist/lens/calendar-placing.js.map +1 -0
  71. package/dist/lens/calendar-spans.d.ts +48 -0
  72. package/dist/lens/calendar-spans.d.ts.map +1 -0
  73. package/dist/lens/calendar-spans.js +146 -0
  74. package/dist/lens/calendar-spans.js.map +1 -0
  75. package/dist/lens/calendar-view.d.ts +34 -0
  76. package/dist/lens/calendar-view.d.ts.map +1 -0
  77. package/dist/lens/calendar-view.js +228 -0
  78. package/dist/lens/calendar-view.js.map +1 -0
  79. package/dist/lens/calendar.d.ts +43 -0
  80. package/dist/lens/calendar.d.ts.map +1 -0
  81. package/dist/lens/calendar.js +43 -0
  82. package/dist/lens/calendar.js.map +1 -0
  83. package/dist/lens/coverage.d.ts +183 -0
  84. package/dist/lens/coverage.d.ts.map +1 -0
  85. package/dist/lens/coverage.js +732 -0
  86. package/dist/lens/coverage.js.map +1 -0
  87. package/dist/lens/horizon.d.ts +14 -0
  88. package/dist/lens/horizon.d.ts.map +1 -0
  89. package/dist/lens/horizon.js +20 -0
  90. package/dist/lens/horizon.js.map +1 -0
  91. package/dist/lens/more.d.ts +16 -0
  92. package/dist/lens/more.d.ts.map +1 -0
  93. package/dist/lens/more.js +17 -0
  94. package/dist/lens/more.js.map +1 -0
  95. package/dist/lens/plan-lens.d.ts +17 -0
  96. package/dist/lens/plan-lens.d.ts.map +1 -0
  97. package/dist/lens/plan-lens.js +24 -0
  98. package/dist/lens/plan-lens.js.map +1 -0
  99. package/dist/lens/plan-state.d.ts +122 -0
  100. package/dist/lens/plan-state.d.ts.map +1 -0
  101. package/dist/lens/plan-state.js +152 -0
  102. package/dist/lens/plan-state.js.map +1 -0
  103. package/dist/lens/plan-view.d.ts +10 -0
  104. package/dist/lens/plan-view.d.ts.map +1 -0
  105. package/dist/lens/plan-view.js +576 -0
  106. package/dist/lens/plan-view.js.map +1 -0
  107. package/dist/lens/plan.d.ts +25 -0
  108. package/dist/lens/plan.d.ts.map +1 -0
  109. package/dist/lens/plan.js +25 -0
  110. package/dist/lens/plan.js.map +1 -0
  111. package/dist/lens/reach.d.ts +47 -0
  112. package/dist/lens/reach.d.ts.map +1 -0
  113. package/dist/lens/reach.js +67 -0
  114. package/dist/lens/reach.js.map +1 -0
  115. package/dist/lens/timeline.d.ts +137 -0
  116. package/dist/lens/timeline.d.ts.map +1 -0
  117. package/dist/lens/timeline.js +426 -0
  118. package/dist/lens/timeline.js.map +1 -0
  119. package/dist/markup.d.ts +23 -0
  120. package/dist/markup.d.ts.map +1 -0
  121. package/dist/markup.js +24 -0
  122. package/dist/markup.js.map +1 -0
  123. package/dist/places.d.ts +24 -0
  124. package/dist/places.d.ts.map +1 -0
  125. package/dist/places.js +227 -0
  126. package/dist/places.js.map +1 -0
  127. package/dist/popover.d.ts +28 -0
  128. package/dist/popover.d.ts.map +1 -0
  129. package/dist/popover.js +59 -0
  130. package/dist/popover.js.map +1 -0
  131. package/dist/primitives/index.d.ts +214 -0
  132. package/dist/primitives/index.d.ts.map +1 -0
  133. package/dist/primitives/index.js +381 -0
  134. package/dist/primitives/index.js.map +1 -0
  135. package/dist/profile.d.ts +65 -0
  136. package/dist/profile.d.ts.map +1 -0
  137. package/dist/profile.js +233 -0
  138. package/dist/profile.js.map +1 -0
  139. package/dist/quick-relations.d.ts +16 -0
  140. package/dist/quick-relations.d.ts.map +1 -0
  141. package/dist/quick-relations.js +183 -0
  142. package/dist/quick-relations.js.map +1 -0
  143. package/dist/relation-key.d.ts +44 -0
  144. package/dist/relation-key.d.ts.map +1 -0
  145. package/dist/relation-key.js +196 -0
  146. package/dist/relation-key.js.map +1 -0
  147. package/dist/seat.d.ts +137 -0
  148. package/dist/seat.d.ts.map +1 -0
  149. package/dist/seat.js +162 -0
  150. package/dist/seat.js.map +1 -0
  151. package/dist/seats.d.ts +21 -0
  152. package/dist/seats.d.ts.map +1 -0
  153. package/dist/seats.js +62 -0
  154. package/dist/seats.js.map +1 -0
  155. package/dist/seeding.d.ts +150 -0
  156. package/dist/seeding.d.ts.map +1 -0
  157. package/dist/seeding.js +538 -0
  158. package/dist/seeding.js.map +1 -0
  159. package/dist/shell.d.ts +74 -0
  160. package/dist/shell.d.ts.map +1 -0
  161. package/dist/shell.js +86 -0
  162. package/dist/shell.js.map +1 -0
  163. package/dist/theme.d.ts +50 -0
  164. package/dist/theme.d.ts.map +1 -0
  165. package/dist/theme.js +1692 -0
  166. package/dist/theme.js.map +1 -0
  167. package/dist/wordmark.d.ts +15 -0
  168. package/dist/wordmark.d.ts.map +1 -0
  169. package/dist/wordmark.js +55 -0
  170. package/dist/wordmark.js.map +1 -0
  171. package/dist/workbench/activity.d.ts +75 -0
  172. package/dist/workbench/activity.d.ts.map +1 -0
  173. package/dist/workbench/activity.js +259 -0
  174. package/dist/workbench/activity.js.map +1 -0
  175. package/dist/workbench/agent-seat.d.ts +51 -0
  176. package/dist/workbench/agent-seat.d.ts.map +1 -0
  177. package/dist/workbench/agent-seat.js +112 -0
  178. package/dist/workbench/agent-seat.js.map +1 -0
  179. package/dist/workbench/answer-args.d.ts +31 -0
  180. package/dist/workbench/answer-args.d.ts.map +1 -0
  181. package/dist/workbench/answer-args.js +257 -0
  182. package/dist/workbench/answer-args.js.map +1 -0
  183. package/dist/workbench/back-out.d.ts +71 -0
  184. package/dist/workbench/back-out.d.ts.map +1 -0
  185. package/dist/workbench/back-out.js +238 -0
  186. package/dist/workbench/back-out.js.map +1 -0
  187. package/dist/workbench/following.d.ts +7 -0
  188. package/dist/workbench/following.d.ts.map +1 -0
  189. package/dist/workbench/following.js +26 -0
  190. package/dist/workbench/following.js.map +1 -0
  191. package/dist/workbench/index.d.ts +23 -0
  192. package/dist/workbench/index.d.ts.map +1 -0
  193. package/dist/workbench/index.js +23 -0
  194. package/dist/workbench/index.js.map +1 -0
  195. package/dist/workbench/inspector.d.ts +27 -0
  196. package/dist/workbench/inspector.d.ts.map +1 -0
  197. package/dist/workbench/inspector.js +745 -0
  198. package/dist/workbench/inspector.js.map +1 -0
  199. package/dist/workbench/standing.d.ts +16 -0
  200. package/dist/workbench/standing.d.ts.map +1 -0
  201. package/dist/workbench/standing.js +102 -0
  202. package/dist/workbench/standing.js.map +1 -0
  203. package/dist/workbench/trail.d.ts +35 -0
  204. package/dist/workbench/trail.d.ts.map +1 -0
  205. package/dist/workbench/trail.js +150 -0
  206. package/dist/workbench/trail.js.map +1 -0
  207. package/package.json +62 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-seat.js","sourceRoot":"","sources":["../../src/workbench/agent-seat.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type AnySchema, type Store } from "@graview/core";
2
+ import type { Affordance, OpenParameter } from "@graview/tools";
3
+ /**
4
+ * The controls for one action's unanswered arguments, walked in order.
5
+ *
6
+ * One at a time and in sequence, because an action can need several: drafting
7
+ * work needs both what it is and how big it is, and asking for the first
8
+ * while ignoring the second would produce a deliverable with an invented
9
+ * size. Each argument draws the control its declared shape asks for — a
10
+ * picker when it names a node, a date field when it is a date, an enum's own
11
+ * options when it is a choice.
12
+ */
13
+ export declare function AnswerArgs({ affordance, onApply, onCancel, }: {
14
+ readonly affordance: Affordance;
15
+ onApply: (args: Record<string, unknown>) => void;
16
+ onCancel: () => void;
17
+ }): import("react").JSX.Element | null;
18
+ /** How many choices an ask shows at once. Past this it offers a filter. */
19
+ export declare const SHOWN = 10;
20
+ /**
21
+ * How one possible answer reads.
22
+ *
23
+ * A node reference reads as the node's own label; anything else reads as
24
+ * itself. `nameOf` would look "yes" up as a node id, fail to find one, and
25
+ * show the id — which is right for nodes and nonsense for a boolean or an
26
+ * enum value.
27
+ */
28
+ export declare function said(store: Store<AnySchema>, shape: NonNullable<OpenParameter["shape"]>, choice: string): string;
29
+ /** A node's own label where there is one, so a picker never offers raw ids. */
30
+ export declare function nameOf(store: Store<AnySchema>, id: string): string;
31
+ //# sourceMappingURL=answer-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answer-args.d.ts","sourceRoot":"","sources":["../../src/workbench/answer-args.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6C,KAAK,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,eAAe,CAAC;AAItG,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIhE;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,OAAO,EACP,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB,sCAwSA;AAID,2EAA2E;AAC3E,eAAO,MAAM,KAAK,KAAK,CAAC;AAoBxB;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAClB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,EACvB,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,EAC1C,MAAM,EAAE,MAAM,GACb,MAAM,CAIR;AAED,+EAA+E;AAC/E,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAsBlE"}
@@ -0,0 +1,257 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { humaniseField, labelOf, nounOf, tellApart } from "@graview/core";
3
+ import { relationWords } from "../relation-key.js";
4
+ import { edgeOfSelection, kindsOf } from "@graview/layout";
5
+ import { useGraview } from "@graview/react";
6
+ import { useEffect, useId, useMemo, useRef, useState } from "react";
7
+ /**
8
+ * The controls for one action's unanswered arguments, walked in order.
9
+ *
10
+ * One at a time and in sequence, because an action can need several: drafting
11
+ * work needs both what it is and how big it is, and asking for the first
12
+ * while ignoring the second would produce a deliverable with an invented
13
+ * size. Each argument draws the control its declared shape asks for — a
14
+ * picker when it names a node, a date field when it is a date, an enum's own
15
+ * options when it is a choice.
16
+ */
17
+ export function AnswerArgs({ affordance, onApply, onCancel, }) {
18
+ const { store } = useGraview();
19
+ const [answers, setAnswers] = useState({});
20
+ const [draft, setDraft] = useState("");
21
+ /** What has been chosen so far, for an argument that takes several. */
22
+ const [picked, setPicked] = useState(NOTHING_PICKED);
23
+ // Stable across the walk's steps, so the group's label never dangles.
24
+ const promptId = useId();
25
+ const asked = useRef(null);
26
+ const remaining = affordance.open.filter((parameter) => !(parameter.name in answers));
27
+ const parameter = remaining[0];
28
+ useEffect(() => setDraft(""), [parameter?.name]);
29
+ /*
30
+ * AND IT IS ON THE SCREEN.
31
+ *
32
+ * The pane scrolls inside itself, and an ask opened under a list of acts
33
+ * taller than the pane lands below its fold: on a phone the field, the
34
+ * Apply and the Skip were all off the bottom of the window, so pressing
35
+ * an act looked like pressing a button that did nothing. The ask is the
36
+ * thing that just happened, so it is what the pane shows. `nearest`
37
+ * moves the pane the least amount that works and leaves everything
38
+ * already visible where it is.
39
+ */
40
+ useEffect(() => {
41
+ // Optional: jsdom has no scrolling at all, and a pane that cannot
42
+ // scroll needs none.
43
+ asked.current?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
44
+ }, [parameter?.name]);
45
+ if (!parameter)
46
+ return null;
47
+ /*
48
+ * An OPTIONAL argument may be passed over. A skipped one is answered
49
+ * `undefined` here so the walk moves on, and left out of what is applied,
50
+ * so the mutation sees only what was actually said. Skipping every one
51
+ * of them is allowed: the mutation's own refusal then says what it
52
+ * needed, on the button, which is the honest answer to an empty change.
53
+ */
54
+ const answer = (value) => {
55
+ const next = { ...answers, [parameter.name]: value };
56
+ const outstanding = affordance.open.filter((other) => !(other.name in next));
57
+ if (outstanding.length === 0) {
58
+ onApply(Object.fromEntries(Object.entries(next).filter(([, given]) => given !== undefined)));
59
+ }
60
+ else
61
+ setAnswers(next);
62
+ };
63
+ const skip = parameter.optional ? (_jsx("button", { type: "button", onClick: () => answer(undefined), style: { fontSize: "0.8125rem" }, children: "Skip" })) : null;
64
+ const shape = parameter.shape ?? { type: "unknown" };
65
+ const choices = choicesFor(parameter, shape);
66
+ /*
67
+ * A PICKER THAT DROPS CHOICES MAKES THE ACT IMPOSSIBLE, AND SAYS NOTHING.
68
+ *
69
+ * This listed the first ten and stopped. A property with twenty-two
70
+ * practices on it offered ten of them under "Name something that helps",
71
+ * and the other twelve could not be chosen at all — not behind a control,
72
+ * not summarised as "+12", simply absent, with the panel looking exactly
73
+ * as it would if ten were all there were.
74
+ *
75
+ * Ten is still the right number to SHOW; a wall of forty chips is its own
76
+ * kind of unusable. What was missing is the way through — a filter, and a
77
+ * count of what is not on screen. Neither is a new idea here: the strip
78
+ * has had both since it was written. It just never reached the ask.
79
+ */
80
+ const [among, setAmong] = useState("");
81
+ /* Two candidates with one name are told apart by what differs (see `tellApart`). */
82
+ const apart = useMemo(() => {
83
+ const nodes = choices.map((choice) => store.graph.getNode(choice)).filter((node) => node !== undefined);
84
+ return tellApart(nodes, (kind) => store.schema.tryDefinition(kind));
85
+ }, [choices, store]);
86
+ const say = (choice) => {
87
+ const words = said(store, shape, choice);
88
+ const told = apart.get(choice);
89
+ return told ? `${words} · ${told}` : words;
90
+ };
91
+ const matching = useMemo(() => {
92
+ const term = among.trim().toLowerCase();
93
+ if (term === "")
94
+ return choices;
95
+ return choices.filter((choice) => say(choice).toLowerCase().includes(term));
96
+ // eslint-disable-next-line react-hooks/exhaustive-deps
97
+ }, [choices, among, store, shape, apart]);
98
+ /*
99
+ * AN ARGUMENT THAT TAKES A LIST IS ANSWERED WITH A LIST.
100
+ *
101
+ * "Invite somebody as coordinator and gardener" is one act with several
102
+ * roles in one argument. Answered one press at a time it would be one
103
+ * role, silently — so the presses TOGGLE and a separate one settles the
104
+ * question. Nothing else about the walk changes: it is still one
105
+ * parameter, still skippable when optional, still applied when the last
106
+ * outstanding one is answered.
107
+ */
108
+ const several = shape.type === "several";
109
+ /*
110
+ * THE ASK SAYS WHAT IT IS ASKING, IN WORDS.
111
+ *
112
+ * The text branch has said so since W-004 — the input's own label and
113
+ * placeholder are the question. The CHOICES branch said nothing at all: an
114
+ * act with one node reference to fill put two bare buttons on the strip
115
+ * ("Ana", "Bo") under no heading, so what was being asked was a guess for
116
+ * anyone looking and unsaid entirely for anyone listening. And where a
117
+ * step counter did name the parameter it used the declaration's
118
+ * IDENTIFIER — "dependsOn · 1 of 2" — which is the same bug W-004 fixed
119
+ * one element lower down.
120
+ */
121
+ /*
122
+ * A NODE PICKER IS NAMED BY WHAT IT PICKS — "Item", not "Id".
123
+ *
124
+ * The routed face has said so since it was written ("the argument's name
125
+ * is an implementation detail, and the kinds it accepts are the
126
+ * declaration's own word for the thing" — `formFields` in
127
+ * `@graview/pages`), and the strip asked with the argument's identifier.
128
+ * Every scaffolded app names its subject argument `id`, as the skills'
129
+ * own examples do, so an act offered from the FAR END of its tie — "Hand
130
+ * one back", standing on the person — put the word "Id" over a list of
131
+ * items.
132
+ */
133
+ const asking = parameter.kinds && parameter.kinds.length > 0 && !parameter.kinds.includes("*")
134
+ ? parameter.kinds.map((kind) => humaniseField(nounOf(store.schema.tryDefinition(kind), kind))).join(" or ")
135
+ : humaniseField(parameter.name);
136
+ const step = affordance.open.length > 1
137
+ ? `${asking} · ${affordance.open.length - remaining.length + 1} of ${affordance.open.length}`
138
+ : asking;
139
+ return (_jsxs("div", { ref: asked, "data-graview-asking": affordance.id, style: {
140
+ display: "grid",
141
+ /*
142
+ * THE ASK FITS THE PANE IT OPENS IN.
143
+ *
144
+ * An auto track takes the min-content width of what is in it, and a
145
+ * text input's is its own default size — so a field, an Apply and a
146
+ * Skip came to 257 inside a 236-wide rail, and the Skip was drawn
147
+ * past the pane's edge, half of it painted and none of it reachable
148
+ * without scrolling a pane that shows no scrollbar. `minmax(0, 1fr)`
149
+ * says the track may not be wider than the pane; the input already
150
+ * carries `minWidth: 0`, so it is the thing that gives.
151
+ */
152
+ gridTemplateColumns: "minmax(0, 1fr)",
153
+ gap: 4,
154
+ padding: "5px 0 2px",
155
+ }, children: [affordance.open.length > 1 || choices.length > 0 ? (_jsx("span", { id: promptId, style: { fontSize: "0.75rem", color: "var(--graview-ink-faint)" }, children: step })) : null, choices.length > SHOWN ? (_jsx("input", { type: "search", value: among, onChange: (event) => setAmong(event.target.value), placeholder: `Filter ${choices.length}…`, "aria-label": `Filter ${asking}`, "data-testid": "ask-filter", style: { font: "inherit", fontSize: "0.8125rem", minWidth: 0, padding: "3px 7px" } })) : null, choices.length > 0 ? (_jsxs("div", { role: "group", "aria-labelledby": promptId, style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: [matching.slice(0, SHOWN).map((choice) => {
156
+ const held = picked.includes(choice);
157
+ return (_jsx("button", { type: "button", "aria-label": `${asking}: ${say(choice)}`, ...(several ? { "aria-pressed": held } : {}), style: {
158
+ padding: "3px 9px",
159
+ fontSize: "0.8125rem",
160
+ ...(held
161
+ ? { borderColor: "var(--graview-accent)", color: "var(--graview-accent)" }
162
+ : {}),
163
+ }, onClick: () => several
164
+ ? setPicked((current) => current.includes(choice)
165
+ ? current.filter((other) => other !== choice)
166
+ : [...current, choice])
167
+ : answer(shape.type === "boolean" ? choice === "yes" : choice), children: say(choice) }, choice));
168
+ }), matching.length > SHOWN ? (_jsxs("span", { "data-testid": "ask-more", style: { alignSelf: "center", fontSize: "0.75rem", color: "var(--graview-ink-faint)" }, children: [matching.length - SHOWN, " more \u2014 type to narrow"] })) : null, matching.length === 0 ? (_jsxs("span", { "data-testid": "ask-none", style: { alignSelf: "center", fontSize: "0.75rem", color: "var(--graview-ink-faint)" }, children: ["None of the ", choices.length, " match that."] })) : null, several ? (_jsx("button", { type: "button", disabled: picked.length === 0, style: { fontSize: "0.8125rem" }, onClick: () => {
169
+ const chosen = picked;
170
+ setPicked(NOTHING_PICKED);
171
+ answer(chosen);
172
+ }, children: remaining.length > 1 ? "Next" : "Apply" })) : null, skip] })) : (_jsxs("form", {
173
+ // And where even a shrunk field would leave no room to type, the
174
+ // buttons drop to a line of their own rather than squeezing it to
175
+ // nothing.
176
+ style: { display: "flex", flexWrap: "wrap", gap: 4 }, onSubmit: (event) => {
177
+ event.preventDefault();
178
+ if (draft.trim().length === 0)
179
+ return;
180
+ answer(shape.type === "number" ? Number(draft) : draft);
181
+ }, children: [_jsx("input", { autoFocus: true, type: shape.type === "date" ? (shape.time ? "datetime-local" : "date") : shape.type === "number" ? "number" : "text", "aria-label": humaniseField(parameter.name), placeholder: humaniseField(parameter.name), value: draft, ...(shape.type === "number" && shape.min !== undefined ? { min: shape.min } : {}), ...(shape.type === "number" && shape.max !== undefined ? { max: shape.max } : {}), onChange: (event) => setDraft(event.target.value), onKeyDown: (event) => {
182
+ if (event.key === "Escape")
183
+ onCancel();
184
+ }, style: {
185
+ flex: 1,
186
+ minWidth: 0,
187
+ font: "inherit",
188
+ fontSize: "0.875rem",
189
+ padding: "5px 8px",
190
+ borderRadius: 7,
191
+ border: "1px solid var(--graview-edge)",
192
+ background: "var(--graview-panel)",
193
+ color: "var(--graview-ink)",
194
+ } }), _jsx("button", { type: "submit", disabled: draft.trim().length === 0, style: { fontSize: "0.8125rem" }, children: remaining.length > 1 ? "Next" : "Apply" }), skip] }))] }));
195
+ }
196
+ const NOTHING_PICKED = [];
197
+ /** How many choices an ask shows at once. Past this it offers a filter. */
198
+ export const SHOWN = 10;
199
+ function choicesFor(parameter, shape) {
200
+ if (parameter.candidates && parameter.candidates.length > 0)
201
+ return parameter.candidates;
202
+ if (shape.type === "choice")
203
+ return shape.options;
204
+ // SEVERAL OF A CHOICE is the same list of buttons; what differs is that
205
+ // pressing one adds it rather than settling the question.
206
+ if (shape.type === "several" && shape.of.type === "choice")
207
+ return shape.of.options;
208
+ // Yes or no is a choice of two, and reads better as two buttons than as
209
+ // a text field somebody has to know to type "true" into.
210
+ if (shape.type === "boolean")
211
+ return YES_NO;
212
+ return [];
213
+ }
214
+ /** The two answers to a boolean, in the words a person would use. */
215
+ const YES_NO = ["yes", "no"];
216
+ /**
217
+ * How one possible answer reads.
218
+ *
219
+ * A node reference reads as the node's own label; anything else reads as
220
+ * itself. `nameOf` would look "yes" up as a node id, fail to find one, and
221
+ * show the id — which is right for nodes and nonsense for a boolean or an
222
+ * enum value.
223
+ */
224
+ export function said(store, shape, choice) {
225
+ if (shape.type === "boolean" || shape.type === "choice")
226
+ return choice;
227
+ if (shape.type === "several" && shape.of.type === "choice")
228
+ return choice;
229
+ return nameOf(store, choice);
230
+ }
231
+ /** A node's own label where there is one, so a picker never offers raw ids. */
232
+ export function nameOf(store, id) {
233
+ /*
234
+ * A selected KIND CARD names its kind, in the plural the declaration
235
+ * already carries — "Gardeners", never "kind:gardener". In an empty app
236
+ * the kind card is the first thing anyone selects, so the raw id here was
237
+ * the first string the interface ever showed them.
238
+ */
239
+ const edge = edgeOfSelection(id);
240
+ // A relation by its words ("Where they work"), never its name ("Works at").
241
+ if (edge)
242
+ return relationWords(store.schema, edge.kind).words;
243
+ const kinds = kindsOf(id);
244
+ if (kinds.length > 0) {
245
+ return kinds
246
+ .map((kind) => {
247
+ const definition = store.schema.tryDefinition(kind);
248
+ return definition?.plural ?? `${kind}s`;
249
+ })
250
+ .join(" + ");
251
+ }
252
+ const node = store.graph.getNode(id);
253
+ if (!node)
254
+ return id;
255
+ return labelOf(store.schema.tryDefinition(node.kind), node);
256
+ }
257
+ //# sourceMappingURL=answer-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answer-args.js","sourceRoot":"","sources":["../../src/workbench/answer-args.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAA8B,MAAM,eAAe,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGpE;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,UAAU,EACV,OAAO,EACP,QAAQ,GAKT;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,EAAa,CAAC;IAC1C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAA0B,EAAE,CAAC,CAAC;IACpE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,uEAAuE;IACvE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAoB,cAAc,CAAC,CAAC;IAExE,sEAAsE;IACtE,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAE3C,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC;IACtF,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAE/B,SAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;IAEjD;;;;;;;;;;OAUG;IACH,SAAS,CAAC,GAAG,EAAE;QACb,kEAAkE;QAClE,qBAAqB;QACrB,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC3E,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;IAEtB,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAE5B;;;;;;OAMG;IACH,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;QACrD,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC;QAC7E,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC;QAC/F,CAAC;;YAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAChC,iBAAQ,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,qBAE/E,CACV,CAAC,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,SAAkB,EAAE,CAAC;IAC9D,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC7C;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,oFAAoF;IACpF,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE;QACzB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAoC,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAC1I,OAAO,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IACrB,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7C,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACxC,IAAI,IAAI,KAAK,EAAE;YAAE,OAAO,OAAO,CAAC;QAChC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5E,uDAAuD;IACzD,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1C;;;;;;;;;OASG;IACH,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;IAEzC;;;;;;;;;;;OAWG;IACH;;;;;;;;;;;OAWG;IACH,MAAM,MAAM,GACV,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC7E,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC3G,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,IAAI,GACR,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QACxB,CAAC,CAAC,GAAG,MAAM,MAAM,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE;QAC7F,CAAC,CAAC,MAAM,CAAC;IAEb,OAAO,CACL,eACE,GAAG,EAAE,KAAK,yBAGW,UAAU,CAAC,EAAE,EAClC,KAAK,EAAE;YACL,OAAO,EAAE,MAAM;YACf;;;;;;;;;;eAUG;YACH,mBAAmB,EAAE,gBAAgB;YACrC,GAAG,EAAE,CAAC;YACN,OAAO,EAAE,WAAW;SACrB,aAIA,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAClD,eAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,0BAA0B,EAAE,YAClF,IAAI,GACA,CACR,CAAC,CAAC,CAAC,IAAI,EAEP,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CACxB,gBACE,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EACjD,WAAW,EAAE,UAAU,OAAO,CAAC,MAAM,GAAG,gBAC5B,UAAU,MAAM,EAAE,iBAClB,YAAY,EACxB,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,GAClF,CACH,CAAC,CAAC,CAAC,IAAI,EAEP,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACpB,eACE,IAAI,EAAC,OAAO,qBACK,QAAQ,EACzB,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,aAEnD,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;wBACvC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;wBACrC,OAAO,CACL,iBAEE,IAAI,EAAC,QAAQ,gBAGD,GAAG,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,KACnC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAC7C,KAAK,EAAE;gCACL,OAAO,EAAE,SAAS;gCAClB,QAAQ,EAAE,WAAW;gCACrB,GAAG,CAAC,IAAI;oCACN,CAAC,CAAC,EAAE,WAAW,EAAE,uBAAuB,EAAE,KAAK,EAAE,uBAAuB,EAAE;oCAC1E,CAAC,CAAC,EAAE,CAAC;6BACR,EACD,OAAO,EAAE,GAAG,EAAE,CACZ,OAAO;gCACL,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,CACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;oCACtB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,MAAM,CAAC;oCAC7C,CAAC,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,CAAC,CACzB;gCACH,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,YAGjE,GAAG,CAAC,MAAM,CAAC,IAvBP,MAAM,CAwBJ,CACV,CAAC;oBACJ,CAAC,CAAC,EACD,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CACzB,+BACc,UAAU,EACtB,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,0BAA0B,EAAE,aAErF,QAAQ,CAAC,MAAM,GAAG,KAAK,mCACnB,CACR,CAAC,CAAC,CAAC,IAAI,EACP,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACvB,+BACc,UAAU,EACtB,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,0BAA0B,EAAE,6BAEzE,OAAO,CAAC,MAAM,oBACtB,CACR,CAAC,CAAC,CAAC,IAAI,EACP,OAAO,CAAC,CAAC,CAAC,CACT,iBACE,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAC7B,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,EAChC,OAAO,EAAE,GAAG,EAAE;4BACZ,MAAM,MAAM,GAAG,MAAM,CAAC;4BACtB,SAAS,CAAC,cAAc,CAAC,CAAC;4BAC1B,MAAM,CAAC,MAAM,CAAC,CAAC;wBACjB,CAAC,YAEA,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,GACjC,CACV,CAAC,CAAC,CAAC,IAAI,EACP,IAAI,IACD,CACP,CAAC,CAAC,CAAC,CACF;gBACE,iEAAiE;gBACjE,kEAAkE;gBAClE,WAAW;gBACX,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,EACpD,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;oBAClB,KAAK,CAAC,cAAc,EAAE,CAAC;oBACvB,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAO;oBACtC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC1D,CAAC,aAED,gBACE,SAAS,QACT,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,gBAOxG,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,EACzC,WAAW,EAAE,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,EAC1C,KAAK,EAAE,KAAK,KACR,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC9E,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAClF,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EACjD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;4BACnB,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;gCAAE,QAAQ,EAAE,CAAC;wBACzC,CAAC,EACD,KAAK,EAAE;4BACL,IAAI,EAAE,CAAC;4BACP,QAAQ,EAAE,CAAC;4BACX,IAAI,EAAE,SAAS;4BACf,QAAQ,EAAE,UAAU;4BACpB,OAAO,EAAE,SAAS;4BAClB,YAAY,EAAE,CAAC;4BACf,MAAM,EAAE,+BAA+B;4BACvC,UAAU,EAAE,sBAAsB;4BAClC,KAAK,EAAE,oBAAoB;yBAC5B,GACD,EACF,iBAAQ,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,YACxF,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,GACjC,EACR,IAAI,IACA,CACR,IACG,CACP,CAAC;AACJ,CAAC;AAED,MAAM,cAAc,GAAsB,EAAE,CAAC;AAE7C,2EAA2E;AAC3E,MAAM,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;AAExB,SAAS,UAAU,CACjB,SAAwB,EACxB,KAA0C;IAE1C,IAAI,SAAS,CAAC,UAAU,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC,UAAU,CAAC;IACzF,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC;IAClD,wEAAwE;IACxE,0DAA0D;IAC1D,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC;IACpF,wEAAwE;IACxE,yDAAyD;IACzD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IAC5C,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,qEAAqE;AACrE,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,IAAI,CAAU,CAAC;AAEtC;;;;;;;GAOG;AACH,MAAM,UAAU,IAAI,CAClB,KAAuB,EACvB,KAA0C,EAC1C,MAAc;IAEd,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IACvE,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC;IAC1E,OAAO,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,MAAM,CAAC,KAAuB,EAAE,EAAU;IACxD;;;;;OAKG;IACH,MAAM,IAAI,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;IACjC,4EAA4E;IAC5E,IAAI,IAAI;QAAE,OAAO,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;IAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK;aACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YACpD,OAAO,UAAU,EAAE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC;QAC1C,CAAC,CAAC;aACD,IAAI,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { type ViewState } from "@graview/layout";
2
+ /**
3
+ * WHERE THE KEYBOARD GOES WHEN ESCAPE TAKES AWAY WHAT IT STOOD ON.
4
+ *
5
+ * Backing out of a record removes its card; the keyboard was on the card, or
6
+ * on the title renamed in it a moment ago, and fell to `<body>`. Chromium
7
+ * then tabs on from wherever the card was, into the zoom buttons, and WebKit
8
+ * from somewhere else again. The honest place is the card that still draws
9
+ * what was left — the district holding its chip — and failing that any card
10
+ * in the scene, so the next arrow or Enter still means the picture.
11
+ *
12
+ * Asked for a while rather than once, because a card leaving on a rise may
13
+ * fade out before it is removed; and only while the keyboard is still on
14
+ * nothing, so a person who moved it in the meantime keeps where they went.
15
+ */
16
+ export declare function landTheKeyboard(stoodOn: HTMLElement, left: string | null, tries?: number): void;
17
+ /**
18
+ * Escape backs out one level: leave the full page, then the Graview, then
19
+ * drop the selection, then the raised relation, then the focus. A spatial
20
+ * interface has to have a way out that does not require finding the right
21
+ * small × in a trail.
22
+ *
23
+ * THE OVERVIEW IS ONLY A RUNG WHEN IT IS SOMETHING YOU CLIMBED TO. An app
24
+ * that OPENS from altitude — which is what `graview create` writes, and what
25
+ * every app with no in-stack default does — is already home up there, and
26
+ * leaving it would be going further IN. It is also, until this was fixed, the
27
+ * state in which Escape did nothing at all: the provider lands a focusless
28
+ * descent back on the overview (deliberately, so the key is never a void),
29
+ * which means the rung neither moved nor fell through, and every rung below
30
+ * it — the selection, the moves, the raised relation — was unreachable from
31
+ * the first screen of every scaffolded app.
32
+ */
33
+ export declare function BackOut({ home }: {
34
+ readonly home: string | null;
35
+ }): null;
36
+ /**
37
+ * The way out to the Graview, and back — one control, two directions.
38
+ *
39
+ * The framework's own name for the view of the whole thing, which is the
40
+ * right name: everything else here is a lens over part of the graph, and this
41
+ * is the graph. It is a TOGGLE and presents as one: labelled "Graview" from
42
+ * the ground (the place it takes you) and "Focus" from altitude (the way back
43
+ * down), with the pressed state saying the same thing to a screen reader.
44
+ *
45
+ * THE MARK MORPHS. The scene's own rising is a morph rather than a cut — the
46
+ * grid dissolves into the iso lattice, the districts grow out of their cards,
47
+ * all riding one registered number. The control sits beside the scene rather
48
+ * than inside it, so it carries its OWN copy of that number, transitioned on
49
+ * the same 640ms curve (`.graview-altitude-control` in the theme): the three
50
+ * kinds on their ring gather into one node inside one ring as the scene
51
+ * rises, and open back out as it lands. Where an engine cannot register the
52
+ * property the scene cuts, and so does the mark — the same mechanism, so they
53
+ * cannot disagree.
54
+ */
55
+ /**
56
+ * Where "Focus" lands from altitude when nothing is focused.
57
+ *
58
+ * An app that opens from the city has no in-stack default, and the provider
59
+ * lands a focusless descent back on the overview — which made the control a
60
+ * button that did nothing, in every such app. Descending has to go
61
+ * SOMEWHERE: into the district that is selected, or the first one declared.
62
+ */
63
+ /**
64
+ * WHERE "FOCUS" LANDS FROM ALTITUDE: the drive-in that is focused, else the
65
+ * selected kind's, else the first kind that has a drive-in — a kind with a
66
+ * picture of its own is a better place to walk up to than the first kind
67
+ * in the declaration — else the first kind at all.
68
+ */
69
+ export declare function descentTarget(view: ViewState, kinds: readonly string[], driveIns?: readonly string[]): string | null;
70
+ export declare function OverviewButton(): import("react").JSX.Element;
71
+ //# sourceMappingURL=back-out.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"back-out.d.ts","sourceRoot":"","sources":["../../src/workbench/back-out.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EAEf,MAAM,iBAAiB,CAAC;AAIzB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,SAAK,GAAG,IAAI,CAmB3F;AAGD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,QAgEjE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH;;;;;;;GAOG;AACH;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,GAAG,IAAI,CAKxH;AAED,wBAAgB,cAAc,gCAoH7B"}
@@ -0,0 +1,238 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { aggregateId, kindOfCard, withFocus, withoutMoves, withOverview, withoutSearch, kindsOfAggregate, } from "@graview/layout";
3
+ import { useGraview, useJackIn, useNavigation, useSelection } from "@graview/react";
4
+ import { useEffect } from "react";
5
+ /**
6
+ * WHERE THE KEYBOARD GOES WHEN ESCAPE TAKES AWAY WHAT IT STOOD ON.
7
+ *
8
+ * Backing out of a record removes its card; the keyboard was on the card, or
9
+ * on the title renamed in it a moment ago, and fell to `<body>`. Chromium
10
+ * then tabs on from wherever the card was, into the zoom buttons, and WebKit
11
+ * from somewhere else again. The honest place is the card that still draws
12
+ * what was left — the district holding its chip — and failing that any card
13
+ * in the scene, so the next arrow or Enter still means the picture.
14
+ *
15
+ * Asked for a while rather than once, because a card leaving on a rise may
16
+ * fade out before it is removed; and only while the keyboard is still on
17
+ * nothing, so a person who moved it in the meantime keeps where they went.
18
+ */
19
+ export function landTheKeyboard(stoodOn, left, tries = 40) {
20
+ const attempt = (remaining) => {
21
+ const active = document.activeElement;
22
+ const onNothing = active === null || active === document.body || active === stoodOn;
23
+ if (!onNothing)
24
+ return;
25
+ if (stoodOn.isConnected) {
26
+ if (remaining > 0)
27
+ setTimeout(() => attempt(remaining - 1), 25);
28
+ return;
29
+ }
30
+ const escaped = left === null ? null : left.replace(/["\\]/g, "\\$&");
31
+ const target = (escaped === null
32
+ ? null
33
+ : (document.querySelector(`[data-graview-view="${escaped}"]`) ??
34
+ document.querySelector(`[data-graview-pick="${escaped}"]`)?.closest("[data-graview-view]"))) ??
35
+ document.querySelector("[data-graview-view][tabindex]");
36
+ target?.focus({ preventScroll: true });
37
+ };
38
+ attempt(tries);
39
+ }
40
+ /**
41
+ * Escape backs out one level: leave the full page, then the Graview, then
42
+ * drop the selection, then the raised relation, then the focus. A spatial
43
+ * interface has to have a way out that does not require finding the right
44
+ * small × in a trail.
45
+ *
46
+ * THE OVERVIEW IS ONLY A RUNG WHEN IT IS SOMETHING YOU CLIMBED TO. An app
47
+ * that OPENS from altitude — which is what `graview create` writes, and what
48
+ * every app with no in-stack default does — is already home up there, and
49
+ * leaving it would be going further IN. It is also, until this was fixed, the
50
+ * state in which Escape did nothing at all: the provider lands a focusless
51
+ * descent back on the overview (deliberately, so the key is never a void),
52
+ * which means the rung neither moved nor fell through, and every rung below
53
+ * it — the selection, the moves, the raised relation — was unreachable from
54
+ * the first screen of every scaffolded app.
55
+ */
56
+ export function BackOut({ home }) {
57
+ const { view, focus, show, go } = useNavigation();
58
+ const { homeView } = useGraview();
59
+ const { selection, clear } = useSelection();
60
+ const { isJackedIn, exit } = useJackIn();
61
+ // Up here on purpose, with somewhere below to land: only then is rising
62
+ // something Escape can undo.
63
+ const overview = (view.overview ?? false) && homeView.overview !== true;
64
+ useEffect(() => {
65
+ const onKey = (event) => {
66
+ if (event.key !== "Escape")
67
+ return;
68
+ // Never steal Escape from a field someone is typing in.
69
+ const active = document.activeElement;
70
+ if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement)
71
+ return;
72
+ /*
73
+ * A POPOVER IS THE OUTERMOST RUNG, and it climbs down by itself.
74
+ *
75
+ * The activity rail, the problems list and the chat each close on
76
+ * Escape with a listener of their own — and this one ran too, so one
77
+ * press closed the rail AND dropped the selection under it (or, on
78
+ * the ground, backed out of the focus). Whatever is open over the
79
+ * scene owns the press; the ladder takes the next one.
80
+ *
81
+ * Asked in the CAPTURE phase, because the popover's own listener sits
82
+ * on the document, runs first in the bubble, and React commits its
83
+ * closing in the microtask between listeners — by the time a bubble
84
+ * listener on the window looked, the popover was already gone.
85
+ */
86
+ // A pane kept in the tree but hidden — the profile, shut — is not open over anything.
87
+ if (document.querySelector("[data-graview-overlay]:not([hidden])"))
88
+ return;
89
+ // The keyboard, if it is on the picture: the rung may take its card away.
90
+ const stoodOn = active instanceof HTMLElement && active.closest("[data-graview-view]") !== null ? active : null;
91
+ if (stoodOn)
92
+ landTheKeyboard(stoodOn, view.focusId ?? null);
93
+ /*
94
+ * Outermost first, and the full page is the outermost thing there is.
95
+ *
96
+ * It is a modal dialog covering everything, and Escape did not close it
97
+ * — the first press dropped the selection underneath it instead, which
98
+ * from inside the page looked like Escape doing nothing at all. A modal
99
+ * that cannot be dismissed from the keyboard is a trap; the only way
100
+ * out was the button.
101
+ */
102
+ if (isJackedIn)
103
+ exit();
104
+ // A search lights the whole picture, so it comes off first, and the
105
+ // emphasis goes back to what the selection reaches.
106
+ else if (view.q)
107
+ go(withoutSearch(view));
108
+ // Then the Graview: rising is the biggest change of place Escape can
109
+ // undo, and it should not also drop a selection on the way past.
110
+ else if (overview)
111
+ go(withOverview(view, false));
112
+ else if (selection.length > 0)
113
+ clear();
114
+ // A move is an adjustment of where you are, so it comes off before the
115
+ // things that decide where you are.
116
+ else if (view.pan !== undefined || Object.keys(view.pins).length > 0) {
117
+ go(withoutMoves(view));
118
+ }
119
+ else if (view.relation)
120
+ show(null);
121
+ else if (view.focusId !== home)
122
+ focus(home);
123
+ };
124
+ window.addEventListener("keydown", onKey, true);
125
+ return () => window.removeEventListener("keydown", onKey, true);
126
+ }, [view, focus, show, go, selection, clear, home, overview, isJackedIn, exit]);
127
+ return null;
128
+ }
129
+ /**
130
+ * The way out to the Graview, and back — one control, two directions.
131
+ *
132
+ * The framework's own name for the view of the whole thing, which is the
133
+ * right name: everything else here is a lens over part of the graph, and this
134
+ * is the graph. It is a TOGGLE and presents as one: labelled "Graview" from
135
+ * the ground (the place it takes you) and "Focus" from altitude (the way back
136
+ * down), with the pressed state saying the same thing to a screen reader.
137
+ *
138
+ * THE MARK MORPHS. The scene's own rising is a morph rather than a cut — the
139
+ * grid dissolves into the iso lattice, the districts grow out of their cards,
140
+ * all riding one registered number. The control sits beside the scene rather
141
+ * than inside it, so it carries its OWN copy of that number, transitioned on
142
+ * the same 640ms curve (`.graview-altitude-control` in the theme): the three
143
+ * kinds on their ring gather into one node inside one ring as the scene
144
+ * rises, and open back out as it lands. Where an engine cannot register the
145
+ * property the scene cuts, and so does the mark — the same mechanism, so they
146
+ * cannot disagree.
147
+ */
148
+ /**
149
+ * Where "Focus" lands from altitude when nothing is focused.
150
+ *
151
+ * An app that opens from the city has no in-stack default, and the provider
152
+ * lands a focusless descent back on the overview — which made the control a
153
+ * button that did nothing, in every such app. Descending has to go
154
+ * SOMEWHERE: into the district that is selected, or the first one declared.
155
+ */
156
+ /**
157
+ * WHERE "FOCUS" LANDS FROM ALTITUDE: the drive-in that is focused, else the
158
+ * selected kind's, else the first kind that has a drive-in — a kind with a
159
+ * picture of its own is a better place to walk up to than the first kind
160
+ * in the declaration — else the first kind at all.
161
+ */
162
+ export function descentTarget(view, kinds, driveIns = []) {
163
+ if (view.focusId)
164
+ return view.focusId;
165
+ const selected = (view.selection ?? []).map(kindOfCard).find((kind) => kind !== null);
166
+ const kind = selected ?? driveIns.find((one) => kinds.includes(one)) ?? kinds[0] ?? null;
167
+ return kind === null ? null : aggregateId(kind);
168
+ }
169
+ export function OverviewButton() {
170
+ const { view, go } = useNavigation();
171
+ const { store, views, hiddenKinds } = useGraview();
172
+ const overview = view.overview ?? false;
173
+ const driveIns = views.places().map((place) => place.kind).filter((kind) => !hiddenKinds.has(kind));
174
+ const target = descentTarget(view, store.schema.kinds, driveIns);
175
+ const descend = () => {
176
+ go(withFocus(withOverview(view, false), target));
177
+ };
178
+ /*
179
+ * UP AND DOWN. "Graview" and "Focus" said neither: a person meeting the
180
+ * control for the first time had to press it to learn what it did. Up is
181
+ * up; down says where you land — the place whose picture is showing, or
182
+ * the district the focus names, in its own words.
183
+ */
184
+ const landing = (() => {
185
+ if (!target)
186
+ return null;
187
+ const kind = kindsOfAggregate(target)[0];
188
+ // The showing that is showing, else the kind's first place.
189
+ const showing = view.within?.["view"];
190
+ const place = (showing ? views.places().find((one) => one.as === showing) : undefined) ??
191
+ (kind ? views.places().find((one) => one.kind === kind) : undefined);
192
+ if (place)
193
+ return place.title;
194
+ if (kind)
195
+ return store.schema.tryDefinition(kind)?.plural ?? kind;
196
+ return store.graph.getNode(target)?.label ?? null;
197
+ })();
198
+ const label = overview ? (landing ? `Down to ${landing}` : "Down") : "Up";
199
+ return (_jsxs("button", { type: "button", "data-testid": "overview", className: "graview-altitude-control", "aria-pressed": overview, "aria-label": label, title: overview ? `${label} — back down into the view` : "Up — the whole thing, from outside",
200
+ // A view state, so it is a URL, the back button works, and the cards
201
+ // already on screen fly out into the ring rather than being replaced.
202
+ onClick: () => (overview ? descend() : go(withOverview(view, true))),
203
+ /*
204
+ * SCENE FURNITURE, in the scene's corner — the way a map carries its
205
+ * own altitude control.
206
+ *
207
+ * It has lived in two wrong places: floating over the scene as a
208
+ * labelled pill ("awkwardly slammed on top", twice), and then in the
209
+ * command bar, where it spent prime chrome on a control that is about
210
+ * the CANVAS, not the app. The bar is for what the app is; rising and
211
+ * descending is something you do to the picture, so the control sits
212
+ * on the picture — quiet, in the one corner every state leaves empty.
213
+ */
214
+ style: {
215
+ position: "absolute",
216
+ top: 14,
217
+ right: 14,
218
+ zIndex: 5,
219
+ display: "inline-flex",
220
+ alignItems: "center",
221
+ justifyContent: "center",
222
+ gap: 7,
223
+ height: 38,
224
+ padding: "0 13px 0 11px",
225
+ borderRadius: 999,
226
+ fontSize: "0.875rem",
227
+ whiteSpace: "nowrap",
228
+ background: "var(--graview-float)",
229
+ boxShadow: "var(--graview-lift-low)",
230
+ // The number the mark rides. Inline, like the ground's own, so the
231
+ // theme's transition on the class carries it between the two.
232
+ ["--graview-altitude"]: overview ? 1 : 0,
233
+ ...(overview
234
+ ? { borderColor: "var(--graview-accent)", color: "var(--graview-accent)" }
235
+ : {}),
236
+ }, children: [_jsxs("svg", { className: "graview-altitude-mark", width: "16", height: "16", viewBox: "0 0 12 12", "aria-hidden": "true", children: [_jsx("ellipse", { className: "graview-altitude-mark-ring", cx: "6", cy: "6.6", rx: "5", ry: "2.6", fill: "none", stroke: "currentColor", strokeWidth: "0.9" }), _jsx("circle", { className: "graview-altitude-mark-apex", cx: "6", cy: "4", r: "1.5", fill: "currentColor" }), _jsx("circle", { className: "graview-altitude-mark-wing", "data-side": "left", cx: "1.6", cy: "7.4", r: "1.2", fill: "currentColor" }), _jsx("circle", { className: "graview-altitude-mark-wing", "data-side": "right", cx: "10.4", cy: "7.4", r: "1.2", fill: "currentColor" })] }), _jsx("span", { className: "graview-altitude-label", children: label })] }));
237
+ }
238
+ //# sourceMappingURL=back-out.js.map