@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,50 @@
1
+ import type { ConnectorRoute } from "@graview/core";
2
+ export interface Point {
3
+ readonly x: number;
4
+ readonly y: number;
5
+ }
6
+ export interface Box {
7
+ readonly x: number;
8
+ readonly y: number;
9
+ readonly width: number;
10
+ readonly height: number;
11
+ }
12
+ export interface Quadratic {
13
+ readonly p0: Point;
14
+ readonly c: Point;
15
+ readonly p1: Point;
16
+ }
17
+ /** The pieces of a polyline that lie outside every box. */
18
+ export declare function clipPolyline(points: readonly Point[], boxes: readonly Box[]): Point[][];
19
+ /**
20
+ * Two elbows, leaving and arriving along the LONGER way.
21
+ *
22
+ * Out along x to the middle, across, and in along x drew the last leg of a
23
+ * line from the focus down to a card in a band as a horizontal run at the
24
+ * card's own height — through the gap between it and its neighbour, so two
25
+ * chips in a row read as joined by a dashed line. Where the ends are further
26
+ * apart vertically than across, the route leaves and arrives vertically and
27
+ * crosses in the gutter halfway between: a line comes down INTO a card, and
28
+ * never lies along the row it sits in.
29
+ */
30
+ export declare function orthogonalPoints(from: Point, to: Point): Point[];
31
+ export declare const polylineD: (runs: readonly (readonly Point[])[]) => string;
32
+ /**
33
+ * A polyline with its corners rounded: each elbow becomes a short quadratic,
34
+ * so a road through the gutters reads as a road and not as a box drawn
35
+ * around whatever it went round.
36
+ */
37
+ export declare function roundedPolylineD(points: readonly Point[], radius: number): string;
38
+ /** Where a route is at parameter t, for sampling a hit corridor. */
39
+ export declare function routePoint(route: ConnectorRoute, q: Quadratic, t: number): Point;
40
+ /** The quadratic a route wants drawn: the scene's own for a curve, its chord for a straight line. */
41
+ export declare function routedQuadratic(route: ConnectorRoute, q: Quadratic): Quadratic;
42
+ /**
43
+ * A ROAD ALONG THE LATTICE. From altitude the ground is a 2:1 lattice and
44
+ * a road between two districts runs along its diagonals — one leg on each,
45
+ * with the elbow where they meet — so the roads lie on the same grid the
46
+ * districts stand on. Solving from + a·(2,1) + b·(−2,1) = to gives the two
47
+ * legs; a pair on one diagonal needs no elbow at all.
48
+ */
49
+ export declare function latticePoints(from: Point, to: Point): Point[];
50
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAcpD,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AACD,MAAM,WAAW,GAAG;IAClB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AACD,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC;IAClB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;CACpB;AAKD,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,CAqCvF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,GAAG,KAAK,EAAE,CAWhE;AAKD,eAAO,MAAM,SAAS,GAAI,MAAM,SAAS,CAAC,SAAS,KAAK,EAAE,CAAC,EAAE,KAAG,MAC0C,CAAC;AAE3G;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAiBjF;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,CAuBhF;AAED,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,EAAE,CAAC,EAAE,SAAS,GAAG,SAAS,CAG9E;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,GAAG,KAAK,EAAE,CAS7D"}
package/dist/routes.js ADDED
@@ -0,0 +1,150 @@
1
+ const inside = (p, boxes) => boxes.some((box) => p.x > box.x && p.x < box.x + box.width && p.y > box.y && p.y < box.y + box.height);
2
+ /** The pieces of a polyline that lie outside every box. */
3
+ export function clipPolyline(points, boxes) {
4
+ const runs = [];
5
+ let open = [];
6
+ const STEPS = 48;
7
+ for (let i = 0; i < points.length - 1; i++) {
8
+ const a = points[i];
9
+ const b = points[i + 1];
10
+ let wasOut = !inside(a, boxes);
11
+ if (wasOut && open.length === 0)
12
+ open.push(a);
13
+ for (let s = 1; s <= STEPS; s++) {
14
+ const t = s / STEPS;
15
+ const p = { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
16
+ const isOut = !inside(p, boxes);
17
+ if (isOut === wasOut)
18
+ continue;
19
+ // Refine the crossing between the last sample and this one.
20
+ let lo = (s - 1) / STEPS;
21
+ let hi = t;
22
+ for (let k = 0; k < 10; k++) {
23
+ const mid = (lo + hi) / 2;
24
+ const q = { x: a.x + (b.x - a.x) * mid, y: a.y + (b.y - a.y) * mid };
25
+ if (!inside(q, boxes) === wasOut)
26
+ lo = mid;
27
+ else
28
+ hi = mid;
29
+ }
30
+ const at = (lo + hi) / 2;
31
+ const crossing = { x: a.x + (b.x - a.x) * at, y: a.y + (b.y - a.y) * at };
32
+ if (isOut)
33
+ open = [crossing];
34
+ else {
35
+ open.push(crossing);
36
+ if (open.length >= 2)
37
+ runs.push(open);
38
+ open = [];
39
+ }
40
+ wasOut = isOut;
41
+ }
42
+ if (wasOut)
43
+ open.push(b);
44
+ }
45
+ if (open.length >= 2)
46
+ runs.push(open);
47
+ return runs;
48
+ }
49
+ /**
50
+ * Two elbows, leaving and arriving along the LONGER way.
51
+ *
52
+ * Out along x to the middle, across, and in along x drew the last leg of a
53
+ * line from the focus down to a card in a band as a horizontal run at the
54
+ * card's own height — through the gap between it and its neighbour, so two
55
+ * chips in a row read as joined by a dashed line. Where the ends are further
56
+ * apart vertically than across, the route leaves and arrives vertically and
57
+ * crosses in the gutter halfway between: a line comes down INTO a card, and
58
+ * never lies along the row it sits in.
59
+ */
60
+ export function orthogonalPoints(from, to) {
61
+ const dx = Math.abs(to.x - from.x);
62
+ const dy = Math.abs(to.y - from.y);
63
+ if (dy > dx) {
64
+ if (dx < 2)
65
+ return [from, to];
66
+ const midY = (from.y + to.y) / 2;
67
+ return [from, { x: from.x, y: midY }, { x: to.x, y: midY }, to];
68
+ }
69
+ const midX = (from.x + to.x) / 2;
70
+ if (Math.abs(to.x - from.x) < 2)
71
+ return [from, to];
72
+ return [from, { x: midX, y: from.y }, { x: midX, y: to.y }, to];
73
+ }
74
+ // Two decimals: a path is read by a person in the inspector, and sub-pixel noise is not information.
75
+ const at = (n) => Math.round(n * 100) / 100;
76
+ export const polylineD = (runs) => runs.map((run) => run.map((p, i) => `${i === 0 ? "M" : "L"} ${at(p.x)} ${at(p.y)}`).join(" ")).join(" ");
77
+ /**
78
+ * A polyline with its corners rounded: each elbow becomes a short quadratic,
79
+ * so a road through the gutters reads as a road and not as a box drawn
80
+ * around whatever it went round.
81
+ */
82
+ export function roundedPolylineD(points, radius) {
83
+ if (points.length < 3)
84
+ return polylineD([points]);
85
+ const parts = [`M ${at(points[0].x)} ${at(points[0].y)}`];
86
+ for (let i = 1; i < points.length - 1; i++) {
87
+ const prev = points[i - 1];
88
+ const corner = points[i];
89
+ const next = points[i + 1];
90
+ const inLen = Math.hypot(corner.x - prev.x, corner.y - prev.y);
91
+ const outLen = Math.hypot(next.x - corner.x, next.y - corner.y);
92
+ const r = Math.min(radius, inLen / 2, outLen / 2);
93
+ const a = { x: corner.x + ((prev.x - corner.x) / (inLen || 1)) * r, y: corner.y + ((prev.y - corner.y) / (inLen || 1)) * r };
94
+ const b = { x: corner.x + ((next.x - corner.x) / (outLen || 1)) * r, y: corner.y + ((next.y - corner.y) / (outLen || 1)) * r };
95
+ parts.push(`L ${at(a.x)} ${at(a.y)} Q ${at(corner.x)} ${at(corner.y)} ${at(b.x)} ${at(b.y)}`);
96
+ }
97
+ const last = points[points.length - 1];
98
+ parts.push(`L ${at(last.x)} ${at(last.y)}`);
99
+ return parts.join(" ");
100
+ }
101
+ /** Where a route is at parameter t, for sampling a hit corridor. */
102
+ export function routePoint(route, q, t) {
103
+ if (route === "orthogonal") {
104
+ const points = orthogonalPoints(q.p0, q.p1);
105
+ const lengths = points.slice(1).map((p, i) => Math.hypot(p.x - points[i].x, p.y - points[i].y));
106
+ const total = lengths.reduce((a, b) => a + b, 0) || 1;
107
+ let along = t * total;
108
+ for (let i = 0; i < lengths.length; i++) {
109
+ const length = lengths[i];
110
+ if (along <= length || i === lengths.length - 1) {
111
+ const u = length === 0 ? 0 : Math.min(1, along / length);
112
+ const a = points[i];
113
+ const b = points[i + 1];
114
+ return { x: a.x + (b.x - a.x) * u, y: a.y + (b.y - a.y) * u };
115
+ }
116
+ along -= length;
117
+ }
118
+ return q.p1;
119
+ }
120
+ const c = route === "straight" ? { x: (q.p0.x + q.p1.x) / 2, y: (q.p0.y + q.p1.y) / 2 } : q.c;
121
+ const a = (1 - t) * (1 - t);
122
+ const b = 2 * (1 - t) * t;
123
+ const d = t * t;
124
+ return { x: a * q.p0.x + b * c.x + d * q.p1.x, y: a * q.p0.y + b * c.y + d * q.p1.y };
125
+ }
126
+ /** The quadratic a route wants drawn: the scene's own for a curve, its chord for a straight line. */
127
+ export function routedQuadratic(route, q) {
128
+ if (route !== "straight")
129
+ return q;
130
+ return { ...q, c: { x: (q.p0.x + q.p1.x) / 2, y: (q.p0.y + q.p1.y) / 2 } };
131
+ }
132
+ /**
133
+ * A ROAD ALONG THE LATTICE. From altitude the ground is a 2:1 lattice and
134
+ * a road between two districts runs along its diagonals — one leg on each,
135
+ * with the elbow where they meet — so the roads lie on the same grid the
136
+ * districts stand on. Solving from + a·(2,1) + b·(−2,1) = to gives the two
137
+ * legs; a pair on one diagonal needs no elbow at all.
138
+ */
139
+ export function latticePoints(from, to) {
140
+ const dx = to.x - from.x;
141
+ const dy = to.y - from.y;
142
+ // Along (2,1): a; along (-2,1): b. dx = 2a − 2b, dy = a + b.
143
+ const a = (dx / 2 + dy) / 2;
144
+ const b = (dy - dx / 2) / 2;
145
+ if (Math.abs(a) < 1 || Math.abs(b) < 1)
146
+ return [from, to];
147
+ const elbow = { x: from.x + 2 * a, y: from.y + a };
148
+ return [from, elbow, to];
149
+ }
150
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type InterpolatedLayout, type Layout, type ViewState } from "@graview/layout";
2
+ import { type Dispatch, type SetStateAction } from "react";
3
+ export declare function useCameraFlights({ view, result, frame, panned, closer, screenId, setCamera, }: {
4
+ readonly view: ViewState;
5
+ /** The layout at rest, with the pan in it. */
6
+ readonly result: Layout;
7
+ /** The frame being drawn, mid-tween. */
8
+ readonly frame: InterpolatedLayout;
9
+ /** The person's pan plus the camera's offset: where the city is now. */
10
+ readonly panned: {
11
+ readonly x: number;
12
+ readonly y: number;
13
+ };
14
+ /** How much closer the camera has flown, when a picture was chosen from altitude. */
15
+ readonly closer: number;
16
+ /** The drive-in in this layout, if there is one: focusing it brings the camera to its plot. */
17
+ readonly screenId: string | null;
18
+ readonly setCamera: Dispatch<SetStateAction<{
19
+ x: number;
20
+ y: number;
21
+ }>>;
22
+ }): {
23
+ readonly gliding: () => boolean;
24
+ };
25
+ //# sourceMappingURL=scene-camera.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-camera.d.ts","sourceRoot":"","sources":["../src/scene-camera.ts"],"names":[],"mappings":"AACA,OAAO,EAA6C,KAAK,kBAAkB,EAAE,KAAK,MAAM,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAClI,OAAO,EAAqB,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAc9E,wBAAgB,gBAAgB,CAAC,EAC/B,IAAI,EACJ,MAAM,EACN,KAAK,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5D,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+FAA+F;IAC/F,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,cAAc,CAAC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CACxE,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAA;CAAE,CA6GtC"}
@@ -0,0 +1,130 @@
1
+ import { toIso } from "@graview/core";
2
+ import { cameraLimit, kindCardId, kindsOfAggregate } from "@graview/layout";
3
+ import { useEffect, useRef } from "react";
4
+ /*
5
+ * WHERE THE CAMERA GOES ON ITS OWN. The camera is not a move: its offset is
6
+ * derived from the focus rather than made by a hand, so it lives in the
7
+ * scene, added to whatever the person panned, and never in the URL. Two
8
+ * things fly it — a drive-in on the far side of a large city, which lights
9
+ * up off-screen unless the camera goes to it, and the descent from
10
+ * altitude, which lands in the village it left.
11
+ */
12
+ /** How long the focus stands where the village stood before the camera glides to rest. */
13
+ const GLIDE_AFTER_MS = 180;
14
+ export function useCameraFlights({ view, result, frame, panned, closer, screenId, setCamera, }) {
15
+ /*
16
+ * THE DESCENT LANDS IN THE VILLAGE. Double-clicking a district from
17
+ * altitude used to fly it to the stage's centre while the rest
18
+ * reorganised around it — the picture rearranging rather than you coming
19
+ * down. The plot is the pivot now: the stack's focus is landed where the
20
+ * village stood, so it grows in place, and the camera then glides to
21
+ * rest so the world slides to meet it. Every way down — the Down
22
+ * control, a marquee's showing, Escape — is a change of view from
23
+ * outside the scene, so the scene watches the view itself: `stood`
24
+ * remembers where each district's plot was in the last altitude frame.
25
+ */
26
+ const stood = useRef(new Map());
27
+ const wasAloft = useRef(view.overview ?? false);
28
+ const glide = useRef(null);
29
+ useEffect(() => {
30
+ if (!view.overview || !screenId || !result.city) {
31
+ if (wasAloft.current && !view.overview)
32
+ return; // the descent effect below owns the camera on the way down
33
+ setCamera((current) => (current.x === 0 && current.y === 0 ? current : { x: 0, y: 0 }));
34
+ return;
35
+ }
36
+ const screen = result.nodes.find((node) => node.id === screenId);
37
+ if (!screen)
38
+ return;
39
+ /*
40
+ * FLOWN CLOSER, the camera centres on the whole drive-in — the
41
+ * billboard and the village under it — rather than only keeping the
42
+ * picture inside the edge; a person chose that plot, and it is what
43
+ * they are looking at.
44
+ */
45
+ const village = closer > 1 && screen.screenOf ? result.nodes.find((node) => node.id === kindCardId(screen.screenOf)) : undefined;
46
+ const want = village
47
+ ? {
48
+ x: Math.min(screen.x, village.x),
49
+ y: Math.min(screen.y, village.y),
50
+ width: Math.max(screen.x + screen.width, village.x + village.width) - Math.min(screen.x, village.x),
51
+ height: Math.max(screen.y + screen.height, village.y + village.height) - Math.min(screen.y, village.y),
52
+ }
53
+ : screen;
54
+ const inside = want.x >= 0 && want.y >= 0 && want.x + want.width <= result.width && want.y + want.height <= result.height;
55
+ if (inside && !village)
56
+ return;
57
+ /*
58
+ * THE SMALLEST MOVE THAT BRINGS THE SCREEN IN. Centring it dragged the
59
+ * rest of the city off the far side — six districts fit the window and
60
+ * four of them left it — so the camera goes only as far as it must for
61
+ * the screen to clear the edge, and the rest stays where it was.
62
+ */
63
+ const EDGE = 24;
64
+ const shift = (start, size, span) => start < EDGE ? EDGE - start : start + size > span - EDGE ? span - EDGE - (start + size) : 0;
65
+ // The whole offset — the person's pan plus the camera — stays inside the
66
+ // camera limit, so the screen can be reached and nothing is dropped off the edge.
67
+ const limit = cameraLimit(result);
68
+ const pan = view.pan ?? { x: 0, y: 0 };
69
+ const wantedX = village ? panned.x + (result.width / 2 - (want.x + want.width / 2)) : panned.x + shift(want.x, want.width, result.width);
70
+ // Centred on the drive-in — but the PICTURE is what was chosen, so when the
71
+ // drive-in is taller than the window the picture's top stays in and the
72
+ // village hangs below rather than the picture losing its head.
73
+ const centredY = result.height / 2 - (want.y + want.height / 2);
74
+ const wantedY = village
75
+ ? panned.y + (screen.y + centredY < EDGE ? EDGE - screen.y : centredY)
76
+ : panned.y + shift(want.y, want.height, result.height);
77
+ // Flown closer, the billboard stands above the city's extent, which the
78
+ // limit does not know about: the camera goes where the drive-in is.
79
+ setCamera({
80
+ x: (village ? wantedX : Math.max(-limit.x, Math.min(limit.x, wantedX))) - pan.x,
81
+ y: (village ? wantedY : Math.max(-limit.y, Math.min(limit.y, wantedY))) - pan.y,
82
+ });
83
+ // Only when the focus lands, or the camera flies closer: a person's own pan afterwards is theirs.
84
+ }, [screenId, view.overview, closer]);
85
+ if (frame.city) {
86
+ // Remembered every altitude frame: where each plot's centre is on the canvas right now.
87
+ const remembered = new Map();
88
+ for (const node of frame.nodes) {
89
+ if (!node.plot || Math.round(node.plane) !== 2)
90
+ continue;
91
+ const centre = toIso(node.plot.col + node.plot.side / 2, node.plot.row + node.plot.side / 2, frame.city.cell);
92
+ remembered.set(node.id, { x: frame.city.originX + panned.x + centre.x, y: frame.city.originY + panned.y + centre.y });
93
+ }
94
+ stood.current = remembered;
95
+ }
96
+ useEffect(() => {
97
+ const aloft = view.overview ?? false;
98
+ const descending = wasAloft.current && !aloft;
99
+ wasAloft.current = aloft;
100
+ if (aloft && glide.current) {
101
+ // Back up before the glide landed: the altitude camera owns the offset now.
102
+ clearTimeout(glide.current);
103
+ glide.current = null;
104
+ }
105
+ if (!descending)
106
+ return;
107
+ const kind = view.focusId ? kindsOfAggregate(view.focusId)[0] : undefined;
108
+ const from = kind ? stood.current.get(kindCardId(kind)) : undefined;
109
+ const focus = result.nodes.find((node) => node.id === view.focusId);
110
+ if (!from || !focus) {
111
+ setCamera({ x: 0, y: 0 });
112
+ return;
113
+ }
114
+ // Land the focus where the village stood; then let go, and the world slides to meet it.
115
+ setCamera({ x: from.x - (focus.x + focus.width / 2), y: from.y - (focus.y + focus.height / 2) });
116
+ if (glide.current)
117
+ clearTimeout(glide.current);
118
+ glide.current = setTimeout(() => {
119
+ glide.current = null;
120
+ setCamera({ x: 0, y: 0 });
121
+ }, GLIDE_AFTER_MS);
122
+ // Only when the altitude changes: a glide in progress is not restarted by what it moves.
123
+ }, [view.overview]);
124
+ useEffect(() => () => {
125
+ if (glide.current)
126
+ clearTimeout(glide.current);
127
+ }, []);
128
+ return { gliding: () => glide.current !== null };
129
+ }
130
+ //# sourceMappingURL=scene-camera.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-camera.js","sourceRoot":"","sources":["../src/scene-camera.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ import { type ViewState } from "@graview/layout";
2
+ import { type PointerEvent as ReactPointerEvent, type RefObject } from "react";
3
+ import type { SceneNode } from "./scene-root.js";
4
+ /** A district where the hand has put it, in the unpanned space a pin is stored in. */
5
+ export interface Held {
6
+ readonly id: string;
7
+ readonly x: number;
8
+ readonly y: number;
9
+ }
10
+ /**
11
+ * THE DISTRICT UNDER THE HAND, placed in the scene while it is dragged —
12
+ * at most once a frame, since pointer events arrive faster than frames are
13
+ * drawn — and handed back on release to be written into the view once.
14
+ */
15
+ export declare function useHeldDistrict(): {
16
+ held: Held | null;
17
+ place: (next: Held) => void;
18
+ release: () => Held | null;
19
+ };
20
+ /**
21
+ * THE HAND MOVES THE PICTURE; ONLY LETTING GO MOVES THE WORLD.
22
+ *
23
+ * While a hand is on it, the offset it has made is painted straight onto
24
+ * the world's layers as a transform, once per animation frame, outside
25
+ * React entirely. Letting go writes it into the view as a pan, and the
26
+ * transform is cleared once that has been committed, so the picture never
27
+ * jumps back for a frame. `settled` is told when the gesture is over — the
28
+ * world already where the hand left it, so nothing tweens its way there.
29
+ *
30
+ * The GPU path keeps the old road: its stage is a `layoutsubtree` canvas,
31
+ * and combining that with CSS transforms crashes the renderer. It is not
32
+ * the default path and it is not the measured one.
33
+ */
34
+ export declare function useWorldShift({ stage, pan, setView, settled, }: {
35
+ readonly stage: RefObject<HTMLElement | null>;
36
+ /** The view's pan: the transform comes off when this has taken the offset. */
37
+ readonly pan: ViewState["pan"];
38
+ readonly setView: (update: (current: ViewState) => ViewState) => void;
39
+ readonly settled: () => void;
40
+ }): {
41
+ shiftTo: (wanted: {
42
+ x: number;
43
+ y: number;
44
+ }, from: {
45
+ x: number;
46
+ y: number;
47
+ }) => void;
48
+ settle: () => boolean;
49
+ settling: RefObject<boolean>;
50
+ offset: () => {
51
+ x: number;
52
+ y: number;
53
+ };
54
+ };
55
+ /**
56
+ * THE GESTURES THEMSELVES. The threshold is what keeps a click a click:
57
+ * below it nothing has happened and the pointer-up is an ordinary
58
+ * selection; above it the gesture owns the pointer and the click that
59
+ * follows is swallowed.
60
+ */
61
+ export declare function useSceneDrag({ view, panned, limit, panWithin, moveByTransform, setView, setDragging, noteMoved, shift, district, }: {
62
+ readonly view: ViewState;
63
+ /** The pan baked into the drawn cards: a card's pin is stored without it. */
64
+ readonly panned: {
65
+ readonly x: number;
66
+ readonly y: number;
67
+ };
68
+ /** How far the camera may go, for the frame as it is now. */
69
+ readonly limit: () => {
70
+ readonly x: number;
71
+ readonly y: number;
72
+ };
73
+ readonly panWithin: (limit: {
74
+ x: number;
75
+ y: number;
76
+ }, wanted: {
77
+ x: number;
78
+ y: number;
79
+ }) => {
80
+ x: number;
81
+ y: number;
82
+ };
83
+ /** The DOM path paints the pan as a transform; the GPU path writes the view. */
84
+ readonly moveByTransform: boolean;
85
+ readonly setView: (update: (current: ViewState) => ViewState) => void;
86
+ readonly setDragging: (dragging: boolean) => void;
87
+ readonly noteMoved: () => void;
88
+ readonly shift: ReturnType<typeof useWorldShift>;
89
+ readonly district: ReturnType<typeof useHeldDistrict>;
90
+ }): {
91
+ onGroundDown: (event: ReactPointerEvent<HTMLDivElement>) => void;
92
+ onCardDown: (node: SceneNode, event: ReactPointerEvent<HTMLElement>) => void;
93
+ onDragMove: (event: ReactPointerEvent<HTMLElement>) => void;
94
+ onDragUp: () => void;
95
+ swallow: RefObject<boolean>;
96
+ };
97
+ /**
98
+ * THE WHEEL AND THE PINCH. `zoomAbout` and `panBy` are filled in by the
99
+ * scene once it knows its city; the listeners call through them, so they
100
+ * are attached once rather than on every zoom.
101
+ */
102
+ export declare function useWheelAndPinch({ stage, view, setView, }: {
103
+ readonly stage: RefObject<HTMLElement | null>;
104
+ readonly view: ViewState;
105
+ readonly setView: (next: ViewState) => void;
106
+ }): {
107
+ zoomAbout: RefObject<(factor: number, clientX?: number, clientY?: number) => void>;
108
+ panBy: RefObject<(dx: number, dy: number) => void>;
109
+ };
110
+ //# sourceMappingURL=scene-hand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-hand.d.ts","sourceRoot":"","sources":["../src/scene-hand.ts"],"names":[],"mappings":"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"}