isard 1.1.0 → 1.2.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 (216) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/basemap/basemaps.d.ts +1 -1
  3. package/dist/basemap/basemaps.js +2 -2
  4. package/dist/basemap/basemaps.js.map +1 -1
  5. package/dist/basemap/grid.d.ts +5 -5
  6. package/dist/basemap/grid.js +59 -65
  7. package/dist/basemap/grid.js.map +1 -1
  8. package/dist/basemap/mvt.d.ts +1 -1
  9. package/dist/basemap/mvt.js +6 -6
  10. package/dist/basemap/mvt.js.map +1 -1
  11. package/dist/basemap/pmtiles.d.ts +10 -10
  12. package/dist/basemap/pmtiles.js +39 -31
  13. package/dist/basemap/pmtiles.js.map +1 -1
  14. package/dist/basemap/resample.d.ts +2 -2
  15. package/dist/basemap/resample.js +16 -14
  16. package/dist/basemap/resample.js.map +1 -1
  17. package/dist/basemap/terrain.d.ts +3 -3
  18. package/dist/basemap/terrain.js +6 -6
  19. package/dist/basemap/terrain.js.map +1 -1
  20. package/dist/basemap/vectorstyle.d.ts +12 -10
  21. package/dist/basemap/vectorstyle.js +128 -110
  22. package/dist/basemap/vectorstyle.js.map +1 -1
  23. package/dist/basemap/vectortiles.d.ts +11 -11
  24. package/dist/basemap/vectortiles.js +141 -103
  25. package/dist/basemap/vectortiles.js.map +1 -1
  26. package/dist/basemap/wmts.d.ts +3 -3
  27. package/dist/basemap/wmts.js +16 -11
  28. package/dist/basemap/wmts.js.map +1 -1
  29. package/dist/basemap.worker.js +2 -2
  30. package/dist/basemap.worker.js.map +14 -13
  31. package/dist/bind/layers.d.ts +13 -4
  32. package/dist/bind/layers.js +64 -40
  33. package/dist/bind/layers.js.map +1 -1
  34. package/dist/data/crs.d.ts +10 -10
  35. package/dist/data/crs.js +38 -34
  36. package/dist/data/crs.js.map +1 -1
  37. package/dist/data/gpx.d.ts +1 -1
  38. package/dist/data/gpx.js +20 -20
  39. package/dist/data/gpx.js.map +1 -1
  40. package/dist/data/kml.d.ts +1 -1
  41. package/dist/data/kml.js +42 -39
  42. package/dist/data/kml.js.map +1 -1
  43. package/dist/data/topojson.d.ts +1 -1
  44. package/dist/data/topojson.js +15 -10
  45. package/dist/data/topojson.js.map +1 -1
  46. package/dist/data/xml.d.ts +5 -5
  47. package/dist/data/xml.js +19 -18
  48. package/dist/data/xml.js.map +1 -1
  49. package/dist/decoder.worker.js +4 -4
  50. package/dist/decoder.worker.js.map +6 -6
  51. package/dist/engine/decoders.d.ts +2 -2
  52. package/dist/engine/decoders.js +28 -25
  53. package/dist/engine/decoders.js.map +1 -1
  54. package/dist/engine/loader.js +13 -14
  55. package/dist/engine/loader.js.map +1 -1
  56. package/dist/engine/requests.d.ts +1 -1
  57. package/dist/engine/requests.js +19 -16
  58. package/dist/engine/requests.js.map +1 -1
  59. package/dist/engine-loader.d.ts +8 -8
  60. package/dist/engine-loader.js +27 -27
  61. package/dist/engine-loader.js.map +1 -1
  62. package/dist/geoplateforme.d.ts +10 -10
  63. package/dist/geoplateforme.js +22 -20
  64. package/dist/geoplateforme.js.map +1 -1
  65. package/dist/index.d.ts +1 -0
  66. package/dist/index.js.map +1 -1
  67. package/dist/isard_bg.wasm +0 -0
  68. package/dist/isard_core_bg.wasm +0 -0
  69. package/dist/isard_points_bg.wasm +0 -0
  70. package/dist/layers/extrusions.d.ts +1 -1
  71. package/dist/layers/extrusions.js +10 -5
  72. package/dist/layers/extrusions.js.map +1 -1
  73. package/dist/layers/features.d.ts +10 -10
  74. package/dist/layers/features.js +41 -42
  75. package/dist/layers/features.js.map +1 -1
  76. package/dist/layers/glyphs.d.ts +3 -3
  77. package/dist/layers/glyphs.js +34 -40
  78. package/dist/layers/glyphs.js.map +1 -1
  79. package/dist/layers/icons.d.ts +8 -8
  80. package/dist/layers/icons.js +76 -68
  81. package/dist/layers/icons.js.map +1 -1
  82. package/dist/layers/layers.d.ts +1 -1
  83. package/dist/layers/layers.js +33 -29
  84. package/dist/layers/layers.js.map +1 -1
  85. package/dist/layers/panoramas.d.ts +2 -2
  86. package/dist/layers/panoramas.js +52 -41
  87. package/dist/layers/panoramas.js.map +1 -1
  88. package/dist/layers/pointclouds.d.ts +3 -3
  89. package/dist/layers/pointclouds.js +25 -33
  90. package/dist/layers/pointclouds.js.map +1 -1
  91. package/dist/layers/symbols.d.ts +1 -1
  92. package/dist/layers/symbols.js +68 -71
  93. package/dist/layers/symbols.js.map +1 -1
  94. package/dist/map/basemap-layers.d.ts +26 -0
  95. package/dist/map/basemap-layers.js +61 -0
  96. package/dist/map/basemap-layers.js.map +1 -0
  97. package/dist/map/canvas.d.ts +17 -0
  98. package/dist/map/canvas.js +56 -0
  99. package/dist/map/canvas.js.map +1 -0
  100. package/dist/map/checks.d.ts +11 -0
  101. package/dist/map/checks.js +39 -0
  102. package/dist/map/checks.js.map +1 -0
  103. package/dist/map/credits.d.ts +17 -0
  104. package/dist/map/credits.js +34 -0
  105. package/dist/map/credits.js.map +1 -0
  106. package/dist/map/engine-settings.d.ts +15 -0
  107. package/dist/map/engine-settings.js +45 -0
  108. package/dist/map/engine-settings.js.map +1 -0
  109. package/dist/map/engines.d.ts +41 -0
  110. package/dist/map/engines.js +77 -0
  111. package/dist/map/engines.js.map +1 -0
  112. package/dist/map/events.d.ts +14 -0
  113. package/dist/map/events.js +46 -0
  114. package/dist/map/events.js.map +1 -0
  115. package/dist/map/frame-loop.d.ts +61 -0
  116. package/dist/map/frame-loop.js +139 -0
  117. package/dist/map/frame-loop.js.map +1 -0
  118. package/dist/map/hover-pick.d.ts +30 -0
  119. package/dist/map/hover-pick.js +56 -0
  120. package/dist/map/hover-pick.js.map +1 -0
  121. package/dist/map/layer-spec.d.ts +42 -0
  122. package/dist/map/layer-spec.js +34 -0
  123. package/dist/map/layer-spec.js.map +1 -0
  124. package/dist/map/layer-stack.d.ts +36 -0
  125. package/dist/map/layer-stack.js +101 -0
  126. package/dist/map/layer-stack.js.map +1 -0
  127. package/dist/map/overlay-host.d.ts +36 -0
  128. package/dist/map/overlay-host.js +101 -0
  129. package/dist/map/overlay-host.js.map +1 -0
  130. package/dist/map/panorama-host.d.ts +5 -0
  131. package/dist/map/panorama-host.js +32 -0
  132. package/dist/map/panorama-host.js.map +1 -0
  133. package/dist/map/raster-source.d.ts +11 -0
  134. package/dist/map/raster-source.js +26 -0
  135. package/dist/map/raster-source.js.map +1 -0
  136. package/dist/map/symbol-atlases.d.ts +26 -0
  137. package/dist/map/symbol-atlases.js +59 -0
  138. package/dist/map/symbol-atlases.js.map +1 -0
  139. package/dist/map/viewshed.d.ts +5 -0
  140. package/dist/map/viewshed.js +28 -0
  141. package/dist/map/viewshed.js.map +1 -0
  142. package/dist/map/workers.d.ts +46 -0
  143. package/dist/map/workers.js +73 -0
  144. package/dist/map/workers.js.map +1 -0
  145. package/dist/map.d.ts +33 -120
  146. package/dist/map.js +164 -689
  147. package/dist/map.js.map +1 -1
  148. package/dist/react/Control.d.ts +11 -0
  149. package/dist/react/Control.js +18 -0
  150. package/dist/react/Control.js.map +1 -0
  151. package/dist/react/CustomLayer.d.ts +11 -0
  152. package/dist/react/CustomLayer.js +30 -0
  153. package/dist/react/CustomLayer.js.map +1 -0
  154. package/dist/react/IsardMap.d.ts +43 -0
  155. package/dist/react/IsardMap.js +146 -0
  156. package/dist/react/IsardMap.js.map +1 -0
  157. package/dist/react/Layer.d.ts +42 -0
  158. package/dist/react/Layer.js +74 -0
  159. package/dist/react/Layer.js.map +1 -0
  160. package/dist/react/Marker.d.ts +24 -0
  161. package/dist/react/Marker.js +53 -0
  162. package/dist/react/Marker.js.map +1 -0
  163. package/dist/react/Panel.d.ts +11 -0
  164. package/dist/react/Panel.js +37 -0
  165. package/dist/react/Panel.js.map +1 -0
  166. package/dist/react/Popup.d.ts +18 -0
  167. package/dist/react/Popup.js +60 -0
  168. package/dist/react/Popup.js.map +1 -0
  169. package/dist/react/Swipe.d.ts +9 -0
  170. package/dist/react/Swipe.js +41 -0
  171. package/dist/react/Swipe.js.map +1 -0
  172. package/dist/react/Viewshed.d.ts +5 -0
  173. package/dist/react/Viewshed.js +28 -0
  174. package/dist/react/Viewshed.js.map +1 -0
  175. package/dist/react/context.d.ts +32 -0
  176. package/dist/react/context.js +20 -0
  177. package/dist/react/context.js.map +1 -0
  178. package/dist/react/index.d.ts +15 -108
  179. package/dist/react/index.js +10 -397
  180. package/dist/react/index.js.map +1 -1
  181. package/dist/settings.d.ts +5 -9
  182. package/dist/settings.js +17 -15
  183. package/dist/settings.js.map +1 -1
  184. package/dist/types.d.ts +3 -3
  185. package/dist/types.js.map +1 -1
  186. package/dist/ui/controls.js +6 -4
  187. package/dist/ui/controls.js.map +1 -1
  188. package/dist/ui/interaction.d.ts +2 -2
  189. package/dist/ui/interaction.js +8 -7
  190. package/dist/ui/interaction.js.map +1 -1
  191. package/dist/ui/overlay.js +18 -20
  192. package/dist/ui/overlay.js.map +1 -1
  193. package/dist/ui/style.d.ts +1 -1
  194. package/dist/ui/style.js +2 -2
  195. package/dist/ui/style.js.map +1 -1
  196. package/dist/util/animation.d.ts +3 -3
  197. package/dist/util/animation.js +6 -6
  198. package/dist/util/animation.js.map +1 -1
  199. package/dist/util/color.d.ts +1 -1
  200. package/dist/util/color.js +14 -16
  201. package/dist/util/color.js.map +1 -1
  202. package/dist/util/geo.d.ts +6 -6
  203. package/dist/util/geo.js +12 -12
  204. package/dist/util/geo.js.map +1 -1
  205. package/dist/util/guards.d.ts +7 -0
  206. package/dist/util/guards.js +8 -0
  207. package/dist/util/guards.js.map +1 -0
  208. package/dist/util/lru.js.map +1 -1
  209. package/dist/wasm/isard.d.ts +168 -0
  210. package/dist/wasm/isard.js +146 -0
  211. package/dist/wasm/isard_core.d.ts +144 -0
  212. package/dist/wasm/isard_core.js +122 -0
  213. package/dist/workers/basemap.worker.d.ts +3 -3
  214. package/dist/workers/basemap.worker.js +94 -83
  215. package/dist/workers/basemap.worker.js.map +1 -1
  216. package/package.json +1 -1
