@accelint/map-toolkit 0.5.0 → 0.6.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 (145) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/catalog-info.yaml +5 -3
  3. package/dist/camera/use-camera-state.js +1 -2
  4. package/dist/camera/use-camera-state.js.map +1 -1
  5. package/dist/deckgl/base-map/constants.d.ts +9 -2
  6. package/dist/deckgl/base-map/constants.js +9 -2
  7. package/dist/deckgl/base-map/constants.js.map +1 -1
  8. package/dist/deckgl/base-map/index.d.ts +4 -2
  9. package/dist/deckgl/base-map/index.js +5 -6
  10. package/dist/deckgl/base-map/index.js.map +1 -1
  11. package/dist/deckgl/base-map/types.d.ts +6 -1
  12. package/dist/deckgl/index.d.ts +8 -2
  13. package/dist/deckgl/index.js +6 -2
  14. package/dist/deckgl/saved-viewports/index.d.ts +1 -1
  15. package/dist/deckgl/saved-viewports/index.js +1 -2
  16. package/dist/deckgl/saved-viewports/index.js.map +1 -1
  17. package/dist/deckgl/shapes/display-shape-layer/constants.d.ts +44 -0
  18. package/dist/deckgl/shapes/display-shape-layer/constants.js +61 -0
  19. package/dist/deckgl/shapes/display-shape-layer/constants.js.map +1 -0
  20. package/dist/{node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/assert.js → deckgl/shapes/display-shape-layer/fiber.d.ts} +11 -7
  21. package/dist/{packages/hotkey-manager/dist/lib/is-client/index.js → deckgl/shapes/display-shape-layer/fiber.js} +6 -7
  22. package/dist/deckgl/shapes/display-shape-layer/fiber.js.map +1 -0
  23. package/dist/deckgl/shapes/display-shape-layer/index.d.ts +206 -0
  24. package/dist/deckgl/shapes/display-shape-layer/index.js +416 -0
  25. package/dist/deckgl/shapes/display-shape-layer/index.js.map +1 -0
  26. package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.d.ts +66 -0
  27. package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.js +116 -0
  28. package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.js.map +1 -0
  29. package/dist/deckgl/shapes/display-shape-layer/store.d.ts +87 -0
  30. package/dist/deckgl/shapes/display-shape-layer/store.js +316 -0
  31. package/dist/deckgl/shapes/display-shape-layer/store.js.map +1 -0
  32. package/dist/deckgl/shapes/display-shape-layer/types.d.ts +115 -0
  33. package/dist/{node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/fly-to-viewport.js → deckgl/shapes/display-shape-layer/types.js} +0 -2
  34. package/dist/deckgl/shapes/display-shape-layer/use-shape-selection.d.ts +89 -0
  35. package/dist/deckgl/shapes/display-shape-layer/use-shape-selection.js +88 -0
  36. package/dist/deckgl/shapes/display-shape-layer/use-shape-selection.js.map +1 -0
  37. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.d.ts +61 -0
  38. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js +111 -0
  39. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js.map +1 -0
  40. package/dist/deckgl/shapes/display-shape-layer/utils/labels.d.ts +196 -0
  41. package/dist/deckgl/shapes/display-shape-layer/utils/labels.js +368 -0
  42. package/dist/deckgl/shapes/display-shape-layer/utils/labels.js.map +1 -0
  43. package/dist/deckgl/shapes/index.d.ts +20 -0
  44. package/dist/{node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/math-utils.js → deckgl/shapes/index.js} +6 -11
  45. package/dist/deckgl/shapes/shared/constants.d.ts +78 -0
  46. package/dist/deckgl/shapes/shared/constants.js +109 -0
  47. package/dist/deckgl/shapes/shared/constants.js.map +1 -0
  48. package/dist/deckgl/shapes/shared/events.d.ts +73 -0
  49. package/dist/deckgl/shapes/shared/events.js +58 -0
  50. package/dist/deckgl/shapes/shared/events.js.map +1 -0
  51. package/dist/deckgl/shapes/shared/types.d.ts +158 -0
  52. package/dist/{node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/get-bounds.js → deckgl/shapes/shared/types.js} +13 -4
  53. package/dist/deckgl/shapes/shared/types.js.map +1 -0
  54. package/dist/deckgl/symbol-layer/index.d.ts +1 -1
  55. package/dist/viewport/viewport-size.d.ts +2 -2
  56. package/package.json +36 -20
  57. package/dist/_virtual/rolldown_runtime.js +0 -22
  58. package/dist/decorators/deckgl.d.ts +0 -19
  59. package/dist/decorators/deckgl.js +0 -32
  60. package/dist/decorators/deckgl.js.map +0 -1
  61. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/assert.js.map +0 -1
  62. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/fit-bounds.js +0 -63
  63. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/fit-bounds.js.map +0 -1
  64. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/get-bounds.js.map +0 -1
  65. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/index.js +0 -19
  66. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/math-utils.js.map +0 -1
  67. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/normalize-viewport-props.js +0 -14
  68. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/web-mercator-utils.js +0 -59
  69. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/web-mercator-utils.js.map +0 -1
  70. package/dist/node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/web-mercator-viewport.js +0 -16
  71. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/attribution-control.js +0 -29
  72. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/attribution-control.js.map +0 -1
  73. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/fullscreen-control.js +0 -29
  74. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/fullscreen-control.js.map +0 -1
  75. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/geolocate-control.js +0 -54
  76. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/geolocate-control.js.map +0 -1
  77. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/layer.js +0 -15
  78. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/logo-control.js +0 -29
  79. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/logo-control.js.map +0 -1
  80. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/map.js +0 -91
  81. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/map.js.map +0 -1
  82. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/marker.js +0 -88
  83. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/marker.js.map +0 -1
  84. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/navigation-control.js +0 -29
  85. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/navigation-control.js.map +0 -1
  86. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/popup.js +0 -69
  87. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/popup.js.map +0 -1
  88. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/scale-control.js +0 -35
  89. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/scale-control.js.map +0 -1
  90. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/source.js +0 -15
  91. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/terrain-control.js +0 -29
  92. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/terrain-control.js.map +0 -1
  93. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/use-control.js +0 -40
  94. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/use-control.js.map +0 -1
  95. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/use-map.js +0 -23
  96. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/use-map.js.map +0 -1
  97. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/index.js +0 -27
  98. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/maplibre/create-ref.js +0 -57
  99. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/maplibre/create-ref.js.map +0 -1
  100. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/maplibre/maplibre.js +0 -343
  101. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/maplibre/maplibre.js.map +0 -1
  102. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/apply-react-style.js +0 -28
  103. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/apply-react-style.js.map +0 -1
  104. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/compare-class-names.js +0 -31
  105. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/compare-class-names.js.map +0 -1
  106. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/deep-equal.js +0 -57
  107. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/deep-equal.js.map +0 -1
  108. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/set-globals.js +0 -30
  109. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/set-globals.js.map +0 -1
  110. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/style-utils.js +0 -53
  111. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/style-utils.js.map +0 -1
  112. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/transform.js +0 -52
  113. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/transform.js.map +0 -1
  114. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/use-isomorphic-layout-effect.js +0 -22
  115. package/dist/node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/utils/use-isomorphic-layout-effect.js.map +0 -1
  116. package/dist/node_modules/.pnpm/immer@10.2.0/node_modules/immer/dist/immer.js +0 -812
  117. package/dist/node_modules/.pnpm/immer@10.2.0/node_modules/immer/dist/immer.js.map +0 -1
  118. package/dist/node_modules/.pnpm/radashi@12.7.1/node_modules/radashi/dist/radashi.js +0 -35
  119. package/dist/node_modules/.pnpm/radashi@12.7.1/node_modules/radashi/dist/radashi.js.map +0 -1
  120. package/dist/node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/cjs/react-dom.development.js +0 -195
  121. package/dist/node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/cjs/react-dom.development.js.map +0 -1
  122. package/dist/node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/cjs/react-dom.production.js +0 -76
  123. package/dist/node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/cjs/react-dom.production.js.map +0 -1
  124. package/dist/node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/index.js +0 -39
  125. package/dist/node_modules/.pnpm/react-dom@19.2.3_react@19.2.3/node_modules/react-dom/index.js.map +0 -1
  126. package/dist/node_modules/.pnpm/react-map-gl@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/react-map-gl/dist/maplibre.js +0 -16
  127. package/dist/node_modules/.pnpm/zustand@5.0.9_@types_react@19.2.7_immer@10.2.0_react@19.2.3_use-sync-external-store@1.6.0_react@19.2.3_/node_modules/zustand/esm/middleware/immer.js +0 -27
  128. package/dist/node_modules/.pnpm/zustand@5.0.9_@types_react@19.2.7_immer@10.2.0_react@19.2.3_use-sync-external-store@1.6.0_react@19.2.3_/node_modules/zustand/esm/middleware/immer.js.map +0 -1
  129. package/dist/node_modules/.pnpm/zustand@5.0.9_@types_react@19.2.7_immer@10.2.0_react@19.2.3_use-sync-external-store@1.6.0_react@19.2.3_/node_modules/zustand/esm/vanilla.js +0 -45
  130. package/dist/node_modules/.pnpm/zustand@5.0.9_@types_react@19.2.7_immer@10.2.0_react@19.2.3_use-sync-external-store@1.6.0_react@19.2.3_/node_modules/zustand/esm/vanilla.js.map +0 -1
  131. package/dist/packages/hotkey-manager/dist/actions/register-hotkey/index.js +0 -78
  132. package/dist/packages/hotkey-manager/dist/actions/register-hotkey/index.js.map +0 -1
  133. package/dist/packages/hotkey-manager/dist/constants.js +0 -47
  134. package/dist/packages/hotkey-manager/dist/constants.js.map +0 -1
  135. package/dist/packages/hotkey-manager/dist/enums/keycode.js +0 -130
  136. package/dist/packages/hotkey-manager/dist/enums/keycode.js.map +0 -1
  137. package/dist/packages/hotkey-manager/dist/lib/is-client/index.js.map +0 -1
  138. package/dist/packages/hotkey-manager/dist/lib/is-mac/index.js +0 -24
  139. package/dist/packages/hotkey-manager/dist/lib/is-mac/index.js.map +0 -1
  140. package/dist/packages/hotkey-manager/dist/lib/key-to-id/index.js +0 -39
  141. package/dist/packages/hotkey-manager/dist/lib/key-to-id/index.js.map +0 -1
  142. package/dist/packages/hotkey-manager/dist/lib/key-to-string/index.js +0 -27
  143. package/dist/packages/hotkey-manager/dist/lib/key-to-string/index.js.map +0 -1
  144. package/dist/packages/hotkey-manager/dist/stores/hotkey-store/index.js +0 -95
  145. package/dist/packages/hotkey-manager/dist/stores/hotkey-store/index.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @accelint/map-toolkit
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7c62ee3: Add display shapes layer to map-toolkit
8
+ - cebdbe7: Expose styleUrl in BaseMap props, update BASE_MAP_STYLE constant to DARK_BASE_MAP_STYLE and provide LIGHT_BASE_MAP_STYLE constant
9
+
10
+ ### Patch Changes
11
+
12
+ - a7d3a1e: Fix bad build by updating configs
13
+ - aa296da: Update the shape labels and point icon behavior to match designs
14
+ - Updated dependencies [308023f]
15
+ - @accelint/geo@0.5.0
16
+
3
17
  ## 0.5.0
4
18
 
5
19
  ### Minor Changes
package/catalog-info.yaml CHANGED
@@ -12,13 +12,14 @@ metadata:
12
12
  Dependencies:
13
13
 
14
14
  accelint_biome-config@1.0.2, accelint_bus@3.0.2, accelint_core@0.5.2,
15
- accelint_design-foundation@2.0.0, accelint_design-toolkit@9.0.0,
15
+ accelint_design-foundation@2.0.0, accelint_design-toolkit@9.1.1,
16
16
  accelint_geo@0.4.2, accelint_postcss-tailwind-css-modules@1.0.1,
17
- accelint_typescript-config@0.1.4, accelint_vitest-config@0.1.6
17
+ accelint_smeegl@0.3.4, accelint_typescript-config@0.1.4,
18
+ accelint_vitest-config@0.1.6
18
19
  annotations:
19
20
  backstage.io/edit-url: https://github.com/gohypergiant/standard-toolkit/blob/main/packages/map-toolkit/catalog-info.yaml
20
21
  backstage.io/techdocs-ref: dir:.
