@accelint/design-toolkit 9.3.0 → 9.4.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 (722) hide show
  1. package/catalog-info.yaml +1 -1
  2. package/dist/components/accordion/context.d.ts +6 -0
  3. package/dist/components/accordion/context.js +6 -0
  4. package/dist/components/accordion/context.js.map +1 -1
  5. package/dist/components/accordion/group.d.ts +37 -2
  6. package/dist/components/accordion/group.js +34 -0
  7. package/dist/components/accordion/group.js.map +1 -1
  8. package/dist/components/accordion/header.d.ts +27 -2
  9. package/dist/components/accordion/header.js +25 -1
  10. package/dist/components/accordion/header.js.map +1 -1
  11. package/dist/components/accordion/index.d.ts +18 -4
  12. package/dist/components/accordion/index.js +16 -2
  13. package/dist/components/accordion/index.js.map +1 -1
  14. package/dist/components/accordion/panel.d.ts +29 -2
  15. package/dist/components/accordion/panel.js +26 -0
  16. package/dist/components/accordion/panel.js.map +1 -1
  17. package/dist/components/accordion/trigger.d.ts +25 -2
  18. package/dist/components/accordion/trigger.js +23 -1
  19. package/dist/components/accordion/trigger.js.map +1 -1
  20. package/dist/components/accordion/types.d.ts +33 -0
  21. package/dist/components/action-bar/index.d.ts +29 -8
  22. package/dist/components/action-bar/index.js +27 -6
  23. package/dist/components/action-bar/index.js.map +1 -1
  24. package/dist/components/action-bar/types.d.ts +7 -0
  25. package/dist/components/avatar/context.d.ts +22 -4
  26. package/dist/components/avatar/context.js +18 -0
  27. package/dist/components/avatar/context.js.map +1 -1
  28. package/dist/components/avatar/index.d.ts +22 -15
  29. package/dist/components/avatar/index.js +21 -14
  30. package/dist/components/avatar/index.js.map +1 -1
  31. package/dist/components/avatar/types.d.ts +13 -0
  32. package/dist/components/badge/context.d.ts +20 -2
  33. package/dist/components/badge/context.js +18 -0
  34. package/dist/components/badge/context.js.map +1 -1
  35. package/dist/components/badge/index.d.ts +28 -14
  36. package/dist/components/badge/index.js +28 -14
  37. package/dist/components/badge/index.js.map +1 -1
  38. package/dist/components/badge/types.d.ts +9 -0
  39. package/dist/components/breadcrumbs/index.d.ts +8 -0
  40. package/dist/components/breadcrumbs/index.js +7 -0
  41. package/dist/components/breadcrumbs/index.js.map +1 -1
  42. package/dist/components/breadcrumbs/item.d.ts +23 -0
  43. package/dist/components/breadcrumbs/item.js +23 -1
  44. package/dist/components/breadcrumbs/item.js.map +1 -1
  45. package/dist/components/breadcrumbs/types.d.ts +17 -0
  46. package/dist/components/button/context.d.ts +62 -8
  47. package/dist/components/button/context.js +54 -0
  48. package/dist/components/button/context.js.map +1 -1
  49. package/dist/components/button/index.d.ts +21 -2
  50. package/dist/components/button/index.js +19 -0
  51. package/dist/components/button/index.js.map +1 -1
  52. package/dist/components/button/link.d.ts +20 -0
  53. package/dist/components/button/link.js +20 -0
  54. package/dist/components/button/link.js.map +1 -1
  55. package/dist/components/button/toggle.d.ts +23 -2
  56. package/dist/components/button/toggle.js +22 -1
  57. package/dist/components/button/toggle.js.map +1 -1
  58. package/dist/components/button/types.d.ts +26 -0
  59. package/dist/components/checkbox/context.d.ts +9 -3
  60. package/dist/components/checkbox/context.js +6 -0
  61. package/dist/components/checkbox/context.js.map +1 -1
  62. package/dist/components/checkbox/group.d.ts +31 -2
  63. package/dist/components/checkbox/group.js +28 -0
  64. package/dist/components/checkbox/group.js.map +1 -1
  65. package/dist/components/checkbox/index.d.ts +19 -2
  66. package/dist/components/checkbox/index.js +19 -1
  67. package/dist/components/checkbox/index.js.map +1 -1
  68. package/dist/components/checkbox/types.d.ts +19 -0
  69. package/dist/components/chip/context.d.ts +22 -4
  70. package/dist/components/chip/context.js +18 -0
  71. package/dist/components/chip/context.js.map +1 -1
  72. package/dist/components/chip/deletable.d.ts +38 -2
  73. package/dist/components/chip/deletable.js +36 -1
  74. package/dist/components/chip/deletable.js.map +1 -1
  75. package/dist/components/chip/index.d.ts +24 -2
  76. package/dist/components/chip/index.js +22 -0
  77. package/dist/components/chip/index.js.map +1 -1
  78. package/dist/components/chip/list.d.ts +47 -2
  79. package/dist/components/chip/list.js +45 -0
  80. package/dist/components/chip/list.js.map +1 -1
  81. package/dist/components/chip/selectable.d.ts +32 -0
  82. package/dist/components/chip/selectable.js +31 -0
  83. package/dist/components/chip/selectable.js.map +1 -1
  84. package/dist/components/chip/types.d.ts +27 -0
  85. package/dist/components/classification-badge/context.d.ts +18 -2
  86. package/dist/components/classification-badge/context.js +16 -0
  87. package/dist/components/classification-badge/context.js.map +1 -1
  88. package/dist/components/classification-badge/index.d.ts +26 -8
  89. package/dist/components/classification-badge/index.js +25 -8
  90. package/dist/components/classification-badge/index.js.map +1 -1
  91. package/dist/components/classification-badge/types.d.ts +4 -0
  92. package/dist/components/classification-banner/context.d.ts +20 -4
  93. package/dist/components/classification-banner/context.js +16 -0
  94. package/dist/components/classification-banner/context.js.map +1 -1
  95. package/dist/components/classification-banner/index.d.ts +12 -2
  96. package/dist/components/classification-banner/index.js +9 -0
  97. package/dist/components/classification-banner/index.js.map +1 -1
  98. package/dist/components/classification-banner/types.d.ts +4 -0
  99. package/dist/components/clock/index.d.ts +12 -2
  100. package/dist/components/clock/index.js +10 -0
  101. package/dist/components/clock/index.js.map +1 -1
  102. package/dist/components/clock/types.d.ts +4 -0
  103. package/dist/components/color-picker/index.d.ts +12 -10
  104. package/dist/components/color-picker/index.js +10 -8
  105. package/dist/components/color-picker/index.js.map +1 -1
  106. package/dist/components/color-picker/types.d.ts +8 -0
  107. package/dist/components/combobox-field/context.d.ts +20 -4
  108. package/dist/components/combobox-field/context.js +16 -0
  109. package/dist/components/combobox-field/context.js.map +1 -1
  110. package/dist/components/combobox-field/index.d.ts +15 -2
  111. package/dist/components/combobox-field/index.js +13 -1
  112. package/dist/components/combobox-field/index.js.map +1 -1
  113. package/dist/components/combobox-field/types.d.ts +19 -0
  114. package/dist/components/coordinate-field/context.d.ts +15 -6
  115. package/dist/components/coordinate-field/context.js +9 -0
  116. package/dist/components/coordinate-field/context.js.map +1 -1
  117. package/dist/components/coordinate-field/coordinate-utils.d.ts +8 -0
  118. package/dist/components/coordinate-field/coordinate-utils.js +8 -0
  119. package/dist/components/coordinate-field/coordinate-utils.js.map +1 -1
  120. package/dist/components/coordinate-field/index.d.ts +29 -2
  121. package/dist/components/coordinate-field/index.js +29 -3
  122. package/dist/components/coordinate-field/index.js.map +1 -1
  123. package/dist/components/coordinate-field/segment.d.ts +27 -2
  124. package/dist/components/coordinate-field/segment.js +25 -0
  125. package/dist/components/coordinate-field/segment.js.map +1 -1
  126. package/dist/components/coordinate-field/styles.module.css +5 -1
  127. package/dist/components/date-field/index.d.ts +27 -2
  128. package/dist/components/date-field/index.js +25 -0
  129. package/dist/components/date-field/index.js.map +1 -1
  130. package/dist/components/date-field/types.d.ts +19 -3
  131. package/dist/components/deferred-collection/index.d.ts +10 -2
  132. package/dist/components/deferred-collection/index.js +8 -0
  133. package/dist/components/deferred-collection/index.js.map +1 -1
  134. package/dist/components/deferred-collection/types.d.ts +6 -3
  135. package/dist/components/details-list/context.d.ts +25 -4
  136. package/dist/components/details-list/context.js +21 -0
  137. package/dist/components/details-list/context.js.map +1 -1
  138. package/dist/components/details-list/index.d.ts +9 -2
  139. package/dist/components/details-list/index.js +7 -0
  140. package/dist/components/details-list/index.js.map +1 -1
  141. package/dist/components/details-list/label.d.ts +18 -2
  142. package/dist/components/details-list/label.js +16 -0
  143. package/dist/components/details-list/label.js.map +1 -1
  144. package/dist/components/details-list/types.d.ts +14 -0
  145. package/dist/components/details-list/value.d.ts +20 -2
  146. package/dist/components/details-list/value.js +17 -0
  147. package/dist/components/details-list/value.js.map +1 -1
  148. package/dist/components/dialog/content.d.ts +23 -2
  149. package/dist/components/dialog/content.js +20 -0
  150. package/dist/components/dialog/content.js.map +1 -1
  151. package/dist/components/dialog/context.d.ts +5 -2
  152. package/dist/components/dialog/context.js +3 -0
  153. package/dist/components/dialog/context.js.map +1 -1
  154. package/dist/components/dialog/footer.d.ts +26 -2
  155. package/dist/components/dialog/footer.js +23 -0
  156. package/dist/components/dialog/footer.js.map +1 -1
  157. package/dist/components/dialog/index.d.ts +12 -2
  158. package/dist/components/dialog/index.js +10 -0
  159. package/dist/components/dialog/index.js.map +1 -1
  160. package/dist/components/dialog/title.d.ts +21 -2
  161. package/dist/components/dialog/title.js +18 -0
  162. package/dist/components/dialog/title.js.map +1 -1
  163. package/dist/components/dialog/trigger.d.ts +18 -0
  164. package/dist/components/dialog/trigger.js +17 -0
  165. package/dist/components/dialog/trigger.js.map +1 -1
  166. package/dist/components/dialog/types.d.ts +12 -0
  167. package/dist/components/divider/context.d.ts +24 -4
  168. package/dist/components/divider/context.js +20 -0
  169. package/dist/components/divider/context.js.map +1 -1
  170. package/dist/components/divider/index.d.ts +13 -2
  171. package/dist/components/divider/index.js +10 -0
  172. package/dist/components/divider/index.js.map +1 -1
  173. package/dist/components/divider/types.d.ts +4 -4
  174. package/dist/components/drawer/back.d.ts +21 -2
  175. package/dist/components/drawer/back.js +19 -1
  176. package/dist/components/drawer/back.js.map +1 -1
  177. package/dist/components/drawer/close.d.ts +25 -2
  178. package/dist/components/drawer/close.js +28 -3
  179. package/dist/components/drawer/close.js.map +1 -1
  180. package/dist/components/drawer/content.d.ts +22 -2
  181. package/dist/components/drawer/content.js +19 -0
  182. package/dist/components/drawer/content.js.map +1 -1
  183. package/dist/components/drawer/context.d.ts +46 -4
  184. package/dist/components/drawer/context.js +45 -2
  185. package/dist/components/drawer/context.js.map +1 -1
  186. package/dist/components/drawer/events.d.ts +2 -0
  187. package/dist/components/drawer/events.js +2 -0
  188. package/dist/components/drawer/events.js.map +1 -1
  189. package/dist/components/drawer/footer.d.ts +24 -2
  190. package/dist/components/drawer/footer.js +21 -0
  191. package/dist/components/drawer/footer.js.map +1 -1
  192. package/dist/components/drawer/header-title.d.ts +22 -4
  193. package/dist/components/drawer/header-title.js +19 -2
  194. package/dist/components/drawer/header-title.js.map +1 -1
  195. package/dist/components/drawer/header.d.ts +34 -2
  196. package/dist/components/drawer/header.js +42 -2
  197. package/dist/components/drawer/header.js.map +1 -1
  198. package/dist/components/drawer/index.d.ts +14 -2
  199. package/dist/components/drawer/index.js +16 -0
  200. package/dist/components/drawer/index.js.map +1 -1
  201. package/dist/components/drawer/layout-main.d.ts +23 -2
  202. package/dist/components/drawer/layout-main.js +20 -0
  203. package/dist/components/drawer/layout-main.js.map +1 -1
  204. package/dist/components/drawer/layout.d.ts +25 -2
  205. package/dist/components/drawer/layout.js +22 -0
  206. package/dist/components/drawer/layout.js.map +1 -1
  207. package/dist/components/drawer/menu-item.d.ts +25 -2
  208. package/dist/components/drawer/menu-item.js +22 -0
  209. package/dist/components/drawer/menu-item.js.map +1 -1
  210. package/dist/components/drawer/menu.d.ts +22 -2
  211. package/dist/components/drawer/menu.js +19 -0
  212. package/dist/components/drawer/menu.js.map +1 -1
  213. package/dist/components/drawer/panel.d.ts +21 -2
  214. package/dist/components/drawer/panel.js +18 -0
  215. package/dist/components/drawer/panel.js.map +1 -1
  216. package/dist/components/drawer/trigger.d.ts +31 -2
  217. package/dist/components/drawer/trigger.js +29 -1
  218. package/dist/components/drawer/trigger.js.map +1 -1
  219. package/dist/components/drawer/types.d.ts +149 -2
  220. package/dist/components/drawer/view.d.ts +25 -2
  221. package/dist/components/drawer/view.js +22 -0
  222. package/dist/components/drawer/view.js.map +1 -1
  223. package/dist/components/flashcard/index.d.ts +129 -27
  224. package/dist/components/flashcard/index.js +120 -18
  225. package/dist/components/flashcard/index.js.map +1 -1
  226. package/dist/components/flashcard/styles.module.css +1 -1
  227. package/dist/components/flashcard/types.d.ts +12 -0
  228. package/dist/components/hero/context.d.ts +5 -2
  229. package/dist/components/hero/context.js +3 -0
  230. package/dist/components/hero/context.js.map +1 -1
  231. package/dist/components/hero/index.d.ts +9 -2
  232. package/dist/components/hero/index.js +7 -0
  233. package/dist/components/hero/index.js.map +1 -1
  234. package/dist/components/hero/subtitle.d.ts +17 -2
  235. package/dist/components/hero/subtitle.js +15 -0
  236. package/dist/components/hero/subtitle.js.map +1 -1
  237. package/dist/components/hero/title.d.ts +15 -2
  238. package/dist/components/hero/title.js +13 -0
  239. package/dist/components/hero/title.js.map +1 -1
  240. package/dist/components/hero/types.d.ts +9 -0
  241. package/dist/components/hotkey/context.d.ts +24 -4
  242. package/dist/components/hotkey/context.js +20 -0
  243. package/dist/components/hotkey/context.js.map +1 -1
  244. package/dist/components/hotkey/index.d.ts +17 -2
  245. package/dist/components/hotkey/index.js +15 -0
  246. package/dist/components/hotkey/index.js.map +1 -1
  247. package/dist/components/hotkey/set.d.ts +21 -2
  248. package/dist/components/hotkey/set.js +18 -0
  249. package/dist/components/hotkey/set.js.map +1 -1
  250. package/dist/components/hotkey/types.d.ts +4 -0
  251. package/dist/components/icon/context.d.ts +24 -4
  252. package/dist/components/icon/context.js +20 -0
  253. package/dist/components/icon/context.js.map +1 -1
  254. package/dist/components/icon/index.d.ts +15 -2
  255. package/dist/components/icon/index.js +13 -0
  256. package/dist/components/icon/index.js.map +1 -1
  257. package/dist/components/icon/types.d.ts +4 -0
  258. package/dist/components/input/context.d.ts +4 -0
  259. package/dist/components/input/context.js +4 -0
  260. package/dist/components/input/context.js.map +1 -1
  261. package/dist/components/input/index.d.ts +17 -2
  262. package/dist/components/input/index.js +16 -1
  263. package/dist/components/input/index.js.map +1 -1
  264. package/dist/components/input/types.d.ts +16 -0
  265. package/dist/components/kanban/card-body.d.ts +10 -2
  266. package/dist/components/kanban/card-body.js +8 -0
  267. package/dist/components/kanban/card-body.js.map +1 -1
  268. package/dist/components/kanban/card-header-actions.d.ts +10 -2
  269. package/dist/components/kanban/card-header-actions.js +8 -0
  270. package/dist/components/kanban/card-header-actions.js.map +1 -1
  271. package/dist/components/kanban/card-header-title.d.ts +10 -2
  272. package/dist/components/kanban/card-header-title.js +8 -0
  273. package/dist/components/kanban/card-header-title.js.map +1 -1
  274. package/dist/components/kanban/card-header.d.ts +12 -2
  275. package/dist/components/kanban/card-header.js +10 -0
  276. package/dist/components/kanban/card-header.js.map +1 -1
  277. package/dist/components/kanban/card.d.ts +26 -2
  278. package/dist/components/kanban/card.js +23 -0
  279. package/dist/components/kanban/card.js.map +1 -1
  280. package/dist/components/kanban/column-actions.d.ts +10 -2
  281. package/dist/components/kanban/column-actions.js +9 -1
  282. package/dist/components/kanban/column-actions.js.map +1 -1
  283. package/dist/components/kanban/column-container.d.ts +10 -2
  284. package/dist/components/kanban/column-container.js +8 -0
  285. package/dist/components/kanban/column-container.js.map +1 -1
  286. package/dist/components/kanban/column-content.d.ts +13 -2
  287. package/dist/components/kanban/column-content.js +11 -0
  288. package/dist/components/kanban/column-content.js.map +1 -1
  289. package/dist/components/kanban/column-header-actions.d.ts +13 -2
  290. package/dist/components/kanban/column-header-actions.js +11 -0
  291. package/dist/components/kanban/column-header-actions.js.map +1 -1
  292. package/dist/components/kanban/column-header-drag-handle.d.ts +7 -2
  293. package/dist/components/kanban/column-header-drag-handle.js +6 -1
  294. package/dist/components/kanban/column-header-drag-handle.js.map +1 -1
  295. package/dist/components/kanban/column-header-title.d.ts +10 -2
  296. package/dist/components/kanban/column-header-title.js +8 -0
  297. package/dist/components/kanban/column-header-title.js.map +1 -1
  298. package/dist/components/kanban/column-header.d.ts +12 -2
  299. package/dist/components/kanban/column-header.js +10 -0
  300. package/dist/components/kanban/column-header.js.map +1 -1
  301. package/dist/components/kanban/column.d.ts +22 -2
  302. package/dist/components/kanban/column.js +19 -0
  303. package/dist/components/kanban/column.js.map +1 -1
  304. package/dist/components/kanban/context.d.ts +49 -2
  305. package/dist/components/kanban/context.js +30 -0
  306. package/dist/components/kanban/context.js.map +1 -1
  307. package/dist/components/kanban/header-actions.d.ts +10 -2
  308. package/dist/components/kanban/header-actions.js +8 -0
  309. package/dist/components/kanban/header-actions.js.map +1 -1
  310. package/dist/components/kanban/header-search.d.ts +9 -2
  311. package/dist/components/kanban/header-search.js +7 -0
  312. package/dist/components/kanban/header-search.js.map +1 -1
  313. package/dist/components/kanban/header-title.d.ts +10 -2
  314. package/dist/components/kanban/header-title.js +8 -0
  315. package/dist/components/kanban/header-title.js.map +1 -1
  316. package/dist/components/kanban/header.d.ts +12 -2
  317. package/dist/components/kanban/header.js +10 -0
  318. package/dist/components/kanban/header.js.map +1 -1
  319. package/dist/components/kanban/kanban.d.ts +33 -4
  320. package/dist/components/kanban/kanban.js +29 -0
  321. package/dist/components/kanban/kanban.js.map +1 -1
  322. package/dist/components/kanban/types.d.ts +51 -0
  323. package/dist/components/label/context.d.ts +25 -4
  324. package/dist/components/label/context.js +21 -0
  325. package/dist/components/label/context.js.map +1 -1
  326. package/dist/components/label/index.d.ts +16 -2
  327. package/dist/components/label/index.js +14 -0
  328. package/dist/components/label/index.js.map +1 -1
  329. package/dist/components/label/types.d.ts +5 -0
  330. package/dist/components/lines/index.d.ts +10 -0
  331. package/dist/components/lines/index.js +9 -0
  332. package/dist/components/lines/index.js.map +1 -1
  333. package/dist/components/lines/types.d.ts +6 -0
  334. package/dist/components/link/context.d.ts +21 -2
  335. package/dist/components/link/context.js +18 -0
  336. package/dist/components/link/context.js.map +1 -1
  337. package/dist/components/link/index.d.ts +12 -2
  338. package/dist/components/link/index.js +9 -0
  339. package/dist/components/link/index.js.map +1 -1
  340. package/dist/components/link/types.d.ts +5 -0
  341. package/dist/components/list/context.d.ts +11 -2
  342. package/dist/components/list/context.js +9 -0
  343. package/dist/components/list/context.js.map +1 -1
  344. package/dist/components/list/index.d.ts +11 -2
  345. package/dist/components/list/index.js +9 -0
  346. package/dist/components/list/index.js.map +1 -1
  347. package/dist/components/list/item-content.d.ts +9 -2
  348. package/dist/components/list/item-content.js +6 -0
  349. package/dist/components/list/item-content.js.map +1 -1
  350. package/dist/components/list/item-description.d.ts +9 -2
  351. package/dist/components/list/item-description.js +7 -0
  352. package/dist/components/list/item-description.js.map +1 -1
  353. package/dist/components/list/item-title.d.ts +9 -2
  354. package/dist/components/list/item-title.js +7 -0
  355. package/dist/components/list/item-title.js.map +1 -1
  356. package/dist/components/list/item.d.ts +10 -2
  357. package/dist/components/list/item.js +8 -0
  358. package/dist/components/list/item.js.map +1 -1
  359. package/dist/components/list/types.d.ts +22 -0
  360. package/dist/components/menu/context.d.ts +6 -2
  361. package/dist/components/menu/context.js +4 -0
  362. package/dist/components/menu/context.js.map +1 -1
  363. package/dist/components/menu/index.d.ts +24 -3
  364. package/dist/components/menu/index.js +22 -1
  365. package/dist/components/menu/index.js.map +1 -1
  366. package/dist/components/menu/item-description.d.ts +17 -2
  367. package/dist/components/menu/item-description.js +15 -0
  368. package/dist/components/menu/item-description.js.map +1 -1
  369. package/dist/components/menu/item-label.d.ts +17 -2
  370. package/dist/components/menu/item-label.js +15 -0
  371. package/dist/components/menu/item-label.js.map +1 -1
  372. package/dist/components/menu/item.d.ts +23 -2
  373. package/dist/components/menu/item.js +21 -1
  374. package/dist/components/menu/item.js.map +1 -1
  375. package/dist/components/menu/section.d.ts +23 -2
  376. package/dist/components/menu/section.js +20 -0
  377. package/dist/components/menu/section.js.map +1 -1
  378. package/dist/components/menu/separator.d.ts +16 -2
  379. package/dist/components/menu/separator.js +14 -0
  380. package/dist/components/menu/separator.js.map +1 -1
  381. package/dist/components/menu/submenu.d.ts +18 -2
  382. package/dist/components/menu/submenu.js +16 -0
  383. package/dist/components/menu/submenu.js.map +1 -1
  384. package/dist/components/menu/trigger.d.ts +15 -0
  385. package/dist/components/menu/trigger.js +15 -0
  386. package/dist/components/menu/trigger.js.map +1 -1
  387. package/dist/components/menu/types.d.ts +25 -0
  388. package/dist/components/notice/events.d.ts +9 -0
  389. package/dist/components/notice/events.js +9 -0
  390. package/dist/components/notice/events.js.map +1 -1
  391. package/dist/components/notice/index.d.ts +34 -2
  392. package/dist/components/notice/index.js +32 -1
  393. package/dist/components/notice/index.js.map +1 -1
  394. package/dist/components/notice/list.d.ts +31 -2
  395. package/dist/components/notice/list.js +28 -0
  396. package/dist/components/notice/list.js.map +1 -1
  397. package/dist/components/notice/notice-icon.d.ts +22 -2
  398. package/dist/components/notice/notice-icon.js +23 -1
  399. package/dist/components/notice/notice-icon.js.map +1 -1
  400. package/dist/components/notice/types.d.ts +60 -0
  401. package/dist/components/notice/utils.d.ts +8 -0
  402. package/dist/components/notice/utils.js +8 -0
  403. package/dist/components/notice/utils.js.map +1 -1
  404. package/dist/components/options/context.d.ts +1 -0
  405. package/dist/components/options/context.js +1 -0
  406. package/dist/components/options/context.js.map +1 -1
  407. package/dist/components/options/index.d.ts +15 -2
  408. package/dist/components/options/index.js +13 -0
  409. package/dist/components/options/index.js.map +1 -1
  410. package/dist/components/options/item-content.d.ts +22 -2
  411. package/dist/components/options/item-content.js +19 -0
  412. package/dist/components/options/item-content.js.map +1 -1
  413. package/dist/components/options/item-description.d.ts +14 -2
  414. package/dist/components/options/item-description.js +12 -0
  415. package/dist/components/options/item-description.js.map +1 -1
  416. package/dist/components/options/item-label.d.ts +14 -2
  417. package/dist/components/options/item-label.js +12 -0
  418. package/dist/components/options/item-label.js.map +1 -1
  419. package/dist/components/options/item.d.ts +24 -2
  420. package/dist/components/options/item.js +21 -0
  421. package/dist/components/options/item.js.map +1 -1
  422. package/dist/components/options/section.d.ts +21 -2
  423. package/dist/components/options/section.js +18 -0
  424. package/dist/components/options/section.js.map +1 -1
  425. package/dist/components/options/types.d.ts +24 -0
  426. package/dist/components/pagination/context.d.ts +3 -2
  427. package/dist/components/pagination/context.js +1 -0
  428. package/dist/components/pagination/context.js.map +1 -1
  429. package/dist/components/pagination/index.d.ts +18 -11
  430. package/dist/components/pagination/index.js +15 -9
  431. package/dist/components/pagination/index.js.map +1 -1
  432. package/dist/components/pagination/next.d.ts +17 -2
  433. package/dist/components/pagination/next.js +15 -0
  434. package/dist/components/pagination/next.js.map +1 -1
  435. package/dist/components/pagination/pages.d.ts +21 -2
  436. package/dist/components/pagination/pages.js +18 -0
  437. package/dist/components/pagination/pages.js.map +1 -1
  438. package/dist/components/pagination/prev.d.ts +17 -2
  439. package/dist/components/pagination/prev.js +16 -1
  440. package/dist/components/pagination/prev.js.map +1 -1
  441. package/dist/components/pagination/types.d.ts +32 -0
  442. package/dist/components/pagination/utils.d.ts +35 -0
  443. package/dist/components/pagination/utils.js +35 -0
  444. package/dist/components/pagination/utils.js.map +1 -1
  445. package/dist/components/popover/content.d.ts +20 -2
  446. package/dist/components/popover/content.js +17 -0
  447. package/dist/components/popover/content.js.map +1 -1
  448. package/dist/components/popover/footer.d.ts +22 -2
  449. package/dist/components/popover/footer.js +19 -0
  450. package/dist/components/popover/footer.js.map +1 -1
  451. package/dist/components/popover/index.d.ts +9 -2
  452. package/dist/components/popover/index.js +8 -1
  453. package/dist/components/popover/index.js.map +1 -1
  454. package/dist/components/popover/styles.module.css +6 -0
  455. package/dist/components/popover/title.d.ts +17 -2
  456. package/dist/components/popover/title.js +15 -0
  457. package/dist/components/popover/title.js.map +1 -1
  458. package/dist/components/popover/trigger.d.ts +24 -2
  459. package/dist/components/popover/trigger.js +21 -0
  460. package/dist/components/popover/trigger.js.map +1 -1
  461. package/dist/components/popover/types.d.ts +10 -0
  462. package/dist/components/query-builder/action-element.d.ts +20 -2
  463. package/dist/components/query-builder/action-element.js +17 -0
  464. package/dist/components/query-builder/action-element.js.map +1 -1
  465. package/dist/components/query-builder/actions.d.ts +37 -4
  466. package/dist/components/query-builder/actions.js +36 -1
  467. package/dist/components/query-builder/actions.js.map +1 -1
  468. package/dist/components/query-builder/combinator-selector.d.ts +10 -2
  469. package/dist/components/query-builder/combinator-selector.js +8 -0
  470. package/dist/components/query-builder/combinator-selector.js.map +1 -1
  471. package/dist/components/query-builder/constants.d.ts +1 -0
  472. package/dist/components/query-builder/constants.js +1 -0
  473. package/dist/components/query-builder/constants.js.map +1 -1
  474. package/dist/components/query-builder/index.d.ts +11 -2
  475. package/dist/components/query-builder/index.js +9 -0
  476. package/dist/components/query-builder/index.js.map +1 -1
  477. package/dist/components/query-builder/rule-group.d.ts +52 -4
  478. package/dist/components/query-builder/rule-group.js +47 -0
  479. package/dist/components/query-builder/rule-group.js.map +1 -1
  480. package/dist/components/query-builder/rule.d.ts +20 -2
  481. package/dist/components/query-builder/rule.js +18 -0
  482. package/dist/components/query-builder/rule.js.map +1 -1
  483. package/dist/components/query-builder/types.d.ts +9 -0
  484. package/dist/components/query-builder/utils.d.ts +15 -0
  485. package/dist/components/query-builder/utils.js +15 -0
  486. package/dist/components/query-builder/utils.js.map +1 -1
  487. package/dist/components/query-builder/value-editor.d.ts +23 -2
  488. package/dist/components/query-builder/value-editor.js +20 -0
  489. package/dist/components/query-builder/value-editor.js.map +1 -1
  490. package/dist/components/query-builder/value-selector.d.ts +23 -2
  491. package/dist/components/query-builder/value-selector.js +20 -0
  492. package/dist/components/query-builder/value-selector.js.map +1 -1
  493. package/dist/components/radio/context.d.ts +2 -2
  494. package/dist/components/radio/group.d.ts +19 -2
  495. package/dist/components/radio/group.js +16 -0
  496. package/dist/components/radio/group.js.map +1 -1
  497. package/dist/components/radio/index.d.ts +13 -26
  498. package/dist/components/radio/index.js +11 -24
  499. package/dist/components/radio/index.js.map +1 -1
  500. package/dist/components/radio/types.d.ts +16 -0
  501. package/dist/components/search-field/context.d.ts +7 -4
  502. package/dist/components/search-field/context.js +3 -0
  503. package/dist/components/search-field/context.js.map +1 -1
  504. package/dist/components/search-field/index.d.ts +15 -24
  505. package/dist/components/search-field/index.js +16 -23
  506. package/dist/components/search-field/index.js.map +1 -1
  507. package/dist/components/search-field/types.d.ts +13 -0
  508. package/dist/components/select-field/context.d.ts +11 -4
  509. package/dist/components/select-field/context.js +7 -0
  510. package/dist/components/select-field/context.js.map +1 -1
  511. package/dist/components/select-field/index.d.ts +19 -39
  512. package/dist/components/select-field/index.js +18 -38
  513. package/dist/components/select-field/index.js.map +1 -1
  514. package/dist/components/select-field/styles.module.css +8 -0
  515. package/dist/components/select-field/types.d.ts +18 -0
  516. package/dist/components/sidenav/avatar.d.ts +19 -2
  517. package/dist/components/sidenav/avatar.js +16 -0
  518. package/dist/components/sidenav/avatar.js.map +1 -1
  519. package/dist/components/sidenav/content.d.ts +23 -2
  520. package/dist/components/sidenav/content.js +20 -0
  521. package/dist/components/sidenav/content.js.map +1 -1
  522. package/dist/components/sidenav/context.d.ts +3 -2
  523. package/dist/components/sidenav/context.js +1 -0
  524. package/dist/components/sidenav/context.js.map +1 -1
  525. package/dist/components/sidenav/events.d.ts +2 -0
  526. package/dist/components/sidenav/events.js +2 -0
  527. package/dist/components/sidenav/events.js.map +1 -1
  528. package/dist/components/sidenav/footer.d.ts +16 -2
  529. package/dist/components/sidenav/footer.js +13 -0
  530. package/dist/components/sidenav/footer.js.map +1 -1
  531. package/dist/components/sidenav/header.d.ts +20 -2
  532. package/dist/components/sidenav/header.js +18 -1
  533. package/dist/components/sidenav/header.js.map +1 -1
  534. package/dist/components/sidenav/index.d.ts +11 -2
  535. package/dist/components/sidenav/index.js +9 -0
  536. package/dist/components/sidenav/index.js.map +1 -1
  537. package/dist/components/sidenav/item.d.ts +17 -2
  538. package/dist/components/sidenav/item.js +14 -0
  539. package/dist/components/sidenav/item.js.map +1 -1
  540. package/dist/components/sidenav/link.d.ts +17 -2
  541. package/dist/components/sidenav/link.js +15 -1
  542. package/dist/components/sidenav/link.js.map +1 -1
  543. package/dist/components/sidenav/menu-item.d.ts +16 -2
  544. package/dist/components/sidenav/menu-item.js +13 -0
  545. package/dist/components/sidenav/menu-item.js.map +1 -1
  546. package/dist/components/sidenav/menu.d.ts +19 -2
  547. package/dist/components/sidenav/menu.js +17 -1
  548. package/dist/components/sidenav/menu.js.map +1 -1
  549. package/dist/components/sidenav/trigger.d.ts +17 -2
  550. package/dist/components/sidenav/trigger.js +14 -0
  551. package/dist/components/sidenav/trigger.js.map +1 -1
  552. package/dist/components/sidenav/types.d.ts +53 -0
  553. package/dist/components/skeleton/index.d.ts +12 -27
  554. package/dist/components/skeleton/index.js +10 -24
  555. package/dist/components/skeleton/index.js.map +1 -1
  556. package/dist/components/skeleton/types.d.ts +4 -0
  557. package/dist/components/slider/index.d.ts +30 -29
  558. package/dist/components/slider/index.js +28 -27
  559. package/dist/components/slider/index.js.map +1 -1
  560. package/dist/components/slider/types.d.ts +18 -0
  561. package/dist/components/switch/context.d.ts +16 -10
  562. package/dist/components/switch/context.js +13 -7
  563. package/dist/components/switch/context.js.map +1 -1
  564. package/dist/components/switch/index.d.ts +14 -31
  565. package/dist/components/switch/index.js +12 -29
  566. package/dist/components/switch/index.js.map +1 -1
  567. package/dist/components/switch/types.d.ts +5 -0
  568. package/dist/components/table/body.d.ts +21 -2
  569. package/dist/components/table/body.js +18 -0
  570. package/dist/components/table/body.js.map +1 -1
  571. package/dist/components/table/cell.d.ts +22 -2
  572. package/dist/components/table/cell.js +19 -0
  573. package/dist/components/table/cell.js.map +1 -1
  574. package/dist/components/table/constants/table.d.ts +6 -0
  575. package/dist/components/table/constants/table.js +4 -0
  576. package/dist/components/table/constants/table.js.map +1 -1
  577. package/dist/components/table/context.d.ts +3 -2
  578. package/dist/components/table/context.js +1 -0
  579. package/dist/components/table/context.js.map +1 -1
  580. package/dist/components/table/header-cell.d.ts +24 -2
  581. package/dist/components/table/header-cell.js +24 -1
  582. package/dist/components/table/header-cell.js.map +1 -1
  583. package/dist/components/table/header.d.ts +20 -0
  584. package/dist/components/table/header.js +19 -0
  585. package/dist/components/table/header.js.map +1 -1
  586. package/dist/components/table/index.d.ts +28 -6
  587. package/dist/components/table/index.js +27 -5
  588. package/dist/components/table/index.js.map +1 -1
  589. package/dist/components/table/row.d.ts +26 -2
  590. package/dist/components/table/row.js +23 -0
  591. package/dist/components/table/row.js.map +1 -1
  592. package/dist/components/table/types.d.ts +3 -0
  593. package/dist/components/tabs/context.d.ts +20 -10
  594. package/dist/components/tabs/context.js +17 -7
  595. package/dist/components/tabs/context.js.map +1 -1
  596. package/dist/components/tabs/index.d.ts +17 -40
  597. package/dist/components/tabs/index.js +15 -38
  598. package/dist/components/tabs/index.js.map +1 -1
  599. package/dist/components/tabs/list.d.ts +20 -4
  600. package/dist/components/tabs/list.js +17 -2
  601. package/dist/components/tabs/list.js.map +1 -1
  602. package/dist/components/tabs/panel.d.ts +21 -4
  603. package/dist/components/tabs/panel.js +18 -2
  604. package/dist/components/tabs/panel.js.map +1 -1
  605. package/dist/components/tabs/tab.d.ts +17 -4
  606. package/dist/components/tabs/tab.js +14 -2
  607. package/dist/components/tabs/tab.js.map +1 -1
  608. package/dist/components/tabs/types.d.ts +3 -0
  609. package/dist/components/text-area-field/context.d.ts +20 -10
  610. package/dist/components/text-area-field/context.js +17 -7
  611. package/dist/components/text-area-field/context.js.map +1 -1
  612. package/dist/components/text-area-field/index.d.ts +20 -15
  613. package/dist/components/text-area-field/index.js +18 -13
  614. package/dist/components/text-area-field/index.js.map +1 -1
  615. package/dist/components/text-area-field/styles.module.css +1 -1
  616. package/dist/components/text-area-field/types.d.ts +9 -0
  617. package/dist/components/text-field/context.d.ts +24 -4
  618. package/dist/components/text-field/context.js +20 -0
  619. package/dist/components/text-field/context.js.map +1 -1
  620. package/dist/components/text-field/index.d.ts +17 -82
  621. package/dist/components/text-field/index.js +15 -80
  622. package/dist/components/text-field/index.js.map +1 -1
  623. package/dist/components/text-field/types.d.ts +9 -0
  624. package/dist/components/time-field/index.d.ts +23 -5
  625. package/dist/components/time-field/index.js +21 -4
  626. package/dist/components/time-field/index.js.map +1 -1
  627. package/dist/components/time-field/types.d.ts +9 -0
  628. package/dist/components/tooltip/context.d.ts +3 -2
  629. package/dist/components/tooltip/context.js +1 -0
  630. package/dist/components/tooltip/context.js.map +1 -1
  631. package/dist/components/tooltip/index.d.ts +15 -30
  632. package/dist/components/tooltip/index.js +13 -28
  633. package/dist/components/tooltip/index.js.map +1 -1
  634. package/dist/components/tooltip/trigger.d.ts +22 -2
  635. package/dist/components/tooltip/trigger.js +19 -0
  636. package/dist/components/tooltip/trigger.js.map +1 -1
  637. package/dist/components/tooltip/types.d.ts +7 -0
  638. package/dist/components/tree/context.d.ts +5 -9
  639. package/dist/components/tree/context.js +2 -6
  640. package/dist/components/tree/context.js.map +1 -1
  641. package/dist/components/tree/index.d.ts +30 -8
  642. package/dist/components/tree/index.js +28 -6
  643. package/dist/components/tree/index.js.map +1 -1
  644. package/dist/components/tree/item-actions.d.ts +19 -4
  645. package/dist/components/tree/item-actions.js +16 -2
  646. package/dist/components/tree/item-actions.js.map +1 -1
  647. package/dist/components/tree/item-content.d.ts +18 -4
  648. package/dist/components/tree/item-content.js +20 -3
  649. package/dist/components/tree/item-content.js.map +1 -1
  650. package/dist/components/tree/item-description.d.ts +15 -4
  651. package/dist/components/tree/item-description.js +13 -2
  652. package/dist/components/tree/item-description.js.map +1 -1
  653. package/dist/components/tree/item-label.d.ts +15 -4
  654. package/dist/components/tree/item-label.js +13 -2
  655. package/dist/components/tree/item-label.js.map +1 -1
  656. package/dist/components/tree/item-prefix-icon.d.ts +15 -4
  657. package/dist/components/tree/item-prefix-icon.js +13 -2
  658. package/dist/components/tree/item-prefix-icon.js.map +1 -1
  659. package/dist/components/tree/item.d.ts +24 -4
  660. package/dist/components/tree/item.js +21 -2
  661. package/dist/components/tree/item.js.map +1 -1
  662. package/dist/components/tree/lines.d.ts +10 -2
  663. package/dist/components/tree/lines.js +8 -0
  664. package/dist/components/tree/lines.js.map +1 -1
  665. package/dist/components/tree/types.d.ts +26 -0
  666. package/dist/components/view-stack/context.d.ts +20 -9
  667. package/dist/components/view-stack/context.js +18 -7
  668. package/dist/components/view-stack/context.js.map +1 -1
  669. package/dist/components/view-stack/events.d.ts +2 -0
  670. package/dist/components/view-stack/events.js +2 -0
  671. package/dist/components/view-stack/events.js.map +1 -1
  672. package/dist/components/view-stack/index.d.ts +16 -24
  673. package/dist/components/view-stack/index.js +14 -22
  674. package/dist/components/view-stack/index.js.map +1 -1
  675. package/dist/components/view-stack/trigger.d.ts +26 -4
  676. package/dist/components/view-stack/trigger.js +23 -2
  677. package/dist/components/view-stack/trigger.js.map +1 -1
  678. package/dist/components/view-stack/types.d.ts +29 -0
  679. package/dist/components/view-stack/view.d.ts +22 -2
  680. package/dist/components/view-stack/view.js +19 -0
  681. package/dist/components/view-stack/view.js.map +1 -1
  682. package/dist/hooks/coordinate-field/use-coordinate-copy.d.ts +44 -0
  683. package/dist/hooks/coordinate-field/use-coordinate-copy.js +35 -0
  684. package/dist/hooks/coordinate-field/use-coordinate-copy.js.map +1 -1
  685. package/dist/hooks/coordinate-field/use-coordinate-field-state.d.ts +69 -0
  686. package/dist/hooks/coordinate-field/use-coordinate-field-state.js +50 -0
  687. package/dist/hooks/coordinate-field/use-coordinate-field-state.js.map +1 -1
  688. package/dist/hooks/coordinate-field/use-coordinate-field.d.ts +61 -0
  689. package/dist/hooks/coordinate-field/use-coordinate-field.js +47 -0
  690. package/dist/hooks/coordinate-field/use-coordinate-field.js.map +1 -1
  691. package/dist/hooks/coordinate-field/use-coordinate-focus.d.ts +51 -0
  692. package/dist/hooks/coordinate-field/use-coordinate-focus.js +39 -0
  693. package/dist/hooks/coordinate-field/use-coordinate-focus.js.map +1 -1
  694. package/dist/hooks/coordinate-field/use-coordinate-paste.d.ts +63 -0
  695. package/dist/hooks/coordinate-field/use-coordinate-paste.js +51 -0
  696. package/dist/hooks/coordinate-field/use-coordinate-paste.js.map +1 -1
  697. package/dist/hooks/coordinate-field/use-timeout-cleanup.d.ts +32 -0
  698. package/dist/hooks/coordinate-field/use-timeout-cleanup.js +30 -0
  699. package/dist/hooks/coordinate-field/use-timeout-cleanup.js.map +1 -1
  700. package/dist/hooks/use-frame-delay/index.d.ts +5 -0
  701. package/dist/hooks/use-frame-delay/index.js +5 -0
  702. package/dist/hooks/use-frame-delay/index.js.map +1 -1
  703. package/dist/hooks/use-tree/actions/index.d.ts +4 -2
  704. package/dist/hooks/use-tree/actions/index.js +4 -2
  705. package/dist/hooks/use-tree/actions/index.js.map +1 -1
  706. package/dist/hooks/use-tree/state/index.d.ts +7 -0
  707. package/dist/hooks/use-tree/state/index.js +7 -0
  708. package/dist/hooks/use-tree/state/index.js.map +1 -1
  709. package/dist/hooks/use-tree/types.d.ts +22 -0
  710. package/dist/index.d.ts +4 -4
  711. package/dist/index.js +1 -1
  712. package/dist/lib/types.d.ts +17 -0
  713. package/dist/lib/utils.d.ts +15 -0
  714. package/dist/lib/utils.js +15 -0
  715. package/dist/lib/utils.js.map +1 -1
  716. package/dist/providers/portal.d.ts +11 -2
  717. package/dist/providers/portal.js +9 -0
  718. package/dist/providers/portal.js.map +1 -1
  719. package/dist/providers/theme-provider.d.ts +18 -2
  720. package/dist/providers/theme-provider.js +15 -0
  721. package/dist/providers/theme-provider.js.map +1 -1
  722. package/package.json +3 -3
