@graview/layout 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +96 -0
- package/README.md +20 -0
- package/dist/band.d.ts +103 -0
- package/dist/band.d.ts.map +1 -0
- package/dist/band.js +344 -0
- package/dist/band.js.map +1 -0
- package/dist/city.d.ts +161 -0
- package/dist/city.d.ts.map +1 -0
- package/dist/city.js +319 -0
- package/dist/city.js.map +1 -0
- package/dist/ids.d.ts +79 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +115 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/interpolate.d.ts +27 -0
- package/dist/interpolate.d.ts.map +1 -0
- package/dist/interpolate.js +217 -0
- package/dist/interpolate.js.map +1 -0
- package/dist/label-fit.d.ts +115 -0
- package/dist/label-fit.d.ts.map +1 -0
- package/dist/label-fit.js +162 -0
- package/dist/label-fit.js.map +1 -0
- package/dist/layout.d.ts +99 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +1391 -0
- package/dist/layout.js.map +1 -0
- package/dist/rank.d.ts +35 -0
- package/dist/rank.d.ts.map +1 -0
- package/dist/rank.js +84 -0
- package/dist/rank.js.map +1 -0
- package/dist/related.d.ts +42 -0
- package/dist/related.d.ts.map +1 -0
- package/dist/related.js +207 -0
- package/dist/related.js.map +1 -0
- package/dist/types.d.ts +404 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +27 -0
- package/dist/types.js.map +1 -0
- package/dist/view-state.d.ts +189 -0
- package/dist/view-state.d.ts.map +1 -0
- package/dist/view-state.js +350 -0
- package/dist/view-state.js.map +1 -0
- package/package.json +54 -0
package/dist/city.d.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { type AnySchema, type CityMap, type Plot } from "@graview/core";
|
|
2
|
+
import type { CityFrame, Layout } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* THE CITY AT ALTITUDE: districts on the lattice, one uniform scale.
|
|
5
|
+
*
|
|
6
|
+
* The map is the declaration's (`cityMap`): a kind's plot never moves
|
|
7
|
+
* because of what happened today or how wide the window is. What this
|
|
8
|
+
* file decides is only how the lattice meets the canvas — ONE scale and
|
|
9
|
+
* ONE translate, so the city keeps its shape at every width, rather than
|
|
10
|
+
* the per-axis stretch a ring needed to fill a wide canvas — and how big
|
|
11
|
+
* each district card is drawn: nearer rows larger, as the ring drew the
|
|
12
|
+
* near side of the ellipse larger, with the reader's unit honoured and
|
|
13
|
+
* given back only as far as the cards need to keep off each other.
|
|
14
|
+
*/
|
|
15
|
+
export interface CityCard {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly kind: string;
|
|
18
|
+
/** Members standing today, for the plot's side. */
|
|
19
|
+
readonly count: number;
|
|
20
|
+
/** Extra height this card asks for, opened in place. */
|
|
21
|
+
readonly opened: number;
|
|
22
|
+
/**
|
|
23
|
+
* The least of that the listing gives up to: a few rows it keeps however
|
|
24
|
+
* crowded the city is. Shrunk to nothing, an opened district of four kinds
|
|
25
|
+
* listed one and counted three — opening it answered nothing.
|
|
26
|
+
*/
|
|
27
|
+
readonly openedMin?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Extra height for a drive-in's marquee — the showings drawn as buttons
|
|
30
|
+
* under the nameplate. Not given back like the listing: a marquee
|
|
31
|
+
* clipped is a button nobody can press.
|
|
32
|
+
*/
|
|
33
|
+
readonly marquee?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface PlacedCard {
|
|
36
|
+
readonly id: string;
|
|
37
|
+
readonly x: number;
|
|
38
|
+
readonly y: number;
|
|
39
|
+
readonly width: number;
|
|
40
|
+
readonly height: number;
|
|
41
|
+
readonly depth: number;
|
|
42
|
+
readonly plot: Plot;
|
|
43
|
+
}
|
|
44
|
+
/** Two drawn boxes sharing ground, with a little air required between them. */
|
|
45
|
+
export declare function collides(a: {
|
|
46
|
+
x: number;
|
|
47
|
+
y: number;
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
}, b: {
|
|
51
|
+
x: number;
|
|
52
|
+
y: number;
|
|
53
|
+
width: number;
|
|
54
|
+
height: number;
|
|
55
|
+
}, air?: number): boolean;
|
|
56
|
+
export declare function placeCity(cards: readonly CityCard[], schema: AnySchema, base: {
|
|
57
|
+
readonly width: number;
|
|
58
|
+
readonly height: number;
|
|
59
|
+
}, canvas: {
|
|
60
|
+
readonly width: number;
|
|
61
|
+
readonly height: number;
|
|
62
|
+
}, inset?: {
|
|
63
|
+
readonly left?: number;
|
|
64
|
+
readonly right?: number;
|
|
65
|
+
}, options?: {
|
|
66
|
+
readonly order?: readonly string[];
|
|
67
|
+
readonly plots?: Readonly<Record<string, {
|
|
68
|
+
col: number;
|
|
69
|
+
row: number;
|
|
70
|
+
}>>;
|
|
71
|
+
readonly scale?: number;
|
|
72
|
+
/** The height a card is never drawn under, whatever the canvas — the layout's own floor. */
|
|
73
|
+
readonly minHeight?: number;
|
|
74
|
+
/** A factor on the fitted cell: the camera brought closer, the city allowed past the window. */
|
|
75
|
+
readonly zoom?: number;
|
|
76
|
+
/** The pan baked into the cards, recorded on the frame so the ground can tween with them. */
|
|
77
|
+
readonly pan?: {
|
|
78
|
+
readonly x: number;
|
|
79
|
+
readonly y: number;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Ground already taken — the picture standing in the middle from
|
|
83
|
+
* altitude. No district is laid under it: the city slides aside, and
|
|
84
|
+
* grows, until every district has ground of its own.
|
|
85
|
+
*/
|
|
86
|
+
readonly avoid?: readonly {
|
|
87
|
+
readonly x: number;
|
|
88
|
+
readonly y: number;
|
|
89
|
+
readonly width: number;
|
|
90
|
+
readonly height: number;
|
|
91
|
+
}[];
|
|
92
|
+
}): {
|
|
93
|
+
readonly placed: readonly PlacedCard[];
|
|
94
|
+
readonly frame: CityFrame;
|
|
95
|
+
readonly map: CityMap;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* HOW FAR THE CAMERA MAY GO. A little way over a picture that fits — losing
|
|
99
|
+
* the scene off the edge of its own window is not panning, it is dropping
|
|
100
|
+
* it — and as far as the city reaches when the city is bigger than the
|
|
101
|
+
* window: every district is reachable, none is lost. Symmetric about the
|
|
102
|
+
* centre so the same limit serves both directions, and read by the scene
|
|
103
|
+
* and by the tests alike, so "reachable" means one thing.
|
|
104
|
+
*/
|
|
105
|
+
export declare function cameraLimit(result: {
|
|
106
|
+
readonly width: number;
|
|
107
|
+
readonly height: number;
|
|
108
|
+
readonly city?: CityFrame;
|
|
109
|
+
}): {
|
|
110
|
+
readonly x: number;
|
|
111
|
+
readonly y: number;
|
|
112
|
+
};
|
|
113
|
+
/** A district the window does not reach, the edge it lies past, and the pan that brings it in. */
|
|
114
|
+
export interface PastTheEdge {
|
|
115
|
+
/** The district's card: `kind:<kind>`. */
|
|
116
|
+
readonly id: string;
|
|
117
|
+
readonly kind: string;
|
|
118
|
+
readonly side: "left" | "right" | "top" | "bottom";
|
|
119
|
+
/** Where along that edge it lies, clamped to the canvas: y for left and right, x for top and bottom. */
|
|
120
|
+
readonly along: number;
|
|
121
|
+
/** The move that brings it a quarter of the way in from that edge. */
|
|
122
|
+
readonly by: {
|
|
123
|
+
readonly x: number;
|
|
124
|
+
readonly y: number;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* THE EDGE SAYS WHAT IS PAST IT. A city wider than the window is reached
|
|
129
|
+
* by panning, and a district has a corner of its own that no phone is
|
|
130
|
+
* allowed to move — so on a 390-pixel phone the conference's Topics and
|
|
131
|
+
* Staff stood wholly off the canvas, with nothing on it saying they were
|
|
132
|
+
* there or which way to go. Every district whose middle is past the edge
|
|
133
|
+
* is named here with the side it lies past, so the scene can put a sign on
|
|
134
|
+
* that edge, and with the pan that brings it into the window.
|
|
135
|
+
*/
|
|
136
|
+
export declare function districtsPastTheEdge(result: Pick<Layout, "nodes" | "width" | "height" | "city">): readonly PastTheEdge[];
|
|
137
|
+
/**
|
|
138
|
+
* THE PAN THAT KEEPS THE POINT UNDER THE POINTER STILL when the city is
|
|
139
|
+
* zoomed. The city is placed about the canvas's centre, so scaling its cell
|
|
140
|
+
* by `ratio` moves every point away from (or toward) the centre; the pan
|
|
141
|
+
* moves the opposite way by the pointer's share of that, and what was under
|
|
142
|
+
* the finger stays under it. Whole offset in, pan out: the camera's own
|
|
143
|
+
* flight is part of where the city is, and only the pan is the person's.
|
|
144
|
+
*/
|
|
145
|
+
export declare function panForZoom(pan: {
|
|
146
|
+
readonly x: number;
|
|
147
|
+
readonly y: number;
|
|
148
|
+
}, camera: {
|
|
149
|
+
readonly x: number;
|
|
150
|
+
readonly y: number;
|
|
151
|
+
}, pointer: {
|
|
152
|
+
readonly x: number;
|
|
153
|
+
readonly y: number;
|
|
154
|
+
}, centre: {
|
|
155
|
+
readonly x: number;
|
|
156
|
+
readonly y: number;
|
|
157
|
+
}, ratio: number): {
|
|
158
|
+
readonly x: number;
|
|
159
|
+
readonly y: number;
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=city.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"city.d.ts","sourceRoot":"","sources":["../src/city.ts"],"names":[],"mappings":"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"}
|
package/dist/city.js
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { cityExtent, cityMap, toIso } from "@graview/core";
|
|
2
|
+
/** Two drawn boxes sharing ground, with a little air required between them. */
|
|
3
|
+
export function collides(a, b, air = 6) {
|
|
4
|
+
return (a.x < b.x + b.width + air &&
|
|
5
|
+
b.x < a.x + a.width + air &&
|
|
6
|
+
a.y < b.y + b.height + air &&
|
|
7
|
+
b.y < a.y + a.height + air);
|
|
8
|
+
}
|
|
9
|
+
/** The centre of a plot's diamond, in lattice pixels at `cell`. */
|
|
10
|
+
const centreOf = (plot, cell) => toIso(plot.col + plot.side / 2, plot.row + plot.side / 2, cell);
|
|
11
|
+
export function placeCity(cards, schema, base, canvas, inset = {}, options = {}) {
|
|
12
|
+
const counts = {};
|
|
13
|
+
for (const card of cards)
|
|
14
|
+
counts[card.kind] = card.count;
|
|
15
|
+
const map = cityMap(schema, {
|
|
16
|
+
...(options.order ? { order: options.order } : {}),
|
|
17
|
+
counts,
|
|
18
|
+
...(options.plots ? { plots: options.plots } : {}),
|
|
19
|
+
});
|
|
20
|
+
const left = inset.left ?? 0;
|
|
21
|
+
const span = canvas.width - left - (inset.right ?? 0);
|
|
22
|
+
const cx = left + span / 2;
|
|
23
|
+
const cy = canvas.height * 0.53;
|
|
24
|
+
/*
|
|
25
|
+
* ONE SCALE. The map's bounding diamond, at one pixel per cell, is
|
|
26
|
+
* fitted into the room the canvas has once a card's own size is taken
|
|
27
|
+
* off each edge — a card is centred on its plot and must not leave the
|
|
28
|
+
* canvas. The cell is then the same on both axes, which is the whole
|
|
29
|
+
* point: a city that was squashed to fit a wide window and stretched to
|
|
30
|
+
* fit a tall one had no shape of its own.
|
|
31
|
+
*/
|
|
32
|
+
const extent = cityExtent(map);
|
|
33
|
+
const corners = [
|
|
34
|
+
toIso(extent.minCol, extent.minRow, 1),
|
|
35
|
+
toIso(extent.maxCol, extent.minRow, 1),
|
|
36
|
+
toIso(extent.minCol, extent.maxRow, 1),
|
|
37
|
+
toIso(extent.maxCol, extent.maxRow, 1),
|
|
38
|
+
];
|
|
39
|
+
const minX = Math.min(...corners.map((c) => c.x));
|
|
40
|
+
const maxX = Math.max(...corners.map((c) => c.x));
|
|
41
|
+
const minY = Math.min(...corners.map((c) => c.y));
|
|
42
|
+
const maxY = Math.max(...corners.map((c) => c.y));
|
|
43
|
+
const spread = { x: Math.max(1, maxX - minX), y: Math.max(0.5, maxY - minY) };
|
|
44
|
+
const roomX = Math.max(40, span - base.width * 1.1);
|
|
45
|
+
const roomY = Math.max(24, canvas.height * 0.62 - base.height * 1.1);
|
|
46
|
+
const fitted = Math.max(18, Math.min(160, roomX / spread.x, roomY / spread.y));
|
|
47
|
+
const scale = options.scale ?? 1;
|
|
48
|
+
const minHeight = options.minHeight ?? 0;
|
|
49
|
+
const avoid = options.avoid ?? [];
|
|
50
|
+
/** Where the whole city is slid to stand beside the rails rather than under them (see below). */
|
|
51
|
+
let nudge = 0;
|
|
52
|
+
const at = (cell, asked, openedShare = 1, shift = { x: 0, y: 0 }) => {
|
|
53
|
+
const originX = cx - ((minX + maxX) / 2) * cell + shift.x + nudge;
|
|
54
|
+
const originY = cy - ((minY + maxY) / 2) * cell + shift.y;
|
|
55
|
+
const size = { width: base.width * asked, height: base.height * asked };
|
|
56
|
+
const rows = cards.map((card) => centreOf(map.get(card.kind), cell).y);
|
|
57
|
+
const lowest = Math.max(...rows);
|
|
58
|
+
const highest = Math.min(...rows);
|
|
59
|
+
return cards.map((card) => {
|
|
60
|
+
const plot = map.get(card.kind);
|
|
61
|
+
const centre = centreOf(plot, cell);
|
|
62
|
+
/*
|
|
63
|
+
* NEARNESS FROM THE ROW. Lower on the ground is nearer the viewer,
|
|
64
|
+
* exactly as the bottom of the ring was: 1 there, 0 at the top, and
|
|
65
|
+
* the depth number everything else reads (`1 − near·0.65`) is
|
|
66
|
+
* unchanged so the plane styles and the altitude opacity are too.
|
|
67
|
+
*/
|
|
68
|
+
const near = lowest === highest ? 0.5 : (centre.y - highest) / (lowest - highest);
|
|
69
|
+
const grow = 0.85 + near * 0.45;
|
|
70
|
+
const width = size.width * grow;
|
|
71
|
+
const base = Math.max(minHeight, size.height * grow);
|
|
72
|
+
const height = base + (card.marquee ?? 0) + (card.opened > 0 ? Math.max(card.openedMin ?? 0, card.opened * openedShare) : 0);
|
|
73
|
+
/*
|
|
74
|
+
* NOT HELD INSIDE THE CANVAS. The ring pushed its near card back in
|
|
75
|
+
* from the edge; a city has a shape, and a district pushed off its
|
|
76
|
+
* corner to fit a phone is a district on the wrong corner. A city
|
|
77
|
+
* wider than the window is reached by panning, which the camera
|
|
78
|
+
* bounds to the map's extent for exactly this reason.
|
|
79
|
+
*/
|
|
80
|
+
/*
|
|
81
|
+
* The NAMEPLATE is centred on the plot; what hangs under it — a
|
|
82
|
+
* marquee, an opened listing — grows DOWNWARD, so the top of the card
|
|
83
|
+
* stays where the plot's far half is, and a screen standing at the
|
|
84
|
+
* far edge is never covered by its own district's growth.
|
|
85
|
+
*/
|
|
86
|
+
return {
|
|
87
|
+
id: card.id,
|
|
88
|
+
x: originX + centre.x - width / 2,
|
|
89
|
+
y: originY + centre.y - base / 2,
|
|
90
|
+
width,
|
|
91
|
+
height,
|
|
92
|
+
depth: 1 - near * 0.65,
|
|
93
|
+
plot,
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
const crowded = (placed) => placed.some((one, index) => placed.some((other, index2) => index2 !== index && collides(one, other))) ||
|
|
98
|
+
placed.some((one) => avoid.some((box) => collides(one, box)));
|
|
99
|
+
/*
|
|
100
|
+
* The reader's unit is given back first, down to the size a card has
|
|
101
|
+
* always been; and when the cards still stand in each other at that
|
|
102
|
+
* size, the CITY grows — the cell widens until every district has its
|
|
103
|
+
* own ground — rather than the cards shrinking below what their names
|
|
104
|
+
* need. A district's legibility is not the window's to take.
|
|
105
|
+
*/
|
|
106
|
+
/*
|
|
107
|
+
* THE CITY SLIDES ASIDE for the picture in the middle, when there is one.
|
|
108
|
+
* A district on the map's own centre stands exactly where the live view
|
|
109
|
+
* stands, and no amount of growing moves it — scaling about the centre
|
|
110
|
+
* keeps the centre where it is. So the map is tried in place first, and
|
|
111
|
+
* then shifted: by the width of what it must clear, right, left, down,
|
|
112
|
+
* up, and the diagonals — the first shift with every district on ground
|
|
113
|
+
* of its own is the one kept. No picture in the middle means no shift.
|
|
114
|
+
*/
|
|
115
|
+
const shifts = (cell) => {
|
|
116
|
+
if (avoid.length === 0)
|
|
117
|
+
return [{ x: 0, y: 0 }];
|
|
118
|
+
const dx = Math.max(...avoid.map((box) => box.width)) / 2 + cell;
|
|
119
|
+
const dy = Math.max(...avoid.map((box) => box.height)) / 2 + cell / 2;
|
|
120
|
+
const out = [{ x: 0, y: 0 }];
|
|
121
|
+
for (const share of [0.5, 0.75, 1, 1.25]) {
|
|
122
|
+
const sx = dx * share;
|
|
123
|
+
const sy = dy * share;
|
|
124
|
+
out.push({ x: sx, y: 0 }, { x: -sx, y: 0 }, { x: 0, y: sy }, { x: 0, y: -sy }, { x: sx, y: sy }, { x: -sx, y: sy }, { x: sx, y: -sy }, { x: -sx, y: -sy });
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
};
|
|
128
|
+
/** How much of the city is off the canvas: the shift that shows the most is the one kept. */
|
|
129
|
+
const right = canvas.width - (inset.right ?? 0);
|
|
130
|
+
const outside = (placed) => placed.reduce((sum, card) => {
|
|
131
|
+
const visibleW = Math.max(0, Math.min(card.x + card.width, canvas.width) - Math.max(card.x, 0));
|
|
132
|
+
const visibleH = Math.max(0, Math.min(card.y + card.height, canvas.height) - Math.max(card.y, 0));
|
|
133
|
+
return sum + card.width * card.height - visibleW * visibleH;
|
|
134
|
+
}, 0);
|
|
135
|
+
const settle = (cell, asked, openedShare) => {
|
|
136
|
+
let best;
|
|
137
|
+
let fallback;
|
|
138
|
+
for (const shift of shifts(cell)) {
|
|
139
|
+
const placed = at(cell, asked, openedShare, shift);
|
|
140
|
+
if (crowded(placed)) {
|
|
141
|
+
fallback ??= { placed, shift };
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const off = outside(placed);
|
|
145
|
+
if (!best || off < best.off - 0.5)
|
|
146
|
+
best = { placed, shift, off };
|
|
147
|
+
}
|
|
148
|
+
return best ?? fallback;
|
|
149
|
+
};
|
|
150
|
+
let cell = fitted;
|
|
151
|
+
let asked = scale;
|
|
152
|
+
let openedShare = 1;
|
|
153
|
+
let settled = settle(cell, asked, openedShare);
|
|
154
|
+
while (crowded(settled.placed) && asked > 1.001) {
|
|
155
|
+
asked = Math.max(1, asked - 0.05);
|
|
156
|
+
settled = settle(cell, asked, openedShare);
|
|
157
|
+
}
|
|
158
|
+
/*
|
|
159
|
+
* An opened district's listing is the luxury and the city is the picture:
|
|
160
|
+
* in a short canvas the listing gives up its room before the city has to
|
|
161
|
+
* grow past the window, exactly as the ring's listing gave up its room
|
|
162
|
+
* before the ring gave up being a ring.
|
|
163
|
+
*/
|
|
164
|
+
while (crowded(settled.placed) && openedShare > 0.3) {
|
|
165
|
+
openedShare = Math.max(0.3, openedShare - 0.1);
|
|
166
|
+
settled = settle(cell, asked, openedShare);
|
|
167
|
+
}
|
|
168
|
+
/*
|
|
169
|
+
* A SMALLER CITY BEFORE A CITY OFF THE EDGE. With a picture standing in
|
|
170
|
+
* the middle, the map fitted to the room may not stand beside it and
|
|
171
|
+
* stay on the canvas; a tighter lattice usually can, and the districts
|
|
172
|
+
* keep their size — only the streets between them shorten. So the cell
|
|
173
|
+
* is tried smaller, down to where the districts would touch, and the
|
|
174
|
+
* largest cell whose every district is on the canvas is the one kept.
|
|
175
|
+
* Only when no cell will do does the city grow past the window.
|
|
176
|
+
*/
|
|
177
|
+
if (crowded(settled.placed) || outside(settled.placed) > 0) {
|
|
178
|
+
let best = crowded(settled.placed) ? undefined : { cell, settled, off: outside(settled.placed) };
|
|
179
|
+
for (let share = 0.9; share >= 0.3; share -= 0.1) {
|
|
180
|
+
const tighter = fitted * share;
|
|
181
|
+
const trial = settle(tighter, asked, openedShare);
|
|
182
|
+
if (crowded(trial.placed))
|
|
183
|
+
continue;
|
|
184
|
+
const off = outside(trial.placed);
|
|
185
|
+
if (!best || off < best.off - 0.5)
|
|
186
|
+
best = { cell: tighter, settled: trial, off };
|
|
187
|
+
if (off === 0)
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
if (best) {
|
|
191
|
+
cell = best.cell;
|
|
192
|
+
settled = best.settled;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (let grown = 0; crowded(settled.placed) && grown < 80; grown++) {
|
|
196
|
+
cell *= 1.06;
|
|
197
|
+
settled = settle(cell, asked, openedShare);
|
|
198
|
+
}
|
|
199
|
+
/*
|
|
200
|
+
* BESIDE THE RAILS, NOT UNDER THEM. The map is centred on its lattice's
|
|
201
|
+
* bounding diamond, and the districts are not: a card is centred on its
|
|
202
|
+
* plot and the plots do not fill the diamond, so a city grown just wide
|
|
203
|
+
* enough for its names stood twenty-five pixels left of the room it
|
|
204
|
+
* fitted — and the leftmost district under the inspector. When the
|
|
205
|
+
* districts fit between the rails, the city slides the least distance
|
|
206
|
+
* that puts every one of them there; when they do not, the camera pans
|
|
207
|
+
* to them, as before.
|
|
208
|
+
*/
|
|
209
|
+
// With a picture standing in the middle the city has already stepped aside for it, and that placement stands.
|
|
210
|
+
if (avoid.length === 0) {
|
|
211
|
+
const lowX = Math.min(...settled.placed.map((card) => card.x));
|
|
212
|
+
const highX = Math.max(...settled.placed.map((card) => card.x + card.width));
|
|
213
|
+
const slide = highX - lowX > right - left ? 0 : lowX < left ? left - lowX : highX > right ? right - highX : 0;
|
|
214
|
+
if (slide !== 0) {
|
|
215
|
+
nudge = slide;
|
|
216
|
+
const slid = at(cell, asked, openedShare, settled.shift);
|
|
217
|
+
if (crowded(slid))
|
|
218
|
+
nudge = 0;
|
|
219
|
+
else
|
|
220
|
+
settled = { placed: slid, shift: settled.shift };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/*
|
|
224
|
+
* FLYING CLOSER. The fit above is the whole map in the window; a zoom is
|
|
225
|
+
* the camera brought in afterwards, so the map keeps its shape and only
|
|
226
|
+
* the cell grows — the city may run past the window, and the camera
|
|
227
|
+
* pans to reach it.
|
|
228
|
+
*/
|
|
229
|
+
if (options.zoom && options.zoom !== 1) {
|
|
230
|
+
cell *= options.zoom;
|
|
231
|
+
nudge *= options.zoom;
|
|
232
|
+
settled = settle(cell, asked, openedShare);
|
|
233
|
+
}
|
|
234
|
+
const placed = settled.placed;
|
|
235
|
+
const originX = cx - ((minX + maxX) / 2) * cell + settled.shift.x + nudge;
|
|
236
|
+
const originY = cy - ((minY + maxY) / 2) * cell + settled.shift.y;
|
|
237
|
+
const frame = {
|
|
238
|
+
cell,
|
|
239
|
+
originX,
|
|
240
|
+
originY,
|
|
241
|
+
pan: options.pan ?? { x: 0, y: 0 },
|
|
242
|
+
extent: {
|
|
243
|
+
x: originX + minX * cell,
|
|
244
|
+
y: originY + minY * cell,
|
|
245
|
+
width: spread.x * cell,
|
|
246
|
+
height: spread.y * cell,
|
|
247
|
+
},
|
|
248
|
+
openedShare,
|
|
249
|
+
};
|
|
250
|
+
return { placed, frame, map };
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* HOW FAR THE CAMERA MAY GO. A little way over a picture that fits — losing
|
|
254
|
+
* the scene off the edge of its own window is not panning, it is dropping
|
|
255
|
+
* it — and as far as the city reaches when the city is bigger than the
|
|
256
|
+
* window: every district is reachable, none is lost. Symmetric about the
|
|
257
|
+
* centre so the same limit serves both directions, and read by the scene
|
|
258
|
+
* and by the tests alike, so "reachable" means one thing.
|
|
259
|
+
*/
|
|
260
|
+
export function cameraLimit(result) {
|
|
261
|
+
const slack = { x: result.width * 0.45, y: result.height * 0.45 };
|
|
262
|
+
if (!result.city)
|
|
263
|
+
return slack;
|
|
264
|
+
const { extent } = result.city;
|
|
265
|
+
const margin = 24;
|
|
266
|
+
return {
|
|
267
|
+
x: Math.max(slack.x, extent.x + extent.width - result.width + margin, -extent.x + margin),
|
|
268
|
+
y: Math.max(slack.y, extent.y + extent.height - result.height + margin, -extent.y + margin),
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/** How far in from an edge a district brought into the window stands, at the least: room for its nameplate's height. */
|
|
272
|
+
const EDGE_CLEAR = 48;
|
|
273
|
+
/**
|
|
274
|
+
* THE EDGE SAYS WHAT IS PAST IT. A city wider than the window is reached
|
|
275
|
+
* by panning, and a district has a corner of its own that no phone is
|
|
276
|
+
* allowed to move — so on a 390-pixel phone the conference's Topics and
|
|
277
|
+
* Staff stood wholly off the canvas, with nothing on it saying they were
|
|
278
|
+
* there or which way to go. Every district whose middle is past the edge
|
|
279
|
+
* is named here with the side it lies past, so the scene can put a sign on
|
|
280
|
+
* that edge, and with the pan that brings it into the window.
|
|
281
|
+
*/
|
|
282
|
+
export function districtsPastTheEdge(result) {
|
|
283
|
+
if (!result.city)
|
|
284
|
+
return [];
|
|
285
|
+
const { width, height } = result;
|
|
286
|
+
const out = [];
|
|
287
|
+
for (const node of result.nodes) {
|
|
288
|
+
if (!node.id.startsWith("kind:") || Math.round(node.plane) !== 2)
|
|
289
|
+
continue;
|
|
290
|
+
const cx = node.x + node.width / 2;
|
|
291
|
+
const cy = node.y + node.height / 2;
|
|
292
|
+
const side = cx < 0 ? "left" : cx > width ? "right" : cy < 0 ? "top" : cy > height ? "bottom" : null;
|
|
293
|
+
if (!side)
|
|
294
|
+
continue;
|
|
295
|
+
const across = side === "left" || side === "right";
|
|
296
|
+
const along = across ? Math.max(0, Math.min(height, cy)) : Math.max(0, Math.min(width, cx));
|
|
297
|
+
// A quarter of the way in from the edge it was past; along that edge, only as far as keeps it off the other two.
|
|
298
|
+
const inward = (at, span) => (at < span / 4 ? span / 4 - at : at > (span * 3) / 4 ? (span * 3) / 4 - at : 0);
|
|
299
|
+
const clear = (at, span) => (at < EDGE_CLEAR ? EDGE_CLEAR - at : at > span - EDGE_CLEAR ? span - EDGE_CLEAR - at : 0);
|
|
300
|
+
const by = across ? { x: inward(cx, width), y: clear(cy, height) } : { x: clear(cx, width), y: inward(cy, height) };
|
|
301
|
+
out.push({ id: node.id, kind: node.id.slice("kind:".length), side, along, by });
|
|
302
|
+
}
|
|
303
|
+
return out;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* THE PAN THAT KEEPS THE POINT UNDER THE POINTER STILL when the city is
|
|
307
|
+
* zoomed. The city is placed about the canvas's centre, so scaling its cell
|
|
308
|
+
* by `ratio` moves every point away from (or toward) the centre; the pan
|
|
309
|
+
* moves the opposite way by the pointer's share of that, and what was under
|
|
310
|
+
* the finger stays under it. Whole offset in, pan out: the camera's own
|
|
311
|
+
* flight is part of where the city is, and only the pan is the person's.
|
|
312
|
+
*/
|
|
313
|
+
export function panForZoom(pan, camera, pointer, centre, ratio) {
|
|
314
|
+
return {
|
|
315
|
+
x: pan.x + (pointer.x - pan.x - camera.x - centre.x) * (1 - ratio),
|
|
316
|
+
y: pan.y + (pointer.y - pan.y - camera.y - centre.y) * (1 - ratio),
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=city.js.map
|
package/dist/city.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"city.js","sourceRoot":"","sources":["../src/city.ts"],"names":[],"mappings":"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"}
|
package/dist/ids.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type ViewState } from "./view-state.js";
|
|
2
|
+
export declare const AGGREGATE_PREFIX = "aggregate:";
|
|
3
|
+
/**
|
|
4
|
+
* The kinds plane's cards have ids of their own.
|
|
5
|
+
*
|
|
6
|
+
* They cannot share `aggregate:<kind>` with a focusable group, because an app
|
|
7
|
+
* whose primary view IS one kind — the coaching example's formation is
|
|
8
|
+
* `aggregate:position` — would then place the same id twice: once as the
|
|
9
|
+
* focus and once as its own card in the strip. The strip is a MAP of kinds,
|
|
10
|
+
* not a set of groups you focus, so it gets its own namespace.
|
|
11
|
+
*/
|
|
12
|
+
export declare const KIND_PREFIX = "kind:";
|
|
13
|
+
export declare function kindCardId(kind: string): string;
|
|
14
|
+
export declare function kindOfCard(id: string): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* The card that stands for the districts the row could not hold.
|
|
17
|
+
*
|
|
18
|
+
* Its own id rather than a kind's, because it is not a kind: it is the row
|
|
19
|
+
* saying what it had to leave out, and naming them.
|
|
20
|
+
*/
|
|
21
|
+
export declare const BEYOND_CARD = "kinds:beyond";
|
|
22
|
+
/** The kinds an id stands for, whichever namespace it is in. */
|
|
23
|
+
export declare function kindsOf(id: string): string[];
|
|
24
|
+
/**
|
|
25
|
+
* The id of a group standing in for one or more kinds.
|
|
26
|
+
*
|
|
27
|
+
* Several kinds because a group is a view of a SET of kinds, not a synonym
|
|
28
|
+
* for one: the household example's week is its blocks and its runs together, and no node
|
|
29
|
+
* kind called "week" exists or should. Kinds are sorted so the same group is
|
|
30
|
+
* always the same id, which keeps it stable in a URL.
|
|
31
|
+
*/
|
|
32
|
+
export declare function aggregateId(...kinds: readonly string[]): string;
|
|
33
|
+
export declare function isAggregateId(id: string): boolean;
|
|
34
|
+
/** The kinds a group id names, or an empty list if it is not a group id. */
|
|
35
|
+
export declare function kindsOfAggregate(id: string): string[];
|
|
36
|
+
/**
|
|
37
|
+
* Going deeper into a card, as view state.
|
|
38
|
+
*
|
|
39
|
+
* A record ZOOMS: the same scene with the record grown to most of it, and
|
|
40
|
+
* the same gesture on the zoomed record zooms back out. A KIND CARD stands
|
|
41
|
+
* for a group, so deeper means the group: on the ground it zooms into the
|
|
42
|
+
* group as a place (`aggregate:<kind>`), and from altitude it opens the
|
|
43
|
+
* district in place — the exploded view — and the same gesture closes it.
|
|
44
|
+
*
|
|
45
|
+
* UNLESS THE KIND HAS A PICTURE OF ITS OWN. A district explodes into a ring
|
|
46
|
+
* of chips because a bag of names is the best a generic card can do with its
|
|
47
|
+
* members. A kind with a lens registered over it has something better, and
|
|
48
|
+
* the card already says so with its ◆ — so "deeper" there means that
|
|
49
|
+
* picture, and the district stays shut. Exploding it replaced a designed
|
|
50
|
+
* view with the fallback it exists to improve on.
|
|
51
|
+
*
|
|
52
|
+
* The card's own id (`kind:<kind>`) is never made the focus. A focus
|
|
53
|
+
* resolves to a node or to a group's kinds, and a kind card is neither: a
|
|
54
|
+
* focus on one laid out an empty scene with the card's name in the URL,
|
|
55
|
+
* which is what double-clicking a group looked like before this existed.
|
|
56
|
+
*/
|
|
57
|
+
export declare function withJackIn(state: ViewState, id: string, options?: {
|
|
58
|
+
readonly ownPicture?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Words to carry into a district: the search that lit it. Descending
|
|
61
|
+
* into a lit district opens it already narrowed — the arrangement's own
|
|
62
|
+
* `in.q` — so the row shows why, and clearing the row clears only that.
|
|
63
|
+
*/
|
|
64
|
+
readonly carry?: string;
|
|
65
|
+
}): ViewState;
|
|
66
|
+
/**
|
|
67
|
+
* Ranks by a STABLE key — the node id — and never by a mutable count.
|
|
68
|
+
*
|
|
69
|
+
* This is the single rule that protects spatial memory. Ordering people by
|
|
70
|
+
* "how many runs they have" would reshuffle the whole plane the moment
|
|
71
|
+
* anything is reassigned, and the picture you remember would stop being the
|
|
72
|
+
* picture you get.
|
|
73
|
+
*/
|
|
74
|
+
export declare function byStableKey(a: {
|
|
75
|
+
id: string;
|
|
76
|
+
}, b: {
|
|
77
|
+
id: string;
|
|
78
|
+
}): number;
|
|
79
|
+
//# sourceMappingURL=ids.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAShH,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAE7C;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpD;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAE1C,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAG5C;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAE/D;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,4EAA4E;AAC5E,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAIrD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,EAChB,EAAE,EAAE,MAAM,EACV,OAAO,GAAE;IACP,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACpB,GACL,SAAS,CAuBX;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAExE"}
|