@accelint/map-toolkit 1.1.0 → 1.3.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 (128) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/catalog-info.yaml +3 -3
  3. package/dist/camera/events.d.ts +45 -0
  4. package/dist/camera/events.js +45 -0
  5. package/dist/camera/events.js.map +1 -1
  6. package/dist/camera/store.d.ts +47 -0
  7. package/dist/camera/store.js +81 -0
  8. package/dist/camera/store.js.map +1 -1
  9. package/dist/camera/types.d.ts +81 -0
  10. package/dist/cursor-coordinates/constants.d.ts +8 -0
  11. package/dist/cursor-coordinates/constants.js +22 -0
  12. package/dist/cursor-coordinates/constants.js.map +1 -0
  13. package/dist/cursor-coordinates/store.d.ts +1 -0
  14. package/dist/cursor-coordinates/store.js +1 -0
  15. package/dist/cursor-coordinates/store.js.map +1 -1
  16. package/dist/cursor-coordinates/use-cursor-coordinates.d.ts +5 -0
  17. package/dist/cursor-coordinates/use-cursor-coordinates.js +21 -6
  18. package/dist/cursor-coordinates/use-cursor-coordinates.js.map +1 -1
  19. package/dist/deckgl/base-map/constants.d.ts +12 -0
  20. package/dist/deckgl/base-map/constants.js +12 -0
  21. package/dist/deckgl/base-map/constants.js.map +1 -1
  22. package/dist/deckgl/base-map/controls.d.ts +10 -0
  23. package/dist/deckgl/base-map/controls.js +5 -0
  24. package/dist/deckgl/base-map/controls.js.map +1 -1
  25. package/dist/deckgl/base-map/events.d.ts +30 -0
  26. package/dist/deckgl/base-map/events.js +30 -0
  27. package/dist/deckgl/base-map/events.js.map +1 -1
  28. package/dist/deckgl/base-map/index.d.ts +2 -2
  29. package/dist/deckgl/base-map/index.js +30 -0
  30. package/dist/deckgl/base-map/index.js.map +1 -1
  31. package/dist/deckgl/saved-viewports/index.d.ts +75 -0
  32. package/dist/deckgl/saved-viewports/index.js +58 -0
  33. package/dist/deckgl/saved-viewports/index.js.map +1 -1
  34. package/dist/deckgl/saved-viewports/storage.d.ts +51 -0
  35. package/dist/deckgl/saved-viewports/storage.js +64 -0
  36. package/dist/deckgl/saved-viewports/storage.js.map +1 -1
  37. package/dist/deckgl/shapes/display-shape-layer/constants.js +18 -6
  38. package/dist/deckgl/shapes/display-shape-layer/constants.js.map +1 -1
  39. package/dist/deckgl/shapes/display-shape-layer/fiber.d.ts +7 -0
  40. package/dist/deckgl/shapes/display-shape-layer/fiber.js.map +1 -1
  41. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js +61 -4
  42. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js.map +1 -1
  43. package/dist/deckgl/shapes/display-shape-layer/utils/labels.d.ts +22 -8
  44. package/dist/deckgl/shapes/display-shape-layer/utils/labels.js +75 -4
  45. package/dist/deckgl/shapes/display-shape-layer/utils/labels.js.map +1 -1
  46. package/dist/deckgl/shapes/draw-shape-layer/constants.js +30 -0
  47. package/dist/deckgl/shapes/draw-shape-layer/constants.js.map +1 -1
  48. package/dist/deckgl/shapes/draw-shape-layer/fiber.js +36 -0
  49. package/dist/deckgl/shapes/draw-shape-layer/fiber.js.map +1 -1
  50. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js +32 -1
  51. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js.map +1 -1
  52. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js +37 -8
  53. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js.map +1 -1
  54. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js +43 -1
  55. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js.map +1 -1
  56. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js +44 -1
  57. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js.map +1 -1
  58. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js +46 -3
  59. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js.map +1 -1
  60. package/dist/deckgl/shapes/draw-shape-layer/modes/index.js +37 -1
  61. package/dist/deckgl/shapes/draw-shape-layer/modes/index.js.map +1 -1
  62. package/dist/deckgl/shapes/draw-shape-layer/store.js +50 -2
  63. package/dist/deckgl/shapes/draw-shape-layer/store.js.map +1 -1
  64. package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js +137 -16
  65. package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js.map +1 -1
  66. package/dist/deckgl/shapes/edit-shape-layer/events.js +1 -1
  67. package/dist/deckgl/shapes/edit-shape-layer/events.js.map +1 -1
  68. package/dist/deckgl/shapes/edit-shape-layer/index.d.ts +2 -2
  69. package/dist/deckgl/shapes/edit-shape-layer/index.js +14 -0
  70. package/dist/deckgl/shapes/edit-shape-layer/index.js.map +1 -1
  71. package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js +56 -8
  72. package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js.map +1 -1
  73. package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js +26 -4
  74. package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js.map +1 -1
  75. package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js +28 -3
  76. package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js.map +1 -1
  77. package/dist/deckgl/shapes/edit-shape-layer/modes/index.js +24 -0
  78. package/dist/deckgl/shapes/edit-shape-layer/modes/index.js.map +1 -1
  79. package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js +33 -4
  80. package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js.map +1 -1
  81. package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js +21 -2
  82. package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js.map +1 -1
  83. package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js +35 -11
  84. package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js.map +1 -1
  85. package/dist/deckgl/shapes/edit-shape-layer/store.js +1 -1
  86. package/dist/deckgl/shapes/edit-shape-layer/store.js.map +1 -1
  87. package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js +12 -0
  88. package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js.map +1 -1
  89. package/dist/deckgl/shapes/shared/types.d.ts +3 -3
  90. package/dist/deckgl/shapes/shared/types.js +2 -2
  91. package/dist/deckgl/shapes/shared/types.js.map +1 -1
  92. package/dist/deckgl/shapes/shared/utils/geometry-measurements.js +3 -3
  93. package/dist/deckgl/shapes/shared/utils/geometry-measurements.js.map +1 -1
  94. package/dist/deckgl/shapes/shared/utils/pick-filtering.js +1 -1
  95. package/dist/deckgl/shapes/shared/utils/pick-filtering.js.map +1 -1
  96. package/dist/deckgl/symbol-layer/fiber.d.ts +18 -0
  97. package/dist/deckgl/symbol-layer/fiber.js.map +1 -1
  98. package/dist/deckgl/symbol-layer/index.d.ts +79 -1
  99. package/dist/deckgl/symbol-layer/index.js +72 -1
  100. package/dist/deckgl/symbol-layer/index.js.map +1 -1
  101. package/dist/deckgl/text-layer/character-sets.d.ts +30 -0
  102. package/dist/deckgl/text-layer/character-sets.js +26 -0
  103. package/dist/deckgl/text-layer/character-sets.js.map +1 -1
  104. package/dist/deckgl/text-layer/default-settings.d.ts +29 -0
  105. package/dist/deckgl/text-layer/default-settings.js +28 -0
  106. package/dist/deckgl/text-layer/default-settings.js.map +1 -1
  107. package/dist/deckgl/text-layer/index.d.ts +65 -0
  108. package/dist/deckgl/text-layer/index.js +56 -0
  109. package/dist/deckgl/text-layer/index.js.map +1 -1
  110. package/dist/map-cursor/events.d.ts +19 -0
  111. package/dist/map-cursor/events.js +19 -0
  112. package/dist/map-cursor/events.js.map +1 -1
  113. package/dist/map-cursor/store.d.ts +34 -2
  114. package/dist/map-cursor/store.js +44 -3
  115. package/dist/map-cursor/store.js.map +1 -1
  116. package/dist/map-mode/store.d.ts +43 -4
  117. package/dist/map-mode/store.js +55 -5
  118. package/dist/map-mode/store.js.map +1 -1
  119. package/dist/shared/create-map-store.d.ts +14 -0
  120. package/dist/shared/create-map-store.js +26 -2
  121. package/dist/shared/create-map-store.js.map +1 -1
  122. package/dist/shared/units.d.ts +24 -0
  123. package/dist/shared/units.js +24 -0
  124. package/dist/shared/units.js.map +1 -1
  125. package/dist/viewport/store.d.ts +1 -0
  126. package/dist/viewport/store.js +4 -0
  127. package/dist/viewport/store.js.map +1 -1
  128. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"create-map-store.js","names":[],"sources":["../../src/shared/create-map-store.ts"],"sourcesContent":["/*\n * Copyright 2026 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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"}