@@ -13,24 +13,37 @@
13
13
  import { OptionsDataItem } from "../options/types.js";
14
14
  import { ComboBoxFieldProps } from "./types.js";
15
15
  import "client-only";
16
- import * as react_jsx_runtime30 from "react/jsx-runtime";
16
+ import * as react_jsx_runtime32 from "react/jsx-runtime";
17
17
 
18
18
  //#region src/components/combobox-field/index.d.ts
19
+
19
20
  /**
20
21
  * ComboBoxField - Accessible searchable combobox with dropdown options
21
22
  *
22
23
  * A combobox field that provides a searchable input with virtualized dropdown
23
24
  * options and support for sections, icons, and rich content.
24
25
  *
26
+ * @param props - The combobox field props.
27
+ * @param props.ref - Reference to the field element.
28
+ * @param props.children - Render function for options.
29
+ * @param props.classNames - Custom class names for sub-elements.
30
+ * @param props.label - Label text displayed above the field.
31
+ * @param props.description - Helper text displayed below the field.
32
+ * @param props.errorMessage - Error message displayed when invalid.
33
+ * @param props.size - Size variant of the field.
34
+ * @returns The combobox field component.
35
+ *
25
36
  * @example
37
+ * ```tsx
26
38
  * <ComboBoxField defaultItems={items}>
27
39
  * {(item) => <OptionsItem key={item.id} textValue={item.name}>{item.name}</OptionsItem>}
28
40
  * </ComboBoxField>
41
+ * ```
29
42
  */