@@ -0,0 +1,28 @@
1
+ /** `<Viewshed>`: an observer's viewshed, several drawn together */
2
+ import { useContext, useEffect, useMemo } from 'react';
3
+ import { MapContext } from "./context.js";
4
+ /** An observer's viewshed; several `<Viewshed>` are drawn together */
5
+ export const Viewshed = (props) => {
6
+ const binding = useContext(MapContext);
7
+ const key = useMemo(() => ({}), []);
8
+ // Numbers, strings and the position: compared by value
9
+ const options = JSON.stringify(props);
10
+ // Its observer taken off the map's viewsheds when unmounted
11
+ useEffect(() => {
12
+ if (!binding)
13
+ return;
14
+ return () => {
15
+ binding.viewsheds.delete(key);
16
+ binding.applyViewsheds();
17
+ };
18
+ }, [binding, key]);
19
+ // Its observer set among the map's viewsheds when its options change (compared by value)
20
+ useEffect(() => {
21
+ if (!binding)
22
+ return;
23
+ binding.viewsheds.set(key, JSON.parse(options));
24
+ binding.applyViewsheds();
25
+ }, [binding, key, options]);
26
+ return null;
27
+ };
28
+ //# sourceMappingURL=Viewshed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Viewshed.js","sourceRoot":"","sources":["../../src/react/Viewshed.tsx"],"names":[],"mappings":"AAAA,mEAAmE;AAEnE,OAAO,EAAkB,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,sEAAsE;AACtE,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAsB,EAAa,EAAE;IAC5D,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACpC,uDAAuD;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEtC,4DAA4D;IAC5D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9B,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAEnB,yFAAyF;IACzF,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAC,CAAC;QACnE,OAAO,CAAC,cAAc,EAAE,CAAC;IAC3B,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAE5B,OAAO,IAAI,CAAC;AACd,CAAC,CAAC","sourcesContent":["/** `<Viewshed>`: an observer's viewshed, several drawn together */\n\nimport { type ReactNode, useContext, useEffect, useMemo } from 'react';\nimport type { ViewshedOptions } from '../types.ts';\nimport { MapContext } from './context.ts';\n\n/** An observer's viewshed; several `<Viewshed>` are drawn together */\nexport const Viewshed = (props: ViewshedOptions): ReactNode => {\n const binding = useContext(MapContext);\n const key = useMemo(() => ({}), []);\n // Numbers, strings and the position: compared by value\n const options = JSON.stringify(props);\n\n // Its observer taken off the map's viewsheds when unmounted\n useEffect(() => {\n if (!binding) return;\n\n return () => {\n binding.viewsheds.delete(key);\n binding.applyViewsheds();\n };\n }, [binding, key]);\n\n // Its observer set among the map's viewsheds when its options change (compared by value)\n useEffect(() => {\n if (!binding) return;\n binding.viewsheds.set(key, JSON.parse(options) as ViewshedOptions);\n binding.applyViewsheds();\n }, [binding, key, options]);\n\n return null;\n};\n"]}
@@ -0,0 +1,32 @@
1
+ /** What the components of a map share: the map, the order of their layers, the viewsheds, the swipe and the marker
2
+ * around; the hooks */
3
+ import type { LayerOrder } from '../bind/layers.ts';
4
+ import type { Layer as LayerHandle } from '../layers/layers.ts';
5
+ import type { GeoMap } from '../map.ts';
6
+ import type { LonLat, MapEvents, ViewshedOptions } from '../types.ts';
7
+ import type { Marker as MarkerHandle } from '../ui/overlay.ts';
8
+ export interface Binding {
9
+ map: GeoMap;
10
+ order: LayerOrder;
11
+ /** The observers of the `<Viewshed>` components, set on the map together */
12
+ viewsheds: Map<object, ViewshedOptions>;
13
+ applyViewsheds(): void;
14
+ }
15
+ export declare const MapContext: import("react").Context<Binding | undefined>;
16
+ /** The layers of a `<Swipe>` around, its `<Layer>` children joining it */
17
+ export interface SwipeGroup {
18
+ set(layer: LayerHandle): void;
19
+ unset(layer: LayerHandle): void;
20
+ }
21
+ export declare const SwipeContext: import("react").Context<SwipeGroup | undefined>;
22
+ /** The marker of a `<Marker>` around and its position (a `<Popup>` in it opens on its click, at that position) */
23
+ export declare const MarkerContext: import("react").Context<{
24
+ marker: MarkerHandle;
25
+ lonLat: LonLat;
26
+ } | undefined>;
27
+ /** The map of the `<IsardMap>` around, once created (undefined before) */
28
+ export declare const useMap: () => GeoMap | undefined;
29
+ /** Listens to an event of the map around while the component is mounted; the listener may change at each render */
30
+ export declare const useMapEvent: <K extends keyof MapEvents>(type: K, listener: (event: MapEvents[K]) => void) => void;
31
+ /** The entries of an object whose value is defined (`exactOptionalPropertyTypes`) */
32
+ export declare const defined: <T extends object>(object: T) => { [K in keyof T]?: Exclude<T[K], undefined>; };
@@ -0,0 +1,20 @@
1
+ /** What the components of a map share: the map, the order of their layers, the viewsheds, the swipe and the marker
2
+ * around; the hooks */
3
+ import { createContext, useContext, useEffect, useRef } from 'react';
4
+ export const MapContext = createContext(undefined);
5
+ export const SwipeContext = createContext(undefined);
6
+ /** The marker of a `<Marker>` around and its position (a `<Popup>` in it opens on its click, at that position) */
7
+ export const MarkerContext = createContext(undefined);
8
+ /** The map of the `<IsardMap>` around, once created (undefined before) */
9
+ export const useMap = () => useContext(MapContext)?.map;
10
+ /** Listens to an event of the map around while the component is mounted; the listener may change at each render */
11
+ export const useMapEvent = (type, listener) => {
12
+ const map = useMap();
13
+ const latest = useRef(listener);
14
+ latest.current = listener;
15
+ // Listening while mounted, to the listener of the last render; stops when unmounted or the map changes
16
+ useEffect(() => map?.on(type, (event) => latest.current(event)), [map, type]);
17
+ };
18
+ /** The entries of an object whose value is defined (`exactOptionalPropertyTypes`) */
19
+ export const defined = (object) => Object.fromEntries(Object.entries(object).filter(([, value]) => value !== undefined));
20
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/react/context.ts"],"names":[],"mappings":"AAAA;uBACuB;AAEvB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAerE,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAsB,SAAS,CAAC,CAAC;AAQxE,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAyB,SAAS,CAAC,CAAC;AAE7E,kHAAkH;AAClH,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAuD,SAAS,CAAC,CAAC;AAE5G,0EAA0E;AAC1E,MAAM,CAAC,MAAM,MAAM,GAAG,GAAuB,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC;AAE5E,mHAAmH;AACnH,MAAM,CAAC,MAAM,WAAW,GAAG,CAA4B,IAAO,EAAE,QAAuC,EAAQ,EAAE;IAC/G,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEhC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC;IAC1B,uGAAuG;IACvG,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AAChF,CAAC,CAAC;AAEF,qFAAqF;AACrF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAmB,MAAS,EAAiD,EAAE,CACpG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAEnF,CAAC","sourcesContent":["/** What the components of a map share: the map, the order of their layers, the viewsheds, the swipe and the marker\n * around; the hooks */\n\nimport { createContext, useContext, useEffect, useRef } from 'react';\nimport type { LayerOrder } from '../bind/layers.ts';\nimport type { Layer as LayerHandle } from '../layers/layers.ts';\nimport type { GeoMap } from '../map.ts';\nimport type { LonLat, MapEvents, ViewshedOptions } from '../types.ts';\nimport type { Marker as MarkerHandle } from '../ui/overlay.ts';\n\nexport interface Binding {\n map: GeoMap;\n order: LayerOrder;\n /** The observers of the `<Viewshed>` components, set on the map together */\n viewsheds: Map<object, ViewshedOptions>;\n applyViewsheds(): void;\n}\n\nexport const MapContext = createContext<Binding | undefined>(undefined);\n\n/** The layers of a `<Swipe>` around, its `<Layer>` children joining it */\nexport interface SwipeGroup {\n set(layer: LayerHandle): void;\n unset(layer: LayerHandle): void;\n}\n\nexport const SwipeContext = createContext<SwipeGroup | undefined>(undefined);\n\n/** The marker of a `<Marker>` around and its position (a `<Popup>` in it opens on its click, at that position) */\nexport const MarkerContext = createContext<{ marker: MarkerHandle; lonLat: LonLat } | undefined>(undefined);\n\n/** The map of the `<IsardMap>` around, once created (undefined before) */\nexport const useMap = (): GeoMap | undefined => useContext(MapContext)?.map;\n\n/** Listens to an event of the map around while the component is mounted; the listener may change at each render */\nexport const useMapEvent = <K extends keyof MapEvents>(type: K, listener: (event: MapEvents[K]) => void): void => {\n const map = useMap();\n const latest = useRef(listener);\n\n latest.current = listener;\n // Listening while mounted, to the listener of the last render; stops when unmounted or the map changes\n useEffect(() => map?.on(type, (event) => latest.current(event)), [map, type]);\n};\n\n/** The entries of an object whose value is defined (`exactOptionalPropertyTypes`) */\nexport const defined = <T extends object>(object: T): { [K in keyof T]?: Exclude<T[K], undefined> } =>\n Object.fromEntries(Object.entries(object).filter(([, value]) => value !== undefined)) as {\n [K in keyof T]?: Exclude<T[K], undefined>;\n };\n"]}
@@ -9,111 +9,18 @@
9
9
  * </IsardMap>
10
10
  * ```
11
11
  */
12
- import { type CSSProperties, type ReactNode } from 'react';
13
- import type { Layer as LayerHandle } from '../layers/layers.ts';
14
- import { GeoMap, type LayerSpec } from '../map.ts';
15
- import type { GeoMapOptions, LonLat, MapEvents, Point, SwipeOptions, ViewshedOptions } from '../types.ts';
16
- import { type Anchor, Marker as MarkerHandle, Panel as PanelHandle, type PanelOptions, Popup as PopupHandle, type PopupOptions } from '../ui/overlay.ts';
17
- import type { Camera } from '../wasm/isard.js';
18
- /** The map of the `<IsardMap>` around, once created (undefined before) */
19
- export declare function useMap(): GeoMap | undefined;
20
- /** Listens to an event of the map around while the component is mounted; the listener may change at each render */
21
- export declare function useMapEvent<K extends keyof MapEvents>(type: K, listener: (event: MapEvents[K]) => void): void;
22
- /** The props of the map's events: `onClick` for 'click', `onMoveEnd` for 'moveend'… */
23
- export interface MapEventProps {
24
- onMoveStart?: (camera: Camera) => void;
25
- onMove?: (camera: Camera) => void;
26
- onMoveEnd?: (camera: Camera) => void;
27
- onResize?: (event: MapEvents['resize']) => void;
28
- onHover?: (event: MapEvents['hover']) => void;
29
- onHoverFeature?: (event: MapEvents['hoverfeature']) => void;
30
- onClick?: (event: MapEvents['click']) => void;
31
- onRender?: (event: MapEvents['render']) => void;
32
- onIdle?: () => void;
33
- onLeave?: () => void;
34
- }
35
- export interface IsardMapProps extends Omit<GeoMapOptions, keyof Camera>, MapEventProps {
36
- /** The camera at creation, then left to the user's gestures */
37
- center?: LonLat;
38
- zoom?: number;
39
- pitch?: number;
40
- bearing?: number;
41
- /** A camera the map follows: set again whenever it changes (with `onMove` to keep it in a state) */
42
- camera?: Partial<Camera>;
43
- /** The map, once created */
44
- onLoad?: (map: GeoMap) => void;
45
- /** The map's creation failed (no WebGL2, the engine not found) */
46
- onError?: (error: unknown) => void;
47
- id?: string;
48
- className?: string;
49
- style?: CSSProperties;
50
- /** Layers, markers, popups, panels, effects; drawn once the map is created */
51
- children?: ReactNode;
52
- }
53
- /**
54
- * A map filling its element (give it a height). Created once mounted, destroyed when unmounted; the options read at
55
- * creation only (`body`, `preset`, `interactive`, the URLs) need a new `key` to take another value
56
- */
57
- export declare const IsardMap: import("react").ForwardRefExoticComponent<IsardMapProps & import("react").RefAttributes<GeoMap | undefined>>;
58
- export type LayerProps<P = Record<string, unknown>> = LayerSpec<P> & {
59
- /** Its place among the layers of the components: from the bottom up, the same order by mounting (default 0) */
60
- order?: number;
61
- /** The layer, once created and each time it is made anew */
62
- onLayer?: (layer: LayerHandle) => void;
63
- };
64
- /**
65
- * A layer: the options of its `add…` method with its `type` (`map.add`). A change of data, style or instances updates
66
- * it; a change of what is set at creation (its URL, grid, nodes…) makes it anew, in its place. Data, functions and
67
- * arrays are compared by identity: keep them in a memo or a state. The ref gives the layer's handle
68
- */
69
- export declare const Layer: import("react").ForwardRefExoticComponent<LayerProps<Record<string, unknown>> & import("react").RefAttributes<LayerHandle | undefined>>;
70
- export interface MarkerProps {
71
- lonLat: LonLat;
72
- /** Metres above the ground, its stem down to `base` (what it stands on: a roof, a mesh) */
73
- height?: number;
74
- base?: number;
75
- draggable?: boolean;
76
- offset?: Point;
77
- /** Which part of the element sits on the position (default 'bottom' for the pin, 'center' with an icon) */
78
- anchor?: Anchor;
79
- className?: string;
80
- /** The marker's look, in place of the default pin; the element changes with it */
81
- icon?: ReactNode;
82
- onDragStart?: (lonLat: LonLat) => void;
83
- onDrag?: (lonLat: LonLat) => void;
84
- onDragEnd?: (lonLat: LonLat) => void;
85
- /** A `<Popup>` opened by a click on the marker */
86
- children?: ReactNode;
87
- }
88
- /** A marker at a position, its look the default pin or the `icon` given */
89
- export declare function Marker(props: MarkerProps): ReactNode;
90
- export interface PopupProps extends PopupOptions {
91
- /** Its position; in a `<Marker>`, the marker's */
92
- lonLat?: LonLat;
93
- /** Metres above the ground (in a `<Marker>`, the marker's) */
94
- height?: number;
95
- /** Open or closed, when the application decides; else open when mounted alone, on the marker's click in a marker */
96
- open?: boolean;
97
- onOpen?: () => void;
98
- /** Closed by its button, a click on the map, or the marker's click */
99
- onClose?: () => void;
100
- children?: ReactNode;
101
- }
102
- /** A popup of JSX content, at a position or on a `<Marker>` */
103
- export declare function Popup(props: PopupProps): ReactNode;
104
- export interface PanelProps extends Omit<PanelOptions, 'element'> {
105
- lonLat: LonLat;
106
- /** What stands in 3D: a video, an iframe, a sign */
107
- children?: ReactNode;
108
- }
109
- /** JSX standing in 3D at a position, `width` metres wide, facing `heading` */
110
- export declare function Panel(props: PanelProps): ReactNode;
111
- /** An observer's viewshed; several `<Viewshed>` are drawn together */
112
- export declare function Viewshed(props: ViewshedOptions): ReactNode;
113
- export interface SwipeProps extends Omit<SwipeOptions, 'layers'> {
114
- /** The `<Layer>` shown on one side of the line only */
115
- children?: ReactNode;
116
- }
117
- /** The `<Layer>` in it shown on one side of a vertical line only, at `position` CSS pixels from the left */
118
- export declare function Swipe(props: SwipeProps): ReactNode;
119
- export type { Camera, GeoMap, LayerHandle, LayerSpec, LonLat, MarkerHandle, PanelHandle, PopupHandle };
12
+ export type { Layer as LayerHandle } from '../layers/layers.ts';
13
+ export type { GeoMap, LayerSpec } from '../map.ts';
14
+ export type { LonLat } from '../types.ts';
15
+ export type { Marker as MarkerHandle, Panel as PanelHandle, Popup as PopupHandle } from '../ui/overlay.ts';
16
+ export type { Camera } from '../wasm/isard.js';
17
+ export { Control, type ControlProps } from './Control.tsx';
18
+ export { CustomLayer, type CustomLayerProps } from './CustomLayer.tsx';
19
+ export { useMap, useMapEvent } from './context.ts';
20
+ export { IsardMap, type IsardMapProps, type MapEventProps } from './IsardMap.tsx';
21
+ export { Layer, type LayerHandles, type LayerProps, type LayerType } from './Layer.tsx';
22
+ export { Marker, type MarkerProps } from './Marker.tsx';
23
+ export { Panel, type PanelProps } from './Panel.tsx';
24
+ export { Popup, type PopupProps } from './Popup.tsx';
25
+ export { Swipe, type SwipeProps } from './Swipe.tsx';
26
+ export { Viewshed } from './Viewshed.tsx';
@@ -9,401 +9,14 @@
9
9
  * </IsardMap>
10
10
  * ```
11
11
  */
12
- import { createContext, createElement, forwardRef, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, } from 'react';
13
- import { createPortal } from 'react-dom';
14
- import { applyLayerChange, LayerOrder, layerChange } from "../bind/layers.js";
15
- import { GeoMap } from "../map.js";
16
- import { Marker as MarkerHandle, Panel as PanelHandle, Popup as PopupHandle, } from "../ui/overlay.js";
17
- const MapContext = createContext(undefined);
18
- /** The map of the `<IsardMap>` around, once created (undefined before) */
19
- export function useMap() {
20
- return useContext(MapContext)?.map;
21
- }
22
- /** Listens to an event of the map around while the component is mounted; the listener may change at each render */
23
- export function useMapEvent(type, listener) {
24
- const map = useMap();
25
- const latest = useRef(listener);
26
- latest.current = listener;
27
- useEffect(() => map?.on(type, (event) => latest.current(event)), [map, type]);
28
- }
29
- const EVENT_PROPS = {
30
- onMoveStart: 'movestart',
31
- onMove: 'move',
32
- onMoveEnd: 'moveend',
33
- onResize: 'resize',
34
- onHover: 'hover',
35
- onHoverFeature: 'hoverfeature',
36
- onClick: 'click',
37
- onRender: 'render',
38
- onIdle: 'idle',
39
- onLeave: 'leave',
40
- };
41
- /** Options the map takes again after its creation, and how */
42
- const LIVE_OPTIONS = {
43
- basemap: (map, p) => {
44
- if (p.basemap)
45
- map.setBasemap(p.basemap, p.hillshade);
46
- },
47
- hillshade: (map, p) => {
48
- if (p.basemap)
49
- map.setBasemap(p.basemap, p.hillshade);
50
- },
51
- terrain: (map, p) => map.setTerrain(p.terrain ?? false),
52
- minZoom: (map, p) => map.setMinZoom(p.minZoom ?? 0),
53
- maxZoom: (map, p) => map.setMaxZoom(p.maxZoom ?? 22),
54
- maxPitch: (map, p) => map.setMaxPitch(p.maxPitch ?? 70),
55
- atmosphere: (map, p) => map.setAtmosphere(p.atmosphere),
56
- projection: (map, p) => map.setProjection(p.projection ?? 'globe'),
57
- loading: (map, p) => map.setLoading(p.loading ?? 'immediate'),
58
- sky: (map, p) => map.setSky(p.sky ?? true),
59
- background: (map, p) => {
60
- if (p.background)
61
- map.setBackground(p.background);
62
- },
63
- };
64
- function sameCamera(a, b) {
65
- return ((b.center === undefined || (a.center[0] === b.center[0] && a.center[1] === b.center[1])) &&
66
- (b.zoom === undefined || a.zoom === b.zoom) &&
67
- (b.pitch === undefined || a.pitch === b.pitch) &&
68
- (b.bearing === undefined || a.bearing === b.bearing));
69
- }
70
- /**
71
- * A map filling its element (give it a height). Created once mounted, destroyed when unmounted; the options read at
72
- * creation only (`body`, `preset`, `interactive`, the URLs) need a new `key` to take another value
73
- */
74
- export const IsardMap = forwardRef(function IsardMap(props, ref) {
75
- const element = useRef(null);
76
- const [binding, setBinding] = useState();
77
- const latest = useRef(props);
78
- latest.current = props;
79
- useImperativeHandle(ref, () => binding?.map, [binding]);
80
- useEffect(() => {
81
- const container = element.current;
82
- if (!container)
83
- return;
84
- let cancelled = false;
85
- let created;
86
- const { camera, center, zoom, pitch, bearing, children: _, ...options } = latest.current;
87
- GeoMap.create(container, {
88
- ...stripProps(options),
89
- ...defined({ center, zoom, pitch, bearing }),
90
- ...camera,
91
- }).then((map) => {
92
- // Unmounted while the engine was loading (or StrictMode's second mount): that map is not wanted
93
- if (cancelled) {
94
- map.destroy();
95
- return;
96
- }
97
- created = map;
98
- const viewsheds = new Map();
99
- setBinding({
100
- map,
101
- order: new LayerOrder(),
102
- viewsheds,
103
- applyViewsheds: () => map.setViewshed(viewsheds.size > 0 ? [...viewsheds.values()] : undefined),
104
- });
105
- latest.current.onLoad?.(map);
106
- }, (error) => {
107
- if (cancelled)
108
- return;
109
- if (latest.current.onError)
110
- latest.current.onError(error);
111
- else
112
- console.error(error);
113
- });
114
- return () => {
115
- cancelled = true;
116
- created?.destroy();
117
- setBinding(undefined);
118
- };
119
- }, []);
120
- // The events, each listened to once: the props may give another function at each render
121
- const map = binding?.map;
122
- useEffect(() => {
123
- if (!map)
124
- return;
125
- const offs = Object.entries(EVENT_PROPS).map(([prop, type]) => map.on(type, (event) => latest.current[prop]?.(event)));
126
- return () => {
127
- for (const off of offs)
128
- off();
129
- };
130
- }, [map]);
131
- // The options taken again, compared with what the map was given last
132
- const applied = useRef(props);
133
- useEffect(() => {
134
- if (!map)
135
- return;
136
- const last = applied.current;
137
- applied.current = props;
138
- const done = new Set();
139
- for (const [key, apply] of Object.entries(LIVE_OPTIONS)) {
140
- if (!apply || done.has(apply) || Object.is(last[key], props[key])) {
141
- continue;
142
- }
143
- done.add(apply);
144
- apply(map, props);
145
- }
146
- });
147
- const { camera } = props;
148
- useEffect(() => {
149
- if (map && camera && !sameCamera(map.getCamera(), camera))
150
- map.setCamera(camera);
151
- }, [map, camera]);
152
- return createElement('div', { ref: element, id: props.id, className: props.className, style: props.style }, binding ? createElement(MapContext.Provider, { value: binding }, props.children) : null);
153
- });
154
- /** The props that are not options of the map */
155
- function stripProps(props) {
156
- const options = { ...props };
157
- for (const key of [...Object.keys(EVENT_PROPS), 'onLoad', 'onError', 'id', 'className', 'style'])
158
- delete options[key];
159
- return options;
160
- }
161
- /** The entries of an object whose value is defined (`exactOptionalPropertyTypes`) */
162
- function defined(object) {
163
- return Object.fromEntries(Object.entries(object).filter(([, value]) => value !== undefined));
164
- }
165
- // ── Layers ──
166
- const SwipeContext = createContext(undefined);
167
- /**
168
- * A layer: the options of its `add…` method with its `type` (`map.add`). A change of data, style or instances updates
169
- * it; a change of what is set at creation (its URL, grid, nodes…) makes it anew, in its place. Data, functions and
170
- * arrays are compared by identity: keep them in a memo or a state. The ref gives the layer's handle
171
- */
172
- export const Layer = forwardRef(function Layer(props, ref) {
173
- const binding = useContext(MapContext);
174
- const swipe = useContext(SwipeContext);
175
- const { order = 0, onLayer, ...spec } = props;
176
- const state = useRef(undefined);
177
- const [layer, setLayer] = useState();
178
- useImperativeHandle(ref, () => layer, [layer]);
179
- const latest = useRef({ spec, order, onLayer });
180
- latest.current = { spec, order, onLayer };
181
- useEffect(() => {
182
- if (!binding)
183
- return;
184
- const { spec, order, onLayer } = latest.current;
185
- const created = binding.map.add(spec);
186
- binding.order.place(created, order);
187
- state.current = { layer: created, spec, order };
188
- swipe?.set(created);
189
- setLayer(created);
190
- onLayer?.(created);
191
- return () => {
192
- const current = state.current;
193
- state.current = undefined;
194
- if (!current)
195
- return;
196
- binding.order.remove(current.layer);
197
- swipe?.unset(current.layer);
198
- if (binding.map.hasLayer(current.layer))
199
- current.layer.remove();
200
- };
201
- }, [binding, swipe]);
202
- useEffect(() => {
203
- const current = state.current;
204
- if (!binding || !current)
205
- return;
206
- const next = spec;
207
- const change = layerChange(current.spec, next);
208
- current.spec = next;
209
- if (change?.rebuild) {
210
- const old = current.layer;
211
- const fresh = binding.map.rebuildLayer(old, next);
212
- binding.order.place(fresh, order, old);
213
- swipe?.unset(old);
214
- swipe?.set(fresh);
215
- current.layer = fresh;
216
- current.order = order;
217
- setLayer(fresh);
218
- latest.current.onLayer?.(fresh);
219
- return;
220
- }
221
- if (change)
222
- applyLayerChange(current.layer, next, change);
223
- if (current.order !== order) {
224
- current.order = order;
225
- binding.order.place(current.layer, order, current.layer);
226
- }
227
- });
228
- return null;
229
- });
230
- // ── Markers, popups, panels ──
231
- /** The marker of a `<Marker>` around (a `<Popup>` in it opens on its click) */
232
- const MarkerContext = createContext(undefined);
233
- /** A marker at a position, its look the default pin or the `icon` given */
234
- export function Marker(props) {
235
- const map = useMap();
236
- const custom = props.icon !== undefined;
237
- const { anchor, className } = props;
238
- const element = useMemo(() => (custom ? document.createElement('div') : undefined), [custom]);
239
- const marker = useMemo(() => new MarkerHandle({ ...defined({ anchor, className, element }) }), [anchor, className, element]);
240
- const latest = useRef(props);
241
- latest.current = props;
242
- useEffect(() => {
243
- if (!map)
244
- return;
245
- marker.addTo(map);
246
- const offs = [
247
- marker.on('dragstart', (e) => latest.current.onDragStart?.(e.lonLat)),
248
- marker.on('drag', (e) => latest.current.onDrag?.(e.lonLat)),
249
- marker.on('dragend', (e) => latest.current.onDragEnd?.(e.lonLat)),
250
- ];
251
- return () => {
252
- for (const off of offs)
253
- off();
254
- marker.remove();
255
- };
256
- }, [map, marker]);
257
- const { lonLat, height = 0, base = 0, draggable = false, offset } = props;
258
- useLayoutEffect(() => {
259
- marker.setLonLat(lonLat);
260
- }, [marker, lonLat[0], lonLat[1]]);
261
- useLayoutEffect(() => {
262
- marker.setHeight(height, base);
263
- }, [marker, height, base]);
264
- useLayoutEffect(() => {
265
- marker.setDraggable(draggable);
266
- }, [marker, draggable]);
267
- useLayoutEffect(() => {
268
- if (offset)
269
- marker.setOffset(offset);
270
- }, [marker, offset?.[0], offset?.[1]]);
271
- return createElement(MarkerContext.Provider, { value: marker }, element ? createPortal(props.icon, element) : null, props.children);
272
- }
273
- /** A popup of JSX content, at a position or on a `<Marker>` */
274
- export function Popup(props) {
275
- const map = useMap();
276
- const marker = useContext(MarkerContext);
277
- const { anchor, closeButton, closeOnClick, maxWidth, className } = props;
278
- const content = useMemo(() => document.createElement('div'), []);
279
- const popup = useMemo(() => new PopupHandle(defined({ anchor, closeButton, closeOnClick, maxWidth, className })).setDOMContent(content), [anchor, closeButton, closeOnClick, maxWidth, className, content]);
280
- const latest = useRef(props);
281
- latest.current = props;
282
- useEffect(() => {
283
- if (!map)
284
- return;
285
- const offs = [
286
- popup.on('open', () => latest.current.onOpen?.()),
287
- popup.on('close', () => latest.current.onClose?.()),
288
- ];
289
- if (marker)
290
- marker.setPopup(popup);
291
- return () => {
292
- for (const off of offs)
293
- off();
294
- if (marker?.getPopup() === popup)
295
- marker.setPopup(undefined);
296
- popup.remove();
297
- };
298
- }, [map, marker, popup]);
299
- const { lonLat, height, open, offset } = props;
300
- const opened = open ?? !marker;
301
- useLayoutEffect(() => {
302
- if (offset)
303
- popup.setOffset(offset);
304
- }, [popup, offset?.[0], offset?.[1]]);
305
- useLayoutEffect(() => {
306
- if (!map)
307
- return;
308
- if (lonLat)
309
- popup.setLonLat(lonLat);
310
- else if (marker)
311
- popup.setLonLat(marker.getLonLat());
312
- if (height !== undefined)
313
- popup.setHeight(height);
314
- if (open === undefined && marker)
315
- return;
316
- if (opened && !popup.isOpen())
317
- popup.addTo(map);
318
- if (!opened && popup.isOpen())
319
- popup.remove();
320
- }, [map, marker, popup, lonLat?.[0], lonLat?.[1], height, open, opened]);
321
- return createPortal(props.children, content);
322
- }
323
- /** JSX standing in 3D at a position, `width` metres wide, facing `heading` */
324
- export function Panel(props) {
325
- const map = useMap();
326
- const { className } = props;
327
- const element = useMemo(() => document.createElement('div'), []);
328
- // The width at creation: the placement is set again by the effect below
329
- const initialWidth = useRef(props.width);
330
- const panel = useMemo(() => new PanelHandle({ element, width: initialWidth.current, ...defined({ className }) }), [element, className]);
331
- useEffect(() => {
332
- if (!map)
333
- return;
334
- panel.addTo(map);
335
- return () => {
336
- panel.remove();
337
- };
338
- }, [map, panel]);
339
- const { lonLat, width, heading, pitch, height } = props;
340
- useLayoutEffect(() => {
341
- panel.setLonLat(lonLat);
342
- }, [panel, lonLat[0], lonLat[1]]);
343
- useLayoutEffect(() => {
344
- panel.setPlacement(defined({ width, heading, pitch, height }));
345
- }, [panel, width, heading, pitch, height]);
346
- // Its content may change its CSS size
347
- useLayoutEffect(() => {
348
- panel.resize();
349
- });
350
- return createPortal(props.children, element);
351
- }
352
- // ── Effects ──
353
- /** An observer's viewshed; several `<Viewshed>` are drawn together */
354
- export function Viewshed(props) {
355
- const binding = useContext(MapContext);
356
- const key = useMemo(() => ({}), []);
357
- useEffect(() => {
358
- if (!binding)
359
- return;
360
- return () => {
361
- binding.viewsheds.delete(key);
362
- binding.applyViewsheds();
363
- };
364
- }, [binding, key]);
365
- // Numbers, strings and the position: compared by value
366
- const options = JSON.stringify(props);
367
- useEffect(() => {
368
- if (!binding)
369
- return;
370
- binding.viewsheds.set(key, JSON.parse(options));
371
- binding.applyViewsheds();
372
- }, [binding, key, options]);
373
- return null;
374
- }
375
- /** The `<Layer>` in it shown on one side of a vertical line only, at `position` CSS pixels from the left */
376
- export function Swipe(props) {
377
- const map = useMap();
378
- const layers = useMemo(() => new Set(), []);
379
- const latest = useRef(props);
380
- latest.current = props;
381
- const group = useMemo(() => {
382
- if (!map)
383
- return undefined;
384
- const apply = () => {
385
- const { position, side } = latest.current;
386
- map.setSwipe(layers.size > 0 ? { position, layers: [...layers], ...defined({ side }) } : undefined);
387
- };
388
- return {
389
- set: (layer) => {
390
- layers.add(layer);
391
- apply();
392
- },
393
- unset: (layer) => {
394
- layers.delete(layer);
395
- apply();
396
- },
397
- };
398
- }, [map, layers]);
399
- const { position, side } = props;
400
- useEffect(() => {
401
- if (map && layers.size > 0)
402
- map.setSwipe({ position, layers: [...layers], ...defined({ side }) });
403
- }, [map, layers, position, side]);
404
- useEffect(() => () => {
405
- map?.setSwipe(undefined);
406
- }, [map]);
407
- return createElement(SwipeContext.Provider, { value: group }, props.children);
408
- }
12
+ export { Control } from "./Control.js";
13
+ export { CustomLayer } from "./CustomLayer.js";
14
+ export { useMap, useMapEvent } from "./context.js";
15
+ export { IsardMap } from "./IsardMap.js";
16
+ export { Layer } from "./Layer.js";
17
+ export { Marker } from "./Marker.js";
18
+ export { Panel } from "./Panel.js";
19
+ export { Popup } from "./Popup.js";
20
+ export { Swipe } from "./Swipe.js";
21
+ export { Viewshed } from "./Viewshed.js";
409
22
  //# sourceMappingURL=index.js.map