@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,233 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { humaniseField, labelOf, nameOfAuthor } from "@graview/core";
3
+ import { useGraview } from "@graview/react";
4
+ import { LadderSetting } from "./ladder.js";
5
+ import { useEffect, useLayoutEffect, useRef, useState } from "react";
6
+ import { Seats } from "./seats.js";
7
+ import { closeToTrigger, keepInside } from "./popover.js";
8
+ /**
9
+ * WHO YOU ARE AT THIS KEYBOARD, AND WHAT YOU SET FOR YOURSELF.
10
+ *
11
+ * Every app needs one place that answers "who am I signed in as" and holds
12
+ * the handful of things that are the READER's rather than the
13
+ * installation's. Text size is the case that forced it: the framework sizes
14
+ * every surface in `rem` precisely so that one number on the root element
15
+ * resizes the whole app — and until now nothing anywhere offered that
16
+ * number, so the property existed and nobody could use it.
17
+ *
18
+ * What the pane holds, in the order a person looks for it:
19
+ *
20
+ * who you are — the seat's own name and role, and where the installation
21
+ * is declared, a way into your own record, which the self
22
+ * grant already makes yours to edit and nobody else's;
23
+ * which seat — the switcher, where the app offers a choice, because
24
+ * "who am I" and "be somebody else" belong together;
25
+ * your settings — drawn from the DECLARATION. Nothing here knows what
26
+ * "text size" means; it renders what the app declared and
27
+ * the provider has already carried the answer to the root.
28
+ * the scheme — light or dark, which was on the bar alone.
29
+ * keeping it — and, for the seat that keeps this installation ONLY, the
30
+ * ways into it: its own districts, and its declaration.
31
+ *
32
+ * That last block was two pills on the bar, beside the places — which put
33
+ * administration in the same row as "the week" and "the month", where every
34
+ * reader saw the app's shape before they saw their own work. They are the
35
+ * keeper's, they are rare, and they belong behind the same door as "who am
36
+ * I". A member never sees the block at all, because both controls draw
37
+ * nothing for a seat that may not administer and the block hides itself
38
+ * when it holds nothing.
39
+ *
40
+ * What is NOT administration stays what it was: a member sees their own
41
+ * name, their own record and their own text size, and never a person who is
42
+ * not them.
43
+ */
44
+ export function Profile({ scheme, onScheme,
45
+ /** Where a person's own record lives on the routed face, if there is one. */
46
+ profileHref,
47
+ /**
48
+ * The ways into the app itself, for the seat that keeps it: showing the
49
+ * installation's own districts, and opening its declaration in the studio.
50
+ *
51
+ * A slot rather than a fixed pair, because the studio lives in a package
52
+ * this one must not depend on — the same reason the shell takes it as a
53
+ * node. Both of them render nothing for a seat that may not administer,
54
+ * and the block they sit in hides itself when they do.
55
+ */
56
+ keeping, compact = false, }) {
57
+ const { store, principal, seats, settings, settingValues, chooseSetting, sharing, hostAnswers } = useGraview();
58
+ const [open, setOpen] = useState(false);
59
+ const anchor = useRef(null);
60
+ useEffect(() => {
61
+ if (!open)
62
+ return;
63
+ const away = (event) => {
64
+ const target = event.target;
65
+ if (anchor.current?.contains(target))
66
+ return;
67
+ /*
68
+ * A CONTROL IN HERE MAY OPEN SOMETHING BIGGER THAN HERE.
69
+ *
70
+ * The studio is a full-screen dialog portalled to the body, and its
71
+ * button lives in this pane. Treating the first press inside the
72
+ * studio as "away" closed the pane, which unmounted the button, which
73
+ * took the portal with it — the studio opened and vanished on the
74
+ * next click. Anything that is itself a dialog or an overlay is not
75
+ * away from the thing that opened it.
76
+ */
77
+ if (target instanceof Element && target.closest('[role="dialog"], [data-graview-overlay]'))
78
+ return;
79
+ setOpen(false);
80
+ };
81
+ const key = (event) => {
82
+ if (event.key === "Escape")
83
+ closeToTrigger(anchor.current, () => setOpen(false));
84
+ };
85
+ document.addEventListener("mousedown", away);
86
+ document.addEventListener("keydown", key);
87
+ return () => {
88
+ document.removeEventListener("mousedown", away);
89
+ document.removeEventListener("keydown", key);
90
+ };
91
+ }, [open]);
92
+ /*
93
+ * The person's own record, WHERE THERE IS ONE.
94
+ *
95
+ * A principal's id is its user node's id — that is what a self grant
96
+ * compares — so "who is signed in" is a graph lookup and not a second
97
+ * identity system. An app with no installation has no such node, and the
98
+ * pane says who you are from the principal alone rather than inventing a
99
+ * name.
100
+ */
101
+ // Inside an embed the pane stays inside the embed's box (see `keepInside`).
102
+ const pane = useRef(null);
103
+ useLayoutEffect(() => {
104
+ if (open)
105
+ keepInside(pane.current);
106
+ }, [open]);
107
+ const me = principal.id === undefined ? undefined : store.graph.getNode(principal.id);
108
+ const name = me === undefined
109
+ ? principal.id === undefined
110
+ ? "Nobody in particular"
111
+ : nameOfAuthor(principal, { graph: store.graph, schema: store.schema, seats })
112
+ : labelOf(store.schema.tryDefinition(me.kind), me);
113
+ const roles = principal.roles ?? [];
114
+ return (_jsxs("div", { ref: anchor, style: { position: "relative" }, children: [_jsxs("button", { type: "button", "data-testid": "profile-button", "aria-expanded": open, onClick: () => setOpen((value) => !value), title: "Who you are signed in as, and your own settings", style: {
115
+ display: "inline-flex",
116
+ alignItems: "center",
117
+ gap: 7,
118
+ padding: "4px 11px",
119
+ borderRadius: 999,
120
+ fontSize: "0.875rem",
121
+ whiteSpace: "nowrap",
122
+ /* In em, so the room for a name grows with the name. At 220px a
123
+ reader on Largest got "Nobody in p…" — the setting made the
124
+ words bigger and the box they live in stayed exactly where it
125
+ was, which is the clipping the setting exists to prevent. */
126
+ maxWidth: "14em",
127
+ }, children: [_jsx("span", { "aria-hidden": "true", "data-testid": "profile-mark", style: {
128
+ display: "inline-flex",
129
+ alignItems: "center",
130
+ justifyContent: "center",
131
+ /* The mark is a letter in a circle: sized in em it stays a
132
+ circle around the letter at every text size, where 18px at
133
+ 2rem was a letter standing outside its own badge. */
134
+ width: "1.35em",
135
+ height: "1.35em",
136
+ borderRadius: 999,
137
+ fontSize: "0.75rem",
138
+ background: "var(--graview-panel-muted)",
139
+ color: "var(--graview-ink-muted)",
140
+ }, children: initial(name) }), _jsx("span", { style: compact ? { position: "absolute", width: 1, height: 1, overflow: "hidden", clipPath: "inset(50%)" } : { overflow: "hidden", textOverflow: "ellipsis" }, children: name }), _jsx("span", { "aria-hidden": "true", "data-testid": "profile-gear", style: { fontSize: "0.75rem", color: "var(--graview-ink-faint)" }, children: "\u2699" })] }), _jsxs("aside", { ref: (element) => {
141
+ pane.current = element;
142
+ }, "aria-label": "Profile", "data-testid": "profile", "data-graview-offstage": "", "data-graview-overlay": "", hidden: !open, style: {
143
+ position: "absolute",
144
+ top: "calc(100% + 6px)",
145
+ right: 0,
146
+ zIndex: 20,
147
+ width: 280,
148
+ maxWidth: "calc(100vw - 32px)",
149
+ maxHeight: "min(62cqh, 520px)",
150
+ overflowY: "auto",
151
+ // Not `overflow: auto`: nothing in here may run off the side.
152
+ // A setting's own sentence was clipped mid-word against the
153
+ // pane's edge, which is the one thing a text-size control must
154
+ // not do.
155
+ overflowX: "hidden",
156
+ /*
157
+ * `hidden` alone is not enough when the element sets its own
158
+ * display: an inline `display: grid` beats the browser's
159
+ * `[hidden] { display: none }`, so the closed pane stayed on
160
+ * top of the bar and swallowed every press aimed at it.
161
+ */
162
+ display: open ? "grid" : "none",
163
+ gap: 12,
164
+ padding: 12,
165
+ borderRadius: 10,
166
+ border: "1px solid var(--graview-edge)",
167
+ background: "var(--graview-float)",
168
+ boxShadow: "var(--graview-lift-high)",
169
+ }, children: [_jsxs("div", { style: { display: "grid", gap: 3 }, children: [_jsx("span", { style: eyebrow, children: "Signed in as" }), _jsx("strong", { style: { fontSize: "1rem", fontWeight: 550 }, children: name }), _jsx("span", { style: { fontSize: "0.8125rem", color: "var(--graview-ink-muted)" }, children: roles.length > 0
170
+ ? // A role in words — "Sales manager", never "sales-manager".
171
+ roles.map((role) => humaniseField(role)).join(", ")
172
+ : me === undefined
173
+ ? "This app has no sign-in; everything here is yours."
174
+ : "No role in particular" }), me !== undefined && profileHref !== undefined ? (_jsx("a", { href: profileHref(me.id), "data-testid": "profile-record", style: {
175
+ /*
176
+ * A full fingertip, like every other control the audit
177
+ * counts. It was nineteen pixels tall — and nothing had
178
+ * ever measured it, because until the keeper's own ways
179
+ * in moved here no audited screen opened this pane.
180
+ */
181
+ display: "inline-flex",
182
+ alignItems: "center",
183
+ minHeight: 24,
184
+ justifySelf: "start",
185
+ fontSize: "0.875rem",
186
+ color: "var(--graview-accent)",
187
+ }, children: "Your record \u2197" })) : null, sharing ? (
188
+ /* How the others here see you — the name on the figure that stands where you are. */
189
+ _jsxs("span", { "data-testid": "profile-seen-as", style: { fontSize: "0.8125rem", color: "var(--graview-ink-muted)" }, children: ["Seen by others as ", sharing.name] })) : null] }), _jsxs("div", { className: "graview-profile-keeping", "data-testid": "profile-keeping", style: ruled, children: [_jsx("span", { style: eyebrow, children: "Keeping this app" }), keeping] }), seats.length > 1 ? (_jsxs("div", { style: { display: "grid", gap: 6, ...ruled }, children: [_jsx("span", { style: eyebrow, children: "Sit as somebody else" }), _jsx(Seats, {})] })) : null, hostAnswers ? null : (_jsx("div", { style: { display: "grid", gap: 6, ...ruled }, children: _jsx(LadderSetting, {}) })), settings.length > 0 ? (_jsx("div", { style: { display: "grid", gap: 10, ...ruled }, children: settings.map((setting) => (_jsxs("fieldset", { "data-testid": `setting-${setting.name}`, style: { border: 0, margin: 0, padding: 0, display: "grid", gap: 5 }, children: [_jsx("legend", { style: { ...eyebrow, padding: 0 }, children: setting.title }), setting.description ? (_jsx("span", { style: { fontSize: "0.8125rem", color: "var(--graview-ink-muted)" }, children: setting.description })) : null, _jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: setting.options.map((option) => {
190
+ const chosen = (settingValues[setting.name] ?? setting.initial) === option.value;
191
+ return (_jsx("button", { type: "button", "aria-pressed": chosen, "data-testid": `setting-${setting.name}-${option.value}`, onClick: () => chooseSetting(setting.name, option.value), style: {
192
+ /*
193
+ * 24px tall, like every other control the audit
194
+ * counts — a setting for people who find the
195
+ * text small must not itself be a small target.
196
+ */
197
+ minHeight: 24,
198
+ padding: "3px 10px",
199
+ borderRadius: 999,
200
+ fontSize: "0.875rem",
201
+ borderWidth: 1,
202
+ borderStyle: "solid",
203
+ borderColor: chosen ? "var(--graview-accent)" : "var(--graview-edge)",
204
+ color: chosen ? "var(--graview-accent)" : "var(--graview-ink-muted)",
205
+ background: chosen ? "var(--graview-panel)" : "transparent",
206
+ }, children: option.label }, option.value));
207
+ }) })] }, setting.name))) })) : null, scheme !== undefined && onScheme !== undefined ? (_jsxs("div", { style: { display: "grid", gap: 5, ...ruled }, children: [_jsx("span", { style: eyebrow, children: "Scheme" }), _jsx("div", { style: { display: "flex", gap: 4 }, children: ["light", "dark"].map((candidate) => (_jsx("button", { type: "button", "aria-pressed": scheme === candidate, "data-testid": `profile-scheme-${candidate}`, onClick: () => onScheme(candidate), style: {
208
+ minHeight: 24,
209
+ padding: "3px 10px",
210
+ borderRadius: 999,
211
+ fontSize: "0.875rem",
212
+ borderWidth: 1,
213
+ borderStyle: "solid",
214
+ borderColor: scheme === candidate ? "var(--graview-accent)" : "var(--graview-edge)",
215
+ color: scheme === candidate ? "var(--graview-accent)" : "var(--graview-ink-muted)",
216
+ background: scheme === candidate ? "var(--graview-panel)" : "transparent",
217
+ }, children: candidate === "light" ? "☀ Light" : "☾ Dark" }, candidate))) })] })) : null] })] }));
218
+ }
219
+ const eyebrow = {
220
+ fontSize: "0.75rem",
221
+ letterSpacing: "0.14em",
222
+ textTransform: "uppercase",
223
+ color: "var(--graview-ink-faint)",
224
+ };
225
+ const ruled = {
226
+ paddingTop: 10,
227
+ borderTop: "1px solid var(--graview-edge)",
228
+ };
229
+ /** One letter for the mark, from a name rather than from an id. */
230
+ function initial(name) {
231
+ return (name.trim()[0] ?? "?").toUpperCase();
232
+ }
233
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAkB,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AACrF,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,OAAO,CAAsB,EAC3C,MAAM,EACN,QAAQ;AACR,6EAA6E;AAC7E,WAAW;AACX;;;;;;;;GAQG;AACH,OAAO,EACP,OAAO,GAAG,KAAK,GAchB;IACC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,UAAU,EAAK,CAAC;IAClH,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,CAAwB,IAAI,CAAC,CAAC;IAEnD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,IAAI,GAAG,CAAC,KAAiB,EAAE,EAAE;YACjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB,CAAC;YAC3C,IAAI,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC;gBAAE,OAAO;YAC7C;;;;;;;;;eASG;YACH,IAAI,MAAM,YAAY,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,yCAAyC,CAAC;gBAAE,OAAO;YACnG,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC;QACF,MAAM,GAAG,GAAG,CAAC,KAAoB,EAAE,EAAE;YACnC,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;gBAAE,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACnF,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC7C,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC1C,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAChD,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC/C,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX;;;;;;;;OAQG;IACH,4EAA4E;IAC5E,MAAM,IAAI,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IAC9C,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,IAAI;YAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IACX,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACtF,MAAM,IAAI,GACR,EAAE,KAAK,SAAS;QACd,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,SAAS;YAC1B,CAAC,CAAC,sBAAsB;YACxB,CAAC,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAc,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;QACzF,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,IAAc,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;IAEpC,OAAO,CACL,eAAK,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,aAC/C,kBACE,IAAI,EAAC,QAAQ,iBACD,gBAAgB,mBACb,IAAI,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EACzC,KAAK,EAAC,iDAAiD,EACvD,KAAK,EAAE;oBACL,OAAO,EAAE,aAAa;oBACtB,UAAU,EAAE,QAAQ;oBACpB,GAAG,EAAE,CAAC;oBACN,OAAO,EAAE,UAAU;oBACnB,YAAY,EAAE,GAAG;oBACjB,QAAQ,EAAE,UAAU;oBACpB,UAAU,EAAE,QAAQ;oBACpB;;;mFAG+D;oBAC/D,QAAQ,EAAE,MAAM;iBACjB,aAED,8BACc,MAAM,iBACN,cAAc,EAC1B,KAAK,EAAE;4BACL,OAAO,EAAE,aAAa;4BACtB,UAAU,EAAE,QAAQ;4BACpB,cAAc,EAAE,QAAQ;4BACxB;;mFAEuD;4BACvD,KAAK,EAAE,QAAQ;4BACf,MAAM,EAAE,QAAQ;4BAChB,YAAY,EAAE,GAAG;4BACjB,QAAQ,EAAE,SAAS;4BACnB,UAAU,EAAE,4BAA4B;4BACxC,KAAK,EAAE,0BAA0B;yBAClC,YAEA,OAAO,CAAC,IAAI,CAAC,GACT,EACP,eAAM,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,YAAG,IAAI,GAAQ,EAUlL,8BAAkB,MAAM,iBAAa,cAAc,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,0BAA0B,EAAE,uBAE9G,IACA,EAYT,iBACI,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE;oBACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;gBACzB,CAAC,gBACU,SAAS,iBACR,SAAS,2BACC,EAAE,0BACH,EAAE,EACvB,MAAM,EAAE,CAAC,IAAI,EACb,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;oBACpB,GAAG,EAAE,kBAAkB;oBACvB,KAAK,EAAE,CAAC;oBACR,MAAM,EAAE,EAAE;oBACV,KAAK,EAAE,GAAG;oBACV,QAAQ,EAAE,oBAAoB;oBAC9B,SAAS,EAAE,mBAAmB;oBAC9B,SAAS,EAAE,MAAM;oBACjB,8DAA8D;oBAC9D,4DAA4D;oBAC5D,+DAA+D;oBAC/D,UAAU;oBACV,SAAS,EAAE,QAAQ;oBACnB;;;;;uBAKG;oBACH,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;oBAC/B,GAAG,EAAE,EAAE;oBACP,OAAO,EAAE,EAAE;oBACX,YAAY,EAAE,EAAE;oBAChB,MAAM,EAAE,+BAA+B;oBACvC,UAAU,EAAE,sBAAsB;oBAClC,SAAS,EAAE,0BAA0B;iBACtC,aAED,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,aACrC,eAAM,KAAK,EAAE,OAAO,6BAAqB,EACzC,iBAAQ,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,YAAG,IAAI,GAAU,EACrE,eAAM,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,0BAA0B,EAAE,YAItE,KAAK,CAAC,MAAM,GAAG,CAAC;oCACf,CAAC,CAAC,4DAA4D;wCAC5D,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;oCACrD,CAAC,CAAC,EAAE,KAAK,SAAS;wCAChB,CAAC,CAAC,oDAAoD;wCACtD,CAAC,CAAC,uBAAuB,GACxB,EACN,EAAE,KAAK,SAAS,IAAI,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAC/C,YACE,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC,iBACZ,gBAAgB,EAC5B,KAAK,EAAE;oCACL;;;;;uCAKG;oCACH,OAAO,EAAE,aAAa;oCACtB,UAAU,EAAE,QAAQ;oCACpB,SAAS,EAAE,EAAE;oCACb,WAAW,EAAE,OAAO;oCACpB,QAAQ,EAAE,UAAU;oCACpB,KAAK,EAAE,uBAAuB;iCAC/B,mCAGC,CACL,CAAC,CAAC,CAAC,IAAI,EACP,OAAO,CAAC,CAAC,CAAC;4BACT,qFAAqF;4BACrF,+BAAkB,iBAAiB,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,0BAA0B,EAAE,mCAClF,OAAO,CAAC,IAAI,IAC1B,CACR,CAAC,CAAC,CAAC,IAAI,IACJ,EAgBN,eAAK,SAAS,EAAC,yBAAyB,iBAAa,iBAAiB,EAAC,KAAK,EAAE,KAAK,aACjF,eAAM,KAAK,EAAE,OAAO,iCAAyB,EAC5C,OAAO,IACJ,EAEL,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAClB,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,aAC/C,eAAM,KAAK,EAAE,OAAO,qCAA6B,EACjD,KAAC,KAAK,KAAM,IACR,CACP,CAAC,CAAC,CAAC,IAAI,EAGP,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACpB,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,YAC/C,KAAC,aAAa,KAAG,GACb,CACP,EAEA,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACrB,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE,YAC/C,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACzB,mCAEe,WAAW,OAAO,CAAC,IAAI,EAAE,EACtC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,aAEpE,iBAAQ,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,YAAG,OAAO,CAAC,KAAK,GAAU,EAClE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CACrB,eAAM,KAAK,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,0BAA0B,EAAE,YACtE,OAAO,CAAC,WAAW,GACf,CACR,CAAC,CAAC,CAAC,IAAI,EACR,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,YACtD,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;wCAC9B,MAAM,MAAM,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC;wCACjF,OAAO,CACL,iBAEE,IAAI,EAAC,QAAQ,kBACC,MAAM,iBACP,WAAW,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,EACtD,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,EACxD,KAAK,EAAE;gDACL;;;;mDAIG;gDACH,SAAS,EAAE,EAAE;gDACb,OAAO,EAAE,UAAU;gDACnB,YAAY,EAAE,GAAG;gDACjB,QAAQ,EAAE,UAAU;gDACpB,WAAW,EAAE,CAAC;gDACd,WAAW,EAAE,OAAO;gDACpB,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,qBAAqB;gDACrE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,0BAA0B;gDACpE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,aAAa;6CAC5D,YAEA,MAAM,CAAC,KAAK,IAtBR,MAAM,CAAC,KAAK,CAuBV,CACV,CAAC;oCACJ,CAAC,CAAC,GACE,KAzCD,OAAO,CAAC,IAAI,CA0CR,CACZ,CAAC,GACE,CACP,CAAC,CAAC,CAAC,IAAI,EAEP,MAAM,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,CAClD,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,aAC/C,eAAM,KAAK,EAAE,OAAO,uBAAe,EACnC,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,YACnC,CAAC,OAAO,EAAE,MAAM,CAAW,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAC/C,iBAEE,IAAI,EAAC,QAAQ,kBACC,MAAM,KAAK,SAAS,iBACrB,kBAAkB,SAAS,EAAE,EAC1C,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAClC,KAAK,EAAE;wCACL,SAAS,EAAE,EAAE;wCACb,OAAO,EAAE,UAAU;wCACnB,YAAY,EAAE,GAAG;wCACjB,QAAQ,EAAE,UAAU;wCACpB,WAAW,EAAE,CAAC;wCACd,WAAW,EAAE,OAAO;wCACpB,WAAW,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,qBAAqB;wCACnF,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,0BAA0B;wCAClF,UAAU,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,aAAa;qCAC1E,YAEA,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,IAjBxC,SAAS,CAkBP,CACV,CAAC,GACE,IACF,CACL,CAAC,CAAC,CAAC,IAAI,IAEF,IACN,CACP,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,GAAG;IACd,QAAQ,EAAE,SAAS;IACnB,aAAa,EAAE,QAAQ;IACvB,aAAa,EAAE,WAAoB;IACnC,KAAK,EAAE,0BAA0B;CAClC,CAAC;AAEF,MAAM,KAAK,GAAG;IACZ,UAAU,EAAE,EAAE;IACd,SAAS,EAAE,+BAA+B;CAC3C,CAAC;AAEF,mEAAmE;AACnE,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { type AnySchema } from "@graview/core";
2
+ /**
3
+ * HANDLES THAT CAN BE TOLD APART.
4
+ *
5
+ * Cut at eighteen characters, a customer's three test drives — "Wei Haddad
6
+ * in the 2017 Jeep…", "…2027 Chevrolet…", "…2027 Honda…" — were three
7
+ * chips reading "Wei Haddad in the…", and three buttons with one name. Where
8
+ * two cut handles would read the same, the words they share are what gets
9
+ * cut: "…2017 Jeep Wrangl…". A label that fits, or whose cut is already
10
+ * its own, is left as it was.
11
+ */
12
+ export declare function handles(labels: readonly string[], most?: number): string[];
13
+ export declare function QuickRelations<S extends AnySchema>({ inside }?: {
14
+ readonly inside?: boolean;
15
+ }): import("react").JSX.Element | null;
16
+ //# sourceMappingURL=quick-relations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quick-relations.d.ts","sourceRoot":"","sources":["../src/quick-relations.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAsCxD;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,SAAa,GAAG,MAAM,EAAE,CAmB9E;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,EAAE,EAAE,MAAc,EAAE,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,sCA0JzG"}
@@ -0,0 +1,183 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { labelOf } from "@graview/core";
3
+ import { kindsOfAggregate } from "@graview/layout";
4
+ import { useGraph, useGraview, useSelection } from "@graview/react";
5
+ import { useMemo } from "react";
6
+ import { hueFor } from "./default-views.js";
7
+ /**
8
+ * THE PEOPLE BEHIND A VIEW, one press away.
9
+ *
10
+ * "Which of this week is Parent1's?" used to cost two deliberate gestures —
11
+ * raise People, then pick the person — for a one-glance question. The
12
+ * answer machinery has always existed (selecting a node lights everything
13
+ * it implicates); this is the fast way in: the graph already knows which
14
+ * few nodes touch the focused group most, so they stand as chips beside
15
+ * the scene. One click selects and the emphasis path does the rest; the
16
+ * pane then owns the rail, and Escape (or its ×) brings the chips back.
17
+ *
18
+ * Everything is derived and capped: kinds one edge from the focus whose
19
+ * membership is SMALL — a household's five people, not a season's forty
20
+ * sessions — ranked by how much of the visible view each one touches. A
21
+ * crowd never becomes a toolbar; it already has a district.
22
+ */
23
+ /*
24
+ * Five, so the panel always finishes above the inspector's docked top edge
25
+ * — the two share the left rail as a stack, never a collision. A kind with
26
+ * more members has a district for exactly this.
27
+ */
28
+ const MOST_MEMBERS = 5;
29
+ /*
30
+ * ONE kind, not a stack of them. Two labelled rows of wrapping chips read
31
+ * as debris; the single kind that touches the view most — the people of a
32
+ * week, the players of a board — is the quick-select that earns the
33
+ * corner. Everything else already has a district and a legend.
34
+ */
35
+ const MOST_KINDS = 1;
36
+ /** A chip is a handle, not a sentence: long names cut with their full text on hover. */
37
+ const MOST_LABEL = 18;
38
+ /**
39
+ * HANDLES THAT CAN BE TOLD APART.
40
+ *
41
+ * Cut at eighteen characters, a customer's three test drives — "Wei Haddad
42
+ * in the 2017 Jeep…", "…2027 Chevrolet…", "…2027 Honda…" — were three
43
+ * chips reading "Wei Haddad in the…", and three buttons with one name. Where
44
+ * two cut handles would read the same, the words they share are what gets
45
+ * cut: "…2017 Jeep Wrangl…". A label that fits, or whose cut is already
46
+ * its own, is left as it was.
47
+ */
48
+ export function handles(labels, most = MOST_LABEL) {
49
+ const cut = (text) => (text.length > most ? `${text.slice(0, most - 1).trimEnd()}…` : text);
50
+ const first = labels.map(cut);
51
+ return labels.map((label, index) => {
52
+ const mine = first[index];
53
+ const twins = labels.filter((_, other) => first[other] === mine);
54
+ if (twins.length < 2)
55
+ return mine;
56
+ // The words every twin starts with, to a word boundary.
57
+ let shared = twins.reduce((prefix, other) => {
58
+ let at = 0;
59
+ while (at < prefix.length && prefix[at] === other[at])
60
+ at += 1;
61
+ return prefix.slice(0, at);
62
+ }, label);
63
+ const space = shared.lastIndexOf(" ");
64
+ shared = space > 0 ? shared.slice(0, space + 1) : "";
65
+ const rest = label.slice(shared.length);
66
+ if (shared.length === 0 || rest.length === 0)
67
+ return mine;
68
+ return `…${rest.length > most - 1 ? `${rest.slice(0, most - 2).trimEnd()}…` : rest}`;
69
+ });
70
+ }
71
+ export function QuickRelations({ inside = false } = {}) {
72
+ const { store, view, brand, menuAt } = useGraview();
73
+ const { set } = useSelection();
74
+ const { selection } = useSelection();
75
+ const nodes = useGraph();
76
+ const rows = useMemo(() => {
77
+ if (!view.focusId)
78
+ return [];
79
+ const focusKinds = kindsOfAggregate(view.focusId);
80
+ const inFocus = new Set(focusKinds.length > 0
81
+ ? nodes.filter((node) => focusKinds.includes(node.kind)).map((node) => node.id)
82
+ : [view.focusId]);
83
+ if (inFocus.size === 0)
84
+ return [];
85
+ // One pass: everything one edge from the focus group, by kind, with how
86
+ // many of the visible things each candidate touches.
87
+ const byKind = new Map();
88
+ for (const edge of store.graph.allEdges()) {
89
+ const outward = inFocus.has(edge.from) ? edge.to : inFocus.has(edge.to) ? edge.from : null;
90
+ if (!outward || inFocus.has(outward))
91
+ continue;
92
+ const node = store.graph.getNode(outward);
93
+ if (!node)
94
+ continue;
95
+ if (focusKinds.includes(node.kind))
96
+ continue;
97
+ const members = byKind.get(node.kind) ?? new Map();
98
+ const entry = members.get(node.id) ?? { id: node.id, kind: node.kind, touches: 0 };
99
+ entry.touches += 1;
100
+ members.set(node.id, entry);
101
+ byKind.set(node.kind, members);
102
+ }
103
+ return [...byKind.entries()]
104
+ .filter(([, members]) => members.size > 0 && members.size <= MOST_MEMBERS)
105
+ .map(([kind, members]) => ({
106
+ kind,
107
+ plural: store.schema.tryDefinition(kind)?.plural ?? `${kind}s`,
108
+ reach: [...members.values()].reduce((sum, entry) => sum + entry.touches, 0),
109
+ members: [...members.values()].sort((a, b) => b.touches - a.touches || a.id.localeCompare(b.id)),
110
+ }))
111
+ .sort((a, b) => b.reach - a.reach)
112
+ .slice(0, MOST_KINDS);
113
+ }, [store, nodes, view.focusId]);
114
+ /*
115
+ * THE RAIL HAS ONE TENANT AT A TIME. At altitude the legend owns the
116
+ * corner; in the stack these chips do — until something is selected, at
117
+ * which point the inspector takes the whole rail and the chips stand
118
+ * aside (they are the way IN; the pane is where you already are, and its
119
+ * × or Escape is the way back out, after which the chips return). A
120
+ * pointer menu quiets the corner the same way.
121
+ */
122
+ if (view.overview || rows.length === 0 || menuAt !== null || selection.length > 0) {
123
+ return null;
124
+ }
125
+ return (_jsx("aside", { "aria-label": "Quick select", "data-testid": "quick-relations", style: inside
126
+ ? { display: "grid", gap: 5 }
127
+ : {
128
+ /*
129
+ * The SAME dress the legend wears at altitude: one corner, one
130
+ * visual language at both heights. Loose chips floating on the
131
+ * ground read as something spilled; a panel reads as something
132
+ * placed.
133
+ */
134
+ position: "absolute",
135
+ left: 16,
136
+ top: 14,
137
+ zIndex: 5,
138
+ display: "grid",
139
+ gap: 5,
140
+ maxWidth: "min(250px, 21cqw)",
141
+ padding: "8px 10px",
142
+ borderRadius: 10,
143
+ border: "1px solid var(--graview-edge)",
144
+ background: "var(--graview-float)",
145
+ boxShadow: "var(--graview-lift-low)",
146
+ animation: "graview-settle 380ms 120ms ease backwards",
147
+ }, children: rows.map((row) => (_jsxs("div", { style: { display: "grid", gap: 5 }, children: [_jsx("span", { style: {
148
+ fontSize: "0.75rem",
149
+ letterSpacing: "0.16em",
150
+ textTransform: "uppercase",
151
+ color: "var(--graview-ink-faint)",
152
+ }, children: row.plural }), _jsx("div", { style: { display: "flex", alignItems: "center", gap: 4, flexWrap: "wrap" }, children: row.members.map((member, index, all) => {
153
+ const node = store.graph.getNode(member.id);
154
+ if (!node)
155
+ return null;
156
+ const hue = Math.round(hueFor(member.kind, brand?.accents));
157
+ const full = labelOf(store.schema.tryDefinition(member.kind), node);
158
+ const shown = handles(all.map((one) => {
159
+ const other = store.graph.getNode(one.id);
160
+ return other ? labelOf(store.schema.tryDefinition(one.kind), other) : one.id;
161
+ }))[index];
162
+ return (_jsxs("button", { type: "button", "data-graview-quick": member.id, "aria-label": full, title: `${full} — ${member.touches} of what you are looking at`, onClick: () => set([member.id]), style: {
163
+ display: "inline-flex",
164
+ alignItems: "center",
165
+ gap: 5,
166
+ minHeight: 24,
167
+ padding: "2px 9px",
168
+ fontSize: "0.8125rem",
169
+ borderRadius: 999,
170
+ cursor: "pointer",
171
+ border: "1px solid var(--graview-edge)",
172
+ background: "var(--graview-float)",
173
+ color: "var(--graview-ink)",
174
+ }, children: [_jsx("span", { "aria-hidden": "true", style: {
175
+ width: 7,
176
+ height: 7,
177
+ borderRadius: 999,
178
+ flex: "0 0 auto",
179
+ background: `hsl(${hue} 55% var(--graview-tint-lightness) / 0.9)`,
180
+ } }), shown] }, member.id));
181
+ }) })] }, row.kind))) }));
182
+ }
183
+ //# sourceMappingURL=quick-relations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quick-relations.js","sourceRoot":"","sources":["../src/quick-relations.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAkB,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;;;;;;;;;;;;;;GAeG;AACH;;;;GAIG;AACH,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,wFAAwF;AACxF,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB;;;;;;;;;GASG;AACH,MAAM,UAAU,OAAO,CAAC,MAAyB,EAAE,IAAI,GAAG,UAAU;IAClE,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpG,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QACjE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAClC,wDAAwD;QACxD,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YAC1C,IAAI,EAAE,GAAG,CAAC,CAAC;YACX,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;gBAAE,EAAE,IAAI,CAAC,CAAC;YAC/D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7B,CAAC,EAAE,KAAK,CAAC,CAAC;QACV,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1D,OAAO,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAsB,EAAE,MAAM,GAAG,KAAK,KAAoC,EAAE;IACxG,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,EAAK,CAAC;IACvD,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,EAAE,CAAC;IAC/B,MAAM,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;IACrC,MAAM,KAAK,GAAG,QAAQ,EAAK,CAAC;IAE5B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;QACxB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,UAAU,CAAC,MAAM,GAAG,CAAC;YACnB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACzF,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CACnB,CAAC;QACF,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAElC,wEAAwE;QACxE,qDAAqD;QACrD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsE,CAAC;QAC7F,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC1C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3F,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;gBAAE,SAAS;YAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC1C,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAc,CAAC;gBAAE,SAAS;YACvD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAc,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;YAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAc,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YAC7F,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAc,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;QAED,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;aACzB,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,IAAI,YAAY,CAAC;aACzE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;YACzB,IAAI;YACJ,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,GAAG;YAC9D,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3E,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAC5D;SACF,CAAC,CAAC;aACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;aACjC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC1B,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAEjC;;;;;;;OAOG;IACH,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,8BACa,cAAc,iBACb,iBAAiB,EAC7B,KAAK,EACH,MAAM;YACJ,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE;YAC7B,CAAC,CAAC;gBACE;;;;;mBAKG;gBACH,QAAQ,EAAE,UAAU;gBACpB,IAAI,EAAE,EAAE;gBACR,GAAG,EAAE,EAAE;gBACP,MAAM,EAAE,CAAC;gBACT,OAAO,EAAE,MAAM;gBACf,GAAG,EAAE,CAAC;gBACN,QAAQ,EAAE,mBAAmB;gBAC7B,OAAO,EAAE,UAAU;gBACnB,YAAY,EAAE,EAAE;gBAChB,MAAM,EAAE,+BAA+B;gBACvC,UAAU,EAAE,sBAAsB;gBAClC,SAAS,EAAE,yBAAyB;gBACpC,SAAS,EAAE,2CAA2C;aACvD,YAGN,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,eAAoB,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,aACpD,eACE,KAAK,EAAE;wBACL,QAAQ,EAAE,SAAS;wBACnB,aAAa,EAAE,QAAQ;wBACvB,aAAa,EAAE,WAAW;wBAC1B,KAAK,EAAE,0BAA0B;qBAClC,YAEA,GAAG,CAAC,MAAM,GACN,EACP,cAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,YAC9E,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;wBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;wBAC5C,IAAI,CAAC,IAAI;4BAAE,OAAO,IAAI,CAAC;wBACvB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;wBAC5D,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;wBACpE,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;4BACd,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;4BAC1C,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC/E,CAAC,CAAC,CACH,CAAC,KAAK,CAAE,CAAC;wBACV,OAAO,CACL,kBAEE,IAAI,EAAC,QAAQ,wBACO,MAAM,CAAC,EAAE,gBAEjB,IAAI,EAChB,KAAK,EAAE,GAAG,IAAI,MAAM,MAAM,CAAC,OAAO,6BAA6B,EAC/D,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAC/B,KAAK,EAAE;gCACL,OAAO,EAAE,aAAa;gCACtB,UAAU,EAAE,QAAQ;gCACpB,GAAG,EAAE,CAAC;gCACN,SAAS,EAAE,EAAE;gCACb,OAAO,EAAE,SAAS;gCAClB,QAAQ,EAAE,WAAW;gCACrB,YAAY,EAAE,GAAG;gCACjB,MAAM,EAAE,SAAS;gCACjB,MAAM,EAAE,+BAA+B;gCACvC,UAAU,EAAE,sBAAsB;gCAClC,KAAK,EAAE,oBAAoB;6BAC5B,aAED,8BACc,MAAM,EAClB,KAAK,EAAE;wCACL,KAAK,EAAE,CAAC;wCACR,MAAM,EAAE,CAAC;wCACT,YAAY,EAAE,GAAG;wCACjB,IAAI,EAAE,UAAU;wCAChB,UAAU,EAAE,OAAO,GAAG,2CAA2C;qCAClE,GACD,EACD,KAAK,KA/BD,MAAM,CAAC,EAAE,CAgCP,CACV,CAAC;oBACJ,CAAC,CAAC,GACI,KA5DE,GAAG,CAAC,IAAI,CA6DZ,CACP,CAAC,GACI,CACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { resolveKit, type AnySchema } from "@graview/core";
2
+ /**
3
+ * What the lines mean.
4
+ *
5
+ * From the Graview the relations ARE the content, drawn with a colour and a
6
+ * stroke pattern per edge kind — and nothing said which was which. A picture
7
+ * of a domain whose only legend is "these are different from each other"
8
+ * answers the shape of the question and not the question.
9
+ *
10
+ * Everything here is derived: the edge kinds come from the schema, the
11
+ * treatment from the same `connectorStyle` the scene draws with, the
12
+ * descriptions from the declarations, and the counts from the graph. Nothing
13
+ * is authored per app, and a new edge kind appears the day it is declared.
14
+ *
15
+ * Clicking one selects the kinds it joins, which is the same gesture as
16
+ * clicking a card: from up here, "show me what this touches" is the only thing
17
+ * selecting can mean.
18
+ */
19
+ export declare function RelationKey<S extends AnySchema>({ inside }?: {
20
+ readonly inside?: boolean;
21
+ }): import("react").JSX.Element | null;
22
+ /**
23
+ * What a relation is called where a person reads it: the declaration's
24
+ * description, capitalised, and which kinds it runs between in their
25
+ * plurals — "The vehicle it is for", "Deals → Vehicles". The edge's name is
26
+ * the source's word for it and only stands in when nothing else was said.
27
+ */
28
+ export declare function relationWords(schema: AnySchema, edgeKind: string): {
29
+ readonly words: string;
30
+ readonly ends: string;
31
+ };
32
+ /**
33
+ * ONE RELATION'S MARK, on its own: the same stroke the scene draws and the
34
+ * key lists, for any surface that names an edge kind — the routed face's
35
+ * map of the kinds, a record's relation groups. Works with or without the
36
+ * scene's provider: outside one, the brand's kit is resolved from what the
37
+ * caller hands over, or the default kit stands.
38
+ */
39
+ export declare function RelationMark({ edgeKind, kit: given, width }: {
40
+ readonly edgeKind: string;
41
+ readonly kit?: Parameters<typeof resolveKit>[0];
42
+ readonly width?: number;
43
+ }): import("react").JSX.Element;
44
+ //# sourceMappingURL=relation-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-key.d.ts","sourceRoot":"","sources":["../src/relation-key.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAS3D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,SAAS,EAAE,EAAE,MAAc,EAAE,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,sCA6MtG;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAOpH;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,+BASzK"}