21
- package/version: 0.5.0
22
+ package/version: 0.6.0
22
23
  github.com/project-slug: gohypergiant/standard-toolkit
23
24
  links:
24
25
  - url: https://github.com/gohypergiant/standard-toolkit/tree/main/packages/map-toolkit
@@ -42,5 +43,6 @@ spec:
42
43
  - component:accelint_design-toolkit
43
44
  - component:accelint_geo
44
45
  - component:accelint_postcss-tailwind-css-modules
46
+ - component:accelint_smeegl
45
47
  - component:accelint_typescript-config
46
48
  - component:accelint_vitest-config
@@ -12,9 +12,8 @@
12
12
 
13
13
 
14
14
  import { CameraEventTypes } from "./events.js";
15
- import { fitBounds } from "../node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/fit-bounds.js";
16
- import "../node_modules/.pnpm/@math.gl_web-mercator@4.1.0/node_modules/@math.gl/web-mercator/dist/index.js";
17
15
  import { Broadcast } from "@accelint/bus";
16
+ import { fitBounds } from "@math.gl/web-mercator";
18
17
  import { useMemo, useSyncExternalStore } from "react";
19
18
 
20
19
  //#region src/camera/use-camera-state.ts
@@ -1 +1 @@
1
- {"version":3,"file":"use-camera-state.js","names":["projection: ProjectionType","view: ViewType","newFallback: CameraState"],"sources":["../../src/camera/use-camera-state.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 { Broadcast } from '@accelint/bus';\nimport { fitBounds } from '@math.gl/web-mercator';\nimport { useMemo, useSyncExternalStore } from 'react';\nimport { CameraEventTypes } from './events';\nimport type { UniqueId } from '@accelint/core';\nimport type { CameraEvent, ProjectionType, ViewType } from './types';\n\n/**\n * Typed event bus instance for camera events.\n * Provides type-safe event emission and listening for all camera state changes.\n */\nconst cameraBus = Broadcast.getInstance<CameraEvent>();\n\ntype CameraState2D = {\n latitude: number;\n longitude: number;\n zoom: number;\n pitch: 0;\n rotation: number;\n projection: 'mercator';\n view: '2D';\n};\n\ntype CameraState3D = {\n latitude: number;\n longitude: number;\n zoom: number;\n pitch: 0;\n rotation: number;\n projection: 'globe';\n view: '3D';\n};\n\ntype CameraState2Point5D = {\n latitude: number;\n longitude: number;\n zoom: number;\n pitch: number;\n rotation: number;\n projection: 'mercator';\n view: '2.5D';\n};\n\nexport type CameraState = CameraState2D | CameraState3D | CameraState2Point5D;\n\nexport type UseCameraStateProps = {\n instanceId: UniqueId;\n initialCameraState?: Partial<CameraState>;\n subscribe?: Parameters<typeof useSyncExternalStore<CameraState>>[0];\n getSnapshot?: Parameters<typeof useSyncExternalStore<CameraState>>[1];\n getServerSnapshot?: Parameters<typeof useSyncExternalStore<CameraState>>[2];\n};\n\n/**\n * Store for camera state keyed by instanceId\n */\nconst cameraStore = new Map<UniqueId, CameraState>();\n\n/**\n * Track React component subscribers per instanceId (for fan-out notifications).\n * Each Set contains onStoreChange callbacks from useSyncExternalStore.\n */\nconst componentSubscribers = new Map<UniqueId, Set<() => void>>();\n\n/**\n * Cache of bus unsubscribe functions (1 per instanceId).\n * This ensures we only have one bus listener per camera, regardless of\n * how many React components subscribe to it.\n */\nconst busUnsubscribers = new Map<UniqueId, () => void>();\n\ntype Subscription = (onStoreChange: () => void) => () => void;\n/**\n * Cache of subscription functions per instanceId to avoid recreating on every render\n */\nconst subscriptionCache = new Map<UniqueId, Subscription>();\n\n/**\n * Cache of snapshot functions per instanceId to maintain referential stability\n */\nconst snapshotCache = new Map<UniqueId, () => CameraState>();\n\n/**\n * Cache of fallback snapshots per instanceId to maintain referential stability.\n * This prevents unnecessary re-renders when no camera data exists yet.\n */\nconst fallbackCache = new Map<UniqueId, CameraState>();\n\n/*\n * Helper to build initial camera state from partial input\n */\nfunction buildInitialCameraState(\n initialCameraState?: Partial<CameraState>,\n): CameraState {\n if (!initialCameraState) {\n return {\n latitude: 0,\n longitude: 0,\n zoom: 0,\n pitch: 0,\n rotation: 0,\n projection: 'mercator',\n view: '2D',\n };\n }\n\n const is2Point5D = initialCameraState.view === '2.5D';\n const is3D =\n initialCameraState.view === '3D' ||\n initialCameraState.projection === 'globe';\n\n let projection: ProjectionType;\n let view: ViewType;\n\n if (is3D) {\n projection = 'globe';\n view = '3D';\n } else if (is2Point5D) {\n projection = 'mercator';\n view = '2.5D';\n } else {\n projection = initialCameraState.projection ?? 'mercator';\n view = initialCameraState.view ?? '2D';\n }\n\n return {\n latitude: initialCameraState.latitude ?? 0,\n longitude: initialCameraState.longitude ?? 0,\n zoom: initialCameraState.zoom ?? 0,\n pitch: is2Point5D ? (initialCameraState.pitch ?? 45) : 0,\n rotation: is3D ? 0 : (initialCameraState.rotation ?? 0),\n projection,\n view,\n } as CameraState;\n}\n\n/*\n * Get or create camera state for a given instanceId\n */\nfunction getOrCreateState(\n instanceId: UniqueId,\n initialCameraState?: Partial<CameraState>,\n): CameraState {\n if (!cameraStore.has(instanceId)) {\n cameraStore.set(instanceId, buildInitialCameraState(initialCameraState));\n }\n // biome-ignore lint/style/noNonNullAssertion: State guaranteed to exist after has() check above\n return cameraStore.get(instanceId)!;\n}\n\n/**\n * Notify all React subscribers for a given instanceId\n */\nfunction notifySubscribers(instanceId: UniqueId): void {\n const subscribers = componentSubscribers.get(instanceId);\n\n if (subscribers) {\n for (const onStoreChange of subscribers) {\n onStoreChange();\n }\n }\n}\n\n/**\n * Ensures a single bus listener exists for the given instanceId.\n * All React subscribers will be notified via fan-out when the bus event fires.\n * This prevents creating N bus listeners for N React components.\n *\n * @param instanceId - The unique identifier for the camera\n * @param initialCameraState - Optional initial camera state to set when creating the listener\n */\nfunction ensureBusListener(\n instanceId: UniqueId,\n initialCameraState?: Partial<CameraState>,\n): void {\n if (busUnsubscribers.has(instanceId)) {\n return; // Already listening\n }\n\n const unsubResetCamera = cameraBus.on(\n CameraEventTypes.reset,\n ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = {\n ...buildInitialCameraState({\n ...state,\n zoom:\n payload.zoom === false ? state.zoom : initialCameraState?.zoom,\n pitch:\n payload.pitch === false ? state.pitch : initialCameraState?.pitch,\n rotation:\n payload.rotation === false\n ? state.rotation\n : initialCameraState?.rotation,\n } as Partial<CameraState>),\n };\n\n cameraStore.set(instanceId, newState);\n\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubSetCenter = cameraBus.on(\n CameraEventTypes.setCenter,\n ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = {\n ...state,\n latitude: payload.latitude,\n longitude: payload.longitude,\n zoom: payload.zoom ?? state.zoom,\n rotation: payload.heading ?? state.rotation,\n pitch: payload.pitch ?? state.pitch,\n } as CameraState;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubFitBounds = cameraBus.on(\n CameraEventTypes.fitBounds,\n ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const { longitude, latitude, zoom } = fitBounds({\n width: payload.width,\n height: payload.height,\n bounds: [\n [payload.bounds[0], payload.bounds[1]],\n [payload.bounds[2], payload.bounds[3]],\n ],\n padding: payload.padding,\n });\n const newState = {\n ...state,\n latitude: latitude,\n longitude: longitude,\n zoom: zoom,\n rotation: payload.heading ?? state.rotation,\n pitch: payload.pitch ?? state.pitch,\n } as CameraState;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubSetProjection = cameraBus.on(\n CameraEventTypes.setProjection,\n ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = { ...state };\n newState.projection = payload.projection;\n if (payload.projection === 'globe') {\n newState.view = '3D';\n } else {\n newState.view = '2D';\n newState.pitch = 0;\n }\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubSetView = cameraBus.on(CameraEventTypes.setView, ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = { ...state };\n newState.view = payload.view;\n if (payload.view === '3D') {\n newState.projection = 'globe';\n newState.pitch = 0;\n } else {\n newState.projection = 'mercator';\n }\n\n if (payload.view === '2.5D') {\n newState.pitch = 45;\n }\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n });\n\n const unsubSetZoom = cameraBus.on(CameraEventTypes.setZoom, ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = { ...state };\n newState.zoom = payload.zoom;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n });\n\n const unsubSetRotation = cameraBus.on(\n CameraEventTypes.setRotation,\n ({ payload }) => {\n const state = getOrCreateState(instanceId, initialCameraState);\n if (instanceId === payload.id && state.view !== '3D') {\n const newState = { ...state };\n newState.rotation = payload.rotation;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubSetPitch = cameraBus.on(\n CameraEventTypes.setPitch,\n ({ payload }) => {\n const state = getOrCreateState(instanceId, initialCameraState);\n if (instanceId === payload.id && state.view === '2.5D') {\n const newState = { ...state };\n newState.pitch = payload.pitch;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n busUnsubscribers.set(instanceId, () => {\n unsubResetCamera();\n unsubSetCenter();\n unsubFitBounds();\n unsubSetProjection();\n unsubSetView();\n unsubSetZoom();\n unsubSetRotation();\n unsubSetPitch();\n });\n}\n\n/**\n * Cleans up the bus listener if no React subscribers remain.\n *\n * @param instanceId - The unique identifier for the camera\n */\nfunction cleanupBusListenerIfNeeded(instanceId: UniqueId): void {\n const subscribers = componentSubscribers.get(instanceId);\n\n if (!subscribers || subscribers.size === 0) {\n // No more React subscribers - clean up bus listener\n const unsub = busUnsubscribers.get(instanceId);\n if (unsub) {\n unsub();\n busUnsubscribers.delete(instanceId);\n }\n\n // Clean up all state\n [\n cameraStore,\n componentSubscribers,\n subscriptionCache,\n snapshotCache,\n fallbackCache,\n ].forEach((map) => {\n map.delete(instanceId);\n });\n }\n}\n\n/**\n * Creates or retrieves a cached subscription function for a given instanceId.\n * Uses a fan-out pattern: 1 bus listener -> N React subscribers.\n * Automatically cleans up camera state when the last subscriber unsubscribes.\n *\n * @param instanceId - The unique identifier for the camera\n * @param initialCameraState - Optional initial camera state to set when creating the listener\n * @returns A subscription function for useSyncExternalStore\n */\nfunction getOrCreateSubscription(\n instanceId: UniqueId,\n initialCameraState?: Partial<CameraState>,\n): (onStoreChange: () => void) => () => void {\n const subscription =\n subscriptionCache.get(instanceId) ??\n ((onStoreChange: () => void) => {\n // Ensure single bus listener exists for this instanceId\n ensureBusListener(instanceId, initialCameraState);\n\n // Get or create the subscriber set for this map instance, then add this component's callback\n let subscriberSet = componentSubscribers.get(instanceId);\n if (!subscriberSet) {\n subscriberSet = new Set();\n componentSubscribers.set(instanceId, subscriberSet);\n }\n subscriberSet.add(onStoreChange);\n\n // Return cleanup function to remove this component's subscription\n return () => {\n const currentSubscriberSet = componentSubscribers.get(instanceId);\n if (currentSubscriberSet) {\n currentSubscriberSet.delete(onStoreChange);\n }\n\n // Clean up bus listener if this was the last React subscriber\n cleanupBusListenerIfNeeded(instanceId);\n };\n });\n\n subscriptionCache.set(instanceId, subscription);\n\n return subscription;\n}\n\n/**\n * Creates or retrieves a cached snapshot function for a given instanceId.\n * The object returned gets equality checked, so it needs to be stable or React re-renders unnecessarily.\n *\n * @param instanceId - The unique identifier for the camera\n * @param initialCameraState - Initialize the snapshot with camera view information\n * @returns A snapshot function for useSyncExternalStore\n */\nfunction getOrCreateSnapshot(\n instanceId: UniqueId,\n initialCameraState?: Partial<CameraState>,\n): () => CameraState {\n // Get or create stable fallback reference for this instanceId\n const fallback =\n fallbackCache.get(instanceId) ??\n (() => {\n const newFallback: CameraState = {\n latitude: initialCameraState?.latitude ?? 0,\n longitude: initialCameraState?.longitude ?? 0,\n zoom: initialCameraState?.zoom ?? 0,\n pitch: 0,\n rotation: 0,\n projection: 'mercator',\n view: '2D',\n };\n fallbackCache.set(instanceId, newFallback);\n return newFallback;\n })();\n\n const snapshot =\n snapshotCache.get(instanceId) ??\n (() => cameraStore.get(instanceId) ?? fallback);\n\n snapshotCache.set(instanceId, snapshot);\n\n return snapshot;\n}\n\n/**\n * Updates the camera state for a given map instance and notifies subscribers.\n *\n * @param instanceId - The unique identifier for the map\n * @param state - The new state to set, will be merged with existing state\n *\n * @example\n * ```tsx\n * // Update camera state manually\n * setCameraState('my-map-instance', {\n * latitude: 37.7749,\n * longitude: -122.4194,\n * zoom: 10,\n * pitch: 30,\n * rotation: 0,\n * projection: 'mercator',\n * });\n * ```\n */\nfunction setCameraState(\n instanceId: UniqueId,\n state: Partial<CameraState>,\n): void {\n const currentState = getOrCreateState(instanceId);\n cameraStore.set(instanceId, { ...currentState, ...state } as CameraState);\n notifySubscribers(instanceId);\n}\n\n/**\n * Hook to access camera state actions.\n *\n * This hook uses `useSyncExternalStore` to subscribe to camera state changes,\n * providing concurrent-safe mode state updates. Uses a fan-out pattern where\n * a single bus listener per map instance notifies N React component subscribers.\n *\n * A thin wrapper around [useSyncExternalStore](https://react.dev/reference/react/useSyncExternalStore).\n *\n * @param instanceId - Unique identifier for the camera to track\n * @param initialCameraState - Optional initial camera state to set\n * @param subscribe - Optional custom subscription function\n * @param getSnapshot - Optional custom snapshot getter\n * @param getServerSnapshot - Optional server-side snapshot getter\n * @returns Current camera state including latitude, longitude, zoom, pitch, rotation, projection\n *\n * @example\n * ```tsx\n * function MapInfo({ instanceId }) {\n * const { latitude, longitude, zoom } = useCameraState({\n * instanceId\n * });\n *\n * return (\n * <div>\n * Lat: {latitude?.toFixed(2)}, Lon: {longitude?.toFixed(2)}, Zoom: {zoom}\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With custom subscribe/getSnapshot for advanced use cases\n * function CustomMapInfo() {\n * const customSubscribe = (onStoreChange) => {\n * // Custom subscription logic\n * return () => { // cleanup }\n * }\n *\n * const customGetSnapshot = () => {\n * // Custom snapshot logic\n * return { latitude: 0, longitude: 0, zoom: 1 };\n * };\n *\n * const viewState = useCameraState({\n * instanceId: 'some-uuid',\n * subscribe: customSubscribe,\n * getSnapshot: customGetSnapshot,\n * });\n *\n * return <div>Custom camera state</div>;\n * }\n * ```\n */\nexport function useCameraState({\n instanceId,\n initialCameraState,\n subscribe,\n getSnapshot,\n getServerSnapshot,\n}: UseCameraStateProps) {\n const cameraState = useSyncExternalStore<CameraState>(\n subscribe ?? getOrCreateSubscription(instanceId, initialCameraState),\n getSnapshot ?? getOrCreateSnapshot(instanceId, initialCameraState),\n getServerSnapshot,\n );\n\n return useMemo(\n () => ({\n cameraState,\n setCameraState,\n }),\n [cameraState],\n );\n}\n\n/**\n * Manually clear camera state for a specific instanceId.\n * This is typically not needed as cleanup happens automatically when all subscribers unmount.\n * Use this only in advanced scenarios where manual cleanup is required.\n *\n * @param instanceId - The unique identifier for the camera to clear\n *\n * @example\n * ```tsx\n * // Manual cleanup (rarely needed)\n * clearCameraState('my-map-instance');\n * ```\n */\nexport function clearCameraState(instanceId: UniqueId): void {\n // Unsubscribe from bus if listening\n const unsub = busUnsubscribers.get(instanceId);\n if (unsub) {\n unsub();\n busUnsubscribers.delete(instanceId);\n }\n\n // Clear all state\n [\n cameraStore,\n componentSubscribers,\n subscriptionCache,\n snapshotCache,\n fallbackCache,\n ].forEach((map) => {\n map.delete(instanceId);\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-camera-state.js","names":["projection: ProjectionType","view: ViewType","newFallback: CameraState"],"sources":["../../src/camera/use-camera-state.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 { Broadcast } from '@accelint/bus';\nimport { fitBounds } from '@math.gl/web-mercator';\nimport { useMemo, useSyncExternalStore } from 'react';\nimport { CameraEventTypes } from './events';\nimport type { UniqueId } from '@accelint/core';\nimport type { CameraEvent, ProjectionType, ViewType } from './types';\n\n/**\n * Typed event bus instance for camera events.\n * Provides type-safe event emission and listening for all camera state changes.\n */\nconst cameraBus = Broadcast.getInstance<CameraEvent>();\n\ntype CameraState2D = {\n latitude: number;\n longitude: number;\n zoom: number;\n pitch: 0;\n rotation: number;\n projection: 'mercator';\n view: '2D';\n};\n\ntype CameraState3D = {\n latitude: number;\n longitude: number;\n zoom: number;\n pitch: 0;\n rotation: number;\n projection: 'globe';\n view: '3D';\n};\n\ntype CameraState2Point5D = {\n latitude: number;\n longitude: number;\n zoom: number;\n pitch: number;\n rotation: number;\n projection: 'mercator';\n view: '2.5D';\n};\n\nexport type CameraState = CameraState2D | CameraState3D | CameraState2Point5D;\n\nexport type UseCameraStateProps = {\n instanceId: UniqueId;\n initialCameraState?: Partial<CameraState>;\n subscribe?: Parameters<typeof useSyncExternalStore<CameraState>>[0];\n getSnapshot?: Parameters<typeof useSyncExternalStore<CameraState>>[1];\n getServerSnapshot?: Parameters<typeof useSyncExternalStore<CameraState>>[2];\n};\n\n/**\n * Store for camera state keyed by instanceId\n */\nconst cameraStore = new Map<UniqueId, CameraState>();\n\n/**\n * Track React component subscribers per instanceId (for fan-out notifications).\n * Each Set contains onStoreChange callbacks from useSyncExternalStore.\n */\nconst componentSubscribers = new Map<UniqueId, Set<() => void>>();\n\n/**\n * Cache of bus unsubscribe functions (1 per instanceId).\n * This ensures we only have one bus listener per camera, regardless of\n * how many React components subscribe to it.\n */\nconst busUnsubscribers = new Map<UniqueId, () => void>();\n\ntype Subscription = (onStoreChange: () => void) => () => void;\n/**\n * Cache of subscription functions per instanceId to avoid recreating on every render\n */\nconst subscriptionCache = new Map<UniqueId, Subscription>();\n\n/**\n * Cache of snapshot functions per instanceId to maintain referential stability\n */\nconst snapshotCache = new Map<UniqueId, () => CameraState>();\n\n/**\n * Cache of fallback snapshots per instanceId to maintain referential stability.\n * This prevents unnecessary re-renders when no camera data exists yet.\n */\nconst fallbackCache = new Map<UniqueId, CameraState>();\n\n/*\n * Helper to build initial camera state from partial input\n */\nfunction buildInitialCameraState(\n initialCameraState?: Partial<CameraState>,\n): CameraState {\n if (!initialCameraState) {\n return {\n latitude: 0,\n longitude: 0,\n zoom: 0,\n pitch: 0,\n rotation: 0,\n projection: 'mercator',\n view: '2D',\n };\n }\n\n const is2Point5D = initialCameraState.view === '2.5D';\n const is3D =\n initialCameraState.view === '3D' ||\n initialCameraState.projection === 'globe';\n\n let projection: ProjectionType;\n let view: ViewType;\n\n if (is3D) {\n projection = 'globe';\n view = '3D';\n } else if (is2Point5D) {\n projection = 'mercator';\n view = '2.5D';\n } else {\n projection = initialCameraState.projection ?? 'mercator';\n view = initialCameraState.view ?? '2D';\n }\n\n return {\n latitude: initialCameraState.latitude ?? 0,\n longitude: initialCameraState.longitude ?? 0,\n zoom: initialCameraState.zoom ?? 0,\n pitch: is2Point5D ? (initialCameraState.pitch ?? 45) : 0,\n rotation: is3D ? 0 : (initialCameraState.rotation ?? 0),\n projection,\n view,\n } as CameraState;\n}\n\n/*\n * Get or create camera state for a given instanceId\n */\nfunction getOrCreateState(\n instanceId: UniqueId,\n initialCameraState?: Partial<CameraState>,\n): CameraState {\n if (!cameraStore.has(instanceId)) {\n cameraStore.set(instanceId, buildInitialCameraState(initialCameraState));\n }\n // biome-ignore lint/style/noNonNullAssertion: State guaranteed to exist after has() check above\n return cameraStore.get(instanceId)!;\n}\n\n/**\n * Notify all React subscribers for a given instanceId\n */\nfunction notifySubscribers(instanceId: UniqueId): void {\n const subscribers = componentSubscribers.get(instanceId);\n\n if (subscribers) {\n for (const onStoreChange of subscribers) {\n onStoreChange();\n }\n }\n}\n\n/**\n * Ensures a single bus listener exists for the given instanceId.\n * All React subscribers will be notified via fan-out when the bus event fires.\n * This prevents creating N bus listeners for N React components.\n *\n * @param instanceId - The unique identifier for the camera\n * @param initialCameraState - Optional initial camera state to set when creating the listener\n */\nfunction ensureBusListener(\n instanceId: UniqueId,\n initialCameraState?: Partial<CameraState>,\n): void {\n if (busUnsubscribers.has(instanceId)) {\n return; // Already listening\n }\n\n const unsubResetCamera = cameraBus.on(\n CameraEventTypes.reset,\n ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = {\n ...buildInitialCameraState({\n ...state,\n zoom:\n payload.zoom === false ? state.zoom : initialCameraState?.zoom,\n pitch:\n payload.pitch === false ? state.pitch : initialCameraState?.pitch,\n rotation:\n payload.rotation === false\n ? state.rotation\n : initialCameraState?.rotation,\n } as Partial<CameraState>),\n };\n\n cameraStore.set(instanceId, newState);\n\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubSetCenter = cameraBus.on(\n CameraEventTypes.setCenter,\n ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = {\n ...state,\n latitude: payload.latitude,\n longitude: payload.longitude,\n zoom: payload.zoom ?? state.zoom,\n rotation: payload.heading ?? state.rotation,\n pitch: payload.pitch ?? state.pitch,\n } as CameraState;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubFitBounds = cameraBus.on(\n CameraEventTypes.fitBounds,\n ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const { longitude, latitude, zoom } = fitBounds({\n width: payload.width,\n height: payload.height,\n bounds: [\n [payload.bounds[0], payload.bounds[1]],\n [payload.bounds[2], payload.bounds[3]],\n ],\n padding: payload.padding,\n });\n const newState = {\n ...state,\n latitude: latitude,\n longitude: longitude,\n zoom: zoom,\n rotation: payload.heading ?? state.rotation,\n pitch: payload.pitch ?? state.pitch,\n } as CameraState;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubSetProjection = cameraBus.on(\n CameraEventTypes.setProjection,\n ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = { ...state };\n newState.projection = payload.projection;\n if (payload.projection === 'globe') {\n newState.view = '3D';\n } else {\n newState.view = '2D';\n newState.pitch = 0;\n }\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubSetView = cameraBus.on(CameraEventTypes.setView, ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = { ...state };\n newState.view = payload.view;\n if (payload.view === '3D') {\n newState.projection = 'globe';\n newState.pitch = 0;\n } else {\n newState.projection = 'mercator';\n }\n\n if (payload.view === '2.5D') {\n newState.pitch = 45;\n }\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n });\n\n const unsubSetZoom = cameraBus.on(CameraEventTypes.setZoom, ({ payload }) => {\n if (instanceId === payload.id) {\n const state = getOrCreateState(instanceId, initialCameraState);\n const newState = { ...state };\n newState.zoom = payload.zoom;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n });\n\n const unsubSetRotation = cameraBus.on(\n CameraEventTypes.setRotation,\n ({ payload }) => {\n const state = getOrCreateState(instanceId, initialCameraState);\n if (instanceId === payload.id && state.view !== '3D') {\n const newState = { ...state };\n newState.rotation = payload.rotation;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n const unsubSetPitch = cameraBus.on(\n CameraEventTypes.setPitch,\n ({ payload }) => {\n const state = getOrCreateState(instanceId, initialCameraState);\n if (instanceId === payload.id && state.view === '2.5D') {\n const newState = { ...state };\n newState.pitch = payload.pitch;\n cameraStore.set(instanceId, newState);\n notifySubscribers(instanceId);\n }\n },\n );\n\n busUnsubscribers.set(instanceId, () => {\n unsubResetCamera();\n unsubSetCenter();\n unsubFitBounds();\n unsubSetProjection();\n unsubSetView();\n unsubSetZoom();\n unsubSetRotation();\n unsubSetPitch();\n });\n}\n\n/**\n * Cleans up the bus listener if no React subscribers remain.\n *\n * @param instanceId - The unique identifier for the camera\n */\nfunction cleanupBusListenerIfNeeded(instanceId: UniqueId): void {\n const subscribers = componentSubscribers.get(instanceId);\n\n if (!subscribers || subscribers.size === 0) {\n // No more React subscribers - clean up bus listener\n const unsub = busUnsubscribers.get(instanceId);\n if (unsub) {\n unsub();\n busUnsubscribers.delete(instanceId);\n }\n\n // Clean up all state\n [\n cameraStore,\n componentSubscribers,\n subscriptionCache,\n snapshotCache,\n fallbackCache,\n ].forEach((map) => {\n map.delete(instanceId);\n });\n }\n}\n\n/**\n * Creates or retrieves a cached subscription function for a given instanceId.\n * Uses a fan-out pattern: 1 bus listener -> N React subscribers.\n * Automatically cleans up camera state when the last subscriber unsubscribes.\n *\n * @param instanceId - The unique identifier for the camera\n * @param initialCameraState - Optional initial camera state to set when creating the listener\n * @returns A subscription function for useSyncExternalStore\n */\nfunction getOrCreateSubscription(\n instanceId: UniqueId,\n initialCameraState?: Partial<CameraState>,\n): (onStoreChange: () => void) => () => void {\n const subscription =\n subscriptionCache.get(instanceId) ??\n ((onStoreChange: () => void) => {\n // Ensure single bus listener exists for this instanceId\n ensureBusListener(instanceId, initialCameraState);\n\n // Get or create the subscriber set for this map instance, then add this component's callback\n let subscriberSet = componentSubscribers.get(instanceId);\n if (!subscriberSet) {\n subscriberSet = new Set();\n componentSubscribers.set(instanceId, subscriberSet);\n }\n subscriberSet.add(onStoreChange);\n\n // Return cleanup function to remove this component's subscription\n return () => {\n const currentSubscriberSet = componentSubscribers.get(instanceId);\n if (currentSubscriberSet) {\n currentSubscriberSet.delete(onStoreChange);\n }\n\n // Clean up bus listener if this was the last React subscriber\n cleanupBusListenerIfNeeded(instanceId);\n };\n });\n\n subscriptionCache.set(instanceId, subscription);\n\n return subscription;\n}\n\n/**\n * Creates or retrieves a cached snapshot function for a given instanceId.\n * The object returned gets equality checked, so it needs to be stable or React re-renders unnecessarily.\n *\n * @param instanceId - The unique identifier for the camera\n * @param initialCameraState - Initialize the snapshot with camera view information\n * @returns A snapshot function for useSyncExternalStore\n */\nfunction getOrCreateSnapshot(\n instanceId: UniqueId,\n initialCameraState?: Partial<CameraState>,\n): () => CameraState {\n // Get or create stable fallback reference for this instanceId\n const fallback =\n fallbackCache.get(instanceId) ??\n (() => {\n const newFallback: CameraState = {\n latitude: initialCameraState?.latitude ?? 0,\n longitude: initialCameraState?.longitude ?? 0,\n zoom: initialCameraState?.zoom ?? 0,\n pitch: 0,\n rotation: 0,\n projection: 'mercator',\n view: '2D',\n };\n fallbackCache.set(instanceId, newFallback);\n return newFallback;\n })();\n\n const snapshot =\n snapshotCache.get(instanceId) ??\n (() => cameraStore.get(instanceId) ?? fallback);\n\n snapshotCache.set(instanceId, snapshot);\n\n return snapshot;\n}\n\n/**\n * Updates the camera state for a given map instance and notifies subscribers.\n *\n * @param instanceId - The unique identifier for the map\n * @param state - The new state to set, will be merged with existing state\n *\n * @example\n * ```tsx\n * // Update camera state manually\n * setCameraState('my-map-instance', {\n * latitude: 37.7749,\n * longitude: -122.4194,\n * zoom: 10,\n * pitch: 30,\n * rotation: 0,\n * projection: 'mercator',\n * });\n * ```\n */\nfunction setCameraState(\n instanceId: UniqueId,\n state: Partial<CameraState>,\n): void {\n const currentState = getOrCreateState(instanceId);\n cameraStore.set(instanceId, { ...currentState, ...state } as CameraState);\n notifySubscribers(instanceId);\n}\n\n/**\n * Hook to access camera state actions.\n *\n * This hook uses `useSyncExternalStore` to subscribe to camera state changes,\n * providing concurrent-safe mode state updates. Uses a fan-out pattern where\n * a single bus listener per map instance notifies N React component subscribers.\n *\n * A thin wrapper around [useSyncExternalStore](https://react.dev/reference/react/useSyncExternalStore).\n *\n * @param instanceId - Unique identifier for the camera to track\n * @param initialCameraState - Optional initial camera state to set\n * @param subscribe - Optional custom subscription function\n * @param getSnapshot - Optional custom snapshot getter\n * @param getServerSnapshot - Optional server-side snapshot getter\n * @returns Current camera state including latitude, longitude, zoom, pitch, rotation, projection\n *\n * @example\n * ```tsx\n * function MapInfo({ instanceId }) {\n * const { latitude, longitude, zoom } = useCameraState({\n * instanceId\n * });\n *\n * return (\n * <div>\n * Lat: {latitude?.toFixed(2)}, Lon: {longitude?.toFixed(2)}, Zoom: {zoom}\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With custom subscribe/getSnapshot for advanced use cases\n * function CustomMapInfo() {\n * const customSubscribe = (onStoreChange) => {\n * // Custom subscription logic\n * return () => { // cleanup }\n * }\n *\n * const customGetSnapshot = () => {\n * // Custom snapshot logic\n * return { latitude: 0, longitude: 0, zoom: 1 };\n * };\n *\n * const viewState = useCameraState({\n * instanceId: 'some-uuid',\n * subscribe: customSubscribe,\n * getSnapshot: customGetSnapshot,\n * });\n *\n * return <div>Custom camera state</div>;\n * }\n * ```\n */\nexport function useCameraState({\n instanceId,\n initialCameraState,\n subscribe,\n getSnapshot,\n getServerSnapshot,\n}: UseCameraStateProps) {\n const cameraState = useSyncExternalStore<CameraState>(\n subscribe ?? getOrCreateSubscription(instanceId, initialCameraState),\n getSnapshot ?? getOrCreateSnapshot(instanceId, initialCameraState),\n getServerSnapshot,\n );\n\n return useMemo(\n () => ({\n cameraState,\n setCameraState,\n }),\n [cameraState],\n );\n}\n\n/**\n * Manually clear camera state for a specific instanceId.\n * This is typically not needed as cleanup happens automatically when all subscribers unmount.\n * Use this only in advanced scenarios where manual cleanup is required.\n *\n * @param instanceId - The unique identifier for the camera to clear\n *\n * @example\n * ```tsx\n * // Manual cleanup (rarely needed)\n * clearCameraState('my-map-instance');\n * ```\n */\nexport function clearCameraState(instanceId: UniqueId): void {\n // Unsubscribe from bus if listening\n const unsub = busUnsubscribers.get(instanceId);\n if (unsub) {\n unsub();\n busUnsubscribers.delete(instanceId);\n }\n\n // Clear all state\n [\n cameraStore,\n componentSubscribers,\n subscriptionCache,\n snapshotCache,\n fallbackCache,\n ].forEach((map) => {\n map.delete(instanceId);\n });\n}\n"],"mappings":"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"}
@@ -1,5 +1,12 @@
1
1
  //#region src/deckgl/base-map/constants.d.ts
2
- declare const BASE_MAP_STYLE = "https://tiles.basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
2
+ declare const DARK_BASE_MAP_STYLE = "https://tiles.basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
3
+ declare const LIGHT_BASE_MAP_STYLE = "https://tiles.basemaps.cartocdn.com/gl/voyager-gl-style/style.json";
4
+ /**
5
+ * Default picking radius in pixels
6
+ * Creates a 5-pixel detection radius around the pointer for pickable objects
7
+ * Makes thin lines and small shapes easier to hover
8
+ */
9
+ declare const PICKING_RADIUS = 5;
3
10
  declare const PARAMETERS: {
4
11
  depthWriteEnabled: boolean;
5
12
  depthCompare: string;
@@ -19,5 +26,5 @@ declare const DEFAULT_VIEW_STATE: {
19
26
  zoom: number;
20
27
  };
21
28
  //#endregion
22
- export { BASE_MAP_STYLE, DEFAULT_VIEW_STATE, PARAMETERS };
29
+ export { DARK_BASE_MAP_STYLE, DEFAULT_VIEW_STATE, LIGHT_BASE_MAP_STYLE, PARAMETERS, PICKING_RADIUS };
23
30
  //# sourceMappingURL=constants.d.ts.map
@@ -12,7 +12,14 @@
12
12
 
13
13
 
14
14
  //#region src/deckgl/base-map/constants.ts
15
- const BASE_MAP_STYLE = "https://tiles.basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
15
+ const DARK_BASE_MAP_STYLE = "https://tiles.basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json";
16
+ const LIGHT_BASE_MAP_STYLE = "https://tiles.basemaps.cartocdn.com/gl/voyager-gl-style/style.json";
17
+ /**
18
+ * Default picking radius in pixels
19
+ * Creates a 5-pixel detection radius around the pointer for pickable objects
20
+ * Makes thin lines and small shapes easier to hover
21
+ */
22
+ const PICKING_RADIUS = 5;
16
23
  const PARAMETERS = {
17
24
  depthWriteEnabled: true,
18
25
  depthCompare: "always",
@@ -33,5 +40,5 @@ const DEFAULT_VIEW_STATE = {
33
40
  };
34
41
 
35
42
  //#endregion
36
- export { BASE_MAP_STYLE, DEFAULT_VIEW_STATE, PARAMETERS };
43
+ export { DARK_BASE_MAP_STYLE, DEFAULT_VIEW_STATE, LIGHT_BASE_MAP_STYLE, PARAMETERS, PICKING_RADIUS };
37
44
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":[],"sources":["../../../src/deckgl/base-map/constants.ts"],"sourcesContent":["// __private-exports\n/*\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\nexport const BASE_MAP_STYLE =\n 'https://tiles.basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json';\n\nexport const PARAMETERS = {\n depthWriteEnabled: true,\n depthCompare: 'always',\n depthBias: 0,\n blend: true,\n depthTest: false,\n blendColorSrcFactor: 'src-alpha',\n blendColorDstFactor: 'one-minus-src-alpha',\n blendAlphaSrcFactor: 'one',\n blendAlphaDstFactor: 'one-minus-src-alpha',\n blendColorOperation: 'add',\n blendAlphaOperation: 'add',\n};\n\nexport const DEFAULT_VIEW_STATE = {\n longitude: -77.0369,\n latitude: 38.9072,\n zoom: 4,\n};\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,iBACX;AAEF,MAAa,aAAa;CACxB,mBAAmB;CACnB,cAAc;CACd,WAAW;CACX,OAAO;CACP,WAAW;CACX,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACtB;AAED,MAAa,qBAAqB;CAChC,WAAW;CACX,UAAU;CACV,MAAM;CACP"}
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../../src/deckgl/base-map/constants.ts"],"sourcesContent":["// __private-exports\n/*\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\nexport const DARK_BASE_MAP_STYLE =\n 'https://tiles.basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json';\n\nexport const LIGHT_BASE_MAP_STYLE =\n 'https://tiles.basemaps.cartocdn.com/gl/voyager-gl-style/style.json';\n\n/**\n * Default picking radius in pixels\n * Creates a 5-pixel detection radius around the pointer for pickable objects\n * Makes thin lines and small shapes easier to hover\n */\nexport const PICKING_RADIUS = 5;\n\nexport const PARAMETERS = {\n depthWriteEnabled: true,\n depthCompare: 'always',\n depthBias: 0,\n blend: true,\n depthTest: false,\n blendColorSrcFactor: 'src-alpha',\n blendColorDstFactor: 'one-minus-src-alpha',\n blendAlphaSrcFactor: 'one',\n blendAlphaDstFactor: 'one-minus-src-alpha',\n blendColorOperation: 'add',\n blendAlphaOperation: 'add',\n};\n\nexport const DEFAULT_VIEW_STATE = {\n longitude: -77.0369,\n latitude: 38.9072,\n zoom: 4,\n};\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,sBACX;AAEF,MAAa,uBACX;;;;;;AAOF,MAAa,iBAAiB;AAE9B,MAAa,aAAa;CACxB,mBAAmB;CACnB,cAAc;CACd,WAAW;CACX,OAAO;CACP,WAAW;CACX,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;CACtB;AAED,MAAa,qBAAqB;CAChC,WAAW;CACX,UAAU;CACV,MAAM;CACP"}
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import { BaseMapProps } from "./types.js";
14
- import * as react_jsx_runtime1 from "react/jsx-runtime";
14
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
15
15
 
16
16
  //#region src/deckgl/base-map/index.d.ts
17
17
 
@@ -96,6 +96,7 @@ declare function BaseMap({
96
96
  enableControlEvents,
97
97
  interleaved,
98
98
  parameters,
99
+ styleUrl,
99
100
  useDevicePixels,
100
101
  widgets: widgetsProp,
101
102
  defaultView,
@@ -103,8 +104,9 @@ declare function BaseMap({
103
104
  onClick,
104
105
  onHover,
105
106
  onViewStateChange,
107
+ pickingRadius,
106
108
  ...rest
107
- }: BaseMapProps): react_jsx_runtime1.JSX.Element;
109
+ }: BaseMapProps): react_jsx_runtime0.JSX.Element;
108
110
  //#endregion
109
111
  export { BaseMap };
110
112
  //# sourceMappingURL=index.d.ts.map
@@ -17,15 +17,13 @@ import { useCameraState } from "../../camera/use-camera-state.js";
17
17
  import { MapEvents } from "./events.js";
18
18
  import { getCursor } from "../../map-cursor/store.js";
19
19
  import { MapProvider } from "./provider.js";
20
- import { Map } from "../../node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/map.js";
21
- import { useControl } from "../../node_modules/.pnpm/@vis.gl_react-maplibre@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/@vis.gl/react-maplibre/dist/components/use-control.js";
22
- import "../../node_modules/.pnpm/react-map-gl@8.1.0_maplibre-gl@5.15.0_react-dom@19.2.3_react@19.2.3__react@19.2.3/node_modules/react-map-gl/dist/maplibre.js";
23
- import { BASE_MAP_STYLE, DEFAULT_VIEW_STATE, PARAMETERS } from "./constants.js";
20
+ import { DARK_BASE_MAP_STYLE, DEFAULT_VIEW_STATE, PARAMETERS, PICKING_RADIUS } from "./constants.js";
24
21
  import { MapControls } from "./controls.js";
25
22
  import { useCallback, useId, useMemo, useRef } from "react";
26
23
  import { jsx, jsxs } from "react/jsx-runtime";
27
24
  import { useEffectEvent, useEmit } from "@accelint/bus/react";
28
25
  import { Deckgl, useDeckgl } from "@deckgl-fiber-renderer/dom";
26
+ import { Map, useControl } from "react-map-gl/maplibre";
29
27
 
30
28
  //#region src/deckgl/base-map/index.tsx
31
29
  /**
@@ -126,7 +124,7 @@ function AddDeckglControl() {
126
124
  * }
127
125
  * ```
128
126
  */
129
- function BaseMap({ id, className, children, controller = true, enableControlEvents = true, interleaved = true, parameters = {}, useDevicePixels = false, widgets: widgetsProp = [], defaultView = "2D", initialViewState, onClick, onHover, onViewStateChange, ...rest }) {
127
+ function BaseMap({ id, className, children, controller = true, enableControlEvents = true, interleaved = true, parameters = {}, styleUrl = DARK_BASE_MAP_STYLE, useDevicePixels = false, widgets: widgetsProp = [], defaultView = "2D", initialViewState, onClick, onHover, onViewStateChange, pickingRadius, ...rest }) {
130
128
  const deckglInstance = useDeckgl();
131
129
  const container = useId();
132
130
  const mapRef = useRef(null);
@@ -233,7 +231,7 @@ function BaseMap({ id, className, children, controller = true, enableControlEven
233
231
  id,
234
232
  children: /* @__PURE__ */ jsx(Map, {
235
233
  onMove: (evt) => setCameraState(id, evt.viewState),
236
- mapStyle: BASE_MAP_STYLE,
234
+ mapStyle: styleUrl,
237
235
  ref: mapRef,
238
236
  ...mapOptions,
239
237
  children: /* @__PURE__ */ jsxs(Deckgl, {
@@ -242,6 +240,7 @@ function BaseMap({ id, className, children, controller = true, enableControlEven
242
240
  getCursor: handleGetCursor,
243
241
  useDevicePixels,
244
242
  onClick: handleClick,
243
+ pickingRadius: pickingRadius ?? PICKING_RADIUS,
245
244
  onHover: handleHover,
246
245
  onLoad: handleLoad,
247
246
  onViewStateChange: handleViewStateChange,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["MapLibre"],"sources":["../../../src/deckgl/base-map/index.tsx"],"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'use client';\n\nimport 'client-only';\nimport { useEffectEvent, useEmit } from '@accelint/bus/react';\nimport { Deckgl, useDeckgl } from '@deckgl-fiber-renderer/dom';\nimport { useCallback, useId, useMemo, useRef } from 'react';\nimport {\n Map as MapLibre,\n type MapRef,\n useControl,\n type ViewState,\n} from 'react-map-gl/maplibre';\nimport { useCameraState } from '../../camera';\nimport { getCursor } from '../../map-cursor/store';\nimport { BASE_MAP_STYLE, DEFAULT_VIEW_STATE, PARAMETERS } from './constants';\nimport { MapControls } from './controls';\nimport { MapEvents } from './events';\nimport { MapProvider } from './provider';\nimport type { PickingInfo, ViewStateChangeParameters } from '@deck.gl/core';\nimport type { IControl } from 'maplibre-gl';\nimport type { MjolnirGestureEvent, MjolnirPointerEvent } from 'mjolnir.js';\nimport type {\n BaseMapProps,\n MapClickEvent,\n MapHoverEvent,\n MapViewportEvent,\n SerializablePickingInfo,\n} from './types';\n\n/**\n * Serializes PickingInfo for event bus transmission.\n * Omits viewport, layer, and sourceLayer (contain functions) but preserves layer IDs.\n */\nfunction serializePickingInfo(info: PickingInfo): SerializablePickingInfo {\n const { viewport, layer, sourceLayer, ...infoRest } = info;\n return {\n layerId: layer?.id,\n sourceLayerId: sourceLayer?.id,\n ...infoRest,\n };\n}\n\n/**\n * Strips non-serializable properties from MjolnirGestureEvent for event bus transmission.\n * Removes functions, DOM elements, and PointerEvent objects that cannot be cloned.\n */\nfunction serializeMjolnirEvent(\n event: MjolnirGestureEvent,\n): Omit<\n MjolnirGestureEvent,\n | 'stopPropagation'\n | 'preventDefault'\n | 'stopImmediatePropagation'\n | 'srcEvent'\n | 'rootElement'\n | 'target'\n | 'changedPointers'\n | 'pointers'\n>;\n/**\n * Strips non-serializable properties from MjolnirPointerEvent for event bus transmission.\n * Removes functions and DOM elements that cannot be cloned.\n */\nfunction serializeMjolnirEvent(\n event: MjolnirPointerEvent,\n): Omit<\n MjolnirPointerEvent,\n | 'stopPropagation'\n | 'preventDefault'\n | 'stopImmediatePropagation'\n | 'srcEvent'\n | 'rootElement'\n | 'target'\n>;\nfunction serializeMjolnirEvent(\n event: MjolnirGestureEvent | MjolnirPointerEvent,\n) {\n const {\n stopImmediatePropagation,\n stopPropagation,\n preventDefault,\n srcEvent,\n rootElement,\n target,\n ...rest\n } = event;\n\n // Remove pointer arrays if present (only on MjolnirGestureEvent)\n if ('changedPointers' in rest) {\n const { changedPointers, pointers, ...gestureRest } = rest;\n return gestureRest;\n }\n\n return rest;\n}\n\nfunction AddDeckglControl() {\n const deckglInstance = useDeckgl();\n useControl(() => deckglInstance as IControl);\n\n return null;\n}\n\n/**\n * A React component that provides a Deck.gl-powered base map with MapLibre GL integration.\n *\n * This component serves as the foundation for building interactive map applications with\n * support for click and hover events through a centralized event bus. It integrates\n * Deck.gl for 3D visualizations with MapLibre GL for the base map tiles.\n *\n * **Map Mode Integration**: BaseMap automatically creates a `MapProvider` internally,\n * which sets up the map mode state management for this instance.\n * - **Children**: Only Deck.gl layer components can be rendered as children. Custom Deck.gl\n * layers can use `useMapMode()` without parameters to access context.\n * - **Siblings**: UI components (buttons, toolbars, etc.) must be rendered as siblings\n * and pass `id` to `useMapMode(id)`.\n *\n * **Event Bus**: Click and hover events are emitted through the event bus with the `id`\n * included in the payload, allowing multiple map instances to coexist without interference.\n *\n * @param props - Component props including id (required), className, onClick, onHover, and all Deck.gl props\n * @returns A map component with Deck.gl and MapLibre GL integration\n *\n * @example\n * Basic usage with id (recommended: module-level constant):\n * ```tsx\n * import { BaseMap } from '@accelint/map-toolkit/deckgl';\n * import { View } from '@deckgl-fiber-renderer/dom';\n * import { uuid } from '@accelint/core';\n *\n * // Create id at module level for stability and easy sharing\n * const MAIN_MAP_ID = uuid();\n *\n * export function MapView() {\n * return (\n * <BaseMap className=\"w-full h-full\" id={MAIN_MAP_ID}>\n * <View id=\"main\" controller />\n * </BaseMap>\n * );\n * }\n * ```\n *\n * @example\n * With map mode and event handlers (module-level constant for sharing):\n * ```tsx\n * import { BaseMap } from '@accelint/map-toolkit/deckgl';\n * import { useMapMode } from '@accelint/map-toolkit/map-mode';\n * import { uuid } from '@accelint/core';\n * import type { PickingInfo } from '@deck.gl/core';\n * import type { MjolnirGestureEvent } from 'mjolnir.js';\n *\n * // Module-level constant - stable and shareable across all components\n * const MAIN_MAP_ID = uuid();\n *\n * function Toolbar() {\n * // Access map mode using the shared id\n * const { mode, requestModeChange } = useMapMode(MAIN_MAP_ID);\n * return <div>Current mode: {mode}</div>;\n * }\n *\n * export function InteractiveMap() {\n * const handleClick = (info: PickingInfo, event: MjolnirGestureEvent) => {\n * console.log('Clicked:', info.object);\n * };\n *\n * return (\n * <div className=\"relative w-full h-full\">\n * <BaseMap className=\"absolute inset-0\" id={MAIN_MAP_ID} onClick={handleClick}>\n * <View id=\"main\" controller />\n * </BaseMap>\n * <Toolbar />\n * </div>\n * );\n * }\n * ```\n */\nexport function BaseMap({\n id,\n className,\n children,\n controller = true,\n enableControlEvents = true,\n interleaved = true,\n parameters = {},\n useDevicePixels = false,\n widgets: widgetsProp = [],\n defaultView = '2D',\n initialViewState,\n onClick,\n onHover,\n onViewStateChange,\n ...rest\n}: BaseMapProps) {\n const deckglInstance = useDeckgl();\n const container = useId();\n const mapRef = useRef<MapRef>(null);\n\n const { cameraState, setCameraState } = useCameraState({\n instanceId: id,\n initialCameraState: {\n view: defaultView,\n zoom: initialViewState?.zoom ?? DEFAULT_VIEW_STATE.zoom,\n latitude: initialViewState?.latitude ?? DEFAULT_VIEW_STATE.latitude,\n longitude: initialViewState?.longitude ?? DEFAULT_VIEW_STATE.longitude,\n },\n });\n\n const viewState = useMemo<ViewState>(\n () => ({\n // @ts-expect-error squirrelly deckglInstance typing\n ...(deckglInstance?._deck?._getViewState() as ViewState),\n ...cameraState,\n bearing: cameraState.rotation,\n }),\n // @ts-expect-error squirrelly deckglInstance typing\n [cameraState, deckglInstance?._deck?._getViewState],\n );\n\n // Memoize MapLibre options to avoid creating new object on every render\n const mapOptions = useMemo(\n () => ({\n container,\n zoom: viewState.zoom,\n pitch: viewState.pitch,\n bearing: viewState.bearing,\n latitude: viewState.latitude,\n longitude: viewState.longitude,\n doubleClickZoom: false,\n dragRotate: false,\n pitchWithRotate: false,\n rollEnabled: false,\n attributionControl: { compact: true },\n projection: cameraState.projection,\n maxPitch: cameraState.view === '2D' ? 0 : 85,\n }),\n [viewState, container, cameraState.projection, cameraState.view],\n );\n\n // Use the custom hook to handle MapLibre\n\n const emitClick = useEmit<MapClickEvent>(MapEvents.click);\n const emitHover = useEmit<MapHoverEvent>(MapEvents.hover);\n const emitViewport = useEmit<MapViewportEvent>(MapEvents.viewport);\n\n const handleClick = useCallback(\n (info: PickingInfo, event: MjolnirGestureEvent) => {\n // send full pickingInfo and event to user-defined onClick\n onClick?.(info, event);\n\n emitClick({\n info: serializePickingInfo(info),\n event: serializeMjolnirEvent(event),\n id,\n });\n },\n [emitClick, id, onClick],\n );\n\n const handleHover = useCallback(\n (info: PickingInfo, event: MjolnirPointerEvent) => {\n // send full pickingInfo and event to user-defined onHover\n onHover?.(info, event);\n\n emitHover({\n info: serializePickingInfo(info),\n event: serializeMjolnirEvent(event),\n id,\n });\n },\n [emitHover, id, onHover],\n );\n\n const handleGetCursor = useCallback(() => {\n return getCursor(id);\n }, [id]);\n\n const handleViewStateChange = useEffectEvent(\n (params: ViewStateChangeParameters) => {\n onViewStateChange?.(params);\n\n const {\n viewId,\n viewState: { latitude, longitude, zoom },\n } = params;\n\n // @ts-expect-error squirrelly deckglInstance typing\n const viewport = deckglInstance._deck\n .getViewports()\n // @ts-expect-error squirrelly deckglInstance typing\n ?.find((vp) => vp.id === viewId);\n\n emitViewport({\n id,\n bounds: viewport?.getBounds(),\n latitude,\n longitude,\n zoom,\n width: viewport?.width ?? 0,\n height: viewport?.height ?? 0,\n });\n },\n );\n\n const handleLoad = useEffectEvent(() => {\n //--- force update viewport state once all viewports initialized ---\n // @ts-expect-error squirrelly deckglInstance typing\n const viewports = deckglInstance._deck.getViewports() ?? [];\n for (const vp of viewports) {\n handleViewStateChange({\n viewId: vp.id,\n viewState: {\n latitude: vp.latitude,\n longitude: vp.longitude,\n zoom: vp.zoom,\n id: vp.id,\n bounds: vp.getBounds(),\n width: vp.width,\n height: vp.height,\n },\n } as ViewStateChangeParameters);\n }\n });\n\n return (\n <div id={container} className={className}>\n {enableControlEvents && <MapControls id={id} mapRef={mapRef} />}\n <MapProvider id={id}>\n <MapLibre\n onMove={(evt) => setCameraState(id, evt.viewState)}\n mapStyle={BASE_MAP_STYLE}\n ref={mapRef}\n {...mapOptions}\n >\n <Deckgl\n {...rest}\n interleaved={interleaved}\n getCursor={handleGetCursor}\n useDevicePixels={useDevicePixels}\n onClick={handleClick}\n onHover={handleHover}\n onLoad={handleLoad}\n onViewStateChange={handleViewStateChange}\n // @ts-expect-error - DeckglProps parameters type is overly strict for WebGL parameter spreading.\n // The merged object is valid at runtime but TypeScript cannot verify all possible parameter combinations.\n parameters={{ ...PARAMETERS, ...parameters }}\n >\n <AddDeckglControl />\n {children}\n </Deckgl>\n </MapLibre>\n </MapProvider>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["MapLibre"],"sources":["../../../src/deckgl/base-map/index.tsx"],"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'use client';\n\nimport 'client-only';\nimport { useEffectEvent, useEmit } from '@accelint/bus/react';\nimport { Deckgl, useDeckgl } from '@deckgl-fiber-renderer/dom';\nimport { useCallback, useId, useMemo, useRef } from 'react';\nimport {\n Map as MapLibre,\n type MapRef,\n useControl,\n type ViewState,\n} from 'react-map-gl/maplibre';\nimport { useCameraState } from '../../camera';\nimport { getCursor } from '../../map-cursor/store';\nimport {\n DARK_BASE_MAP_STYLE,\n DEFAULT_VIEW_STATE,\n PARAMETERS,\n PICKING_RADIUS,\n} from './constants';\nimport { MapControls } from './controls';\nimport { MapEvents } from './events';\nimport { MapProvider } from './provider';\nimport type { PickingInfo, ViewStateChangeParameters } from '@deck.gl/core';\nimport type { IControl } from 'maplibre-gl';\nimport type { MjolnirGestureEvent, MjolnirPointerEvent } from 'mjolnir.js';\nimport type {\n BaseMapProps,\n MapClickEvent,\n MapHoverEvent,\n MapViewportEvent,\n SerializablePickingInfo,\n} from './types';\n\n/**\n * Serializes PickingInfo for event bus transmission.\n * Omits viewport, layer, and sourceLayer (contain functions) but preserves layer IDs.\n */\nfunction serializePickingInfo(info: PickingInfo): SerializablePickingInfo {\n const { viewport, layer, sourceLayer, ...infoRest } = info;\n return {\n layerId: layer?.id,\n sourceLayerId: sourceLayer?.id,\n ...infoRest,\n };\n}\n\n/**\n * Strips non-serializable properties from MjolnirGestureEvent for event bus transmission.\n * Removes functions, DOM elements, and PointerEvent objects that cannot be cloned.\n */\nfunction serializeMjolnirEvent(\n event: MjolnirGestureEvent,\n): Omit<\n MjolnirGestureEvent,\n | 'stopPropagation'\n | 'preventDefault'\n | 'stopImmediatePropagation'\n | 'srcEvent'\n | 'rootElement'\n | 'target'\n | 'changedPointers'\n | 'pointers'\n>;\n/**\n * Strips non-serializable properties from MjolnirPointerEvent for event bus transmission.\n * Removes functions and DOM elements that cannot be cloned.\n */\nfunction serializeMjolnirEvent(\n event: MjolnirPointerEvent,\n): Omit<\n MjolnirPointerEvent,\n | 'stopPropagation'\n | 'preventDefault'\n | 'stopImmediatePropagation'\n | 'srcEvent'\n | 'rootElement'\n | 'target'\n>;\nfunction serializeMjolnirEvent(\n event: MjolnirGestureEvent | MjolnirPointerEvent,\n) {\n const {\n stopImmediatePropagation,\n stopPropagation,\n preventDefault,\n srcEvent,\n rootElement,\n target,\n ...rest\n } = event;\n\n // Remove pointer arrays if present (only on MjolnirGestureEvent)\n if ('changedPointers' in rest) {\n const { changedPointers, pointers, ...gestureRest } = rest;\n return gestureRest;\n }\n\n return rest;\n}\n\nfunction AddDeckglControl() {\n const deckglInstance = useDeckgl();\n useControl(() => deckglInstance as IControl);\n\n return null;\n}\n\n/**\n * A React component that provides a Deck.gl-powered base map with MapLibre GL integration.\n *\n * This component serves as the foundation for building interactive map applications with\n * support for click and hover events through a centralized event bus. It integrates\n * Deck.gl for 3D visualizations with MapLibre GL for the base map tiles.\n *\n * **Map Mode Integration**: BaseMap automatically creates a `MapProvider` internally,\n * which sets up the map mode state management for this instance.\n * - **Children**: Only Deck.gl layer components can be rendered as children. Custom Deck.gl\n * layers can use `useMapMode()` without parameters to access context.\n * - **Siblings**: UI components (buttons, toolbars, etc.) must be rendered as siblings\n * and pass `id` to `useMapMode(id)`.\n *\n * **Event Bus**: Click and hover events are emitted through the event bus with the `id`\n * included in the payload, allowing multiple map instances to coexist without interference.\n *\n * @param props - Component props including id (required), className, onClick, onHover, and all Deck.gl props\n * @returns A map component with Deck.gl and MapLibre GL integration\n *\n * @example\n * Basic usage with id (recommended: module-level constant):\n * ```tsx\n * import { BaseMap } from '@accelint/map-toolkit/deckgl';\n * import { View } from '@deckgl-fiber-renderer/dom';\n * import { uuid } from '@accelint/core';\n *\n * // Create id at module level for stability and easy sharing\n * const MAIN_MAP_ID = uuid();\n *\n * export function MapView() {\n * return (\n * <BaseMap className=\"w-full h-full\" id={MAIN_MAP_ID}>\n * <View id=\"main\" controller />\n * </BaseMap>\n * );\n * }\n * ```\n *\n * @example\n * With map mode and event handlers (module-level constant for sharing):\n * ```tsx\n * import { BaseMap } from '@accelint/map-toolkit/deckgl';\n * import { useMapMode } from '@accelint/map-toolkit/map-mode';\n * import { uuid } from '@accelint/core';\n * import type { PickingInfo } from '@deck.gl/core';\n * import type { MjolnirGestureEvent } from 'mjolnir.js';\n *\n * // Module-level constant - stable and shareable across all components\n * const MAIN_MAP_ID = uuid();\n *\n * function Toolbar() {\n * // Access map mode using the shared id\n * const { mode, requestModeChange } = useMapMode(MAIN_MAP_ID);\n * return <div>Current mode: {mode}</div>;\n * }\n *\n * export function InteractiveMap() {\n * const handleClick = (info: PickingInfo, event: MjolnirGestureEvent) => {\n * console.log('Clicked:', info.object);\n * };\n *\n * return (\n * <div className=\"relative w-full h-full\">\n * <BaseMap className=\"absolute inset-0\" id={MAIN_MAP_ID} onClick={handleClick}>\n * <View id=\"main\" controller />\n * </BaseMap>\n * <Toolbar />\n * </div>\n * );\n * }\n * ```\n */\nexport function BaseMap({\n id,\n className,\n children,\n controller = true,\n enableControlEvents = true,\n interleaved = true,\n parameters = {},\n styleUrl = DARK_BASE_MAP_STYLE,\n useDevicePixels = false,\n widgets: widgetsProp = [],\n defaultView = '2D',\n initialViewState,\n onClick,\n onHover,\n onViewStateChange,\n pickingRadius,\n ...rest\n}: BaseMapProps) {\n const deckglInstance = useDeckgl();\n const container = useId();\n const mapRef = useRef<MapRef>(null);\n\n const { cameraState, setCameraState } = useCameraState({\n instanceId: id,\n initialCameraState: {\n view: defaultView,\n zoom: initialViewState?.zoom ?? DEFAULT_VIEW_STATE.zoom,\n latitude: initialViewState?.latitude ?? DEFAULT_VIEW_STATE.latitude,\n longitude: initialViewState?.longitude ?? DEFAULT_VIEW_STATE.longitude,\n },\n });\n\n const viewState = useMemo<ViewState>(\n () => ({\n // @ts-expect-error squirrelly deckglInstance typing\n ...(deckglInstance?._deck?._getViewState() as ViewState),\n ...cameraState,\n bearing: cameraState.rotation,\n }),\n // @ts-expect-error squirrelly deckglInstance typing\n [cameraState, deckglInstance?._deck?._getViewState],\n );\n\n // Memoize MapLibre options to avoid creating new object on every render\n const mapOptions = useMemo(\n () => ({\n container,\n zoom: viewState.zoom,\n pitch: viewState.pitch,\n bearing: viewState.bearing,\n latitude: viewState.latitude,\n longitude: viewState.longitude,\n doubleClickZoom: false,\n dragRotate: false,\n pitchWithRotate: false,\n rollEnabled: false,\n attributionControl: { compact: true },\n projection: cameraState.projection,\n maxPitch: cameraState.view === '2D' ? 0 : 85,\n }),\n [viewState, container, cameraState.projection, cameraState.view],\n );\n\n const emitClick = useEmit<MapClickEvent>(MapEvents.click);\n const emitHover = useEmit<MapHoverEvent>(MapEvents.hover);\n const emitViewport = useEmit<MapViewportEvent>(MapEvents.viewport);\n\n const handleClick = useCallback(\n (info: PickingInfo, event: MjolnirGestureEvent) => {\n // send full pickingInfo and event to user-defined onClick\n onClick?.(info, event);\n\n emitClick({\n info: serializePickingInfo(info),\n event: serializeMjolnirEvent(event),\n id,\n });\n },\n [emitClick, id, onClick],\n );\n\n const handleHover = useCallback(\n (info: PickingInfo, event: MjolnirPointerEvent) => {\n // send full pickingInfo and event to user-defined onHover\n onHover?.(info, event);\n\n emitHover({\n info: serializePickingInfo(info),\n event: serializeMjolnirEvent(event),\n id,\n });\n },\n [emitHover, id, onHover],\n );\n\n const handleGetCursor = useCallback(() => {\n return getCursor(id);\n }, [id]);\n\n const handleViewStateChange = useEffectEvent(\n (params: ViewStateChangeParameters) => {\n onViewStateChange?.(params);\n\n const {\n viewId,\n viewState: { latitude, longitude, zoom },\n } = params;\n\n // @ts-expect-error squirrelly deckglInstance typing\n const viewport = deckglInstance._deck\n .getViewports()\n // @ts-expect-error squirrelly deckglInstance typing\n ?.find((vp) => vp.id === viewId);\n\n emitViewport({\n id,\n bounds: viewport?.getBounds(),\n latitude,\n longitude,\n zoom,\n width: viewport?.width ?? 0,\n height: viewport?.height ?? 0,\n });\n },\n );\n\n const handleLoad = useEffectEvent(() => {\n //--- force update viewport state once all viewports initialized ---\n // @ts-expect-error squirrelly deckglInstance typing\n const viewports = deckglInstance._deck.getViewports() ?? [];\n for (const vp of viewports) {\n handleViewStateChange({\n viewId: vp.id,\n viewState: {\n latitude: vp.latitude,\n longitude: vp.longitude,\n zoom: vp.zoom,\n id: vp.id,\n bounds: vp.getBounds(),\n width: vp.width,\n height: vp.height,\n },\n } as ViewStateChangeParameters);\n }\n });\n\n return (\n <div id={container} className={className}>\n {enableControlEvents && <MapControls id={id} mapRef={mapRef} />}\n <MapProvider id={id}>\n <MapLibre\n onMove={(evt) => setCameraState(id, evt.viewState)}\n mapStyle={styleUrl}\n ref={mapRef}\n {...mapOptions}\n >\n <Deckgl\n {...rest}\n interleaved={interleaved}\n getCursor={handleGetCursor}\n useDevicePixels={useDevicePixels}\n onClick={handleClick}\n pickingRadius={pickingRadius ?? PICKING_RADIUS}\n onHover={handleHover}\n onLoad={handleLoad}\n onViewStateChange={handleViewStateChange}\n // @ts-expect-error - DeckglProps parameters type is overly strict for WebGL parameter spreading.\n // The merged object is valid at runtime but TypeScript cannot verify all possible parameter combinations.\n parameters={{ ...PARAMETERS, ...parameters }}\n >\n <AddDeckglControl />\n {children}\n </Deckgl>\n </MapLibre>\n </MapProvider>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -14,8 +14,8 @@ import { MapEvents } from "./events.js";
14
14
  import { Payload } from "@accelint/bus";
15
15
  import { UniqueId } from "@accelint/core";
16
16
  import { PickingInfo } from "@deck.gl/core";
17
- import { MjolnirGestureEvent, MjolnirPointerEvent } from "mjolnir.js";
18
17
  import { DeckglProps } from "@deckgl-fiber-renderer/types";
18
+ import { MjolnirGestureEvent, MjolnirPointerEvent } from "mjolnir.js";
19
19
 
20
20
  //#region src/deckgl/base-map/types.d.ts
21
21
  /**
@@ -45,6 +45,11 @@ type BaseMapProps = DeckglProps & {
45
45
  * Default view for the map: '2D', '2.5D', or '3D'. Defaults to '2D'.
46
46
  */
47
47
  defaultView?: '2D' | '2.5D' | '3D';
48
+ /**
49
+ * MapLibre style URL for the base map tiles.
50
+ * @default DARK_BASE_MAP_STYLE ('https://tiles.basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json')
51
+ */
52
+ styleUrl?: string;
48
53
  };
49
54
  /**
50
55
  * PickingInfo modified for serialization through the event bus.
@@ -12,8 +12,14 @@
12
12
 
13
13
  import { MapEvents, MapEventsNamespace } from "./base-map/events.js";
14
14
  import { BaseMapProps, MapClickEvent, MapClickPayload, MapControlPayload, MapDisablePanEvent, MapDisableZoomEvent, MapEnablePanEvent, MapEnableZoomEvent, MapEventType, MapHoverEvent, MapHoverPayload } from "./base-map/types.js";
15
- import { BASE_MAP_STYLE, PARAMETERS } from "./base-map/constants.js";
15
+ import { DARK_BASE_MAP_STYLE, LIGHT_BASE_MAP_STYLE, PARAMETERS } from "./base-map/constants.js";
16
16
  import { BaseMap } from "./base-map/index.js";
17
17
  import { SavedViewportOptions, createSavedViewport } from "./saved-viewports/index.js";
18
+ import { CircleProperties, CircleRadius, DisplayShape, EditableShape, ShapeFeature, ShapeFeatureProperties, ShapeFeatureType, ShapeFeatureTypeValues, ShapeId, StyleProperties } from "./shapes/shared/types.js";
19
+ import { DisplayShapeLayerProps, StyledFeature, StyledFeatureProperties } from "./shapes/display-shape-layer/types.js";
20
+ import { DisplayShapeLayer } from "./shapes/display-shape-layer/index.js";
21
+ import { DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, SHAPE_LAYER_IDS, STROKE_PATTERNS, STROKE_WIDTHS } from "./shapes/shared/constants.js";
22
+ import { SHAPE_EVENTS, ShapeEventHandler, ShapeEventPayload, ShapeEventType, ShapeEvents } from "./shapes/shared/events.js";
23
+ import "./shapes/index.js";
18
24
  import { SymbolLayer, SymbolLayerProps } from "./symbol-layer/index.js";
19
- export { BASE_MAP_STYLE, BaseMap, type BaseMapProps, type MapClickEvent, type MapClickPayload, type MapControlPayload, type MapDisablePanEvent, type MapDisableZoomEvent, type MapEnablePanEvent, type MapEnableZoomEvent, type MapEventType, MapEvents, MapEventsNamespace, type MapHoverEvent, type MapHoverPayload, PARAMETERS, type SavedViewportOptions, SymbolLayer, type SymbolLayerProps, createSavedViewport };
25
+ export { BaseMap, type BaseMapProps, type CircleProperties, type CircleRadius, DARK_BASE_MAP_STYLE, DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, type DisplayShape, DisplayShapeLayer, type DisplayShapeLayerProps, type EditableShape, LIGHT_BASE_MAP_STYLE, type MapClickEvent, type MapClickPayload, type MapControlPayload, type MapDisablePanEvent, type MapDisableZoomEvent, type MapEnablePanEvent, type MapEnableZoomEvent, type MapEventType, MapEvents, MapEventsNamespace, type MapHoverEvent, type MapHoverPayload, PARAMETERS, SHAPE_EVENTS, SHAPE_LAYER_IDS, STROKE_PATTERNS, STROKE_WIDTHS, type SavedViewportOptions, type ShapeEventHandler, type ShapeEventPayload, type ShapeEventType, ShapeEvents, type ShapeFeature, type ShapeFeatureProperties, ShapeFeatureType, type ShapeFeatureTypeValues, type ShapeId, type StyleProperties, type StyledFeature, type StyledFeatureProperties, SymbolLayer, type SymbolLayerProps, createSavedViewport };
@@ -12,9 +12,13 @@
12
12
 
13
13
 
14
14
  import { MapEvents, MapEventsNamespace } from "./base-map/events.js";
15
- import { BASE_MAP_STYLE, PARAMETERS } from "./base-map/constants.js";
15
+ import { DARK_BASE_MAP_STYLE, LIGHT_BASE_MAP_STYLE, PARAMETERS } from "./base-map/constants.js";
16
16
  import { BaseMap } from "./base-map/index.js";
17
17
  import { createSavedViewport } from "./saved-viewports/index.js";
18
+ import { DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, SHAPE_LAYER_IDS, STROKE_PATTERNS, STROKE_WIDTHS } from "./shapes/shared/constants.js";
19
+ import { SHAPE_EVENTS, ShapeEvents } from "./shapes/shared/events.js";
20
+ import { DisplayShapeLayer } from "./shapes/display-shape-layer/index.js";
21
+ import { ShapeFeatureType } from "./shapes/shared/types.js";
18
22
  import { SymbolLayer } from "./symbol-layer/index.js";
19
23
 
20
- export { BASE_MAP_STYLE, BaseMap, MapEvents, MapEventsNamespace, PARAMETERS, SymbolLayer, createSavedViewport };
24
+ export { BaseMap, DARK_BASE_MAP_STYLE, DASH_ARRAYS, DEFAULT_COLORS, DEFAULT_STYLE_PROPERTIES, DisplayShapeLayer, LIGHT_BASE_MAP_STYLE, MapEvents, MapEventsNamespace, PARAMETERS, SHAPE_EVENTS, SHAPE_LAYER_IDS, STROKE_PATTERNS, STROKE_WIDTHS, ShapeEvents, ShapeFeatureType, SymbolLayer, createSavedViewport };
@@ -10,8 +10,8 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import { MapViewState } from "@deck.gl/core";
14
13
  import { HotkeyOptions, KeyCombinationId, registerHotkey } from "@accelint/hotkey-manager";
14
+ import { MapViewState } from "@deck.gl/core";
15
15
  import { RequireAllOrNone } from "type-fest";
16
16
 
17
17
  //#region src/deckgl/saved-viewports/index.d.ts
@@ -11,9 +11,8 @@
11
11
  */
12
12
 
13
13
 
14
- import { registerHotkey } from "../../packages/hotkey-manager/dist/actions/register-hotkey/index.js";
15
- import { Keycode } from "../../packages/hotkey-manager/dist/enums/keycode.js";
16
14
  import { STORAGE_ID, persist, retrieve } from "./storage.js";
15
+ import { Keycode, registerHotkey } from "@accelint/hotkey-manager";
17
16
 
18
17
  //#region src/deckgl/saved-viewports/index.ts
19
18
  const createSavedViewport = (options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/deckgl/saved-viewports/index.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 {\n type HotkeyOptions,\n type KeyCombination,\n type KeyCombinationId,\n Keycode,\n registerHotkey,\n} from '@accelint/hotkey-manager';\nimport { persist, retrieve, STORAGE_ID } from './storage';\nimport type { MapViewState } from '@deck.gl/core';\nimport type { RequireAllOrNone } from 'type-fest';\n\ntype BaseOptions = {\n uniqueIdentifier?: string;\n threshold?: number;\n getCurrentViewport: () => MapViewState;\n setCurrentViewport: (viewport: MapViewState) => void;\n};\n\ntype PersistOptions = RequireAllOrNone<{\n getSavedViewport: (\n id: KeyCombinationId,\n uniqueIdentifier?: string,\n ) => MapViewState;\n setSavedViewport: (\n id: KeyCombinationId,\n viewport: MapViewState,\n uniqueIdentifier?: string,\n ) => void;\n}>;\n\nexport type SavedViewportOptions = Partial<HotkeyOptions> &\n BaseOptions &\n PersistOptions;\n\nexport const createSavedViewport = (\n options: SavedViewportOptions,\n): ReturnType<typeof registerHotkey> => {\n const setFn = options.setSavedViewport ?? persist;\n const getFn = options.getSavedViewport ?? retrieve;\n\n return registerHotkey({\n id: STORAGE_ID,\n heldThresholdMs: options.threshold,\n key: options.key ?? [\n {\n code: Keycode.Digit0,\n },\n {\n code: Keycode.Digit1,\n },\n {\n code: Keycode.Digit2,\n },\n {\n code: Keycode.Digit3,\n },\n {\n code: Keycode.Digit4,\n },\n {\n code: Keycode.Digit5,\n },\n {\n code: Keycode.Digit6,\n },\n {\n code: Keycode.Digit7,\n },\n {\n code: Keycode.Digit8,\n },\n {\n code: Keycode.Digit9,\n },\n ],\n onKeyHeld: (e: KeyboardEvent, key: KeyCombination) => {\n e.preventDefault();\n const viewport = options.getCurrentViewport();\n setFn(key.id, viewport, options.uniqueIdentifier);\n },\n onKeyUp: (e: KeyboardEvent, key: KeyCombination) => {\n e.preventDefault();\n const viewport = getFn(key.id, options.uniqueIdentifier);\n if (viewport) {\n options.setCurrentViewport(viewport);\n }\n },\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AA8CA,MAAa,uBACX,YACsC;CACtC,MAAM,QAAQ,QAAQ,oBAAoB;CAC1C,MAAM,QAAQ,QAAQ,oBAAoB;AAE1C,QAAO,eAAe;EACpB,IAAI;EACJ,iBAAiB,QAAQ;EACzB,KAAK,QAAQ,OAAO;GAClB,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACF;EACD,YAAY,GAAkB,QAAwB;AACpD,KAAE,gBAAgB;GAClB,MAAM,WAAW,QAAQ,oBAAoB;AAC7C,SAAM,IAAI,IAAI,UAAU,QAAQ,iBAAiB;;EAEnD,UAAU,GAAkB,QAAwB;AAClD,KAAE,gBAAgB;GAClB,MAAM,WAAW,MAAM,IAAI,IAAI,QAAQ,iBAAiB;AACxD,OAAI,SACF,SAAQ,mBAAmB,SAAS;;EAGzC,CAAC"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/deckgl/saved-viewports/index.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 {\n type HotkeyOptions,\n type KeyCombination,\n type KeyCombinationId,\n Keycode,\n registerHotkey,\n} from '@accelint/hotkey-manager';\nimport { persist, retrieve, STORAGE_ID } from './storage';\nimport type { MapViewState } from '@deck.gl/core';\nimport type { RequireAllOrNone } from 'type-fest';\n\ntype BaseOptions = {\n uniqueIdentifier?: string;\n threshold?: number;\n getCurrentViewport: () => MapViewState;\n setCurrentViewport: (viewport: MapViewState) => void;\n};\n\ntype PersistOptions = RequireAllOrNone<{\n getSavedViewport: (\n id: KeyCombinationId,\n uniqueIdentifier?: string,\n ) => MapViewState;\n setSavedViewport: (\n id: KeyCombinationId,\n viewport: MapViewState,\n uniqueIdentifier?: string,\n ) => void;\n}>;\n\nexport type SavedViewportOptions = Partial<HotkeyOptions> &\n BaseOptions &\n PersistOptions;\n\nexport const createSavedViewport = (\n options: SavedViewportOptions,\n): ReturnType<typeof registerHotkey> => {\n const setFn = options.setSavedViewport ?? persist;\n const getFn = options.getSavedViewport ?? retrieve;\n\n return registerHotkey({\n id: STORAGE_ID,\n heldThresholdMs: options.threshold,\n key: options.key ?? [\n {\n code: Keycode.Digit0,\n },\n {\n code: Keycode.Digit1,\n },\n {\n code: Keycode.Digit2,\n },\n {\n code: Keycode.Digit3,\n },\n {\n code: Keycode.Digit4,\n },\n {\n code: Keycode.Digit5,\n },\n {\n code: Keycode.Digit6,\n },\n {\n code: Keycode.Digit7,\n },\n {\n code: Keycode.Digit8,\n },\n {\n code: Keycode.Digit9,\n },\n ],\n onKeyHeld: (e: KeyboardEvent, key: KeyCombination) => {\n e.preventDefault();\n const viewport = options.getCurrentViewport();\n setFn(key.id, viewport, options.uniqueIdentifier);\n },\n onKeyUp: (e: KeyboardEvent, key: KeyCombination) => {\n e.preventDefault();\n const viewport = getFn(key.id, options.uniqueIdentifier);\n if (viewport) {\n options.setCurrentViewport(viewport);\n }\n },\n });\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AA8CA,MAAa,uBACX,YACsC;CACtC,MAAM,QAAQ,QAAQ,oBAAoB;CAC1C,MAAM,QAAQ,QAAQ,oBAAoB;AAE1C,QAAO,eAAe;EACpB,IAAI;EACJ,iBAAiB,QAAQ;EACzB,KAAK,QAAQ,OAAO;GAClB,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACD,EACE,MAAM,QAAQ,QACf;GACF;EACD,YAAY,GAAkB,QAAwB;AACpD,KAAE,gBAAgB;GAClB,MAAM,WAAW,QAAQ,oBAAoB;AAC7C,SAAM,IAAI,IAAI,UAAU,QAAQ,iBAAiB;;EAEnD,UAAU,GAAkB,QAAwB;AAClD,KAAE,gBAAgB;GAClB,MAAM,WAAW,MAAM,IAAI,IAAI,QAAQ,iBAAiB;AACxD,OAAI,SACF,SAAQ,mBAAmB,SAAS;;EAGzC,CAAC"}
@@ -0,0 +1,44 @@
1
+ //#region src/deckgl/shapes/display-shape-layer/constants.d.ts
2
+ /**
3
+ * Map interaction constants
4
+ * Values derived from ngc2 for consistency
5
+ */
6
+ declare const MAP_INTERACTION: {
7
+ readonly LINE_WIDTH_MIN_PIXELS: 1;
8
+ readonly ICON_SIZE: 38;
9
+ readonly ICON_HOVER_SIZE_INCREASE: 5;
10
+ };
11
+ /**
12
+ * Selection highlight configuration
13
+ */
14
+ declare const SELECTION_HIGHLIGHT: {
15
+ readonly COLOR: [number, number, number, number];
16
+ readonly ICON_SIZE_INCREASE: 8;
17
+ };
18
+ /**
19
+ * Coffin corners configuration for Point selection/hover feedback
20
+ * Coffin corners are bracket-like corners that appear around points
21
+ */
22
+ declare const COFFIN_CORNERS: {
23
+ /** Icon name for hover state (white corners with background fill) */
24
+ readonly HOVER_ICON: "coffin-corners-hover";
25
+ /** Icon name for selected state (blue corners, no fill) */
26
+ readonly SELECTED_ICON: "coffin-corners-selected";
27
+ /** Icon name for selected+hover state (blue corners with background fill) */
28
+ readonly SELECTED_HOVER_ICON: "coffin-corners-selected-hover";
29
+ /** Size of the coffin corners icon */
30
+ readonly SIZE: 38;
31
+ };
32
+ /**
33
+ * Default props for DisplayShapeLayer
34
+ */
35
+ declare const DEFAULT_DISPLAY_PROPS: {
36
+ pickable: boolean;
37
+ showLabels: boolean;
38
+ showHighlight: boolean;
39
+ applyBaseOpacity: boolean;
40
+ highlightColor: [number, number, number, number];
41
+ };
42
+ //#endregion
43
+ export { COFFIN_CORNERS, DEFAULT_DISPLAY_PROPS, MAP_INTERACTION, SELECTION_HIGHLIGHT };
44
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1,61 @@
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
+ 'use client';
15
+
16
+ //#region src/deckgl/shapes/display-shape-layer/constants.ts
17
+ /**
18
+ * Map interaction constants
19
+ * Values derived from ngc2 for consistency
20
+ */
21
+ const MAP_INTERACTION = {
22
+ LINE_WIDTH_MIN_PIXELS: 1,
23
+ ICON_SIZE: 38,
24
+ ICON_HOVER_SIZE_INCREASE: 5
25
+ };
26
+ /**
27
+ * Selection highlight configuration
28
+ */
29
+ const SELECTION_HIGHLIGHT = {
30
+ COLOR: [
31
+ 40,
32
+ 245,
33
+ 190,
34
+ 100
35
+ ],
36
+ ICON_SIZE_INCREASE: 8
37
+ };
38
+ /**
39
+ * Coffin corners configuration for Point selection/hover feedback
40
+ * Coffin corners are bracket-like corners that appear around points
41
+ */
42
+ const COFFIN_CORNERS = {
43
+ HOVER_ICON: "coffin-corners-hover",
44
+ SELECTED_ICON: "coffin-corners-selected",
45
+ SELECTED_HOVER_ICON: "coffin-corners-selected-hover",
46
+ SIZE: 38
47
+ };
48
+ /**
49
+ * Default props for DisplayShapeLayer
50
+ */
51
+ const DEFAULT_DISPLAY_PROPS = {
52
+ pickable: true,
53
+ showLabels: true,
54
+ showHighlight: false,
55
+ applyBaseOpacity: true,
56
+ highlightColor: SELECTION_HIGHLIGHT.COLOR
57
+ };
58
+
59
+ //#endregion
60
+ export { COFFIN_CORNERS, DEFAULT_DISPLAY_PROPS, MAP_INTERACTION, SELECTION_HIGHLIGHT };
61
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../../../src/deckgl/shapes/display-shape-layer/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'use client';\n\n/**\n * Map interaction constants\n * Values derived from ngc2 for consistency\n */\nexport const MAP_INTERACTION = {\n LINE_WIDTH_MIN_PIXELS: 1, // Minimum line width in pixels\n ICON_SIZE: 38, // Size of shape icons\n ICON_HOVER_SIZE_INCREASE: 5, // Additional pixels added on hover\n} as const;\n\n/**\n * Selection highlight configuration\n */\nexport const SELECTION_HIGHLIGHT = {\n COLOR: [40, 245, 190, 100] as [number, number, number, number], // Turquoise/cyan at ~39% opacity\n ICON_SIZE_INCREASE: 8, // Additional pixels for highlight icon\n} as const;\n\n/**\n * Coffin corners configuration for Point selection/hover feedback\n * Coffin corners are bracket-like corners that appear around points\n */\nexport const COFFIN_CORNERS = {\n /** Icon name for hover state (white corners with background fill) */\n HOVER_ICON: 'coffin-corners-hover',\n /** Icon name for selected state (blue corners, no fill) */\n SELECTED_ICON: 'coffin-corners-selected',\n /** Icon name for selected+hover state (blue corners with background fill) */\n SELECTED_HOVER_ICON: 'coffin-corners-selected-hover',\n /** Size of the coffin corners icon */\n SIZE: 38,\n} as const;\n\n/**\n * Default props for DisplayShapeLayer\n */\nexport const DEFAULT_DISPLAY_PROPS = {\n pickable: true,\n showLabels: true,\n showHighlight: false,\n applyBaseOpacity: true,\n highlightColor: SELECTION_HIGHLIGHT.COLOR,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAkBA,MAAa,kBAAkB;CAC7B,uBAAuB;CACvB,WAAW;CACX,0BAA0B;CAC3B;;;;AAKD,MAAa,sBAAsB;CACjC,OAAO;EAAC;EAAI;EAAK;EAAK;EAAI;CAC1B,oBAAoB;CACrB;;;;;AAMD,MAAa,iBAAiB;CAE5B,YAAY;CAEZ,eAAe;CAEf,qBAAqB;CAErB,MAAM;CACP;;;;AAKD,MAAa,wBAAwB;CACnC,UAAU;CACV,YAAY;CACZ,eAAe;CACf,kBAAkB;CAClB,gBAAgB,oBAAoB;CACrC"}