mudlet-map-renderer 1.0.0 → 1.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 (106) hide show
  1. package/README.md +520 -0
  2. package/dist/AreaMapRenderer.d.ts +125 -0
  3. package/dist/CullingManager.d.ts +15 -0
  4. package/dist/ExitRenderer.d.ts +109 -0
  5. package/dist/InteractionHandler.d.ts +47 -0
  6. package/dist/MapGraph.d.ts +28 -0
  7. package/dist/MapReader-mU_4JWv_.js +224 -0
  8. package/dist/MapReader-mU_4JWv_.js.map +1 -0
  9. package/dist/MapState.d.ts +110 -0
  10. package/dist/PathData.d.ts +18 -0
  11. package/dist/PathFinder.d.ts +12 -0
  12. package/dist/ScenePipeline.d.ts +226 -0
  13. package/dist/SvgTypes.d.ts +21 -0
  14. package/dist/TypedEventEmitter.d.ts +17 -0
  15. package/dist/binary/BinaryMapReader.d.ts +36 -0
  16. package/dist/binary/index.d.ts +2 -0
  17. package/dist/binary.mjs +34 -0
  18. package/dist/binary.mjs.map +1 -0
  19. package/dist/camera/Camera.d.ts +106 -0
  20. package/dist/coord/CoordFn.d.ts +13 -0
  21. package/dist/directions.d.ts +25 -0
  22. package/dist/draw/DrawCommand.d.ts +104 -0
  23. package/dist/draw/DrawCommandBuilder.d.ts +19 -0
  24. package/dist/export/CanvasExporter.d.ts +71 -0
  25. package/dist/export/Exporter.d.ts +58 -0
  26. package/dist/export/PngExporter.d.ts +23 -0
  27. package/dist/export/SvgExporter.d.ts +19 -0
  28. package/dist/export/canvasToBytes.d.ts +19 -0
  29. package/dist/export/clipSceneToViewport.d.ts +48 -0
  30. package/dist/export/flushSceneShapes.d.ts +21 -0
  31. package/dist/export/sceneBounds.d.ts +24 -0
  32. package/dist/hit/HitTester.d.ts +101 -0
  33. package/dist/index.d.ts +61 -0
  34. package/dist/index.mjs +6656 -0
  35. package/dist/index.mjs.map +1 -0
  36. package/dist/lens/ExplorationLens.d.ts +29 -0
  37. package/dist/lens/RoomLens.d.ts +47 -0
  38. package/dist/lens/composeLenses.d.ts +31 -0
  39. package/dist/lens/index.d.ts +5 -0
  40. package/dist/overlay/AmbientLightOverlay.d.ts +32 -0
  41. package/dist/overlay/LiveEffect.d.ts +33 -0
  42. package/dist/overlay/SceneOverlay.d.ts +68 -0
  43. package/dist/reader/Area.d.ts +63 -0
  44. package/dist/reader/Exit.d.ts +15 -0
  45. package/dist/reader/MapReader.d.ts +34 -0
  46. package/dist/reader/Plane.d.ts +33 -0
  47. package/dist/render/CanvasRenderer.d.ts +17 -0
  48. package/dist/render/RecordingLayer.d.ts +158 -0
  49. package/dist/render/SvgRenderer.d.ts +7 -0
  50. package/dist/render/shapeToRecording.d.ts +3 -0
  51. package/dist/rendering/KonvaRenderBackend.d.ts +122 -0
  52. package/dist/rendering/MapRenderer.d.ts +213 -0
  53. package/dist/rendering/SceneManager.d.ts +54 -0
  54. package/dist/scene/AmbientLightStyle.d.ts +29 -0
  55. package/dist/scene/GridStyle.d.ts +21 -0
  56. package/dist/scene/InnerExitStyle.d.ts +24 -0
  57. package/dist/scene/OverlayStyle.d.ts +47 -0
  58. package/dist/scene/RoomStyle.d.ts +32 -0
  59. package/dist/scene/Shape.d.ts +151 -0
  60. package/dist/scene/SpecialExitStyle.d.ts +37 -0
  61. package/dist/scene/StubStyle.d.ts +15 -0
  62. package/dist/scene/elements/ExitLayout.d.ts +22 -0
  63. package/dist/scene/elements/GridLayout.d.ts +24 -0
  64. package/dist/scene/elements/LabelLayout.d.ts +11 -0
  65. package/dist/scene/elements/OverlayLayout.d.ts +14 -0
  66. package/dist/scene/elements/RoomLayout.d.ts +19 -0
  67. package/dist/scene/elements/SpecialExitLayout.d.ts +19 -0
  68. package/dist/scene/elements/StubLayout.d.ts +19 -0
  69. package/dist/style/Style.d.ts +60 -0
  70. package/dist/style/applyStyle.d.ts +3 -0
  71. package/dist/style/index.d.ts +21 -0
  72. package/dist/style/shape/BlueprintStyle.d.ts +11 -0
  73. package/dist/style/shape/ConstructionStyle.d.ts +17 -0
  74. package/dist/style/shape/IsometricStyle.d.ts +32 -0
  75. package/dist/style/shape/NeonStyle.d.ts +17 -0
  76. package/dist/style/shape/ParchmentStyle.d.ts +13 -0
  77. package/dist/style/shape/SciFiStyle.d.ts +16 -0
  78. package/dist/style/shape/SketchyStyle.d.ts +22 -0
  79. package/dist/style/shape/index.d.ts +25 -0
  80. package/dist/style/shape/paintMap.d.ts +25 -0
  81. package/dist/style/shape/wobble.d.ts +24 -0
  82. package/{src/types/MapData.ts → dist/types/MapData.d.ts} +70 -90
  83. package/dist/types/Settings.d.ts +206 -0
  84. package/dist/utils/color.d.ts +12 -0
  85. package/dist/utils/textMeasure.d.ts +38 -0
  86. package/package.json +67 -37
  87. package/demo/colors.json +0 -1
  88. package/demo/index.html +0 -102
  89. package/demo/main.ts +0 -389
  90. package/demo/mapExport.json +0 -1
  91. package/demo/tsconfig.json +0 -11
  92. package/src/ExitRenderer.ts +0 -275
  93. package/src/PathFinder.ts +0 -93
  94. package/src/PathRenderer.ts +0 -129
  95. package/src/Renderer.ts +0 -374
  96. package/src/directions.ts +0 -66
  97. package/src/index.ts +0 -4
  98. package/src/reader/Area.ts +0 -96
  99. package/src/reader/Exit.ts +0 -36
  100. package/src/reader/ExplorationArea.ts +0 -132
  101. package/src/reader/MapReader.ts +0 -123
  102. package/src/reader/Plane.ts +0 -42
  103. package/tsconfig.json +0 -17
  104. package/vercel.json +0 -5
  105. package/vite.config.ts +0 -29
  106. package/vite.demo.config.ts +0 -15
