@accelint/map-toolkit 0.6.0 → 1.0.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 (183) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/catalog-info.yaml +5 -4
  3. package/dist/camera/index.d.ts +2 -2
  4. package/dist/camera/index.js +2 -2
  5. package/dist/camera/store.d.ts +120 -0
  6. package/dist/camera/store.js +279 -0
  7. package/dist/camera/store.js.map +1 -0
  8. package/dist/deckgl/base-map/constants.d.ts +1 -6
  9. package/dist/deckgl/base-map/constants.js +1 -6
  10. package/dist/deckgl/base-map/constants.js.map +1 -1
  11. package/dist/deckgl/base-map/controls.js +2 -0
  12. package/dist/deckgl/base-map/controls.js.map +1 -1
  13. package/dist/deckgl/base-map/index.d.ts +2 -2
  14. package/dist/deckgl/base-map/index.js +10 -11
  15. package/dist/deckgl/base-map/index.js.map +1 -1
  16. package/dist/deckgl/base-map/provider.js +1 -1
  17. package/dist/deckgl/index.d.ts +4 -4
  18. package/dist/deckgl/index.js +4 -4
  19. package/dist/deckgl/saved-viewports/storage.js +10 -2
  20. package/dist/deckgl/saved-viewports/storage.js.map +1 -1
  21. package/dist/deckgl/shapes/display-shape-layer/constants.js +5 -8
  22. package/dist/deckgl/shapes/display-shape-layer/constants.js.map +1 -1
  23. package/dist/deckgl/shapes/display-shape-layer/index.d.ts +18 -14
  24. package/dist/deckgl/shapes/display-shape-layer/index.js +63 -30
  25. package/dist/deckgl/shapes/display-shape-layer/index.js.map +1 -1
  26. package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.js +2 -16
  27. package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.js.map +1 -1
  28. package/dist/deckgl/shapes/display-shape-layer/store.js +58 -272
  29. package/dist/deckgl/shapes/display-shape-layer/store.js.map +1 -1
  30. package/dist/deckgl/shapes/display-shape-layer/types.d.ts +22 -11
  31. package/dist/deckgl/shapes/display-shape-layer/{use-shape-selection.d.ts → use-select-shape.d.ts} +9 -9
  32. package/dist/deckgl/shapes/display-shape-layer/{use-shape-selection.js → use-select-shape.js} +12 -12
  33. package/dist/deckgl/shapes/display-shape-layer/use-select-shape.js.map +1 -0
  34. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js +5 -66
  35. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js.map +1 -1
  36. package/dist/deckgl/shapes/display-shape-layer/utils/labels.d.ts +2 -65
  37. package/dist/deckgl/shapes/display-shape-layer/utils/labels.js +3 -121
  38. package/dist/deckgl/shapes/display-shape-layer/utils/labels.js.map +1 -1
  39. package/dist/deckgl/shapes/draw-shape-layer/constants.js +46 -0
  40. package/dist/deckgl/shapes/draw-shape-layer/constants.js.map +1 -0
  41. package/dist/deckgl/shapes/draw-shape-layer/events.d.ts +92 -0
  42. package/dist/deckgl/shapes/draw-shape-layer/events.js +56 -0
  43. package/dist/deckgl/shapes/draw-shape-layer/events.js.map +1 -0
  44. package/dist/deckgl/shapes/draw-shape-layer/fiber.d.ts +11 -0
  45. package/dist/{maplibre/constants.js → deckgl/shapes/draw-shape-layer/fiber.js} +6 -12
  46. package/dist/deckgl/shapes/draw-shape-layer/fiber.js.map +1 -0
  47. package/dist/deckgl/shapes/draw-shape-layer/index.d.ts +53 -0
  48. package/dist/deckgl/shapes/draw-shape-layer/index.js +95 -0
  49. package/dist/deckgl/shapes/draw-shape-layer/index.js.map +1 -0
  50. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js +51 -0
  51. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js.map +1 -0
  52. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js +73 -0
  53. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js.map +1 -0
  54. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js +87 -0
  55. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js.map +1 -0
  56. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js +88 -0
  57. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js.map +1 -0
  58. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js +77 -0
  59. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js.map +1 -0
  60. package/dist/deckgl/shapes/draw-shape-layer/modes/index.js +64 -0
  61. package/dist/deckgl/shapes/draw-shape-layer/modes/index.js.map +1 -0
  62. package/dist/deckgl/shapes/draw-shape-layer/store.js +175 -0
  63. package/dist/deckgl/shapes/draw-shape-layer/store.js.map +1 -0
  64. package/dist/deckgl/shapes/draw-shape-layer/types.d.ts +86 -0
  65. package/dist/{viewport/constants.js → deckgl/shapes/draw-shape-layer/types.js} +1 -12
  66. package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.d.ts +82 -0
  67. package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.js +112 -0
  68. package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.js.map +1 -0
  69. package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js +147 -0
  70. package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js.map +1 -0
  71. package/dist/deckgl/shapes/edit-shape-layer/constants.js +41 -0
  72. package/dist/deckgl/shapes/edit-shape-layer/constants.js.map +1 -0
  73. package/dist/deckgl/shapes/edit-shape-layer/events.d.ts +92 -0
  74. package/dist/deckgl/shapes/edit-shape-layer/events.js +56 -0
  75. package/dist/deckgl/shapes/edit-shape-layer/events.js.map +1 -0
  76. package/dist/deckgl/shapes/edit-shape-layer/fiber.d.ts +13 -0
  77. package/dist/deckgl/shapes/edit-shape-layer/fiber.js +14 -0
  78. package/dist/deckgl/shapes/edit-shape-layer/index.d.ts +63 -0
  79. package/dist/deckgl/shapes/edit-shape-layer/index.js +162 -0
  80. package/dist/deckgl/shapes/edit-shape-layer/index.js.map +1 -0
  81. package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js +154 -0
  82. package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js.map +1 -0
  83. package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js +147 -0
  84. package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js.map +1 -0
  85. package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js +87 -0
  86. package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js.map +1 -0
  87. package/dist/deckgl/shapes/edit-shape-layer/modes/index.js +61 -0
  88. package/dist/deckgl/shapes/edit-shape-layer/modes/index.js.map +1 -0
  89. package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js +109 -0
  90. package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js.map +1 -0
  91. package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js +289 -0
  92. package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js.map +1 -0
  93. package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js +121 -0
  94. package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js.map +1 -0
  95. package/dist/deckgl/shapes/edit-shape-layer/store.js +194 -0
  96. package/dist/deckgl/shapes/edit-shape-layer/store.js.map +1 -0
  97. package/dist/deckgl/shapes/edit-shape-layer/types.d.ts +93 -0
  98. package/dist/deckgl/shapes/edit-shape-layer/types.js +14 -0
  99. package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.d.ts +82 -0
  100. package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.js +114 -0
  101. package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.js.map +1 -0
  102. package/dist/deckgl/shapes/index.d.ts +15 -6
  103. package/dist/deckgl/shapes/index.js +12 -5
  104. package/dist/deckgl/shapes/shared/constants.d.ts +27 -32
  105. package/dist/deckgl/shapes/shared/constants.js +189 -25
  106. package/dist/deckgl/shapes/shared/constants.js.map +1 -1
  107. package/dist/deckgl/shapes/shared/events.d.ts +1 -20
  108. package/dist/deckgl/shapes/shared/events.js +1 -31
  109. package/dist/deckgl/shapes/shared/events.js.map +1 -1
  110. package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js +84 -0
  111. package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js.map +1 -0
  112. package/dist/deckgl/shapes/shared/types.d.ts +187 -28
  113. package/dist/deckgl/shapes/shared/types.js +55 -1
  114. package/dist/deckgl/shapes/shared/types.js.map +1 -1
  115. package/dist/deckgl/shapes/shared/utils/geometry-measurements.js +128 -0
  116. package/dist/deckgl/shapes/shared/utils/geometry-measurements.js.map +1 -0
  117. package/dist/deckgl/shapes/shared/utils/layer-config.js +50 -0
  118. package/dist/deckgl/shapes/shared/utils/layer-config.js.map +1 -0
  119. package/dist/deckgl/shapes/shared/utils/mode-utils.js +113 -0
  120. package/dist/deckgl/shapes/shared/utils/mode-utils.js.map +1 -0
  121. package/dist/deckgl/shapes/shared/utils/pick-filtering.js +57 -0
  122. package/dist/deckgl/shapes/shared/utils/pick-filtering.js.map +1 -0
  123. package/dist/deckgl/shapes/shared/utils/style-utils.d.ts +64 -0
  124. package/dist/deckgl/shapes/shared/utils/style-utils.js +101 -0
  125. package/dist/deckgl/shapes/shared/utils/style-utils.js.map +1 -0
  126. package/dist/deckgl/text-layer/default-settings.js +4 -24
  127. package/dist/deckgl/text-layer/default-settings.js.map +1 -1
  128. package/dist/deckgl/text-settings.d.ts +77 -0
  129. package/dist/deckgl/text-settings.js +83 -0
  130. package/dist/deckgl/text-settings.js.map +1 -0
  131. package/dist/map-cursor/index.d.ts +2 -2
  132. package/dist/map-cursor/index.js +2 -2
  133. package/dist/map-cursor/store.d.ts +32 -61
  134. package/dist/map-cursor/store.js +165 -294
  135. package/dist/map-cursor/store.js.map +1 -1
  136. package/dist/map-cursor/use-map-cursor.d.ts +5 -2
  137. package/dist/map-cursor/use-map-cursor.js +33 -15
  138. package/dist/map-cursor/use-map-cursor.js.map +1 -1
  139. package/dist/map-mode/index.d.ts +2 -2
  140. package/dist/map-mode/index.js +2 -2
  141. package/dist/map-mode/store.d.ts +36 -37
  142. package/dist/map-mode/store.js +131 -237
  143. package/dist/map-mode/store.js.map +1 -1
  144. package/dist/map-mode/use-map-mode.js +6 -5
  145. package/dist/map-mode/use-map-mode.js.map +1 -1
  146. package/dist/maplibre/index.d.ts +2 -2
  147. package/dist/maplibre/index.js +2 -2
  148. package/dist/shared/constants.d.ts +19 -0
  149. package/dist/shared/constants.js +33 -0
  150. package/dist/shared/constants.js.map +1 -0
  151. package/dist/shared/create-map-store.d.ts +202 -0
  152. package/dist/shared/create-map-store.js +223 -0
  153. package/dist/shared/create-map-store.js.map +1 -0
  154. package/dist/shared/units.d.ts +39 -0
  155. package/dist/shared/units.js +49 -0
  156. package/dist/shared/units.js.map +1 -0
  157. package/dist/viewport/index.d.ts +3 -3
  158. package/dist/viewport/index.js +3 -3
  159. package/dist/viewport/store.d.ts +69 -0
  160. package/dist/viewport/store.js +125 -0
  161. package/dist/viewport/store.js.map +1 -0
  162. package/dist/viewport/types.d.ts +2 -2
  163. package/dist/viewport/utils.js +2 -2
  164. package/dist/viewport/utils.js.map +1 -1
  165. package/dist/viewport/viewport-size.d.ts +2 -2
  166. package/dist/viewport/viewport-size.js +2 -2
  167. package/dist/viewport/viewport-size.js.map +1 -1
  168. package/package.json +36 -18
  169. package/dist/camera/use-camera-state.d.ts +0 -153
  170. package/dist/camera/use-camera-state.js +0 -418
  171. package/dist/camera/use-camera-state.js.map +0 -1
  172. package/dist/deckgl/shapes/display-shape-layer/constants.d.ts +0 -44
  173. package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.d.ts +0 -66
  174. package/dist/deckgl/shapes/display-shape-layer/store.d.ts +0 -87
  175. package/dist/deckgl/shapes/display-shape-layer/use-shape-selection.js.map +0 -1
  176. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.d.ts +0 -61
  177. package/dist/maplibre/constants.d.ts +0 -13
  178. package/dist/maplibre/constants.js.map +0 -1
  179. package/dist/viewport/constants.d.ts +0 -11
  180. package/dist/viewport/constants.js.map +0 -1
  181. package/dist/viewport/use-viewport-state.d.ts +0 -100
  182. package/dist/viewport/use-viewport-state.js +0 -222
  183. package/dist/viewport/use-viewport-state.js.map +0 -1
