@graview/react 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 (147) hide show
  1. package/LICENSE +96 -0
  2. package/README.md +20 -0
  3. package/dist/activity.d.ts +113 -0
  4. package/dist/activity.d.ts.map +1 -0
  5. package/dist/activity.js +207 -0
  6. package/dist/activity.js.map +1 -0
  7. package/dist/animation.d.ts +64 -0
  8. package/dist/animation.d.ts.map +1 -0
  9. package/dist/animation.js +245 -0
  10. package/dist/animation.js.map +1 -0
  11. package/dist/captions.d.ts +43 -0
  12. package/dist/captions.d.ts.map +1 -0
  13. package/dist/captions.js +61 -0
  14. package/dist/captions.js.map +1 -0
  15. package/dist/channels.d.ts +15 -0
  16. package/dist/channels.d.ts.map +1 -0
  17. package/dist/channels.js +114 -0
  18. package/dist/channels.js.map +1 -0
  19. package/dist/connectors.d.ts +176 -0
  20. package/dist/connectors.d.ts.map +1 -0
  21. package/dist/connectors.js +837 -0
  22. package/dist/connectors.js.map +1 -0
  23. package/dist/context.d.ts +348 -0
  24. package/dist/context.d.ts.map +1 -0
  25. package/dist/context.js +568 -0
  26. package/dist/context.js.map +1 -0
  27. package/dist/drawn.d.ts +60 -0
  28. package/dist/drawn.d.ts.map +1 -0
  29. package/dist/drawn.js +58 -0
  30. package/dist/drawn.js.map +1 -0
  31. package/dist/edge-signs.d.ts +13 -0
  32. package/dist/edge-signs.d.ts.map +1 -0
  33. package/dist/edge-signs.js +76 -0
  34. package/dist/edge-signs.js.map +1 -0
  35. package/dist/hooks.d.ts +160 -0
  36. package/dist/hooks.d.ts.map +1 -0
  37. package/dist/hooks.js +457 -0
  38. package/dist/hooks.js.map +1 -0
  39. package/dist/index.d.ts +37 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +22 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/keyboard.d.ts +5 -0
  44. package/dist/keyboard.d.ts.map +1 -0
  45. package/dist/keyboard.js +178 -0
  46. package/dist/keyboard.js.map +1 -0
  47. package/dist/kit.d.ts +10 -0
  48. package/dist/kit.d.ts.map +1 -0
  49. package/dist/kit.js +32 -0
  50. package/dist/kit.js.map +1 -0
  51. package/dist/local-intelligence.d.ts +31 -0
  52. package/dist/local-intelligence.d.ts.map +1 -0
  53. package/dist/local-intelligence.js +66 -0
  54. package/dist/local-intelligence.js.map +1 -0
  55. package/dist/motion.d.ts +17 -0
  56. package/dist/motion.d.ts.map +1 -0
  57. package/dist/motion.js +26 -0
  58. package/dist/motion.js.map +1 -0
  59. package/dist/occupants.d.ts +45 -0
  60. package/dist/occupants.d.ts.map +1 -0
  61. package/dist/occupants.js +57 -0
  62. package/dist/occupants.js.map +1 -0
  63. package/dist/parallel.d.ts +19 -0
  64. package/dist/parallel.d.ts.map +1 -0
  65. package/dist/parallel.js +30 -0
  66. package/dist/parallel.js.map +1 -0
  67. package/dist/picking.d.ts +30 -0
  68. package/dist/picking.d.ts.map +1 -0
  69. package/dist/picking.js +140 -0
  70. package/dist/picking.js.map +1 -0
  71. package/dist/plots.d.ts +106 -0
  72. package/dist/plots.d.ts.map +1 -0
  73. package/dist/plots.js +306 -0
  74. package/dist/plots.js.map +1 -0
  75. package/dist/pointer.d.ts +27 -0
  76. package/dist/pointer.d.ts.map +1 -0
  77. package/dist/pointer.js +39 -0
  78. package/dist/pointer.js.map +1 -0
  79. package/dist/presence.d.ts +110 -0
  80. package/dist/presence.d.ts.map +1 -0
  81. package/dist/presence.js +280 -0
  82. package/dist/presence.js.map +1 -0
  83. package/dist/rails.d.ts +11 -0
  84. package/dist/rails.d.ts.map +1 -0
  85. package/dist/rails.js +15 -0
  86. package/dist/rails.js.map +1 -0
  87. package/dist/resolved-view.d.ts +78 -0
  88. package/dist/resolved-view.d.ts.map +1 -0
  89. package/dist/resolved-view.js +365 -0
  90. package/dist/resolved-view.js.map +1 -0
  91. package/dist/robot.d.ts +114 -0
  92. package/dist/robot.d.ts.map +1 -0
  93. package/dist/robot.js +93 -0
  94. package/dist/robot.js.map +1 -0
  95. package/dist/routes.d.ts +50 -0
  96. package/dist/routes.d.ts.map +1 -0
  97. package/dist/routes.js +150 -0
  98. package/dist/routes.js.map +1 -0
  99. package/dist/scene-camera.d.ts +25 -0
  100. package/dist/scene-camera.d.ts.map +1 -0
  101. package/dist/scene-camera.js +130 -0
  102. package/dist/scene-camera.js.map +1 -0
  103. package/dist/scene-hand.d.ts +110 -0
  104. package/dist/scene-hand.d.ts.map +1 -0
  105. package/dist/scene-hand.js +317 -0
  106. package/dist/scene-hand.js.map +1 -0
  107. package/dist/scene-helpers.d.ts +46 -0
  108. package/dist/scene-helpers.d.ts.map +1 -0
  109. package/dist/scene-helpers.js +108 -0
  110. package/dist/scene-helpers.js.map +1 -0
  111. package/dist/scene-lines.d.ts +76 -0
  112. package/dist/scene-lines.d.ts.map +1 -0
  113. package/dist/scene-lines.js +578 -0
  114. package/dist/scene-lines.js.map +1 -0
  115. package/dist/scene-root.d.ts +71 -0
  116. package/dist/scene-root.d.ts.map +1 -0
  117. package/dist/scene-root.js +790 -0
  118. package/dist/scene-root.js.map +1 -0
  119. package/dist/scene.d.ts +17 -0
  120. package/dist/scene.d.ts.map +1 -0
  121. package/dist/scene.js +17 -0
  122. package/dist/scene.js.map +1 -0
  123. package/dist/seat-marks.d.ts +35 -0
  124. package/dist/seat-marks.d.ts.map +1 -0
  125. package/dist/seat-marks.js +43 -0
  126. package/dist/seat-marks.js.map +1 -0
  127. package/dist/settings.d.ts +30 -0
  128. package/dist/settings.d.ts.map +1 -0
  129. package/dist/settings.js +73 -0
  130. package/dist/settings.js.map +1 -0
  131. package/dist/view-boundary.d.ts +33 -0
  132. package/dist/view-boundary.d.ts.map +1 -0
  133. package/dist/view-boundary.js +53 -0
  134. package/dist/view-boundary.js.map +1 -0
  135. package/dist/view-host.d.ts +57 -0
  136. package/dist/view-host.d.ts.map +1 -0
  137. package/dist/view-host.js +474 -0
  138. package/dist/view-host.js.map +1 -0
  139. package/dist/view-registry.d.ts +122 -0
  140. package/dist/view-registry.d.ts.map +1 -0
  141. package/dist/view-registry.js +20 -0
  142. package/dist/view-registry.js.map +1 -0
  143. package/dist/where-drawn.d.ts +151 -0
  144. package/dist/where-drawn.d.ts.map +1 -0
  145. package/dist/where-drawn.js +231 -0
  146. package/dist/where-drawn.js.map +1 -0
  147. package/package.json +60 -0
