@kanzo-tech/graph 0.14.0 → 0.15.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 (113) hide show
  1. package/README.md +12 -15
  2. package/dist/core/categories.d.ts +18 -6
  3. package/dist/core/categories.d.ts.map +1 -1
  4. package/dist/core/categories.js +41 -10
  5. package/dist/core/categories.js.map +1 -1
  6. package/dist/core/channels.d.ts +10 -5
  7. package/dist/core/channels.d.ts.map +1 -1
  8. package/dist/core/channels.js +11 -13
  9. package/dist/core/channels.js.map +1 -1
  10. package/dist/core/detail.d.ts +14 -8
  11. package/dist/core/detail.d.ts.map +1 -1
  12. package/dist/core/detail.js +33 -15
  13. package/dist/core/detail.js.map +1 -1
  14. package/dist/core/filter.d.ts +3 -1
  15. package/dist/core/filter.d.ts.map +1 -1
  16. package/dist/core/filter.js +54 -50
  17. package/dist/core/filter.js.map +1 -1
  18. package/dist/core/load.d.ts +58 -0
  19. package/dist/core/load.d.ts.map +1 -0
  20. package/dist/core/load.js +115 -0
  21. package/dist/core/load.js.map +1 -0
  22. package/dist/core/state.d.ts +27 -55
  23. package/dist/core/state.d.ts.map +1 -1
  24. package/dist/core/store.d.ts +1 -3
  25. package/dist/core/store.d.ts.map +1 -1
  26. package/dist/core/store.js +160 -175
  27. package/dist/core/store.js.map +1 -1
  28. package/dist/core/types.d.ts +21 -17
  29. package/dist/core/types.d.ts.map +1 -1
  30. package/dist/index.d.ts +5 -7
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +19 -25
  33. package/dist/index.js.map +1 -1
  34. package/dist/parts/gesture.d.ts +1 -10
  35. package/dist/parts/gesture.d.ts.map +1 -1
  36. package/dist/parts/gesture.js +28 -28
  37. package/dist/parts/gesture.js.map +1 -1
  38. package/dist/parts/graph-canvas.d.ts.map +1 -1
  39. package/dist/parts/graph-canvas.js +119 -108
  40. package/dist/parts/graph-canvas.js.map +1 -1
  41. package/dist/parts/graph-inspector.d.ts +4 -4
  42. package/dist/parts/graph-inspector.d.ts.map +1 -1
  43. package/dist/parts/graph-inspector.js +55 -57
  44. package/dist/parts/graph-inspector.js.map +1 -1
  45. package/dist/parts/graph-legend.d.ts +4 -4
  46. package/dist/parts/graph-legend.d.ts.map +1 -1
  47. package/dist/parts/graph-legend.js +21 -21
  48. package/dist/parts/graph-legend.js.map +1 -1
  49. package/dist/parts/overlays.d.ts +2 -4
  50. package/dist/parts/overlays.d.ts.map +1 -1
  51. package/dist/parts/overlays.js +45 -45
  52. package/dist/parts/overlays.js.map +1 -1
  53. package/dist/react/use-graph-state.d.ts +4 -2
  54. package/dist/react/use-graph-state.d.ts.map +1 -1
  55. package/dist/react/use-graph-state.js +10 -6
  56. package/dist/react/use-graph-state.js.map +1 -1
  57. package/dist/react/use-graph.d.ts +1 -4
  58. package/dist/react/use-graph.d.ts.map +1 -1
  59. package/dist/react/use-graph.js +38 -49
  60. package/dist/react/use-graph.js.map +1 -1
  61. package/dist/render/graph-looks.d.ts.map +1 -1
  62. package/dist/render/graph-looks.js.map +1 -1
  63. package/dist/render/graph-model.d.ts +6 -8
  64. package/dist/render/graph-model.d.ts.map +1 -1
  65. package/dist/render/graph-model.js +51 -57
  66. package/dist/render/graph-model.js.map +1 -1
  67. package/dist/render/graph-sim.d.ts +2 -3
  68. package/dist/render/graph-sim.d.ts.map +1 -1
  69. package/dist/render/graph-sim.js.map +1 -1
  70. package/dist/render/renderer.d.ts +6 -11
  71. package/dist/render/renderer.d.ts.map +1 -1
  72. package/dist/render/renderer.js +120 -173
  73. package/dist/render/renderer.js.map +1 -1
  74. package/dist/section.d.ts.map +1 -1
  75. package/dist/section.js +3 -7
  76. package/dist/section.js.map +1 -1
  77. package/package.json +11 -11
  78. package/dist/core/refine.d.ts +0 -14
  79. package/dist/core/refine.d.ts.map +0 -1
  80. package/dist/core/refine.js +0 -20
  81. package/dist/core/refine.js.map +0 -1
  82. package/dist/core/resident.d.ts +0 -79
  83. package/dist/core/resident.d.ts.map +0 -1
  84. package/dist/core/resident.js +0 -44
  85. package/dist/core/resident.js.map +0 -1
  86. package/dist/core/scheduler.d.ts +0 -42
  87. package/dist/core/scheduler.d.ts.map +0 -1
  88. package/dist/core/scheduler.js +0 -77
  89. package/dist/core/scheduler.js.map +0 -1
  90. package/dist/core/tile-matrix.d.ts +0 -37
  91. package/dist/core/tile-matrix.d.ts.map +0 -1
  92. package/dist/core/tile-matrix.js +0 -49
  93. package/dist/core/tile-matrix.js.map +0 -1
  94. package/dist/core/tile.d.ts +0 -54
  95. package/dist/core/tile.d.ts.map +0 -1
  96. package/dist/core/tile.js +0 -76
  97. package/dist/core/tile.js.map +0 -1
  98. package/dist/core/tileset.d.ts +0 -59
  99. package/dist/core/tileset.d.ts.map +0 -1
  100. package/dist/core/tileset.js +0 -177
  101. package/dist/core/tileset.js.map +0 -1
  102. package/dist/render/adaptive.d.ts +0 -27
  103. package/dist/render/adaptive.d.ts.map +0 -1
  104. package/dist/render/adaptive.js +0 -25
  105. package/dist/render/adaptive.js.map +0 -1
  106. package/dist/render/compose.d.ts +0 -51
  107. package/dist/render/compose.d.ts.map +0 -1
  108. package/dist/render/compose.js +0 -107
  109. package/dist/render/compose.js.map +0 -1
  110. package/dist/render/encode.d.ts +0 -42
  111. package/dist/render/encode.d.ts.map +0 -1
  112. package/dist/render/encode.js +0 -68
  113. package/dist/render/encode.js.map +0 -1