@@ -0,0 +1,19 @@
1
+ //#region src/shared/constants.d.ts
2
+ /**
3
+ * Default view state for map initialization.
4
+ * Used by both BaseMap (deck.gl) and MapLibre components.
5
+ *
6
+ * Centered on Washington D.C. at zoom level 4 (continental US view).
7
+ */
8
+ declare const DEFAULT_VIEW_STATE: {
9
+ longitude: number;
10
+ latitude: number;
11
+ zoom: number;
12
+ minZoom: number;
13
+ maxZoom: number;
14
+ pitch: number;
15
+ bearing: number;
16
+ };
17
+ //#endregion
18
+ export { DEFAULT_VIEW_STATE };
19
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at https://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+
14
+ //#region src/shared/constants.ts
15
+ /**
16
+ * Default view state for map initialization.
17
+ * Used by both BaseMap (deck.gl) and MapLibre components.
18
+ *
19
+ * Centered on Washington D.C. at zoom level 4 (continental US view).
20
+ */
21
+ const DEFAULT_VIEW_STATE = {
22
+ longitude: -77.0369,
23
+ latitude: 38.9072,
24
+ zoom: 4,
25
+ minZoom: 1,
26
+ maxZoom: 22,
27
+ pitch: 0,
28
+ bearing: 0
29
+ };
30
+
31
+ //#endregion
32
+ export { DEFAULT_VIEW_STATE };
33
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../src/shared/constants.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/**\n * Default view state for map initialization.\n * Used by both BaseMap (deck.gl) and MapLibre components.\n *\n * Centered on Washington D.C. at zoom level 4 (continental US view).\n */\nexport const DEFAULT_VIEW_STATE = {\n longitude: -77.0369,\n latitude: 38.9072,\n zoom: 4,\n minZoom: 1,\n maxZoom: 22,\n pitch: 0,\n bearing: 0,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAkBA,MAAa,qBAAqB;CAChC,WAAW;CACX,UAAU;CACV,MAAM;CACN,SAAS;CACT,SAAS;CACT,OAAO;CACP,SAAS;CACV"}
@@ -0,0 +1,202 @@
1
+ /*
2
+ * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at https://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { UniqueId } from "@accelint/core";
14
+
15
+ //#region src/shared/create-map-store.d.ts
16
+ /**
17
+ * Create a new Map with an entry added or updated (immutable).
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const newMap = mapSet(state.cursorOwners, 'draw-layer', 'crosshair');
22
+ * set({ cursorOwners: newMap });
23
+ * ```
24
+ */
25
+ declare function mapSet<K, V>(map: Map<K, V>, key: K, value: V): Map<K, V>;
26
+ /**
27
+ * Create a new Map with an entry removed (immutable).
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const newMap = mapDelete(state.cursorOwners, 'draw-layer');
32
+ * set({ cursorOwners: newMap });
33
+ * ```
34
+ */
35
+ declare function mapDelete<K, V>(map: Map<K, V>, key: K): Map<K, V>;
36
+ /**
37
+ * Create a new empty Map (immutable replacement for Map.clear()).
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * set({ pendingRequests: mapClear<string, PendingRequest>() });
42
+ * ```
43
+ */
44
+ declare function mapClear<K, V>(): Map<K, V>;
45
+ /**
46
+ * Helper methods passed to action creators and bus setup functions.
47
+ *
48
+ * This type is exported for consumers building custom store extensions or
49
+ * helper functions that need to interact with store state.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * import type { StoreHelpers } from '@accelint/map-toolkit/shared';
54
+ *
55
+ * function createCustomAction<T>(helpers: StoreHelpers<T>) {
56
+ * return () => {
57
+ * const current = helpers.get();
58
+ * helpers.set({ ...current, modified: true });
59
+ * };
60
+ * }
61
+ * ```
62
+ */
63
+ type StoreHelpers<TState> = {
64
+ /** Get current state */
65
+ get: () => TState;
66
+ /** Update state (partial merge) and notify subscribers */
67
+ set: (updates: Partial<TState>) => void;
68
+ /** Replace entire state and notify subscribers */
69
+ replace: (state: TState) => void;
70
+ /** Notify subscribers without changing state */
71
+ notify: () => void;
72
+ };
73
+ /**
74
+ * Configuration for creating a map store
75
+ */
76
+ type MapStoreConfig<TState, TActions> = {
77
+ /** Default state for new instances and SSR */
78
+ defaultState: TState;
79
+ /**
80
+ * Action creators - receives mapId and helpers, returns action methods.
81
+ * Actions are cached per mapId for referential stability.
82
+ */
83
+ actions: (mapId: UniqueId, helpers: StoreHelpers<TState>) => TActions;
84
+ /**
85
+ * Optional bus listener setup. Called when first subscriber mounts.
86
+ * Return cleanup function to unsubscribe.
87
+ */
88
+ bus?: (mapId: UniqueId, helpers: StoreHelpers<TState>) => () => void;
89
+ /**
90
+ * Optional cleanup when instance is destroyed (last subscriber unmounts).
91
+ */
92
+ onCleanup?: (mapId: UniqueId, state: TState) => void;
93
+ };
94
+ /**
95
+ * The store object returned by createMapStore
96
+ */
97
+ type MapStore<TState, TActions> = {
98
+ /**
99
+ * React hook - the primary way to use the store.
100
+ * Returns state and actions with proper memoization.
101
+ */
102
+ use: (mapId: UniqueId) => {
103
+ state: TState;
104
+ } & TActions;
105
+ /**
106
+ * React hook with selector for derived state.
107
+ * Only re-renders when the underlying state changes.
108
+ *
109
+ * The selector result is memoized - it only recomputes when the **state reference**
110
+ * changes, not on every render or when the selector function changes. This means:
111
+ *
112
+ * - Selectors that create new objects/arrays are safe without additional memoization
113
+ * - Changing the selector function does NOT trigger recomputation (by design)
114
+ * - This prevents infinite re-render loops when using inline arrow functions
115
+ *
116
+ * **Important**: The selector function is intentionally NOT tracked as a dependency.
117
+ * If you need the selector to change dynamically, extract the changing value as a
118
+ * separate dependency and use it within a stable selector, or use the `use()` hook
119
+ * with your own `useMemo` for derived state.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * // Returns primitive - recomputes when state.count changes
124
+ * const count = store.useSelector(mapId, (s) => s.count);
125
+ *
126
+ * // Returns existing reference - recomputes when state.items ref changes
127
+ * const items = store.useSelector(mapId, (s) => s.items);
128
+ *
129
+ * // Safe: derived object is memoized internally, no infinite loops
130
+ * const derived = store.useSelector(mapId, (s) => ({ doubled: s.count * 2 }));
131
+ *
132
+ * // If you need dynamic selector behavior, use the base hook instead:
133
+ * const { state } = store.use(mapId);
134
+ * const filtered = useMemo(() => filterFn(state.items), [state.items, filterFn]);
135
+ * ```
136
+ */
137
+ useSelector: <TSelected>(mapId: UniqueId, selector: (state: TState) => TSelected) => TSelected;
138
+ /**
139
+ * Get actions without subscribing to state changes.
140
+ * Useful for event handlers or effects.
141
+ */
142
+ actions: (mapId: UniqueId) => TActions;
143
+ /**
144
+ * Get current state (non-reactive, for imperative code).
145
+ */
146
+ get: (mapId: UniqueId) => TState;
147
+ /**
148
+ * Update state directly (usually prefer actions).
149
+ */
150
+ set: (mapId: UniqueId, updates: Partial<TState>) => void;
151
+ /**
152
+ * Check if instance exists (has been initialized).
153
+ */
154
+ exists: (mapId: UniqueId) => boolean;
155
+ /**
156
+ * Clear instance state (for tests or manual cleanup).
157
+ */
158
+ clear: (mapId: UniqueId) => void;
159
+ /**
160
+ * Low-level access for custom hooks or useSyncExternalStore.
161
+ */
162
+ subscribe: (mapId: UniqueId) => (callback: () => void) => () => void;
163
+ snapshot: (mapId: UniqueId) => () => TState;
164
+ serverSnapshot: () => TState;
165
+ };
166
+ /**
167
+ * Creates a store for managing state across multiple map instances.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * const cursorStore = createMapStore({
172
+ * defaultState: { cursor: 'default', owner: null },
173
+ *
174
+ * actions: (mapId, { get, set }) => ({
175
+ * setCursor: (cursor: string, owner: string) => {
176
+ * set({ cursor, owner });
177
+ * },
178
+ * clearCursor: () => {
179
+ * set({ cursor: 'default', owner: null });
180
+ * },
181
+ * }),
182
+ *
183
+ * bus: (mapId, { set }) => {
184
+ * return cursorBus.on(CursorEvents.change, (e) => {
185
+ * if (e.payload.id === mapId) {
186
+ * set({ cursor: e.payload.cursor });
187
+ * }
188
+ * });
189
+ * },
190
+ * });
191
+ *
192
+ * // In component:
193
+ * function CursorDisplay({ mapId }) {
194
+ * const { state, setCursor } = cursorStore.use(mapId);
195
+ * return <div style={{ cursor: state.cursor }} />;
196
+ * }
197
+ * ```
198
+ */
199
+ declare function createMapStore<TState, TActions>(config: MapStoreConfig<TState, TActions>): MapStore<TState, TActions>;
200
+ //#endregion
201
+ export { MapStore, MapStoreConfig, StoreHelpers, createMapStore, mapClear, mapDelete, mapSet };
202
+ //# sourceMappingURL=create-map-store.d.ts.map
@@ -0,0 +1,223 @@
1
+ /*
2
+ * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at https://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+
14
+ import { useRef, useSyncExternalStore } from "react";
15
+
16
+ //#region src/shared/create-map-store.ts
17
+ /**
18
+ * Create a new Map with an entry added or updated (immutable).
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const newMap = mapSet(state.cursorOwners, 'draw-layer', 'crosshair');
23
+ * set({ cursorOwners: newMap });
24
+ * ```
25
+ */
26
+ function mapSet(map, key, value) {
27
+ const newMap = new Map(map);
28
+ newMap.set(key, value);
29
+ return newMap;
30
+ }
31
+ /**
32
+ * Create a new Map with an entry removed (immutable).
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const newMap = mapDelete(state.cursorOwners, 'draw-layer');
37
+ * set({ cursorOwners: newMap });
38
+ * ```
39
+ */
40
+ function mapDelete(map, key) {
41
+ const newMap = new Map(map);
42
+ newMap.delete(key);
43
+ return newMap;
44
+ }
45
+ /**
46
+ * Create a new empty Map (immutable replacement for Map.clear()).
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * set({ pendingRequests: mapClear<string, PendingRequest>() });
51
+ * ```
52
+ */
53
+ function mapClear() {
54
+ return /* @__PURE__ */ new Map();
55
+ }
56
+ /**
57
+ * Creates a store for managing state across multiple map instances.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const cursorStore = createMapStore({
62
+ * defaultState: { cursor: 'default', owner: null },
63
+ *
64
+ * actions: (mapId, { get, set }) => ({
65
+ * setCursor: (cursor: string, owner: string) => {
66
+ * set({ cursor, owner });
67
+ * },
68
+ * clearCursor: () => {
69
+ * set({ cursor: 'default', owner: null });
70
+ * },
71
+ * }),
72
+ *
73
+ * bus: (mapId, { set }) => {
74
+ * return cursorBus.on(CursorEvents.change, (e) => {
75
+ * if (e.payload.id === mapId) {
76
+ * set({ cursor: e.payload.cursor });
77
+ * }
78
+ * });
79
+ * },
80
+ * });
81
+ *
82
+ * // In component:
83
+ * function CursorDisplay({ mapId }) {
84
+ * const { state, setCursor } = cursorStore.use(mapId);
85
+ * return <div style={{ cursor: state.cursor }} />;
86
+ * }
87
+ * ```
88
+ */
89
+ function createMapStore(config) {
90
+ const { defaultState, actions: createActions, bus, onCleanup } = config;
91
+ const instances = /* @__PURE__ */ new Map();
92
+ const subscriptionCache = /* @__PURE__ */ new Map();
93
+ const snapshotCache = /* @__PURE__ */ new Map();
94
+ function getInstance(mapId) {
95
+ let instance = instances.get(mapId);
96
+ if (!instance) {
97
+ instance = {
98
+ state: { ...defaultState },
99
+ subscribers: /* @__PURE__ */ new Set()
100
+ };
101
+ instances.set(mapId, instance);
102
+ }
103
+ return instance;
104
+ }
105
+ function notify(mapId) {
106
+ const instance = instances.get(mapId);
107
+ if (instance) for (const callback of instance.subscribers) callback();
108
+ }
109
+ function getHelpers(mapId) {
110
+ return {
111
+ get: () => getInstance(mapId).state,
112
+ set: (updates) => {
113
+ const instance = getInstance(mapId);
114
+ instance.state = {
115
+ ...instance.state,
116
+ ...updates
117
+ };
118
+ notify(mapId);
119
+ },
120
+ replace: (state) => {
121
+ const instance = getInstance(mapId);
122
+ instance.state = state;
123
+ notify(mapId);
124
+ },
125
+ notify: () => notify(mapId)
126
+ };
127
+ }
128
+ function getActions(mapId) {
129
+ const instance = getInstance(mapId);
130
+ if (!instance.actions) instance.actions = createActions(mapId, getHelpers(mapId));
131
+ return instance.actions;
132
+ }
133
+ /**
134
+ * Clean up instance when last subscriber unmounts
135
+ */
136
+ function cleanupInstance(mapId, instance) {
137
+ if (onCleanup) onCleanup(mapId, instance.state);
138
+ if (instance.busCleanup) instance.busCleanup();
139
+ instances.delete(mapId);
140
+ subscriptionCache.delete(mapId);
141
+ snapshotCache.delete(mapId);
142
+ }
143
+ function subscribe(mapId) {
144
+ let cached = subscriptionCache.get(mapId);
145
+ if (!cached) {
146
+ cached = (callback) => {
147
+ const instance = getInstance(mapId);
148
+ if (instance.subscribers.size === 0 && bus) instance.busCleanup = bus(mapId, getHelpers(mapId));
149
+ instance.subscribers.add(callback);
150
+ return () => {
151
+ instance.subscribers.delete(callback);
152
+ if (instance.subscribers.size === 0) cleanupInstance(mapId, instance);
153
+ };
154
+ };
155
+ subscriptionCache.set(mapId, cached);
156
+ }
157
+ return cached;
158
+ }
159
+ function snapshot(mapId) {
160
+ let cached = snapshotCache.get(mapId);
161
+ if (!cached) {
162
+ cached = () => {
163
+ return getInstance(mapId).state;
164
+ };
165
+ snapshotCache.set(mapId, cached);
166
+ }
167
+ return cached;
168
+ }
169
+ function serverSnapshot() {
170
+ return defaultState;
171
+ }
172
+ /**
173
+ * Main hook - returns state and actions
174
+ */
175
+ function use(mapId) {
176
+ return {
177
+ state: useSyncExternalStore(subscribe(mapId), snapshot(mapId), serverSnapshot),
178
+ ...getActions(mapId)
179
+ };
180
+ }
181
+ /**
182
+ * Selector hook - only re-renders when selected value changes.
183
+ *
184
+ * Note: The selector function is intentionally NOT tracked as a dependency.
185
+ * This prevents infinite re-render loops when using inline arrow functions.
186
+ * If you need dynamic selector behavior, use the `use()` hook with `useMemo`.
187
+ */
188
+ function useSelector(mapId, selector) {
189
+ const cache = useRef(null);
190
+ const state = useSyncExternalStore(subscribe(mapId), snapshot(mapId), serverSnapshot);
191
+ if (cache.current === null || cache.current.state !== state) cache.current = {
192
+ state,
193
+ selected: selector(state)
194
+ };
195
+ return cache.current.selected;
196
+ }
197
+ return {
198
+ use,
199
+ useSelector,
200
+ actions: getActions,
201
+ get: (mapId) => getInstance(mapId).state,
202
+ set: (mapId, updates) => {
203
+ const instance = getInstance(mapId);
204
+ instance.state = {
205
+ ...instance.state,
206
+ ...updates
207
+ };
208
+ notify(mapId);
209
+ },
210
+ exists: (mapId) => instances.has(mapId),
211
+ clear: (mapId) => {
212
+ const instance = instances.get(mapId);
213
+ if (instance) cleanupInstance(mapId, instance);
214
+ },
215
+ subscribe,
216
+ snapshot,
217
+ serverSnapshot
218
+ };
219
+ }
220
+
221
+ //#endregion
222
+ export { createMapStore, mapClear, mapDelete, mapSet };
223
+ //# sourceMappingURL=create-map-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-map-store.js","names":[],"sources":["../../src/shared/create-map-store.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { useRef, useSyncExternalStore } from 'react';\nimport type { UniqueId } from '@accelint/core';\n\n// =============================================================================\n// Immutable Map Helpers\n// =============================================================================\n\n/**\n * Create a new Map with an entry added or updated (immutable).\n *\n * @example\n * ```ts\n * const newMap = mapSet(state.cursorOwners, 'draw-layer', 'crosshair');\n * set({ cursorOwners: newMap });\n * ```\n */\nexport function mapSet<K, V>(map: Map<K, V>, key: K, value: V): Map<K, V> {\n const newMap = new Map(map);\n newMap.set(key, value);\n return newMap;\n}\n\n/**\n * Create a new Map with an entry removed (immutable).\n *\n * @example\n * ```ts\n * const newMap = mapDelete(state.cursorOwners, 'draw-layer');\n * set({ cursorOwners: newMap });\n * ```\n */\nexport function mapDelete<K, V>(map: Map<K, V>, key: K): Map<K, V> {\n const newMap = new Map(map);\n newMap.delete(key);\n return newMap;\n}\n\n/**\n * Create a new empty Map (immutable replacement for Map.clear()).\n *\n * @example\n * ```ts\n * set({ pendingRequests: mapClear<string, PendingRequest>() });\n * ```\n */\nexport function mapClear<K, V>(): Map<K, V> {\n return new Map<K, V>();\n}\n\n/**\n * Helper methods passed to action creators and bus setup functions.\n *\n * This type is exported for consumers building custom store extensions or\n * helper functions that need to interact with store state.\n *\n * @example\n * ```ts\n * import type { StoreHelpers } from '@accelint/map-toolkit/shared';\n *\n * function createCustomAction<T>(helpers: StoreHelpers<T>) {\n * return () => {\n * const current = helpers.get();\n * helpers.set({ ...current, modified: true });\n * };\n * }\n * ```\n */\nexport type StoreHelpers<TState> = {\n /** Get current state */\n get: () => TState;\n /** Update state (partial merge) and notify subscribers */\n set: (updates: Partial<TState>) => void;\n /** Replace entire state and notify subscribers */\n replace: (state: TState) => void;\n /** Notify subscribers without changing state */\n notify: () => void;\n};\n\n/**\n * Configuration for creating a map store\n */\nexport type MapStoreConfig<TState, TActions> = {\n /** Default state for new instances and SSR */\n defaultState: TState;\n\n /**\n * Action creators - receives mapId and helpers, returns action methods.\n * Actions are cached per mapId for referential stability.\n */\n actions: (mapId: UniqueId, helpers: StoreHelpers<TState>) => TActions;\n\n /**\n * Optional bus listener setup. Called when first subscriber mounts.\n * Return cleanup function to unsubscribe.\n */\n bus?: (mapId: UniqueId, helpers: StoreHelpers<TState>) => () => void;\n\n /**\n * Optional cleanup when instance is destroyed (last subscriber unmounts).\n */\n onCleanup?: (mapId: UniqueId, state: TState) => void;\n};\n\n/**\n * Instance data for a single map\n */\ntype Instance<TState, TActions> = {\n state: TState;\n actions?: TActions;\n subscribers: Set<() => void>;\n busCleanup?: () => void;\n};\n\n/**\n * The store object returned by createMapStore\n */\nexport type MapStore<TState, TActions> = {\n /**\n * React hook - the primary way to use the store.\n * Returns state and actions with proper memoization.\n */\n use: (mapId: UniqueId) => { state: TState } & TActions;\n\n /**\n * React hook with selector for derived state.\n * Only re-renders when the underlying state changes.\n *\n * The selector result is memoized - it only recomputes when the **state reference**\n * changes, not on every render or when the selector function changes. This means:\n *\n * - Selectors that create new objects/arrays are safe without additional memoization\n * - Changing the selector function does NOT trigger recomputation (by design)\n * - This prevents infinite re-render loops when using inline arrow functions\n *\n * **Important**: The selector function is intentionally NOT tracked as a dependency.\n * If you need the selector to change dynamically, extract the changing value as a\n * separate dependency and use it within a stable selector, or use the `use()` hook\n * with your own `useMemo` for derived state.\n *\n * @example\n * ```ts\n * // Returns primitive - recomputes when state.count changes\n * const count = store.useSelector(mapId, (s) => s.count);\n *\n * // Returns existing reference - recomputes when state.items ref changes\n * const items = store.useSelector(mapId, (s) => s.items);\n *\n * // Safe: derived object is memoized internally, no infinite loops\n * const derived = store.useSelector(mapId, (s) => ({ doubled: s.count * 2 }));\n *\n * // If you need dynamic selector behavior, use the base hook instead:\n * const { state } = store.use(mapId);\n * const filtered = useMemo(() => filterFn(state.items), [state.items, filterFn]);\n * ```\n */\n useSelector: <TSelected>(\n mapId: UniqueId,\n selector: (state: TState) => TSelected,\n ) => TSelected;\n\n /**\n * Get actions without subscribing to state changes.\n * Useful for event handlers or effects.\n */\n actions: (mapId: UniqueId) => TActions;\n\n /**\n * Get current state (non-reactive, for imperative code).\n */\n get: (mapId: UniqueId) => TState;\n\n /**\n * Update state directly (usually prefer actions).\n */\n set: (mapId: UniqueId, updates: Partial<TState>) => void;\n\n /**\n * Check if instance exists (has been initialized).\n */\n exists: (mapId: UniqueId) => boolean;\n\n /**\n * Clear instance state (for tests or manual cleanup).\n */\n clear: (mapId: UniqueId) => void;\n\n /**\n * Low-level access for custom hooks or useSyncExternalStore.\n */\n subscribe: (mapId: UniqueId) => (callback: () => void) => () => void;\n snapshot: (mapId: UniqueId) => () => TState;\n serverSnapshot: () => TState;\n};\n\n/**\n * Creates a store for managing state across multiple map instances.\n *\n * @example\n * ```ts\n * const cursorStore = createMapStore({\n * defaultState: { cursor: 'default', owner: null },\n *\n * actions: (mapId, { get, set }) => ({\n * setCursor: (cursor: string, owner: string) => {\n * set({ cursor, owner });\n * },\n * clearCursor: () => {\n * set({ cursor: 'default', owner: null });\n * },\n * }),\n *\n * bus: (mapId, { set }) => {\n * return cursorBus.on(CursorEvents.change, (e) => {\n * if (e.payload.id === mapId) {\n * set({ cursor: e.payload.cursor });\n * }\n * });\n * },\n * });\n *\n * // In component:\n * function CursorDisplay({ mapId }) {\n * const { state, setCursor } = cursorStore.use(mapId);\n * return <div style={{ cursor: state.cursor }} />;\n * }\n * ```\n */\nexport function createMapStore<TState, TActions>(\n config: MapStoreConfig<TState, TActions>,\n): MapStore<TState, TActions> {\n const { defaultState, actions: createActions, bus, onCleanup } = config;\n\n const instances = new Map<UniqueId, Instance<TState, TActions>>();\n\n // Cached functions for referential stability\n const subscriptionCache = new Map<\n UniqueId,\n (callback: () => void) => () => void\n >();\n const snapshotCache = new Map<UniqueId, () => TState>();\n\n function getInstance(mapId: UniqueId): Instance<TState, TActions> {\n let instance = instances.get(mapId);\n if (!instance) {\n instance = {\n state: { ...defaultState },\n subscribers: new Set(),\n };\n instances.set(mapId, instance);\n }\n return instance;\n }\n\n function notify(mapId: UniqueId): void {\n const instance = instances.get(mapId);\n if (instance) {\n for (const callback of instance.subscribers) {\n callback();\n }\n }\n }\n\n function getHelpers(mapId: UniqueId): StoreHelpers<TState> {\n return {\n get: () => getInstance(mapId).state,\n set: (updates) => {\n const instance = getInstance(mapId);\n instance.state = { ...instance.state, ...updates };\n notify(mapId);\n },\n replace: (state) => {\n const instance = getInstance(mapId);\n instance.state = state;\n notify(mapId);\n },\n notify: () => notify(mapId),\n };\n }\n\n function getActions(mapId: UniqueId): TActions {\n const instance = getInstance(mapId);\n if (!instance.actions) {\n instance.actions = createActions(mapId, getHelpers(mapId));\n }\n return instance.actions;\n }\n\n /**\n * Clean up instance when last subscriber unmounts\n */\n function cleanupInstance(\n mapId: UniqueId,\n instance: Instance<TState, TActions>,\n ): void {\n if (onCleanup) {\n onCleanup(mapId, instance.state);\n }\n if (instance.busCleanup) {\n instance.busCleanup();\n }\n instances.delete(mapId);\n subscriptionCache.delete(mapId);\n snapshotCache.delete(mapId);\n }\n\n function subscribe(mapId: UniqueId): (callback: () => void) => () => void {\n let cached = subscriptionCache.get(mapId);\n if (!cached) {\n cached = (callback: () => void) => {\n const instance = getInstance(mapId);\n\n // Setup bus on first subscriber\n if (instance.subscribers.size === 0 && bus) {\n instance.busCleanup = bus(mapId, getHelpers(mapId));\n }\n\n instance.subscribers.add(callback);\n\n return () => {\n instance.subscribers.delete(callback);\n\n // Cleanup when last subscriber unmounts\n if (instance.subscribers.size === 0) {\n cleanupInstance(mapId, instance);\n }\n };\n };\n subscriptionCache.set(mapId, cached);\n }\n return cached;\n }\n\n function snapshot(mapId: UniqueId): () => TState {\n let cached = snapshotCache.get(mapId);\n if (!cached) {\n cached = () => {\n // State is already a new object reference when updated via set()\n // which creates { ...instance.state, ...updates }\n return getInstance(mapId).state;\n };\n snapshotCache.set(mapId, cached);\n }\n return cached;\n }\n\n function serverSnapshot(): TState {\n return defaultState;\n }\n\n /**\n * Main hook - returns state and actions\n */\n function use(mapId: UniqueId): { state: TState } & TActions {\n const state = useSyncExternalStore(\n subscribe(mapId),\n snapshot(mapId),\n serverSnapshot,\n );\n\n const actions = getActions(mapId);\n\n // Return merged object with state wrapper for clarity\n return { state, ...actions };\n }\n\n /**\n * Selector hook - only re-renders when selected value changes.\n *\n * Note: The selector function is intentionally NOT tracked as a dependency.\n * This prevents infinite re-render loops when using inline arrow functions.\n * If you need dynamic selector behavior, use the `use()` hook with `useMemo`.\n */\n function useSelector<TSelected>(\n mapId: UniqueId,\n selector: (state: TState) => TSelected,\n ): TSelected {\n // Cache the previous state and selected value to avoid unnecessary re-computation.\n // We intentionally do NOT track selector changes - only state changes trigger\n // recomputation. This prevents infinite loops with inline selectors.\n const cache = useRef<{ state: TState; selected: TSelected } | null>(null);\n\n const state = useSyncExternalStore(\n subscribe(mapId),\n snapshot(mapId),\n serverSnapshot,\n );\n\n // Only recompute if state reference changed (selector changes are ignored)\n if (cache.current === null || cache.current.state !== state) {\n cache.current = {\n state,\n selected: selector(state),\n };\n }\n\n return cache.current.selected;\n }\n\n return {\n use,\n useSelector,\n actions: getActions,\n get: (mapId) => getInstance(mapId).state,\n set: (mapId, updates) => {\n const instance = getInstance(mapId);\n instance.state = { ...instance.state, ...updates };\n notify(mapId);\n },\n exists: (mapId) => instances.has(mapId),\n clear: (mapId) => {\n const instance = instances.get(mapId);\n if (instance) {\n cleanupInstance(mapId, instance);\n }\n },\n subscribe,\n snapshot,\n serverSnapshot,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ //#region src/shared/units.d.ts
2
+ /**
3
+ * Map of Turf.js unit names to display abbreviations.
4
+ * These are the practical units users would select for map measurements.
5
+ */
6
+ declare const DISTANCE_UNIT_ABBREVIATIONS: {
7
+ readonly kilometers: "km";
8
+ readonly meters: "m";
9
+ readonly nauticalmiles: "nm";
10
+ readonly miles: "mi";
11
+ readonly feet: "ft";
12
+ };
13
+ /**
14
+ * Turf.js unit name (e.g., 'kilometers', 'nauticalmiles').
15
+ */
16
+ type DistanceUnit = keyof typeof DISTANCE_UNIT_ABBREVIATIONS;
17
+ /**
18
+ * Display abbreviation (e.g., 'km', 'nm').
19
+ */
20
+ type DistanceUnitAbbreviation = (typeof DISTANCE_UNIT_ABBREVIATIONS)[DistanceUnit];
21
+ /**
22
+ * Default distance units for geographic measurements.
23
+ */
24
+ declare const DEFAULT_DISTANCE_UNITS: DistanceUnit;
25
+ /**
26
+ * Get the full Turf.js unit name from an abbreviation.
27
+ * @param abbrev - The abbreviation (e.g., 'km', 'nm')
28
+ * @returns The full unit name (e.g., 'kilometers', 'nauticalmiles') or undefined
29
+ */
30
+ declare function getDistanceUnitFromAbbreviation(abbrev: string): DistanceUnit | undefined;
31
+ /**
32
+ * Get the abbreviation for a Turf.js unit name.
33
+ * @param unit - The full unit name (e.g., 'kilometers')
34
+ * @returns The abbreviation (e.g., 'km') or the input if not found
35
+ */
36
+ declare function getDistanceUnitAbbreviation(unit: string): string;
37
+ //#endregion
38
+ export { DEFAULT_DISTANCE_UNITS, DISTANCE_UNIT_ABBREVIATIONS, DistanceUnit, DistanceUnitAbbreviation, getDistanceUnitAbbreviation, getDistanceUnitFromAbbreviation };
39
+ //# sourceMappingURL=units.d.ts.map
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at https://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+
14
+ //#region src/shared/units.ts
15
+ /**
16
+ * Map of Turf.js unit names to display abbreviations.
17
+ * These are the practical units users would select for map measurements.
18
+ */
19
+ const DISTANCE_UNIT_ABBREVIATIONS = {
20
+ kilometers: "km",
21
+ meters: "m",
22
+ nauticalmiles: "nm",
23
+ miles: "mi",
24
+ feet: "ft"
25
+ };
26
+ /**
27
+ * Default distance units for geographic measurements.
28
+ */
29
+ const DEFAULT_DISTANCE_UNITS = "kilometers";
30
+ /**
31
+ * Get the full Turf.js unit name from an abbreviation.
32
+ * @param abbrev - The abbreviation (e.g., 'km', 'nm')
33
+ * @returns The full unit name (e.g., 'kilometers', 'nauticalmiles') or undefined
34
+ */
35
+ function getDistanceUnitFromAbbreviation(abbrev) {
36
+ return Object.entries(DISTANCE_UNIT_ABBREVIATIONS).find(([, a]) => a === abbrev)?.[0];
37
+ }
38
+ /**
39
+ * Get the abbreviation for a Turf.js unit name.
40
+ * @param unit - The full unit name (e.g., 'kilometers')
41
+ * @returns The abbreviation (e.g., 'km') or the input if not found
42
+ */
43
+ function getDistanceUnitAbbreviation(unit) {
44
+ return DISTANCE_UNIT_ABBREVIATIONS[unit] ?? unit;
45
+ }
46
+
47
+ //#endregion
48
+ export { DEFAULT_DISTANCE_UNITS, DISTANCE_UNIT_ABBREVIATIONS, getDistanceUnitAbbreviation, getDistanceUnitFromAbbreviation };
49
+ //# sourceMappingURL=units.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"units.js","names":["DEFAULT_DISTANCE_UNITS: DistanceUnit"],"sources":["../../src/shared/units.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n/**\n * Map of Turf.js unit names to display abbreviations.\n * These are the practical units users would select for map measurements.\n */\nexport const DISTANCE_UNIT_ABBREVIATIONS = {\n kilometers: 'km',\n meters: 'm',\n nauticalmiles: 'nm',\n miles: 'mi',\n feet: 'ft',\n} as const;\n\n/**\n * Turf.js unit name (e.g., 'kilometers', 'nauticalmiles').\n */\nexport type DistanceUnit = keyof typeof DISTANCE_UNIT_ABBREVIATIONS;\n\n/**\n * Display abbreviation (e.g., 'km', 'nm').\n */\nexport type DistanceUnitAbbreviation =\n (typeof DISTANCE_UNIT_ABBREVIATIONS)[DistanceUnit];\n\n/**\n * Default distance units for geographic measurements.\n */\nexport const DEFAULT_DISTANCE_UNITS: DistanceUnit = 'kilometers';\n\n/**\n * Get the full Turf.js unit name from an abbreviation.\n * @param abbrev - The abbreviation (e.g., 'km', 'nm')\n * @returns The full unit name (e.g., 'kilometers', 'nauticalmiles') or undefined\n */\nexport function getDistanceUnitFromAbbreviation(\n abbrev: string,\n): DistanceUnit | undefined {\n const entry = Object.entries(DISTANCE_UNIT_ABBREVIATIONS).find(\n ([, a]) => a === abbrev,\n );\n return entry?.[0] as DistanceUnit | undefined;\n}\n\n/**\n * Get the abbreviation for a Turf.js unit name.\n * @param unit - The full unit name (e.g., 'kilometers')\n * @returns The abbreviation (e.g., 'km') or the input if not found\n */\nexport function getDistanceUnitAbbreviation(unit: string): string {\n return DISTANCE_UNIT_ABBREVIATIONS[unit as DistanceUnit] ?? unit;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAgBA,MAAa,8BAA8B;CACzC,YAAY;CACZ,QAAQ;CACR,eAAe;CACf,OAAO;CACP,MAAM;CACP;;;;AAgBD,MAAaA,yBAAuC;;;;;;AAOpD,SAAgB,gCACd,QAC0B;AAI1B,QAHc,OAAO,QAAQ,4BAA4B,CAAC,MACvD,GAAG,OAAO,MAAM,OAClB,GACc;;;;;;;AAQjB,SAAgB,4BAA4B,MAAsB;AAChE,QAAO,4BAA4B,SAAyB"}
@@ -10,9 +10,9 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import { UNIT_MAP } from "./constants.js";
14
- import { UseViewportStateProps, clearViewportState, useViewportState } from "./use-viewport-state.js";
13
+ import { DISTANCE_UNIT_ABBREVIATIONS, DistanceUnit, DistanceUnitAbbreviation, getDistanceUnitFromAbbreviation } from "../shared/units.js";
14
+ import { clearViewportState, useMapViewport, viewportStore } from "./store.js";
15
15
  import { GeoCoordinate, GetViewportSizeArgs, SupportedDistanceUnit } from "./types.js";
16
16
  import { getViewportSize } from "./utils.js";
17
17
  import { ViewportSize, ViewportSizeProps } from "./viewport-size.js";
18
- export { type GeoCoordinate, type GetViewportSizeArgs, type SupportedDistanceUnit, UNIT_MAP, type UseViewportStateProps, ViewportSize, type ViewportSizeProps, clearViewportState, getViewportSize, useViewportState };
18
+ export { DISTANCE_UNIT_ABBREVIATIONS, type DistanceUnit, type DistanceUnitAbbreviation, type GeoCoordinate, type GetViewportSizeArgs, type SupportedDistanceUnit, ViewportSize, type ViewportSizeProps, clearViewportState, getDistanceUnitFromAbbreviation, getViewportSize, useMapViewport, viewportStore };
@@ -11,9 +11,9 @@
11
11
  */
12
12
 
13
13
 
14
- import { UNIT_MAP } from "./constants.js";
15
- import { clearViewportState, useViewportState } from "./use-viewport-state.js";
14
+ import { DISTANCE_UNIT_ABBREVIATIONS, getDistanceUnitFromAbbreviation } from "../shared/units.js";
15
+ import { clearViewportState, useMapViewport, viewportStore } from "./store.js";
16
16
  import { getViewportSize } from "./utils.js";
17
17
  import { ViewportSize } from "./viewport-size.js";
18
18
 
19
- export { UNIT_MAP, ViewportSize, clearViewportState, getViewportSize, useViewportState };
19
+ export { DISTANCE_UNIT_ABBREVIATIONS, ViewportSize, clearViewportState, getDistanceUnitFromAbbreviation, getViewportSize, useMapViewport, viewportStore };