@accelint/map-toolkit 1.5.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/catalog-info.yaml +4 -4
  3. package/dist/camera/events.js +1 -1
  4. package/dist/camera/index.d.ts +1 -1
  5. package/dist/camera/index.js +1 -1
  6. package/dist/camera/store.d.ts +1 -1
  7. package/dist/camera/store.js +3 -5
  8. package/dist/camera/store.js.map +1 -1
  9. package/dist/camera/types.d.ts +1 -1
  10. package/dist/camera/types.js +1 -1
  11. package/dist/cursor-coordinates/constants.js +1 -1
  12. package/dist/cursor-coordinates/index.d.ts +1 -1
  13. package/dist/cursor-coordinates/index.js +1 -1
  14. package/dist/cursor-coordinates/store.d.ts +1 -1
  15. package/dist/cursor-coordinates/store.js +1 -1
  16. package/dist/cursor-coordinates/types.d.ts +1 -1
  17. package/dist/cursor-coordinates/types.js +1 -1
  18. package/dist/cursor-coordinates/use-cursor-coordinates.d.ts +1 -1
  19. package/dist/cursor-coordinates/use-cursor-coordinates.js +4 -9
  20. package/dist/cursor-coordinates/use-cursor-coordinates.js.map +1 -1
  21. package/dist/deckgl/base-map/constants.js +1 -1
  22. package/dist/deckgl/base-map/controls.d.ts +1 -1
  23. package/dist/deckgl/base-map/controls.js +1 -1
  24. package/dist/deckgl/base-map/events.js +1 -1
  25. package/dist/deckgl/base-map/index.d.ts +1 -1
  26. package/dist/deckgl/base-map/index.js +1 -1
  27. package/dist/deckgl/base-map/provider.d.ts +3 -3
  28. package/dist/deckgl/base-map/provider.js +1 -1
  29. package/dist/deckgl/base-map/types.d.ts +1 -1
  30. package/dist/deckgl/base-map/types.js +1 -1
  31. package/dist/deckgl/index.d.ts +4 -4
  32. package/dist/deckgl/index.js +1 -1
  33. package/dist/deckgl/saved-viewports/index.d.ts +1 -1
  34. package/dist/deckgl/saved-viewports/index.js +1 -1
  35. package/dist/deckgl/saved-viewports/storage.d.ts +1 -1
  36. package/dist/deckgl/saved-viewports/storage.js +5 -10
  37. package/dist/deckgl/saved-viewports/storage.js.map +1 -1
  38. package/dist/deckgl/shapes/display-shape-layer/constants.js +66 -13
  39. package/dist/deckgl/shapes/display-shape-layer/constants.js.map +1 -1
  40. package/dist/deckgl/shapes/display-shape-layer/fiber.d.ts +1 -1
  41. package/dist/deckgl/shapes/display-shape-layer/fiber.js +1 -1
  42. package/dist/deckgl/shapes/display-shape-layer/index.d.ts +74 -35
  43. package/dist/deckgl/shapes/display-shape-layer/index.js +381 -154
  44. package/dist/deckgl/shapes/display-shape-layer/index.js.map +1 -1
  45. package/dist/deckgl/shapes/display-shape-layer/shape-label-layer.js +1 -1
  46. package/dist/deckgl/shapes/display-shape-layer/store.js +1 -1
  47. package/dist/deckgl/shapes/display-shape-layer/types.d.ts +108 -19
  48. package/dist/deckgl/shapes/display-shape-layer/types.js +1 -1
  49. package/dist/deckgl/shapes/display-shape-layer/use-select-shape.d.ts +1 -1
  50. package/dist/deckgl/shapes/display-shape-layer/use-select-shape.js +1 -1
  51. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js +66 -36
  52. package/dist/deckgl/shapes/display-shape-layer/utils/display-style.js.map +1 -1
  53. package/dist/deckgl/shapes/display-shape-layer/utils/elevation.js +407 -0
  54. package/dist/deckgl/shapes/display-shape-layer/utils/elevation.js.map +1 -0
  55. package/dist/deckgl/shapes/display-shape-layer/utils/icon-config.js +151 -0
  56. package/dist/deckgl/shapes/display-shape-layer/utils/icon-config.js.map +1 -0
  57. package/dist/deckgl/shapes/display-shape-layer/utils/interaction.js +50 -0
  58. package/dist/deckgl/shapes/display-shape-layer/utils/interaction.js.map +1 -0
  59. package/dist/deckgl/shapes/display-shape-layer/utils/labels.d.ts +1 -1
  60. package/dist/deckgl/shapes/display-shape-layer/utils/labels.js +28 -39
  61. package/dist/deckgl/shapes/display-shape-layer/utils/labels.js.map +1 -1
  62. package/dist/deckgl/shapes/draw-shape-layer/constants.js +1 -1
  63. package/dist/deckgl/shapes/draw-shape-layer/events.d.ts +1 -1
  64. package/dist/deckgl/shapes/draw-shape-layer/events.js +1 -1
  65. package/dist/deckgl/shapes/draw-shape-layer/fiber.js +1 -1
  66. package/dist/deckgl/shapes/draw-shape-layer/index.d.ts +1 -1
  67. package/dist/deckgl/shapes/draw-shape-layer/index.js +4 -14
  68. package/dist/deckgl/shapes/draw-shape-layer/index.js.map +1 -1
  69. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js +2 -3
  70. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-circle-mode-with-tooltip.js.map +1 -1
  71. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-ellipse-mode-with-tooltip.js +1 -1
  72. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js +2 -19
  73. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-line-string-mode-with-tooltip.js.map +1 -1
  74. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js +2 -32
  75. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.js.map +1 -1
  76. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js +9 -10
  77. package/dist/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.js.map +1 -1
  78. package/dist/deckgl/shapes/draw-shape-layer/modes/index.js +2 -32
  79. package/dist/deckgl/shapes/draw-shape-layer/modes/index.js.map +1 -1
  80. package/dist/deckgl/shapes/draw-shape-layer/store.js +1 -1
  81. package/dist/deckgl/shapes/draw-shape-layer/types.d.ts +1 -1
  82. package/dist/deckgl/shapes/draw-shape-layer/types.js +1 -1
  83. package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.d.ts +1 -1
  84. package/dist/deckgl/shapes/draw-shape-layer/use-draw-shape.js +1 -1
  85. package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js +3 -8
  86. package/dist/deckgl/shapes/draw-shape-layer/utils/feature-conversion.js.map +1 -1
  87. package/dist/deckgl/shapes/edit-shape-layer/constants.js +17 -2
  88. package/dist/deckgl/shapes/edit-shape-layer/constants.js.map +1 -1
  89. package/dist/deckgl/shapes/edit-shape-layer/events.d.ts +1 -1
  90. package/dist/deckgl/shapes/edit-shape-layer/events.js +1 -1
  91. package/dist/deckgl/shapes/edit-shape-layer/fiber.d.ts +1 -1
  92. package/dist/deckgl/shapes/edit-shape-layer/fiber.js +1 -1
  93. package/dist/deckgl/shapes/edit-shape-layer/index.d.ts +5 -2
  94. package/dist/deckgl/shapes/edit-shape-layer/index.js +51 -20
  95. package/dist/deckgl/shapes/edit-shape-layer/index.js.map +1 -1
  96. package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js +4 -1
  97. package/dist/deckgl/shapes/edit-shape-layer/modes/base-transform-mode.js.map +1 -1
  98. package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js +1 -1
  99. package/dist/deckgl/shapes/edit-shape-layer/modes/bounding-transform-mode.js.map +1 -1
  100. package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js +1 -1
  101. package/dist/deckgl/shapes/edit-shape-layer/modes/circle-transform-mode.js.map +1 -1
  102. package/dist/deckgl/shapes/edit-shape-layer/modes/index.js +1 -1
  103. package/dist/deckgl/shapes/edit-shape-layer/modes/point-translate-mode.js +1 -1
  104. package/dist/deckgl/shapes/edit-shape-layer/modes/point-translate-mode.js.map +1 -1
  105. package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js +1 -1
  106. package/dist/deckgl/shapes/edit-shape-layer/modes/rotate-mode-with-snap.js.map +1 -1
  107. package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js +1 -1
  108. package/dist/deckgl/shapes/edit-shape-layer/modes/scale-mode-with-free-transform.js.map +1 -1
  109. package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js +1 -1
  110. package/dist/deckgl/shapes/edit-shape-layer/modes/vertex-transform-mode.js.map +1 -1
  111. package/dist/deckgl/shapes/edit-shape-layer/store.js +70 -12
  112. package/dist/deckgl/shapes/edit-shape-layer/store.js.map +1 -1
  113. package/dist/deckgl/shapes/edit-shape-layer/types.d.ts +14 -2
  114. package/dist/deckgl/shapes/edit-shape-layer/types.js +1 -1
  115. package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.d.ts +1 -1
  116. package/dist/deckgl/shapes/edit-shape-layer/use-edit-shape.js +1 -1
  117. package/dist/deckgl/shapes/index.d.ts +4 -4
  118. package/dist/deckgl/shapes/index.js +1 -1
  119. package/dist/deckgl/shapes/shared/constants.d.ts +4 -3
  120. package/dist/deckgl/shapes/shared/constants.js +50 -10
  121. package/dist/deckgl/shapes/shared/constants.js.map +1 -1
  122. package/dist/deckgl/shapes/shared/events.d.ts +5 -1
  123. package/dist/deckgl/shapes/shared/events.js +1 -1
  124. package/dist/deckgl/shapes/shared/events.js.map +1 -1
  125. package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js +19 -16
  126. package/dist/deckgl/shapes/shared/hooks/use-shift-zoom-disable.js.map +1 -1
  127. package/dist/deckgl/shapes/shared/types.d.ts +174 -53
  128. package/dist/deckgl/shapes/shared/types.js +155 -2
  129. package/dist/deckgl/shapes/shared/types.js.map +1 -1
  130. package/dist/deckgl/shapes/shared/utils/geometry-measurements.js +29 -24
  131. package/dist/deckgl/shapes/shared/utils/geometry-measurements.js.map +1 -1
  132. package/dist/deckgl/shapes/shared/utils/layer-config.js +8 -5
  133. package/dist/deckgl/shapes/shared/utils/layer-config.js.map +1 -1
  134. package/dist/deckgl/shapes/shared/utils/mode-utils.js +50 -20
  135. package/dist/deckgl/shapes/shared/utils/mode-utils.js.map +1 -1
  136. package/dist/deckgl/shapes/shared/utils/pick-filtering.js +22 -15
  137. package/dist/deckgl/shapes/shared/utils/pick-filtering.js.map +1 -1
  138. package/dist/deckgl/shapes/shared/utils/style-utils.d.ts +38 -14
  139. package/dist/deckgl/shapes/shared/utils/style-utils.js +43 -32
  140. package/dist/deckgl/shapes/shared/utils/style-utils.js.map +1 -1
  141. package/dist/deckgl/symbol-layer/fiber.d.ts +1 -1
  142. package/dist/deckgl/symbol-layer/fiber.js +1 -1
  143. package/dist/deckgl/symbol-layer/index.d.ts +1 -1
  144. package/dist/deckgl/symbol-layer/index.js +1 -1
  145. package/dist/deckgl/text-layer/character-sets.js +1 -1
  146. package/dist/deckgl/text-layer/default-settings.d.ts +1 -1
  147. package/dist/deckgl/text-layer/default-settings.js +1 -1
  148. package/dist/deckgl/text-layer/fiber.d.ts +1 -1
  149. package/dist/deckgl/text-layer/fiber.js +1 -1
  150. package/dist/deckgl/text-layer/index.d.ts +1 -1
  151. package/dist/deckgl/text-layer/index.js +1 -1
  152. package/dist/deckgl/text-settings.d.ts +3 -3
  153. package/dist/deckgl/text-settings.js +1 -1
  154. package/dist/map-cursor/events.js +1 -1
  155. package/dist/map-cursor/index.d.ts +1 -1
  156. package/dist/map-cursor/index.js +1 -1
  157. package/dist/map-cursor/store.d.ts +1 -1
  158. package/dist/map-cursor/store.js +1 -1
  159. package/dist/map-cursor/types.d.ts +1 -1
  160. package/dist/map-cursor/types.js +1 -1
  161. package/dist/map-cursor/use-map-cursor.d.ts +1 -1
  162. package/dist/map-cursor/use-map-cursor.js +1 -1
  163. package/dist/map-mode/events.js +1 -1
  164. package/dist/map-mode/index.d.ts +1 -1
  165. package/dist/map-mode/index.js +1 -1
  166. package/dist/map-mode/store.d.ts +1 -1
  167. package/dist/map-mode/store.js +3 -8
  168. package/dist/map-mode/store.js.map +1 -1
  169. package/dist/map-mode/types.d.ts +1 -1
  170. package/dist/map-mode/types.js +1 -1
  171. package/dist/map-mode/use-map-mode.d.ts +1 -1
  172. package/dist/map-mode/use-map-mode.js +1 -1
  173. package/dist/maplibre/hooks/use-maplibre.d.ts +1 -1
  174. package/dist/maplibre/hooks/use-maplibre.js +1 -1
  175. package/dist/maplibre/index.d.ts +1 -1
  176. package/dist/maplibre/index.js +1 -1
  177. package/dist/shared/cleanup.d.ts +1 -1
  178. package/dist/shared/cleanup.js +1 -1
  179. package/dist/shared/constants.js +1 -1
  180. package/dist/shared/create-map-store.d.ts +1 -1
  181. package/dist/shared/create-map-store.js +1 -1
  182. package/dist/shared/logger.js +31 -0
  183. package/dist/shared/logger.js.map +1 -0
  184. package/dist/shared/units.js +1 -1
  185. package/dist/viewport/index.d.ts +1 -1
  186. package/dist/viewport/index.js +1 -1
  187. package/dist/viewport/store.d.ts +1 -1
  188. package/dist/viewport/store.js +1 -1
  189. package/dist/viewport/types.d.ts +1 -1
  190. package/dist/viewport/types.js +1 -1
  191. package/dist/viewport/utils.d.ts +1 -1
  192. package/dist/viewport/utils.js +1 -1
  193. package/dist/viewport/viewport-size.d.ts +3 -3
  194. package/dist/viewport/viewport-size.js +1 -1
  195. package/package.json +22 -20
  196. package/dist/hotkey-manager/dist/react/use-hotkey.js +0 -39
  197. package/dist/hotkey-manager/dist/react/use-hotkey.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -29,9 +29,6 @@ import { DrawPolygonMode } from "@deck.gl-community/editable-layers";