1
+ {"version":3,"file":"create-map-store.js","names":[],"sources":["../../src/shared/create-map-store.ts"],"sourcesContent":["/*\n * Copyright 2026 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 * @param map - The Map to copy\n * @param key - The key to set\n * @param value - The value to set\n * @returns A new Map with the entry added/updated\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 * @param map - The Map to copy\n * @param key - The key to remove\n * @returns A new Map with the entry removed\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 * @returns A new empty Map\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 * @param config - Store configuration including default state, actions, and optional bus setup\n * @returns A MapStore instance with hooks and methods for accessing/updating state\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 * @param mapId - Unique identifier for the map instance\n * @param instance - The instance to clean up\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 * @param mapId - Unique identifier for the map instance\n * @returns Object containing state and all 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 * @param mapId - Unique identifier for the map instance\n * @param selector - Function to select derived state\n * @returns The selected value\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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"}
@@ -24,14 +24,38 @@ type DistanceUnitAbbreviation = (typeof DISTANCE_UNIT_ABBREVIATIONS)[DistanceUni
24
24
  declare const DEFAULT_DISTANCE_UNITS: DistanceUnit;
25
25
  /**
26
26
  * Get the full Turf.js unit name from an abbreviation.
27
+ *
27
28
  * @param abbrev - The abbreviation (e.g., 'km', 'nm')
28
29
  * @returns The full unit name (e.g., 'kilometers', 'nauticalmiles') or undefined
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * import { getDistanceUnitFromAbbreviation } from '@accelint/map-toolkit/shared';
34
+ *
35
+ * const unit = getDistanceUnitFromAbbreviation('km');
36
+ * console.log(unit); // 'kilometers'
37
+ *
38
+ * const unknown = getDistanceUnitFromAbbreviation('invalid');
39
+ * console.log(unknown); // undefined
40
+ * ```
29
41
  */
30
42
  declare function getDistanceUnitFromAbbreviation(abbrev: string): DistanceUnit | undefined;
31
43
  /**
32
44
  * Get the abbreviation for a Turf.js unit name.
45
+ *
33
46
  * @param unit - The full unit name (e.g., 'kilometers')
34
47
  * @returns The abbreviation (e.g., 'km') or the input if not found
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * import { getDistanceUnitAbbreviation } from '@accelint/map-toolkit/shared';
52
+ *
53
+ * const abbrev = getDistanceUnitAbbreviation('kilometers');
54
+ * console.log(abbrev); // 'km'
55
+ *
56
+ * const fallback = getDistanceUnitAbbreviation('unknown');
57
+ * console.log(fallback); // 'unknown'
58
+ * ```
35
59
  */
36
60
  declare function getDistanceUnitAbbreviation(unit: string): string;
37
61
  //#endregion
@@ -29,16 +29,40 @@ const DISTANCE_UNIT_ABBREVIATIONS = {
29
29
  const DEFAULT_DISTANCE_UNITS = "kilometers";
30
30
  /**
31
31
  * Get the full Turf.js unit name from an abbreviation.
32
+ *
32
33
  * @param abbrev - The abbreviation (e.g., 'km', 'nm')
33
34
  * @returns The full unit name (e.g., 'kilometers', 'nauticalmiles') or undefined
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * import { getDistanceUnitFromAbbreviation } from '@accelint/map-toolkit/shared';
39
+ *
40
+ * const unit = getDistanceUnitFromAbbreviation('km');
41
+ * console.log(unit); // 'kilometers'
42
+ *
43
+ * const unknown = getDistanceUnitFromAbbreviation('invalid');
44
+ * console.log(unknown); // undefined
45
+ * ```
34
46
  */
35
47
  function getDistanceUnitFromAbbreviation(abbrev) {
36
48
  return Object.entries(DISTANCE_UNIT_ABBREVIATIONS).find(([, a]) => a === abbrev)?.[0];
37
49
  }
38
50
  /**
39
51
  * Get the abbreviation for a Turf.js unit name.
52
+ *
40
53
  * @param unit - The full unit name (e.g., 'kilometers')
41
54
  * @returns The abbreviation (e.g., 'km') or the input if not found
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * import { getDistanceUnitAbbreviation } from '@accelint/map-toolkit/shared';
59
+ *
60
+ * const abbrev = getDistanceUnitAbbreviation('kilometers');
61
+ * console.log(abbrev); // 'km'
62
+ *
63
+ * const fallback = getDistanceUnitAbbreviation('unknown');
64
+ * console.log(fallback); // 'unknown'
65
+ * ```
42
66
  */
43
67
  function getDistanceUnitAbbreviation(unit) {
44
68
  return DISTANCE_UNIT_ABBREVIATIONS[unit] ?? unit;
@@ -1 +1 @@
1
- {"version":3,"file":"units.js","names":["DEFAULT_DISTANCE_UNITS: DistanceUnit"],"sources":["../../src/shared/units.ts"],"sourcesContent":["/*\n * Copyright 2026 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"}
1
+ {"version":3,"file":"units.js","names":["DEFAULT_DISTANCE_UNITS: DistanceUnit"],"sources":["../../src/shared/units.ts"],"sourcesContent":["/*\n * Copyright 2026 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 *\n * @param abbrev - The abbreviation (e.g., 'km', 'nm')\n * @returns The full unit name (e.g., 'kilometers', 'nauticalmiles') or undefined\n *\n * @example\n * ```typescript\n * import { getDistanceUnitFromAbbreviation } from '@accelint/map-toolkit/shared';\n *\n * const unit = getDistanceUnitFromAbbreviation('km');\n * console.log(unit); // 'kilometers'\n *\n * const unknown = getDistanceUnitFromAbbreviation('invalid');\n * console.log(unknown); // undefined\n * ```\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 *\n * @param unit - The full unit name (e.g., 'kilometers')\n * @returns The abbreviation (e.g., 'km') or the input if not found\n *\n * @example\n * ```typescript\n * import { getDistanceUnitAbbreviation } from '@accelint/map-toolkit/shared';\n *\n * const abbrev = getDistanceUnitAbbreviation('kilometers');\n * console.log(abbrev); // 'km'\n *\n * const fallback = getDistanceUnitAbbreviation('unknown');\n * console.log(fallback); // 'unknown'\n * ```\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;;;;;;;;;;;;;;;;;;AAmBpD,SAAgB,gCACd,QAC0B;AAI1B,QAHc,OAAO,QAAQ,4BAA4B,CAAC,MACvD,GAAG,OAAO,MAAM,OAClB,GACc;;;;;;;;;;;;;;;;;;;AAoBjB,SAAgB,4BAA4B,MAAsB;AAChE,QAAO,4BAA4B,SAAyB"}
@@ -62,6 +62,7 @@ declare function getViewport(mapId: UniqueId): ViewportState;
62
62
  * This is typically not needed as cleanup happens automatically when all subscribers unmount.
63
63
  *
64
64
  * @param mapId - The unique identifier for the map instance to clear
65
+ * @returns void
65
66
  */
66
67
  declare function clearViewportState(mapId: UniqueId): void;
67
68
  //#endregion
@@ -40,6 +40,9 @@ const bus = Broadcast.getInstance();
40
40
  /**
41
41
  * Create default state for a given mapId.
42
42
  * Returns uninitialized values that indicate no viewport data yet.
43
+ *
44
+ * @param mapId - Unique identifier for the map instance
45
+ * @returns Uninitialized viewport state with NaN values and undefined bounds
43
46
  */
44
47
  function createDefaultState(mapId) {
45
48
  return {
@@ -115,6 +118,7 @@ function getViewport(mapId) {
115
118
  * This is typically not needed as cleanup happens automatically when all subscribers unmount.
116
119
  *
117
120
  * @param mapId - The unique identifier for the map instance to clear
121
+ * @returns void
118
122
  */
119
123
  function clearViewportState(mapId) {
120
124
  viewportStore.clear(mapId);
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","names":[],"sources":["../../src/viewport/store.ts"],"sourcesContent":["/*\n * Copyright 2026 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 * Viewport Store\n *\n * Manages viewport state (bounds, lat/lon, zoom, dimensions) per map instance.\n * State is updated automatically from MapEvents.viewport bus events.\n *\n * @example\n * ```tsx\n * import { viewportStore } from '@accelint/map-toolkit/viewport';\n *\n * function MapInfo({ mapId }) {\n * const { state } = viewportStore.use(mapId);\n * return (\n * <div>\n * Lat: {state.latitude.toFixed(2)}, Lon: {state.longitude.toFixed(2)}\n * </div>\n * );\n * }\n * ```\n */\n\nimport { Broadcast } from '@accelint/bus';\nimport { MapEvents } from '../deckgl/base-map/events';\nimport { createMapStore } from '../shared/create-map-store';\nimport type { UniqueId } from '@accelint/core';\nimport type {\n MapEventType,\n MapViewportPayload,\n} from '../deckgl/base-map/types';\n\nconst bus = Broadcast.getInstance<MapEventType>();\n\n/**\n * State shape for viewport - mirrors MapViewportPayload but with\n * a placeholder id that gets replaced per-instance\n */\ntype ViewportState = MapViewportPayload;\n\n/**\n * No actions needed - viewport state is read-only from bus events\n */\ntype ViewportActions = Record<string, never>;\n\n/**\n * Create default state for a given mapId.\n * Returns uninitialized values that indicate no viewport data yet.\n */\nfunction createDefaultState(mapId: UniqueId): ViewportState {\n return {\n id: mapId,\n bounds: undefined,\n latitude: Number.NaN,\n longitude: Number.NaN,\n zoom: Number.NaN,\n width: 0,\n height: 0,\n };\n}\n\n/**\n * Viewport store instance.\n *\n * Note: The defaultState uses a placeholder id that gets replaced\n * when instances are created. The actual id comes from the bus event payload.\n */\nexport const viewportStore = createMapStore<ViewportState, ViewportActions>({\n // Placeholder default state - actual instances get proper id from bus events\n defaultState: {\n id: '' as UniqueId,\n bounds: undefined,\n latitude: Number.NaN,\n longitude: Number.NaN,\n zoom: Number.NaN,\n width: 0,\n height: 0,\n },\n\n // No actions - state is read-only from bus events\n actions: () => ({}) as ViewportActions,\n\n bus: (mapId, { replace }) => {\n const unsub = bus.on(MapEvents.viewport, ({ payload }) => {\n if (payload.id === mapId) {\n // Replace entire state with the new payload\n replace(payload);\n }\n });\n\n return unsub;\n },\n});\n\n// =============================================================================\n// Convenience exports\n// =============================================================================\n\n/**\n * Hook to subscribe to viewport state changes for a specific map.\n *\n * @param mapId - Unique identifier for the map instance\n * @returns Current viewport state including bounds, latitude, longitude, zoom, width, height\n *\n * @example\n * ```tsx\n * function MapInfo({ mapId }) {\n * const viewport = useMapViewport(mapId);\n * return (\n * <div>\n * Lat: {viewport.latitude?.toFixed(2)}, Lon: {viewport.longitude?.toFixed(2)}, Zoom: {viewport.zoom}\n * </div>\n * );\n * }\n * ```\n */\nexport function useMapViewport(mapId: UniqueId): ViewportState {\n return viewportStore.useSelector(mapId, (state) => {\n // Return proper default state with correct mapId if uninitialized\n if (state.id === '') {\n return createDefaultState(mapId);\n }\n return state;\n });\n}\n\n/**\n * Get current viewport state (non-reactive, for imperative code).\n *\n * @param mapId - Unique identifier for the map instance\n * @returns Current viewport state\n */\nexport function getViewport(mapId: UniqueId): ViewportState {\n const state = viewportStore.get(mapId);\n // Return proper default state with correct mapId if uninitialized\n if (state.id === '') {\n return createDefaultState(mapId);\n }\n return state;\n}\n\n/**\n * Manually clear viewport state for a specific map instance.\n * This is typically not needed as cleanup happens automatically when all subscribers unmount.\n *\n * @param mapId - The unique identifier for the map instance to clear\n */\nexport function clearViewportState(mapId: UniqueId): void {\n viewportStore.clear(mapId);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,MAAM,MAAM,UAAU,aAA2B;;;;;AAiBjD,SAAS,mBAAmB,OAAgC;AAC1D,QAAO;EACL,IAAI;EACJ,QAAQ;EACR,UAAU;EACV,WAAW;EACX,MAAM;EACN,OAAO;EACP,QAAQ;EACT;;;;;;;;AASH,MAAa,gBAAgB,eAA+C;CAE1E,cAAc;EACZ,IAAI;EACJ,QAAQ;EACR,UAAU;EACV,WAAW;EACX,MAAM;EACN,OAAO;EACP,QAAQ;EACT;CAGD,gBAAgB,EAAE;CAElB,MAAM,OAAO,EAAE,cAAc;AAQ3B,SAPc,IAAI,GAAG,UAAU,WAAW,EAAE,cAAc;AACxD,OAAI,QAAQ,OAAO,MAEjB,SAAQ,QAAQ;IAElB;;CAIL,CAAC;;;;;;;;;;;;;;;;;;;AAwBF,SAAgB,eAAe,OAAgC;AAC7D,QAAO,cAAc,YAAY,QAAQ,UAAU;AAEjD,MAAI,MAAM,OAAO,GACf,QAAO,mBAAmB,MAAM;AAElC,SAAO;GACP;;;;;;;;AASJ,SAAgB,YAAY,OAAgC;CAC1D,MAAM,QAAQ,cAAc,IAAI,MAAM;AAEtC,KAAI,MAAM,OAAO,GACf,QAAO,mBAAmB,MAAM;AAElC,QAAO;;;;;;;;AAST,SAAgB,mBAAmB,OAAuB;AACxD,eAAc,MAAM,MAAM"}
1
+ {"version":3,"file":"store.js","names":[],"sources":["../../src/viewport/store.ts"],"sourcesContent":["/*\n * Copyright 2026 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 * Viewport Store\n *\n * Manages viewport state (bounds, lat/lon, zoom, dimensions) per map instance.\n * State is updated automatically from MapEvents.viewport bus events.\n *\n * @example\n * ```tsx\n * import { viewportStore } from '@accelint/map-toolkit/viewport';\n *\n * function MapInfo({ mapId }) {\n * const { state } = viewportStore.use(mapId);\n * return (\n * <div>\n * Lat: {state.latitude.toFixed(2)}, Lon: {state.longitude.toFixed(2)}\n * </div>\n * );\n * }\n * ```\n */\n\nimport { Broadcast } from '@accelint/bus';\nimport { MapEvents } from '../deckgl/base-map/events';\nimport { createMapStore } from '../shared/create-map-store';\nimport type { UniqueId } from '@accelint/core';\nimport type {\n MapEventType,\n MapViewportPayload,\n} from '../deckgl/base-map/types';\n\nconst bus = Broadcast.getInstance<MapEventType>();\n\n/**\n * State shape for viewport - mirrors MapViewportPayload but with\n * a placeholder id that gets replaced per-instance\n */\ntype ViewportState = MapViewportPayload;\n\n/**\n * No actions needed - viewport state is read-only from bus events\n */\ntype ViewportActions = Record<string, never>;\n\n/**\n * Create default state for a given mapId.\n * Returns uninitialized values that indicate no viewport data yet.\n *\n * @param mapId - Unique identifier for the map instance\n * @returns Uninitialized viewport state with NaN values and undefined bounds\n */\nfunction createDefaultState(mapId: UniqueId): ViewportState {\n return {\n id: mapId,\n bounds: undefined,\n latitude: Number.NaN,\n longitude: Number.NaN,\n zoom: Number.NaN,\n width: 0,\n height: 0,\n };\n}\n\n/**\n * Viewport store instance.\n *\n * Note: The defaultState uses a placeholder id that gets replaced\n * when instances are created. The actual id comes from the bus event payload.\n */\nexport const viewportStore = createMapStore<ViewportState, ViewportActions>({\n // Placeholder default state - actual instances get proper id from bus events\n defaultState: {\n id: '' as UniqueId,\n bounds: undefined,\n latitude: Number.NaN,\n longitude: Number.NaN,\n zoom: Number.NaN,\n width: 0,\n height: 0,\n },\n\n // No actions - state is read-only from bus events\n actions: () => ({}) as ViewportActions,\n\n bus: (mapId, { replace }) => {\n const unsub = bus.on(MapEvents.viewport, ({ payload }) => {\n if (payload.id === mapId) {\n // Replace entire state with the new payload\n replace(payload);\n }\n });\n\n return unsub;\n },\n});\n\n// =============================================================================\n// Convenience exports\n// =============================================================================\n\n/**\n * Hook to subscribe to viewport state changes for a specific map.\n *\n * @param mapId - Unique identifier for the map instance\n * @returns Current viewport state including bounds, latitude, longitude, zoom, width, height\n *\n * @example\n * ```tsx\n * function MapInfo({ mapId }) {\n * const viewport = useMapViewport(mapId);\n * return (\n * <div>\n * Lat: {viewport.latitude?.toFixed(2)}, Lon: {viewport.longitude?.toFixed(2)}, Zoom: {viewport.zoom}\n * </div>\n * );\n * }\n * ```\n */\nexport function useMapViewport(mapId: UniqueId): ViewportState {\n return viewportStore.useSelector(mapId, (state) => {\n // Return proper default state with correct mapId if uninitialized\n if (state.id === '') {\n return createDefaultState(mapId);\n }\n return state;\n });\n}\n\n/**\n * Get current viewport state (non-reactive, for imperative code).\n *\n * @param mapId - Unique identifier for the map instance\n * @returns Current viewport state\n */\nexport function getViewport(mapId: UniqueId): ViewportState {\n const state = viewportStore.get(mapId);\n // Return proper default state with correct mapId if uninitialized\n if (state.id === '') {\n return createDefaultState(mapId);\n }\n return state;\n}\n\n/**\n * Manually clear viewport state for a specific map instance.\n * This is typically not needed as cleanup happens automatically when all subscribers unmount.\n *\n * @param mapId - The unique identifier for the map instance to clear\n * @returns void\n */\nexport function clearViewportState(mapId: UniqueId): void {\n viewportStore.clear(mapId);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,MAAM,MAAM,UAAU,aAA2B;;;;;;;;AAoBjD,SAAS,mBAAmB,OAAgC;AAC1D,QAAO;EACL,IAAI;EACJ,QAAQ;EACR,UAAU;EACV,WAAW;EACX,MAAM;EACN,OAAO;EACP,QAAQ;EACT;;;;;;;;AASH,MAAa,gBAAgB,eAA+C;CAE1E,cAAc;EACZ,IAAI;EACJ,QAAQ;EACR,UAAU;EACV,WAAW;EACX,MAAM;EACN,OAAO;EACP,QAAQ;EACT;CAGD,gBAAgB,EAAE;CAElB,MAAM,OAAO,EAAE,cAAc;AAQ3B,SAPc,IAAI,GAAG,UAAU,WAAW,EAAE,cAAc;AACxD,OAAI,QAAQ,OAAO,MAEjB,SAAQ,QAAQ;IAElB;;CAIL,CAAC;;;;;;;;;;;;;;;;;;;AAwBF,SAAgB,eAAe,OAAgC;AAC7D,QAAO,cAAc,YAAY,QAAQ,UAAU;AAEjD,MAAI,MAAM,OAAO,GACf,QAAO,mBAAmB,MAAM;AAElC,SAAO;GACP;;;;;;;;AASJ,SAAgB,YAAY,OAAgC;CAC1D,MAAM,QAAQ,cAAc,IAAI,MAAM;AAEtC,KAAI,MAAM,OAAO,GACf,QAAO,mBAAmB,MAAM;AAElC,QAAO;;;;;;;;;AAUT,SAAgB,mBAAmB,OAAuB;AACxD,eAAc,MAAM,MAAM"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@accelint/map-toolkit",
3
3
  "description": "A collection of components and utilities to simplify visualizing and working with geospatial data.",
4
- "version": "1.1.0",
4
+ "version": "1.3.0",
5
5
  "author": "https://hypergiant.com",
6
6
  "$schema": "https://json.schemastore.org/package",
7
7
  "devDependencies": {
@@ -46,13 +46,13 @@
46
46
  "@accelint/bus": "3.0.2",
47
47
  "@accelint/core": "0.5.2",
48
48
  "@accelint/design-foundation": "2.1.0",
49
- "@accelint/design-toolkit": "9.3.0",
49
+ "@accelint/design-toolkit": "9.5.0",
50
50
  "@accelint/geo": "0.5.1",
51
51
  "@accelint/logger": "0.1.5",
52
52
  "@accelint/postcss-tailwind-css-modules": "1.0.1",
53
+ "@accelint/smeegl": "0.3.5",
53
54
  "@accelint/typescript-config": "0.1.4",
54
- "@accelint/vitest-config": "0.1.6",
55
- "@accelint/smeegl": "0.3.4"
55
+ "@accelint/vitest-config": "0.1.6"
56
56
  },
57
57
  "engines": {
58
58
  "node": ">=22",
@@ -151,16 +151,16 @@
151
151
  "milsymbol": "^3.0.2",
152
152
  "mjolnir.js": "^3.0.0",
153
153
  "react-map-gl": "^8.1.0",
154
- "@accelint/hotkey-manager": "0.1.3"
154
+ "@accelint/hotkey-manager": "1.0.1"
155
155
  },
156
156
  "owner": "default/pathfinder",
157
157
  "peerDependencies": {
158
158
  "@types/geojson": "^7946.0.14",
159
159
  "react": "^19",
160
+ "@accelint/bus": "3.0.2",
160
161
  "@accelint/core": "0.5.2",
161
162
  "@accelint/geo": "0.5.1",
162
- "@accelint/logger": "0.1.5",
163
- "@accelint/bus": "3.0.2"
163
+ "@accelint/logger": "0.1.5"
164
164
  },
165
165
  "private": false,
166
166
  "publishConfig": {