@bendyline/squisq-react 0.1.3 → 1.0.2

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 (139) hide show
  1. package/dist/BlockRenderer.d.ts +37 -0
  2. package/dist/BlockRenderer.d.ts.map +1 -0
  3. package/dist/BlockRenderer.js +51 -0
  4. package/dist/BlockRenderer.js.map +1 -0
  5. package/dist/CaptionOverlay.d.ts +24 -0
  6. package/dist/CaptionOverlay.d.ts.map +1 -0
  7. package/dist/CaptionOverlay.js +40 -0
  8. package/dist/CaptionOverlay.js.map +1 -0
  9. package/dist/DocControlsBottom.d.ts +28 -0
  10. package/dist/DocControlsBottom.d.ts.map +1 -0
  11. package/dist/DocControlsBottom.js +23 -0
  12. package/dist/DocControlsBottom.js.map +1 -0
  13. package/dist/DocControlsOverlay.d.ts +28 -0
  14. package/dist/DocControlsOverlay.d.ts.map +1 -0
  15. package/dist/DocControlsOverlay.js +75 -0
  16. package/dist/DocControlsOverlay.js.map +1 -0
  17. package/dist/DocControlsSidebar.d.ts +27 -0
  18. package/dist/DocControlsSidebar.d.ts.map +1 -0
  19. package/dist/DocControlsSidebar.js +6 -0
  20. package/dist/DocControlsSidebar.js.map +1 -0
  21. package/dist/DocControlsSlideshow.d.ts +20 -0
  22. package/dist/DocControlsSlideshow.d.ts.map +1 -0
  23. package/dist/DocControlsSlideshow.js +69 -0
  24. package/dist/DocControlsSlideshow.js.map +1 -0
  25. package/dist/DocPlayer.d.ts +87 -0
  26. package/dist/DocPlayer.d.ts.map +1 -0
  27. package/dist/DocPlayer.js +604 -0
  28. package/dist/DocPlayer.js.map +1 -0
  29. package/dist/DocPlayerWithSidebar.d.ts +41 -0
  30. package/dist/DocPlayerWithSidebar.d.ts.map +1 -0
  31. package/dist/DocPlayerWithSidebar.js +68 -0
  32. package/dist/DocPlayerWithSidebar.js.map +1 -0
  33. package/dist/DocProgressBar.d.ts +31 -0
  34. package/dist/DocProgressBar.d.ts.map +1 -0
  35. package/dist/DocProgressBar.js +122 -0
  36. package/dist/DocProgressBar.js.map +1 -0
  37. package/dist/LinearDocView.d.ts +47 -0
  38. package/dist/LinearDocView.d.ts.map +1 -0
  39. package/dist/LinearDocView.js +184 -0
  40. package/dist/LinearDocView.js.map +1 -0
  41. package/dist/MarkdownRenderer.d.ts +32 -0
  42. package/dist/MarkdownRenderer.d.ts.map +1 -0
  43. package/dist/MarkdownRenderer.js +133 -0
  44. package/dist/MarkdownRenderer.js.map +1 -0
  45. package/dist/__tests__/BlockRenderer.test.d.ts +2 -0
  46. package/dist/__tests__/BlockRenderer.test.d.ts.map +1 -0
  47. package/dist/__tests__/BlockRenderer.test.js +82 -0
  48. package/dist/__tests__/BlockRenderer.test.js.map +1 -0
  49. package/dist/__tests__/DocControlsSlideshow.test.d.ts +2 -0
  50. package/dist/__tests__/DocControlsSlideshow.test.d.ts.map +1 -0
  51. package/dist/__tests__/DocControlsSlideshow.test.js +88 -0
  52. package/dist/__tests__/DocControlsSlideshow.test.js.map +1 -0
  53. package/dist/__tests__/LinearDocView.test.d.ts +2 -0
  54. package/dist/__tests__/LinearDocView.test.d.ts.map +1 -0
  55. package/dist/__tests__/LinearDocView.test.js +160 -0
  56. package/dist/__tests__/LinearDocView.test.js.map +1 -0
  57. package/dist/__tests__/MarkdownRenderer.test.d.ts +2 -0
  58. package/dist/__tests__/MarkdownRenderer.test.d.ts.map +1 -0
  59. package/dist/__tests__/MarkdownRenderer.test.js +208 -0
  60. package/dist/__tests__/MarkdownRenderer.test.js.map +1 -0
  61. package/dist/__tests__/exports.test.d.ts +2 -0
  62. package/dist/__tests__/exports.test.d.ts.map +1 -0
  63. package/dist/__tests__/exports.test.js +48 -0
  64. package/dist/__tests__/exports.test.js.map +1 -0
  65. package/dist/hooks/AudioProvider.d.ts +71 -0
  66. package/dist/hooks/AudioProvider.d.ts.map +1 -0
  67. package/dist/hooks/AudioProvider.js +52 -0
  68. package/dist/hooks/AudioProvider.js.map +1 -0
  69. package/dist/hooks/MediaContext.d.ts +35 -0
  70. package/dist/hooks/MediaContext.d.ts.map +1 -0
  71. package/dist/hooks/MediaContext.js +66 -0
  72. package/dist/hooks/MediaContext.js.map +1 -0
  73. package/dist/hooks/index.d.ts +6 -0
  74. package/dist/hooks/index.d.ts.map +1 -0
  75. package/dist/hooks/index.js +5 -0
  76. package/dist/hooks/index.js.map +1 -0
  77. package/dist/hooks/useAudioSync.d.ts +18 -0
  78. package/dist/hooks/useAudioSync.d.ts.map +1 -0
  79. package/dist/hooks/useAudioSync.js +338 -0
  80. package/dist/hooks/useAudioSync.js.map +1 -0
  81. package/dist/hooks/useDocPlayback.d.ts +47 -0
  82. package/dist/hooks/useDocPlayback.d.ts.map +1 -0
  83. package/dist/hooks/useDocPlayback.js +176 -0
  84. package/dist/hooks/useDocPlayback.js.map +1 -0
  85. package/dist/hooks/useViewportOrientation.d.ts +31 -0
  86. package/dist/hooks/useViewportOrientation.d.ts.map +1 -0
  87. package/dist/hooks/useViewportOrientation.js +92 -0
  88. package/dist/hooks/useViewportOrientation.js.map +1 -0
  89. package/dist/index.d.ts +25 -563
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +26 -3179
  92. package/dist/index.js.map +1 -1
  93. package/dist/layers/ImageLayer.d.ts +23 -0
  94. package/dist/layers/ImageLayer.d.ts.map +1 -0
  95. package/dist/layers/ImageLayer.js +104 -0
  96. package/dist/layers/ImageLayer.js.map +1 -0
  97. package/dist/layers/MapLayer.d.ts +29 -0
  98. package/dist/layers/MapLayer.d.ts.map +1 -0
  99. package/dist/layers/MapLayer.js +97 -0
  100. package/dist/layers/MapLayer.js.map +1 -0
  101. package/dist/layers/ShapeLayer.d.ts +20 -0
  102. package/dist/layers/ShapeLayer.d.ts.map +1 -0
  103. package/dist/layers/ShapeLayer.js +35 -0
  104. package/dist/layers/ShapeLayer.js.map +1 -0
  105. package/dist/layers/TextLayer.d.ts +23 -0
  106. package/dist/layers/TextLayer.d.ts.map +1 -0
  107. package/dist/layers/TextLayer.js +126 -0
  108. package/dist/layers/TextLayer.js.map +1 -0
  109. package/dist/layers/VideoLayer.d.ts +40 -0
  110. package/dist/layers/VideoLayer.d.ts.map +1 -0
  111. package/dist/layers/VideoLayer.js +105 -0
  112. package/dist/layers/VideoLayer.js.map +1 -0
  113. package/dist/layers/index.d.ts +6 -0
  114. package/dist/layers/index.d.ts.map +1 -0
  115. package/dist/layers/index.js +6 -0
  116. package/dist/layers/index.js.map +1 -0
  117. package/dist/squisq-player.global.js +1 -1
  118. package/dist/standalone-entry.d.ts +61 -0
  119. package/dist/standalone-entry.d.ts.map +1 -0
  120. package/dist/standalone-entry.js +169 -0
  121. package/dist/standalone-entry.js.map +1 -0
  122. package/dist/standalone-source.js +1 -1
  123. package/dist/types.d.ts +131 -0
  124. package/dist/types.d.ts.map +1 -0
  125. package/dist/types.js +21 -0
  126. package/dist/types.js.map +1 -0
  127. package/dist/utils/animationUtils.d.ts +8 -0
  128. package/dist/utils/animationUtils.d.ts.map +1 -0
  129. package/dist/utils/animationUtils.js +8 -0
  130. package/dist/utils/animationUtils.js.map +1 -0
  131. package/dist/utils/layerUtils.d.ts +17 -0
  132. package/dist/utils/layerUtils.d.ts.map +1 -0
  133. package/dist/utils/layerUtils.js +37 -0
  134. package/dist/utils/layerUtils.js.map +1 -0
  135. package/dist/utils/mapTileUtils.d.ts +105 -0
  136. package/dist/utils/mapTileUtils.d.ts.map +1 -0
  137. package/dist/utils/mapTileUtils.js +268 -0
  138. package/dist/utils/mapTileUtils.js.map +1 -0
  139. package/package.json +3 -4
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Doc Player Control Types
3
+ *
4
+ * Shared type definitions for doc player controls across different
5
+ * layout modes (overlay, sidebar, bottom). These interfaces allow
6
+ * control components to be decoupled from the core DocPlayer.
7
+ *
8
+ * Related Files:
9
+ * - DocPlayer.tsx — Core player component
10
+ * - DocProgressBar.tsx — Extracted progress bar
11
+ * - DocControlsOverlay.tsx — Overlay controls (default)
12
+ * - DocControlsSidebar.tsx — Vertical sidebar controls
13
+ * - DocControlsBottom.tsx — Horizontal bottom strip controls
14
+ */
15
+ import type { Block } from '@bendyline/squisq/schemas';
16
+ /** Layout mode for doc player controls */
17
+ export type ControlsLayout = 'overlay' | 'sidebar' | 'bottom';
18
+ /**
19
+ * Display mode for DocPlayer.
20
+ *
21
+ * - `'video'` — Traditional video-style playback with play/pause, scrub bar,
22
+ * and time-based auto-advance. Default mode.
23
+ * - `'slideshow'` — PowerPoint-style presentation with prev/next navigation.
24
+ * Blocks are treated as static slides that only change on user click.
25
+ * No auto-advance, no scrub bar.
26
+ * - `'linear'` — Long-scrolling document view. Renders the full markdown as
27
+ * readable HTML with template-annotated sections shown as inline SVG cards.
28
+ * No audio, no timeline, no controls — just a scrollable page.
29
+ */
30
+ export type DisplayMode = 'video' | 'slideshow' | 'linear';
31
+ /** Slide navigation actions for slideshow display mode */
32
+ export interface SlideNavActions {
33
+ /** Navigate to the next slide */
34
+ nextSlide: () => void;
35
+ /** Navigate to the previous slide */
36
+ prevSlide: () => void;
37
+ /** Navigate to a specific slide by index (0-based) */
38
+ goToSlide: (index: number) => void;
39
+ }
40
+ /** Playback state exposed to external control components */
41
+ export interface PlaybackState {
42
+ isPlaying: boolean;
43
+ currentTime: number;
44
+ totalDuration: number;
45
+ currentBlockIndex: number;
46
+ totalBlocks: number;
47
+ docProgress: number;
48
+ hasCaptions: boolean;
49
+ captionsEnabled: boolean;
50
+ isFullscreen?: boolean;
51
+ /** Current audio segment index (0-based) */
52
+ currentSegmentIndex: number;
53
+ /** Current audio segment name (e.g., 'intro', 'history') */
54
+ currentSegmentName: string | null;
55
+ /** Current block data (for extracting image info, etc.) */
56
+ currentBlock: Block | null;
57
+ }
58
+ /** Playback actions exposed to external control components */
59
+ export interface PlaybackActions {
60
+ toggle: () => void;
61
+ restart: () => void;
62
+ seekTo: (time: number) => void;
63
+ setCaptionsEnabled: (enabled: boolean) => void;
64
+ toggleFullscreen?: () => void;
65
+ }
66
+ /** Block marker data for the progress bar */
67
+ export interface BlockMarker {
68
+ block: Block;
69
+ index: number;
70
+ position: number;
71
+ title: string;
72
+ /** True if this block is the first in a new audio segment (section boundary) */
73
+ isSectionStart: boolean;
74
+ }
75
+ /** Block metadata returned by SquisqRenderAPI.getBlocks() */
76
+ export interface RenderBlockInfo {
77
+ id: string;
78
+ template: string;
79
+ startTime: number;
80
+ duration: number;
81
+ }
82
+ /** Audio segment info returned by SquisqRenderAPI.getAudioSegments() */
83
+ export interface RenderAudioSegmentInfo {
84
+ src: string;
85
+ name: string;
86
+ duration: number;
87
+ startTime: number;
88
+ }
89
+ /** Caption phrase info returned by SquisqRenderAPI.getCaptions() */
90
+ export interface RenderCaptionInfo {
91
+ text: string;
92
+ startTime: number;
93
+ endTime: number;
94
+ }
95
+ /** Chapter marker returned by SquisqRenderAPI.getChapters() */
96
+ export interface RenderChapterInfo {
97
+ title: string;
98
+ startTime: number;
99
+ duration: number;
100
+ }
101
+ /**
102
+ * API surface exposed on `window` in render mode and debug mode.
103
+ * Used by Playwright for video export and by ?debug=true for testing.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * // In Playwright:
108
+ * const w = window as unknown as SquisqWindow;
109
+ * await w.seekTo!(5.0);
110
+ * const blocks = w.getBlocks!();
111
+ * ```
112
+ */
113
+ export interface SquisqRenderAPI {
114
+ seekTo: (time: number) => Promise<void>;
115
+ getDuration: () => number;
116
+ getBlocks: () => RenderBlockInfo[];
117
+ getAudioSegments: () => RenderAudioSegmentInfo[];
118
+ getCaptions: () => RenderCaptionInfo[];
119
+ getChapters: () => RenderChapterInfo[];
120
+ showCover: () => Promise<void>;
121
+ hideCover: () => Promise<void>;
122
+ hasCoverBlock: () => boolean;
123
+ }
124
+ /**
125
+ * Window augmented with optional SquisqRenderAPI properties.
126
+ * Each property is optional because they're only present in render/debug mode.
127
+ */
128
+ export type SquisqWindow = Window & typeof globalThis & Partial<SquisqRenderAPI>;
129
+ /** Format time in seconds to MM:SS string */
130
+ export declare function formatTime(seconds: number): string;
131
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Doc Player Control Types
3
+ *
4
+ * Shared type definitions for doc player controls across different
5
+ * layout modes (overlay, sidebar, bottom). These interfaces allow
6
+ * control components to be decoupled from the core DocPlayer.
7
+ *
8
+ * Related Files:
9
+ * - DocPlayer.tsx — Core player component
10
+ * - DocProgressBar.tsx — Extracted progress bar
11
+ * - DocControlsOverlay.tsx — Overlay controls (default)
12
+ * - DocControlsSidebar.tsx — Vertical sidebar controls
13
+ * - DocControlsBottom.tsx — Horizontal bottom strip controls
14
+ */
15
+ /** Format time in seconds to MM:SS string */
16
+ export function formatTime(seconds) {
17
+ const mins = Math.floor(seconds / 60);
18
+ const secs = Math.floor(seconds % 60);
19
+ return `${mins}:${secs.toString().padStart(2, '0')}`;
20
+ }
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAqIH,6CAA6C;AAC7C,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACtC,OAAO,GAAG,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACvD,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Animation Utilities (React)
3
+ *
4
+ * Re-exports the shared animation utilities for use in the React package.
5
+ * All animation logic is in shared/doc/utils.
6
+ */
7
+ export { getAnimationStyle, getDefaultAnimationDuration, getTransitionClass, getAnimationProgress, } from '@bendyline/squisq/doc';
8
+ //# sourceMappingURL=animationUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animationUtils.d.ts","sourceRoot":"","sources":["../../src/utils/animationUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Animation Utilities (React)
3
+ *
4
+ * Re-exports the shared animation utilities for use in the React package.
5
+ * All animation logic is in shared/doc/utils.
6
+ */
7
+ export { getAnimationStyle, getDefaultAnimationDuration, getTransitionClass, getAnimationProgress, } from '@bendyline/squisq/doc';
8
+ //# sourceMappingURL=animationUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"animationUtils.js","sourceRoot":"","sources":["../../src/utils/animationUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Shared utilities for layer components.
3
+ *
4
+ * Resolves position values and anchor offsets used by all layer types.
5
+ */
6
+ /**
7
+ * Resolve a position value (number or percentage string) to pixels.
8
+ */
9
+ export declare function resolveValue(value: number | string, dimension: number): number;
10
+ /**
11
+ * Get offset based on anchor point.
12
+ */
13
+ export declare function getAnchorOffset(anchor: string | undefined, width: number, height: number): {
14
+ x: number;
15
+ y: number;
16
+ };
17
+ //# sourceMappingURL=layerUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layerUtils.d.ts","sourceRoot":"","sources":["../../src/utils/layerUtils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAS9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAc1B"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared utilities for layer components.
3
+ *
4
+ * Resolves position values and anchor offsets used by all layer types.
5
+ */
6
+ /**
7
+ * Resolve a position value (number or percentage string) to pixels.
8
+ */
9
+ export function resolveValue(value, dimension) {
10
+ if (typeof value === 'number') {
11
+ return value;
12
+ }
13
+ if (value.endsWith('%')) {
14
+ const percent = parseFloat(value);
15
+ return (percent / 100) * dimension;
16
+ }
17
+ return parseFloat(value);
18
+ }
19
+ /**
20
+ * Get offset based on anchor point.
21
+ */
22
+ export function getAnchorOffset(anchor, width, height) {
23
+ switch (anchor) {
24
+ case 'center':
25
+ return { x: -width / 2, y: -height / 2 };
26
+ case 'top-right':
27
+ return { x: -width, y: 0 };
28
+ case 'bottom-left':
29
+ return { x: 0, y: -height };
30
+ case 'bottom-right':
31
+ return { x: -width, y: -height };
32
+ case 'top-left':
33
+ default:
34
+ return { x: 0, y: 0 };
35
+ }
36
+ }
37
+ //# sourceMappingURL=layerUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layerUtils.js","sourceRoot":"","sources":["../../src/utils/layerUtils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAsB,EAAE,SAAiB;IACpE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAClC,OAAO,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,SAAS,CAAC;IACrC,CAAC;IACD,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,MAA0B,EAC1B,KAAa,EACb,MAAc;IAEd,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ;YACX,OAAO,EAAE,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,KAAK,WAAW;YACd,OAAO,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7B,KAAK,aAAa;YAChB,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;QAC9B,KAAK,cAAc;YACjB,OAAO,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;QACnC,KAAK,UAAU,CAAC;QAChB;YACE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAC1B,CAAC;AACH,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Map Tile Utilities
3
+ *
4
+ * Functions for fetching and composing map tiles from free/open-source providers.
5
+ * Converts lat/lng to tile coordinates and composites multiple tiles into a
6
+ * single image for SVG embedding.
7
+ *
8
+ * Supported Providers (all free with attribution):
9
+ * - terrain: OpenTopoMap (CC-BY-SA)
10
+ * - road: OpenStreetMap (ODbL)
11
+ * - satellite: ESRI World Imagery (free with attribution)
12
+ * - toner: Stadia/Stamen Toner (free tier)
13
+ * - watercolor: Stadia/Stamen Watercolor (free tier)
14
+ *
15
+ * See docs/MAP_TILES.md for full provider details and terms.
16
+ */
17
+ import type { MapTileStyle, MapMarker } from '@bendyline/squisq/schemas';
18
+ /**
19
+ * Tile provider configuration.
20
+ */
21
+ export interface TileProvider {
22
+ /** URL template with {z}, {x}, {y} placeholders */
23
+ url: string;
24
+ /** Attribution text (required for display) */
25
+ attribution: string;
26
+ /** Maximum zoom level */
27
+ maxZoom: number;
28
+ /** Tile size in pixels (default: 256) */
29
+ tileSize?: number;
30
+ }
31
+ /**
32
+ * Free tile providers for each map style.
33
+ * All require attribution to be displayed.
34
+ */
35
+ export declare const TILE_PROVIDERS: Record<MapTileStyle, TileProvider>;
36
+ /**
37
+ * Convert latitude/longitude to tile coordinates at a given zoom level.
38
+ * Uses Web Mercator projection (EPSG:3857).
39
+ */
40
+ export declare function latLngToTile(lat: number, lng: number, zoom: number): {
41
+ x: number;
42
+ y: number;
43
+ };
44
+ /**
45
+ * Convert tile coordinates back to lat/lng (top-left corner of tile).
46
+ */
47
+ export declare function tileToLatLng(x: number, y: number, zoom: number): {
48
+ lat: number;
49
+ lng: number;
50
+ };
51
+ /**
52
+ * Get the pixel offset within a tile for a given lat/lng.
53
+ */
54
+ export declare function getPixelOffset(lat: number, lng: number, zoom: number, tileSize?: number): {
55
+ x: number;
56
+ y: number;
57
+ };
58
+ /**
59
+ * Calculate which tiles are needed to cover a viewport centered on lat/lng.
60
+ */
61
+ export declare function getTilesForViewport(centerLat: number, centerLng: number, zoom: number, viewportWidth: number, viewportHeight: number, tileSize?: number): Array<{
62
+ x: number;
63
+ y: number;
64
+ screenX: number;
65
+ screenY: number;
66
+ }>;
67
+ /**
68
+ * Build a tile URL from the provider template.
69
+ */
70
+ export declare function buildTileUrl(provider: TileProvider, x: number, y: number, z: number): string;
71
+ /**
72
+ * Options for composing a map image.
73
+ */
74
+ export interface ComposeMapOptions {
75
+ /** Center coordinates */
76
+ center: {
77
+ lat: number;
78
+ lng: number;
79
+ };
80
+ /** Zoom level */
81
+ zoom: number;
82
+ /** Map tile style */
83
+ style: MapTileStyle;
84
+ /** Output width in pixels */
85
+ width: number;
86
+ /** Output height in pixels */
87
+ height: number;
88
+ /** Optional markers to render */
89
+ markers?: MapMarker[];
90
+ /** Show attribution (default: true) */
91
+ showAttribution?: boolean;
92
+ }
93
+ /**
94
+ * Compose map tiles into a single data URL image.
95
+ *
96
+ * This is the main function for generating map images for blocks.
97
+ * It fetches all needed tiles, composites them on a canvas, and
98
+ * returns a data URL that can be used in an SVG <image> element.
99
+ */
100
+ export declare function composeMapImage(options: ComposeMapOptions): Promise<string>;
101
+ /**
102
+ * Get attribution text for a map style.
103
+ */
104
+ export declare function getAttribution(style: MapTileStyle): string;
105
+ //# sourceMappingURL=mapTileUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapTileUtils.d.ts","sourceRoot":"","sources":["../../src/utils/mapTileUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE,YAAY,CA0B7D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAM7F;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAM7F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAY,GACrB;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAU1B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,QAAQ,GAAE,MAAY,GACrB,KAAK,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA8BnE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5F;AAeD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,KAAK,EAAE,YAAY,CAAC;IACpB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;IACtB,uCAAuC;IACvC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA8CjF;AA8HD;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAE1D"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Map Tile Utilities
3
+ *
4
+ * Functions for fetching and composing map tiles from free/open-source providers.
5
+ * Converts lat/lng to tile coordinates and composites multiple tiles into a
6
+ * single image for SVG embedding.
7
+ *
8
+ * Supported Providers (all free with attribution):
9
+ * - terrain: OpenTopoMap (CC-BY-SA)
10
+ * - road: OpenStreetMap (ODbL)
11
+ * - satellite: ESRI World Imagery (free with attribution)
12
+ * - toner: Stadia/Stamen Toner (free tier)
13
+ * - watercolor: Stadia/Stamen Watercolor (free tier)
14
+ *
15
+ * See docs/MAP_TILES.md for full provider details and terms.
16
+ */
17
+ /**
18
+ * Free tile providers for each map style.
19
+ * All require attribution to be displayed.
20
+ */
21
+ export const TILE_PROVIDERS = {
22
+ terrain: {
23
+ url: 'https://tile.opentopomap.org/{z}/{x}/{y}.png',
24
+ attribution: 'Map: OpenTopoMap (CC-BY-SA)',
25
+ maxZoom: 17,
26
+ },
27
+ road: {
28
+ url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
29
+ attribution: '© OpenStreetMap contributors',
30
+ maxZoom: 19,
31
+ },
32
+ satellite: {
33
+ url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
34
+ attribution: 'Imagery: Esri, Maxar, Earthstar',
35
+ maxZoom: 18,
36
+ },
37
+ toner: {
38
+ url: 'https://tiles.stadiamaps.com/tiles/stamen_toner/{z}/{x}/{y}.png',
39
+ attribution: 'Map: Stadia Maps, Stamen Design',
40
+ maxZoom: 20,
41
+ },
42
+ watercolor: {
43
+ url: 'https://tiles.stadiamaps.com/tiles/stamen_watercolor/{z}/{x}/{y}.jpg',
44
+ attribution: 'Map: Stadia Maps, Stamen Design',
45
+ maxZoom: 16,
46
+ },
47
+ };
48
+ /**
49
+ * Convert latitude/longitude to tile coordinates at a given zoom level.
50
+ * Uses Web Mercator projection (EPSG:3857).
51
+ */
52
+ export function latLngToTile(lat, lng, zoom) {
53
+ const n = Math.pow(2, zoom);
54
+ const x = Math.floor(((lng + 180) / 360) * n);
55
+ const latRad = (lat * Math.PI) / 180;
56
+ const y = Math.floor(((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2) * n);
57
+ return { x, y };
58
+ }
59
+ /**
60
+ * Convert tile coordinates back to lat/lng (top-left corner of tile).
61
+ */
62
+ export function tileToLatLng(x, y, zoom) {
63
+ const n = Math.pow(2, zoom);
64
+ const lng = (x / n) * 360 - 180;
65
+ const latRad = Math.atan(Math.sinh(Math.PI * (1 - (2 * y) / n)));
66
+ const lat = (latRad * 180) / Math.PI;
67
+ return { lat, lng };
68
+ }
69
+ /**
70
+ * Get the pixel offset within a tile for a given lat/lng.
71
+ */
72
+ export function getPixelOffset(lat, lng, zoom, tileSize = 256) {
73
+ const n = Math.pow(2, zoom);
74
+ const xTile = ((lng + 180) / 360) * n;
75
+ const latRad = (lat * Math.PI) / 180;
76
+ const yTile = ((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2) * n;
77
+ return {
78
+ x: (xTile - Math.floor(xTile)) * tileSize,
79
+ y: (yTile - Math.floor(yTile)) * tileSize,
80
+ };
81
+ }
82
+ /**
83
+ * Calculate which tiles are needed to cover a viewport centered on lat/lng.
84
+ */
85
+ export function getTilesForViewport(centerLat, centerLng, zoom, viewportWidth, viewportHeight, tileSize = 256) {
86
+ const centerTile = latLngToTile(centerLat, centerLng, zoom);
87
+ const pixelOffset = getPixelOffset(centerLat, centerLng, zoom, tileSize);
88
+ // How many tiles we need in each direction
89
+ const tilesX = Math.ceil(viewportWidth / tileSize) + 1;
90
+ const tilesY = Math.ceil(viewportHeight / tileSize) + 1;
91
+ // Start tile offset
92
+ const startX = centerTile.x - Math.floor(tilesX / 2);
93
+ const startY = centerTile.y - Math.floor(tilesY / 2);
94
+ // Screen position of the center tile
95
+ const centerScreenX = viewportWidth / 2 - pixelOffset.x;
96
+ const centerScreenY = viewportHeight / 2 - pixelOffset.y;
97
+ const tiles = [];
98
+ for (let dy = 0; dy < tilesY; dy++) {
99
+ for (let dx = 0; dx < tilesX; dx++) {
100
+ const tileX = startX + dx;
101
+ const tileY = startY + dy;
102
+ const screenX = centerScreenX + (tileX - centerTile.x) * tileSize;
103
+ const screenY = centerScreenY + (tileY - centerTile.y) * tileSize;
104
+ tiles.push({ x: tileX, y: tileY, screenX, screenY });
105
+ }
106
+ }
107
+ return tiles;
108
+ }
109
+ /**
110
+ * Build a tile URL from the provider template.
111
+ */
112
+ export function buildTileUrl(provider, x, y, z) {
113
+ return provider.url.replace('{z}', String(z)).replace('{x}', String(x)).replace('{y}', String(y));
114
+ }
115
+ /**
116
+ * Fetch a single tile image as an HTMLImageElement.
117
+ */
118
+ async function fetchTileImage(url) {
119
+ return new Promise((resolve, reject) => {
120
+ const img = new Image();
121
+ img.crossOrigin = 'anonymous';
122
+ img.onload = () => resolve(img);
123
+ img.onerror = () => reject(new Error(`Failed to load tile: ${url}`));
124
+ img.src = url;
125
+ });
126
+ }
127
+ /**
128
+ * Compose map tiles into a single data URL image.
129
+ *
130
+ * This is the main function for generating map images for blocks.
131
+ * It fetches all needed tiles, composites them on a canvas, and
132
+ * returns a data URL that can be used in an SVG <image> element.
133
+ */
134
+ export async function composeMapImage(options) {
135
+ const { center, zoom, style, width, height, markers = [], showAttribution = true } = options;
136
+ const provider = TILE_PROVIDERS[style];
137
+ const tileSize = provider.tileSize || 256;
138
+ const clampedZoom = Math.min(zoom, provider.maxZoom);
139
+ // Create canvas
140
+ const canvas = document.createElement('canvas');
141
+ canvas.width = width;
142
+ canvas.height = height;
143
+ const ctx = canvas.getContext('2d');
144
+ if (!ctx)
145
+ throw new Error('Failed to get canvas context');
146
+ // Fill with a neutral background in case tiles fail to load
147
+ ctx.fillStyle = style === 'toner' ? '#ffffff' : '#e5e7eb';
148
+ ctx.fillRect(0, 0, width, height);
149
+ // Get tiles needed
150
+ const tiles = getTilesForViewport(center.lat, center.lng, clampedZoom, width, height, tileSize);
151
+ // Fetch and draw tiles
152
+ const tilePromises = tiles.map(async (tile) => {
153
+ const url = buildTileUrl(provider, tile.x, tile.y, clampedZoom);
154
+ try {
155
+ const img = await fetchTileImage(url);
156
+ ctx.drawImage(img, tile.screenX, tile.screenY, tileSize, tileSize);
157
+ }
158
+ catch (err) {
159
+ // Tile failed to load - leave background color
160
+ console.warn(`Tile load failed: ${url}`, err);
161
+ }
162
+ });
163
+ await Promise.all(tilePromises);
164
+ // Draw markers
165
+ for (const marker of markers) {
166
+ drawMarker(ctx, marker, center, clampedZoom, width, height, tileSize);
167
+ }
168
+ // Draw attribution
169
+ if (showAttribution) {
170
+ drawAttribution(ctx, provider.attribution, width, height);
171
+ }
172
+ return canvas.toDataURL('image/png');
173
+ }
174
+ /**
175
+ * Draw a marker on the canvas.
176
+ */
177
+ function drawMarker(ctx, marker, center, zoom, width, height, tileSize) {
178
+ // Calculate screen position of marker relative to center
179
+ const centerTile = latLngToTile(center.lat, center.lng, zoom);
180
+ const markerTile = latLngToTile(marker.lat, marker.lng, zoom);
181
+ const centerOffset = getPixelOffset(center.lat, center.lng, zoom, tileSize);
182
+ const markerOffset = getPixelOffset(marker.lat, marker.lng, zoom, tileSize);
183
+ const dx = (markerTile.x - centerTile.x) * tileSize + (markerOffset.x - centerOffset.x);
184
+ const dy = (markerTile.y - centerTile.y) * tileSize + (markerOffset.y - centerOffset.y);
185
+ const screenX = width / 2 + dx;
186
+ const screenY = height / 2 + dy;
187
+ // Draw marker
188
+ const color = marker.color || '#ef4444';
189
+ const icon = marker.icon || 'pin';
190
+ ctx.save();
191
+ if (icon === 'pin') {
192
+ // Draw pin shape
193
+ ctx.fillStyle = color;
194
+ ctx.beginPath();
195
+ ctx.arc(screenX, screenY - 12, 8, Math.PI, 0, false);
196
+ ctx.lineTo(screenX, screenY);
197
+ ctx.closePath();
198
+ ctx.fill();
199
+ // White dot in center
200
+ ctx.fillStyle = '#ffffff';
201
+ ctx.beginPath();
202
+ ctx.arc(screenX, screenY - 12, 3, 0, Math.PI * 2);
203
+ ctx.fill();
204
+ }
205
+ else if (icon === 'circle') {
206
+ ctx.fillStyle = color;
207
+ ctx.beginPath();
208
+ ctx.arc(screenX, screenY, 8, 0, Math.PI * 2);
209
+ ctx.fill();
210
+ ctx.strokeStyle = '#ffffff';
211
+ ctx.lineWidth = 2;
212
+ ctx.stroke();
213
+ }
214
+ else if (icon === 'star') {
215
+ ctx.fillStyle = color;
216
+ drawStar(ctx, screenX, screenY, 5, 10, 5);
217
+ ctx.fill();
218
+ }
219
+ // Draw label if present
220
+ if (marker.label) {
221
+ ctx.fillStyle = '#1f2937';
222
+ ctx.font = 'bold 12px system-ui, sans-serif';
223
+ ctx.textAlign = 'center';
224
+ ctx.fillText(marker.label, screenX, screenY + 20);
225
+ }
226
+ ctx.restore();
227
+ }
228
+ /**
229
+ * Draw a star shape.
230
+ */
231
+ function drawStar(ctx, cx, cy, spikes, outerRadius, innerRadius) {
232
+ let rot = (Math.PI / 2) * 3;
233
+ const step = Math.PI / spikes;
234
+ ctx.beginPath();
235
+ ctx.moveTo(cx, cy - outerRadius);
236
+ for (let i = 0; i < spikes; i++) {
237
+ ctx.lineTo(cx + Math.cos(rot) * outerRadius, cy + Math.sin(rot) * outerRadius);
238
+ rot += step;
239
+ ctx.lineTo(cx + Math.cos(rot) * innerRadius, cy + Math.sin(rot) * innerRadius);
240
+ rot += step;
241
+ }
242
+ ctx.lineTo(cx, cy - outerRadius);
243
+ ctx.closePath();
244
+ }
245
+ /**
246
+ * Draw attribution text on the canvas.
247
+ */
248
+ function drawAttribution(ctx, text, width, height) {
249
+ ctx.save();
250
+ // Semi-transparent background
251
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
252
+ const padding = 4;
253
+ ctx.font = '10px system-ui, sans-serif';
254
+ const textWidth = ctx.measureText(text).width;
255
+ ctx.fillRect(width - textWidth - padding * 2 - 4, height - 16, textWidth + padding * 2, 14);
256
+ // Text
257
+ ctx.fillStyle = '#374151';
258
+ ctx.textAlign = 'right';
259
+ ctx.fillText(text, width - padding - 4, height - 5);
260
+ ctx.restore();
261
+ }
262
+ /**
263
+ * Get attribution text for a map style.
264
+ */
265
+ export function getAttribution(style) {
266
+ return TILE_PROVIDERS[style].attribution;
267
+ }
268
+ //# sourceMappingURL=mapTileUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapTileUtils.js","sourceRoot":"","sources":["../../src/utils/mapTileUtils.ts"],"names":[],"mappings":"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"}