29
29
  * 3. Click to add more vertices
30
30
  * 4. Double-click or click the starting point to close the polygon
31
31
  *
32
- * ## Double-Click Workaround
33
- * Includes a workaround for the double-click to finish issue in @deck.gl-community/editable-layers ~9.1.
34
- * This will be fixed in a future version (PR #225).
35
32
  *
36
33
  * @example
37
34
  * ```typescript
@@ -44,15 +41,12 @@ import { DrawPolygonMode } from "@deck.gl-community/editable-layers";
44
41
  var DrawPolygonModeWithTooltip = class extends DrawPolygonMode {
45
42
  /** Current tooltip state (null when not drawing) */
46
43
  tooltip = null;
47
- /** Cached mode props for double-click workaround */
48
- lastModeProps = null;
49
44
  /**
50
45
  * Finish drawing the polygon.
51
46
  *
52
47
  * Creates a Polygon geometry from the click sequence and emits an edit action.
53
48
  * Requires at least 3 points to create a valid polygon. Automatically closes
54
49
  * the polygon by adding the first point to the end of the coordinate ring.
55
- * Extracted to share between double-click workaround and parent class logic.
56
50
  *
57
51
  * @param props - Mode properties with onEdit callback
58
52
  */
@@ -66,33 +60,10 @@ var DrawPolygonModeWithTooltip = class extends DrawPolygonMode {
66
60
  };
67
61
  this.resetClickSequence();
68
62
  this.tooltip = null;
69
- this.lastModeProps = null;
70
63
  const editAction = this.getAddFeatureOrBooleanPolygonAction(polygonToAdd, props);
71
64
  if (editAction) props.onEdit(editAction);
72
65
  }
73
66
  /**
74
- * Handle double-click to finish drawing.
75
- * This is called externally via a DOM event listener as a workaround for
76
- * @deck.gl-community/editable-layers ~9.1 which doesn't register 'dblclick' in EVENT_TYPES.
77
- * @see https://github.com/visgl/deck.gl-community/pull/225
78
- */
79
- handleDoubleClick() {
80
- if (this.lastModeProps) this.finishDrawing(this.lastModeProps);
81
- }
82
- /**
83
- * Override handleClick to store props for double-click workaround.
84
- *
85
- * Caches the mode props so that the external double-click handler can
86
- * access them when finishing the drawing.
87
- *
88
- * @param event - Click event with map coordinates
89
- * @param props - Mode properties including onEdit callback
90
- */
91
- handleClick(event, props) {
92
- this.lastModeProps = props;
93
- super.handleClick(event, props);
94
- }
95
- /**
96
67
  * Handle pointer move events to update the tooltip with distance.
97
68
  *
98
69
  * Calculates the distance from the last clicked vertex to the current
@@ -110,10 +81,9 @@ var DrawPolygonModeWithTooltip = class extends DrawPolygonMode {
110
81
  }
111
82
  const { mapCoords } = event;
112
83
  const distanceUnits = props.modeConfig?.distanceUnits ?? DEFAULT_DISTANCE_UNITS;
113
- const lastPoint = clickSequence[clickSequence.length - 1];
114
84
  this.tooltip = {
115
85
  position: mapCoords,
116
- text: formatDistanceTooltip(distance(lastPoint, mapCoords, { units: distanceUnits }), getDistanceUnitAbbreviation(distanceUnits))
86
+ text: formatDistanceTooltip(distance(clickSequence.at(-1), mapCoords, { units: distanceUnits }), getDistanceUnitAbbreviation(distanceUnits))
117
87
  };
118
88
  }
119
89
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"draw-polygon-mode-with-tooltip.js","names":[],"sources":["../../../../../src/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n type ClickEvent,\n DrawPolygonMode,\n type FeatureCollection,\n type ModeProps,\n type PointerMoveEvent,\n type Tooltip,\n} from '@deck.gl-community/editable-layers';\nimport { type Coord, distance } from '@turf/turf';\nimport {\n DEFAULT_DISTANCE_UNITS,\n getDistanceUnitAbbreviation,\n} from '@/shared/units';\nimport { formatDistanceTooltip } from '../../shared/constants';\n\n/**\n * Extends DrawPolygonMode to display distance tooltip between points.\n *\n * Shows the distance from the last clicked point to the current cursor position\n * while drawing a polygon. The tooltip updates in real-time as the cursor moves.\n *\n * ## Drawing Flow\n * 1. Click to add first vertex\n * 2. Move cursor (tooltip shows distance from last vertex)\n * 3. Click to add more vertices\n * 4. Double-click or click the starting point to close the polygon\n *\n * ## Double-Click Workaround\n * Includes a workaround for the double-click to finish issue in @deck.gl-community/editable-layers ~9.1.\n * This will be fixed in a future version (PR #225).\n *\n * @example\n * ```typescript\n * import { DrawPolygonModeWithTooltip } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n *\n * // Used internally by DrawShapeLayer\n * const mode = new DrawPolygonModeWithTooltip();\n * ```\n */\nexport class DrawPolygonModeWithTooltip extends DrawPolygonMode {\n /** Current tooltip state (null when not drawing) */\n private tooltip: Tooltip | null = null;\n /** Cached mode props for double-click workaround */\n private lastModeProps: ModeProps<FeatureCollection> | null = null;\n\n /**\n * Finish drawing the polygon.\n *\n * Creates a Polygon geometry from the click sequence and emits an edit action.\n * Requires at least 3 points to create a valid polygon. Automatically closes\n * the polygon by adding the first point to the end of the coordinate ring.\n * Extracted to share between double-click workaround and parent class logic.\n *\n * @param props - Mode properties with onEdit callback\n */\n private finishDrawing(props: ModeProps<FeatureCollection>): void {\n const clickSequence = this.getClickSequence();\n const firstPoint = clickSequence[0];\n if (clickSequence.length <= 2 || !firstPoint) {\n return;\n }\n\n const polygonToAdd = {\n type: 'Polygon' as const,\n coordinates: [[...clickSequence, firstPoint]],\n };\n\n this.resetClickSequence();\n this.tooltip = null;\n this.lastModeProps = null;\n\n const editAction = this.getAddFeatureOrBooleanPolygonAction(\n polygonToAdd,\n props,\n );\n if (editAction) {\n props.onEdit(editAction);\n }\n }\n\n /**\n * Handle double-click to finish drawing.\n * This is called externally via a DOM event listener as a workaround for\n * @deck.gl-community/editable-layers ~9.1 which doesn't register 'dblclick' in EVENT_TYPES.\n * @see https://github.com/visgl/deck.gl-community/pull/225\n */\n handleDoubleClick(): void {\n if (this.lastModeProps) {\n this.finishDrawing(this.lastModeProps);\n }\n }\n\n /**\n * Override handleClick to store props for double-click workaround.\n *\n * Caches the mode props so that the external double-click handler can\n * access them when finishing the drawing.\n *\n * @param event - Click event with map coordinates\n * @param props - Mode properties including onEdit callback\n */\n override handleClick(\n event: ClickEvent,\n props: ModeProps<FeatureCollection>,\n ): void {\n // Store props so handleDoubleClick can access them\n this.lastModeProps = props;\n super.handleClick(event, props);\n }\n\n /**\n * Handle pointer move events to update the tooltip with distance.\n *\n * Calculates the distance from the last clicked vertex to the current\n * cursor position and displays it in the configured distance units.\n *\n * @param event - Pointer move event with cursor position\n * @param props - Mode properties including distance units configuration\n */\n override handlePointerMove(\n event: PointerMoveEvent,\n props: ModeProps<FeatureCollection>,\n ) {\n super.handlePointerMove(event, props);\n\n const clickSequence = this.getClickSequence();\n if (!clickSequence.length) {\n this.tooltip = null;\n return;\n }\n\n const { mapCoords } = event;\n const distanceUnits =\n props.modeConfig?.distanceUnits ?? DEFAULT_DISTANCE_UNITS;\n\n const lastPoint = clickSequence[clickSequence.length - 1] as Coord;\n const currentPoint = mapCoords as Coord;\n\n const dist = distance(lastPoint, currentPoint, { units: distanceUnits });\n const unitAbbrev = getDistanceUnitAbbreviation(distanceUnits);\n\n this.tooltip = {\n position: mapCoords,\n text: formatDistanceTooltip(dist, unitAbbrev),\n };\n }\n\n /**\n * Get the current tooltip array for rendering.\n *\n * @returns Array containing the tooltip if one is active, empty array otherwise\n */\n override getTooltips(): Tooltip[] {\n return this.tooltip ? [this.tooltip] : [];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,IAAa,6BAAb,cAAgD,gBAAgB;;CAE9D,AAAQ,UAA0B;;CAElC,AAAQ,gBAAqD;;;;;;;;;;;CAY7D,AAAQ,cAAc,OAA2C;EAC/D,MAAM,gBAAgB,KAAK,kBAAkB;EAC7C,MAAM,aAAa,cAAc;AACjC,MAAI,cAAc,UAAU,KAAK,CAAC,WAChC;EAGF,MAAM,eAAe;GACnB,MAAM;GACN,aAAa,CAAC,CAAC,GAAG,eAAe,WAAW,CAAC;GAC9C;AAED,OAAK,oBAAoB;AACzB,OAAK,UAAU;AACf,OAAK,gBAAgB;EAErB,MAAM,aAAa,KAAK,oCACtB,cACA,MACD;AACD,MAAI,WACF,OAAM,OAAO,WAAW;;;;;;;;CAU5B,oBAA0B;AACxB,MAAI,KAAK,cACP,MAAK,cAAc,KAAK,cAAc;;;;;;;;;;;CAa1C,AAAS,YACP,OACA,OACM;AAEN,OAAK,gBAAgB;AACrB,QAAM,YAAY,OAAO,MAAM;;;;;;;;;;;CAYjC,AAAS,kBACP,OACA,OACA;AACA,QAAM,kBAAkB,OAAO,MAAM;EAErC,MAAM,gBAAgB,KAAK,kBAAkB;AAC7C,MAAI,CAAC,cAAc,QAAQ;AACzB,QAAK,UAAU;AACf;;EAGF,MAAM,EAAE,cAAc;EACtB,MAAM,gBACJ,MAAM,YAAY,iBAAiB;EAErC,MAAM,YAAY,cAAc,cAAc,SAAS;AAMvD,OAAK,UAAU;GACb,UAAU;GACV,MAAM,sBALK,SAAS,WAFD,WAE0B,EAAE,OAAO,eAAe,CAAC,EACrD,4BAA4B,cAAc,CAId;GAC9C;;;;;;;CAQH,AAAS,cAAyB;AAChC,SAAO,KAAK,UAAU,CAAC,KAAK,QAAQ,GAAG,EAAE"}
1
+ {"version":3,"file":"draw-polygon-mode-with-tooltip.js","names":[],"sources":["../../../../../src/deckgl/shapes/draw-shape-layer/modes/draw-polygon-mode-with-tooltip.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n DrawPolygonMode,\n type FeatureCollection,\n type ModeProps,\n type PointerMoveEvent,\n type SimpleFeatureCollection,\n type Tooltip,\n} from '@deck.gl-community/editable-layers';\nimport { type Coord, distance } from '@turf/turf';\nimport {\n DEFAULT_DISTANCE_UNITS,\n getDistanceUnitAbbreviation,\n} from '@/shared/units';\nimport { formatDistanceTooltip } from '../../shared/constants';\n\n/**\n * Extends DrawPolygonMode to display distance tooltip between points.\n *\n * Shows the distance from the last clicked point to the current cursor position\n * while drawing a polygon. The tooltip updates in real-time as the cursor moves.\n *\n * ## Drawing Flow\n * 1. Click to add first vertex\n * 2. Move cursor (tooltip shows distance from last vertex)\n * 3. Click to add more vertices\n * 4. Double-click or click the starting point to close the polygon\n *\n *\n * @example\n * ```typescript\n * import { DrawPolygonModeWithTooltip } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n *\n * // Used internally by DrawShapeLayer\n * const mode = new DrawPolygonModeWithTooltip();\n * ```\n */\nexport class DrawPolygonModeWithTooltip extends DrawPolygonMode {\n /** Current tooltip state (null when not drawing) */\n private tooltip: Tooltip | null = null;\n\n /**\n * Finish drawing the polygon.\n *\n * Creates a Polygon geometry from the click sequence and emits an edit action.\n * Requires at least 3 points to create a valid polygon. Automatically closes\n * the polygon by adding the first point to the end of the coordinate ring.\n *\n * @param props - Mode properties with onEdit callback\n */\n override finishDrawing(props: ModeProps<SimpleFeatureCollection>): void {\n const clickSequence = this.getClickSequence();\n const firstPoint = clickSequence[0];\n if (clickSequence.length <= 2 || !firstPoint) {\n return;\n }\n\n const polygonToAdd = {\n type: 'Polygon' as const,\n coordinates: [[...clickSequence, firstPoint]],\n };\n\n this.resetClickSequence();\n this.tooltip = null;\n\n const editAction = this.getAddFeatureOrBooleanPolygonAction(\n polygonToAdd,\n props,\n );\n if (editAction) {\n props.onEdit(editAction);\n }\n }\n\n /**\n * Handle pointer move events to update the tooltip with distance.\n *\n * Calculates the distance from the last clicked vertex to the current\n * cursor position and displays it in the configured distance units.\n *\n * @param event - Pointer move event with cursor position\n * @param props - Mode properties including distance units configuration\n */\n override handlePointerMove(\n event: PointerMoveEvent,\n props: ModeProps<FeatureCollection>,\n ) {\n super.handlePointerMove(event, props);\n\n const clickSequence = this.getClickSequence();\n if (!clickSequence.length) {\n this.tooltip = null;\n return;\n }\n\n const { mapCoords } = event;\n const distanceUnits =\n props.modeConfig?.distanceUnits ?? DEFAULT_DISTANCE_UNITS;\n\n const lastPoint = clickSequence.at(-1) as Coord;\n const currentPoint = mapCoords as Coord;\n\n const dist = distance(lastPoint, currentPoint, { units: distanceUnits });\n const unitAbbrev = getDistanceUnitAbbreviation(distanceUnits);\n\n this.tooltip = {\n position: mapCoords,\n text: formatDistanceTooltip(dist, unitAbbrev),\n };\n }\n\n /**\n * Get the current tooltip array for rendering.\n *\n * @returns Array containing the tooltip if one is active, empty array otherwise\n */\n override getTooltips(): Tooltip[] {\n return this.tooltip ? [this.tooltip] : [];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,IAAa,6BAAb,cAAgD,gBAAgB;;CAE9D,AAAQ,UAA0B;;;;;;;;;;CAWlC,AAAS,cAAc,OAAiD;EACtE,MAAM,gBAAgB,KAAK,kBAAkB;EAC7C,MAAM,aAAa,cAAc;AACjC,MAAI,cAAc,UAAU,KAAK,CAAC,WAChC;EAGF,MAAM,eAAe;GACnB,MAAM;GACN,aAAa,CAAC,CAAC,GAAG,eAAe,WAAW,CAAC;GAC9C;AAED,OAAK,oBAAoB;AACzB,OAAK,UAAU;EAEf,MAAM,aAAa,KAAK,oCACtB,cACA,MACD;AACD,MAAI,WACF,OAAM,OAAO,WAAW;;;;;;;;;;;CAa5B,AAAS,kBACP,OACA,OACA;AACA,QAAM,kBAAkB,OAAO,MAAM;EAErC,MAAM,gBAAgB,KAAK,kBAAkB;AAC7C,MAAI,CAAC,cAAc,QAAQ;AACzB,QAAK,UAAU;AACf;;EAGF,MAAM,EAAE,cAAc;EACtB,MAAM,gBACJ,MAAM,YAAY,iBAAiB;AAQrC,OAAK,UAAU;GACb,UAAU;GACV,MAAM,sBALK,SAHK,cAAc,GAAG,GAAG,EACjB,WAE0B,EAAE,OAAO,eAAe,CAAC,EACrD,4BAA4B,cAAc,CAId;GAC9C;;;;;;;CAQH,AAAS,cAAyB;AAChC,SAAO,KAAK,UAAU,CAAC,KAAK,QAAQ,GAAG,EAAE"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -15,7 +15,7 @@ import { DEFAULT_DISTANCE_UNITS, getDistanceUnitAbbreviation } from "../../../..
15
15
  import { formatRectangleTooltip } from "../../shared/constants.js";
16
16
  import { area, bbox, bboxPolygon, convertArea, destination, distance } from "@turf/turf";
17
17
  import { DrawRectangleMode } from "@deck.gl-community/editable-layers";
18
- import { featureCollection, point as point$1 } from "@turf/helpers";
18
+ import { featureCollection, point } from "@turf/helpers";
19
19
 
20
20
  //#region src/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.ts
21
21
  /**
@@ -67,12 +67,12 @@ var DrawRectangleModeWithTooltip = class extends DrawRectangleMode {
67
67
  const lat1 = coord1[1] ?? 0;
68
68
  const lon2 = coord2[0] ?? 0;
69
69
  const lat2 = coord2[1] ?? 0;
70
- const horizontalDist = distance(point$1([lon1, lat1]), point$1([lon2, lat1]), { units: "kilometers" });
71
- const verticalDist = distance(point$1([lon1, lat1]), point$1([lon1, lat2]), { units: "kilometers" });
70
+ const horizontalDist = distance(point([lon1, lat1]), point([lon2, lat1]), { units: "kilometers" });
71
+ const verticalDist = distance(point([lon1, lat1]), point([lon1, lat2]), { units: "kilometers" });
72
72
  const maxDist = Math.max(horizontalDist, verticalDist);
73
73
  const lonSign = lon2 >= lon1 ? 1 : -1;
74
74
  const latSign = lat2 >= lat1 ? 1 : -1;
75
- finalCoord2 = destination(destination(point$1([lon1, lat1]), maxDist, lonSign > 0 ? 90 : 270, { units: "kilometers" }), maxDist, latSign > 0 ? 0 : 180, { units: "kilometers" }).geometry.coordinates;
75
+ finalCoord2 = destination(destination(point([lon1, lat1]), maxDist, lonSign > 0 ? 90 : 270, { units: "kilometers" }), maxDist, latSign > 0 ? 0 : 180, { units: "kilometers" }).geometry.coordinates;
76
76
  }
77
77
  return super.getTwoClickPolygon(coord1, finalCoord2, modeConfig);
78
78
  }
@@ -89,17 +89,16 @@ var DrawRectangleModeWithTooltip = class extends DrawRectangleMode {
89
89
  handlePointerMove(event, props) {
90
90
  this.isShiftPressed = event.sourceEvent?.shiftKey ?? false;
91
91
  super.handlePointerMove(event, props);
92
- const clickSequence = this.getClickSequence();
93
- const firstClick = clickSequence[clickSequence.length - 1];
92
+ const firstClick = this.getClickSequence().at(-1);
94
93
  if (!firstClick) {
95
94
  this.tooltip = null;
96
95
  return;
97
96
  }
98
97
  const { mapCoords } = event;
99
98
  const distanceUnits = props.modeConfig?.distanceUnits ?? DEFAULT_DISTANCE_UNITS;
100
- const firstClickPoint = point$1(firstClick);
101
- const currentPoint = point$1(mapCoords);
102
- const cornerPoint = point$1([firstClick[0], mapCoords[1]]);
99
+ const firstClickPoint = point(firstClick);
100
+ const currentPoint = point(mapCoords);
101
+ const cornerPoint = point([firstClick[0], mapCoords[1]]);
103
102
  this.tooltip = {
104
103
  position: mapCoords,
105
104
  text: formatRectangleTooltip(distance(firstClickPoint, cornerPoint, { units: distanceUnits }), distance(currentPoint, cornerPoint, { units: distanceUnits }), convertArea(area(bboxPolygon(bbox(featureCollection([firstClickPoint, currentPoint])))), "meters", distanceUnits), getDistanceUnitAbbreviation(distanceUnits))
@@ -1 +1 @@
1
- {"version":3,"file":"draw-rectangle-mode-with-tooltip.js","names":["point"],"sources":["../../../../../src/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n DrawRectangleMode,\n type FeatureCollection,\n type ModeProps,\n type PointerMoveEvent,\n type Tooltip,\n} from '@deck.gl-community/editable-layers';\nimport { featureCollection, point } from '@turf/helpers';\nimport {\n area,\n bbox,\n bboxPolygon,\n convertArea,\n destination,\n distance,\n} from '@turf/turf';\nimport {\n DEFAULT_DISTANCE_UNITS,\n getDistanceUnitAbbreviation,\n} from '@/shared/units';\nimport { formatRectangleTooltip } from '../../shared/constants';\nimport type { Position } from 'geojson';\n\n/**\n * Extends DrawRectangleMode to display dimensions and area tooltip.\n *\n * Shows the width, height, and total area of the rectangle being drawn.\n * The tooltip updates in real-time as the cursor moves, displaying measurements\n * in the configured distance units.\n *\n * ## Drawing Flow\n * 1. Click to set first corner\n * 2. Move cursor (tooltip shows dimensions and area)\n * 3. Click to set opposite corner and finish the rectangle\n *\n * ## Shift-to-Square Constraint\n * Hold Shift while drawing to constrain the rectangle to a square with equal sides.\n * Uses real-world distances (via Turf.js) to account for lat/lon distortion.\n *\n * @example\n * ```typescript\n * import { DrawRectangleModeWithTooltip } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n *\n * // Used internally by DrawShapeLayer\n * const mode = new DrawRectangleModeWithTooltip();\n * ```\n */\nexport class DrawRectangleModeWithTooltip extends DrawRectangleMode {\n /** Current tooltip state (null when not drawing) */\n private tooltip: Tooltip | null = null;\n /** Tracks whether Shift key is currently pressed for square constraint */\n private isShiftPressed = false;\n\n /**\n * Override getTwoClickPolygon to support Shift-constrained squares.\n *\n * When Shift is held, constrains the rectangle to a square by using the larger\n * of the horizontal or vertical distances as the side length. Uses real-world\n * geographic distances (via Turf.js) to account for lat/lon distortion at different\n * latitudes.\n *\n * @param coord1 - First corner coordinates [lon, lat]\n * @param coord2 - Second corner coordinates [lon, lat]\n * @param modeConfig - Mode configuration options\n * @returns Polygon geometry for the rectangle or square\n */\n override getTwoClickPolygon(\n coord1: Position,\n coord2: Position,\n modeConfig: ModeProps<FeatureCollection>['modeConfig'],\n ) {\n let finalCoord2 = coord2;\n\n // If Shift is pressed, constrain to a square using real distances\n if (this.isShiftPressed && coord1 && coord2) {\n const lon1 = coord1[0] ?? 0;\n const lat1 = coord1[1] ?? 0;\n const lon2 = coord2[0] ?? 0;\n const lat2 = coord2[1] ?? 0;\n\n // Calculate real-world distances using turf\n // Horizontal distance (along latitude)\n const horizontalDist = distance(\n point([lon1, lat1]),\n point([lon2, lat1]),\n {\n units: 'kilometers',\n },\n );\n // Vertical distance (along longitude)\n const verticalDist = distance(point([lon1, lat1]), point([lon1, lat2]), {\n units: 'kilometers',\n });\n\n // Use the larger distance for the square side\n const maxDist = Math.max(horizontalDist, verticalDist);\n\n // Determine direction signs\n const lonSign = lon2 >= lon1 ? 1 : -1;\n const latSign = lat2 >= lat1 ? 1 : -1;\n\n // Calculate new corner using destination() for accurate geographic positioning\n // Move horizontally from coord1\n const horizontalPoint = destination(\n point([lon1, lat1]),\n maxDist,\n lonSign > 0 ? 90 : 270,\n {\n units: 'kilometers',\n },\n );\n // Move vertically from that point\n const cornerPoint = destination(\n horizontalPoint,\n maxDist,\n latSign > 0 ? 0 : 180,\n {\n units: 'kilometers',\n },\n );\n\n finalCoord2 = cornerPoint.geometry.coordinates;\n }\n\n // Call parent implementation with potentially adjusted coordinates\n return super.getTwoClickPolygon(coord1, finalCoord2, modeConfig);\n }\n\n /**\n * Handle pointer move events to update the tooltip with rectangle measurements.\n *\n * Tracks the Shift key state for square constraint and calculates the width,\n * height, and area of the rectangle being drawn. Uses Turf.js for accurate\n * geographic distance and area calculations.\n *\n * @param event - Pointer move event with cursor position and source event\n * @param props - Mode properties including distance units configuration\n */\n override handlePointerMove(\n event: PointerMoveEvent,\n props: ModeProps<FeatureCollection>,\n ) {\n // Track shift key state from the source event\n const sourceEvent = event.sourceEvent as KeyboardEvent | undefined;\n this.isShiftPressed = sourceEvent?.shiftKey ?? false;\n\n super.handlePointerMove(event, props);\n\n const clickSequence = this.getClickSequence();\n const firstClick = clickSequence[clickSequence.length - 1];\n if (!firstClick) {\n this.tooltip = null;\n return;\n }\n\n const { mapCoords } = event;\n const distanceUnits =\n props.modeConfig?.distanceUnits ?? DEFAULT_DISTANCE_UNITS;\n\n const firstClickPoint = point(firstClick);\n const currentPoint = point(mapCoords);\n\n // Calculate dimensions by finding the corner point\n const cornerPoint = point([\n firstClick[0] as number,\n mapCoords[1] as number,\n ]);\n const dimension1 = distance(firstClickPoint, cornerPoint, {\n units: distanceUnits,\n });\n const dimension2 = distance(currentPoint, cornerPoint, {\n units: distanceUnits,\n });\n\n // Calculate area properly accounting for Earth's curvature\n const points = featureCollection([firstClickPoint, currentPoint]);\n const bboxPoly = bboxPolygon(bbox(points));\n const rectArea = area(bboxPoly);\n const convertedArea = convertArea(rectArea, 'meters', distanceUnits);\n const unitAbbrev = getDistanceUnitAbbreviation(distanceUnits);\n\n this.tooltip = {\n position: mapCoords,\n text: formatRectangleTooltip(\n dimension1,\n dimension2,\n convertedArea,\n unitAbbrev,\n ),\n };\n }\n\n /**\n * Get the current tooltip array for rendering.\n *\n * @returns Array containing the tooltip if one is active, empty array otherwise\n */\n override getTooltips(): Tooltip[] {\n return this.tooltip ? [this.tooltip] : [];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,IAAa,+BAAb,cAAkD,kBAAkB;;CAElE,AAAQ,UAA0B;;CAElC,AAAQ,iBAAiB;;;;;;;;;;;;;;CAezB,AAAS,mBACP,QACA,QACA,YACA;EACA,IAAI,cAAc;AAGlB,MAAI,KAAK,kBAAkB,UAAU,QAAQ;GAC3C,MAAM,OAAO,OAAO,MAAM;GAC1B,MAAM,OAAO,OAAO,MAAM;GAC1B,MAAM,OAAO,OAAO,MAAM;GAC1B,MAAM,OAAO,OAAO,MAAM;GAI1B,MAAM,iBAAiB,SACrBA,QAAM,CAAC,MAAM,KAAK,CAAC,EACnBA,QAAM,CAAC,MAAM,KAAK,CAAC,EACnB,EACE,OAAO,cACR,CACF;GAED,MAAM,eAAe,SAASA,QAAM,CAAC,MAAM,KAAK,CAAC,EAAEA,QAAM,CAAC,MAAM,KAAK,CAAC,EAAE,EACtE,OAAO,cACR,CAAC;GAGF,MAAM,UAAU,KAAK,IAAI,gBAAgB,aAAa;GAGtD,MAAM,UAAU,QAAQ,OAAO,IAAI;GACnC,MAAM,UAAU,QAAQ,OAAO,IAAI;AAsBnC,iBAToB,YATI,YACtBA,QAAM,CAAC,MAAM,KAAK,CAAC,EACnB,SACA,UAAU,IAAI,KAAK,KACnB,EACE,OAAO,cACR,CACF,EAIC,SACA,UAAU,IAAI,IAAI,KAClB,EACE,OAAO,cACR,CACF,CAEyB,SAAS;;AAIrC,SAAO,MAAM,mBAAmB,QAAQ,aAAa,WAAW;;;;;;;;;;;;CAalE,AAAS,kBACP,OACA,OACA;AAGA,OAAK,iBADe,MAAM,aACS,YAAY;AAE/C,QAAM,kBAAkB,OAAO,MAAM;EAErC,MAAM,gBAAgB,KAAK,kBAAkB;EAC7C,MAAM,aAAa,cAAc,cAAc,SAAS;AACxD,MAAI,CAAC,YAAY;AACf,QAAK,UAAU;AACf;;EAGF,MAAM,EAAE,cAAc;EACtB,MAAM,gBACJ,MAAM,YAAY,iBAAiB;EAErC,MAAM,kBAAkBA,QAAM,WAAW;EACzC,MAAM,eAAeA,QAAM,UAAU;EAGrC,MAAM,cAAcA,QAAM,CACxB,WAAW,IACX,UAAU,GACX,CAAC;AAeF,OAAK,UAAU;GACb,UAAU;GACV,MAAM,uBAhBW,SAAS,iBAAiB,aAAa,EACxD,OAAO,eACR,CAAC,EACiB,SAAS,cAAc,aAAa,EACrD,OAAO,eACR,CAAC,EAMoB,YADL,KADA,YAAY,KADd,kBAAkB,CAAC,iBAAiB,aAAa,CAAC,CACxB,CAAC,CACX,EACa,UAAU,cAAc,EACjD,4BAA4B,cAAc,CAS1D;GACF;;;;;;;CAQH,AAAS,cAAyB;AAChC,SAAO,KAAK,UAAU,CAAC,KAAK,QAAQ,GAAG,EAAE"}
1
+ {"version":3,"file":"draw-rectangle-mode-with-tooltip.js","names":[],"sources":["../../../../../src/deckgl/shapes/draw-shape-layer/modes/draw-rectangle-mode-with-tooltip.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n DrawRectangleMode,\n type FeatureCollection,\n type ModeProps,\n type PointerMoveEvent,\n type Tooltip,\n} from '@deck.gl-community/editable-layers';\nimport { featureCollection, point } from '@turf/helpers';\nimport {\n area,\n bbox,\n bboxPolygon,\n convertArea,\n destination,\n distance,\n} from '@turf/turf';\nimport {\n DEFAULT_DISTANCE_UNITS,\n getDistanceUnitAbbreviation,\n} from '@/shared/units';\nimport { formatRectangleTooltip } from '../../shared/constants';\nimport type { Position } from 'geojson';\n\n/**\n * Extends DrawRectangleMode to display dimensions and area tooltip.\n *\n * Shows the width, height, and total area of the rectangle being drawn.\n * The tooltip updates in real-time as the cursor moves, displaying measurements\n * in the configured distance units.\n *\n * ## Drawing Flow\n * 1. Click to set first corner\n * 2. Move cursor (tooltip shows dimensions and area)\n * 3. Click to set opposite corner and finish the rectangle\n *\n * ## Shift-to-Square Constraint\n * Hold Shift while drawing to constrain the rectangle to a square with equal sides.\n * Uses real-world distances (via Turf.js) to account for lat/lon distortion.\n *\n * @example\n * ```typescript\n * import { DrawRectangleModeWithTooltip } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n *\n * // Used internally by DrawShapeLayer\n * const mode = new DrawRectangleModeWithTooltip();\n * ```\n */\nexport class DrawRectangleModeWithTooltip extends DrawRectangleMode {\n /** Current tooltip state (null when not drawing) */\n private tooltip: Tooltip | null = null;\n /** Tracks whether Shift key is currently pressed for square constraint */\n private isShiftPressed = false;\n\n /**\n * Override getTwoClickPolygon to support Shift-constrained squares.\n *\n * When Shift is held, constrains the rectangle to a square by using the larger\n * of the horizontal or vertical distances as the side length. Uses real-world\n * geographic distances (via Turf.js) to account for lat/lon distortion at different\n * latitudes.\n *\n * @param coord1 - First corner coordinates [lon, lat]\n * @param coord2 - Second corner coordinates [lon, lat]\n * @param modeConfig - Mode configuration options\n * @returns Polygon geometry for the rectangle or square\n */\n override getTwoClickPolygon(\n coord1: Position,\n coord2: Position,\n modeConfig: ModeProps<FeatureCollection>['modeConfig'],\n ) {\n let finalCoord2 = coord2;\n\n // If Shift is pressed, constrain to a square using real distances\n if (this.isShiftPressed && coord1 && coord2) {\n const lon1 = coord1[0] ?? 0;\n const lat1 = coord1[1] ?? 0;\n const lon2 = coord2[0] ?? 0;\n const lat2 = coord2[1] ?? 0;\n\n // Calculate real-world distances using turf\n // Horizontal distance (along latitude)\n const horizontalDist = distance(\n point([lon1, lat1]),\n point([lon2, lat1]),\n {\n units: 'kilometers',\n },\n );\n // Vertical distance (along longitude)\n const verticalDist = distance(point([lon1, lat1]), point([lon1, lat2]), {\n units: 'kilometers',\n });\n\n // Use the larger distance for the square side\n const maxDist = Math.max(horizontalDist, verticalDist);\n\n // Determine direction signs\n const lonSign = lon2 >= lon1 ? 1 : -1;\n const latSign = lat2 >= lat1 ? 1 : -1;\n\n // Calculate new corner using destination() for accurate geographic positioning\n // Move horizontally from coord1\n const horizontalPoint = destination(\n point([lon1, lat1]),\n maxDist,\n lonSign > 0 ? 90 : 270,\n {\n units: 'kilometers',\n },\n );\n // Move vertically from that point\n const cornerPoint = destination(\n horizontalPoint,\n maxDist,\n latSign > 0 ? 0 : 180,\n {\n units: 'kilometers',\n },\n );\n\n finalCoord2 = cornerPoint.geometry.coordinates;\n }\n\n // Call parent implementation with potentially adjusted coordinates\n return super.getTwoClickPolygon(coord1, finalCoord2, modeConfig);\n }\n\n /**\n * Handle pointer move events to update the tooltip with rectangle measurements.\n *\n * Tracks the Shift key state for square constraint and calculates the width,\n * height, and area of the rectangle being drawn. Uses Turf.js for accurate\n * geographic distance and area calculations.\n *\n * @param event - Pointer move event with cursor position and source event\n * @param props - Mode properties including distance units configuration\n */\n override handlePointerMove(\n event: PointerMoveEvent,\n props: ModeProps<FeatureCollection>,\n ) {\n // Track shift key state from the source event\n const sourceEvent = event.sourceEvent as KeyboardEvent | undefined;\n this.isShiftPressed = sourceEvent?.shiftKey ?? false;\n\n super.handlePointerMove(event, props);\n\n const clickSequence = this.getClickSequence();\n const firstClick = clickSequence.at(-1);\n if (!firstClick) {\n this.tooltip = null;\n return;\n }\n\n const { mapCoords } = event;\n const distanceUnits =\n props.modeConfig?.distanceUnits ?? DEFAULT_DISTANCE_UNITS;\n\n const firstClickPoint = point(firstClick);\n const currentPoint = point(mapCoords);\n\n // Calculate dimensions by finding the corner point\n const cornerPoint = point([\n firstClick[0] as number,\n mapCoords[1] as number,\n ]);\n const dimension1 = distance(firstClickPoint, cornerPoint, {\n units: distanceUnits,\n });\n const dimension2 = distance(currentPoint, cornerPoint, {\n units: distanceUnits,\n });\n\n // Calculate area properly accounting for Earth's curvature\n const points = featureCollection([firstClickPoint, currentPoint]);\n const bboxPoly = bboxPolygon(bbox(points));\n const rectArea = area(bboxPoly);\n const convertedArea = convertArea(rectArea, 'meters', distanceUnits);\n const unitAbbrev = getDistanceUnitAbbreviation(distanceUnits);\n\n this.tooltip = {\n position: mapCoords,\n text: formatRectangleTooltip(\n dimension1,\n dimension2,\n convertedArea,\n unitAbbrev,\n ),\n };\n }\n\n /**\n * Get the current tooltip array for rendering.\n *\n * @returns Array containing the tooltip if one is active, empty array otherwise\n */\n override getTooltips(): Tooltip[] {\n return this.tooltip ? [this.tooltip] : [];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,IAAa,+BAAb,cAAkD,kBAAkB;;CAElE,AAAQ,UAA0B;;CAElC,AAAQ,iBAAiB;;;;;;;;;;;;;;CAezB,AAAS,mBACP,QACA,QACA,YACA;EACA,IAAI,cAAc;AAGlB,MAAI,KAAK,kBAAkB,UAAU,QAAQ;GAC3C,MAAM,OAAO,OAAO,MAAM;GAC1B,MAAM,OAAO,OAAO,MAAM;GAC1B,MAAM,OAAO,OAAO,MAAM;GAC1B,MAAM,OAAO,OAAO,MAAM;GAI1B,MAAM,iBAAiB,SACrB,MAAM,CAAC,MAAM,KAAK,CAAC,EACnB,MAAM,CAAC,MAAM,KAAK,CAAC,EACnB,EACE,OAAO,cACR,CACF;GAED,MAAM,eAAe,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,EACtE,OAAO,cACR,CAAC;GAGF,MAAM,UAAU,KAAK,IAAI,gBAAgB,aAAa;GAGtD,MAAM,UAAU,QAAQ,OAAO,IAAI;GACnC,MAAM,UAAU,QAAQ,OAAO,IAAI;AAsBnC,iBAToB,YATI,YACtB,MAAM,CAAC,MAAM,KAAK,CAAC,EACnB,SACA,UAAU,IAAI,KAAK,KACnB,EACE,OAAO,cACR,CACF,EAIC,SACA,UAAU,IAAI,IAAI,KAClB,EACE,OAAO,cACR,CACF,CAEyB,SAAS;;AAIrC,SAAO,MAAM,mBAAmB,QAAQ,aAAa,WAAW;;;;;;;;;;;;CAalE,AAAS,kBACP,OACA,OACA;AAGA,OAAK,iBADe,MAAM,aACS,YAAY;AAE/C,QAAM,kBAAkB,OAAO,MAAM;EAGrC,MAAM,aADgB,KAAK,kBAAkB,CACZ,GAAG,GAAG;AACvC,MAAI,CAAC,YAAY;AACf,QAAK,UAAU;AACf;;EAGF,MAAM,EAAE,cAAc;EACtB,MAAM,gBACJ,MAAM,YAAY,iBAAiB;EAErC,MAAM,kBAAkB,MAAM,WAAW;EACzC,MAAM,eAAe,MAAM,UAAU;EAGrC,MAAM,cAAc,MAAM,CACxB,WAAW,IACX,UAAU,GACX,CAAC;AAeF,OAAK,UAAU;GACb,UAAU;GACV,MAAM,uBAhBW,SAAS,iBAAiB,aAAa,EACxD,OAAO,eACR,CAAC,EACiB,SAAS,cAAc,aAAa,EACrD,OAAO,eACR,CAAC,EAMoB,YADL,KADA,YAAY,KADd,kBAAkB,CAAC,iBAAiB,aAAa,CAAC,CACxB,CAAC,CACX,EACa,UAAU,cAAc,EACjD,4BAA4B,cAAc,CAS1D;GACF;;;;;;;CAQH,AAAS,cAAyB;AAChC,SAAO,KAAK,UAAU,CAAC,KAAK,QAAQ,GAAG,EAAE"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -64,37 +64,7 @@ const MODE_INSTANCES = {
64
64
  function getModeInstance(shapeType) {
65
65
  return MODE_INSTANCES[shapeType];
66
66
  }
67
- /**
68
- * Trigger double-click finish on the active drawing mode.
69
- *
70
- * This is a workaround for @deck.gl-community/editable-layers ~9.1 which doesn't
71
- * register 'dblclick' in EVENT_TYPES. We listen for dblclick at the DOM level
72
- * and call this function to finish drawing.
73
- *
74
- * Only LineString and Polygon modes support double-click to finish. Other shape
75
- * types are completed with a single click and ignore this call.
76
- *
77
- * @param shapeType - The shape type currently being drawn
78
- * @see https://github.com/visgl/deck.gl-community/pull/225
79
- *
80
- * @example
81
- * ```typescript
82
- * import { triggerDoubleClickFinish } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';
83
- * import { ShapeFeatureType } from '@accelint/map-toolkit/deckgl/shapes/shared/types';
84
- *
85
- * // Listen for double-click at the DOM level
86
- * mapContainer.addEventListener('dblclick', () => {
87
- * if (currentShapeType === ShapeFeatureType.Polygon) {
88
- * triggerDoubleClickFinish(currentShapeType);
89
- * }
90
- * });
91
- * ```
92
- */
93
- function triggerDoubleClickFinish(shapeType) {
94
- const mode = MODE_INSTANCES[shapeType];
95
- if (mode instanceof DrawPolygonModeWithTooltip || mode instanceof DrawLineStringModeWithTooltip) mode.handleDoubleClick();
96
- }
97
67
 
98
68
  //#endregion
99
- export { getModeInstance, triggerDoubleClickFinish };
69
+ export { getModeInstance };
100
70
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/deckgl/shapes/draw-shape-layer/modes/index.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { DrawPointMode, ViewMode } from '@deck.gl-community/editable-layers';\nimport { ShapeFeatureType } from '../../shared/types';\nimport { DrawCircleModeWithTooltip } from './draw-circle-mode-with-tooltip';\nimport { DrawEllipseModeWithTooltip } from './draw-ellipse-mode-with-tooltip';\nimport { DrawLineStringModeWithTooltip } from './draw-line-string-mode-with-tooltip';\nimport { DrawPolygonModeWithTooltip } from './draw-polygon-mode-with-tooltip';\nimport { DrawRectangleModeWithTooltip } from './draw-rectangle-mode-with-tooltip';\n\nexport { DrawCircleModeWithTooltip } from './draw-circle-mode-with-tooltip';\nexport { DrawEllipseModeWithTooltip } from './draw-ellipse-mode-with-tooltip';\nexport { DrawLineStringModeWithTooltip } from './draw-line-string-mode-with-tooltip';\nexport { DrawPolygonModeWithTooltip } from './draw-polygon-mode-with-tooltip';\nexport { DrawRectangleModeWithTooltip } from './draw-rectangle-mode-with-tooltip';\n\n/**\n * Cached mode instances.\n *\n * CRITICAL: Mode instances must be cached at module level to prevent\n * deck.gl assertion failures. Creating new mode instances on each render\n * causes the EditableGeoJsonLayer to fail with assertion errors.\n */\nconst MODE_INSTANCES = {\n [ShapeFeatureType.Point]: new DrawPointMode(),\n [ShapeFeatureType.LineString]: new DrawLineStringModeWithTooltip(),\n [ShapeFeatureType.Polygon]: new DrawPolygonModeWithTooltip(),\n [ShapeFeatureType.Rectangle]: new DrawRectangleModeWithTooltip(),\n [ShapeFeatureType.Circle]: new DrawCircleModeWithTooltip(),\n [ShapeFeatureType.Ellipse]: new DrawEllipseModeWithTooltip(),\n view: new ViewMode(),\n};\n\n/**\n * Get the cached mode instance for a shape type.\n *\n * Returns the pre-instantiated drawing mode for the specified shape type.\n * Modes are cached at module level to prevent deck.gl assertion failures\n * that occur when creating new mode instances on each render.\n *\n * @param shapeType - The shape type to get the mode for\n * @returns The cached mode instance for drawing that shape type\n *\n * @example\n * ```typescript\n * import { getModeInstance } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n * import { ShapeFeatureType } from '@accelint/map-toolkit/deckgl/shapes/shared/types';\n *\n * // Get the mode for drawing circles\n * const circleMode = getModeInstance(ShapeFeatureType.Circle);\n *\n * // Use with EditableGeoJsonLayer\n * const layer = new EditableGeoJsonLayer({\n * mode: circleMode,\n * // ... other props\n * });\n * ```\n */\nexport function getModeInstance(\n shapeType: ShapeFeatureType,\n): (typeof MODE_INSTANCES)[ShapeFeatureType] {\n return MODE_INSTANCES[shapeType];\n}\n\n/**\n * Get the view mode instance (for when not drawing).\n *\n * Returns the pre-instantiated ViewMode which is the default mode when\n * no drawing operation is active. This mode allows viewing and interacting\n * with the map without drawing new shapes.\n *\n * @returns The cached ViewMode instance\n *\n * @example\n * ```typescript\n * import { getViewModeInstance } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n *\n * // Get the view mode (default when not drawing)\n * const viewMode = getViewModeInstance();\n *\n * // Use with EditableGeoJsonLayer\n * const layer = new EditableGeoJsonLayer({\n * mode: viewMode,\n * // ... other props\n * });\n * ```\n */\nexport function getViewModeInstance(): ViewMode {\n return MODE_INSTANCES.view;\n}\n\n/**\n * Trigger double-click finish on the active drawing mode.\n *\n * This is a workaround for @deck.gl-community/editable-layers ~9.1 which doesn't\n * register 'dblclick' in EVENT_TYPES. We listen for dblclick at the DOM level\n * and call this function to finish drawing.\n *\n * Only LineString and Polygon modes support double-click to finish. Other shape\n * types are completed with a single click and ignore this call.\n *\n * @param shapeType - The shape type currently being drawn\n * @see https://github.com/visgl/deck.gl-community/pull/225\n *\n * @example\n * ```typescript\n * import { triggerDoubleClickFinish } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n * import { ShapeFeatureType } from '@accelint/map-toolkit/deckgl/shapes/shared/types';\n *\n * // Listen for double-click at the DOM level\n * mapContainer.addEventListener('dblclick', () => {\n * if (currentShapeType === ShapeFeatureType.Polygon) {\n * triggerDoubleClickFinish(currentShapeType);\n * }\n * });\n * ```\n */\nexport function triggerDoubleClickFinish(shapeType: ShapeFeatureType): void {\n const mode = MODE_INSTANCES[shapeType];\n\n // Only Polygon and LineString modes support double-click to finish\n if (\n mode instanceof DrawPolygonModeWithTooltip ||\n mode instanceof DrawLineStringModeWithTooltip\n ) {\n mode.handleDoubleClick();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAM,iBAAiB;EACpB,iBAAiB,QAAQ,IAAI,eAAe;EAC5C,iBAAiB,aAAa,IAAI,+BAA+B;EACjE,iBAAiB,UAAU,IAAI,4BAA4B;EAC3D,iBAAiB,YAAY,IAAI,8BAA8B;EAC/D,iBAAiB,SAAS,IAAI,2BAA2B;EACzD,iBAAiB,UAAU,IAAI,4BAA4B;CAC5D,MAAM,IAAI,UAAU;CACrB;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BD,SAAgB,gBACd,WAC2C;AAC3C,QAAO,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDxB,SAAgB,yBAAyB,WAAmC;CAC1E,MAAM,OAAO,eAAe;AAG5B,KACE,gBAAgB,8BAChB,gBAAgB,8BAEhB,MAAK,mBAAmB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../../src/deckgl/shapes/draw-shape-layer/modes/index.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { DrawPointMode, ViewMode } from '@deck.gl-community/editable-layers';\nimport { ShapeFeatureType } from '../../shared/types';\nimport { DrawCircleModeWithTooltip } from './draw-circle-mode-with-tooltip';\nimport { DrawEllipseModeWithTooltip } from './draw-ellipse-mode-with-tooltip';\nimport { DrawLineStringModeWithTooltip } from './draw-line-string-mode-with-tooltip';\nimport { DrawPolygonModeWithTooltip } from './draw-polygon-mode-with-tooltip';\nimport { DrawRectangleModeWithTooltip } from './draw-rectangle-mode-with-tooltip';\n\nexport { DrawCircleModeWithTooltip } from './draw-circle-mode-with-tooltip';\nexport { DrawEllipseModeWithTooltip } from './draw-ellipse-mode-with-tooltip';\nexport { DrawLineStringModeWithTooltip } from './draw-line-string-mode-with-tooltip';\nexport { DrawPolygonModeWithTooltip } from './draw-polygon-mode-with-tooltip';\nexport { DrawRectangleModeWithTooltip } from './draw-rectangle-mode-with-tooltip';\n\n/**\n * Cached mode instances.\n *\n * CRITICAL: Mode instances must be cached at module level to prevent\n * deck.gl assertion failures. Creating new mode instances on each render\n * causes the EditableGeoJsonLayer to fail with assertion errors.\n */\nconst MODE_INSTANCES = {\n [ShapeFeatureType.Point]: new DrawPointMode(),\n [ShapeFeatureType.LineString]: new DrawLineStringModeWithTooltip(),\n [ShapeFeatureType.Polygon]: new DrawPolygonModeWithTooltip(),\n [ShapeFeatureType.Rectangle]: new DrawRectangleModeWithTooltip(),\n [ShapeFeatureType.Circle]: new DrawCircleModeWithTooltip(),\n [ShapeFeatureType.Ellipse]: new DrawEllipseModeWithTooltip(),\n view: new ViewMode(),\n};\n\n/**\n * Get the cached mode instance for a shape type.\n *\n * Returns the pre-instantiated drawing mode for the specified shape type.\n * Modes are cached at module level to prevent deck.gl assertion failures\n * that occur when creating new mode instances on each render.\n *\n * @param shapeType - The shape type to get the mode for\n * @returns The cached mode instance for drawing that shape type\n *\n * @example\n * ```typescript\n * import { getModeInstance } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n * import { ShapeFeatureType } from '@accelint/map-toolkit/deckgl/shapes/shared/types';\n *\n * // Get the mode for drawing circles\n * const circleMode = getModeInstance(ShapeFeatureType.Circle);\n *\n * // Use with EditableGeoJsonLayer\n * const layer = new EditableGeoJsonLayer({\n * mode: circleMode,\n * // ... other props\n * });\n * ```\n */\nexport function getModeInstance(\n shapeType: ShapeFeatureType,\n): (typeof MODE_INSTANCES)[ShapeFeatureType] {\n return MODE_INSTANCES[shapeType];\n}\n\n/**\n * Get the view mode instance (for when not drawing).\n *\n * Returns the pre-instantiated ViewMode which is the default mode when\n * no drawing operation is active. This mode allows viewing and interacting\n * with the map without drawing new shapes.\n *\n * @returns The cached ViewMode instance\n *\n * @example\n * ```typescript\n * import { getViewModeInstance } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/modes';\n *\n * // Get the view mode (default when not drawing)\n * const viewMode = getViewModeInstance();\n *\n * // Use with EditableGeoJsonLayer\n * const layer = new EditableGeoJsonLayer({\n * mode: viewMode,\n * // ... other props\n * });\n * ```\n */\nexport function getViewModeInstance(): ViewMode {\n return MODE_INSTANCES.view;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAM,iBAAiB;EACpB,iBAAiB,QAAQ,IAAI,eAAe;EAC5C,iBAAiB,aAAa,IAAI,+BAA+B;EACjE,iBAAiB,UAAU,IAAI,4BAA4B;EAC3D,iBAAiB,YAAY,IAAI,8BAA8B;EAC/D,iBAAiB,SAAS,IAAI,2BAA2B;EACzD,iBAAiB,UAAU,IAAI,4BAA4B;CAC5D,MAAM,IAAI,UAAU;CACrB;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BD,SAAgB,gBACd,WAC2C;AAC3C,QAAO,eAAe"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -13,20 +13,15 @@
13
13
 
14
14
  'use client';
15
15
 
16
+ import { createLoggerDomain } from "../../../../shared/logger.js";
16
17
  import { ShapeFeatureType } from "../../shared/types.js";
17
18
  import { DEFAULT_DISTANCE_UNITS } from "../../../../shared/units.js";
18
19
  import { DEFAULT_STYLE_PROPERTIES } from "../../shared/constants.js";
19
- import { getLogger } from "@accelint/logger";
20
20
  import { uuid } from "@accelint/core";
21
21
  import { centroid, distance } from "@turf/turf";
22
22
 
23
23
  //#region src/deckgl/shapes/draw-shape-layer/utils/feature-conversion.ts
24
- const logger = getLogger({
25
- enabled: process.env.NODE_ENV !== "production",
26
- level: "warn",
27
- prefix: "[FeatureConversion]",
28
- pretty: true
29
- });
24
+ const logger = createLoggerDomain("[FeatureConversion]");
30
25
  /**
31
26
  * Generate a default name for a shape based on its type.
32
27
  *
@@ -1 +1 @@
1
- {"version":3,"file":"feature-conversion.js","names":["styleProperties: StyleProperties","circleProperties: CircleProperties | undefined","ShapeFeatureTypeEnum","ellipseProperties: EllipseProperties | undefined"],"sources":["../../../../../src/deckgl/shapes/draw-shape-layer/utils/feature-conversion.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport { uuid } from '@accelint/core';\nimport { getLogger } from '@accelint/logger';\nimport { centroid, distance } from '@turf/turf';\nimport { DEFAULT_DISTANCE_UNITS } from '@/shared/units';\nimport { DEFAULT_STYLE_PROPERTIES } from '../../shared/constants';\nimport {\n type CircleProperties,\n type EllipseProperties,\n type Shape,\n type ShapeFeature,\n type ShapeFeatureType,\n ShapeFeatureType as ShapeFeatureTypeEnum,\n type StyleProperties,\n} from '../../shared/types';\nimport type { Feature, Polygon, Position } from 'geojson';\n\nconst logger = getLogger({\n enabled: process.env.NODE_ENV !== 'production',\n level: 'warn',\n prefix: '[FeatureConversion]',\n pretty: true,\n});\n\n/**\n * Generate a default name for a shape based on its type.\n *\n * Creates a name in the format \"New {ShapeType} (HH:MM:SS AM/PM)\" using the\n * current time. This provides a default name for shapes created through the\n * drawing interface that includes a timestamp for uniqueness.\n *\n * @param shape - The shape type to generate a name for\n * @returns A formatted name string with timestamp\n *\n * @example\n * ```typescript\n * import { generateShapeName } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/utils/feature-conversion';\n * import { ShapeFeatureType } from '@accelint/map-toolkit/deckgl/shapes/shared/types';\n *\n * const name = generateShapeName(ShapeFeatureType.Polygon);\n * // Returns: \"New Polygon (2:30:45 PM)\"\n * ```\n */\nfunction generateShapeName(shape: ShapeFeatureType): string {\n const timestamp = new Date().toLocaleTimeString();\n return `New ${shape} (${timestamp})`;\n}\n\n/**\n * Compute circle properties from a polygon geometry (circle approximation).\n *\n * The EditableGeoJsonLayer creates circles as polygon approximations with multiple\n * vertices arranged in a circular pattern. This function extracts the original circle's\n * center and radius from that polygon approximation.\n *\n * The center is calculated using Turf's centroid function, and the radius is computed\n * as the distance from the center to the first edge point.\n *\n * @param geometry - Polygon geometry representing a circle approximation\n * @returns Circle properties with center and radius, or undefined if computation fails\n *\n * @example\n * ```typescript\n * import { computeCircleProperties } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/utils/feature-conversion';\n * import type { Polygon } from 'geojson';\n *\n * const polygonGeometry: Polygon = {\n * type: 'Polygon',\n * coordinates: [[\n * [-122.4, 37.8],\n * [-122.39, 37.81],\n * // ... more points forming a circle\n * [-122.4, 37.8], // closing point\n * ]],\n * };\n *\n * const circleProps = computeCircleProperties(polygonGeometry);\n * // Returns: { center: [-122.395, 37.805], radius: { value: 1.5, units: 'kilometers' } }\n * ```\n */\nfunction computeCircleProperties(\n geometry: Polygon,\n): CircleProperties | undefined {\n const coordinates = geometry.coordinates[0];\n if (!coordinates || coordinates.length < 3) {\n logger.warn(\n 'Cannot compute circle properties: polygon has insufficient coordinates',\n );\n return undefined;\n }\n\n // Calculate center using turf centroid\n const centerFeature = centroid({\n type: 'Polygon',\n coordinates: geometry.coordinates,\n });\n const center = centerFeature.geometry.coordinates as [number, number];\n\n // Validate center coordinates are valid numbers\n const isCenterValid =\n Number.isFinite(center[0]) && Number.isFinite(center[1]);\n if (!isCenterValid) {\n logger.warn('Cannot compute circle properties: invalid center coordinates');\n return undefined;\n }\n\n // Calculate radius as distance from center to first point\n const firstPoint = coordinates[0] as Position;\n\n // Validate first point coordinates\n const isFirstPointValid =\n firstPoint &&\n Number.isFinite(firstPoint[0]) &&\n Number.isFinite(firstPoint[1]);\n if (!isFirstPointValid) {\n logger.warn(\n 'Cannot compute circle properties: invalid edge point coordinates',\n );\n return undefined;\n }\n\n const radius = distance(center, firstPoint, {\n units: DEFAULT_DISTANCE_UNITS,\n });\n\n // Validate computed radius\n if (!Number.isFinite(radius) || radius <= 0) {\n logger.warn('Cannot compute circle properties: invalid radius computed');\n return undefined;\n }\n\n return {\n center,\n radius: {\n value: radius,\n units: DEFAULT_DISTANCE_UNITS,\n },\n };\n}\n\n/**\n * Edit properties attached by DrawEllipseUsingThreePointsMode.\n *\n * The DrawEllipseUsingThreePointsMode from @deck.gl-community/editable-layers\n * attaches ellipse metadata to the feature's properties.editProperties field.\n * This interface defines the structure of that metadata.\n *\n * @internal\n */\ninterface EllipseEditProperties {\n /** Shape discriminator - always 'Ellipse' */\n shape: 'Ellipse';\n /** X semi-axis (horizontal radius) with value and unit */\n xSemiAxis: { value: number; unit: string };\n /** Y semi-axis (vertical radius) with value and unit */\n ySemiAxis: { value: number; unit: string };\n /** Rotation angle in degrees */\n angle: number;\n /** Center point coordinates [longitude, latitude] */\n center: [number, number];\n}\n\n/**\n * Compute ellipse properties from a feature's editProperties.\n *\n * The DrawEllipseUsingThreePointsMode attaches ellipse metadata to the feature's\n * properties.editProperties field. This function extracts and normalizes that data\n * into the standard EllipseProperties format used by Shape objects.\n *\n * The function validates that editProperties exists and has the correct shape\n * discriminator before extracting the ellipse parameters.\n *\n * @param feature - GeoJSON feature with editProperties attached by the draw mode\n * @returns Normalized ellipse properties, or undefined if extraction fails\n *\n * @example\n * ```typescript\n * import { computeEllipseProperties } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/utils/feature-conversion';\n * import type { Feature } from 'geojson';\n *\n * const feature: Feature = {\n * type: 'Feature',\n * geometry: { type: 'Polygon', coordinates: [[...]] },\n * properties: {\n * editProperties: {\n * shape: 'Ellipse',\n * center: [-122.4, 37.8],\n * xSemiAxis: { value: 2.5, unit: 'kilometers' },\n * ySemiAxis: { value: 1.5, unit: 'kilometers' },\n * angle: 45,\n * },\n * },\n * };\n *\n * const ellipseProps = computeEllipseProperties(feature);\n * // Returns normalized ellipse properties with standard distance units\n * ```\n */\nfunction computeEllipseProperties(\n feature: Feature,\n): EllipseProperties | undefined {\n const editProps = (\n feature.properties as { editProperties?: EllipseEditProperties } | null\n )?.editProperties;\n\n if (!editProps || editProps.shape !== 'Ellipse') {\n logger.warn(\n 'Cannot compute ellipse properties: feature missing editProperties or not an ellipse',\n );\n return undefined;\n }\n\n return {\n center: editProps.center,\n xSemiAxis: {\n value: editProps.xSemiAxis.value,\n units: DEFAULT_DISTANCE_UNITS,\n },\n ySemiAxis: {\n value: editProps.ySemiAxis.value,\n units: DEFAULT_DISTANCE_UNITS,\n },\n angle: editProps.angle,\n };\n}\n\n/**\n * Convert a raw GeoJSON Feature from EditableGeoJsonLayer to a Shape.\n *\n * This function transforms the raw GeoJSON features produced by deck.gl's\n * EditableGeoJsonLayer into the Shape format used throughout the map-toolkit.\n * It handles geometry normalization, style property merging, and special handling\n * for Circle and Ellipse shapes which are stored as polygon approximations.\n *\n * ## The returned Shape includes:\n * - **Auto-generated UUID**: Unique identifier for the shape\n * - **Auto-generated name**: Format \"New {ShapeType} (HH:MM:SS AM/PM)\"\n * - **Merged style properties**: Defaults + optional custom overrides\n * - **Circle/ellipse properties**: Computed from geometry if applicable\n * - **lastUpdated timestamp**: UTC timestamp when created\n * - **locked: false**: Newly created shapes are always unlocked\n *\n * ## Special Handling\n * - **Circles**: Extracts center and radius from polygon approximation\n * - **Ellipses**: Extracts center, semi-axes, and angle from editProperties\n *\n * @param feature - The raw GeoJSON feature from the editable layer\n * @param shape - The type of shape being created\n * @param styleDefaults - Optional style property overrides (colors, line width, etc.)\n * @returns A complete Shape object ready for use in DisplayShapeLayer\n *\n * @example Basic usage with polygon\n * ```typescript\n * import { convertFeatureToShape } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/utils/feature-conversion';\n * import { ShapeFeatureType } from '@accelint/map-toolkit/deckgl/shapes/shared/types';\n * import type { Feature } from 'geojson';\n *\n * const feature: Feature = {\n * type: 'Feature',\n * geometry: {\n * type: 'Polygon',\n * coordinates: [[\n * [-122.4, 37.8],\n * [-122.3, 37.8],\n * [-122.3, 37.9],\n * [-122.4, 37.9],\n * [-122.4, 37.8],\n * ]],\n * },\n * properties: {},\n * };\n *\n * const shape = convertFeatureToShape(feature, ShapeFeatureType.Polygon);\n * // Returns: { id: 'uuid...', name: 'New Polygon (2:30:45 PM)', shape: 'Polygon', ... }\n * ```\n *\n * @example With custom style defaults\n * ```typescript\n * const shape = convertFeatureToShape(\n * feature,\n * ShapeFeatureType.Circle,\n * {\n * fillColor: [255, 100, 100, 180], // RGBA: red fill\n * lineColor: [200, 0, 0, 255], // RGBA: dark red line\n * lineWidth: 4,\n * linePattern: 'solid',\n * }\n * );\n * // Returns a shape with custom colors applied\n * ```\n */\nexport function convertFeatureToShape(\n feature: Feature,\n shape: ShapeFeatureType,\n styleDefaults?: Partial<StyleProperties> | null,\n): Shape {\n const id = uuid();\n const name = generateShapeName(shape);\n\n // Merge default styles with any provided defaults\n const styleProperties: StyleProperties = {\n ...DEFAULT_STYLE_PROPERTIES,\n ...(styleDefaults ?? {}),\n };\n\n // Compute circle properties if this is a circle\n let circleProperties: CircleProperties | undefined;\n if (\n shape === ShapeFeatureTypeEnum.Circle &&\n feature.geometry.type === 'Polygon'\n ) {\n circleProperties = computeCircleProperties(feature.geometry);\n }\n\n // Compute ellipse properties if this is an ellipse\n let ellipseProperties: EllipseProperties | undefined;\n if (\n shape === ShapeFeatureTypeEnum.Ellipse &&\n feature.geometry.type === 'Polygon'\n ) {\n ellipseProperties = computeEllipseProperties(feature);\n }\n\n // Create the styled feature\n const styledFeature: ShapeFeature = {\n type: 'Feature',\n geometry: feature.geometry,\n properties: {\n styleProperties,\n circleProperties,\n ellipseProperties,\n shapeId: id,\n },\n };\n\n // Type assertion needed because TypeScript can't narrow the return type\n // based on the runtime shape value. The constructed object satisfies\n // the Shape union at runtime based on which shape was passed in.\n return {\n id,\n name,\n shape,\n feature: styledFeature,\n lastUpdated: Date.now(),\n locked: false,\n } as Shape;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,SAAS,UAAU;CACvB,SAAS,QAAQ,IAAI,aAAa;CAClC,OAAO;CACP,QAAQ;CACR,QAAQ;CACT,CAAC;;;;;;;;;;;;;;;;;;;;AAqBF,SAAS,kBAAkB,OAAiC;AAE1D,QAAO,OAAO,MAAM,qBADF,IAAI,MAAM,EAAC,oBAAoB,CACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCpC,SAAS,wBACP,UAC8B;CAC9B,MAAM,cAAc,SAAS,YAAY;AACzC,KAAI,CAAC,eAAe,YAAY,SAAS,GAAG;AAC1C,SAAO,KACL,yEACD;AACD;;CAQF,MAAM,SAJgB,SAAS;EAC7B,MAAM;EACN,aAAa,SAAS;EACvB,CAAC,CAC2B,SAAS;AAKtC,KAAI,EADF,OAAO,SAAS,OAAO,GAAG,IAAI,OAAO,SAAS,OAAO,GAAG,GACtC;AAClB,SAAO,KAAK,+DAA+D;AAC3E;;CAIF,MAAM,aAAa,YAAY;AAO/B,KAAI,EAHF,cACA,OAAO,SAAS,WAAW,GAAG,IAC9B,OAAO,SAAS,WAAW,GAAG,GACR;AACtB,SAAO,KACL,mEACD;AACD;;CAGF,MAAM,SAAS,SAAS,QAAQ,YAAY,EAC1C,OAAO,wBACR,CAAC;AAGF,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,GAAG;AAC3C,SAAO,KAAK,4DAA4D;AACxE;;AAGF,QAAO;EACL;EACA,QAAQ;GACN,OAAO;GACP,OAAO;GACR;EACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DH,SAAS,yBACP,SAC+B;CAC/B,MAAM,YACJ,QAAQ,YACP;AAEH,KAAI,CAAC,aAAa,UAAU,UAAU,WAAW;AAC/C,SAAO,KACL,sFACD;AACD;;AAGF,QAAO;EACL,QAAQ,UAAU;EAClB,WAAW;GACT,OAAO,UAAU,UAAU;GAC3B,OAAO;GACR;EACD,WAAW;GACT,OAAO,UAAU,UAAU;GAC3B,OAAO;GACR;EACD,OAAO,UAAU;EAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEH,SAAgB,sBACd,SACA,OACA,eACO;CACP,MAAM,KAAK,MAAM;CACjB,MAAM,OAAO,kBAAkB,MAAM;CAGrC,MAAMA,kBAAmC;EACvC,GAAG;EACH,GAAI,iBAAiB,EAAE;EACxB;CAGD,IAAIC;AACJ,KACE,UAAUC,iBAAqB,UAC/B,QAAQ,SAAS,SAAS,UAE1B,oBAAmB,wBAAwB,QAAQ,SAAS;CAI9D,IAAIC;AACJ,KACE,UAAUD,iBAAqB,WAC/B,QAAQ,SAAS,SAAS,UAE1B,qBAAoB,yBAAyB,QAAQ;AAkBvD,QAAO;EACL;EACA;EACA;EACA,SAlBkC;GAClC,MAAM;GACN,UAAU,QAAQ;GAClB,YAAY;IACV;IACA;IACA;IACA,SAAS;IACV;GACF;EAUC,aAAa,KAAK,KAAK;EACvB,QAAQ;EACT"}
1
+ {"version":3,"file":"feature-conversion.js","names":["styleProperties: StyleProperties","circleProperties: CircleProperties | undefined","ShapeFeatureTypeEnum","ellipseProperties: EllipseProperties | undefined"],"sources":["../../../../../src/deckgl/shapes/draw-shape-layer/utils/feature-conversion.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport { uuid } from '@accelint/core';\nimport { centroid, distance } from '@turf/turf';\nimport { createLoggerDomain } from '@/shared/logger';\nimport { DEFAULT_DISTANCE_UNITS } from '@/shared/units';\nimport { DEFAULT_STYLE_PROPERTIES } from '../../shared/constants';\nimport {\n type CircleProperties,\n type EllipseProperties,\n type Shape,\n type ShapeFeature,\n type ShapeFeatureType,\n ShapeFeatureType as ShapeFeatureTypeEnum,\n type StyleProperties,\n} from '../../shared/types';\nimport type { Feature, Polygon, Position } from 'geojson';\n\nconst logger = createLoggerDomain('[FeatureConversion]');\n\n/**\n * Generate a default name for a shape based on its type.\n *\n * Creates a name in the format \"New {ShapeType} (HH:MM:SS AM/PM)\" using the\n * current time. This provides a default name for shapes created through the\n * drawing interface that includes a timestamp for uniqueness.\n *\n * @param shape - The shape type to generate a name for\n * @returns A formatted name string with timestamp\n *\n * @example\n * ```typescript\n * import { generateShapeName } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/utils/feature-conversion';\n * import { ShapeFeatureType } from '@accelint/map-toolkit/deckgl/shapes/shared/types';\n *\n * const name = generateShapeName(ShapeFeatureType.Polygon);\n * // Returns: \"New Polygon (2:30:45 PM)\"\n * ```\n */\nfunction generateShapeName(shape: ShapeFeatureType): string {\n const timestamp = new Date().toLocaleTimeString();\n return `New ${shape} (${timestamp})`;\n}\n\n/**\n * Compute circle properties from a polygon geometry (circle approximation).\n *\n * The EditableGeoJsonLayer creates circles as polygon approximations with multiple\n * vertices arranged in a circular pattern. This function extracts the original circle's\n * center and radius from that polygon approximation.\n *\n * The center is calculated using Turf's centroid function, and the radius is computed\n * as the distance from the center to the first edge point.\n *\n * @param geometry - Polygon geometry representing a circle approximation\n * @returns Circle properties with center and radius, or undefined if computation fails\n *\n * @example\n * ```typescript\n * import { computeCircleProperties } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/utils/feature-conversion';\n * import type { Polygon } from 'geojson';\n *\n * const polygonGeometry: Polygon = {\n * type: 'Polygon',\n * coordinates: [[\n * [-122.4, 37.8],\n * [-122.39, 37.81],\n * // ... more points forming a circle\n * [-122.4, 37.8], // closing point\n * ]],\n * };\n *\n * const circleProps = computeCircleProperties(polygonGeometry);\n * // Returns: { center: [-122.395, 37.805], radius: { value: 1.5, units: 'kilometers' } }\n * ```\n */\nfunction computeCircleProperties(\n geometry: Polygon,\n): CircleProperties | undefined {\n const coordinates = geometry.coordinates[0];\n if (!coordinates || coordinates.length < 3) {\n logger.warn(\n 'Cannot compute circle properties: polygon has insufficient coordinates',\n );\n return undefined;\n }\n\n // Calculate center using turf centroid\n const centerFeature = centroid({\n type: 'Polygon',\n coordinates: geometry.coordinates,\n });\n const center = centerFeature.geometry.coordinates as [number, number];\n\n // Validate center coordinates are valid numbers\n const isCenterValid =\n Number.isFinite(center[0]) && Number.isFinite(center[1]);\n if (!isCenterValid) {\n logger.warn('Cannot compute circle properties: invalid center coordinates');\n return undefined;\n }\n\n // Calculate radius as distance from center to first point\n const firstPoint = coordinates[0] as Position;\n\n // Validate first point coordinates\n const isFirstPointValid =\n firstPoint &&\n Number.isFinite(firstPoint[0]) &&\n Number.isFinite(firstPoint[1]);\n if (!isFirstPointValid) {\n logger.warn(\n 'Cannot compute circle properties: invalid edge point coordinates',\n );\n return undefined;\n }\n\n const radius = distance(center, firstPoint, {\n units: DEFAULT_DISTANCE_UNITS,\n });\n\n // Validate computed radius\n if (!Number.isFinite(radius) || radius <= 0) {\n logger.warn('Cannot compute circle properties: invalid radius computed');\n return undefined;\n }\n\n return {\n center,\n radius: {\n value: radius,\n units: DEFAULT_DISTANCE_UNITS,\n },\n };\n}\n\n/**\n * Edit properties attached by DrawEllipseUsingThreePointsMode.\n *\n * The DrawEllipseUsingThreePointsMode from @deck.gl-community/editable-layers\n * attaches ellipse metadata to the feature's properties.editProperties field.\n * This interface defines the structure of that metadata.\n *\n * @internal\n */\ninterface EllipseEditProperties {\n /** Shape discriminator - always 'Ellipse' */\n shape: 'Ellipse';\n /** X semi-axis (horizontal radius) with value and unit */\n xSemiAxis: { value: number; unit: string };\n /** Y semi-axis (vertical radius) with value and unit */\n ySemiAxis: { value: number; unit: string };\n /** Rotation angle in degrees */\n angle: number;\n /** Center point coordinates [longitude, latitude] */\n center: [number, number];\n}\n\n/**\n * Compute ellipse properties from a feature's editProperties.\n *\n * The DrawEllipseUsingThreePointsMode attaches ellipse metadata to the feature's\n * properties.editProperties field. This function extracts and normalizes that data\n * into the standard EllipseProperties format used by Shape objects.\n *\n * The function validates that editProperties exists and has the correct shape\n * discriminator before extracting the ellipse parameters.\n *\n * @param feature - GeoJSON feature with editProperties attached by the draw mode\n * @returns Normalized ellipse properties, or undefined if extraction fails\n *\n * @example\n * ```typescript\n * import { computeEllipseProperties } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/utils/feature-conversion';\n * import type { Feature } from 'geojson';\n *\n * const feature: Feature = {\n * type: 'Feature',\n * geometry: { type: 'Polygon', coordinates: [[...]] },\n * properties: {\n * editProperties: {\n * shape: 'Ellipse',\n * center: [-122.4, 37.8],\n * xSemiAxis: { value: 2.5, unit: 'kilometers' },\n * ySemiAxis: { value: 1.5, unit: 'kilometers' },\n * angle: 45,\n * },\n * },\n * };\n *\n * const ellipseProps = computeEllipseProperties(feature);\n * // Returns normalized ellipse properties with standard distance units\n * ```\n */\nfunction computeEllipseProperties(\n feature: Feature,\n): EllipseProperties | undefined {\n const editProps = (\n feature.properties as { editProperties?: EllipseEditProperties } | null\n )?.editProperties;\n\n if (!editProps || editProps.shape !== 'Ellipse') {\n logger.warn(\n 'Cannot compute ellipse properties: feature missing editProperties or not an ellipse',\n );\n return undefined;\n }\n\n return {\n center: editProps.center,\n xSemiAxis: {\n value: editProps.xSemiAxis.value,\n units: DEFAULT_DISTANCE_UNITS,\n },\n ySemiAxis: {\n value: editProps.ySemiAxis.value,\n units: DEFAULT_DISTANCE_UNITS,\n },\n angle: editProps.angle,\n };\n}\n\n/**\n * Convert a raw GeoJSON Feature from EditableGeoJsonLayer to a Shape.\n *\n * This function transforms the raw GeoJSON features produced by deck.gl's\n * EditableGeoJsonLayer into the Shape format used throughout the map-toolkit.\n * It handles geometry normalization, style property merging, and special handling\n * for Circle and Ellipse shapes which are stored as polygon approximations.\n *\n * ## The returned Shape includes:\n * - **Auto-generated UUID**: Unique identifier for the shape\n * - **Auto-generated name**: Format \"New {ShapeType} (HH:MM:SS AM/PM)\"\n * - **Merged style properties**: Defaults + optional custom overrides\n * - **Circle/ellipse properties**: Computed from geometry if applicable\n * - **lastUpdated timestamp**: UTC timestamp when created\n * - **locked: false**: Newly created shapes are always unlocked\n *\n * ## Special Handling\n * - **Circles**: Extracts center and radius from polygon approximation\n * - **Ellipses**: Extracts center, semi-axes, and angle from editProperties\n *\n * @param feature - The raw GeoJSON feature from the editable layer\n * @param shape - The type of shape being created\n * @param styleDefaults - Optional style property overrides (colors, line width, etc.)\n * @returns A complete Shape object ready for use in DisplayShapeLayer\n *\n * @example Basic usage with polygon\n * ```typescript\n * import { convertFeatureToShape } from '@accelint/map-toolkit/deckgl/shapes/draw-shape-layer/utils/feature-conversion';\n * import { ShapeFeatureType } from '@accelint/map-toolkit/deckgl/shapes/shared/types';\n * import type { Feature } from 'geojson';\n *\n * const feature: Feature = {\n * type: 'Feature',\n * geometry: {\n * type: 'Polygon',\n * coordinates: [[\n * [-122.4, 37.8],\n * [-122.3, 37.8],\n * [-122.3, 37.9],\n * [-122.4, 37.9],\n * [-122.4, 37.8],\n * ]],\n * },\n * properties: {},\n * };\n *\n * const shape = convertFeatureToShape(feature, ShapeFeatureType.Polygon);\n * // Returns: { id: 'uuid...', name: 'New Polygon (2:30:45 PM)', shape: 'Polygon', ... }\n * ```\n *\n * @example With custom style defaults\n * ```typescript\n * const shape = convertFeatureToShape(\n * feature,\n * ShapeFeatureType.Circle,\n * {\n * fillColor: [255, 100, 100, 180], // RGBA: red fill\n * lineColor: [200, 0, 0, 255], // RGBA: dark red line\n * lineWidth: 4,\n * linePattern: 'solid',\n * }\n * );\n * // Returns a shape with custom colors applied\n * ```\n */\nexport function convertFeatureToShape(\n feature: Feature,\n shape: ShapeFeatureType,\n styleDefaults?: Partial<StyleProperties> | null,\n): Shape {\n const id = uuid();\n const name = generateShapeName(shape);\n\n // Merge default styles with any provided defaults\n const styleProperties: StyleProperties = {\n ...DEFAULT_STYLE_PROPERTIES,\n ...(styleDefaults ?? {}),\n };\n\n // Compute circle properties if this is a circle\n let circleProperties: CircleProperties | undefined;\n if (\n shape === ShapeFeatureTypeEnum.Circle &&\n feature.geometry.type === 'Polygon'\n ) {\n circleProperties = computeCircleProperties(feature.geometry);\n }\n\n // Compute ellipse properties if this is an ellipse\n let ellipseProperties: EllipseProperties | undefined;\n if (\n shape === ShapeFeatureTypeEnum.Ellipse &&\n feature.geometry.type === 'Polygon'\n ) {\n ellipseProperties = computeEllipseProperties(feature);\n }\n\n // Create the styled feature\n const styledFeature: ShapeFeature = {\n type: 'Feature',\n geometry: feature.geometry,\n properties: {\n styleProperties,\n circleProperties,\n ellipseProperties,\n shapeId: id,\n },\n };\n\n // Type assertion needed because TypeScript can't narrow the return type\n // based on the runtime shape value. The constructed object satisfies\n // the Shape union at runtime based on which shape was passed in.\n return {\n id,\n name,\n shape,\n feature: styledFeature,\n lastUpdated: Date.now(),\n locked: false,\n } as Shape;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,SAAS,mBAAmB,sBAAsB;;;;;;;;;;;;;;;;;;;;AAqBxD,SAAS,kBAAkB,OAAiC;AAE1D,QAAO,OAAO,MAAM,qBADF,IAAI,MAAM,EAAC,oBAAoB,CACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCpC,SAAS,wBACP,UAC8B;CAC9B,MAAM,cAAc,SAAS,YAAY;AACzC,KAAI,CAAC,eAAe,YAAY,SAAS,GAAG;AAC1C,SAAO,KACL,yEACD;AACD;;CAQF,MAAM,SAJgB,SAAS;EAC7B,MAAM;EACN,aAAa,SAAS;EACvB,CAAC,CAC2B,SAAS;AAKtC,KAAI,EADF,OAAO,SAAS,OAAO,GAAG,IAAI,OAAO,SAAS,OAAO,GAAG,GACtC;AAClB,SAAO,KAAK,+DAA+D;AAC3E;;CAIF,MAAM,aAAa,YAAY;AAO/B,KAAI,EAHF,cACA,OAAO,SAAS,WAAW,GAAG,IAC9B,OAAO,SAAS,WAAW,GAAG,GACR;AACtB,SAAO,KACL,mEACD;AACD;;CAGF,MAAM,SAAS,SAAS,QAAQ,YAAY,EAC1C,OAAO,wBACR,CAAC;AAGF,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,GAAG;AAC3C,SAAO,KAAK,4DAA4D;AACxE;;AAGF,QAAO;EACL;EACA,QAAQ;GACN,OAAO;GACP,OAAO;GACR;EACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DH,SAAS,yBACP,SAC+B;CAC/B,MAAM,YACJ,QAAQ,YACP;AAEH,KAAI,CAAC,aAAa,UAAU,UAAU,WAAW;AAC/C,SAAO,KACL,sFACD;AACD;;AAGF,QAAO;EACL,QAAQ,UAAU;EAClB,WAAW;GACT,OAAO,UAAU,UAAU;GAC3B,OAAO;GACR;EACD,WAAW;GACT,OAAO,UAAU,UAAU;GAC3B,OAAO;GACR;EACD,OAAO,UAAU;EAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEH,SAAgB,sBACd,SACA,OACA,eACO;CACP,MAAM,KAAK,MAAM;CACjB,MAAM,OAAO,kBAAkB,MAAM;CAGrC,MAAMA,kBAAmC;EACvC,GAAG;EACH,GAAI,iBAAiB,EAAE;EACxB;CAGD,IAAIC;AACJ,KACE,UAAUC,iBAAqB,UAC/B,QAAQ,SAAS,SAAS,UAE1B,oBAAmB,wBAAwB,QAAQ,SAAS;CAI9D,IAAIC;AACJ,KACE,UAAUD,iBAAqB,WAC/B,QAAQ,SAAS,SAAS,UAE1B,qBAAoB,yBAAyB,QAAQ;AAkBvD,QAAO;EACL;EACA;EACA;EACA,SAlBkC;GAClC,MAAM;GACN,UAAU,QAAQ;GAClB,YAAY;IACV;IACA;IACA;IACA,SAAS;IACV;GACF;EAUC,aAAa,KAAK,KAAK;EACvB,QAAQ;EACT"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -13,7 +13,9 @@
13
13
 
14
14
  'use client';
15
15
 
16
+ import { ShapeFeatureType } from "../shared/types.js";
16
17
  import { COMPLETION_EDIT_TYPES, CONTINUOUS_EDIT_TYPES } from "../shared/constants.js";
18
+ import { Keycode } from "@accelint/hotkey-manager";
17
19
 
18
20
  //#region src/deckgl/shapes/edit-shape-layer/constants.ts
19
21
  /**
@@ -36,7 +38,20 @@ const EDIT_CURSOR_MAP = {
36
38
  translate: "crosshair",
37
39
  "point-translate": "crosshair"
38
40
  };
41
+ /**
42
+ * Defaults for EditShapeLayer hotkeys.
43
+ */
44
+ const DEFAULT_HOTKEY_CONFIG = { panning: { code: Keycode.Space } };
45
+ /**
46
+ * Maps shape types to the `properties.shape` value required by editable-layers modes.
47
+ * - ResizeCircleMode requires `shape: 'Circle'`
48
+ * - ModifyMode lockRectangles requires `shape: 'Rectangle'`
49
+ */
50
+ const SHAPE_PROPERTY_MAP = {
51
+ [ShapeFeatureType.Circle]: "Circle",
52
+ [ShapeFeatureType.Rectangle]: "Rectangle"
53
+ };
39
54
 
40
55
  //#endregion
41
- export { EDIT_CURSOR_MAP, EDIT_SHAPE_LAYER_ID, EDIT_SHAPE_MODE };
56
+ export { DEFAULT_HOTKEY_CONFIG, EDIT_CURSOR_MAP, EDIT_SHAPE_LAYER_ID, EDIT_SHAPE_MODE, SHAPE_PROPERTY_MAP };
42
57
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":["EDIT_CURSOR_MAP: Record<EditMode, CSSCursorType>"],"sources":["../../../../src/deckgl/shapes/edit-shape-layer/constants.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport type { CSSCursorType } from '@/map-cursor/types';\nimport type { EditMode } from './types';\n\n// Re-export edit event type sets from shared constants\nexport {\n COMPLETION_EDIT_TYPES,\n CONTINUOUS_EDIT_TYPES,\n} from '../shared/constants';\n\n/**\n * Mode name for the map-mode integration\n */\nexport const EDIT_SHAPE_MODE = 'edit-shape';\n\n/**\n * Identifier for the edit shape layer.\n * Used as the owner for map-mode/cursor and as the default layer ID.\n */\nexport const EDIT_SHAPE_LAYER_ID = 'edit-shape-layer';\n\n/**\n * Cursor mapping for each edit mode\n */\nexport const EDIT_CURSOR_MAP: Record<EditMode, CSSCursorType> = {\n view: 'default',\n 'bounding-transform': 'crosshair',\n 'vertex-transform': 'crosshair',\n 'circle-transform': 'crosshair',\n translate: 'crosshair',\n 'point-translate': 'crosshair',\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0BA,MAAa,kBAAkB;;;;;AAM/B,MAAa,sBAAsB;;;;AAKnC,MAAaA,kBAAmD;CAC9D,MAAM;CACN,sBAAsB;CACtB,oBAAoB;CACpB,oBAAoB;CACpB,WAAW;CACX,mBAAmB;CACpB"}
1
+ {"version":3,"file":"constants.js","names":["EDIT_CURSOR_MAP: Record<EditMode, CSSCursorType>","SHAPE_PROPERTY_MAP: Partial<Record<ShapeFeatureType, string>>"],"sources":["../../../../src/deckgl/shapes/edit-shape-layer/constants.ts"],"sourcesContent":["/*\n * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport { Keycode } from '@accelint/hotkey-manager';\nimport { ShapeFeatureType } from '../shared/types';\nimport type { CSSCursorType } from '@/map-cursor/types';\nimport type { EditMode } from './types';\n\n// Re-export edit event type sets from shared constants\nexport {\n COMPLETION_EDIT_TYPES,\n CONTINUOUS_EDIT_TYPES,\n} from '../shared/constants';\n\n/**\n * Mode name for the map-mode integration\n */\nexport const EDIT_SHAPE_MODE = 'edit-shape';\n\n/**\n * Identifier for the edit shape layer.\n * Used as the owner for map-mode/cursor and as the default layer ID.\n */\nexport const EDIT_SHAPE_LAYER_ID = 'edit-shape-layer';\n\n/**\n * Cursor mapping for each edit mode\n */\nexport const EDIT_CURSOR_MAP: Record<EditMode, CSSCursorType> = {\n view: 'default',\n 'bounding-transform': 'crosshair',\n 'vertex-transform': 'crosshair',\n 'circle-transform': 'crosshair',\n translate: 'crosshair',\n 'point-translate': 'crosshair',\n};\n\n/**\n * Defaults for EditShapeLayer hotkeys.\n */\nexport const DEFAULT_HOTKEY_CONFIG = {\n panning: { code: Keycode.Space },\n};\n\n/**\n * Maps shape types to the `properties.shape` value required by editable-layers modes.\n * - ResizeCircleMode requires `shape: 'Circle'`\n * - ModifyMode lockRectangles requires `shape: 'Rectangle'`\n */\nexport const SHAPE_PROPERTY_MAP: Partial<Record<ShapeFeatureType, string>> = {\n [ShapeFeatureType.Circle]: 'Circle',\n [ShapeFeatureType.Rectangle]: 'Rectangle',\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAa,kBAAkB;;;;;AAM/B,MAAa,sBAAsB;;;;AAKnC,MAAaA,kBAAmD;CAC9D,MAAM;CACN,sBAAsB;CACtB,oBAAoB;CACpB,oBAAoB;CACpB,WAAW;CACX,mBAAmB;CACpB;;;;AAKD,MAAa,wBAAwB,EACnC,SAAS,EAAE,MAAM,QAAQ,OAAO,EACjC;;;;;;AAOD,MAAaC,qBAAgE;EAC1E,iBAAiB,SAAS;EAC1B,iBAAiB,YAAY;CAC/B"}
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.
2
+ * Copyright 2026 Hypergiant Galactic Systems Inc. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at https://www.apache.org/licenses/LICENSE-2.0
@@ -52,11 +52,14 @@ import * as react_jsx_runtime3 from "react/jsx-runtime";
52
52
  * );
53
53
  * }
54
54
  * ```
55
+ *
56
+ * @throws {Error} Throws if neither `mapId` prop nor `MapProvider` context is available.
55
57
  */
56
58
  declare function EditShapeLayer({
57
59
  id,
58
60
  mapId,
59
- unit
61
+ unit,
62
+ hotkeyConfig
60
63
  }: EditShapeLayerProps): react_jsx_runtime3.JSX.Element | null;
61
64
  //#endregion
62
65
  export { EditShapeLayer };