30
43
  declare function ComboBoxField<T extends OptionsDataItem>({
31
44
  ref,
32
45
  ...props
33
- }: ComboBoxFieldProps<T>): react_jsx_runtime30.JSX.Element;
46
+ }: ComboBoxFieldProps<T>): react_jsx_runtime32.JSX.Element;
34
47
  //#endregion
35
48
  export { ComboBoxField };
36
49
  //# sourceMappingURL=index.d.ts.map
@@ -21,7 +21,7 @@ import "client-only";
21
21
  import { clsx } from "@accelint/design-foundation/lib/utils";
22
22
  import { Button, ComboBox, FieldError, Input, ListLayout, Popover, Text, Virtualizer, composeRenderProps, useContextProps } from "react-aria-components";
23
23
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
24
- import { ChevronDown } from "@accelint/icons";
24
+ import ChevronDown from "@accelint/icons/chevron-down";
25
25
  import styles from "./styles.module.css";
26
26
 
27
27
  //#region src/components/combobox-field/index.tsx
@@ -31,10 +31,22 @@ import styles from "./styles.module.css";
31
31
  * A combobox field that provides a searchable input with virtualized dropdown
32
32
  * options and support for sections, icons, and rich content.
33
33
  *
34
+ * @param props - The combobox field props.
35
+ * @param props.ref - Reference to the field element.
36
+ * @param props.children - Render function for options.
37
+ * @param props.classNames - Custom class names for sub-elements.
38
+ * @param props.label - Label text displayed above the field.
39
+ * @param props.description - Helper text displayed below the field.
40
+ * @param props.errorMessage - Error message displayed when invalid.
41
+ * @param props.size - Size variant of the field.
42
+ * @returns The combobox field component.
43
+ *
34
44
  * @example
45
+ * ```tsx
35
46
  * <ComboBoxField defaultItems={items}>
36
47
  * {(item) => <OptionsItem key={item.id} textValue={item.name}>{item.name}</OptionsItem>}
37
48
  * </ComboBoxField>
49
+ * ```
38
50
  */
39
51
  function ComboBoxField({ ref, ...props }) {
40
52
  [props, ref] = useContextProps(props, ref ?? null, ComboBoxFieldContext);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Label"],"sources":["../../../src/components/combobox-field/index.tsx"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n'use client';\n\nimport { ChevronDown } from '@accelint/icons';\nimport 'client-only';\nimport { clsx } from '@accelint/design-foundation/lib/utils';\nimport {\n Button,\n ComboBox,\n composeRenderProps,\n FieldError,\n Input,\n ListLayout,\n Popover,\n Text,\n useContextProps,\n Virtualizer,\n} from 'react-aria-components';\nimport { Icon } from '../icon';\nimport { Label } from '../label';\nimport { Options } from '../options';\nimport { ComboBoxFieldContext } from './context';\nimport styles from './styles.module.css';\nimport type { OptionsDataItem } from '../options/types';\nimport type { ComboBoxFieldProps } from './types';\n\n/**\n * ComboBoxField - Accessible searchable combobox with dropdown options\n *\n * A combobox field that provides a searchable input with virtualized dropdown\n * options and support for sections, icons, and rich content.\n *\n * @example\n * <ComboBoxField defaultItems={items}>\n * {(item) => <OptionsItem key={item.id} textValue={item.name}>{item.name}</OptionsItem>}\n * </ComboBoxField>\n */\nexport function ComboBoxField<T extends OptionsDataItem>({\n ref,\n ...props\n}: ComboBoxFieldProps<T>) {\n [props, ref] = useContextProps(props, ref ?? null, ComboBoxFieldContext);\n\n const {\n children,\n classNames,\n description: descriptionProp,\n errorMessage: errorMessageProp,\n inputProps,\n label: labelProp,\n layoutOptions,\n menuTrigger = 'focus',\n size = 'medium',\n isInvalid: isInvalidProp,\n isReadOnly = false,\n ...rest\n } = props;\n const errorMessage = errorMessageProp || null; // Protect against empty string\n const isSmall = size === 'small';\n\n return (\n <ComboBox<T>\n {...rest}\n ref={ref}\n className={composeRenderProps(classNames?.field, (className) =>\n clsx('group/combobox-field', styles.field, className),\n )}\n menuTrigger={menuTrigger}\n isInvalid={isInvalidProp || (errorMessage ? true : undefined)} // Leave uncontrolled if possible to fallback to validation state\n isReadOnly={isReadOnly}\n data-size={size}\n >\n {(\n { isDisabled, isInvalid, isRequired }, // Rely on internal state, not props, since state could differ from props\n ) => {\n const shouldShowDescription =\n !isReadOnly && !!descriptionProp && !(isSmall || isInvalid);\n\n return (\n <>\n {!!labelProp && !isSmall && (\n <Label\n className={clsx(styles.label, classNames?.label)}\n isDisabled={isDisabled}\n isRequired={isRequired}\n >\n {labelProp}\n </Label>\n )}\n <div\n className={clsx(styles.control, classNames?.control)}\n data-readonly={isReadOnly || null}\n >\n <Input\n {...inputProps}\n tabIndex={isReadOnly ? -1 : 0}\n className={composeRenderProps(classNames?.input, (className) =>\n clsx(styles.input, className),\n )}\n title={inputProps?.value ? String(inputProps?.value) : ''}\n />\n {!isReadOnly && (\n <Button\n className={composeRenderProps(\n classNames?.trigger,\n (className) => clsx(styles.trigger, className),\n )}\n >\n <Icon size='small'>\n <ChevronDown />\n </Icon>\n </Button>\n )}\n </div>\n {shouldShowDescription && (\n <Text\n className={clsx(styles.description, classNames?.description)}\n slot='description'\n >\n {descriptionProp}\n </Text>\n )}\n <FieldError\n className={composeRenderProps(classNames?.error, (className) =>\n clsx(styles.error, className),\n )}\n >\n {errorMessage}\n </FieldError>\n <Popover\n className={composeRenderProps(classNames?.popover, (className) =>\n clsx(styles.popover, className),\n )}\n >\n <Virtualizer layout={ListLayout} layoutOptions={layoutOptions}>\n <Options>{children}</Options>\n </Virtualizer>\n </Popover>\n </>\n );\n }}\n </ComboBox>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,SAAgB,cAAyC,EACvD,KACA,GAAG,SACqB;AACxB,EAAC,OAAO,OAAO,gBAAgB,OAAO,OAAO,MAAM,qBAAqB;CAExE,MAAM,EACJ,UACA,YACA,aAAa,iBACb,cAAc,kBACd,YACA,OAAO,WACP,eACA,cAAc,SACd,OAAO,UACP,WAAW,eACX,aAAa,OACb,GAAG,SACD;CACJ,MAAM,eAAe,oBAAoB;CACzC,MAAM,UAAU,SAAS;AAEzB,QACE,oBAAC;EACC,GAAI;EACC;EACL,WAAW,mBAAmB,YAAY,QAAQ,cAChD,KAAK,wBAAwB,OAAO,OAAO,UAAU,CACtD;EACY;EACb,WAAW,kBAAkB,eAAe,OAAO;EACvC;EACZ,aAAW;aAGT,EAAE,YAAY,WAAW,iBACtB;GACH,MAAM,wBACJ,CAAC,cAAc,CAAC,CAAC,mBAAmB,EAAE,WAAW;AAEnD,UACE;IACG,CAAC,CAAC,aAAa,CAAC,WACf,oBAACA;KACC,WAAW,KAAK,OAAO,OAAO,YAAY,MAAM;KACpC;KACA;eAEX;MACK;IAEV,qBAAC;KACC,WAAW,KAAK,OAAO,SAAS,YAAY,QAAQ;KACpD,iBAAe,cAAc;gBAE7B,oBAAC;MACC,GAAI;MACJ,UAAU,aAAa,KAAK;MAC5B,WAAW,mBAAmB,YAAY,QAAQ,cAChD,KAAK,OAAO,OAAO,UAAU,CAC9B;MACD,OAAO,YAAY,QAAQ,OAAO,YAAY,MAAM,GAAG;OACvD,EACD,CAAC,cACA,oBAAC;MACC,WAAW,mBACT,YAAY,UACX,cAAc,KAAK,OAAO,SAAS,UAAU,CAC/C;gBAED,oBAAC;OAAK,MAAK;iBACT,oBAAC,gBAAc;QACV;OACA;MAEP;IACL,yBACC,oBAAC;KACC,WAAW,KAAK,OAAO,aAAa,YAAY,YAAY;KAC5D,MAAK;eAEJ;MACI;IAET,oBAAC;KACC,WAAW,mBAAmB,YAAY,QAAQ,cAChD,KAAK,OAAO,OAAO,UAAU,CAC9B;eAEA;MACU;IACb,oBAAC;KACC,WAAW,mBAAmB,YAAY,UAAU,cAClD,KAAK,OAAO,SAAS,UAAU,CAChC;eAED,oBAAC;MAAY,QAAQ;MAA2B;gBAC9C,oBAAC,WAAS,WAAmB;OACjB;MACN;OACT;;GAGE"}