@@ -0,0 +1,178 @@
1
+ import { useEffect } from "react";
2
+ /**
3
+ * THE KEYBOARD ALWAYS LANDS SOMEWHERE.
4
+ *
5
+ * An act removes what the keyboard stood on all the time here: Escape
6
+ * closes the popover, a chip's × drops the selection it was, Back takes the
7
+ * page away, an answered form gives way to the record it changed. A browser
8
+ * does nothing about it — the keyboard falls to <body>, Tab starts again at
9
+ * the top of the document, and a screen reader says nothing at all. Six
10
+ * walks found that eight times, on eight different surfaces, each fixed on
11
+ * its own surface (W-053, W-070, W-083, W-090, W-092, W-111, W-125, W-136).
12
+ *
13
+ * So it is one rule at the root instead. While the keyboard is inside this
14
+ * root, the line of elements it stands in is remembered; when the element it
15
+ * stood on is removed and nothing else took the keyboard, it lands on the
16
+ * nearest of those that still stands — the first control inside it, or the
17
+ * element itself when it can take the keyboard — which is the place the
18
+ * removed thing was IN: the bar a closed menu hung from, the panel a closed
19
+ * form sat in, the card that still draws what was deselected.
20
+ *
21
+ * A surface that knows better (Escape's own landing on the card that still
22
+ * draws the record, `landTheKeyboard`) moves the keyboard first, and this
23
+ * then finds it somewhere and does nothing. Only a keyboard left on nothing
24
+ * is moved, and only one that was in this root, so a host page around an
25
+ * embed is never touched.
26
+ */
27
+ const CONTROL = 'button:not([disabled]), a[href], input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), summary, [tabindex]:not([tabindex="-1"])';
28
+ const takesTheKeyboard = (el) => el instanceof HTMLElement && (el.matches(CONTROL) || el.hasAttribute("tabindex"));
29
+ const shown = (el) => typeof el.checkVisibility === "function" ? el.checkVisibility() : el.getClientRects().length > 0;
30
+ /**
31
+ * The same control, drawn again: a re-render that replaced the element the
32
+ * keyboard stood on is not the control going away.
33
+ */
34
+ function twinIn(standing, gone) {
35
+ const css = (value) => value.replace(/["\\]/g, "\\$&");
36
+ const testid = gone.getAttribute("data-testid");
37
+ const pick = gone.getAttribute("data-graview-pick");
38
+ const label = gone.getAttribute("aria-label");
39
+ const selector = testid
40
+ ? `[data-testid="${css(testid)}"]`
41
+ : pick
42
+ ? `[data-graview-pick="${css(pick)}"]`
43
+ : label
44
+ ? `${gone.tagName.toLowerCase()}[aria-label="${css(label)}"]`
45
+ : null;
46
+ if (!selector)
47
+ return null;
48
+ const twin = standing.querySelector(selector);
49
+ return twin && takesTheKeyboard(twin) && shown(twin) ? twin : null;
50
+ }
51
+ /** Still there, and still able to hold the keyboard: a person who clicked away left it on purpose. */
52
+ const standsAndTakesTheKeyboard = (el) => el.isConnected && takesTheKeyboard(el) && !el.matches(":disabled") && el instanceof HTMLElement && shown(el);
53
+ /** Where the keyboard goes inside what still stands. Exported for its test. */
54
+ export function landingIn(standing, gone) {
55
+ const twin = gone ? twinIn(standing, gone) : null;
56
+ if (twin)
57
+ return twin;
58
+ // A drawn record first: in the scene the picture is what the keys mean.
59
+ const view = standing.querySelector("[data-graview-view][tabindex]");
60
+ if (view && shown(view))
61
+ return view;
62
+ for (const candidate of standing.querySelectorAll(CONTROL)) {
63
+ if (shown(candidate))
64
+ return candidate;
65
+ }
66
+ return takesTheKeyboard(standing) && shown(standing) ? standing : null;
67
+ }
68
+ export function useTheKeyboardLandsSomewhere(root) {
69
+ useEffect(() => {
70
+ const at = root.current;
71
+ if (!at || typeof MutationObserver === "undefined")
72
+ return;
73
+ // The line the keyboard stands in, innermost first, up to this root.
74
+ let line = [];
75
+ const remember = (event) => {
76
+ const target = event.target;
77
+ if (!(target instanceof Element))
78
+ return;
79
+ line = [];
80
+ for (let el = target; el && el !== at.parentElement; el = el.parentElement)
81
+ line.push(el);
82
+ };
83
+ let queued = false;
84
+ const land = (afterAnAct) => {
85
+ queued = false;
86
+ const active = document.activeElement;
87
+ const onNothing = active === null || active === document.body || active === document.documentElement;
88
+ if (!onNothing || line.length === 0)
89
+ return;
90
+ if (standsAndTakesTheKeyboard(line[0])) {
91
+ // Still there: after a press of its own it gets the keyboard back; a
92
+ // person who clicked away from it left it on purpose.
93
+ if (afterAnAct && line[0] instanceof HTMLElement)
94
+ line[0].focus({ preventScroll: true });
95
+ return;
96
+ }
97
+ for (const el of line.slice(1)) {
98
+ if (!el.isConnected)
99
+ continue;
100
+ const target = landingIn(el, line[0]);
101
+ if (target) {
102
+ target.focus({ preventScroll: true });
103
+ line = [];
104
+ return;
105
+ }
106
+ }
107
+ };
108
+ /*
109
+ * ASKED UNTIL IT IS SOMEWHERE, not a set number of times. The rule looked
110
+ * at fixed moments — 60, 150, 600 ms — and on a starved machine every one
111
+ * of them came before the change it was waiting for: the nightly's runner
112
+ * left the keyboard on <body> after the studio's Keep for seconds. It is
113
+ * asked again every tenth of a second until it lands, or for two and a
114
+ * half seconds, whichever is first; a person who moves it meanwhile ends
115
+ * it, because the keyboard is then somewhere.
116
+ */
117
+ const persist = (afterAnAct, until = Date.now() + 2500) => {
118
+ setTimeout(() => {
119
+ land(afterAnAct);
120
+ const active = document.activeElement;
121
+ const onNothing = active === null || active === document.body || active === document.documentElement;
122
+ if (onNothing && line.length > 0 && Date.now() < until)
123
+ persist(afterAnAct, until);
124
+ }, 100);
125
+ };
126
+ const later = () => {
127
+ if (queued || line.length === 0)
128
+ return;
129
+ queued = true;
130
+ // After the frame a surface that knows better gets to move it first.
131
+ setTimeout(() => requestAnimationFrame(() => {
132
+ land(false);
133
+ persist(false);
134
+ }), 60);
135
+ };
136
+ /*
137
+ * AND AFTER AN ACT, ASKED AGAIN. A press can take the keyboard off a
138
+ * control without removing it or firing anything the root hears — a
139
+ * button disabled while its answer comes, a form that resets — so after
140
+ * a press or Enter, Space or Escape inside the root, it is asked whether
141
+ * the keyboard is anywhere until it is.
142
+ */
143
+ const acted = (event) => {
144
+ if (event instanceof KeyboardEvent && !["Enter", " ", "Escape"].includes(event.key))
145
+ return;
146
+ // A click elsewhere — on the empty picture, say — is a person leaving on purpose.
147
+ if (!(event instanceof KeyboardEvent) && !(event.target instanceof Node && line[0]?.contains(event.target)))
148
+ return;
149
+ setTimeout(() => requestAnimationFrame(() => {
150
+ land(true);
151
+ persist(true);
152
+ }), 150);
153
+ };
154
+ const observer = new MutationObserver(() => {
155
+ if (line.length > 0 && !line[0].isConnected)
156
+ later();
157
+ });
158
+ // A control disabled or hidden while it held the keyboard stays in the
159
+ // document and lets go of it — "Send" while the answer is coming.
160
+ const letGo = (event) => {
161
+ if (event.relatedTarget === null)
162
+ later();
163
+ };
164
+ at.addEventListener("focusin", remember);
165
+ at.addEventListener("focusout", letGo);
166
+ at.addEventListener("click", acted);
167
+ at.addEventListener("keydown", acted);
168
+ observer.observe(at, { childList: true, subtree: true });
169
+ return () => {
170
+ at.removeEventListener("focusin", remember);
171
+ at.removeEventListener("focusout", letGo);
172
+ at.removeEventListener("click", acted);
173
+ at.removeEventListener("keydown", acted);
174
+ observer.disconnect();
175
+ };
176
+ }, [root]);
177
+ }
178
+ //# sourceMappingURL=keyboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"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"}
package/dist/kit.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { type ConnectorKit, type Kit } from "@graview/core";
2
+ import { type ConnectorStyle } from "@graview/render";
3
+ /** The brand's kit, resolved once per brand. */
4
+ export declare function useKit(): Kit;
5
+ /** The render style for one edge kind, with what the kit says laid over the derived treatment. */
6
+ export declare function kitConnector(kit: Kit, kind: string): {
7
+ readonly connector: ConnectorKit;
8
+ readonly style: ConnectorStyle;
9
+ };
10
+ //# sourceMappingURL=kit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kit.d.ts","sourceRoot":"","sources":["../src/kit.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,YAAY,EAAE,KAAK,GAAG,EAAqB,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AActE,gDAAgD;AAChD,wBAAgB,MAAM,IAAI,GAAG,CAI5B;AAED,kGAAkG;AAClG,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CAUzH"}
package/dist/kit.js ADDED
@@ -0,0 +1,32 @@
1
+ import { connectorKitFor, resolveKit } from "@graview/core";
2
+ import { connectorStyle } from "@graview/render";
3
+ import { useMemo } from "react";
4
+ import { useGraview } from "./context.js";
5
+ /*
6
+ * THE KIT AS THE SCENE ASKS FOR IT.
7
+ *
8
+ * The brand declares a kit; the scene never reads the brand. It asks for
9
+ * one edge kind's connector — the kit's `all`, the kind's own entry over
10
+ * it — and gets the render style with the kit's colour, pattern, weight
11
+ * and cap laid over the hash-derived treatment. A kind the kit keeps quiet
12
+ * is `visible: false`, and the scene draws nothing for it.
13
+ */
14
+ /** The brand's kit, resolved once per brand. */
15
+ export function useKit() {
16
+ const { brand } = useGraview();
17
+ const overrides = brand?.kit;
18
+ return useMemo(() => resolveKit(overrides), [overrides]);
19
+ }
20
+ /** The render style for one edge kind, with what the kit says laid over the derived treatment. */
21
+ export function kitConnector(kit, kind) {
22
+ const connector = connectorKitFor(kit, kind);
23
+ const over = {
24
+ ...(connector.colour !== undefined ? { colour: connector.colour } : {}),
25
+ ...(connector.pattern !== undefined ? { pattern: connector.pattern } : {}),
26
+ ...(connector.width !== undefined ? { width: connector.width } : {}),
27
+ ...(connector.cap !== undefined ? { cap: connector.cap } : {}),
28
+ ...(connector.opacity !== undefined ? { opacity: connector.opacity } : {}),
29
+ };
30
+ return { connector, style: connectorStyle(kind, { [kind]: over }) };
31
+ }
32
+ //# sourceMappingURL=kit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kit.js","sourceRoot":"","sources":["../src/kit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAkD,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAE,cAAc,EAAuB,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C;;;;;;;;GAQG;AAEH,gDAAgD;AAChD,MAAM,UAAU,MAAM;IACpB,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,EAAE,CAAC;IAC/B,MAAM,SAAS,GAA6B,KAAK,EAAE,GAAG,CAAC;IACvD,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,YAAY,CAAC,GAAQ,EAAE,IAAY;IACjD,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,IAAI,GAA4B;QACpC,GAAG,CAAC,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,SAAS,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,GAAG,CAAC,SAAS,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,SAAS,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3E,CAAC;IACF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACtE,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * IS THERE A MACHINE BEHIND THIS PAGE, AND WILL IT ANSWER?
3
+ *
4
+ * The local door is open only while somebody is running the app from a
5
+ * terminal: `localIntelligence()` from `@graview/ship/dev` is a dev-server
6
+ * plugin, so a built deployment has nothing serving the path at all. Every
7
+ * way that can go wrong has to read as CLOSED rather than as broken —
8
+ *
9
+ * - a 404, because the page is on a static host and no plugin exists;
10
+ * - an HTML answer, because a dev server with history fallback hands the
11
+ * index page to an unknown path and `JSON.parse` would throw on it;
12
+ * - a network failure, because nothing is listening at all.
13
+ *
14
+ * Closed is not an error. A door that is not there is the normal state of
15
+ * every deployed copy of the app, and an interface that says "failed" there
16
+ * is telling a person to fix something that is working.
17
+ */
18
+ export type LocalIntelligence = {
19
+ readonly state: "probing";
20
+ } | {
21
+ readonly state: "open";
22
+ readonly version: string;
23
+ readonly ask: Ask;
24
+ } | {
25
+ readonly state: "closed";
26
+ readonly reason: string;
27
+ };
28
+ /** Words and photographs (base64 data URLs) in, what it said out. */
29
+ export type Ask = (prompt: string, photos?: readonly string[]) => Promise<string>;
30
+ export declare function useLocalIntelligence(path?: string): LocalIntelligence;
31
+ //# sourceMappingURL=local-intelligence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-intelligence.d.ts","sourceRoot":"","sources":["../src/local-intelligence.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;CAAE,GACvE;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,qEAAqE;AACrE,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAalF,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,MAA0B,GAAG,iBAAiB,CAkDxF"}
@@ -0,0 +1,66 @@
1
+ import { LOCAL_BRIDGE_PATH } from "@graview/core";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ /** A JSON body, or nothing at all when the answer was not JSON. */
4
+ async function json(response) {
5
+ const type = response.headers.get("content-type") ?? "";
6
+ if (!type.includes("json"))
7
+ return undefined;
8
+ try {
9
+ return (await response.json());
10
+ }
11
+ catch {
12
+ return undefined;
13
+ }
14
+ }
15
+ export function useLocalIntelligence(path = LOCAL_BRIDGE_PATH) {
16
+ const [status, setStatus] = useState(null);
17
+ useEffect(() => {
18
+ let live = true;
19
+ const closed = (reason) => {
20
+ if (live)
21
+ setStatus({ available: false, reason });
22
+ };
23
+ void (async () => {
24
+ try {
25
+ const response = await fetch(path, { method: "GET", headers: { accept: "application/json" } });
26
+ if (!response.ok) {
27
+ closed("Nothing is serving the local door here.");
28
+ return;
29
+ }
30
+ const body = await json(response);
31
+ if (body === undefined) {
32
+ /* An HTML index page: the dev server's history fallback, not a door. */
33
+ closed("Nothing is serving the local door here.");
34
+ return;
35
+ }
36
+ if (live)
37
+ setStatus(body);
38
+ }
39
+ catch {
40
+ closed("Nothing is serving the local door here.");
41
+ }
42
+ })();
43
+ return () => {
44
+ live = false;
45
+ };
46
+ }, [path]);
47
+ const ask = useCallback(async (prompt, photos = []) => {
48
+ const response = await fetch(path, {
49
+ method: "POST",
50
+ headers: { "content-type": "application/json" },
51
+ body: JSON.stringify({ prompt, photos }),
52
+ });
53
+ const body = (await json(response));
54
+ if (body === undefined)
55
+ throw new Error("The local door answered with something that was not JSON.");
56
+ if ("error" in body)
57
+ throw new Error(body.error);
58
+ return body.text;
59
+ }, [path]);
60
+ if (status === null)
61
+ return { state: "probing" };
62
+ return status.available
63
+ ? { state: "open", version: status.version, ask }
64
+ : { state: "closed", reason: status.reason };
65
+ }
66
+ //# sourceMappingURL=local-intelligence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-intelligence.js","sourceRoot":"","sources":["../src/local-intelligence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAkD,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA2BzD,mEAAmE;AACnE,KAAK,UAAU,IAAI,CAAC,QAAkB;IACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IACxD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAY,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAe,iBAAiB;IACnE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAA2B,IAAI,CAAC,CAAC;IAErE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,GAAG,IAAI,CAAC;QAChB,MAAM,MAAM,GAAG,CAAC,MAAc,EAAE,EAAE;YAChC,IAAI,IAAI;gBAAE,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC;QACF,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;gBAC/F,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,MAAM,CAAC,yCAAyC,CAAC,CAAC;oBAClD,OAAO;gBACT,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAClC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACvB,wEAAwE;oBACxE,MAAM,CAAC,yCAAyC,CAAC,CAAC;oBAClD,OAAO;gBACT,CAAC;gBACD,IAAI,IAAI;oBAAE,SAAS,CAAC,IAAyB,CAAC,CAAC;YACjD,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,yCAAyC,CAAC,CAAC;YACpD,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,GAAG,EAAE;YACV,IAAI,GAAG,KAAK,CAAC;QACf,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,GAAG,GAAG,WAAW,CACrB,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE;QAC5B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE;YACjC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;SACzC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAkC,CAAC;QACrE,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QACrG,IAAI,OAAO,IAAI,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC,EACD,CAAC,IAAI,CAAC,CACP,CAAC;IAEF,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IACjD,OAAO,MAAM,CAAC,SAAS;QACrB,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE;QACjD,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACjD,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * WHETHER THE SCENE IS MOVING — a drag, a wheel, a transition — for the few
3
+ * things that should wait for it to stop (docs/scale.md): a drive-in's
4
+ * thumbnail is a lens drawn small, and building one while the camera flies
5
+ * spends a frame on a picture nobody can read yet. A store, not context
6
+ * state: setting it re-renders only what subscribed.
7
+ */
8
+ export interface MotionStore {
9
+ moving(): boolean;
10
+ /** The scene calls this; nobody else does. */
11
+ set(moving: boolean): void;
12
+ subscribe(listener: () => void): () => void;
13
+ }
14
+ export declare function createMotionStore(): MotionStore;
15
+ /** True while the scene is still. */
16
+ export declare function useSceneStill(): boolean;
17
+ //# sourceMappingURL=motion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.d.ts","sourceRoot":"","sources":["../src/motion.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,IAAI,OAAO,CAAC;IAClB,8CAA8C;IAC9C,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAe/C;AAED,qCAAqC;AACrC,wBAAgB,aAAa,IAAI,OAAO,CAGvC"}
package/dist/motion.js ADDED
@@ -0,0 +1,26 @@
1
+ import { useSyncExternalStore } from "react";
2
+ import { useGraview } from "./context.js";
3
+ export function createMotionStore() {
4
+ let moving = false;
5
+ const listeners = new Set();
6
+ return {
7
+ moving: () => moving,
8
+ set(next) {
9
+ if (next === moving)
10
+ return;
11
+ moving = next;
12
+ for (const listener of listeners)
13
+ listener();
14
+ },
15
+ subscribe(listener) {
16
+ listeners.add(listener);
17
+ return () => listeners.delete(listener);
18
+ },
19
+ };
20
+ }
21
+ /** True while the scene is still. */
22
+ export function useSceneStill() {
23
+ const { motion } = useGraview();
24
+ return useSyncExternalStore(motion.subscribe, () => !motion.moving(), () => true);
25
+ }
26
+ //# sourceMappingURL=motion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"motion.js","sourceRoot":"","sources":["../src/motion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAgB1C,MAAM,UAAU,iBAAiB;IAC/B,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IACxC,OAAO;QACL,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM;QACpB,GAAG,CAAC,IAAI;YACN,IAAI,IAAI,KAAK,MAAM;gBAAE,OAAO;YAC5B,MAAM,GAAG,IAAI,CAAC;YACd,KAAK,MAAM,QAAQ,IAAI,SAAS;gBAAE,QAAQ,EAAE,CAAC;QAC/C,CAAC;QACD,SAAS,CAAC,QAAQ;YAChB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;AACJ,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,aAAa;IAC3B,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IAChC,OAAO,oBAAoB,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACpF,CAAC"}
@@ -0,0 +1,45 @@
1
+ import type { ReactElement } from "react";
2
+ import { type DrawnBox } from "./context.js";
3
+ import type { RobotState } from "./robot.js";
4
+ /**
5
+ * THE OCCUPANTS: the other bodies in the city. People and their agents,
6
+ * drawn in an overlay OVER the stage on both renderer paths at the boxes
7
+ * `whereIs` gives for the frame being drawn — so they ride the tween and
8
+ * the pan for free and never enter `layout()`. Movement is a CSS
9
+ * transition on transform: a quiet city runs nothing.
10
+ *
11
+ * This tab's own seat is not here. It used to stand on a pad, walk to what
12
+ * it wrote and follow the pointer — a thing in the middle of the picture
13
+ * that moved on its own, and nothing at all inside a full-screen lens. The
14
+ * companion on the frame says who it is and what it is doing, at every
15
+ * height; what it wrote is marked on the things themselves. Somebody
16
+ * else's agent keeps its body: that is how you see them at work.
17
+ */
18
+ export interface OccupantsProps {
19
+ readonly width: number;
20
+ readonly whereIs: (id: string) => DrawnBox | null;
21
+ }
22
+ /**
23
+ * THE ROBOT, in the scene's own line vocabulary. A dome head with a visor
24
+ * and two eyes, an antenna, and a body that is one of the city's own iso
25
+ * blocks — the same block a district is — on two small feet. What it is
26
+ * doing is in the drawing: the antenna lights while it follows, an arm
27
+ * comes up with a pen while it writes, the visor sweeps while it reads,
28
+ * the eyes drop while it is docked, and a refusal flattens the visor.
29
+ */
30
+ export declare function Figure({ hue, mode }: {
31
+ readonly hue: number;
32
+ readonly mode: RobotState["mode"];
33
+ }): ReactElement;
34
+ /** A person, in the same line vocabulary: a head, shoulders, standing. */
35
+ export declare function PersonFigure({ hue }: {
36
+ readonly hue: number;
37
+ }): ReactElement;
38
+ /**
39
+ * THE OTHERS, on this map: people as figures at the plots they are looking
40
+ * at, their agents as robots, and the ones elsewhere as a mark at the edge.
41
+ * Placed with this frame's own `whereIs`, so each viewer draws the same
42
+ * people at the same plots in its own pixels.
43
+ */
44
+ export declare function Occupants({ width, whereIs }: OccupantsProps): ReactElement | null;
45
+ //# sourceMappingURL=occupants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"occupants.d.ts","sourceRoot":"","sources":["../src/occupants.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,QAAQ,GAAG,IAAI,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;CAAE,GAAG,YAAY,CAgD/G;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAU5E;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,cAAc,GAAG,YAAY,GAAG,IAAI,CAqGjF"}
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useGraview } from "./context.js";
3
+ import { placeOthers } from "./presence.js";
4
+ /**
5
+ * THE ROBOT, in the scene's own line vocabulary. A dome head with a visor
6
+ * and two eyes, an antenna, and a body that is one of the city's own iso
7
+ * blocks — the same block a district is — on two small feet. What it is
8
+ * doing is in the drawing: the antenna lights while it follows, an arm
9
+ * comes up with a pen while it writes, the visor sweeps while it reads,
10
+ * the eyes drop while it is docked, and a refusal flattens the visor.
11
+ */
12
+ export function Figure({ hue, mode }) {
13
+ const docked = mode === "docked";
14
+ const writing = mode === "writing";
15
+ const reading = mode === "reading";
16
+ const refused = mode === "refused";
17
+ void hue;
18
+ return (_jsxs("svg", { viewBox: "0 0 32 38", "aria-hidden": "true", children: [_jsxs("g", { fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinejoin: "round", strokeLinecap: "round", children: [_jsx("line", { x1: "16", y1: "3.5", x2: "16", y2: "7" }), _jsx("circle", { cx: "16", cy: "2.6", r: "1.5", fill: "none" }), _jsx("path", { d: "M8 16 V12.5 C8 8.5 11.5 7 16 7 C20.5 7 24 8.5 24 12.5 V16 Z", fill: "currentColor", fillOpacity: "0.1" }), refused ? (_jsx("line", { x1: "11", y1: "12.5", x2: "21", y2: "12.5", strokeWidth: "2" })) : (_jsxs(_Fragment, { children: [_jsx("rect", { x: "10.2", y: "10.2", width: "11.6", height: "4.6", rx: "2.3", fill: "currentColor", fillOpacity: "0.14", strokeWidth: "1" }), _jsx("circle", { cx: "13.4", cy: "12.5", r: "1.25", fill: "currentColor", stroke: "none", opacity: docked ? 0.45 : 1 }), _jsx("circle", { cx: "18.6", cy: "12.5", r: "1.25", fill: "currentColor", stroke: "none", opacity: docked ? 0.45 : 1 }), reading ? _jsx("line", { x1: "10.2", y1: "12.5", x2: "21.8", y2: "12.5", strokeWidth: "0.8", opacity: "0.7" }) : null] })), _jsx("line", { x1: "16", y1: "16", x2: "16", y2: "18.5" }), _jsx("polygon", { points: "16,18.5 24,22.5 16,26.5 8,22.5", fill: "currentColor", fillOpacity: "0.22" }), _jsx("polygon", { points: "8,22.5 16,26.5 16,33.5 8,29.5", fill: "currentColor", fillOpacity: "0.08" }), _jsx("polygon", { points: "24,22.5 16,26.5 16,33.5 24,29.5", fill: "currentColor", fillOpacity: "0.3" }), writing ? (_jsxs(_Fragment, { children: [_jsx("polyline", { points: "24,24 28.5,20.5" }), _jsx("line", { x1: "27.5", y1: "19", x2: "30", y2: "21.5", strokeWidth: "1.8" })] })) : (_jsx("line", { x1: "24", y1: "24", x2: "26.5", y2: "29" })), _jsx("line", { x1: "8", y1: "24", x2: "5.5", y2: "29" }), _jsx("path", { d: "M9.5 33.5 v2.2 h4" }), _jsx("path", { d: "M22.5 33.5 v2.2 h-4" })] }), _jsx("title", { children: `robot, ${mode}` })] }));
19
+ }
20
+ /** A person, in the same line vocabulary: a head, shoulders, standing. */
21
+ export function PersonFigure({ hue }) {
22
+ return (_jsxs("svg", { viewBox: "0 0 22 24", "aria-hidden": "true", style: { color: `hsl(${Math.round(hue)} 50% 48%)` }, children: [_jsxs("g", { fill: "none", stroke: "currentColor", strokeWidth: "1.4", strokeLinejoin: "round", strokeLinecap: "round", children: [_jsx("circle", { cx: "11", cy: "6", r: "4.2" }), _jsx("path", { d: "M3 23 C3 15.5 6 13 11 13 C16 13 19 15.5 19 23" })] }), _jsx("title", { children: "somebody" })] }));
23
+ }
24
+ /**
25
+ * THE OTHERS, on this map: people as figures at the plots they are looking
26
+ * at, their agents as robots, and the ones elsewhere as a mark at the edge.
27
+ * Placed with this frame's own `whereIs`, so each viewer draws the same
28
+ * people at the same plots in its own pixels.
29
+ */
30
+ export function Occupants({ width, whereIs }) {
31
+ const { who, following, follow } = useGraview();
32
+ const others = placeOthers([...who.values()], whereIs, width);
33
+ if (others.length === 0)
34
+ return null;
35
+ return (_jsx("div", { className: "graview-occupants", "data-testid": "occupants", "data-graview-occupants": others.length, children: others.map((one, index) => {
36
+ if (one.kind === "over") {
37
+ return (_jsx("div", { className: "graview-presence-over", "data-testid": "presence-over", "data-graview-over-by": one.presence.participant, style: { left: one.box.x - 3, top: one.box.y - 3, width: one.box.width + 6, height: one.box.height + 6, ["--graview-hue"]: one.presence.hue } }, `over:${one.presence.participant}`));
38
+ }
39
+ if (one.kind === "count") {
40
+ return (_jsxs("span", { className: "graview-figure-count", "data-testid": "presence-count", "data-graview-at": one.at, style: { left: one.point.x, top: one.point.y }, title: `${one.n} more here`, children: ["+", one.n] }, `count:${one.at}:${index}`));
41
+ }
42
+ const hue = one.presence.hue;
43
+ const name = one.presence.name ?? "somebody";
44
+ if (one.kind === "edge") {
45
+ return (_jsxs("button", { type: "button", className: "graview-figure-edge", "data-testid": "presence-edge", "data-graview-person": one.presence.participant, style: { left: Math.max(8, one.point.x - 120), top: one.point.y }, onClick: () => follow(one.presence.participant), "aria-label": `${name} is somewhere else — press to go where they are`, children: ["\u2192 ", name] }, `edge:${one.presence.participant}`));
46
+ }
47
+ if (one.kind === "robot") {
48
+ return (_jsxs("div", { className: "graview-figure", "data-graview-figure": `theirs:${one.presence.participant}`, "data-graview-theirs": "", "data-graview-mode": one.mode, "data-graview-at": one.presence.robot?.at ?? "", style: { transform: `translate(${one.point.x.toFixed(1)}px, ${one.point.y.toFixed(1)}px)`, ["--graview-hue"]: hue }, children: [_jsx("span", { className: "graview-figure-body", role: "img", "aria-label": `${name}'s agent — ${one.mode}`, style: { cursor: "default" }, children: _jsx(Figure, { hue: hue, mode: one.mode }) }), _jsxs("span", { className: "graview-figure-name", children: [name, "'s agent"] })] }, `robot:${one.presence.participant}`));
49
+ }
50
+ const followed = following?.participant === one.presence.participant;
51
+ return (_jsxs("div", { className: "graview-figure", "data-graview-figure": one.presence.participant, "data-graview-person": "", "data-graview-at": one.at, "data-graview-audience": one.audience ? "" : undefined, "data-graview-followed": followed ? "" : undefined, style: { transform: `translate(${one.point.x.toFixed(1)}px, ${one.point.y.toFixed(1)}px)`, ["--graview-hue"]: hue }, children: [_jsx("button", { type: "button", className: "graview-figure-body", "aria-label": `${name} is here${followed ? ". Press to stop following" : ". Press to go where they go"}`, "aria-pressed": followed, onClick: (event) => {
52
+ event.stopPropagation();
53
+ follow(followed ? null : one.presence.participant);
54
+ }, onPointerDown: (event) => event.stopPropagation(), children: _jsx(PersonFigure, { hue: hue }) }), _jsx("span", { className: "graview-figure-name", children: name })] }, `person:${one.presence.participant}`));
55
+ }) }));
56
+ }
57
+ //# sourceMappingURL=occupants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"occupants.js","sourceRoot":"","sources":["../src/occupants.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * TWO RELATIONS BETWEEN THE SAME TWO THINGS ARE TWO LINES.
3
+ *
4
+ * A song is by Mara Vey and produced by Mara Vey: two edges, two kinds,
5
+ * two lines — drawn along the identical curve, so the picture showed one
6
+ * and the pointer could only ever pick the one on top. The first was
7
+ * neither visible nor selectable, and "selecting the line offers the act
8
+ * that severs it" was false for it.
9
+ *
10
+ * Lines sharing both ends fan out: each is bowed by its own offset about
11
+ * the shared curve, centred so the bundle stays where one line would be.
12
+ * Returns the offset, in pixels along the curve's normal, for each line.
13
+ */
14
+ export declare function parallelOffsets(lines: readonly {
15
+ readonly key: string;
16
+ readonly a: string;
17
+ readonly b: string;
18
+ }[], spacing?: number): Map<string, number>;
19
+ //# sourceMappingURL=parallel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,EAClF,OAAO,SAAK,GACX,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAarB"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * TWO RELATIONS BETWEEN THE SAME TWO THINGS ARE TWO LINES.
3
+ *
4
+ * A song is by Mara Vey and produced by Mara Vey: two edges, two kinds,
5
+ * two lines — drawn along the identical curve, so the picture showed one
6
+ * and the pointer could only ever pick the one on top. The first was
7
+ * neither visible nor selectable, and "selecting the line offers the act
8
+ * that severs it" was false for it.
9
+ *
10
+ * Lines sharing both ends fan out: each is bowed by its own offset about
11
+ * the shared curve, centred so the bundle stays where one line would be.
12
+ * Returns the offset, in pixels along the curve's normal, for each line.
13
+ */
14
+ export function parallelOffsets(lines, spacing = 16) {
15
+ const pairs = new Map();
16
+ for (const line of lines) {
17
+ const pair = line.a < line.b ? `${line.a}\u0000${line.b}` : `${line.b}\u0000${line.a}`;
18
+ const held = pairs.get(pair);
19
+ if (held)
20
+ held.push(line.key);
21
+ else
22
+ pairs.set(pair, [line.key]);
23
+ }
24
+ const offsets = new Map();
25
+ for (const keys of pairs.values()) {
26
+ keys.forEach((key, index) => offsets.set(key, (index - (keys.length - 1) / 2) * spacing));
27
+ }
28
+ return offsets;
29
+ }
30
+ //# sourceMappingURL=parallel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAkF,EAClF,OAAO,GAAG,EAAE;IAEZ,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC;QACvF,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;;YACzB,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The one rule that makes anything a view drew into a real target.
3
+ *
4
+ * A view marks an element with `data-graview-pick="<node id>"` and that is the
5
+ * WHOLE contract: whatever surface the view is drawn on routes the gesture to
6
+ * that node. Which surface is the part that was wrong — the rule lived inside
7
+ * the scene's host, so a view lifted out into a full page kept its marks and
8
+ * lost its behaviour. Every chip on it was a button-shaped thing that did
9
+ * nothing, which is precisely the "I clicked it and nothing happened" the
10
+ * marks exist to prevent.
11
+ *
12
+ * So it lives here, and both surfaces use it.
13
+ */
14
+ /** The node a pointer or key event is really about, if any. */
15
+ export declare function pickedFrom(target: EventTarget | null): string | null;
16
+ /**
17
+ * Makes every `data-graview-pick` element inside a host a real control.
18
+ *
19
+ * Having made clicking the primary way to move through the graph, leaving
20
+ * those targets unreachable by keyboard would make the primary interaction
21
+ * mouse-only.
22
+ *
23
+ * Set as attributes rather than as props because the elements belong to
24
+ * whatever view drew them; React is not managing these, so there is nothing
25
+ * to fight over.
26
+ */
27
+ export declare function usePickTargets(ref: {
28
+ current: HTMLElement | null;
29
+ }): void;
30
+ //# sourceMappingURL=picking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"picking.d.ts","sourceRoot":"","sources":["../src/picking.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAMpE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE;IAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAqCzE"}