@@ -1,37 +0,0 @@
1
- import { TileAddress, TileMatrixSet } from '@fossil-lang/corpus';
2
- /** A rectangle in the corpus's own coordinates, which are the camera's. */
3
- export interface Viewport {
4
- xMin: number;
5
- yMin: number;
6
- xMax: number;
7
- yMax: number;
8
- }
9
- /** deck.gl's `${x}-${y}-${z}`, on fossil's one-dimensional address. */
10
- export declare const tileId: ({ tile, type, z }: TileAddress) => string;
11
- /**
12
- * The tiles of one matrix in view — deck.gl's `getTileIndices`, as a cull rather than arithmetic:
13
- * where a rank falls on the plane depends on the positions, so only the published boxes can say.
14
- */
15
- export declare function cull(set: TileMatrixSet, z: number, view: Viewport, among?: ReadonlySet<number>): number[];
16
- /**
17
- * **The finest planned `z` whose tiles in view hold, by their published `rows`, at most `limit`.**
18
- *
19
- * `planned` is what `scan.plan()` kept, by zoom — a filter on a payload column plans nothing below
20
- * `Z`, so the choice is among the planned zooms only and a coarse camera then draws rows. When no
21
- * zoom fits, the coarsest planned one is drawn.
22
- */
23
- export declare function selectLevel(set: TileMatrixSet, view: Viewport, limit: number, planned: ReadonlyMap<number, ReadonlySet<number>>): {
24
- z: number;
25
- tiles: number[];
26
- } | null;
27
- /**
28
- * The tile one zoom coarser that covers this one: `(z − 1, t >> (shift(z − 1) − shift(z)))`.
29
- * Every zoom has the same `tileRows`, so a coarser tile covers `2^Δshift` finer ones — sixteen
30
- * between the payload and the first rung, four between rungs.
31
- */
32
- export declare function parentOf(set: TileMatrixSet, address: TileAddress): TileAddress | null;
33
- /** The centre of a tile's box, or of the extent when it publishes none. */
34
- export declare function centreOf(set: TileMatrixSet, address: TileAddress): [number, number] | null;
35
- /** The payload tile a vertex's `dense_id` falls in. */
36
- export declare function tileOfDense(set: TileMatrixSet, dense: number): TileAddress | null;
37
- //# sourceMappingURL=tile-matrix.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tile-matrix.d.ts","sourceRoot":"","sources":["../../src/core/tile-matrix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE3E,2EAA2E;AAC3E,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,uEAAuE;AACvE,eAAO,MAAM,MAAM,GAAI,mBAAmB,WAAW,KAAG,MAAgC,CAAC;AAQzF;;;GAGG;AACH,wBAAgB,IAAI,CAClB,GAAG,EAAE,aAAa,EAClB,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,QAAQ,EACd,KAAK,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAC1B,MAAM,EAAE,CASV;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,aAAa,EAClB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,GAChD;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAYvC;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAMrF;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAG1F;AAED,uDAAuD;AACvD,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAMjF"}
@@ -1,49 +0,0 @@
1
- const x = ({ tile: t, type: e, z: n }) => `${e}-${n}-${t}`;
2
- function h(t, e) {
3
- return t === null ? !0 : t.x <= e.xMax && t.x + t.w >= e.xMin && t.y <= e.yMax && t.y + t.h >= e.yMin;
4
- }
5
- function y(t, e, n, i) {
6
- const l = t.tileMatrices[e];
7
- if (!l) return [];
8
- const o = [];
9
- for (const r of l.tiles)
10
- i && !i.has(r.tile) || h(r.bbox, n) && o.push(r.tile);
11
- return o;
12
- }
13
- function z(t, e, n, i) {
14
- var r, f;
15
- const l = [...i.keys()].sort((s, c) => c - s);
16
- let o = null;
17
- for (const s of l) {
18
- const c = y(t, s, e, i.get(s)), a = ((r = t.tileMatrices[s]) == null ? void 0 : r.tiles) ?? [];
19
- let u = 0;
20
- for (const M of c) u += ((f = a[M]) == null ? void 0 : f.rows) ?? 0;
21
- if (u <= n) return { z: s, tiles: c };
22
- o = { z: s, tiles: c };
23
- }
24
- return o;
25
- }
26
- function p(t, e) {
27
- const { tile: n, type: i, z: l } = e, o = t.tileMatrices[l], r = t.tileMatrices[l - 1];
28
- return !o || !r ? null : { type: i, z: l - 1, tile: Math.floor(n / 2 ** (r.shift - o.shift)) };
29
- }
30
- function m(t, e) {
31
- var i, l;
32
- const n = ((l = (i = t.tileMatrices[e.z]) == null ? void 0 : i.tiles[e.tile]) == null ? void 0 : l.bbox) ?? t.extent;
33
- return n === null ? null : [n.x + n.w / 2, n.y + n.h / 2];
34
- }
35
- function O(t, e) {
36
- const n = t.tileMatrices.length - 1, i = t.tileMatrices[n];
37
- if (!i) return null;
38
- const l = Math.floor(e / i.tileRows);
39
- return l < i.tiles.length ? { type: t.type, z: n, tile: l } : null;
40
- }
41
- export {
42
- m as centreOf,
43
- y as cull,
44
- p as parentOf,
45
- z as selectLevel,
46
- x as tileId,
47
- O as tileOfDense
48
- };
49
- //# sourceMappingURL=tile-matrix.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tile-matrix.js","sources":["../../src/core/tile-matrix.ts"],"sourcesContent":["import type { Box, TileAddress, TileMatrixSet } from \"@fossil-lang/corpus\";\n\n/** A rectangle in the corpus's own coordinates, which are the camera's. */\nexport interface Viewport {\n xMin: number;\n yMin: number;\n xMax: number;\n yMax: number;\n}\n\n/** deck.gl's `${x}-${y}-${z}`, on fossil's one-dimensional address. */\nexport const tileId = ({ tile, type, z }: TileAddress): string => `${type}-${z}-${tile}`;\n\n/** Closed on both edges: a published box is a bound, not a selection. */\nfunction meets(box: Box | null, view: Viewport): boolean {\n if (box === null) return true;\n return box.x <= view.xMax && box.x + box.w >= view.xMin && box.y <= view.yMax && box.y + box.h >= view.yMin;\n}\n\n/**\n * The tiles of one matrix in view — deck.gl's `getTileIndices`, as a cull rather than arithmetic:\n * where a rank falls on the plane depends on the positions, so only the published boxes can say.\n */\nexport function cull(\n set: TileMatrixSet,\n z: number,\n view: Viewport,\n among?: ReadonlySet<number>,\n): number[] {\n const matrix = set.tileMatrices[z];\n if (!matrix) return [];\n const found: number[] = [];\n for (const info of matrix.tiles) {\n if (among && !among.has(info.tile)) continue;\n if (meets(info.bbox, view)) found.push(info.tile);\n }\n return found;\n}\n\n/**\n * **The finest planned `z` whose tiles in view hold, by their published `rows`, at most `limit`.**\n *\n * `planned` is what `scan.plan()` kept, by zoom — a filter on a payload column plans nothing below\n * `Z`, so the choice is among the planned zooms only and a coarse camera then draws rows. When no\n * zoom fits, the coarsest planned one is drawn.\n */\nexport function selectLevel(\n set: TileMatrixSet,\n view: Viewport,\n limit: number,\n planned: ReadonlyMap<number, ReadonlySet<number>>,\n): { z: number; tiles: number[] } | null {\n const zooms = [...planned.keys()].sort((a, b) => b - a);\n let coarsest: { z: number; tiles: number[] } | null = null;\n for (const z of zooms) {\n const tiles = cull(set, z, view, planned.get(z));\n const infos = set.tileMatrices[z]?.tiles ?? [];\n let rows = 0;\n for (const tile of tiles) rows += infos[tile]?.rows ?? 0;\n if (rows <= limit) return { z, tiles };\n coarsest = { z, tiles };\n }\n return coarsest;\n}\n\n/**\n * The tile one zoom coarser that covers this one: `(z − 1, t >> (shift(z − 1) − shift(z)))`.\n * Every zoom has the same `tileRows`, so a coarser tile covers `2^Δshift` finer ones — sixteen\n * between the payload and the first rung, four between rungs.\n */\nexport function parentOf(set: TileMatrixSet, address: TileAddress): TileAddress | null {\n const { tile, type, z } = address;\n const here = set.tileMatrices[z];\n const above = set.tileMatrices[z - 1];\n if (!here || !above) return null;\n return { type, z: z - 1, tile: Math.floor(tile / 2 ** (above.shift - here.shift)) };\n}\n\n/** The centre of a tile's box, or of the extent when it publishes none. */\nexport function centreOf(set: TileMatrixSet, address: TileAddress): [number, number] | null {\n const box = set.tileMatrices[address.z]?.tiles[address.tile]?.bbox ?? set.extent;\n return box === null ? null : [box.x + box.w / 2, box.y + box.h / 2];\n}\n\n/** The payload tile a vertex's `dense_id` falls in. */\nexport function tileOfDense(set: TileMatrixSet, dense: number): TileAddress | null {\n const z = set.tileMatrices.length - 1;\n const matrix = set.tileMatrices[z];\n if (!matrix) return null;\n const tile = Math.floor(dense / matrix.tileRows);\n return tile < matrix.tiles.length ? { type: set.type, z, tile } : null;\n}\n"],"names":["tileId","tile","type","z","meets","box","view","cull","set","among","matrix","found","info","selectLevel","limit","planned","_a","_b","zooms","a","b","coarsest","tiles","infos","rows","parentOf","address","here","above","centreOf","tileOfDense","dense"],"mappings":"AAWO,MAAMA,IAAS,CAAC,EAAE,MAAAC,GAAM,MAAAC,GAAM,GAAAC,EAAA,MAA6B,GAAGD,CAAI,IAAIC,CAAC,IAAIF,CAAI;AAGtF,SAASG,EAAMC,GAAiBC,GAAyB;AACvD,SAAID,MAAQ,OAAa,KAClBA,EAAI,KAAKC,EAAK,QAAQD,EAAI,IAAIA,EAAI,KAAKC,EAAK,QAAQD,EAAI,KAAKC,EAAK,QAAQD,EAAI,IAAIA,EAAI,KAAKC,EAAK;AACzG;AAMO,SAASC,EACdC,GACAL,GACAG,GACAG,GACU;AACV,QAAMC,IAASF,EAAI,aAAaL,CAAC;AACjC,MAAI,CAACO,EAAQ,QAAO,CAAA;AACpB,QAAMC,IAAkB,CAAA;AACxB,aAAWC,KAAQF,EAAO;AACxB,IAAID,KAAS,CAACA,EAAM,IAAIG,EAAK,IAAI,KAC7BR,EAAMQ,EAAK,MAAMN,CAAI,KAAGK,EAAM,KAAKC,EAAK,IAAI;AAElD,SAAOD;AACT;AASO,SAASE,EACdL,GACAF,GACAQ,GACAC,GACuC;AAxClC,MAAAC,GAAAC;AAyCL,QAAMC,IAAQ,CAAC,GAAGH,EAAQ,KAAA,CAAM,EAAE,KAAK,CAACI,GAAGC,MAAMA,IAAID,CAAC;AACtD,MAAIE,IAAkD;AACtD,aAAWlB,KAAKe,GAAO;AACrB,UAAMI,IAAQf,EAAKC,GAAKL,GAAGG,GAAMS,EAAQ,IAAIZ,CAAC,CAAC,GACzCoB,MAAQP,IAAAR,EAAI,aAAaL,CAAC,MAAlB,gBAAAa,EAAqB,UAAS,CAAA;AAC5C,QAAIQ,IAAO;AACX,eAAWvB,KAAQqB,EAAO,CAAAE,OAAQP,IAAAM,EAAMtB,CAAI,MAAV,gBAAAgB,EAAa,SAAQ;AACvD,QAAIO,KAAQV,EAAO,QAAO,EAAE,GAAAX,GAAG,OAAAmB,EAAA;AAC/B,IAAAD,IAAW,EAAE,GAAAlB,GAAG,OAAAmB,EAAA;AAAA,EAClB;AACA,SAAOD;AACT;AAOO,SAASI,EAASjB,GAAoBkB,GAA0C;AACrF,QAAM,EAAE,MAAAzB,GAAM,MAAAC,GAAM,GAAAC,EAAA,IAAMuB,GACpBC,IAAOnB,EAAI,aAAaL,CAAC,GACzByB,IAAQpB,EAAI,aAAaL,IAAI,CAAC;AACpC,SAAI,CAACwB,KAAQ,CAACC,IAAc,OACrB,EAAE,MAAA1B,GAAM,GAAGC,IAAI,GAAG,MAAM,KAAK,MAAMF,IAAO,MAAM2B,EAAM,QAAQD,EAAK,MAAM,EAAA;AAClF;AAGO,SAASE,EAASrB,GAAoBkB,GAA+C;AApErF,MAAAV,GAAAC;AAqEL,QAAMZ,MAAMY,KAAAD,IAAAR,EAAI,aAAakB,EAAQ,CAAC,MAA1B,gBAAAV,EAA6B,MAAMU,EAAQ,UAA3C,gBAAAT,EAAkD,SAAQT,EAAI;AAC1E,SAAOH,MAAQ,OAAO,OAAO,CAACA,EAAI,IAAIA,EAAI,IAAI,GAAGA,EAAI,IAAIA,EAAI,IAAI,CAAC;AACpE;AAGO,SAASyB,EAAYtB,GAAoBuB,GAAmC;AACjF,QAAM5B,IAAIK,EAAI,aAAa,SAAS,GAC9BE,IAASF,EAAI,aAAaL,CAAC;AACjC,MAAI,CAACO,EAAQ,QAAO;AACpB,QAAMT,IAAO,KAAK,MAAM8B,IAAQrB,EAAO,QAAQ;AAC/C,SAAOT,IAAOS,EAAO,MAAM,SAAS,EAAE,MAAMF,EAAI,MAAM,GAAAL,GAAG,MAAAF,EAAA,IAAS;AACpE;"}
@@ -1,54 +0,0 @@
1
- import { Batch, EdgeBatch, Gap, TileAddress } from '@fossil-lang/corpus';
2
- import { RequestScheduler } from './scheduler';
3
- /** What one tile holds once read: its rows, the relations incident to it, and what was declined. */
4
- export interface TileContent {
5
- readonly rows: Batch;
6
- readonly edges: readonly EdgeBatch[];
7
- readonly declined: readonly Gap[];
8
- readonly byteLength: number;
9
- }
10
- /**
11
- * deck.gl's `getTileData`, over a batch: fossil's addresses where deck.gl has `{ x, y, z }`, and one
12
- * content per address, in order, because the corpus reads a run of consecutive tiles in one statement.
13
- */
14
- export type TileLoader = (addresses: readonly TileAddress[], signal: AbortSignal) => Promise<readonly TileContent[]>;
15
- export interface TileLoad {
16
- scheduler: RequestScheduler<Tile, TileContent>;
17
- priority: (tile: Tile) => number;
18
- onLoad: (tile: Tile) => void;
19
- onError: (error: unknown, tile: Tile) => void;
20
- }
21
- /**
22
- * deck.gl's `Tile2DHeader`: one tile's load, abort and content, and its place in the tree.
23
- *
24
- * **Content outlives a reload.** A tile marked for reload keeps what it last read until the new
25
- * answer arrives, and an aborted or failed reload keeps it too, so a change of question never
26
- * shows a hole. deck.gl drops it on a cancelled reload; the one departure, and it is what
27
- * `/docs/design/graph` asks of a change of data.
28
- */
29
- export declare class Tile {
30
- #private;
31
- readonly address: TileAddress;
32
- readonly id: string;
33
- content: TileContent | null;
34
- isSelected: boolean;
35
- isVisible: boolean;
36
- parent: Tile | null;
37
- children: Tile[];
38
- constructor(address: TileAddress);
39
- get z(): number;
40
- /** Read at least once for the current question. */
41
- get isLoaded(): boolean;
42
- /** Queued or running, and not cancelled. */
43
- get isLoading(): boolean;
44
- get needsReload(): boolean;
45
- get byteLength(): number;
46
- loadData(options: TileLoad): Promise<void>;
47
- /**
48
- * A finished tile has nothing to abort; a queued or running one is cancelled, and its batch is
49
- * aborted once no tile in it is wanted.
50
- */
51
- abort(): void;
52
- setNeedsReload(): void;
53
- }
54
- //# sourceMappingURL=tile.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tile.d.ts","sourceRoot":"","sources":["../../src/core/tile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,oGAAoG;AACpG,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,EAAE,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,SAAS,WAAW,EAAE,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;AAErH,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,gBAAgB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC/C,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;IACjC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC7B,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;;;GAOG;AACH,qBAAa,IAAI;;IACf,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAQ;IACnC,UAAU,UAAS;IACnB,SAAS,UAAS;IAClB,MAAM,EAAE,IAAI,GAAG,IAAI,CAAQ;IAC3B,QAAQ,EAAE,IAAI,EAAE,CAAM;gBASV,OAAO,EAAE,WAAW;IAKhC,IAAI,CAAC,IAAI,MAAM,CAEd;IAED,mDAAmD;IACnD,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,4CAA4C;IAC5C,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1C;;;OAGG;IACH,KAAK,IAAI,IAAI;IAMb,cAAc,IAAI,IAAI;CAyBvB"}
package/dist/core/tile.js DELETED
@@ -1,76 +0,0 @@
1
- var v = Object.defineProperty;
2
- var m = (e) => {
3
- throw TypeError(e);
4
- };
5
- var w = (e, t, s) => t in e ? v(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
6
- var h = (e, t, s) => w(e, typeof t != "symbol" ? t + "" : t, s), L = (e, t, s) => t.has(e) || m("Cannot " + s);
7
- var i = (e, t, s) => (L(e, t, "read from private field"), s ? s.call(e) : t.get(e)), n = (e, t, s) => t.has(e) ? m("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, s), l = (e, t, s, f) => (L(e, t, "write to private field"), f ? f.call(e, s) : t.set(e, s), s), y = (e, t, s) => (L(e, t, "access private method"), s);
8
- import { tileId as z } from "./tile-matrix.js";
9
- var c, a, u, d, r, o, b, I;
10
- class E {
11
- constructor(t) {
12
- n(this, b);
13
- h(this, "address");
14
- h(this, "id");
15
- h(this, "content", null);
16
- h(this, "isSelected", !1);
17
- h(this, "isVisible", !1);
18
- h(this, "parent", null);
19
- h(this, "children", []);
20
- n(this, c, null);
21
- n(this, a, null);
22
- n(this, u, 0);
23
- n(this, d, !1);
24
- n(this, r, !1);
25
- n(this, o, !1);
26
- this.address = t, this.id = z(t);
27
- }
28
- get z() {
29
- return this.address.z;
30
- }
31
- /** Read at least once for the current question. */
32
- get isLoaded() {
33
- return i(this, d) && !i(this, o);
34
- }
35
- /** Queued or running, and not cancelled. */
36
- get isLoading() {
37
- return i(this, a) !== null && !i(this, r);
38
- }
39
- get needsReload() {
40
- return i(this, o) || i(this, r);
41
- }
42
- get byteLength() {
43
- var t;
44
- return ((t = this.content) == null ? void 0 : t.byteLength) ?? 0;
45
- }
46
- loadData(t) {
47
- l(this, c, t.scheduler), l(this, d, !1), l(this, r, !1), l(this, o, !1), l(this, u, i(this, u) + 1);
48
- const s = y(this, b, I).call(this, t);
49
- return l(this, a, s), s;
50
- }
51
- /**
52
- * A finished tile has nothing to abort; a queued or running one is cancelled, and its batch is
53
- * aborted once no tile in it is wanted.
54
- */
55
- abort() {
56
- var t;
57
- i(this, d) || i(this, a) === null || (l(this, r, !0), (t = i(this, c)) == null || t.cancel(this));
58
- }
59
- setNeedsReload() {
60
- this.isLoading && (this.abort(), l(this, a, null)), l(this, o, !0);
61
- }
62
- }
63
- c = new WeakMap(), a = new WeakMap(), u = new WeakMap(), d = new WeakMap(), r = new WeakMap(), o = new WeakMap(), b = new WeakSet(), I = async function({ onError: t, onLoad: s, priority: f, scheduler: R }) {
64
- const p = i(this, u), g = await R.schedule(this, f);
65
- if (p === i(this, u)) {
66
- if (l(this, a, null), g === null || i(this, r)) {
67
- l(this, r, !0);
68
- return;
69
- }
70
- l(this, d, !0), "value" in g ? (this.content = g.value, s(this)) : t(g.error ?? new Error("the tile failed to load"), this);
71
- }
72
- };
73
- export {
74
- E as Tile
75
- };
76
- //# sourceMappingURL=tile.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tile.js","sources":["../../src/core/tile.ts"],"sourcesContent":["import type { Batch, EdgeBatch, Gap, TileAddress } from \"@fossil-lang/corpus\";\nimport type { RequestScheduler } from \"./scheduler\";\nimport { tileId } from \"./tile-matrix\";\n\n/** What one tile holds once read: its rows, the relations incident to it, and what was declined. */\nexport interface TileContent {\n readonly rows: Batch;\n readonly edges: readonly EdgeBatch[];\n readonly declined: readonly Gap[];\n readonly byteLength: number;\n}\n\n/**\n * deck.gl's `getTileData`, over a batch: fossil's addresses where deck.gl has `{ x, y, z }`, and one\n * content per address, in order, because the corpus reads a run of consecutive tiles in one statement.\n */\nexport type TileLoader = (addresses: readonly TileAddress[], signal: AbortSignal) => Promise<readonly TileContent[]>;\n\nexport interface TileLoad {\n scheduler: RequestScheduler<Tile, TileContent>;\n priority: (tile: Tile) => number;\n onLoad: (tile: Tile) => void;\n onError: (error: unknown, tile: Tile) => void;\n}\n\n/**\n * deck.gl's `Tile2DHeader`: one tile's load, abort and content, and its place in the tree.\n *\n * **Content outlives a reload.** A tile marked for reload keeps what it last read until the new\n * answer arrives, and an aborted or failed reload keeps it too, so a change of question never\n * shows a hole. deck.gl drops it on a cancelled reload; the one departure, and it is what\n * `/docs/design/graph` asks of a change of data.\n */\nexport class Tile {\n readonly address: TileAddress;\n readonly id: string;\n content: TileContent | null = null;\n isSelected = false;\n isVisible = false;\n parent: Tile | null = null;\n children: Tile[] = [];\n\n #scheduler: RequestScheduler<Tile, TileContent> | null = null;\n #loader: Promise<void> | null = null;\n #loaderId = 0;\n #loaded = false;\n #cancelled = false;\n #needsReload = false;\n\n constructor(address: TileAddress) {\n this.address = address;\n this.id = tileId(address);\n }\n\n get z(): number {\n return this.address.z;\n }\n\n /** Read at least once for the current question. */\n get isLoaded(): boolean {\n return this.#loaded && !this.#needsReload;\n }\n\n /** Queued or running, and not cancelled. */\n get isLoading(): boolean {\n return this.#loader !== null && !this.#cancelled;\n }\n\n get needsReload(): boolean {\n return this.#needsReload || this.#cancelled;\n }\n\n get byteLength(): number {\n return this.content?.byteLength ?? 0;\n }\n\n loadData(options: TileLoad): Promise<void> {\n this.#scheduler = options.scheduler;\n this.#loaded = false;\n this.#cancelled = false;\n this.#needsReload = false;\n this.#loaderId += 1;\n const loader = this.#load(options);\n this.#loader = loader;\n return loader;\n }\n\n /**\n * A finished tile has nothing to abort; a queued or running one is cancelled, and its batch is\n * aborted once no tile in it is wanted.\n */\n abort(): void {\n if (this.#loaded || this.#loader === null) return;\n this.#cancelled = true;\n this.#scheduler?.cancel(this);\n }\n\n setNeedsReload(): void {\n if (this.isLoading) {\n this.abort();\n this.#loader = null;\n }\n this.#needsReload = true;\n }\n\n async #load({ onError, onLoad, priority, scheduler }: TileLoad): Promise<void> {\n const loaderId = this.#loaderId;\n const outcome = await scheduler.schedule(this, priority);\n if (loaderId !== this.#loaderId) return;\n this.#loader = null;\n if (outcome === null || this.#cancelled) {\n this.#cancelled = true;\n return;\n }\n this.#loaded = true;\n if (\"value\" in outcome) {\n this.content = outcome.value;\n onLoad(this);\n } else {\n onError(outcome.error ?? new Error(\"the tile failed to load\"), this);\n }\n }\n}\n"],"names":["Tile","address","__privateAdd","_Tile_instances","__publicField","_scheduler","_loader","_loaderId","_loaded","_cancelled","_needsReload","tileId","__privateGet","_a","options","__privateSet","loader","__privateMethod","load_fn","onError","onLoad","priority","scheduler","loaderId","outcome"],"mappings":";;;;;;;;;AAiCO,MAAMA,EAAK;AAAA,EAgBhB,YAAYC,GAAsB;AAhB7B,IAAAC,EAAA,MAAAC;AACI,IAAAC,EAAA;AACA,IAAAA,EAAA;AACT,IAAAA,EAAA,iBAA8B;AAC9B,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,gBAAsB;AACtB,IAAAA,EAAA,kBAAmB,CAAA;AAEnB,IAAAF,EAAA,MAAAG,GAAyD;AACzD,IAAAH,EAAA,MAAAI,GAAgC;AAChC,IAAAJ,EAAA,MAAAK,GAAY;AACZ,IAAAL,EAAA,MAAAM,GAAU;AACV,IAAAN,EAAA,MAAAO,GAAa;AACb,IAAAP,EAAA,MAAAQ,GAAe;AAGb,SAAK,UAAUT,GACf,KAAK,KAAKU,EAAOV,CAAO;AAAA,EAC1B;AAAA,EAEA,IAAI,IAAY;AACd,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA,EAGA,IAAI,WAAoB;AACtB,WAAOW,EAAA,MAAKJ,MAAW,CAACI,EAAA,MAAKF;AAAA,EAC/B;AAAA;AAAA,EAGA,IAAI,YAAqB;AACvB,WAAOE,EAAA,MAAKN,OAAY,QAAQ,CAACM,EAAA,MAAKH;AAAA,EACxC;AAAA,EAEA,IAAI,cAAuB;AACzB,WAAOG,EAAA,MAAKF,MAAgBE,EAAA,MAAKH;AAAA,EACnC;AAAA,EAEA,IAAI,aAAqB;;AACvB,aAAOI,IAAA,KAAK,YAAL,gBAAAA,EAAc,eAAc;AAAA,EACrC;AAAA,EAEA,SAASC,GAAkC;AACzC,IAAAC,EAAA,MAAKV,GAAaS,EAAQ,YAC1BC,EAAA,MAAKP,GAAU,KACfO,EAAA,MAAKN,GAAa,KAClBM,EAAA,MAAKL,GAAe,KACpBK,EAAA,MAAKR,GAALK,EAAA,MAAKL,KAAa;AAClB,UAAMS,IAASC,EAAA,MAAKd,GAAAe,GAAL,WAAWJ;AAC1B,WAAAC,EAAA,MAAKT,GAAUU,IACRA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;;AACZ,IAAIJ,EAAA,MAAKJ,MAAWI,EAAA,MAAKN,OAAY,SACrCS,EAAA,MAAKN,GAAa,MAClBI,IAAAD,EAAA,MAAKP,OAAL,QAAAQ,EAAiB,OAAO;AAAA,EAC1B;AAAA,EAEA,iBAAuB;AACrB,IAAI,KAAK,cACP,KAAK,MAAA,GACLE,EAAA,MAAKT,GAAU,QAEjBS,EAAA,MAAKL,GAAe;AAAA,EACtB;AAmBF;AAhFEL,IAAA,eACAC,IAAA,eACAC,IAAA,eACAC,IAAA,eACAC,IAAA,eACAC,IAAA,eAdKP,IAAA,eAwECe,IAAA,eAAM,EAAE,SAAAC,GAAS,QAAAC,GAAQ,UAAAC,GAAU,WAAAC,KAAsC;AAC7E,QAAMC,IAAWX,EAAA,MAAKL,IAChBiB,IAAU,MAAMF,EAAU,SAAS,MAAMD,CAAQ;AACvD,MAAIE,MAAaX,EAAA,MAAKL,IAEtB;AAAA,QADAQ,EAAA,MAAKT,GAAU,OACXkB,MAAY,QAAQZ,EAAA,MAAKH,IAAY;AACvC,MAAAM,EAAA,MAAKN,GAAa;AAClB;AAAA,IACF;AACA,IAAAM,EAAA,MAAKP,GAAU,KACX,WAAWgB,KACb,KAAK,UAAUA,EAAQ,OACvBJ,EAAO,IAAI,KAEXD,EAAQK,EAAQ,SAAS,IAAI,MAAM,yBAAyB,GAAG,IAAI;AAAA;AAEvE;"}
@@ -1,59 +0,0 @@
1
- import { TileAddress, TileMatrixSet } from '@fossil-lang/corpus';
2
- import { Tile, TileLoader } from './tile';
3
- import { Viewport } from './tile-matrix';
4
- export interface TilesetOptions {
5
- load: TileLoader;
6
- onTileLoad?: (tile: Tile) => void;
7
- onTileError?: (error: unknown, tile: Tile) => void;
8
- onTileUnload?: (tile: Tile) => void;
9
- /** Tiles kept; five times the selected count when absent. */
10
- maxCacheSize?: number;
11
- /** Bytes kept; unbounded when absent. */
12
- maxCacheByteSize?: number;
13
- /** Batches in flight — one: see `RequestScheduler`. */
14
- maxRequests?: number;
15
- debounceTime?: number;
16
- }
17
- /**
18
- * **deck.gl's `Tileset2D` with the loader swapped for the corpus** — `modules/geo-layers/src/
19
- * tileset-2d/tileset-2d.ts`, its names kept so either can be read from the other.
20
- *
21
- * `update(viewport)` selects, then sets tile states, then prunes requests, then resizes the cache,
22
- * in deck.gl's order. Where it departs is `/docs/design/graph`'s table: a tile is fossil's
23
- * `{ type, z, tile }`, the level is chosen by published row counts, a tile is in view by its
24
- * published box, and the tiles wanted in one tick are read as one batch, whose read is aborted once
25
- * no tile in it is wanted.
26
- */
27
- export declare class Tileset2D {
28
- #private;
29
- constructor(options: TilesetOptions);
30
- get tiles(): Tile[];
31
- get selectedTiles(): readonly Tile[];
32
- /** Moves whenever the selected or visible set, or what a tile holds, may have changed. */
33
- get frame(): number;
34
- /** The zoom the last selection chose, or `null` before one. */
35
- get z(): number | null;
36
- get isLoaded(): boolean;
37
- get maxCacheSize(): number;
38
- get maxCacheByteSize(): number;
39
- /** The matrices, from `corpus.tileMatrix(type)`. A new set empties the cache. */
40
- setMatrix(matrix: TileMatrixSet): void;
41
- /** The tiles `scan.plan()` kept, by zoom — asked once per question, never per camera move. */
42
- setPlan(planned: readonly TileAddress[]): void;
43
- /**
44
- * The question changed: every tile is marked for reload and keeps its content until the new
45
- * answer arrives — `TileLayer`'s `reloadAll` when its `data` moves. A cached tile that is not
46
- * selected is dropped, since nothing will ask it again under the old question.
47
- */
48
- reloadAll(): void;
49
- /**
50
- * Select what the viewport needs and refine; returns a frame number that moves whenever the
51
- * visible set may have changed.
52
- */
53
- update(viewport: Viewport, limit: number): number;
54
- /** Re-run refinement after a load, with no change of viewport. */
55
- refresh(): number;
56
- /** Abort everything and forget the cache. */
57
- finalize(): void;
58
- }
59
- //# sourceMappingURL=tileset.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tileset.d.ts","sourceRoot":"","sources":["../../src/core/tileset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGtE,OAAO,EAAE,IAAI,EAAoB,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AACjE,OAAO,EAA2C,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKvF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACnD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACpC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,qBAAa,SAAS;;gBAcR,OAAO,EAAE,cAAc;IASnC,IAAI,KAAK,IAAI,IAAI,EAAE,CAElB;IAED,IAAI,aAAa,IAAI,SAAS,IAAI,EAAE,CAEnC;IAED,0FAA0F;IAC1F,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,+DAA+D;IAC/D,IAAI,CAAC,IAAI,MAAM,GAAG,IAAI,CAErB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,iFAAiF;IACjF,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAOtC,8FAA8F;IAC9F,OAAO,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,IAAI;IAW9C;;;;OAIG;IACH,SAAS,IAAI,IAAI;IAcjB;;;OAGG;IACH,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IA2BjD,kEAAkE;IAClE,OAAO,IAAI,MAAM;IAIjB,6CAA6C;IAC7C,QAAQ,IAAI,IAAI;CAoGjB"}
@@ -1,177 +0,0 @@
1
- var w = (o) => {
2
- throw TypeError(o);
3
- };
4
- var L = (o, e, i) => e.has(o) || w("Cannot " + i);
5
- var t = (o, e, i) => (L(o, e, "read from private field"), i ? i.call(o) : e.get(o)), c = (o, e, i) => e.has(o) ? w("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(o) : e.set(o, i), l = (o, e, i, s) => (L(o, e, "write to private field"), s ? s.call(o, i) : e.set(o, i), i), d = (o, e, i) => (L(o, e, "access private method"), i);
6
- import { refine as $ } from "./refine.js";
7
- import { RequestScheduler as D } from "./scheduler.js";
8
- import { Tile as O } from "./tile.js";
9
- import { selectLevel as U, tileId as E, centreOf as _, parentOf as I } from "./tile-matrix.js";
10
- const k = 5;
11
- var f, y, h, z, g, u, m, b, S, x, M, T, a, v, R, q, A, B, N, C;
12
- class Z {
13
- constructor(e) {
14
- c(this, a);
15
- c(this, f);
16
- c(this, y);
17
- c(this, h, /* @__PURE__ */ new Map());
18
- c(this, z, null);
19
- c(this, g, /* @__PURE__ */ new Map());
20
- c(this, u, []);
21
- c(this, m, null);
22
- c(this, b, 0);
23
- c(this, S, null);
24
- c(this, x, !0);
25
- c(this, M, 0);
26
- c(this, T, "");
27
- l(this, f, e), l(this, y, new D({
28
- run: (i, s) => e.load(i.map((r) => r.address), s),
29
- debounceTime: e.debounceTime,
30
- maxRequests: e.maxRequests ?? 1
31
- }));
32
- }
33
- get tiles() {
34
- return [...t(this, h).values()].sort((e, i) => e.z - i.z);
35
- }
36
- get selectedTiles() {
37
- return t(this, u);
38
- }
39
- /** Moves whenever the selected or visible set, or what a tile holds, may have changed. */
40
- get frame() {
41
- return t(this, M);
42
- }
43
- /** The zoom the last selection chose, or `null` before one. */
44
- get z() {
45
- return t(this, S);
46
- }
47
- get isLoaded() {
48
- return t(this, u).every((e) => e.isLoaded);
49
- }
50
- get maxCacheSize() {
51
- return t(this, f).maxCacheSize ?? k * Math.max(1, t(this, u).length);
52
- }
53
- get maxCacheByteSize() {
54
- return t(this, f).maxCacheByteSize ?? Number.POSITIVE_INFINITY;
55
- }
56
- /** The matrices, from `corpus.tileMatrix(type)`. A new set empties the cache. */
57
- setMatrix(e) {
58
- e !== t(this, z) && (l(this, z, e), this.finalize(), l(this, x, !0));
59
- }
60
- /** The tiles `scan.plan()` kept, by zoom — asked once per question, never per camera move. */
61
- setPlan(e) {
62
- const i = /* @__PURE__ */ new Map();
63
- for (const { tile: s, z: r } of e) {
64
- let n = i.get(r);
65
- n || i.set(r, n = /* @__PURE__ */ new Set()), n.add(s);
66
- }
67
- l(this, g, i), l(this, x, !0);
68
- }
69
- /**
70
- * The question changed: every tile is marked for reload and keeps its content until the new
71
- * answer arrives — `TileLayer`'s `reloadAll` when its `data` moves. A cached tile that is not
72
- * selected is dropped, since nothing will ask it again under the old question.
73
- */
74
- reloadAll() {
75
- var e, i;
76
- for (const [s, r] of t(this, h))
77
- t(this, u).includes(r) ? r.setNeedsReload() : (r.abort(), t(this, h).delete(s), (i = (e = t(this, f)).onTileUnload) == null || i.call(e, r));
78
- d(this, a, C).call(this), l(this, x, !0);
79
- }
80
- /**
81
- * Select what the viewport needs and refine; returns a frame number that moves whenever the
82
- * visible set may have changed.
83
- */
84
- update(e, i) {
85
- const s = t(this, z);
86
- if (!s) return t(this, M);
87
- if (t(this, x) || i !== t(this, b) || !t(this, m) || e.xMin !== t(this, m).xMin || e.yMin !== t(this, m).yMin || e.xMax !== t(this, m).xMax || e.yMax !== t(this, m).yMax) {
88
- l(this, x, !1), l(this, m, e), l(this, b, i);
89
- const n = U(s, e, i, t(this, g));
90
- l(this, S, (n == null ? void 0 : n.z) ?? null);
91
- const V = n ? n.tiles.map((p) => ({ type: s.type, z: n.z, tile: p })) : [];
92
- for (const p of t(this, u)) p.isSelected = !1;
93
- l(this, u, V.map((p) => d(this, a, R).call(this, p)));
94
- for (const p of t(this, u)) p.isSelected = !0;
95
- d(this, a, C).call(this), d(this, a, q).call(this);
96
- }
97
- return d(this, a, v).call(this);
98
- }
99
- /** Re-run refinement after a load, with no change of viewport. */
100
- refresh() {
101
- return d(this, a, v).call(this);
102
- }
103
- /** Abort everything and forget the cache. */
104
- finalize() {
105
- for (const e of t(this, h).values()) e.abort();
106
- t(this, y).clear(), t(this, h).clear(), l(this, u, []), l(this, S, null), l(this, x, !0);
107
- }
108
- }
109
- f = new WeakMap(), y = new WeakMap(), h = new WeakMap(), z = new WeakMap(), g = new WeakMap(), u = new WeakMap(), m = new WeakMap(), b = new WeakMap(), S = new WeakMap(), x = new WeakMap(), M = new WeakMap(), T = new WeakMap(), a = new WeakSet(), v = function() {
110
- $(t(this, h).values()), d(this, a, B).call(this), d(this, a, N).call(this);
111
- const e = (s) => `${s.id}${s.isVisible ? "+" : ""}${s.isSelected ? "*" : ""}:${s.content ? 1 : 0}`, i = [...t(this, h).values()].map(e).join(",");
112
- return i !== t(this, T) && (l(this, T, i), l(this, M, t(this, M) + 1)), t(this, M);
113
- }, R = function(e) {
114
- const i = E(e);
115
- let s = t(this, h).get(i);
116
- return s || (s = new O(e), t(this, h).set(i, s)), s;
117
- }, q = function() {
118
- for (const e of t(this, u))
119
- e.isLoaded || e.isLoading || e.loadData({
120
- scheduler: t(this, y),
121
- priority: (i) => d(this, a, A).call(this, i),
122
- onLoad: (i) => {
123
- var s, r;
124
- return (r = (s = t(this, f)).onTileLoad) == null ? void 0 : r.call(s, i);
125
- },
126
- onError: (i, s) => {
127
- var r, n;
128
- return (n = (r = t(this, f)).onTileError) == null ? void 0 : n.call(r, i, s);
129
- }
130
- });
131
- }, /** `_getRequestPriority`: `-1` drops a tile nobody wants; the rest go nearest the centre first. */
132
- A = function(e) {
133
- if (!e.isSelected && !e.isVisible) return -1;
134
- const i = t(this, z), s = t(this, m);
135
- if (!i || !s) return 0;
136
- const r = _(i, e.address);
137
- return r ? Math.hypot(r[0] - (s.xMin + s.xMax) / 2, r[1] - (s.yMin + s.yMax) / 2) : 0;
138
- }, /**
139
- * Always, where deck.gl waits for `maxRequests` to be exceeded: the one slot is the only one. A
140
- * batch is the unit aborted, so a tile nobody wants rides out a batch somebody else still does.
141
- */
142
- B = function() {
143
- t(this, y).prune();
144
- }, /** Evicts tiles neither visible nor selected, in insertion order — deck.gl's, and not LRU. */
145
- N = function() {
146
- var i, s;
147
- let e = 0;
148
- for (const r of t(this, h).values()) e += r.byteLength;
149
- if (!(t(this, h).size <= this.maxCacheSize && e <= this.maxCacheByteSize)) {
150
- for (const [r, n] of t(this, h)) {
151
- if (t(this, h).size <= this.maxCacheSize && e <= this.maxCacheByteSize) break;
152
- n.isVisible || n.isSelected || (e -= n.byteLength, n.abort(), t(this, h).delete(r), (s = (i = t(this, f)).onTileUnload) == null || s.call(i, n));
153
- }
154
- d(this, a, C).call(this);
155
- }
156
- }, /** Each tile's parent is its nearest ancestor in the cache — `_rebuildTree`. */
157
- C = function() {
158
- const e = t(this, z);
159
- for (const i of t(this, h).values())
160
- i.parent = null, i.children = [];
161
- if (e)
162
- for (const i of t(this, h).values()) {
163
- let s = I(e, i.address);
164
- for (; s; ) {
165
- const r = t(this, h).get(E(s));
166
- if (r) {
167
- i.parent = r, r.children.push(i);
168
- break;
169
- }
170
- s = I(e, s);
171
- }
172
- }
173
- };
174
- export {
175
- Z as Tileset2D
176
- };
177
- //# sourceMappingURL=tileset.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tileset.js","sources":["../../src/core/tileset.ts"],"sourcesContent":["import type { TileAddress, TileMatrixSet } from \"@fossil-lang/corpus\";\nimport { refine } from \"./refine\";\nimport { RequestScheduler } from \"./scheduler\";\nimport { Tile, type TileContent, type TileLoader } from \"./tile\";\nimport { centreOf, parentOf, selectLevel, tileId, type Viewport } from \"./tile-matrix\";\n\n/** deck.gl's `DEFAULT_CACHE_SCALE`: the cache holds five times what is selected. */\nconst DEFAULT_CACHE_SCALE = 5;\n\nexport interface TilesetOptions {\n load: TileLoader;\n onTileLoad?: (tile: Tile) => void;\n onTileError?: (error: unknown, tile: Tile) => void;\n onTileUnload?: (tile: Tile) => void;\n /** Tiles kept; five times the selected count when absent. */\n maxCacheSize?: number;\n /** Bytes kept; unbounded when absent. */\n maxCacheByteSize?: number;\n /** Batches in flight — one: see `RequestScheduler`. */\n maxRequests?: number;\n debounceTime?: number;\n}\n\n/**\n * **deck.gl's `Tileset2D` with the loader swapped for the corpus** — `modules/geo-layers/src/\n * tileset-2d/tileset-2d.ts`, its names kept so either can be read from the other.\n *\n * `update(viewport)` selects, then sets tile states, then prunes requests, then resizes the cache,\n * in deck.gl's order. Where it departs is `/docs/design/graph`'s table: a tile is fossil's\n * `{ type, z, tile }`, the level is chosen by published row counts, a tile is in view by its\n * published box, and the tiles wanted in one tick are read as one batch, whose read is aborted once\n * no tile in it is wanted.\n */\nexport class Tileset2D {\n readonly #options: TilesetOptions;\n readonly #scheduler: RequestScheduler<Tile, TileContent>;\n readonly #cache = new Map<string, Tile>();\n #matrix: TileMatrixSet | null = null;\n #planned: ReadonlyMap<number, ReadonlySet<number>> = new Map();\n #selected: Tile[] = [];\n #viewport: Viewport | null = null;\n #limit = 0;\n #z: number | null = null;\n #stale = true;\n #frame = 0;\n #signature = \"\";\n\n constructor(options: TilesetOptions) {\n this.#options = options;\n this.#scheduler = new RequestScheduler({\n run: (tiles, signal) => options.load(tiles.map((tile) => tile.address), signal),\n debounceTime: options.debounceTime,\n maxRequests: options.maxRequests ?? 1,\n });\n }\n\n get tiles(): Tile[] {\n return [...this.#cache.values()].sort((a, b) => a.z - b.z);\n }\n\n get selectedTiles(): readonly Tile[] {\n return this.#selected;\n }\n\n /** Moves whenever the selected or visible set, or what a tile holds, may have changed. */\n get frame(): number {\n return this.#frame;\n }\n\n /** The zoom the last selection chose, or `null` before one. */\n get z(): number | null {\n return this.#z;\n }\n\n get isLoaded(): boolean {\n return this.#selected.every((tile) => tile.isLoaded);\n }\n\n get maxCacheSize(): number {\n return this.#options.maxCacheSize ?? DEFAULT_CACHE_SCALE * Math.max(1, this.#selected.length);\n }\n\n get maxCacheByteSize(): number {\n return this.#options.maxCacheByteSize ?? Number.POSITIVE_INFINITY;\n }\n\n /** The matrices, from `corpus.tileMatrix(type)`. A new set empties the cache. */\n setMatrix(matrix: TileMatrixSet): void {\n if (matrix === this.#matrix) return;\n this.#matrix = matrix;\n this.finalize();\n this.#stale = true;\n }\n\n /** The tiles `scan.plan()` kept, by zoom — asked once per question, never per camera move. */\n setPlan(planned: readonly TileAddress[]): void {\n const byZoom = new Map<number, Set<number>>();\n for (const { tile, z } of planned) {\n let tiles = byZoom.get(z);\n if (!tiles) byZoom.set(z, (tiles = new Set()));\n tiles.add(tile);\n }\n this.#planned = byZoom;\n this.#stale = true;\n }\n\n /**\n * The question changed: every tile is marked for reload and keeps its content until the new\n * answer arrives — `TileLayer`'s `reloadAll` when its `data` moves. A cached tile that is not\n * selected is dropped, since nothing will ask it again under the old question.\n */\n reloadAll(): void {\n for (const [id, tile] of this.#cache) {\n if (!this.#selected.includes(tile)) {\n tile.abort();\n this.#cache.delete(id);\n this.#options.onTileUnload?.(tile);\n } else {\n tile.setNeedsReload();\n }\n }\n this.#rebuildTree();\n this.#stale = true;\n }\n\n /**\n * Select what the viewport needs and refine; returns a frame number that moves whenever the\n * visible set may have changed.\n */\n update(viewport: Viewport, limit: number): number {\n const matrix = this.#matrix;\n if (!matrix) return this.#frame;\n const moved =\n this.#stale ||\n limit !== this.#limit ||\n !this.#viewport ||\n viewport.xMin !== this.#viewport.xMin ||\n viewport.yMin !== this.#viewport.yMin ||\n viewport.xMax !== this.#viewport.xMax ||\n viewport.yMax !== this.#viewport.yMax;\n if (moved) {\n this.#stale = false;\n this.#viewport = viewport;\n this.#limit = limit;\n const level = selectLevel(matrix, viewport, limit, this.#planned);\n this.#z = level?.z ?? null;\n const wanted = level ? level.tiles.map((tile) => ({ type: matrix.type, z: level.z, tile })) : [];\n for (const tile of this.#selected) tile.isSelected = false;\n this.#selected = wanted.map((address) => this.#getTile(address));\n for (const tile of this.#selected) tile.isSelected = true;\n this.#rebuildTree();\n this.#loadSelected();\n }\n return this.#refresh();\n }\n\n /** Re-run refinement after a load, with no change of viewport. */\n refresh(): number {\n return this.#refresh();\n }\n\n /** Abort everything and forget the cache. */\n finalize(): void {\n for (const tile of this.#cache.values()) tile.abort();\n this.#scheduler.clear();\n this.#cache.clear();\n this.#selected = [];\n this.#z = null;\n this.#stale = true;\n }\n\n #refresh(): number {\n refine(this.#cache.values());\n this.#pruneRequests();\n this.#resizeCache();\n const shown = (tile: Tile) => `${tile.id}${tile.isVisible ? \"+\" : \"\"}${tile.isSelected ? \"*\" : \"\"}:${tile.content ? 1 : 0}`;\n const signature = [...this.#cache.values()].map(shown).join(\",\");\n if (signature !== this.#signature) {\n this.#signature = signature;\n this.#frame += 1;\n }\n return this.#frame;\n }\n\n #getTile(address: TileAddress): Tile {\n const id = tileId(address);\n let tile = this.#cache.get(id);\n if (!tile) {\n tile = new Tile(address);\n this.#cache.set(id, tile);\n }\n return tile;\n }\n\n #loadSelected(): void {\n for (const tile of this.#selected) {\n if (tile.isLoaded || tile.isLoading) continue;\n void tile.loadData({\n scheduler: this.#scheduler,\n priority: (t) => this.#priority(t),\n onLoad: (t) => this.#options.onTileLoad?.(t),\n onError: (error, t) => this.#options.onTileError?.(error, t),\n });\n }\n }\n\n /** `_getRequestPriority`: `-1` drops a tile nobody wants; the rest go nearest the centre first. */\n #priority(tile: Tile): number {\n if (!tile.isSelected && !tile.isVisible) return -1;\n const matrix = this.#matrix;\n const view = this.#viewport;\n if (!matrix || !view) return 0;\n const centre = centreOf(matrix, tile.address);\n if (!centre) return 0;\n return Math.hypot(centre[0] - (view.xMin + view.xMax) / 2, centre[1] - (view.yMin + view.yMax) / 2);\n }\n\n /**\n * Always, where deck.gl waits for `maxRequests` to be exceeded: the one slot is the only one. A\n * batch is the unit aborted, so a tile nobody wants rides out a batch somebody else still does.\n */\n #pruneRequests(): void {\n this.#scheduler.prune();\n }\n\n /** Evicts tiles neither visible nor selected, in insertion order — deck.gl's, and not LRU. */\n #resizeCache(): void {\n let bytes = 0;\n for (const tile of this.#cache.values()) bytes += tile.byteLength;\n if (this.#cache.size <= this.maxCacheSize && bytes <= this.maxCacheByteSize) return;\n for (const [id, tile] of this.#cache) {\n if (this.#cache.size <= this.maxCacheSize && bytes <= this.maxCacheByteSize) break;\n if (tile.isVisible || tile.isSelected) continue;\n bytes -= tile.byteLength;\n tile.abort();\n this.#cache.delete(id);\n this.#options.onTileUnload?.(tile);\n }\n this.#rebuildTree();\n }\n\n /** Each tile's parent is its nearest ancestor in the cache — `_rebuildTree`. */\n #rebuildTree(): void {\n const matrix = this.#matrix;\n for (const tile of this.#cache.values()) {\n tile.parent = null;\n tile.children = [];\n }\n if (!matrix) return;\n for (const tile of this.#cache.values()) {\n let up = parentOf(matrix, tile.address);\n while (up) {\n const found = this.#cache.get(tileId(up));\n if (found) {\n tile.parent = found;\n found.children.push(tile);\n break;\n }\n up = parentOf(matrix, up);\n }\n }\n }\n}\n"],"names":["DEFAULT_CACHE_SCALE","Tileset2D","options","__privateAdd","_Tileset2D_instances","_options","_scheduler","_cache","_matrix","_planned","_selected","_viewport","_limit","_z","_stale","_frame","_signature","__privateSet","RequestScheduler","tiles","signal","tile","__privateGet","a","b","matrix","planned","byZoom","z","id","_b","_a","__privateMethod","rebuildTree_fn","viewport","limit","level","selectLevel","wanted","address","getTile_fn","loadSelected_fn","refresh_fn","refine","pruneRequests_fn","resizeCache_fn","shown","signature","tileId","Tile","t","priority_fn","error","view","centre","centreOf","bytes","up","parentOf","found"],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- import { Sim } from './graph-sim';
2
- /**
3
- * The coefficients and the drawing options a graph this size wants.
4
- *
5
- * Returned together because they are one judgement asked of one number, and splitting them into two
6
- * exports that must be called with the same argument is how they drift apart. The caller still keeps
7
- * them apart downstream — a `Sim` rebuilds nothing and `links` is a uniform — which is the split
8
- * that actually costs something.
9
- *
10
- * **The mark scale left with `Display`.** This used to answer a `pointScale` too, interpolated from
11
- * 1.5 to 0.5 with the corpus, and nothing ever called it: the field it fed was a reader's multiplier
12
- * over the radius ramp `lookFrom` computes from `marks`, and two ways to size a mark is one too
13
- * many. What a host with a large corpus wants is the tenant policy — *start your users here* — over
14
- * the declared axes, which is where a computed fit belongs.
15
- *
16
- * **`spaceSize` is deliberately not here.** The original scaled the simulation box from 2,048 to
17
- * 8,192 with the corpus, which is coherent when a layout is computed on the fly and incoherent once
18
- * positions are authority: the box is the coordinate space a source's positions are expressed in and
19
- * a spatial query is asked against, so resizing it by node count would move the index under the
20
- * camera. It is not a constant of ours either, for the same reason turned around — it is the
21
- * tile matrix's extent, and the renderer sets it from there.
22
- */
23
- export declare function adaptive(nodes: number): {
24
- sim: Sim;
25
- links: boolean;
26
- };
27
- //# sourceMappingURL=adaptive.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"adaptive.d.ts","sourceRoot":"","sources":["../../src/render/adaptive.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAgCvC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAgBpE"}
@@ -1,25 +0,0 @@
1
- const r = (t, n, a) => Math.min(a, Math.max(n, t)), i = (t, n, a) => t + (n - t) * r(a, 0, 1);
2
- function c(t) {
3
- return r((Math.log10(Math.max(t, 1)) - 1) / 4, 0, 1);
4
- }
5
- function e(t) {
6
- const n = c(t);
7
- return {
8
- sim: {
9
- // Bigger graphs need less push and more damping, or they never settle.
10
- repulsion: i(1.2, 0.4, n),
11
- friction: i(0.7, 0.92, n),
12
- linkSpring: i(0.5, 0.25, n),
13
- linkDistance: i(30, 12, n),
14
- gravity: i(0.35, 0.08, n),
15
- cluster: 0.15
16
- },
17
- // Past a quarter of a million links the edge layer is fog, and fog costs a draw call per frame
18
- // to render. Below it, links are most of what a reader is actually looking at.
19
- links: t < 25e4
20
- };
21
- }
22
- export {
23
- e as adaptive
24
- };
25
- //# sourceMappingURL=adaptive.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"adaptive.js","sources":["../../src/render/adaptive.ts"],"sourcesContent":["import type { Sim } from \"./graph-sim\";\n\n/**\n * How a graph of *this size* should be drawn — force coefficients and two render\n * switches, interpolated continuously against node count.\n *\n * Absorbed from `@fossil-lang/viewer`'s `getAdaptiveConfig` when fossil stopped shipping a viewer, which filed it under\n * \"level-of-detail policy\". Reading it, that is not quite what it is, and the difference matters:\n * almost all of it is **simulation tuning** — repulsion, friction, spring, gravity — plus two\n * genuinely render-side switches. Level of detail in the bounded sense is the zoom of fossil's cell\n * pyramid the tileset draws at, and is a different mechanism entirely.\n *\n * That means most of this only applies under `simulate: true`, which ADR-0001 made the opt-in case.\n * It is still worth having: the host with arrays in hand and no precomputed layout is exactly the\n * host that runs a live simulation, and one set of production-tuned numbers beats each call site\n * inventing its own.\n *\n * **The continuous interpolation is the design**, not an implementation detail. Breakpoints snap —\n * a graph crossing 10,000 nodes would visibly jump — and Cosmograph 1.x is the cautionary example.\n * The constants are tuned across 10 to 100,000 nodes and divergence from them is a defect.\n */\n\nconst clamp = (value: number, lo: number, hi: number): number =>\n Math.min(hi, Math.max(lo, value));\n\nconst lerp = (a: number, b: number, t: number): number => a + (b - a) * clamp(t, 0, 1);\n\n/** `0` at about ten nodes, `1` at about a hundred thousand — log₁₀, because node counts are. */\nfunction scaleOfCount(nodes: number): number {\n return clamp((Math.log10(Math.max(nodes, 1)) - 1) / 4, 0, 1);\n}\n\n/**\n * The coefficients and the drawing options a graph this size wants.\n *\n * Returned together because they are one judgement asked of one number, and splitting them into two\n * exports that must be called with the same argument is how they drift apart. The caller still keeps\n * them apart downstream — a `Sim` rebuilds nothing and `links` is a uniform — which is the split\n * that actually costs something.\n *\n * **The mark scale left with `Display`.** This used to answer a `pointScale` too, interpolated from\n * 1.5 to 0.5 with the corpus, and nothing ever called it: the field it fed was a reader's multiplier\n * over the radius ramp `lookFrom` computes from `marks`, and two ways to size a mark is one too\n * many. What a host with a large corpus wants is the tenant policy — *start your users here* — over\n * the declared axes, which is where a computed fit belongs.\n *\n * **`spaceSize` is deliberately not here.** The original scaled the simulation box from 2,048 to\n * 8,192 with the corpus, which is coherent when a layout is computed on the fly and incoherent once\n * positions are authority: the box is the coordinate space a source's positions are expressed in and\n * a spatial query is asked against, so resizing it by node count would move the index under the\n * camera. It is not a constant of ours either, for the same reason turned around — it is the\n * tile matrix's extent, and the renderer sets it from there.\n */\nexport function adaptive(nodes: number): { sim: Sim; links: boolean } {\n const t = scaleOfCount(nodes);\n return {\n sim: {\n // Bigger graphs need less push and more damping, or they never settle.\n repulsion: lerp(1.2, 0.4, t),\n friction: lerp(0.7, 0.92, t),\n linkSpring: lerp(0.5, 0.25, t),\n linkDistance: lerp(30, 12, t),\n gravity: lerp(0.35, 0.08, t),\n cluster: 0.15,\n },\n // Past a quarter of a million links the edge layer is fog, and fog costs a draw call per frame\n // to render. Below it, links are most of what a reader is actually looking at.\n links: nodes < 250_000,\n };\n}\n"],"names":["clamp","value","lo","hi","lerp","a","b","t","scaleOfCount","nodes","adaptive"],"mappings":"AAsBA,MAAMA,IAAQ,CAACC,GAAeC,GAAYC,MACxC,KAAK,IAAIA,GAAI,KAAK,IAAID,GAAID,CAAK,CAAC,GAE5BG,IAAO,CAACC,GAAWC,GAAWC,MAAsBF,KAAKC,IAAID,KAAKL,EAAMO,GAAG,GAAG,CAAC;AAGrF,SAASC,EAAaC,GAAuB;AAC3C,SAAOT,GAAO,KAAK,MAAM,KAAK,IAAIS,GAAO,CAAC,CAAC,IAAI,KAAK,GAAG,GAAG,CAAC;AAC7D;AAuBO,SAASC,EAASD,GAA6C;AACpE,QAAMF,IAAIC,EAAaC,CAAK;AAC5B,SAAO;AAAA,IACL,KAAK;AAAA;AAAA,MAEH,WAAWL,EAAK,KAAK,KAAKG,CAAC;AAAA,MAC3B,UAAUH,EAAK,KAAK,MAAMG,CAAC;AAAA,MAC3B,YAAYH,EAAK,KAAK,MAAMG,CAAC;AAAA,MAC7B,cAAcH,EAAK,IAAI,IAAIG,CAAC;AAAA,MAC5B,SAASH,EAAK,MAAM,MAAMG,CAAC;AAAA,MAC3B,SAAS;AAAA,IAAA;AAAA;AAAA;AAAA,IAIX,OAAOE,IAAQ;AAAA,EAAA;AAEnB;"}