1
+ {"version":3,"file":"index.js","names":["Label"],"sources":["../../../src/components/combobox-field/index.tsx"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n'use client';\nimport 'client-only';\nimport { clsx } from '@accelint/design-foundation/lib/utils';\nimport ChevronDown from '@accelint/icons/chevron-down';\nimport {\n Button,\n ComboBox,\n composeRenderProps,\n FieldError,\n Input,\n ListLayout,\n Popover,\n Text,\n useContextProps,\n Virtualizer,\n} from 'react-aria-components';\nimport { Icon } from '../icon';\nimport { Label } from '../label';\nimport { Options } from '../options';\nimport { ComboBoxFieldContext } from './context';\nimport styles from './styles.module.css';\nimport type { OptionsDataItem } from '../options/types';\nimport type { ComboBoxFieldProps } from './types';\n\n/**\n * ComboBoxField - Accessible searchable combobox with dropdown options\n *\n * A combobox field that provides a searchable input with virtualized dropdown\n * options and support for sections, icons, and rich content.\n *\n * @param props - The combobox field props.\n * @param props.ref - Reference to the field element.\n * @param props.children - Render function for options.\n * @param props.classNames - Custom class names for sub-elements.\n * @param props.label - Label text displayed above the field.\n * @param props.description - Helper text displayed below the field.\n * @param props.errorMessage - Error message displayed when invalid.\n * @param props.size - Size variant of the field.\n * @returns The combobox field component.\n *\n * @example\n * ```tsx\n * <ComboBoxField defaultItems={items}>\n * {(item) => <OptionsItem key={item.id} textValue={item.name}>{item.name}</OptionsItem>}\n * </ComboBoxField>\n * ```\n */\nexport function ComboBoxField<T extends OptionsDataItem>({\n ref,\n ...props\n}: ComboBoxFieldProps<T>) {\n [props, ref] = useContextProps(props, ref ?? null, ComboBoxFieldContext);\n\n const {\n children,\n classNames,\n description: descriptionProp,\n errorMessage: errorMessageProp,\n inputProps,\n label: labelProp,\n layoutOptions,\n menuTrigger = 'focus',\n size = 'medium',\n isInvalid: isInvalidProp,\n isReadOnly = false,\n ...rest\n } = props;\n const errorMessage = errorMessageProp || null; // Protect against empty string\n const isSmall = size === 'small';\n\n return (\n <ComboBox<T>\n {...rest}\n ref={ref}\n className={composeRenderProps(classNames?.field, (className) =>\n clsx('group/combobox-field', styles.field, className),\n )}\n menuTrigger={menuTrigger}\n isInvalid={isInvalidProp || (errorMessage ? true : undefined)} // Leave uncontrolled if possible to fallback to validation state\n isReadOnly={isReadOnly}\n data-size={size}\n >\n {(\n { isDisabled, isInvalid, isRequired }, // Rely on internal state, not props, since state could differ from props\n ) => {\n const shouldShowDescription =\n !isReadOnly && !!descriptionProp && !(isSmall || isInvalid);\n\n return (\n <>\n {!!labelProp && !isSmall && (\n <Label\n className={clsx(styles.label, classNames?.label)}\n isDisabled={isDisabled}\n isRequired={isRequired}\n >\n {labelProp}\n </Label>\n )}\n <div\n className={clsx(styles.control, classNames?.control)}\n data-readonly={isReadOnly || null}\n >\n <Input\n {...inputProps}\n tabIndex={isReadOnly ? -1 : 0}\n className={composeRenderProps(classNames?.input, (className) =>\n clsx(styles.input, className),\n )}\n title={inputProps?.value ? String(inputProps?.value) : ''}\n />\n {!isReadOnly && (\n <Button\n className={composeRenderProps(\n classNames?.trigger,\n (className) => clsx(styles.trigger, className),\n )}\n >\n <Icon size='small'>\n <ChevronDown />\n </Icon>\n </Button>\n )}\n </div>\n {shouldShowDescription && (\n <Text\n className={clsx(styles.description, classNames?.description)}\n slot='description'\n >\n {descriptionProp}\n </Text>\n )}\n <FieldError\n className={composeRenderProps(classNames?.error, (className) =>\n clsx(styles.error, className),\n )}\n >\n {errorMessage}\n </FieldError>\n <Popover\n className={composeRenderProps(classNames?.popover, (className) =>\n clsx(styles.popover, className),\n )}\n >\n <Virtualizer layout={ListLayout} layoutOptions={layoutOptions}>\n <Options>{children}</Options>\n </Virtualizer>\n </Popover>\n </>\n );\n }}\n </ComboBox>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,SAAgB,cAAyC,EACvD,KACA,GAAG,SACqB;AACxB,EAAC,OAAO,OAAO,gBAAgB,OAAO,OAAO,MAAM,qBAAqB;CAExE,MAAM,EACJ,UACA,YACA,aAAa,iBACb,cAAc,kBACd,YACA,OAAO,WACP,eACA,cAAc,SACd,OAAO,UACP,WAAW,eACX,aAAa,OACb,GAAG,SACD;CACJ,MAAM,eAAe,oBAAoB;CACzC,MAAM,UAAU,SAAS;AAEzB,QACE,oBAAC;EACC,GAAI;EACC;EACL,WAAW,mBAAmB,YAAY,QAAQ,cAChD,KAAK,wBAAwB,OAAO,OAAO,UAAU,CACtD;EACY;EACb,WAAW,kBAAkB,eAAe,OAAO;EACvC;EACZ,aAAW;aAGT,EAAE,YAAY,WAAW,iBACtB;GACH,MAAM,wBACJ,CAAC,cAAc,CAAC,CAAC,mBAAmB,EAAE,WAAW;AAEnD,UACE;IACG,CAAC,CAAC,aAAa,CAAC,WACf,oBAACA;KACC,WAAW,KAAK,OAAO,OAAO,YAAY,MAAM;KACpC;KACA;eAEX;MACK;IAEV,qBAAC;KACC,WAAW,KAAK,OAAO,SAAS,YAAY,QAAQ;KACpD,iBAAe,cAAc;gBAE7B,oBAAC;MACC,GAAI;MACJ,UAAU,aAAa,KAAK;MAC5B,WAAW,mBAAmB,YAAY,QAAQ,cAChD,KAAK,OAAO,OAAO,UAAU,CAC9B;MACD,OAAO,YAAY,QAAQ,OAAO,YAAY,MAAM,GAAG;OACvD,EACD,CAAC,cACA,oBAAC;MACC,WAAW,mBACT,YAAY,UACX,cAAc,KAAK,OAAO,SAAS,UAAU,CAC/C;gBAED,oBAAC;OAAK,MAAK;iBACT,oBAAC,gBAAc;QACV;OACA;MAEP;IACL,yBACC,oBAAC;KACC,WAAW,KAAK,OAAO,aAAa,YAAY,YAAY;KAC5D,MAAK;eAEJ;MACI;IAET,oBAAC;KACC,WAAW,mBAAmB,YAAY,QAAQ,cAChD,KAAK,OAAO,OAAO,UAAU,CAC9B;eAEA;MACU;IACb,oBAAC;KACC,WAAW,mBAAmB,YAAY,UAAU,cAClD,KAAK,OAAO,SAAS,UAAU,CAChC;eAED,oBAAC;MAAY,QAAQ;MAA2B;gBAC9C,oBAAC,WAAS,WAAmB;OACjB;MACN;OACT;;GAGE"}
@@ -16,21 +16,40 @@ import { RefAttributes } from "react";
16
16
  import { ComboBoxProps, FieldErrorProps, InputProps, LabelProps, ListLayoutOptions, PopoverProps, VirtualizerProps } from "react-aria-components";
17
17
 
18
18
  //#region src/components/combobox-field/types.d.ts
19
+ /**
20
+ * Props for the ComboBoxField component.
21
+ *
22
+ * Extends ComboBox props with virtualization, styling, and field configuration.
23
+ */
19
24
  type ComboBoxFieldProps<T extends OptionsDataItem> = Omit<ComboBoxProps<T>, 'children' | 'className'> & Pick<VirtualizerProps<ListLayoutOptions>, 'layoutOptions'> & Pick<OptionsProps<T>, 'children'> & RefAttributes<HTMLDivElement> & {
25
+ /** Custom class names for sub-elements. */
20
26
  classNames?: {
27
+ /** Class name for the field container. */
21
28
  field?: ComboBoxProps<T>['className'];
29
+ /** Class name for the label. */
22
30
  label?: LabelProps['className'];
31
+ /** Class name for the control wrapper. */
23
32
  control?: string;
33
+ /** Class name for the input element. */
24
34
  input?: InputProps['className'];
35
+ /** Class name for the trigger button. */
25
36
  trigger?: ButtonProps$1['className'];
37
+ /** Class name for the description text. */
26
38
  description?: string;
39
+ /** Class name for the error message. */
27
40
  error?: FieldErrorProps['className'];
41
+ /** Class name for the popover dropdown. */
28
42
  popover?: PopoverProps['className'];
29
43
  };
44
+ /** Label text displayed above the field. */
30
45
  label?: string;
46
+ /** Additional props passed to the input element. */
31
47
  inputProps?: Omit<InputProps, 'className'>;
48
+ /** Helper text displayed below the field. */
32
49
  description?: string;
50
+ /** Error message displayed when invalid. */
33
51
  errorMessage?: string;
52
+ /** Size variant of the field. */
34
53
  size?: 'small' | 'medium';
35
54
  };
36
55
  //#endregion
@@ -12,9 +12,9 @@
12
12
 
13
13
  import { ProviderProps } from "../../lib/types.js";
14
14
  import { CoordinateFieldProps, CoordinateFieldState } from "./types.js";
15
- import * as react10 from "react";
15
+ import * as react14 from "react";
16
16
  import { ContextValue } from "react-aria-components";
17
- import * as react_jsx_runtime26 from "react/jsx-runtime";
17
+ import * as react_jsx_runtime34 from "react/jsx-runtime";
18
18
 
19
19
  //#region src/components/coordinate-field/context.d.ts
20
20
 
@@ -48,7 +48,7 @@ import * as react_jsx_runtime26 from "react/jsx-runtime";
48
48
  *
49
49
  * @see CoordinateFieldStateContext for internal runtime state
50
50
  */
51
- declare const CoordinateFieldContext: react10.Context<ContextValue<CoordinateFieldProps, HTMLDivElement>>;
51
+ declare const CoordinateFieldContext: react14.Context<ContextValue<CoordinateFieldProps, HTMLDivElement>>;
52
52
  /**
53
53
  * State Context for CoordinateField component.
54
54
  *
@@ -66,18 +66,27 @@ declare const CoordinateFieldContext: react10.Context<ContextValue<CoordinateFie
66
66
  * const state = useCoordinateFieldStateContext();
67
67
  * const { segmentValues, isDisabled, registerTimeout } = state;
68
68
  */
69
- declare const CoordinateFieldStateContext: react10.Context<CoordinateFieldState | null>;
69
+ declare const CoordinateFieldStateContext: react14.Context<CoordinateFieldState | null>;
70
70
  /**
71
71
  * Provider component for CoordinateField context
72
72
  * Wraps children with CoordinateFieldContext
73
+ *
74
+ * @param props - The provider props.
75
+ * @param props.children - Child components that will receive the coordinate field context.
76
+ * @returns The coordinate field context provider wrapping children.
73
77
  */
74
78
  declare function CoordinateFieldProvider({
75
79
  children,
76
80
  ...props
77
- }: ProviderProps<CoordinateFieldProps>): react_jsx_runtime26.JSX.Element;
81
+ }: ProviderProps<CoordinateFieldProps>): react_jsx_runtime34.JSX.Element;
78
82
  /**
79
83
  * Provider component for CoordinateField state context
80
84
  * Wraps children with CoordinateFieldStateContext
85
+ *
86
+ * @param props - The provider props.
87
+ * @param props.children - Child components that will receive the state context.
88
+ * @param props.value - The coordinate field state to provide.
89
+ * @returns The coordinate field state context provider wrapping children.
81
90
  */
82
91
  declare function CoordinateFieldStateProvider({
83
92
  children,
@@ -85,7 +94,7 @@ declare function CoordinateFieldStateProvider({
85
94
  }: {
86
95
  children: React.ReactNode;
87
96
  value: CoordinateFieldState;
88
- }): react_jsx_runtime26.JSX.Element;
97
+ }): react_jsx_runtime34.JSX.Element;
89
98
  /**
90
99
  * Hook to access CoordinateField state context
91
100
  * Must be used within a CoordinateField component
@@ -69,6 +69,10 @@ const CoordinateFieldStateContext = createContext(null);
69
69
  /**
70
70
  * Provider component for CoordinateField context
71
71
  * Wraps children with CoordinateFieldContext
72
+ *
73
+ * @param props - The provider props.
74
+ * @param props.children - Child components that will receive the coordinate field context.
75
+ * @returns The coordinate field context provider wrapping children.
72
76
  */
73
77
  function CoordinateFieldProvider({ children, ...props }) {
74
78
  return /* @__PURE__ */ jsx(CoordinateFieldContext.Provider, {
@@ -79,6 +83,11 @@ function CoordinateFieldProvider({ children, ...props }) {
79
83
  /**
80
84
  * Provider component for CoordinateField state context
81
85
  * Wraps children with CoordinateFieldStateContext
86
+ *
87
+ * @param props - The provider props.
88
+ * @param props.children - Child components that will receive the state context.
89
+ * @param props.value - The coordinate field state to provide.
90
+ * @returns The coordinate field state context provider wrapping children.
82
91
  */
83
92
  function CoordinateFieldStateProvider({ children, value }) {
84
93
  return /* @__PURE__ */ jsx(CoordinateFieldStateContext.Provider, {
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","names":[],"sources":["../../../src/components/coordinate-field/context.tsx"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport { createContext, useContext } from 'react';\nimport type { ContextValue } from 'react-aria-components';\nimport type { ProviderProps } from '@/lib/types';\nimport type { CoordinateFieldProps, CoordinateFieldState } from './types';\n\n/**\n * CoordinateField Context Architecture\n *\n * This file defines two separate contexts following the React Aria component pattern:\n *\n * 1. CoordinateFieldContext (Props Context):\n * - Contains user-provided props for the component\n * - Used for React Aria's context-based prop merging\n * - Part of the public composition API\n *\n * 2. CoordinateFieldStateContext (State Context):\n * - Contains derived/computed runtime state\n * - Used to share state with child components (e.g., CoordinateSegment)\n * - Primarily for internal use\n\n * Separation keeps the public API (props) distinct from internal\n * implementation details (state), improving maintainability and composition.\n */\n\n/**\n * Props Context for CoordinateField component.\n *\n * Contains user-provided props (label, format, size, value, onChange, etc.)\n * and is used by React Aria's useContextProps hook for context-based prop merging.\n * This enables parent components to provide default props to nested CoordinateField\n * components, supporting composition patterns.\n *\n * Part of the public API - external consumers can use this for component composition.\n *\n * @see CoordinateFieldStateContext for internal runtime state\n */\nexport const CoordinateFieldContext =\n createContext<ContextValue<CoordinateFieldProps, HTMLDivElement>>(null);\n\n/**\n * State Context for CoordinateField component.\n *\n * Contains derived/computed runtime state (segmentValues, currentValue,\n * validationErrors, registerTimeout, etc.) that is shared with child components\n * like CoordinateSegment. This avoids prop drilling for deeply nested children.\n *\n * This follows the React Aria pattern of separating props context (public API)\n * from state context (internal implementation). While exported for composition\n * scenarios and testing, this is primarily for internal use.\n *\n * @see CoordinateFieldContext for user-provided props\n * @example\n * // Used internally by child components\n * const state = useCoordinateFieldStateContext();\n * const { segmentValues, isDisabled, registerTimeout } = state;\n */\nexport const CoordinateFieldStateContext =\n createContext<CoordinateFieldState | null>(null);\n\n/**\n * Provider component for CoordinateField context\n * Wraps children with CoordinateFieldContext\n */\nexport function CoordinateFieldProvider({\n children,\n ...props\n}: ProviderProps<CoordinateFieldProps>) {\n return (\n <CoordinateFieldContext.Provider value={props}>\n {children}\n </CoordinateFieldContext.Provider>\n );\n}\n\n/**\n * Provider component for CoordinateField state context\n * Wraps children with CoordinateFieldStateContext\n */\nexport function CoordinateFieldStateProvider({\n children,\n value,\n}: {\n children: React.ReactNode;\n value: CoordinateFieldState;\n}) {\n return (\n <CoordinateFieldStateContext.Provider value={value}>\n {children}\n </CoordinateFieldStateContext.Provider>\n );\n}\n\n/**\n * Hook to access CoordinateField state context\n * Must be used within a CoordinateField component\n * @throws {Error} If used outside of CoordinateField\n * @returns {CoordinateFieldState} The coordinate field state\n */\nexport const useCoordinateFieldStateContext = () => {\n const context = useContext(CoordinateFieldStateContext);\n if (!context) {\n throw new Error(\n 'useCoordinateFieldStateContext must be used within CoordinateField',\n );\n }\n return context;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,MAAa,yBACX,cAAkE,KAAK;;;;;;;;;;;;;;;;;;AAmBzE,MAAa,8BACX,cAA2C,KAAK;;;;;AAMlD,SAAgB,wBAAwB,EACtC,UACA,GAAG,SACmC;AACtC,QACE,oBAAC,uBAAuB;EAAS,OAAO;EACrC;GAC+B;;;;;;AAQtC,SAAgB,6BAA6B,EAC3C,UACA,SAIC;AACD,QACE,oBAAC,4BAA4B;EAAgB;EAC1C;GACoC;;;;;;;;AAU3C,MAAa,uCAAuC;CAClD,MAAM,UAAU,WAAW,4BAA4B;AACvD,KAAI,CAAC,QACH,OAAM,IAAI,MACR,qEACD;AAEH,QAAO"}
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../../src/components/coordinate-field/context.tsx"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\n'use client';\n\nimport { createContext, useContext } from 'react';\nimport type { ContextValue } from 'react-aria-components';\nimport type { ProviderProps } from '@/lib/types';\nimport type { CoordinateFieldProps, CoordinateFieldState } from './types';\n\n/**\n * CoordinateField Context Architecture\n *\n * This file defines two separate contexts following the React Aria component pattern:\n *\n * 1. CoordinateFieldContext (Props Context):\n * - Contains user-provided props for the component\n * - Used for React Aria's context-based prop merging\n * - Part of the public composition API\n *\n * 2. CoordinateFieldStateContext (State Context):\n * - Contains derived/computed runtime state\n * - Used to share state with child components (e.g., CoordinateSegment)\n * - Primarily for internal use\n\n * Separation keeps the public API (props) distinct from internal\n * implementation details (state), improving maintainability and composition.\n */\n\n/**\n * Props Context for CoordinateField component.\n *\n * Contains user-provided props (label, format, size, value, onChange, etc.)\n * and is used by React Aria's useContextProps hook for context-based prop merging.\n * This enables parent components to provide default props to nested CoordinateField\n * components, supporting composition patterns.\n *\n * Part of the public API - external consumers can use this for component composition.\n *\n * @see CoordinateFieldStateContext for internal runtime state\n */\nexport const CoordinateFieldContext =\n createContext<ContextValue<CoordinateFieldProps, HTMLDivElement>>(null);\n\n/**\n * State Context for CoordinateField component.\n *\n * Contains derived/computed runtime state (segmentValues, currentValue,\n * validationErrors, registerTimeout, etc.) that is shared with child components\n * like CoordinateSegment. This avoids prop drilling for deeply nested children.\n *\n * This follows the React Aria pattern of separating props context (public API)\n * from state context (internal implementation). While exported for composition\n * scenarios and testing, this is primarily for internal use.\n *\n * @see CoordinateFieldContext for user-provided props\n * @example\n * // Used internally by child components\n * const state = useCoordinateFieldStateContext();\n * const { segmentValues, isDisabled, registerTimeout } = state;\n */\nexport const CoordinateFieldStateContext =\n createContext<CoordinateFieldState | null>(null);\n\n/**\n * Provider component for CoordinateField context\n * Wraps children with CoordinateFieldContext\n *\n * @param props - The provider props.\n * @param props.children - Child components that will receive the coordinate field context.\n * @returns The coordinate field context provider wrapping children.\n */\nexport function CoordinateFieldProvider({\n children,\n ...props\n}: ProviderProps<CoordinateFieldProps>) {\n return (\n <CoordinateFieldContext.Provider value={props}>\n {children}\n </CoordinateFieldContext.Provider>\n );\n}\n\n/**\n * Provider component for CoordinateField state context\n * Wraps children with CoordinateFieldStateContext\n *\n * @param props - The provider props.\n * @param props.children - Child components that will receive the state context.\n * @param props.value - The coordinate field state to provide.\n * @returns The coordinate field state context provider wrapping children.\n */\nexport function CoordinateFieldStateProvider({\n children,\n value,\n}: {\n children: React.ReactNode;\n value: CoordinateFieldState;\n}) {\n return (\n <CoordinateFieldStateContext.Provider value={value}>\n {children}\n </CoordinateFieldStateContext.Provider>\n );\n}\n\n/**\n * Hook to access CoordinateField state context\n * Must be used within a CoordinateField component\n * @throws {Error} If used outside of CoordinateField\n * @returns {CoordinateFieldState} The coordinate field state\n */\nexport const useCoordinateFieldStateContext = () => {\n const context = useContext(CoordinateFieldStateContext);\n if (!context) {\n throw new Error(\n 'useCoordinateFieldStateContext must be used within CoordinateField',\n );\n }\n return context;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,MAAa,yBACX,cAAkE,KAAK;;;;;;;;;;;;;;;;;;AAmBzE,MAAa,8BACX,cAA2C,KAAK;;;;;;;;;AAUlD,SAAgB,wBAAwB,EACtC,UACA,GAAG,SACmC;AACtC,QACE,oBAAC,uBAAuB;EAAS,OAAO;EACrC;GAC+B;;;;;;;;;;;AAatC,SAAgB,6BAA6B,EAC3C,UACA,SAIC;AACD,QACE,oBAAC,4BAA4B;EAAgB;EAC1C;GACoC;;;;;;;;AAU3C,MAAa,uCAAuC;CAClD,MAAM,UAAU,WAAW,4BAA4B;AACvD,KAAI,CAAC,QACH,OAAM,IAAI,MACR,qEACD;AAEH,QAAO"}
@@ -277,6 +277,11 @@ declare function isCompleteCoordinate(text: string): boolean;
277
277
  declare function parseCoordinatePaste(pastedText: string): ParsedCoordinateMatch[];
278
278
  /**
279
279
  * Check if two coordinates are equal within epsilon tolerance
280
+ *
281
+ * @param coord1 - First coordinate to compare.
282
+ * @param coord2 - Second coordinate to compare.
283
+ * @param epsilon - Tolerance for comparison (defaults to COORDINATE_EPSILON).
284
+ * @returns True if coordinates are equal within tolerance.
280
285
  */
281
286
  declare function areCoordinatesEqual(coord1: {
282
287
  lat: number;
@@ -287,6 +292,9 @@ declare function areCoordinatesEqual(coord1: {
287
292
  }, epsilon?: number): boolean;
288
293
  /**
289
294
  * Deduplicate coordinate matches by location, keeping first match for each unique location
295
+ *
296
+ * @param matches - Array of parsed coordinate matches to deduplicate.
297
+ * @returns Array of unique matches based on coordinate location.
290
298
  */
291
299
  declare function deduplicateMatchesByLocation(matches: ParsedCoordinateMatch[]): ParsedCoordinateMatch[];
292
300
  //#endregion
@@ -797,12 +797,20 @@ function parseCoordinatePaste(pastedText) {
797
797
  }
798
798
  /**
799
799
  * Check if two coordinates are equal within epsilon tolerance
800
+ *
801
+ * @param coord1 - First coordinate to compare.
802
+ * @param coord2 - Second coordinate to compare.
803
+ * @param epsilon - Tolerance for comparison (defaults to COORDINATE_EPSILON).
804
+ * @returns True if coordinates are equal within tolerance.
800
805
  */
801
806
  function areCoordinatesEqual(coord1, coord2, epsilon = COORDINATE_EPSILON) {
802
807
  return Math.abs(coord1.lat - coord2.lat) < epsilon && Math.abs(coord1.lon - coord2.lon) < epsilon;
803
808
  }
804
809
  /**
805
810
  * Deduplicate coordinate matches by location, keeping first match for each unique location
811
+ *
812
+ * @param matches - Array of parsed coordinate matches to deduplicate.
813
+ * @returns Array of unique matches based on coordinate location.
806
814
  */
807
815
  function deduplicateMatchesByLocation(matches) {
808
816
  const uniqueMatches = [];
@@ -1 +1 @@
1
- {"version":3,"file":"coordinate-utils.js","names":["coordString: string","formattedValue: string","matches: ParsedCoordinateMatch[]","displayString: string","uniqueMatches: ParsedCoordinateMatch[]"],"sources":["../../../src/components/coordinate-field/coordinate-utils.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { getLogger } from '@accelint/logger';\n\nconst logger = getLogger({\n enabled: process.env.NODE_ENV !== 'production',\n level: 'debug',\n prefix: '[CoordinateField]',\n pretty: true,\n});\n\n/**\n * Coordinate Conversion Utilities\n *\n * This module provides utilities for converting between:\n * 1. Segment values (user input) → Coordinate strings (for @accelint/geo parsing)\n * 2. Coordinate strings (from @accelint/geo output) → Segment values (for display)\n * 3. Decimal Degrees (internal format) ↔ Display format segment values\n *\n * All conversions use the local @accelint/geo package for accurate coordinate parsing\n * and conversion between coordinate systems.\n *\n * ## Architecture: Bridge Layer Between UI and Geo Package\n *\n * This module serves as a bridge layer to handle the impedance mismatch between:\n * - **UI Requirements**: Individual segment fields (e.g., degrees, minutes, seconds, direction)\n * - **Geo Package API**: Complete coordinate strings (e.g., \"40° 42' 46\" N / 74° 0' 22\" W\")\n *\n * ### Why This Bridge Layer Exists\n *\n * The @accelint/geo package provides excellent coordinate parsing, validation, and conversion,\n * but its API is designed around complete coordinate strings:\n *\n * ```typescript\n * // What geo provides:\n * const coord = createCoordinate(coordinateSystems.ddm, 'LATLON')('40 42.768 N / 74 0.36 W');\n * coord.dd() // Returns: \"40.7128 N / 74.006 W\" (formatted string)\n * coord.ddm() // Returns: \"40 42.768 N / 74 0.36 W\" (formatted string)\n * coord.raw // Returns: { LAT: 40.7128, LON: -74.006 } (only DD numbers)\n * ```\n *\n * The coordinate-field component needs segment-level data for individual input fields:\n * - DDM: ['40', '42.768', 'N', '74', '0.36', 'W'] ← Not provided by geo\n * - DMS: ['40', '42', '46.08', 'N', '74', '0', '21.6', 'W'] ← Not provided by geo\n *\n * ### Current Limitations and Duplication\n *\n * Because the geo package only exposes:\n * 1. **Formatters** that return complete strings (coord.ddm(), coord.dms(), etc.)\n * 2. **Raw values** in Decimal Degrees only (coord.raw)\n *\n * This module must:\n * 1. Build coordinate strings from segments → Pass to geo for parsing\n * 2. Parse geo's formatted output strings → Extract segments using regex\n *\n * This creates a circular conversion flow for DD → Display Segments:\n * ```\n * DD value → String → Geo parse → Geo format → String → Regex parse → Segments\n * ```\n *\n * **Note on Duplication**: The regex parsing in this module duplicates work that the\n * geo package parsers already do internally. However, since geo doesn't expose the\n * parsed segment components (only formatted strings and raw DD values), we must\n * re-parse its output to extract the individual segments for the UI.\n *\n * ### What Would Eliminate This Duplication\n *\n * If the geo package exported component-level converters like:\n * ```typescript\n * // Hypothetical API that would eliminate the bridge layer:\n * export function ddToDdmComponents(dd: number): {\n * degrees: number;\n * minutes: number;\n * direction: 'N' | 'S' | 'E' | 'W';\n * }\n * ```\n *\n * Then this bridge layer could be significantly simplified. The math for these conversions\n * exists in the geo package's formatters (e.g., formatDegreesDecimalMinutes), but it's\n * wrapped in string formatting logic rather than exposed as standalone utilities.\n *\n * ### Conversion Efficiency\n *\n * - **Efficient Path** (Display Segments → DD): Segments → String → Geo parse → DD\n * - Uses geo package for all parsing and validation ✓\n *\n * - **Inefficient Path** (DD → Display Segments): DD → String → Geo parse → Geo format → Regex parse → Segments\n * - Circular conversion with redundant string parsing/formatting ✗\n * - Necessary given current geo API limitations\n */\n\nimport { coordinateSystems, createCoordinate } from '@accelint/geo';\nimport {\n COORDINATE_SYSTEMS,\n type CoordinateSystem,\n type CoordinateValue,\n type ParsedCoordinateMatch,\n} from './types';\n\n/** Epsilon for coordinate equality comparison (≈11cm precision at equator) */\nexport const COORDINATE_EPSILON = 0.000001;\n\n/**\n * Error message constants for coordinate format conversion\n * @internal\n */\nexport const COORDINATE_ERROR_MESSAGES = {\n INVALID: 'Invalid coordinate',\n CONVERSION_FAILED: 'Conversion failed',\n NOT_AVAILABLE_AT_POLES: 'Not available at poles',\n} as const;\n\n/**\n * Result of coordinate format conversion\n */\nexport interface CoordinateFormatResult {\n /** The formatted coordinate string or error message */\n value: string;\n /** Whether the coordinate format is valid and can be used/copied */\n isValid: boolean;\n}\n\n/**\n * Format DD (Decimal Degrees) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatDDSegments(segments: string[]): string | null {\n if (segments.length < 2) {\n return null;\n }\n const latNum = Number.parseFloat(segments[0] as string);\n const lonNum = Number.parseFloat(segments[1] as string);\n\n if (Number.isNaN(latNum) || Number.isNaN(lonNum)) {\n return null;\n }\n\n const latDir = latNum >= 0 ? 'N' : 'S';\n const lonDir = lonNum >= 0 ? 'E' : 'W';\n\n return `${Math.abs(latNum)} ${latDir} / ${Math.abs(lonNum)} ${lonDir}`;\n}\n\n/**\n * Format DDM (Degrees Decimal Minutes) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatDDMSegments(segments: string[]): string | null {\n if (segments.length < 6) {\n return null;\n }\n return `${segments[0]}° ${segments[1]}' ${segments[2]}, ${segments[3]}° ${segments[4]}' ${segments[5]}`;\n}\n\n/**\n * Format DMS (Degrees Minutes Seconds) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatDMSSegments(segments: string[]): string | null {\n if (segments.length < 8) {\n return null;\n }\n return `${segments[0]}° ${segments[1]}' ${segments[2]}\" ${segments[3]}, ${segments[4]}° ${segments[5]}' ${segments[6]}\" ${segments[7]}`;\n}\n\n/**\n * Format MGRS (Military Grid Reference System) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatMGRSSegments(segments: string[]): string | null {\n if (segments.length < 5) {\n return null;\n }\n return `${segments[0]}${segments[1]} ${segments[2]} ${segments[3]} ${segments[4]}`;\n}\n\n/**\n * Format UTM (Universal Transverse Mercator) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatUTMSegments(segments: string[]): string | null {\n if (segments.length < 4) {\n return null;\n }\n return `${segments[0]}${segments[1]} ${segments[2]} ${segments[3]}`;\n}\n\n/**\n * Format segment values into a coordinate string suitable for @accelint/geo parsing\n *\n * Converts an array of segment values into a string format that the geo package\n * parsers can understand. Each format has different requirements:\n *\n * DD: [lat, lon] → \"lat, lon\"\n * DDM: [latDeg, latMin, latDir, lonDeg, lonMin, lonDir] → \"latDeg° latMin' latDir, lonDeg° lonMin' lonDir\"\n * DMS: [latDeg, latMin, latSec, latDir, lonDeg, lonMin, lonSec, lonDir] → \"latDeg° latMin' latSec\\\" latDir, lonDeg° lonMin' lonSec\\\" lonDir\"\n * MGRS: [zone, band, grid, easting, northing] → \"zone+band grid easting northing\"\n * UTM: [zone, hemisphere, easting, northing] → \"zone+hemisphere easting northing\"\n *\n * @param segments - Array of segment values from user input\n * @param format - The coordinate system format\n * @returns Formatted coordinate string, or null if segments are invalid\n */\nexport function formatSegmentsToCoordinateString(\n segments: string[],\n format: CoordinateSystem,\n): string | null {\n if (segments.some((seg) => seg === '' || seg === undefined)) {\n return null;\n }\n\n try {\n switch (format) {\n case 'dd':\n return formatDDSegments(segments);\n case 'ddm':\n return formatDDMSegments(segments);\n case 'dms':\n return formatDMSSegments(segments);\n case 'mgrs':\n return formatMGRSSegments(segments);\n case 'utm':\n return formatUTMSegments(segments);\n default:\n return null;\n }\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Format a decimal string to specified precision for display\n *\n * This is used to ensure consistent decimal precision when displaying\n * coordinate segments, regardless of the precision returned by the geo package.\n *\n * @param value - The decimal string to format\n * @param decimals - Number of decimal places to display\n * @returns Formatted string with specified precision\n * @internal\n */\nfunction formatDecimalPrecision(value: string, decimals: number): string {\n const num = Number.parseFloat(value);\n if (Number.isNaN(num)) {\n return value;\n }\n // Round to specified decimals, then remove trailing zeros\n return Number.parseFloat(num.toFixed(decimals)).toString();\n}\n\n/**\n * Parse DD coordinate string to segments\n *\n * Extracts segment values from a formatted DD coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseDecimalDegrees, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseDDCoordinateString(coordString: string): string[] | null {\n // DD formats from @accelint/geo (no degree symbols):\n // \"40.7128 N / -74.006 W\" or \"0 N / 180 W\"\n // Also handle user input with symbols:\n // \"89.765432° N / 123.456789° W\" or \"89.765432, -123.456789\"\n\n // Match DD format with optional degree symbols and optional direction letters\n const match = coordString.match(\n /([-]?\\d+\\.?\\d*)°?\\s*([NS])?\\s*[,/\\s]+\\s*([-]?\\d+\\.?\\d*)°?\\s*([EW])?/i,\n );\n if (!match) {\n return null;\n }\n\n let lat = match[1];\n let lon = match[3];\n\n if (!(lat && lon)) {\n return null;\n }\n\n if (match[2]?.toUpperCase() === 'S' && !lat.startsWith('-')) {\n lat = `-${lat}`;\n }\n if (match[4]?.toUpperCase() === 'W' && !lon.startsWith('-')) {\n lon = `-${lon}`;\n }\n\n return [lat, lon];\n}\n\n/**\n * Parse DDM coordinate string to segments\n *\n * Extracts segment values from a formatted DDM coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseDegreesDecimalMinutes, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseDDMCoordinateString(coordString: string): string[] | null {\n // DDM formats from @accelint/geo (no symbols):\n // \"40 42.768 N / 74 0.36 W\"\n // Also handle user input with symbols:\n // \"89° 45.9259' N / 123° 27.4073' W\"\n\n // Match DDM format with optional degree and minute symbols\n const match = coordString.match(\n /(\\d+)°?\\s+([\\d.]+)'?\\s+([NS])\\s*[,/]\\s*(\\d+)°?\\s+([\\d.]+)'?\\s+([EW])/i,\n );\n if (!match) {\n return null;\n }\n // Round minutes to 4 decimal places for display (CJCSI 3900.01E compliance)\n return [\n match[1] as string,\n formatDecimalPrecision(match[2] as string, 4),\n match[3] as string,\n match[4] as string,\n formatDecimalPrecision(match[5] as string, 4),\n match[6] as string,\n ];\n}\n\n/**\n * Parse DMS coordinate string to segments\n *\n * Extracts segment values from a formatted DMS coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseDegreesMinutesSeconds, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseDMSCoordinateString(coordString: string): string[] | null {\n // DMS formats from @accelint/geo (no symbols):\n // \"40 42 46.08 N / 74 0 21.60 W\"\n // Also handle user input with symbols:\n // \"89° 45' 55.56\" N / 123° 27' 24.44\" W\"\n\n // Match DMS format with optional degree, minute, and second symbols\n const match = coordString.match(\n /(\\d+)°?\\s+(\\d+)'?\\s+([\\d.]+)\"?\\s+([NS])\\s*[,/]\\s*(\\d+)°?\\s+(\\d+)'?\\s+([\\d.]+)\"?\\s+([EW])/i,\n );\n if (!match) {\n return null;\n }\n // Round seconds to 2 decimal places for display\n return [\n match[1] as string,\n match[2] as string,\n formatDecimalPrecision(match[3] as string, 2),\n match[4] as string,\n match[5] as string,\n match[6] as string,\n formatDecimalPrecision(match[7] as string, 2),\n match[8] as string,\n ];\n}\n\n/**\n * Parse MGRS coordinate string to segments\n *\n * Extracts segment values from a formatted MGRS coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseMGRS, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseMGRSCoordinateString(coordString: string): string[] | null {\n // MGRS: \"18T WM 12345 67890\"\n const match = coordString.match(/(\\d+)([A-Z])\\s+([A-Z]{2})\\s+(\\d+)\\s+(\\d+)/i);\n if (!match) {\n return null;\n }\n return [\n match[1] as string,\n match[2] as string,\n match[3] as string,\n match[4] as string,\n match[5] as string,\n ];\n}\n\n/**\n * Parse UTM coordinate string to segments\n *\n * Extracts segment values from a formatted UTM coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseUTM, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseUTMCoordinateString(coordString: string): string[] | null {\n // UTM: \"18N 585628 4511644\" or \"18 N 585628 4511644\" (with optional space)\n const match = coordString.match(/(\\d+)\\s*([NS])\\s+(\\d+)\\s+(\\d+)/i);\n if (!match) {\n return null;\n }\n return [\n match[1] as string,\n match[2] as string,\n match[3] as string,\n match[4] as string,\n ];\n}\n\n/**\n * Parse a coordinate string into segment values\n *\n * Converts a formatted coordinate string (from @accelint/geo output or user input)\n * back into individual segment values for display.\n *\n * This is the inverse of formatSegmentsToCoordinateString.\n *\n * **Note on Duplication**: This function and its helpers (parseDDCoordinateString,\n * parseDDMCoordinateString, etc.) duplicate parsing logic that already exists in\n * the @accelint/geo package parsers:\n *\n * - Geo parsers: parseDecimalDegrees, parseDegreesDecimalMinutes, etc.\n * - These functions: parseDDCoordinateString, parseDDMCoordinateString, etc.\n *\n * Both use regex patterns to extract coordinate components from strings. The duplication\n * exists because:\n *\n * 1. **Geo parsers** extract components, validate them, convert to DD, then format back to strings\n * 2. **This function** extracts components from those formatted strings for the UI\n *\n * We're essentially undoing the formatting that geo just did. This is the second half\n * of the circular conversion described in convertDDToDisplaySegments.\n *\n * **Why we can't use geo parsers directly**: The geo parsers return coord objects with\n * only `coord.raw` (DD numbers) and formatting methods. They don't expose the parsed\n * segment components we need for the UI (e.g., the degrees, minutes, and direction values).\n *\n * **Parsing Order**:\n * - **convertDisplaySegmentsToDD**: Segments → String → **Geo parse** → DD ✓ (efficient)\n * - **convertDDToDisplaySegments**: DD → String → Geo parse → Geo format → **This parse** → Segments ✗ (circular)\n *\n * @param coordString - Formatted coordinate string\n * @param format - The coordinate system format\n * @returns Array of segment values, or null if parsing fails\n */\nexport function parseCoordinateStringToSegments(\n coordString: string,\n format: CoordinateSystem,\n): string[] | null {\n if (!coordString) {\n return null;\n }\n\n try {\n switch (format) {\n case 'dd':\n return parseDDCoordinateString(coordString);\n case 'ddm':\n return parseDDMCoordinateString(coordString);\n case 'dms':\n return parseDMSCoordinateString(coordString);\n case 'mgrs':\n return parseMGRSCoordinateString(coordString);\n case 'utm':\n return parseUTMCoordinateString(coordString);\n default:\n return null;\n }\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Convert DD (internal format) to display format segment values\n *\n * Takes a CoordinateValue in Decimal Degrees format and converts it to the\n * segment values needed for the specified display format.\n *\n * Uses @accelint/geo to ensure accurate conversion between coordinate systems.\n *\n * **Note on Circular Conversion**: This function demonstrates the circular conversion\n * pattern discussed in the module documentation. The flow is:\n *\n * 1. Start with DD value: `{ lat: 40.7128, lon: -74.0060 }`\n * 2. Convert to coordinate string: `\"40.7128 / -74.006\"`\n * 3. Parse with geo package (creates coord object with internal parsed state)\n * 4. Format to target system using geo: `coord.ddm()` → `\"40 42.768 N / 74 0.36 W\"`\n * 5. Parse the formatted string AGAIN with regex to extract segments: `['40', '42.768', 'N', ...]`\n *\n * This is inefficient because:\n * - The geo package already has the component values (degrees, minutes, direction) internally\n * - We format them into a string, then immediately parse the string back apart\n * - The regex parsing duplicates work the geo parsers already did\n *\n * However, this approach is necessary because:\n * - The geo package only exposes `coord.raw` (DD numbers) and formatted strings\n * - It doesn't expose the intermediate component values we need for the UI segments\n * - We need individual segment values for separate input fields\n *\n * **Future Improvement**: If geo package exported component extractors like:\n * ```typescript\n * coord.components.ddm // { latDeg: 40, latMin: 42.768, latDir: 'N', ... }\n * ```\n * Then we could eliminate the format→parse cycle entirely.\n *\n * @param value - Coordinate value in DD format `{ lat: number, lon: number }`\n * @param format - Target display format\n * @returns Array of segment values for display, or null if conversion fails\n *\n * @example\n * const segments = convertDDToDisplaySegments({ lat: 40.7128, lon: -74.0060 }, 'ddm');\n * // Returns: ['40', '42.7680', 'N', '74', '0.3600', 'W']\n */\nexport function convertDDToDisplaySegments(\n value: CoordinateValue,\n format: CoordinateSystem,\n): string[] | null {\n if (\n !value ||\n typeof value.lat !== 'number' ||\n typeof value.lon !== 'number'\n ) {\n return null;\n }\n\n try {\n const create = createCoordinate(coordinateSystems.dd, 'LATLON');\n\n // Round to 10 decimal places to match geo package internal precision\n // Use signed numbers (not cardinal directions) for reliable conversions to all formats\n const lat = Number(value.lat.toFixed(10));\n const lon = Number(value.lon.toFixed(10));\n const inputCoordString = `${lat} / ${lon}`;\n\n const coord = create(inputCoordString);\n\n if (!coord.valid) {\n return null;\n }\n\n // Format the coordinate using geo package formatters\n // These return complete coordinate strings (e.g., \"40 42.768 N / 74 0.36 W\")\n let coordString: string;\n switch (format) {\n case 'dd':\n coordString = coord.dd();\n break;\n case 'ddm':\n coordString = coord.ddm();\n break;\n case 'dms':\n coordString = coord.dms();\n break;\n case 'mgrs':\n coordString = coord.mgrs();\n break;\n case 'utm':\n coordString = coord.utm();\n break;\n default:\n return null;\n }\n\n // Parse the formatted string to extract individual segment values\n // This is the circular part: geo formatted it, now we parse it back apart\n // Necessary because geo doesn't expose the components directly\n const segments = parseCoordinateStringToSegments(coordString, format);\n return segments;\n } catch (error) {\n logger\n .withContext({\n value: String(value),\n format: String(format),\n })\n .withError(error)\n .error('Failed to convert DD to display');\n return null;\n }\n}\n\n/**\n * Convert display format segment values to DD (internal format)\n *\n * Takes segment values from user input and converts them to a CoordinateValue\n * in Decimal Degrees format using @accelint/geo for validation and conversion.\n *\n * **Note on Efficiency**: This function demonstrates the EFFICIENT conversion direction.\n * The flow is:\n *\n * 1. Start with UI segments: `['40', '42.768', 'N', '74', '0.36', 'W']`\n * 2. Build coordinate string: `\"40° 42.768' N, 74° 0.36' W\"`\n * 3. Parse with geo package (validates and converts internally)\n * 4. Extract DD from coord.raw: `{ lat: 40.7128, lon: -74.0060 }`\n *\n * This is efficient because:\n * - We let geo do what it's designed for: parsing and validating coordinate strings\n * - We extract the DD values directly from `coord.raw` (no string parsing needed)\n * - Single direction: Segments → String → Geo Parse → DD (no circular conversion)\n *\n * Contrast with `convertDDToDisplaySegments` which has the circular pattern:\n * DD → String → Geo Parse → Geo Format → String → Regex Parse → Segments\n *\n * @param segments - Array of segment values from user input\n * @param format - The coordinate system format of the segments\n * @returns CoordinateValue in DD format, or null if invalid\n *\n * @example\n * const coord = convertDisplaySegmentsToDD(['40', '42.7680', 'N', '74', '0.3600', 'W'], 'ddm');\n * // Returns: { lat: 40.7128, lon: -74.0060 }\n */\nexport function convertDisplaySegmentsToDD(\n segments: string[],\n format: CoordinateSystem,\n): CoordinateValue | null {\n // Build coordinate string from segments for geo parsing\n const coordString = formatSegmentsToCoordinateString(segments, format);\n if (!coordString) {\n return null;\n }\n\n try {\n // Parse and validate with geo package\n const create = createCoordinate(coordinateSystems[format], 'LATLON');\n const coord = create(coordString);\n\n if (!coord.valid) {\n // Return null for invalid coordinates (errors will be handled separately)\n return null;\n }\n\n // Extract DD values directly from coord.raw and round to 6 decimals\n // This ensures consistency with convertDDToDisplaySegments and getAllCoordinateFormats\n const { LAT, LON } = coord.raw;\n\n return {\n lat: LAT,\n lon: LON,\n };\n } catch (error) {\n logger\n .withContext({\n segments: JSON.stringify(segments),\n format: String(format),\n })\n .withError(error)\n .error('Failed to convert display to DD');\n return null;\n }\n}\n\n/**\n * Validate coordinate segments and return errors\n *\n * Uses @accelint/geo to validate the segments and returns any validation errors.\n * Only validates when all required segments are filled.\n *\n * @param segments - Array of segment values from user input\n * @param format - The coordinate system format\n * @returns Array of error messages, empty if valid or incomplete\n *\n * @example\n * const errors = validateCoordinateSegments(['91', '0', 'N', '0', '0', 'E'], 'ddm');\n * // Returns: ['Invalid coordinate value']\n */\nexport function validateCoordinateSegments(\n segments: string[],\n format: CoordinateSystem,\n): string[] {\n if (segments.some((seg) => seg === '' || seg === undefined)) {\n return [];\n }\n\n const coordString = formatSegmentsToCoordinateString(segments, format);\n if (!coordString) {\n return ['Invalid coordinate value'];\n }\n\n try {\n const create = createCoordinate(coordinateSystems[format], 'LATLON');\n const coord = create(coordString);\n\n if (!coord.valid) {\n return ['Invalid coordinate value'];\n }\n\n return [];\n } catch (_error) {\n return ['Invalid coordinate value'];\n }\n}\n\n/**\n * Check if all segments are filled\n *\n * Helper to determine if the user has completed entering all segment values.\n * Used to determine when to trigger validation.\n *\n * @param segments - Array of segment values\n * @returns True if all segments have values, false otherwise\n */\nexport function areAllSegmentsFilled(segments: string[]): boolean {\n return segments.every((seg) => seg !== '' && seg !== undefined);\n}\n\n/**\n * Check if any segments have values\n *\n * Helper to determine if the user has started entering coordinate values.\n *\n * @param segments - Array of segment values\n * @returns True if any segment has a value, false if all empty\n */\nexport function hasAnySegmentValue(segments: string[]): boolean {\n return segments.some((seg) => seg !== '' && seg !== undefined);\n}\n\n/**\n * Create an invalid result object for all coordinate systems\n * @internal\n */\nfunction createInvalidResult(): Record<\n CoordinateSystem,\n CoordinateFormatResult\n> {\n return {\n dd: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n ddm: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n dms: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n mgrs: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n utm: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n };\n}\n\n/**\n * Validate coordinate value\n * @internal\n */\nfunction isValidCoordinateValue(value: CoordinateValue | null): boolean {\n return (\n value !== null &&\n typeof value.lat === 'number' &&\n typeof value.lon === 'number'\n );\n}\n\n/**\n * Check if error is due to geographic limitation (poles)\n * @internal\n */\nfunction isGeographicLimitationError(error: unknown): boolean {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return (\n errorMessage.includes('outside UTM limits') ||\n errorMessage.includes('invalid UTM zone')\n );\n}\n\n/**\n * Convert coordinate to a specific format with error handling\n * @internal\n */\nfunction convertToFormat(\n coord: {\n dd: () => string;\n ddm: () => string;\n dms: () => string;\n mgrs: () => string;\n utm: () => string;\n },\n format: CoordinateSystem,\n value: CoordinateValue,\n): CoordinateFormatResult {\n try {\n let formattedValue: string;\n switch (format) {\n case 'dd':\n formattedValue = coord.dd();\n break;\n case 'ddm': {\n const raw = coord.ddm();\n const s = parseDDMCoordinateString(raw);\n // parseDDMCoordinateString already applies 4 decimal precision to minutes\n formattedValue = s\n ? `${s[0]} ${s[1]} ${s[2]} / ${s[3]} ${s[4]} ${s[5]}`\n : raw;\n break;\n }\n case 'dms': {\n const raw = coord.dms();\n const s = parseDMSCoordinateString(raw);\n // parseDMSCoordinateString already applies 2 decimal precision to seconds\n formattedValue = s\n ? `${s[0]} ${s[1]} ${s[2]} ${s[3]} / ${s[4]} ${s[5]} ${s[6]} ${s[7]}`\n : raw;\n break;\n }\n case 'mgrs':\n formattedValue = coord.mgrs();\n break;\n case 'utm':\n formattedValue = coord.utm();\n break;\n default:\n return { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false };\n }\n return { value: formattedValue, isValid: true };\n } catch (error) {\n // Handle geographic limitations for MGRS/UTM\n if (\n (format === 'mgrs' || format === 'utm') &&\n isGeographicLimitationError(error)\n ) {\n return {\n value: COORDINATE_ERROR_MESSAGES.NOT_AVAILABLE_AT_POLES,\n isValid: false,\n };\n }\n\n // Log other errors in development\n logger\n .withContext({\n value: JSON.stringify(value),\n })\n .withError(error)\n .error(`Failed to convert to ${format}`);\n return {\n value: COORDINATE_ERROR_MESSAGES.CONVERSION_FAILED,\n isValid: false,\n };\n }\n}\n\n/**\n * Get all coordinate formats for a given DD value\n *\n * Converts a Decimal Degrees coordinate to all 5 supported coordinate systems\n * for display in the format conversion popover.\n *\n * Each format is tried independently - if one fails (e.g., UTM/MGRS at poles),\n * the others can still succeed.\n *\n * @param value - Coordinate value in DD format `{ lat: number, lon: number }`\n * @returns Object containing formatted strings and validity status for all coordinate systems\n *\n * @example\n * const formats = getAllCoordinateFormats({ lat: 40.7128, lon: -74.0060 });\n * // Returns: {\n * // dd: { value: \"40.7128 N / 74.006 W\", isValid: true },\n * // ddm: { value: \"40 42.768 N / 74 0.36 W\", isValid: true },\n * // dms: { value: \"40 42 46.08 N / 74 0 21.6 W\", isValid: true },\n * // mgrs: { value: \"18T WL 80654 06346\", isValid: true },\n * // utm: { value: \"18N 585628 4511644\", isValid: true }\n * // }\n *\n * @example\n * const formats = getAllCoordinateFormats({ lat: 90, lon: 0 });\n * // Returns: {\n * // dd: { value: \"90 N / 0 E\", isValid: true },\n * // ddm: { value: \"90 0 N / 0 0 E\", isValid: true },\n * // dms: { value: \"90 0 0 N / 0 0 0 E\", isValid: true },\n * // mgrs: { value: \"Not available at poles\", isValid: false },\n * // utm: { value: \"Not available at poles\", isValid: false }\n * // }\n */\nexport function getAllCoordinateFormats(\n value: CoordinateValue | null,\n): Record<CoordinateSystem, CoordinateFormatResult> {\n const invalidResult = createInvalidResult();\n\n if (!isValidCoordinateValue(value)) {\n return invalidResult;\n }\n\n const validValue = value as CoordinateValue;\n\n try {\n const create = createCoordinate(coordinateSystems.dd, 'LATLON');\n const coord = create(\n `${validValue.lat.toFixed(10)} / ${validValue.lon.toFixed(10)}`,\n );\n\n if (!coord.valid) {\n return invalidResult;\n }\n\n const result = {} as Record<CoordinateSystem, CoordinateFormatResult>;\n\n for (const format of COORDINATE_SYSTEMS) {\n result[format] = convertToFormat(coord, format, validValue);\n }\n\n return result;\n } catch (error) {\n logger\n .withContext({\n value: JSON.stringify(validValue),\n })\n .withError(error)\n .error('Failed to get all coordinate formats');\n return invalidResult;\n }\n}\n\n/**\n * Check if pasted text looks like a complete coordinate string\n *\n * Uses heuristics to detect if the pasted text contains a full coordinate\n * rather than just a single segment value. This prevents intercepting\n * single-segment pastes.\n *\n * Indicators of a complete coordinate:\n * - Contains separators: comma, slash, or multiple consecutive spaces\n * - Contains coordinate symbols: °, ′, ″, ', \"\n * - Multiple numbers separated by whitespace\n *\n * @param text - The pasted text to check\n * @returns True if it looks like a complete coordinate string\n *\n * @example\n * isCompleteCoordinate(\"40.7128, -74.0060\") // true - contains comma\n * isCompleteCoordinate(\"40° 42' 46\\\" N / 74° 0' 22\\\" W\") // true - contains symbols\n * isCompleteCoordinate(\"18T WM 12345 67890\") // true - multiple parts\n * isCompleteCoordinate(\"42\") // false - single number\n * isCompleteCoordinate(\"N\") // false - single letter\n */\nexport function isCompleteCoordinate(text: string): boolean {\n if (!text || text.trim() === '') {\n return false;\n }\n\n const hasSeparators = /[,/]|°|′|″|['\"]|\\s{2,}/.test(text);\n const numbers = text.match(/\\d+/g) || [];\n const hasMultipleNumbers = numbers.length >= 2;\n\n // Explicitly detect MGRS format: <zone><band> <grid> <easting> <northing>\n // Example: \"18T WL 80654 06346\"\n const isMGRS = /^\\d{1,2}[A-Z]\\s+[A-Z]{2}\\s+\\d+\\s+\\d+$/i.test(text.trim());\n\n // Explicitly detect UTM format: <zone><hemisphere> <easting> <northing>\n // Example: \"18N 585628 4511644\"\n const isUTM = /^\\d{1,2}[NS]\\s+\\d+\\s+\\d+$/i.test(text.trim());\n\n return hasSeparators || hasMultipleNumbers || isMGRS || isUTM;\n}\n\n/**\n * Attempt to parse pasted text as all coordinate formats\n *\n * Tries to parse the pasted text using each of the 5 coordinate system parsers.\n * Returns all formats that successfully parse the text.\n *\n * This enables automatic detection of coordinate format and disambiguation\n * when multiple formats match the same input string.\n *\n * @param pastedText - The raw text from clipboard\n * @returns Array of successfully parsed coordinate matches (may be empty)\n *\n * @example\n * const matches = parseCoordinatePaste(\"40.7128, -74.0060\");\n * // Returns: [{ format: 'dd', value: { lat: 40.7128, lon: -74.0060 }, displayString: \"...\" }]\n *\n * @example\n * const matches = parseCoordinatePaste(\"18T WM 12345 67890\");\n * // Returns: [{ format: 'mgrs', value: { lat: ..., lon: ... }, displayString: \"...\" }]\n *\n * @example\n * const matches = parseCoordinatePaste(\"invalid text\");\n * // Returns: []\n */\nexport function parseCoordinatePaste(\n pastedText: string,\n): ParsedCoordinateMatch[] {\n if (!pastedText || pastedText.trim() === '') {\n return [];\n }\n\n const matches: ParsedCoordinateMatch[] = [];\n\n for (const format of COORDINATE_SYSTEMS) {\n try {\n const create = createCoordinate(coordinateSystems[format], 'LATLON');\n const coord = create(pastedText.trim());\n\n if (coord.valid) {\n const { LAT, LON } = coord.raw;\n\n let displayString: string;\n switch (format) {\n case 'dd':\n displayString = coord.dd();\n break;\n case 'ddm':\n displayString = coord.ddm();\n break;\n case 'dms':\n displayString = coord.dms();\n break;\n case 'mgrs':\n displayString = coord.mgrs();\n break;\n case 'utm':\n displayString = coord.utm();\n break;\n default:\n displayString = '';\n }\n\n matches.push({\n format,\n value: { lat: LAT, lon: LON },\n displayString,\n });\n }\n } catch (error) {\n // Log parsing errors in development for debugging\n logger\n .withContext({\n pastedText: pastedText.trim(),\n format: String(format),\n })\n .withError(error)\n .warn(`Failed to parse as ${format}`);\n // Continue trying other parsers\n }\n }\n\n return matches;\n}\n\n/**\n * Check if two coordinates are equal within epsilon tolerance\n */\nexport function areCoordinatesEqual(\n coord1: { lat: number; lon: number },\n coord2: { lat: number; lon: number },\n epsilon = COORDINATE_EPSILON,\n): boolean {\n return (\n Math.abs(coord1.lat - coord2.lat) < epsilon &&\n Math.abs(coord1.lon - coord2.lon) < epsilon\n );\n}\n\n/**\n * Deduplicate coordinate matches by location, keeping first match for each unique location\n */\nexport function deduplicateMatchesByLocation(\n matches: ParsedCoordinateMatch[],\n): ParsedCoordinateMatch[] {\n const uniqueMatches: ParsedCoordinateMatch[] = [];\n\n for (const match of matches) {\n const isDuplicate = uniqueMatches.some((existing) =>\n areCoordinatesEqual(existing.value, match.value),\n );\n\n if (!isDuplicate) {\n uniqueMatches.push(match);\n }\n }\n\n return uniqueMatches;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"coordinate-utils.js","names":["coordString: string","formattedValue: string","matches: ParsedCoordinateMatch[]","displayString: string","uniqueMatches: ParsedCoordinateMatch[]"],"sources":["../../../src/components/coordinate-field/coordinate-utils.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport { getLogger } from '@accelint/logger';\n\nconst logger = getLogger({\n enabled: process.env.NODE_ENV !== 'production',\n level: 'debug',\n prefix: '[CoordinateField]',\n pretty: true,\n});\n\n/**\n * Coordinate Conversion Utilities\n *\n * This module provides utilities for converting between:\n * 1. Segment values (user input) → Coordinate strings (for @accelint/geo parsing)\n * 2. Coordinate strings (from @accelint/geo output) → Segment values (for display)\n * 3. Decimal Degrees (internal format) ↔ Display format segment values\n *\n * All conversions use the local @accelint/geo package for accurate coordinate parsing\n * and conversion between coordinate systems.\n *\n * ## Architecture: Bridge Layer Between UI and Geo Package\n *\n * This module serves as a bridge layer to handle the impedance mismatch between:\n * - **UI Requirements**: Individual segment fields (e.g., degrees, minutes, seconds, direction)\n * - **Geo Package API**: Complete coordinate strings (e.g., \"40° 42' 46\" N / 74° 0' 22\" W\")\n *\n * ### Why This Bridge Layer Exists\n *\n * The @accelint/geo package provides excellent coordinate parsing, validation, and conversion,\n * but its API is designed around complete coordinate strings:\n *\n * ```typescript\n * // What geo provides:\n * const coord = createCoordinate(coordinateSystems.ddm, 'LATLON')('40 42.768 N / 74 0.36 W');\n * coord.dd() // Returns: \"40.7128 N / 74.006 W\" (formatted string)\n * coord.ddm() // Returns: \"40 42.768 N / 74 0.36 W\" (formatted string)\n * coord.raw // Returns: { LAT: 40.7128, LON: -74.006 } (only DD numbers)\n * ```\n *\n * The coordinate-field component needs segment-level data for individual input fields:\n * - DDM: ['40', '42.768', 'N', '74', '0.36', 'W'] ← Not provided by geo\n * - DMS: ['40', '42', '46.08', 'N', '74', '0', '21.6', 'W'] ← Not provided by geo\n *\n * ### Current Limitations and Duplication\n *\n * Because the geo package only exposes:\n * 1. **Formatters** that return complete strings (coord.ddm(), coord.dms(), etc.)\n * 2. **Raw values** in Decimal Degrees only (coord.raw)\n *\n * This module must:\n * 1. Build coordinate strings from segments → Pass to geo for parsing\n * 2. Parse geo's formatted output strings → Extract segments using regex\n *\n * This creates a circular conversion flow for DD → Display Segments:\n * ```\n * DD value → String → Geo parse → Geo format → String → Regex parse → Segments\n * ```\n *\n * **Note on Duplication**: The regex parsing in this module duplicates work that the\n * geo package parsers already do internally. However, since geo doesn't expose the\n * parsed segment components (only formatted strings and raw DD values), we must\n * re-parse its output to extract the individual segments for the UI.\n *\n * ### What Would Eliminate This Duplication\n *\n * If the geo package exported component-level converters like:\n * ```typescript\n * // Hypothetical API that would eliminate the bridge layer:\n * export function ddToDdmComponents(dd: number): {\n * degrees: number;\n * minutes: number;\n * direction: 'N' | 'S' | 'E' | 'W';\n * }\n * ```\n *\n * Then this bridge layer could be significantly simplified. The math for these conversions\n * exists in the geo package's formatters (e.g., formatDegreesDecimalMinutes), but it's\n * wrapped in string formatting logic rather than exposed as standalone utilities.\n *\n * ### Conversion Efficiency\n *\n * - **Efficient Path** (Display Segments → DD): Segments → String → Geo parse → DD\n * - Uses geo package for all parsing and validation ✓\n *\n * - **Inefficient Path** (DD → Display Segments): DD → String → Geo parse → Geo format → Regex parse → Segments\n * - Circular conversion with redundant string parsing/formatting ✗\n * - Necessary given current geo API limitations\n */\n\nimport { coordinateSystems, createCoordinate } from '@accelint/geo';\nimport {\n COORDINATE_SYSTEMS,\n type CoordinateSystem,\n type CoordinateValue,\n type ParsedCoordinateMatch,\n} from './types';\n\n/** Epsilon for coordinate equality comparison (≈11cm precision at equator) */\nexport const COORDINATE_EPSILON = 0.000001;\n\n/**\n * Error message constants for coordinate format conversion\n * @internal\n */\nexport const COORDINATE_ERROR_MESSAGES = {\n INVALID: 'Invalid coordinate',\n CONVERSION_FAILED: 'Conversion failed',\n NOT_AVAILABLE_AT_POLES: 'Not available at poles',\n} as const;\n\n/**\n * Result of coordinate format conversion\n */\nexport interface CoordinateFormatResult {\n /** The formatted coordinate string or error message */\n value: string;\n /** Whether the coordinate format is valid and can be used/copied */\n isValid: boolean;\n}\n\n/**\n * Format DD (Decimal Degrees) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatDDSegments(segments: string[]): string | null {\n if (segments.length < 2) {\n return null;\n }\n const latNum = Number.parseFloat(segments[0] as string);\n const lonNum = Number.parseFloat(segments[1] as string);\n\n if (Number.isNaN(latNum) || Number.isNaN(lonNum)) {\n return null;\n }\n\n const latDir = latNum >= 0 ? 'N' : 'S';\n const lonDir = lonNum >= 0 ? 'E' : 'W';\n\n return `${Math.abs(latNum)} ${latDir} / ${Math.abs(lonNum)} ${lonDir}`;\n}\n\n/**\n * Format DDM (Degrees Decimal Minutes) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatDDMSegments(segments: string[]): string | null {\n if (segments.length < 6) {\n return null;\n }\n return `${segments[0]}° ${segments[1]}' ${segments[2]}, ${segments[3]}° ${segments[4]}' ${segments[5]}`;\n}\n\n/**\n * Format DMS (Degrees Minutes Seconds) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatDMSSegments(segments: string[]): string | null {\n if (segments.length < 8) {\n return null;\n }\n return `${segments[0]}° ${segments[1]}' ${segments[2]}\" ${segments[3]}, ${segments[4]}° ${segments[5]}' ${segments[6]}\" ${segments[7]}`;\n}\n\n/**\n * Format MGRS (Military Grid Reference System) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatMGRSSegments(segments: string[]): string | null {\n if (segments.length < 5) {\n return null;\n }\n return `${segments[0]}${segments[1]} ${segments[2]} ${segments[3]} ${segments[4]}`;\n}\n\n/**\n * Format UTM (Universal Transverse Mercator) segments to coordinate string\n *\n * Bridge function that builds a coordinate string from UI segment values\n * for passing to the geo package parser. Part of the Segments → String → Geo Parse flow.\n *\n * @internal\n */\nfunction formatUTMSegments(segments: string[]): string | null {\n if (segments.length < 4) {\n return null;\n }\n return `${segments[0]}${segments[1]} ${segments[2]} ${segments[3]}`;\n}\n\n/**\n * Format segment values into a coordinate string suitable for @accelint/geo parsing\n *\n * Converts an array of segment values into a string format that the geo package\n * parsers can understand. Each format has different requirements:\n *\n * DD: [lat, lon] → \"lat, lon\"\n * DDM: [latDeg, latMin, latDir, lonDeg, lonMin, lonDir] → \"latDeg° latMin' latDir, lonDeg° lonMin' lonDir\"\n * DMS: [latDeg, latMin, latSec, latDir, lonDeg, lonMin, lonSec, lonDir] → \"latDeg° latMin' latSec\\\" latDir, lonDeg° lonMin' lonSec\\\" lonDir\"\n * MGRS: [zone, band, grid, easting, northing] → \"zone+band grid easting northing\"\n * UTM: [zone, hemisphere, easting, northing] → \"zone+hemisphere easting northing\"\n *\n * @param segments - Array of segment values from user input\n * @param format - The coordinate system format\n * @returns Formatted coordinate string, or null if segments are invalid\n */\nexport function formatSegmentsToCoordinateString(\n segments: string[],\n format: CoordinateSystem,\n): string | null {\n if (segments.some((seg) => seg === '' || seg === undefined)) {\n return null;\n }\n\n try {\n switch (format) {\n case 'dd':\n return formatDDSegments(segments);\n case 'ddm':\n return formatDDMSegments(segments);\n case 'dms':\n return formatDMSSegments(segments);\n case 'mgrs':\n return formatMGRSSegments(segments);\n case 'utm':\n return formatUTMSegments(segments);\n default:\n return null;\n }\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Format a decimal string to specified precision for display\n *\n * This is used to ensure consistent decimal precision when displaying\n * coordinate segments, regardless of the precision returned by the geo package.\n *\n * @param value - The decimal string to format\n * @param decimals - Number of decimal places to display\n * @returns Formatted string with specified precision\n * @internal\n */\nfunction formatDecimalPrecision(value: string, decimals: number): string {\n const num = Number.parseFloat(value);\n if (Number.isNaN(num)) {\n return value;\n }\n // Round to specified decimals, then remove trailing zeros\n return Number.parseFloat(num.toFixed(decimals)).toString();\n}\n\n/**\n * Parse DD coordinate string to segments\n *\n * Extracts segment values from a formatted DD coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseDecimalDegrees, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseDDCoordinateString(coordString: string): string[] | null {\n // DD formats from @accelint/geo (no degree symbols):\n // \"40.7128 N / -74.006 W\" or \"0 N / 180 W\"\n // Also handle user input with symbols:\n // \"89.765432° N / 123.456789° W\" or \"89.765432, -123.456789\"\n\n // Match DD format with optional degree symbols and optional direction letters\n const match = coordString.match(\n /([-]?\\d+\\.?\\d*)°?\\s*([NS])?\\s*[,/\\s]+\\s*([-]?\\d+\\.?\\d*)°?\\s*([EW])?/i,\n );\n if (!match) {\n return null;\n }\n\n let lat = match[1];\n let lon = match[3];\n\n if (!(lat && lon)) {\n return null;\n }\n\n if (match[2]?.toUpperCase() === 'S' && !lat.startsWith('-')) {\n lat = `-${lat}`;\n }\n if (match[4]?.toUpperCase() === 'W' && !lon.startsWith('-')) {\n lon = `-${lon}`;\n }\n\n return [lat, lon];\n}\n\n/**\n * Parse DDM coordinate string to segments\n *\n * Extracts segment values from a formatted DDM coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseDegreesDecimalMinutes, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseDDMCoordinateString(coordString: string): string[] | null {\n // DDM formats from @accelint/geo (no symbols):\n // \"40 42.768 N / 74 0.36 W\"\n // Also handle user input with symbols:\n // \"89° 45.9259' N / 123° 27.4073' W\"\n\n // Match DDM format with optional degree and minute symbols\n const match = coordString.match(\n /(\\d+)°?\\s+([\\d.]+)'?\\s+([NS])\\s*[,/]\\s*(\\d+)°?\\s+([\\d.]+)'?\\s+([EW])/i,\n );\n if (!match) {\n return null;\n }\n // Round minutes to 4 decimal places for display (CJCSI 3900.01E compliance)\n return [\n match[1] as string,\n formatDecimalPrecision(match[2] as string, 4),\n match[3] as string,\n match[4] as string,\n formatDecimalPrecision(match[5] as string, 4),\n match[6] as string,\n ];\n}\n\n/**\n * Parse DMS coordinate string to segments\n *\n * Extracts segment values from a formatted DMS coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseDegreesMinutesSeconds, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseDMSCoordinateString(coordString: string): string[] | null {\n // DMS formats from @accelint/geo (no symbols):\n // \"40 42 46.08 N / 74 0 21.60 W\"\n // Also handle user input with symbols:\n // \"89° 45' 55.56\" N / 123° 27' 24.44\" W\"\n\n // Match DMS format with optional degree, minute, and second symbols\n const match = coordString.match(\n /(\\d+)°?\\s+(\\d+)'?\\s+([\\d.]+)\"?\\s+([NS])\\s*[,/]\\s*(\\d+)°?\\s+(\\d+)'?\\s+([\\d.]+)\"?\\s+([EW])/i,\n );\n if (!match) {\n return null;\n }\n // Round seconds to 2 decimal places for display\n return [\n match[1] as string,\n match[2] as string,\n formatDecimalPrecision(match[3] as string, 2),\n match[4] as string,\n match[5] as string,\n match[6] as string,\n formatDecimalPrecision(match[7] as string, 2),\n match[8] as string,\n ];\n}\n\n/**\n * Parse MGRS coordinate string to segments\n *\n * Extracts segment values from a formatted MGRS coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseMGRS, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseMGRSCoordinateString(coordString: string): string[] | null {\n // MGRS: \"18T WM 12345 67890\"\n const match = coordString.match(/(\\d+)([A-Z])\\s+([A-Z]{2})\\s+(\\d+)\\s+(\\d+)/i);\n if (!match) {\n return null;\n }\n return [\n match[1] as string,\n match[2] as string,\n match[3] as string,\n match[4] as string,\n match[5] as string,\n ];\n}\n\n/**\n * Parse UTM coordinate string to segments\n *\n * Extracts segment values from a formatted UTM coordinate string. This duplicates\n * parsing logic from @accelint/geo's parseUTM, but is necessary because\n * geo doesn't expose the parsed components - only formatted strings and raw DD numbers.\n *\n * Part of the Geo Format → String → Regex Parse → Segments flow (circular conversion).\n *\n * @internal\n */\nfunction parseUTMCoordinateString(coordString: string): string[] | null {\n // UTM: \"18N 585628 4511644\" or \"18 N 585628 4511644\" (with optional space)\n const match = coordString.match(/(\\d+)\\s*([NS])\\s+(\\d+)\\s+(\\d+)/i);\n if (!match) {\n return null;\n }\n return [\n match[1] as string,\n match[2] as string,\n match[3] as string,\n match[4] as string,\n ];\n}\n\n/**\n * Parse a coordinate string into segment values\n *\n * Converts a formatted coordinate string (from @accelint/geo output or user input)\n * back into individual segment values for display.\n *\n * This is the inverse of formatSegmentsToCoordinateString.\n *\n * **Note on Duplication**: This function and its helpers (parseDDCoordinateString,\n * parseDDMCoordinateString, etc.) duplicate parsing logic that already exists in\n * the @accelint/geo package parsers:\n *\n * - Geo parsers: parseDecimalDegrees, parseDegreesDecimalMinutes, etc.\n * - These functions: parseDDCoordinateString, parseDDMCoordinateString, etc.\n *\n * Both use regex patterns to extract coordinate components from strings. The duplication\n * exists because:\n *\n * 1. **Geo parsers** extract components, validate them, convert to DD, then format back to strings\n * 2. **This function** extracts components from those formatted strings for the UI\n *\n * We're essentially undoing the formatting that geo just did. This is the second half\n * of the circular conversion described in convertDDToDisplaySegments.\n *\n * **Why we can't use geo parsers directly**: The geo parsers return coord objects with\n * only `coord.raw` (DD numbers) and formatting methods. They don't expose the parsed\n * segment components we need for the UI (e.g., the degrees, minutes, and direction values).\n *\n * **Parsing Order**:\n * - **convertDisplaySegmentsToDD**: Segments → String → **Geo parse** → DD ✓ (efficient)\n * - **convertDDToDisplaySegments**: DD → String → Geo parse → Geo format → **This parse** → Segments ✗ (circular)\n *\n * @param coordString - Formatted coordinate string\n * @param format - The coordinate system format\n * @returns Array of segment values, or null if parsing fails\n */\nexport function parseCoordinateStringToSegments(\n coordString: string,\n format: CoordinateSystem,\n): string[] | null {\n if (!coordString) {\n return null;\n }\n\n try {\n switch (format) {\n case 'dd':\n return parseDDCoordinateString(coordString);\n case 'ddm':\n return parseDDMCoordinateString(coordString);\n case 'dms':\n return parseDMSCoordinateString(coordString);\n case 'mgrs':\n return parseMGRSCoordinateString(coordString);\n case 'utm':\n return parseUTMCoordinateString(coordString);\n default:\n return null;\n }\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Convert DD (internal format) to display format segment values\n *\n * Takes a CoordinateValue in Decimal Degrees format and converts it to the\n * segment values needed for the specified display format.\n *\n * Uses @accelint/geo to ensure accurate conversion between coordinate systems.\n *\n * **Note on Circular Conversion**: This function demonstrates the circular conversion\n * pattern discussed in the module documentation. The flow is:\n *\n * 1. Start with DD value: `{ lat: 40.7128, lon: -74.0060 }`\n * 2. Convert to coordinate string: `\"40.7128 / -74.006\"`\n * 3. Parse with geo package (creates coord object with internal parsed state)\n * 4. Format to target system using geo: `coord.ddm()` → `\"40 42.768 N / 74 0.36 W\"`\n * 5. Parse the formatted string AGAIN with regex to extract segments: `['40', '42.768', 'N', ...]`\n *\n * This is inefficient because:\n * - The geo package already has the component values (degrees, minutes, direction) internally\n * - We format them into a string, then immediately parse the string back apart\n * - The regex parsing duplicates work the geo parsers already did\n *\n * However, this approach is necessary because:\n * - The geo package only exposes `coord.raw` (DD numbers) and formatted strings\n * - It doesn't expose the intermediate component values we need for the UI segments\n * - We need individual segment values for separate input fields\n *\n * **Future Improvement**: If geo package exported component extractors like:\n * ```typescript\n * coord.components.ddm // { latDeg: 40, latMin: 42.768, latDir: 'N', ... }\n * ```\n * Then we could eliminate the format→parse cycle entirely.\n *\n * @param value - Coordinate value in DD format `{ lat: number, lon: number }`\n * @param format - Target display format\n * @returns Array of segment values for display, or null if conversion fails\n *\n * @example\n * const segments = convertDDToDisplaySegments({ lat: 40.7128, lon: -74.0060 }, 'ddm');\n * // Returns: ['40', '42.7680', 'N', '74', '0.3600', 'W']\n */\nexport function convertDDToDisplaySegments(\n value: CoordinateValue,\n format: CoordinateSystem,\n): string[] | null {\n if (\n !value ||\n typeof value.lat !== 'number' ||\n typeof value.lon !== 'number'\n ) {\n return null;\n }\n\n try {\n const create = createCoordinate(coordinateSystems.dd, 'LATLON');\n\n // Round to 10 decimal places to match geo package internal precision\n // Use signed numbers (not cardinal directions) for reliable conversions to all formats\n const lat = Number(value.lat.toFixed(10));\n const lon = Number(value.lon.toFixed(10));\n const inputCoordString = `${lat} / ${lon}`;\n\n const coord = create(inputCoordString);\n\n if (!coord.valid) {\n return null;\n }\n\n // Format the coordinate using geo package formatters\n // These return complete coordinate strings (e.g., \"40 42.768 N / 74 0.36 W\")\n let coordString: string;\n switch (format) {\n case 'dd':\n coordString = coord.dd();\n break;\n case 'ddm':\n coordString = coord.ddm();\n break;\n case 'dms':\n coordString = coord.dms();\n break;\n case 'mgrs':\n coordString = coord.mgrs();\n break;\n case 'utm':\n coordString = coord.utm();\n break;\n default:\n return null;\n }\n\n // Parse the formatted string to extract individual segment values\n // This is the circular part: geo formatted it, now we parse it back apart\n // Necessary because geo doesn't expose the components directly\n const segments = parseCoordinateStringToSegments(coordString, format);\n return segments;\n } catch (error) {\n logger\n .withContext({\n value: String(value),\n format: String(format),\n })\n .withError(error)\n .error('Failed to convert DD to display');\n return null;\n }\n}\n\n/**\n * Convert display format segment values to DD (internal format)\n *\n * Takes segment values from user input and converts them to a CoordinateValue\n * in Decimal Degrees format using @accelint/geo for validation and conversion.\n *\n * **Note on Efficiency**: This function demonstrates the EFFICIENT conversion direction.\n * The flow is:\n *\n * 1. Start with UI segments: `['40', '42.768', 'N', '74', '0.36', 'W']`\n * 2. Build coordinate string: `\"40° 42.768' N, 74° 0.36' W\"`\n * 3. Parse with geo package (validates and converts internally)\n * 4. Extract DD from coord.raw: `{ lat: 40.7128, lon: -74.0060 }`\n *\n * This is efficient because:\n * - We let geo do what it's designed for: parsing and validating coordinate strings\n * - We extract the DD values directly from `coord.raw` (no string parsing needed)\n * - Single direction: Segments → String → Geo Parse → DD (no circular conversion)\n *\n * Contrast with `convertDDToDisplaySegments` which has the circular pattern:\n * DD → String → Geo Parse → Geo Format → String → Regex Parse → Segments\n *\n * @param segments - Array of segment values from user input\n * @param format - The coordinate system format of the segments\n * @returns CoordinateValue in DD format, or null if invalid\n *\n * @example\n * const coord = convertDisplaySegmentsToDD(['40', '42.7680', 'N', '74', '0.3600', 'W'], 'ddm');\n * // Returns: { lat: 40.7128, lon: -74.0060 }\n */\nexport function convertDisplaySegmentsToDD(\n segments: string[],\n format: CoordinateSystem,\n): CoordinateValue | null {\n // Build coordinate string from segments for geo parsing\n const coordString = formatSegmentsToCoordinateString(segments, format);\n if (!coordString) {\n return null;\n }\n\n try {\n // Parse and validate with geo package\n const create = createCoordinate(coordinateSystems[format], 'LATLON');\n const coord = create(coordString);\n\n if (!coord.valid) {\n // Return null for invalid coordinates (errors will be handled separately)\n return null;\n }\n\n // Extract DD values directly from coord.raw and round to 6 decimals\n // This ensures consistency with convertDDToDisplaySegments and getAllCoordinateFormats\n const { LAT, LON } = coord.raw;\n\n return {\n lat: LAT,\n lon: LON,\n };\n } catch (error) {\n logger\n .withContext({\n segments: JSON.stringify(segments),\n format: String(format),\n })\n .withError(error)\n .error('Failed to convert display to DD');\n return null;\n }\n}\n\n/**\n * Validate coordinate segments and return errors\n *\n * Uses @accelint/geo to validate the segments and returns any validation errors.\n * Only validates when all required segments are filled.\n *\n * @param segments - Array of segment values from user input\n * @param format - The coordinate system format\n * @returns Array of error messages, empty if valid or incomplete\n *\n * @example\n * const errors = validateCoordinateSegments(['91', '0', 'N', '0', '0', 'E'], 'ddm');\n * // Returns: ['Invalid coordinate value']\n */\nexport function validateCoordinateSegments(\n segments: string[],\n format: CoordinateSystem,\n): string[] {\n if (segments.some((seg) => seg === '' || seg === undefined)) {\n return [];\n }\n\n const coordString = formatSegmentsToCoordinateString(segments, format);\n if (!coordString) {\n return ['Invalid coordinate value'];\n }\n\n try {\n const create = createCoordinate(coordinateSystems[format], 'LATLON');\n const coord = create(coordString);\n\n if (!coord.valid) {\n return ['Invalid coordinate value'];\n }\n\n return [];\n } catch (_error) {\n return ['Invalid coordinate value'];\n }\n}\n\n/**\n * Check if all segments are filled\n *\n * Helper to determine if the user has completed entering all segment values.\n * Used to determine when to trigger validation.\n *\n * @param segments - Array of segment values\n * @returns True if all segments have values, false otherwise\n */\nexport function areAllSegmentsFilled(segments: string[]): boolean {\n return segments.every((seg) => seg !== '' && seg !== undefined);\n}\n\n/**\n * Check if any segments have values\n *\n * Helper to determine if the user has started entering coordinate values.\n *\n * @param segments - Array of segment values\n * @returns True if any segment has a value, false if all empty\n */\nexport function hasAnySegmentValue(segments: string[]): boolean {\n return segments.some((seg) => seg !== '' && seg !== undefined);\n}\n\n/**\n * Create an invalid result object for all coordinate systems\n * @internal\n */\nfunction createInvalidResult(): Record<\n CoordinateSystem,\n CoordinateFormatResult\n> {\n return {\n dd: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n ddm: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n dms: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n mgrs: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n utm: { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false },\n };\n}\n\n/**\n * Validate coordinate value\n * @internal\n */\nfunction isValidCoordinateValue(value: CoordinateValue | null): boolean {\n return (\n value !== null &&\n typeof value.lat === 'number' &&\n typeof value.lon === 'number'\n );\n}\n\n/**\n * Check if error is due to geographic limitation (poles)\n * @internal\n */\nfunction isGeographicLimitationError(error: unknown): boolean {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return (\n errorMessage.includes('outside UTM limits') ||\n errorMessage.includes('invalid UTM zone')\n );\n}\n\n/**\n * Convert coordinate to a specific format with error handling\n * @internal\n */\nfunction convertToFormat(\n coord: {\n dd: () => string;\n ddm: () => string;\n dms: () => string;\n mgrs: () => string;\n utm: () => string;\n },\n format: CoordinateSystem,\n value: CoordinateValue,\n): CoordinateFormatResult {\n try {\n let formattedValue: string;\n switch (format) {\n case 'dd':\n formattedValue = coord.dd();\n break;\n case 'ddm': {\n const raw = coord.ddm();\n const s = parseDDMCoordinateString(raw);\n // parseDDMCoordinateString already applies 4 decimal precision to minutes\n formattedValue = s\n ? `${s[0]} ${s[1]} ${s[2]} / ${s[3]} ${s[4]} ${s[5]}`\n : raw;\n break;\n }\n case 'dms': {\n const raw = coord.dms();\n const s = parseDMSCoordinateString(raw);\n // parseDMSCoordinateString already applies 2 decimal precision to seconds\n formattedValue = s\n ? `${s[0]} ${s[1]} ${s[2]} ${s[3]} / ${s[4]} ${s[5]} ${s[6]} ${s[7]}`\n : raw;\n break;\n }\n case 'mgrs':\n formattedValue = coord.mgrs();\n break;\n case 'utm':\n formattedValue = coord.utm();\n break;\n default:\n return { value: COORDINATE_ERROR_MESSAGES.INVALID, isValid: false };\n }\n return { value: formattedValue, isValid: true };\n } catch (error) {\n // Handle geographic limitations for MGRS/UTM\n if (\n (format === 'mgrs' || format === 'utm') &&\n isGeographicLimitationError(error)\n ) {\n return {\n value: COORDINATE_ERROR_MESSAGES.NOT_AVAILABLE_AT_POLES,\n isValid: false,\n };\n }\n\n // Log other errors in development\n logger\n .withContext({\n value: JSON.stringify(value),\n })\n .withError(error)\n .error(`Failed to convert to ${format}`);\n return {\n value: COORDINATE_ERROR_MESSAGES.CONVERSION_FAILED,\n isValid: false,\n };\n }\n}\n\n/**\n * Get all coordinate formats for a given DD value\n *\n * Converts a Decimal Degrees coordinate to all 5 supported coordinate systems\n * for display in the format conversion popover.\n *\n * Each format is tried independently - if one fails (e.g., UTM/MGRS at poles),\n * the others can still succeed.\n *\n * @param value - Coordinate value in DD format `{ lat: number, lon: number }`\n * @returns Object containing formatted strings and validity status for all coordinate systems\n *\n * @example\n * const formats = getAllCoordinateFormats({ lat: 40.7128, lon: -74.0060 });\n * // Returns: {\n * // dd: { value: \"40.7128 N / 74.006 W\", isValid: true },\n * // ddm: { value: \"40 42.768 N / 74 0.36 W\", isValid: true },\n * // dms: { value: \"40 42 46.08 N / 74 0 21.6 W\", isValid: true },\n * // mgrs: { value: \"18T WL 80654 06346\", isValid: true },\n * // utm: { value: \"18N 585628 4511644\", isValid: true }\n * // }\n *\n * @example\n * const formats = getAllCoordinateFormats({ lat: 90, lon: 0 });\n * // Returns: {\n * // dd: { value: \"90 N / 0 E\", isValid: true },\n * // ddm: { value: \"90 0 N / 0 0 E\", isValid: true },\n * // dms: { value: \"90 0 0 N / 0 0 0 E\", isValid: true },\n * // mgrs: { value: \"Not available at poles\", isValid: false },\n * // utm: { value: \"Not available at poles\", isValid: false }\n * // }\n */\nexport function getAllCoordinateFormats(\n value: CoordinateValue | null,\n): Record<CoordinateSystem, CoordinateFormatResult> {\n const invalidResult = createInvalidResult();\n\n if (!isValidCoordinateValue(value)) {\n return invalidResult;\n }\n\n const validValue = value as CoordinateValue;\n\n try {\n const create = createCoordinate(coordinateSystems.dd, 'LATLON');\n const coord = create(\n `${validValue.lat.toFixed(10)} / ${validValue.lon.toFixed(10)}`,\n );\n\n if (!coord.valid) {\n return invalidResult;\n }\n\n const result = {} as Record<CoordinateSystem, CoordinateFormatResult>;\n\n for (const format of COORDINATE_SYSTEMS) {\n result[format] = convertToFormat(coord, format, validValue);\n }\n\n return result;\n } catch (error) {\n logger\n .withContext({\n value: JSON.stringify(validValue),\n })\n .withError(error)\n .error('Failed to get all coordinate formats');\n return invalidResult;\n }\n}\n\n/**\n * Check if pasted text looks like a complete coordinate string\n *\n * Uses heuristics to detect if the pasted text contains a full coordinate\n * rather than just a single segment value. This prevents intercepting\n * single-segment pastes.\n *\n * Indicators of a complete coordinate:\n * - Contains separators: comma, slash, or multiple consecutive spaces\n * - Contains coordinate symbols: °, ′, ″, ', \"\n * - Multiple numbers separated by whitespace\n *\n * @param text - The pasted text to check\n * @returns True if it looks like a complete coordinate string\n *\n * @example\n * isCompleteCoordinate(\"40.7128, -74.0060\") // true - contains comma\n * isCompleteCoordinate(\"40° 42' 46\\\" N / 74° 0' 22\\\" W\") // true - contains symbols\n * isCompleteCoordinate(\"18T WM 12345 67890\") // true - multiple parts\n * isCompleteCoordinate(\"42\") // false - single number\n * isCompleteCoordinate(\"N\") // false - single letter\n */\nexport function isCompleteCoordinate(text: string): boolean {\n if (!text || text.trim() === '') {\n return false;\n }\n\n const hasSeparators = /[,/]|°|′|″|['\"]|\\s{2,}/.test(text);\n const numbers = text.match(/\\d+/g) || [];\n const hasMultipleNumbers = numbers.length >= 2;\n\n // Explicitly detect MGRS format: <zone><band> <grid> <easting> <northing>\n // Example: \"18T WL 80654 06346\"\n const isMGRS = /^\\d{1,2}[A-Z]\\s+[A-Z]{2}\\s+\\d+\\s+\\d+$/i.test(text.trim());\n\n // Explicitly detect UTM format: <zone><hemisphere> <easting> <northing>\n // Example: \"18N 585628 4511644\"\n const isUTM = /^\\d{1,2}[NS]\\s+\\d+\\s+\\d+$/i.test(text.trim());\n\n return hasSeparators || hasMultipleNumbers || isMGRS || isUTM;\n}\n\n/**\n * Attempt to parse pasted text as all coordinate formats\n *\n * Tries to parse the pasted text using each of the 5 coordinate system parsers.\n * Returns all formats that successfully parse the text.\n *\n * This enables automatic detection of coordinate format and disambiguation\n * when multiple formats match the same input string.\n *\n * @param pastedText - The raw text from clipboard\n * @returns Array of successfully parsed coordinate matches (may be empty)\n *\n * @example\n * const matches = parseCoordinatePaste(\"40.7128, -74.0060\");\n * // Returns: [{ format: 'dd', value: { lat: 40.7128, lon: -74.0060 }, displayString: \"...\" }]\n *\n * @example\n * const matches = parseCoordinatePaste(\"18T WM 12345 67890\");\n * // Returns: [{ format: 'mgrs', value: { lat: ..., lon: ... }, displayString: \"...\" }]\n *\n * @example\n * const matches = parseCoordinatePaste(\"invalid text\");\n * // Returns: []\n */\nexport function parseCoordinatePaste(\n pastedText: string,\n): ParsedCoordinateMatch[] {\n if (!pastedText || pastedText.trim() === '') {\n return [];\n }\n\n const matches: ParsedCoordinateMatch[] = [];\n\n for (const format of COORDINATE_SYSTEMS) {\n try {\n const create = createCoordinate(coordinateSystems[format], 'LATLON');\n const coord = create(pastedText.trim());\n\n if (coord.valid) {\n const { LAT, LON } = coord.raw;\n\n let displayString: string;\n switch (format) {\n case 'dd':\n displayString = coord.dd();\n break;\n case 'ddm':\n displayString = coord.ddm();\n break;\n case 'dms':\n displayString = coord.dms();\n break;\n case 'mgrs':\n displayString = coord.mgrs();\n break;\n case 'utm':\n displayString = coord.utm();\n break;\n default:\n displayString = '';\n }\n\n matches.push({\n format,\n value: { lat: LAT, lon: LON },\n displayString,\n });\n }\n } catch (error) {\n // Log parsing errors in development for debugging\n logger\n .withContext({\n pastedText: pastedText.trim(),\n format: String(format),\n })\n .withError(error)\n .warn(`Failed to parse as ${format}`);\n // Continue trying other parsers\n }\n }\n\n return matches;\n}\n\n/**\n * Check if two coordinates are equal within epsilon tolerance\n *\n * @param coord1 - First coordinate to compare.\n * @param coord2 - Second coordinate to compare.\n * @param epsilon - Tolerance for comparison (defaults to COORDINATE_EPSILON).\n * @returns True if coordinates are equal within tolerance.\n */\nexport function areCoordinatesEqual(\n coord1: { lat: number; lon: number },\n coord2: { lat: number; lon: number },\n epsilon = COORDINATE_EPSILON,\n): boolean {\n return (\n Math.abs(coord1.lat - coord2.lat) < epsilon &&\n Math.abs(coord1.lon - coord2.lon) < epsilon\n );\n}\n\n/**\n * Deduplicate coordinate matches by location, keeping first match for each unique location\n *\n * @param matches - Array of parsed coordinate matches to deduplicate.\n * @returns Array of unique matches based on coordinate location.\n */\nexport function deduplicateMatchesByLocation(\n matches: ParsedCoordinateMatch[],\n): ParsedCoordinateMatch[] {\n const uniqueMatches: ParsedCoordinateMatch[] = [];\n\n for (const match of matches) {\n const isDuplicate = uniqueMatches.some((existing) =>\n areCoordinatesEqual(existing.value, match.value),\n );\n\n if (!isDuplicate) {\n uniqueMatches.push(match);\n }\n }\n\n return uniqueMatches;\n}\n"],"mappings":"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"}