@@ -0,0 +1,29 @@
1
+ import { RoomLens } from './RoomLens';
2
+ /**
3
+ * Fog-of-war lens: rooms render only when their id is in the visited set.
4
+ *
5
+ * Default exit treatment is left to {@link RoomLens}'s built-in derivation
6
+ * (both visible → full, one visible → stub, neither → hidden), which produces
7
+ * the "explored frontier" look without any extra wiring.
8
+ *
9
+ * Mutations bump {@link getVersion} so a composing renderer can detect the
10
+ * change; the renderer still needs an explicit `refresh()` after mutation —
11
+ * the lens doesn't emit events.
12
+ */
13
+ export declare class ExplorationLens implements RoomLens {
14
+ private readonly visited;
15
+ private version;
16
+ constructor(visited?: Iterable<number>);
17
+ isVisible(room: MapData.Room): boolean;
18
+ getVersion(): number;
19
+ hasVisited(roomId: number): boolean;
20
+ getVisitedRoomIds(): number[];
21
+ getVisitedCount(): number;
22
+ /** Returns true if the room was newly added. */
23
+ addVisited(roomId: number): boolean;
24
+ /** Returns the number of newly added rooms. */
25
+ addVisitedAll(roomIds: Iterable<number>): number;
26
+ /** Replace the visited set wholesale. */
27
+ setVisited(roomIds: Iterable<number>): void;
28
+ clear(): void;
29
+ }
@@ -0,0 +1,47 @@
1
+ import { default as IExit } from '../reader/Exit';
2
+ /**
3
+ * How the renderer should treat an exit whose endpoints are not both visible.
4
+ *
5
+ * - `"full"` — draw the exit normally (both endpoints are visible, or the
6
+ * lens overrides the default and wants the full line anyway).
7
+ * - `"stub"` — draw only a short stub leaving the visible endpoint; the
8
+ * far end isn't shown. This is the "explored frontier" look.
9
+ * - `"hidden"` — don't draw the exit at all.
10
+ *
11
+ * Cross-area exits (rooms in different `area` ids) are an orthogonal concept
12
+ * decided by raw room data, not by the lens. A lens that returns `"full"` for
13
+ * a cross-area exit still gets the cross-area arrow treatment.
14
+ */
15
+ export type ExitTreatment = "full" | "stub" | "hidden";
16
+ /**
17
+ * Visibility filter applied during scene build.
18
+ *
19
+ * `IArea` / `IPlane` / `IMapReader` are pure data — they return every room and
20
+ * every link exit the underlying map defines. The lens decides which of those
21
+ * actually paint, and (optionally) how partially-visible exits should be
22
+ * stubbed or hidden. Multiple concerns (exploration, guild scope, quest
23
+ * overlay, …) compose through {@link composeLenses}.
24
+ */
25
+ export interface RoomLens {
26
+ isVisible(room: MapData.Room): boolean;
27
+ /**
28
+ * Decide how an exit between `a` and `b` should be drawn.
29
+ *
30
+ * Optional — when omitted, treatment is derived from endpoint visibility:
31
+ * both visible → `"full"`, one visible → `"stub"`, neither → `"hidden"`.
32
+ */
33
+ getExitTreatment?(exit: IExit, a: MapData.Room, b: MapData.Room): ExitTreatment;
34
+ /**
35
+ * Monotonically increasing version. The renderer caches the value from the
36
+ * last build and rebuilds when it changes. Mutations on a stateful lens
37
+ * (e.g. {@link ExplorationLens.addVisited}) bump this; callers that mutate
38
+ * the lens still call `renderer.refresh()` explicitly.
39
+ */
40
+ getVersion(): number;
41
+ }
42
+ export declare const ALL_VISIBLE: RoomLens;
43
+ /**
44
+ * Default treatment when no lens supplies `getExitTreatment`: derive purely
45
+ * from endpoint visibility.
46
+ */
47
+ export declare function defaultExitTreatment(lens: RoomLens, _exit: IExit, a: MapData.Room, b: MapData.Room): ExitTreatment;
@@ -0,0 +1,31 @@
1
+ import { RoomLens } from './RoomLens';
2
+ /**
3
+ * How a composite lens reconciles disagreeing children when both expose
4
+ * `getExitTreatment`.
5
+ *
6
+ * - `"most-restrictive"` (default): `hidden` > `stub` > `full`. A single
7
+ * child that says hide wins. Safe default for stacked visibility filters.
8
+ * - `"least-restrictive"`: `full` > `stub` > `hidden`. Useful when lenses are
9
+ * additive scopes ("show guild rooms OR quest rooms").
10
+ * - `"first"`: the first child whose `getExitTreatment` returns non-undefined
11
+ * decides. Lets the caller pick a dominant lens by ordering.
12
+ */
13
+ export type ExitConflictStrategy = "most-restrictive" | "least-restrictive" | "first";
14
+ export type ComposeOptions = {
15
+ /** Defaults to `"most-restrictive"`. */
16
+ exitStrategy?: ExitConflictStrategy;
17
+ /**
18
+ * AND (visibility must hold in every lens) vs OR (any lens may grant
19
+ * visibility). Defaults to `"and"` — restrictive intersection.
20
+ */
21
+ visibility?: "and" | "or";
22
+ };
23
+ /**
24
+ * Combine multiple lenses into one. Visibility uses AND by default (a room
25
+ * must pass every lens to render); exit treatment uses most-restrictive when
26
+ * children disagree. Both behaviours are configurable via {@link ComposeOptions}.
27
+ *
28
+ * Composing zero lenses returns a no-op equivalent to `ALL_VISIBLE`.
29
+ */
30
+ export declare function composeLenses(...lenses: RoomLens[]): RoomLens;
31
+ export declare function composeLenses(options: ComposeOptions, ...lenses: RoomLens[]): RoomLens;
@@ -0,0 +1,5 @@
1
+ export type { RoomLens, ExitTreatment } from './RoomLens';
2
+ export { ALL_VISIBLE, defaultExitTreatment } from './RoomLens';
3
+ export { composeLenses } from './composeLenses';
4
+ export type { ComposeOptions, ExitConflictStrategy } from './composeLenses';
5
+ export { ExplorationLens } from './ExplorationLens';
@@ -0,0 +1,32 @@
1
+ import { MapState } from '../MapState';
2
+ import { ViewportBounds } from '../types/Settings';
3
+ import { AmbientLightParams } from '../scene/AmbientLightStyle';
4
+ import { Shape } from '../scene/Shape';
5
+ import { SceneOverlay, SceneOverlayContext } from './SceneOverlay';
6
+ export type AmbientLightOptions = Partial<AmbientLightParams>;
7
+ /**
8
+ * Vignette centered on the player room. Re-renders on position changes and
9
+ * viewport changes (pan/zoom/resize). Registering the overlay turns the effect
10
+ * on; removing it turns it off — there is no global settings flag.
11
+ *
12
+ * ```ts
13
+ * const ambient = new AmbientLightOverlay({ color: '#ffcc44', radius: 12 });
14
+ * renderer.addSceneOverlay('ambient-light', ambient);
15
+ * // later:
16
+ * ambient.setOptions({ intensity: 0.9 });
17
+ * renderer.removeSceneOverlay('ambient-light');
18
+ * ```
19
+ */
20
+ export declare class AmbientLightOverlay implements SceneOverlay {
21
+ private params;
22
+ private ctx?;
23
+ private viewportUnsub?;
24
+ private readonly onPosition;
25
+ constructor(options?: AmbientLightOptions);
26
+ /** Update tunables at runtime. Triggers a re-render. */
27
+ setOptions(options: AmbientLightOptions): void;
28
+ getOptions(): AmbientLightParams;
29
+ attach(ctx: SceneOverlayContext): void;
30
+ detach(): void;
31
+ render(state: MapState, bounds: ViewportBounds): Shape | void;
32
+ }
@@ -0,0 +1,33 @@
1
+ import { default as Konva } from 'konva';
2
+ import { ViewportBounds } from '../types/Settings';
3
+ /** Map-space → render-space coordinate transform. */
4
+ export type CoordinateTransform = (x: number, y: number) => {
5
+ x: number;
6
+ y: number;
7
+ };
8
+ /**
9
+ * Interactive-only animated effect. A {@link LiveEffect} receives a live Konva
10
+ * layer and viewport updates so it can react to pan/zoom and run its own
11
+ * animation loop.
12
+ *
13
+ * Exporters (SVG, PNG, PDF, …) skip `LiveEffect`s by design — use
14
+ * `SceneOverlay` when you need an overlay to appear in exports.
15
+ *
16
+ * ```ts
17
+ * class PulseEffect implements LiveEffect {
18
+ * private shape?: Konva.Shape;
19
+ * attach(layer: Konva.Layer) {
20
+ * this.shape = new Konva.Shape({ sceneFunc: (ctx) => { ... } });
21
+ * layer.add(this.shape);
22
+ * }
23
+ * updateViewport(bounds, scale) { ... }
24
+ * destroy() { this.shape?.destroy(); }
25
+ * }
26
+ * renderer.konvaBackend?.addLiveEffect('pulse', new PulseEffect());
27
+ * ```
28
+ */
29
+ export interface LiveEffect {
30
+ attach(layer: Konva.Layer): void;
31
+ updateViewport(bounds: ViewportBounds, scale: number, coordinateTransform: CoordinateTransform): void;
32
+ destroy(): void;
33
+ }
@@ -0,0 +1,68 @@
1
+ import { MapState } from '../MapState';
2
+ import { ViewportBounds } from '../types/Settings';
3
+ import { Shape } from '../scene/Shape';
4
+ /**
5
+ * Context handed to a {@link SceneOverlay} when it is registered. Gives the
6
+ * overlay access to {@link MapState} events, viewport changes, and a way to
7
+ * request its own re-render.
8
+ */
9
+ export interface SceneOverlayContext {
10
+ readonly state: MapState;
11
+ /**
12
+ * Subscribe to viewport changes (pan, zoom, resize). Returns an unsubscribe
13
+ * function — call it from {@link SceneOverlay.detach} to avoid leaks.
14
+ */
15
+ onViewportChange(cb: () => void): () => void;
16
+ /** Request a re-render of this overlay only. Cheap — no full scene rebuild. */
17
+ invalidate(): void;
18
+ }
19
+ /**
20
+ * Target-agnostic overlay. A {@link SceneOverlay} contributes static geometry
21
+ * to the scene by emitting one or more {@link Shape}s, so it renders in every
22
+ * output path: interactive canvas, SVG export, PNG export, and any future
23
+ * {@link Exporter}.
24
+ *
25
+ * Overlays may opt into reactivity via {@link attach}: subscribe to MapState or
26
+ * viewport events, then call `ctx.invalidate()` to re-render. Exporters skip
27
+ * `attach`/`detach` — they just call {@link render} once.
28
+ *
29
+ * ```ts
30
+ * class BadgeOverlay implements SceneOverlay {
31
+ * render(state: MapState, bounds: ViewportBounds): Shape {
32
+ * return {
33
+ * type: 'circle',
34
+ * cx: 5, cy: 5,
35
+ * radius: 0.4,
36
+ * paint: { fill: '#ff0' },
37
+ * layer: 'overlay',
38
+ * };
39
+ * }
40
+ * }
41
+ *
42
+ * renderer.addSceneOverlay('badge', new BadgeOverlay());
43
+ * ```
44
+ */
45
+ export interface SceneOverlay {
46
+ /**
47
+ * Optional. Called once when the overlay is registered with an interactive
48
+ * renderer. Subscribe to events here and call `ctx.invalidate()` when the
49
+ * overlay needs to re-render.
50
+ *
51
+ * Not called by exporters — they render statically via {@link render}.
52
+ */
53
+ attach?(ctx: SceneOverlayContext): void;
54
+ /**
55
+ * Optional. Called when the overlay is removed (or the renderer is
56
+ * destroyed). Unsubscribe from any events registered in {@link attach}.
57
+ */
58
+ detach?(): void;
59
+ /**
60
+ * Contribute geometry to the scene. Called on register, on invalidate, and
61
+ * by every exporter.
62
+ *
63
+ * @returns one or more world-space {@link Shape}s, or `void` to emit
64
+ * nothing this frame. Shapes carry their own {@link Shape.layer} hint;
65
+ * leaving it unset routes them to the overlay layer.
66
+ */
67
+ render(state: MapState, bounds: ViewportBounds): Shape | Shape[] | void;
68
+ }
@@ -0,0 +1,63 @@
1
+ import { default as Plane, IPlane } from './Plane';
2
+ import { default as IExit } from './Exit';
3
+ /**
4
+ * Public, renderer-facing surface of an area. The renderer never inspects
5
+ * private state of {@link Area}; it talks to this interface only. Custom data
6
+ * models (e.g. an app that owns its own room store) can satisfy `IArea` and
7
+ * hand the result to {@link MapRenderer} without subclassing.
8
+ *
9
+ * Mutability lives on the concrete implementation: {@link Area.markDirty} is
10
+ * `protected`, kept off the public interface. Consumers signal "redraw me" by
11
+ * bumping {@link getVersion}; the renderer reads the version to decide
12
+ * whether to rebuild.
13
+ */
14
+ export interface IArea {
15
+ getAreaName(): string;
16
+ getAreaId(): number;
17
+ /**
18
+ * Monotonically increasing version. The renderer compares the value it
19
+ * cached on the last build against the current value to decide whether
20
+ * the area needs a rebuild.
21
+ */
22
+ getVersion(): number;
23
+ getPlane(zIndex: number): IPlane;
24
+ getPlanes(): IPlane[];
25
+ getZLevels(): number[];
26
+ getRooms(): MapData.Room[];
27
+ getFullBounds(): {
28
+ minX: number;
29
+ maxX: number;
30
+ minY: number;
31
+ maxY: number;
32
+ };
33
+ /**
34
+ * Inter-room exits drawn on the given z-level. Each exit is bidirectional
35
+ * with optional one-way fallback; see {@link IExit}.
36
+ */
37
+ getLinkExits(zIndex: number): IExit[];
38
+ }
39
+ export default class Area implements IArea {
40
+ private readonly planes;
41
+ private readonly area;
42
+ private readonly exits;
43
+ private version;
44
+ constructor(area: MapData.Area);
45
+ getAreaName(): string;
46
+ getAreaId(): number;
47
+ getVersion(): number;
48
+ protected markDirty(): void;
49
+ getPlane(zIndex: number): Plane;
50
+ getPlanes(): Plane[];
51
+ getZLevels(): number[];
52
+ getRooms(): MapData.Room[];
53
+ getFullBounds(): {
54
+ minX: number;
55
+ maxX: number;
56
+ minY: number;
57
+ maxY: number;
58
+ };
59
+ getLinkExits(zIndex: number): IExit[];
60
+ private createPlanes;
61
+ private static readonly oppositeDir;
62
+ private createExits;
63
+ }
@@ -0,0 +1,15 @@
1
+ export type Kind = "exit" | "specialExit";
2
+ export default interface IExit {
3
+ a: number;
4
+ b: number;
5
+ aDir?: MapData.direction;
6
+ bDir?: MapData.direction;
7
+ kind?: Kind;
8
+ zIndex: number[];
9
+ }
10
+ export type { IExit };
11
+ /** @deprecated Use {@link IExit}. Retained as a structural alias for backwards compatibility. */
12
+ export type Exit = IExit;
13
+ export declare const regularExits: MapData.direction[];
14
+ export declare const shortTolong: Record<string, MapData.direction>;
15
+ export declare const longToShort: Record<MapData.direction, string>;
@@ -0,0 +1,34 @@
1
+ import { default as Area, IArea } from './Area';
2
+ /**
3
+ * Public, renderer-facing surface for map data. Everything the renderer
4
+ * (and other library consumers) call on `MapReader` is on this interface —
5
+ * private state and internal helpers are not.
6
+ *
7
+ * Downstream apps with their own room/area store can implement `IMapReader`
8
+ * directly (no need to subclass {@link MapReader}) and hand the result to
9
+ * {@link MapRenderer}. Visibility filtering (exploration, scope overlays,
10
+ * etc.) lives on the renderer's lens — it is intentionally not on this
11
+ * interface.
12
+ */
13
+ export interface IMapReader {
14
+ getArea(areaId: number): IArea;
15
+ getAreas(): IArea[];
16
+ getRooms(): MapData.Room[];
17
+ getRoom(roomId: number): MapData.Room;
18
+ /** Returns the env's `rgb(r,g,b)` string, or a default colour if the env id is unknown. */
19
+ getColorValue(envId: number): string;
20
+ /** Returns a contrasting symbol colour for the env, optionally with the given alpha. */
21
+ getSymbolColor(envId: number, opacity?: number): string;
22
+ }
23
+ export default class MapReader implements IMapReader {
24
+ private rooms;
25
+ private areas;
26
+ private colors;
27
+ constructor(map: MapData.Map, envs: MapData.Env[]);
28
+ getArea(areaId: number): Area;
29
+ getAreas(): Area[];
30
+ getRooms(): MapData.Room[];
31
+ getRoom(roomId: number): MapData.Room;
32
+ getColorValue(envId: number): string;
33
+ getSymbolColor(envId: number, opacity?: number): string;
34
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Public, renderer-facing surface of a z-level slice of an area.
3
+ *
4
+ * The renderer (and other library consumers) only depend on this interface;
5
+ * the concrete {@link Plane} class is one implementation of it. Downstream
6
+ * apps that want to drive the renderer from their own data model can hand it
7
+ * any `IPlane`-shaped object (typically returned from an {@link IArea}).
8
+ */
9
+ export interface IPlane {
10
+ getRooms(): MapData.Room[];
11
+ getLabels(): MapData.Label[];
12
+ getBounds(): {
13
+ minX: number;
14
+ maxX: number;
15
+ minY: number;
16
+ maxY: number;
17
+ };
18
+ }
19
+ export default class Plane implements IPlane {
20
+ private readonly bounds;
21
+ private readonly rooms;
22
+ private readonly labels;
23
+ constructor(rooms: MapData.Room[], labels: MapData.Label[]);
24
+ getRooms(): MapData.Room[];
25
+ getLabels(): MapData.Label[];
26
+ getBounds(): {
27
+ minX: number;
28
+ maxX: number;
29
+ minY: number;
30
+ maxY: number;
31
+ };
32
+ private createBounds;
33
+ }
@@ -0,0 +1,17 @@
1
+ import { DrawCommandBatch } from '../draw/DrawCommand';
2
+ /**
3
+ * Image loader hook. Canvas2D's `drawImage` needs an `HTMLImageElement` (or
4
+ * compatible). Browsers create one via `new Image()`; Node-canvas provides
5
+ * its own `Image` constructor. The default tries both — callers can override
6
+ * for tests or unusual targets.
7
+ */
8
+ export type ImageFactory = (src: string) => unknown;
9
+ export interface CanvasRenderOptions {
10
+ imageFactory?: ImageFactory;
11
+ }
12
+ /**
13
+ * Replay every batch onto `ctx`, in order. Each batch's commands are flushed
14
+ * sequentially; transform / clip stacks are independent per batch so a stray
15
+ * push in one layer cannot leak into the next.
16
+ */
17
+ export declare function renderToCanvas(ctx: CanvasRenderingContext2D, batches: DrawCommandBatch[], options?: CanvasRenderOptions): void;
@@ -0,0 +1,158 @@
1
+ import { default as Konva } from 'konva';
2
+ type RectCommand = {
3
+ type: 'rect';
4
+ x: number;
5
+ y: number;
6
+ w: number;
7
+ h: number;
8
+ fill?: string;
9
+ stroke?: string;
10
+ sw: number;
11
+ cr: number;
12
+ dash?: number[];
13
+ };
14
+ type CircleCommand = {
15
+ type: 'circle';
16
+ cx: number;
17
+ cy: number;
18
+ r: number;
19
+ fill?: string;
20
+ stroke?: string;
21
+ sw: number;
22
+ dash?: number[];
23
+ };
24
+ type LineCommand = {
25
+ type: 'line';
26
+ points: number[];
27
+ stroke?: string;
28
+ sw: number;
29
+ dash?: number[];
30
+ lineCap?: string;
31
+ lineJoin?: string;
32
+ alpha?: number;
33
+ };
34
+ type PolygonCommand = {
35
+ type: 'polygon';
36
+ vertices: number[];
37
+ fill?: string;
38
+ stroke?: string;
39
+ sw: number;
40
+ };
41
+ type TextCommand = {
42
+ type: 'text';
43
+ x: number;
44
+ y: number;
45
+ text: string;
46
+ fontSize: number;
47
+ fontFamily: string;
48
+ fontStyle: string;
49
+ fill: string;
50
+ stroke?: string;
51
+ sw: number;
52
+ align: string;
53
+ vAlign: string;
54
+ w: number;
55
+ h: number;
56
+ baselineRatio?: number;
57
+ transform?: [number, number, number, number, number, number];
58
+ };
59
+ type ImageCommand = {
60
+ type: 'image';
61
+ x: number;
62
+ y: number;
63
+ w: number;
64
+ h: number;
65
+ image: HTMLImageElement | any;
66
+ transform?: [number, number, number, number, number, number];
67
+ };
68
+ export type RecordingDrawCommand = RectCommand | CircleCommand | LineCommand | PolygonCommand | TextCommand | ImageCommand;
69
+ /**
70
+ * One positional group of recorded draw commands. Used as both the unit a
71
+ * shape walker emits and the cull-tracking handle inside
72
+ * {@link DrawCommandLayerNode}. Lazily materializes into a `Konva.Group` /
73
+ * `Konva.Shape` pair when added directly to a Konva layer.
74
+ */
75
+ export declare class RecordingGroupNode {
76
+ x: number;
77
+ y: number;
78
+ _visible: boolean;
79
+ noScaling: boolean;
80
+ readonly commands: RecordingDrawCommand[];
81
+ /** Lazily created when this group is materialized for a Konva.Layer. */
82
+ _konvaGroup?: Konva.Group;
83
+ constructor(x: number, y: number);
84
+ setVisible(visible: boolean): void;
85
+ isVisible(): boolean;
86
+ destroy(): void;
87
+ setPosition(x: number, y: number): void;
88
+ getPosition(): {
89
+ x: number;
90
+ y: number;
91
+ };
92
+ moveToTop(): void;
93
+ /**
94
+ * Materialize this recording as a Konva.Group + Konva.Shape. Used by
95
+ * {@link MaterializingLayerNode} for layers that want individual nodes
96
+ * (overlay, position) rather than a single bulk replay.
97
+ */
98
+ materialize(): Konva.Group;
99
+ }
100
+ /**
101
+ * Lightweight record extracted from a {@link RecordingGroupNode} when added
102
+ * to a {@link DrawCommandLayerNode}. Contains only plain data so culling
103
+ * callbacks can toggle visibility without a Konva node reference.
104
+ */
105
+ export type DrawEntry = {
106
+ x: number;
107
+ y: number;
108
+ noScaling: boolean;
109
+ readonly commands: RecordingDrawCommand[];
110
+ visible: boolean;
111
+ };
112
+ /**
113
+ * LayerNode backed by a single Konva.Shape whose sceneFunc replays
114
+ * {@link DrawEntry} objects. Used for the main scene layer where individual
115
+ * shapes need cull toggling.
116
+ */
117
+ export declare class DrawCommandLayerNode {
118
+ private readonly entries;
119
+ private readonly nodeToEntry;
120
+ private readonly konvaLayer;
121
+ private konvaShape;
122
+ constructor(konvaLayer: Konva.Layer);
123
+ addNode(node: RecordingGroupNode): void;
124
+ /** Return the DrawEntry created when `node` was added, or undefined if not found. */
125
+ getEntry(node: RecordingGroupNode): DrawEntry | undefined;
126
+ destroyChildren(): void;
127
+ batchDraw(): void;
128
+ private ensureShape;
129
+ }
130
+ /**
131
+ * Layer backed by a single Konva.Shape whose sceneFunc replays every added
132
+ * {@link RecordingGroupNode} in order. Used for layers that don't need
133
+ * per-shape cull toggling (grid, top-label).
134
+ */
135
+ export declare class RecordingLayerNode {
136
+ private groups;
137
+ private readonly konvaLayer;
138
+ private konvaShape;
139
+ constructor(konvaLayer: Konva.Layer);
140
+ addNode(node: RecordingGroupNode): void;
141
+ destroyChildren(): void;
142
+ batchDraw(): void;
143
+ private ensureShape;
144
+ }
145
+ /**
146
+ * Layer that materializes each added {@link RecordingGroupNode} as its own
147
+ * `Konva.Group`. Used for layers where the renderer keeps a reference to
148
+ * each node (overlay highlights, position marker) so it can destroy them
149
+ * individually.
150
+ */
151
+ export declare class MaterializingLayerNode {
152
+ private readonly konvaLayer;
153
+ constructor(konvaLayer: Konva.Layer);
154
+ addNode(node: RecordingGroupNode): void;
155
+ destroyChildren(): void;
156
+ batchDraw(): void;
157
+ }
158
+ export {};
@@ -0,0 +1,7 @@
1
+ import { DrawCommandBatch } from '../draw/DrawCommand';
2
+ /**
3
+ * Convert one or more {@link DrawCommandBatch}es into SVG element strings, in
4
+ * the order they appear. Caller wraps the result in `<svg viewBox=…>` /
5
+ * `</svg>` and inserts a background rect.
6
+ */
7
+ export declare function svgFromBatches(batches: DrawCommandBatch[]): string[];
@@ -0,0 +1,3 @@
1
+ import { RecordingGroupNode } from './RecordingLayer';
2
+ import { GroupShape } from '../scene/Shape';
3
+ export declare function shapeToRecording(group: GroupShape): RecordingGroupNode;