@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
@@ -16,6 +16,56 @@ import { getSegmentConfigs } from "../../components/coordinate-field/segment-con
16
16
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
17
17
 
18
18
  //#region src/hooks/coordinate-field/use-coordinate-field-state.ts
19
+ /**
20
+ * Manages coordinate segment values, validation, and format conversion
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * function CoordinateInputs() {
25
+ * const [value, setValue] = useState<CoordinateValue | null>(null);
26
+ * const { registerTimeout } = useTimeoutCleanup();
27
+ *
28
+ * const {
29
+ * currentValue,
30
+ * segmentValues,
31
+ * validationErrors,
32
+ * editableSegmentConfigs,
33
+ * handleSegmentChange,
34
+ * } = useCoordinateFieldState({
35
+ * value,
36
+ * format: 'ddm',
37
+ * onChange: setValue,
38
+ * onError: (msg) => console.error(msg),
39
+ * registerTimeout,
40
+ * });
41
+ *
42
+ * return (
43
+ * <div>
44
+ * {editableSegmentConfigs.map((config, i) => (
45
+ * <input
46
+ * key={i}
47
+ * value={segmentValues[i]}
48
+ * onChange={(e) => handleSegmentChange(i, e.target.value)}
49
+ * placeholder={config.placeholder}
50
+ * />
51
+ * ))}
52
+ * {validationErrors.map((error, i) => (
53
+ * <span key={i}>{error}</span>
54
+ * ))}
55
+ * </div>
56
+ * );
57
+ * }
58
+ * ```
59
+ *
60
+ * @param options - {@link UseCoordinateFieldStateOptions}
61
+ * @param options.value - Controlled coordinate value.
62
+ * @param options.defaultValue - Default value for uncontrolled mode.
63
+ * @param options.format - Coordinate format system (dd, ddm, dms, mgrs, utm).
64
+ * @param options.onChange - Callback when coordinate value changes.
65
+ * @param options.onError - Callback for validation errors.
66
+ * @param options.registerTimeout - Register timeouts for cleanup on unmount.
67
+ * @returns {@link UseCoordinateFieldStateResult} Segment state, validation, and change handlers.
68
+ */
19
69
  function useCoordinateFieldState({ value, defaultValue, format, onChange, onError, registerTimeout }) {
20
70
  const [internalValue, setInternalValue] = useState(defaultValue || null);
21
71
  const [validationErrors, setValidationErrors] = useState([]);
@@ -1 +1 @@
1
- {"version":3,"file":"use-coordinate-field-state.js","names":[],"sources":["../../../src/hooks/coordinate-field/use-coordinate-field-state.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n type Dispatch,\n type SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n areAllSegmentsFilled,\n convertDDToDisplaySegments,\n convertDisplaySegmentsToDD,\n validateCoordinateSegments,\n} from '../../components/coordinate-field/coordinate-utils';\nimport { getSegmentConfigs } from '../../components/coordinate-field/segment-configs';\nimport type {\n CoordinateSystem,\n CoordinateValue,\n SegmentConfig,\n} from '../../components/coordinate-field/types';\n\nexport interface UseCoordinateFieldStateOptions {\n value?: CoordinateValue | null;\n defaultValue?: CoordinateValue;\n format: CoordinateSystem;\n onChange?:\n | Dispatch<SetStateAction<CoordinateValue | null>>\n | ((value: CoordinateValue | null) => void);\n onError?: (message: string, context?: Record<string, unknown>) => void;\n registerTimeout?: (timeoutId: NodeJS.Timeout) => void;\n}\n\nexport interface UseCoordinateFieldStateResult {\n currentValue: CoordinateValue | null;\n segmentValues: string[];\n validationErrors: string[];\n segmentConfigs: SegmentConfig[];\n editableSegmentConfigs: SegmentConfig[];\n handleSegmentChange: (index: number, newValue: string) => void;\n setSegmentValues: (values: string[]) => void;\n setValidationErrors: (errors: string[]) => void;\n effectiveErrorMessage: string | null;\n applyPastedCoordinate: (pastedValue: CoordinateValue) => void;\n flushPendingValidation: () => void;\n}\n\nexport function useCoordinateFieldState({\n value,\n defaultValue,\n format,\n onChange,\n onError,\n registerTimeout,\n}: UseCoordinateFieldStateOptions): UseCoordinateFieldStateResult {\n const [internalValue, setInternalValue] = useState<CoordinateValue | null>(\n defaultValue || null,\n );\n const [validationErrors, setValidationErrors] = useState<string[]>([]);\n const validationTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n const currentValue = value !== undefined ? value : internalValue;\n\n const clearValidationTimeout = () => {\n if (validationTimeoutRef.current) {\n clearTimeout(validationTimeoutRef.current);\n validationTimeoutRef.current = null;\n }\n };\n\n const handleChange = (newValue: CoordinateValue | null) => {\n if (value === undefined) {\n setInternalValue(newValue);\n }\n onChange?.(newValue);\n };\n\n const segmentConfigs = useMemo(() => getSegmentConfigs(format), [format]);\n\n const editableSegmentConfigs = useMemo(\n () => segmentConfigs.flat().filter((config) => config.type !== 'literal'),\n [segmentConfigs],\n );\n\n const [segmentValues, setSegmentValues] = useState<string[]>(() => {\n const initialValue = value !== undefined ? value : defaultValue;\n if (!initialValue) {\n return new Array(editableSegmentConfigs.length).fill('');\n }\n\n const segments = convertDDToDisplaySegments(initialValue, format);\n if (!segments) {\n return new Array(editableSegmentConfigs.length).fill('');\n }\n\n return segments;\n });\n\n const convertValueToSegmentsOrClear = useCallback(\n (valueToConvert: CoordinateValue | null) => {\n // Clear any pending validation when value changes\n clearValidationTimeout();\n\n const segments = valueToConvert\n ? convertDDToDisplaySegments(valueToConvert, format)\n : null;\n\n setSegmentValues(\n segments || new Array(editableSegmentConfigs.length).fill(''),\n );\n setValidationErrors([]);\n },\n [format, editableSegmentConfigs.length],\n );\n\n const prevFormatRef = useRef(format);\n\n useEffect(() => {\n if (prevFormatRef.current !== format) {\n prevFormatRef.current = format;\n const valueToConvert = value !== undefined ? value : internalValue;\n convertValueToSegmentsOrClear(valueToConvert);\n }\n }, [format, value, internalValue, convertValueToSegmentsOrClear]);\n\n useEffect(() => {\n if (value !== undefined) {\n convertValueToSegmentsOrClear(value);\n }\n }, [value, convertValueToSegmentsOrClear]);\n\n /**\n * Validates segment values and updates the coordinate state\n *\n * When validation fails, calls onError with \"Invalid coordinate value\" message\n * and context containing the detailed validation errors from @accelint/geo.\n *\n * @param updatedValues - Array of segment values to validate\n */\n const validateAndUpdateCoordinate = (updatedValues: string[]) => {\n const errors = validateCoordinateSegments(updatedValues, format);\n\n if (errors.length > 0) {\n setValidationErrors(errors);\n onError?.('Invalid coordinate value', {\n errors,\n format,\n segments: updatedValues,\n });\n handleChange(null);\n return;\n }\n\n const ddValue = convertDisplaySegmentsToDD(updatedValues, format);\n if (!ddValue) {\n const errorMsg = 'Invalid coordinate value';\n setValidationErrors([errorMsg]);\n onError?.(errorMsg, { format, segments: updatedValues });\n handleChange(null);\n return;\n }\n\n setValidationErrors([]);\n handleChange(ddValue);\n };\n\n const handleSegmentChange = (index: number, newValue: string) => {\n const updatedValues = [...segmentValues];\n updatedValues[index] = newValue;\n setSegmentValues(updatedValues);\n\n if (areAllSegmentsFilled(updatedValues)) {\n // Clear any pending validation timeout\n clearValidationTimeout();\n\n // Debounce validation by 400ms when all segments are full\n const timeoutId = setTimeout(() => {\n validateAndUpdateCoordinate(updatedValues);\n validationTimeoutRef.current = null;\n }, 400);\n\n validationTimeoutRef.current = timeoutId;\n registerTimeout?.(timeoutId);\n } else {\n // Clear any pending validation when segments become incomplete\n clearValidationTimeout();\n setValidationErrors([]);\n if (currentValue !== null) {\n handleChange(null);\n }\n }\n };\n\n const applyPastedCoordinate = (pastedValue: CoordinateValue) => {\n // Clear any pending validation when applying pasted coordinate\n clearValidationTimeout();\n\n const segments = convertDDToDisplaySegments(pastedValue, format);\n\n if (segments) {\n setSegmentValues(segments);\n setValidationErrors([]);\n handleChange(pastedValue);\n }\n };\n\n const flushPendingValidation = () => {\n if (validationTimeoutRef.current) {\n clearValidationTimeout();\n\n // Immediately validate if all segments are filled\n if (areAllSegmentsFilled(segmentValues)) {\n validateAndUpdateCoordinate(segmentValues);\n }\n }\n };\n\n const effectiveErrorMessage = useMemo(\n () => validationErrors[0] || null,\n [validationErrors],\n );\n\n return {\n currentValue,\n segmentValues,\n validationErrors,\n segmentConfigs,\n editableSegmentConfigs,\n handleSegmentChange,\n setSegmentValues,\n setValidationErrors,\n effectiveErrorMessage,\n applyPastedCoordinate,\n flushPendingValidation,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2DA,SAAgB,wBAAwB,EACtC,OACA,cACA,QACA,UACA,SACA,mBACgE;CAChE,MAAM,CAAC,eAAe,oBAAoB,SACxC,gBAAgB,KACjB;CACD,MAAM,CAAC,kBAAkB,uBAAuB,SAAmB,EAAE,CAAC;CACtE,MAAM,uBAAuB,OAA8B,KAAK;CAEhE,MAAM,eAAe,UAAU,SAAY,QAAQ;CAEnD,MAAM,+BAA+B;AACnC,MAAI,qBAAqB,SAAS;AAChC,gBAAa,qBAAqB,QAAQ;AAC1C,wBAAqB,UAAU;;;CAInC,MAAM,gBAAgB,aAAqC;AACzD,MAAI,UAAU,OACZ,kBAAiB,SAAS;AAE5B,aAAW,SAAS;;CAGtB,MAAM,iBAAiB,cAAc,kBAAkB,OAAO,EAAE,CAAC,OAAO,CAAC;CAEzE,MAAM,yBAAyB,cACvB,eAAe,MAAM,CAAC,QAAQ,WAAW,OAAO,SAAS,UAAU,EACzE,CAAC,eAAe,CACjB;CAED,MAAM,CAAC,eAAe,oBAAoB,eAAyB;EACjE,MAAM,eAAe,UAAU,SAAY,QAAQ;AACnD,MAAI,CAAC,aACH,QAAO,IAAI,MAAM,uBAAuB,OAAO,CAAC,KAAK,GAAG;EAG1D,MAAM,WAAW,2BAA2B,cAAc,OAAO;AACjE,MAAI,CAAC,SACH,QAAO,IAAI,MAAM,uBAAuB,OAAO,CAAC,KAAK,GAAG;AAG1D,SAAO;GACP;CAEF,MAAM,gCAAgC,aACnC,mBAA2C;AAE1C,0BAAwB;AAMxB,oBAJiB,iBACb,2BAA2B,gBAAgB,OAAO,GAClD,SAGU,IAAI,MAAM,uBAAuB,OAAO,CAAC,KAAK,GAAG,CAC9D;AACD,sBAAoB,EAAE,CAAC;IAEzB,CAAC,QAAQ,uBAAuB,OAAO,CACxC;CAED,MAAM,gBAAgB,OAAO,OAAO;AAEpC,iBAAgB;AACd,MAAI,cAAc,YAAY,QAAQ;AACpC,iBAAc,UAAU;AAExB,iCADuB,UAAU,SAAY,QAAQ,cACR;;IAE9C;EAAC;EAAQ;EAAO;EAAe;EAA8B,CAAC;AAEjE,iBAAgB;AACd,MAAI,UAAU,OACZ,+BAA8B,MAAM;IAErC,CAAC,OAAO,8BAA8B,CAAC;;;;;;;;;CAU1C,MAAM,+BAA+B,kBAA4B;EAC/D,MAAM,SAAS,2BAA2B,eAAe,OAAO;AAEhE,MAAI,OAAO,SAAS,GAAG;AACrB,uBAAoB,OAAO;AAC3B,aAAU,4BAA4B;IACpC;IACA;IACA,UAAU;IACX,CAAC;AACF,gBAAa,KAAK;AAClB;;EAGF,MAAM,UAAU,2BAA2B,eAAe,OAAO;AACjE,MAAI,CAAC,SAAS;GACZ,MAAM,WAAW;AACjB,uBAAoB,CAAC,SAAS,CAAC;AAC/B,aAAU,UAAU;IAAE;IAAQ,UAAU;IAAe,CAAC;AACxD,gBAAa,KAAK;AAClB;;AAGF,sBAAoB,EAAE,CAAC;AACvB,eAAa,QAAQ;;CAGvB,MAAM,uBAAuB,OAAe,aAAqB;EAC/D,MAAM,gBAAgB,CAAC,GAAG,cAAc;AACxC,gBAAc,SAAS;AACvB,mBAAiB,cAAc;AAE/B,MAAI,qBAAqB,cAAc,EAAE;AAEvC,2BAAwB;GAGxB,MAAM,YAAY,iBAAiB;AACjC,gCAA4B,cAAc;AAC1C,yBAAqB,UAAU;MAC9B,IAAI;AAEP,wBAAqB,UAAU;AAC/B,qBAAkB,UAAU;SACvB;AAEL,2BAAwB;AACxB,uBAAoB,EAAE,CAAC;AACvB,OAAI,iBAAiB,KACnB,cAAa,KAAK;;;CAKxB,MAAM,yBAAyB,gBAAiC;AAE9D,0BAAwB;EAExB,MAAM,WAAW,2BAA2B,aAAa,OAAO;AAEhE,MAAI,UAAU;AACZ,oBAAiB,SAAS;AAC1B,uBAAoB,EAAE,CAAC;AACvB,gBAAa,YAAY;;;CAI7B,MAAM,+BAA+B;AACnC,MAAI,qBAAqB,SAAS;AAChC,2BAAwB;AAGxB,OAAI,qBAAqB,cAAc,CACrC,6BAA4B,cAAc;;;AAUhD,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,uBAd4B,cACtB,iBAAiB,MAAM,MAC7B,CAAC,iBAAiB,CACnB;EAYC;EACA;EACD"}
1
+ {"version":3,"file":"use-coordinate-field-state.js","names":[],"sources":["../../../src/hooks/coordinate-field/use-coordinate-field-state.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n type Dispatch,\n type SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n areAllSegmentsFilled,\n convertDDToDisplaySegments,\n convertDisplaySegmentsToDD,\n validateCoordinateSegments,\n} from '../../components/coordinate-field/coordinate-utils';\nimport { getSegmentConfigs } from '../../components/coordinate-field/segment-configs';\nimport type {\n CoordinateSystem,\n CoordinateValue,\n SegmentConfig,\n} from '../../components/coordinate-field/types';\n\n/** Options for the useCoordinateFieldState hook */\nexport interface UseCoordinateFieldStateOptions {\n /** Controlled coordinate value */\n value?: CoordinateValue | null;\n /** Default value for uncontrolled mode */\n defaultValue?: CoordinateValue;\n /** Coordinate format system (dd, ddm, dms, mgrs, utm) */\n format: CoordinateSystem;\n /** Callback when coordinate value changes */\n onChange?:\n | Dispatch<SetStateAction<CoordinateValue | null>>\n | ((value: CoordinateValue | null) => void);\n /** Callback for validation errors */\n onError?: (message: string, context?: Record<string, unknown>) => void;\n /** Register timeouts for cleanup on unmount */\n registerTimeout?: (timeoutId: NodeJS.Timeout) => void;\n}\n\n/** Return value from the useCoordinateFieldState hook */\nexport interface UseCoordinateFieldStateResult {\n /** Current coordinate value (null if incomplete/invalid) */\n currentValue: CoordinateValue | null;\n /** Array of display values for each segment */\n segmentValues: string[];\n /** Array of validation error messages */\n validationErrors: string[];\n /** All segment configurations including literals */\n segmentConfigs: SegmentConfig[];\n /** Only editable segment configurations */\n editableSegmentConfigs: SegmentConfig[];\n /** Handle change of a single segment */\n handleSegmentChange: (index: number, newValue: string) => void;\n /** Set all segment values at once */\n setSegmentValues: (values: string[]) => void;\n /** Set validation errors */\n setValidationErrors: (errors: string[]) => void;\n /** First validation error or null */\n effectiveErrorMessage: string | null;\n /** Apply a pasted coordinate value */\n applyPastedCoordinate: (pastedValue: CoordinateValue) => void;\n /** Immediately run pending validation */\n flushPendingValidation: () => void;\n}\n\n/**\n * Manages coordinate segment values, validation, and format conversion\n *\n * @example\n * ```tsx\n * function CoordinateInputs() {\n * const [value, setValue] = useState<CoordinateValue | null>(null);\n * const { registerTimeout } = useTimeoutCleanup();\n *\n * const {\n * currentValue,\n * segmentValues,\n * validationErrors,\n * editableSegmentConfigs,\n * handleSegmentChange,\n * } = useCoordinateFieldState({\n * value,\n * format: 'ddm',\n * onChange: setValue,\n * onError: (msg) => console.error(msg),\n * registerTimeout,\n * });\n *\n * return (\n * <div>\n * {editableSegmentConfigs.map((config, i) => (\n * <input\n * key={i}\n * value={segmentValues[i]}\n * onChange={(e) => handleSegmentChange(i, e.target.value)}\n * placeholder={config.placeholder}\n * />\n * ))}\n * {validationErrors.map((error, i) => (\n * <span key={i}>{error}</span>\n * ))}\n * </div>\n * );\n * }\n * ```\n *\n * @param options - {@link UseCoordinateFieldStateOptions}\n * @param options.value - Controlled coordinate value.\n * @param options.defaultValue - Default value for uncontrolled mode.\n * @param options.format - Coordinate format system (dd, ddm, dms, mgrs, utm).\n * @param options.onChange - Callback when coordinate value changes.\n * @param options.onError - Callback for validation errors.\n * @param options.registerTimeout - Register timeouts for cleanup on unmount.\n * @returns {@link UseCoordinateFieldStateResult} Segment state, validation, and change handlers.\n */\nexport function useCoordinateFieldState({\n value,\n defaultValue,\n format,\n onChange,\n onError,\n registerTimeout,\n}: UseCoordinateFieldStateOptions): UseCoordinateFieldStateResult {\n const [internalValue, setInternalValue] = useState<CoordinateValue | null>(\n defaultValue || null,\n );\n const [validationErrors, setValidationErrors] = useState<string[]>([]);\n const validationTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n const currentValue = value !== undefined ? value : internalValue;\n\n const clearValidationTimeout = () => {\n if (validationTimeoutRef.current) {\n clearTimeout(validationTimeoutRef.current);\n validationTimeoutRef.current = null;\n }\n };\n\n const handleChange = (newValue: CoordinateValue | null) => {\n if (value === undefined) {\n setInternalValue(newValue);\n }\n onChange?.(newValue);\n };\n\n const segmentConfigs = useMemo(() => getSegmentConfigs(format), [format]);\n\n const editableSegmentConfigs = useMemo(\n () => segmentConfigs.flat().filter((config) => config.type !== 'literal'),\n [segmentConfigs],\n );\n\n const [segmentValues, setSegmentValues] = useState<string[]>(() => {\n const initialValue = value !== undefined ? value : defaultValue;\n if (!initialValue) {\n return new Array(editableSegmentConfigs.length).fill('');\n }\n\n const segments = convertDDToDisplaySegments(initialValue, format);\n if (!segments) {\n return new Array(editableSegmentConfigs.length).fill('');\n }\n\n return segments;\n });\n\n const convertValueToSegmentsOrClear = useCallback(\n (valueToConvert: CoordinateValue | null) => {\n // Clear any pending validation when value changes\n clearValidationTimeout();\n\n const segments = valueToConvert\n ? convertDDToDisplaySegments(valueToConvert, format)\n : null;\n\n setSegmentValues(\n segments || new Array(editableSegmentConfigs.length).fill(''),\n );\n setValidationErrors([]);\n },\n [format, editableSegmentConfigs.length],\n );\n\n const prevFormatRef = useRef(format);\n\n useEffect(() => {\n if (prevFormatRef.current !== format) {\n prevFormatRef.current = format;\n const valueToConvert = value !== undefined ? value : internalValue;\n convertValueToSegmentsOrClear(valueToConvert);\n }\n }, [format, value, internalValue, convertValueToSegmentsOrClear]);\n\n useEffect(() => {\n if (value !== undefined) {\n convertValueToSegmentsOrClear(value);\n }\n }, [value, convertValueToSegmentsOrClear]);\n\n /**\n * Validates segment values and updates the coordinate state\n *\n * When validation fails, calls onError with \"Invalid coordinate value\" message\n * and context containing the detailed validation errors from @accelint/geo.\n *\n * @param updatedValues - Array of segment values to validate\n */\n const validateAndUpdateCoordinate = (updatedValues: string[]) => {\n const errors = validateCoordinateSegments(updatedValues, format);\n\n if (errors.length > 0) {\n setValidationErrors(errors);\n onError?.('Invalid coordinate value', {\n errors,\n format,\n segments: updatedValues,\n });\n handleChange(null);\n return;\n }\n\n const ddValue = convertDisplaySegmentsToDD(updatedValues, format);\n if (!ddValue) {\n const errorMsg = 'Invalid coordinate value';\n setValidationErrors([errorMsg]);\n onError?.(errorMsg, { format, segments: updatedValues });\n handleChange(null);\n return;\n }\n\n setValidationErrors([]);\n handleChange(ddValue);\n };\n\n const handleSegmentChange = (index: number, newValue: string) => {\n const updatedValues = [...segmentValues];\n updatedValues[index] = newValue;\n setSegmentValues(updatedValues);\n\n if (areAllSegmentsFilled(updatedValues)) {\n // Clear any pending validation timeout\n clearValidationTimeout();\n\n // Debounce validation by 400ms when all segments are full\n const timeoutId = setTimeout(() => {\n validateAndUpdateCoordinate(updatedValues);\n validationTimeoutRef.current = null;\n }, 400);\n\n validationTimeoutRef.current = timeoutId;\n registerTimeout?.(timeoutId);\n } else {\n // Clear any pending validation when segments become incomplete\n clearValidationTimeout();\n setValidationErrors([]);\n if (currentValue !== null) {\n handleChange(null);\n }\n }\n };\n\n const applyPastedCoordinate = (pastedValue: CoordinateValue) => {\n // Clear any pending validation when applying pasted coordinate\n clearValidationTimeout();\n\n const segments = convertDDToDisplaySegments(pastedValue, format);\n\n if (segments) {\n setSegmentValues(segments);\n setValidationErrors([]);\n handleChange(pastedValue);\n }\n };\n\n const flushPendingValidation = () => {\n if (validationTimeoutRef.current) {\n clearValidationTimeout();\n\n // Immediately validate if all segments are filled\n if (areAllSegmentsFilled(segmentValues)) {\n validateAndUpdateCoordinate(segmentValues);\n }\n }\n };\n\n const effectiveErrorMessage = useMemo(\n () => validationErrors[0] || null,\n [validationErrors],\n );\n\n return {\n currentValue,\n segmentValues,\n validationErrors,\n segmentConfigs,\n editableSegmentConfigs,\n handleSegmentChange,\n setSegmentValues,\n setValidationErrors,\n effectiveErrorMessage,\n applyPastedCoordinate,\n flushPendingValidation,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgIA,SAAgB,wBAAwB,EACtC,OACA,cACA,QACA,UACA,SACA,mBACgE;CAChE,MAAM,CAAC,eAAe,oBAAoB,SACxC,gBAAgB,KACjB;CACD,MAAM,CAAC,kBAAkB,uBAAuB,SAAmB,EAAE,CAAC;CACtE,MAAM,uBAAuB,OAA8B,KAAK;CAEhE,MAAM,eAAe,UAAU,SAAY,QAAQ;CAEnD,MAAM,+BAA+B;AACnC,MAAI,qBAAqB,SAAS;AAChC,gBAAa,qBAAqB,QAAQ;AAC1C,wBAAqB,UAAU;;;CAInC,MAAM,gBAAgB,aAAqC;AACzD,MAAI,UAAU,OACZ,kBAAiB,SAAS;AAE5B,aAAW,SAAS;;CAGtB,MAAM,iBAAiB,cAAc,kBAAkB,OAAO,EAAE,CAAC,OAAO,CAAC;CAEzE,MAAM,yBAAyB,cACvB,eAAe,MAAM,CAAC,QAAQ,WAAW,OAAO,SAAS,UAAU,EACzE,CAAC,eAAe,CACjB;CAED,MAAM,CAAC,eAAe,oBAAoB,eAAyB;EACjE,MAAM,eAAe,UAAU,SAAY,QAAQ;AACnD,MAAI,CAAC,aACH,QAAO,IAAI,MAAM,uBAAuB,OAAO,CAAC,KAAK,GAAG;EAG1D,MAAM,WAAW,2BAA2B,cAAc,OAAO;AACjE,MAAI,CAAC,SACH,QAAO,IAAI,MAAM,uBAAuB,OAAO,CAAC,KAAK,GAAG;AAG1D,SAAO;GACP;CAEF,MAAM,gCAAgC,aACnC,mBAA2C;AAE1C,0BAAwB;AAMxB,oBAJiB,iBACb,2BAA2B,gBAAgB,OAAO,GAClD,SAGU,IAAI,MAAM,uBAAuB,OAAO,CAAC,KAAK,GAAG,CAC9D;AACD,sBAAoB,EAAE,CAAC;IAEzB,CAAC,QAAQ,uBAAuB,OAAO,CACxC;CAED,MAAM,gBAAgB,OAAO,OAAO;AAEpC,iBAAgB;AACd,MAAI,cAAc,YAAY,QAAQ;AACpC,iBAAc,UAAU;AAExB,iCADuB,UAAU,SAAY,QAAQ,cACR;;IAE9C;EAAC;EAAQ;EAAO;EAAe;EAA8B,CAAC;AAEjE,iBAAgB;AACd,MAAI,UAAU,OACZ,+BAA8B,MAAM;IAErC,CAAC,OAAO,8BAA8B,CAAC;;;;;;;;;CAU1C,MAAM,+BAA+B,kBAA4B;EAC/D,MAAM,SAAS,2BAA2B,eAAe,OAAO;AAEhE,MAAI,OAAO,SAAS,GAAG;AACrB,uBAAoB,OAAO;AAC3B,aAAU,4BAA4B;IACpC;IACA;IACA,UAAU;IACX,CAAC;AACF,gBAAa,KAAK;AAClB;;EAGF,MAAM,UAAU,2BAA2B,eAAe,OAAO;AACjE,MAAI,CAAC,SAAS;GACZ,MAAM,WAAW;AACjB,uBAAoB,CAAC,SAAS,CAAC;AAC/B,aAAU,UAAU;IAAE;IAAQ,UAAU;IAAe,CAAC;AACxD,gBAAa,KAAK;AAClB;;AAGF,sBAAoB,EAAE,CAAC;AACvB,eAAa,QAAQ;;CAGvB,MAAM,uBAAuB,OAAe,aAAqB;EAC/D,MAAM,gBAAgB,CAAC,GAAG,cAAc;AACxC,gBAAc,SAAS;AACvB,mBAAiB,cAAc;AAE/B,MAAI,qBAAqB,cAAc,EAAE;AAEvC,2BAAwB;GAGxB,MAAM,YAAY,iBAAiB;AACjC,gCAA4B,cAAc;AAC1C,yBAAqB,UAAU;MAC9B,IAAI;AAEP,wBAAqB,UAAU;AAC/B,qBAAkB,UAAU;SACvB;AAEL,2BAAwB;AACxB,uBAAoB,EAAE,CAAC;AACvB,OAAI,iBAAiB,KACnB,cAAa,KAAK;;;CAKxB,MAAM,yBAAyB,gBAAiC;AAE9D,0BAAwB;EAExB,MAAM,WAAW,2BAA2B,aAAa,OAAO;AAEhE,MAAI,UAAU;AACZ,oBAAiB,SAAS;AAC1B,uBAAoB,EAAE,CAAC;AACvB,gBAAa,YAAY;;;CAI7B,MAAM,+BAA+B;AACnC,MAAI,qBAAqB,SAAS;AAChC,2BAAwB;AAGxB,OAAI,qBAAqB,cAAc,CACrC,6BAA4B,cAAc;;;AAUhD,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,uBAd4B,cACtB,iBAAiB,MAAM,MAC7B,CAAC,iBAAiB,CACnB;EAYC;EACA;EACD"}
@@ -18,12 +18,19 @@ import { useCoordinatePaste } from "./use-coordinate-paste.js";
18
18
  import { ValidationResult } from "react-aria-components";
19
19
 
20
20
  //#region src/hooks/coordinate-field/use-coordinate-field.d.ts
21
+ /** Return value from the useCoordinateField hook */
21
22
  interface UseCoordinateFieldResult {
23
+ /** Coordinate state management utilities */
22
24
  state: ReturnType<typeof useCoordinateFieldState>;
25
+ /** Focus management utilities */
23
26
  focus: ReturnType<typeof useCoordinateFocus>;
27
+ /** Paste handling utilities */
24
28
  paste: ReturnType<typeof useCoordinatePaste>;
29
+ /** Copy handling utilities */
25
30
  copy: ReturnType<typeof useCoordinateCopy>;
31
+ /** Register timeouts for cleanup */
26
32
  registerTimeout: (timeoutId: NodeJS.Timeout) => void;
33
+ /** ARIA props for the field container */
27
34
  fieldProps: {
28
35
  id: string;
29
36
  role: 'group';
@@ -35,26 +42,80 @@ interface UseCoordinateFieldResult {
35
42
  'aria-required': boolean | undefined;
36
43
  'aria-disabled': boolean | undefined;
37
44
  };
45
+ /** Props for the label element */
38
46
  labelProps: {
39
47
  id: string;
40
48
  htmlFor: string;
41
49
  };
50
+ /** Props for the description element */
42
51
  descriptionProps: {
43
52
  id: string;
44
53
  };
54
+ /** Props for the error message element */
45
55
  errorProps: {
46
56
  id: string;
47
57
  };
58
+ /** Validation result for react-aria */
48
59
  validation: ValidationResult;
60
+ /** Generated element IDs */
49
61
  ids: {
50
62
  fieldId: string;
51
63
  labelId: string;
52
64
  descriptionId: string;
53
65
  errorId: string;
54
66
  };
67
+ /** First error message or null */
55
68
  effectiveErrorMessage: string | null;
69
+ /** Whether the field is in an invalid state */
56
70
  isInvalid: boolean;
57
71
  }
72
+ /**
73
+ * Manages coordinate field state, focus, copy, paste, and accessibility props
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * function CoordinateFieldComponent() {
78
+ * const [value, setValue] = useState<CoordinateValue | null>(null);
79
+ *
80
+ * const {
81
+ * state,
82
+ * focus,
83
+ * paste,
84
+ * copy,
85
+ * fieldProps,
86
+ * labelProps,
87
+ * isInvalid,
88
+ * effectiveErrorMessage,
89
+ * } = useCoordinateField({
90
+ * value,
91
+ * onChange: setValue,
92
+ * format: 'dd',
93
+ * label: 'Location',
94
+ * });
95
+ *
96
+ * return (
97
+ * <div {...fieldProps}>
98
+ * <label {...labelProps}>Location</label>
99
+ * {state.editableSegmentConfigs.map((config, index) => (
100
+ * <input
101
+ * key={index}
102
+ * ref={focus.segmentRefs[index]}
103
+ * value={state.segmentValues[index]}
104
+ * onChange={(e) => state.handleSegmentChange(index, e.target.value)}
105
+ * />
106
+ * ))}
107
+ * {isInvalid && <span>{effectiveErrorMessage}</span>}
108
+ * </div>
109
+ * );
110
+ * }
111
+ * ```
112
+ *
113
+ * @param props - {@link CoordinateFieldProps}
114
+ * @param customAriaLabel - Custom aria-label for the field.
115
+ * @param customAriaDescribedby - Custom aria-describedby IDs.
116
+ * @param customAriaDetails - Custom aria-details ID.
117
+ * @returns {@link UseCoordinateFieldResult} Combined state, focus, copy, paste utilities and accessibility props.
118
+ */
58
119
  declare function useCoordinateField(props: CoordinateFieldProps, customAriaLabel?: string, customAriaDescribedby?: string, customAriaDetails?: string): UseCoordinateFieldResult;
59
120
  //#endregion
60
121
  export { UseCoordinateFieldResult, useCoordinateField };
@@ -21,6 +21,53 @@ import { useId } from "@react-aria/utils";
21
21
 
22
22
  //#region src/hooks/coordinate-field/use-coordinate-field.ts
23
23
  const FOCUS_DELAY_MS = 0;
24
+ /**
25
+ * Manages coordinate field state, focus, copy, paste, and accessibility props
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * function CoordinateFieldComponent() {
30
+ * const [value, setValue] = useState<CoordinateValue | null>(null);
31
+ *
32
+ * const {
33
+ * state,
34
+ * focus,
35
+ * paste,
36
+ * copy,
37
+ * fieldProps,
38
+ * labelProps,
39
+ * isInvalid,
40
+ * effectiveErrorMessage,
41
+ * } = useCoordinateField({
42
+ * value,
43
+ * onChange: setValue,
44
+ * format: 'dd',
45
+ * label: 'Location',
46
+ * });
47
+ *
48
+ * return (
49
+ * <div {...fieldProps}>
50
+ * <label {...labelProps}>Location</label>
51
+ * {state.editableSegmentConfigs.map((config, index) => (
52
+ * <input
53
+ * key={index}
54
+ * ref={focus.segmentRefs[index]}
55
+ * value={state.segmentValues[index]}
56
+ * onChange={(e) => state.handleSegmentChange(index, e.target.value)}
57
+ * />
58
+ * ))}
59
+ * {isInvalid && <span>{effectiveErrorMessage}</span>}
60
+ * </div>
61
+ * );
62
+ * }
63
+ * ```
64
+ *
65
+ * @param props - {@link CoordinateFieldProps}
66
+ * @param customAriaLabel - Custom aria-label for the field.
67
+ * @param customAriaDescribedby - Custom aria-describedby IDs.
68
+ * @param customAriaDetails - Custom aria-details ID.
69
+ * @returns {@link UseCoordinateFieldResult} Combined state, focus, copy, paste utilities and accessibility props.
70
+ */
24
71
  function useCoordinateField(props, customAriaLabel, customAriaDescribedby, customAriaDetails) {
25
72
  const { description, errorMessage: errorMessageProp, format = "dd", value, defaultValue, onChange, onError, isDisabled = false, isInvalid: isInvalidProp = false, isRequired = false, id: idProp } = props;
26
73
  const fieldId = useId(idProp);
@@ -1 +1 @@
1
- {"version":3,"file":"use-coordinate-field.js","names":[],"sources":["../../../src/hooks/coordinate-field/use-coordinate-field.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 { useId } from '@react-aria/utils';\nimport { useMemo } from 'react';\nimport { useCoordinateCopy } from './use-coordinate-copy';\nimport { useCoordinateFieldState } from './use-coordinate-field-state';\nimport { useCoordinateFocus } from './use-coordinate-focus';\nimport { useCoordinatePaste } from './use-coordinate-paste';\nimport { useTimeoutCleanup } from './use-timeout-cleanup';\nimport type { ValidationResult } from 'react-aria-components';\nimport type {\n CoordinateFieldProps,\n CoordinateSystem,\n CoordinateValue,\n} from '../../components/coordinate-field/types';\n\nconst FOCUS_DELAY_MS = 0;\n\nexport interface UseCoordinateFieldResult {\n state: ReturnType<typeof useCoordinateFieldState>;\n focus: ReturnType<typeof useCoordinateFocus>;\n paste: ReturnType<typeof useCoordinatePaste>;\n copy: ReturnType<typeof useCoordinateCopy>;\n registerTimeout: (timeoutId: NodeJS.Timeout) => void;\n fieldProps: {\n id: string;\n role: 'group';\n 'aria-labelledby': string | undefined;\n 'aria-describedby': string | undefined;\n 'aria-label': string | undefined;\n 'aria-details': string | undefined;\n 'aria-invalid': boolean | undefined;\n 'aria-required': boolean | undefined;\n 'aria-disabled': boolean | undefined;\n };\n labelProps: {\n id: string;\n htmlFor: string;\n };\n descriptionProps: {\n id: string;\n };\n errorProps: {\n id: string;\n };\n validation: ValidationResult;\n ids: {\n fieldId: string;\n labelId: string;\n descriptionId: string;\n errorId: string;\n };\n effectiveErrorMessage: string | null;\n isInvalid: boolean;\n}\n\nexport function useCoordinateField(\n props: CoordinateFieldProps,\n customAriaLabel?: string,\n customAriaDescribedby?: string,\n customAriaDetails?: string,\n): UseCoordinateFieldResult {\n const {\n description,\n errorMessage: errorMessageProp,\n format = 'dd' as CoordinateSystem,\n value,\n defaultValue,\n onChange,\n onError,\n isDisabled = false,\n isInvalid: isInvalidProp = false,\n isRequired = false,\n id: idProp,\n } = props;\n\n const fieldId = useId(idProp);\n const labelId = useId();\n const descriptionId = useId();\n const errorId = useId();\n\n const { registerTimeout } = useTimeoutCleanup();\n\n const state = useCoordinateFieldState({\n value,\n defaultValue,\n format,\n onChange,\n onError,\n registerTimeout,\n });\n\n const focus = useCoordinateFocus({\n editableSegmentConfigs: state.editableSegmentConfigs,\n });\n\n const handlePasteValueApplied = (pastedValue: CoordinateValue) => {\n state.applyPastedCoordinate(pastedValue);\n\n // Defer focus until after React commits state updates to the DOM.\n // applyPastedCoordinate triggers setSegmentValues which updates the input\n // elements, and we need those updates to complete before focusing.\n registerTimeout(\n setTimeout(() => {\n focus.focusFirstSegment();\n }, FOCUS_DELAY_MS),\n );\n };\n\n const paste = useCoordinatePaste({\n onValueApplied: handlePasteValueApplied,\n onError,\n });\n\n const copy = useCoordinateCopy({\n currentValue: state.currentValue,\n validationErrors: state.validationErrors,\n isDisabled,\n registerTimeout,\n });\n\n const effectiveErrorMessage = useMemo(\n () => errorMessageProp || state.effectiveErrorMessage,\n [errorMessageProp, state.effectiveErrorMessage],\n );\n\n const isInvalid = isInvalidProp || effectiveErrorMessage !== null;\n\n const describedByIds = [\n description && descriptionId,\n effectiveErrorMessage && errorId,\n customAriaDescribedby,\n ].filter(Boolean);\n const describedBy =\n describedByIds.length > 0 ? describedByIds.join(' ') : undefined;\n\n const labelProps = {\n id: labelId,\n htmlFor: fieldId,\n };\n\n // Only use aria-labelledby when we have a visible label (not using aria-label)\n // When aria-label is provided (e.g., in small size), it takes precedence\n const ariaLabelledBy = customAriaLabel ? undefined : labelId;\n\n const fieldProps = {\n id: fieldId,\n role: 'group' as const,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': describedBy,\n 'aria-label': customAriaLabel || undefined,\n 'aria-details': customAriaDetails || undefined,\n 'aria-invalid': isInvalid || undefined,\n 'aria-required': isRequired || undefined,\n 'aria-disabled': isDisabled || undefined,\n };\n\n const descriptionProps = {\n id: descriptionId,\n };\n\n const errorProps = {\n id: errorId,\n };\n\n const validation: ValidationResult = useMemo(\n () => ({\n isInvalid,\n validationErrors: effectiveErrorMessage ? [effectiveErrorMessage] : [],\n validationDetails: {} as ValidityState,\n }),\n [isInvalid, effectiveErrorMessage],\n );\n\n return {\n state,\n focus,\n paste,\n copy,\n registerTimeout,\n fieldProps,\n labelProps,\n descriptionProps,\n errorProps,\n validation,\n ids: {\n fieldId,\n labelId,\n descriptionId,\n errorId,\n },\n effectiveErrorMessage,\n isInvalid,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,iBAAiB;AAwCvB,SAAgB,mBACd,OACA,iBACA,uBACA,mBAC0B;CAC1B,MAAM,EACJ,aACA,cAAc,kBACd,SAAS,MACT,OACA,cACA,UACA,SACA,aAAa,OACb,WAAW,gBAAgB,OAC3B,aAAa,OACb,IAAI,WACF;CAEJ,MAAM,UAAU,MAAM,OAAO;CAC7B,MAAM,UAAU,OAAO;CACvB,MAAM,gBAAgB,OAAO;CAC7B,MAAM,UAAU,OAAO;CAEvB,MAAM,EAAE,oBAAoB,mBAAmB;CAE/C,MAAM,QAAQ,wBAAwB;EACpC;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CAEF,MAAM,QAAQ,mBAAmB,EAC/B,wBAAwB,MAAM,wBAC/B,CAAC;CAEF,MAAM,2BAA2B,gBAAiC;AAChE,QAAM,sBAAsB,YAAY;AAKxC,kBACE,iBAAiB;AACf,SAAM,mBAAmB;KACxB,eAAe,CACnB;;CAGH,MAAM,QAAQ,mBAAmB;EAC/B,gBAAgB;EAChB;EACD,CAAC;CAEF,MAAM,OAAO,kBAAkB;EAC7B,cAAc,MAAM;EACpB,kBAAkB,MAAM;EACxB;EACA;EACD,CAAC;CAEF,MAAM,wBAAwB,cACtB,oBAAoB,MAAM,uBAChC,CAAC,kBAAkB,MAAM,sBAAsB,CAChD;CAED,MAAM,YAAY,iBAAiB,0BAA0B;CAE7D,MAAM,iBAAiB;EACrB,eAAe;EACf,yBAAyB;EACzB;EACD,CAAC,OAAO,QAAQ;CACjB,MAAM,cACJ,eAAe,SAAS,IAAI,eAAe,KAAK,IAAI,GAAG;CAEzD,MAAM,aAAa;EACjB,IAAI;EACJ,SAAS;EACV;CAID,MAAM,iBAAiB,kBAAkB,SAAY;AA+BrD,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,YAnCiB;GACjB,IAAI;GACJ,MAAM;GACN,mBAAmB;GACnB,oBAAoB;GACpB,cAAc,mBAAmB;GACjC,gBAAgB,qBAAqB;GACrC,gBAAgB,aAAa;GAC7B,iBAAiB,cAAc;GAC/B,iBAAiB,cAAc;GAChC;EA0BC;EACA,kBAzBuB,EACvB,IAAI,eACL;EAwBC,YAtBiB,EACjB,IAAI,SACL;EAqBC,YAnBmC,eAC5B;GACL;GACA,kBAAkB,wBAAwB,CAAC,sBAAsB,GAAG,EAAE;GACtE,mBAAmB,EAAE;GACtB,GACD,CAAC,WAAW,sBAAsB,CACnC;EAaC,KAAK;GACH;GACA;GACA;GACA;GACD;EACD;EACA;EACD"}
1
+ {"version":3,"file":"use-coordinate-field.js","names":[],"sources":["../../../src/hooks/coordinate-field/use-coordinate-field.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 { useId } from '@react-aria/utils';\nimport { useMemo } from 'react';\nimport { useCoordinateCopy } from './use-coordinate-copy';\nimport { useCoordinateFieldState } from './use-coordinate-field-state';\nimport { useCoordinateFocus } from './use-coordinate-focus';\nimport { useCoordinatePaste } from './use-coordinate-paste';\nimport { useTimeoutCleanup } from './use-timeout-cleanup';\nimport type { ValidationResult } from 'react-aria-components';\nimport type {\n CoordinateFieldProps,\n CoordinateSystem,\n CoordinateValue,\n} from '../../components/coordinate-field/types';\n\nconst FOCUS_DELAY_MS = 0;\n\n/** Return value from the useCoordinateField hook */\nexport interface UseCoordinateFieldResult {\n /** Coordinate state management utilities */\n state: ReturnType<typeof useCoordinateFieldState>;\n /** Focus management utilities */\n focus: ReturnType<typeof useCoordinateFocus>;\n /** Paste handling utilities */\n paste: ReturnType<typeof useCoordinatePaste>;\n /** Copy handling utilities */\n copy: ReturnType<typeof useCoordinateCopy>;\n /** Register timeouts for cleanup */\n registerTimeout: (timeoutId: NodeJS.Timeout) => void;\n /** ARIA props for the field container */\n fieldProps: {\n id: string;\n role: 'group';\n 'aria-labelledby': string | undefined;\n 'aria-describedby': string | undefined;\n 'aria-label': string | undefined;\n 'aria-details': string | undefined;\n 'aria-invalid': boolean | undefined;\n 'aria-required': boolean | undefined;\n 'aria-disabled': boolean | undefined;\n };\n /** Props for the label element */\n labelProps: {\n id: string;\n htmlFor: string;\n };\n /** Props for the description element */\n descriptionProps: {\n id: string;\n };\n /** Props for the error message element */\n errorProps: {\n id: string;\n };\n /** Validation result for react-aria */\n validation: ValidationResult;\n /** Generated element IDs */\n ids: {\n fieldId: string;\n labelId: string;\n descriptionId: string;\n errorId: string;\n };\n /** First error message or null */\n effectiveErrorMessage: string | null;\n /** Whether the field is in an invalid state */\n isInvalid: boolean;\n}\n\n/**\n * Manages coordinate field state, focus, copy, paste, and accessibility props\n *\n * @example\n * ```tsx\n * function CoordinateFieldComponent() {\n * const [value, setValue] = useState<CoordinateValue | null>(null);\n *\n * const {\n * state,\n * focus,\n * paste,\n * copy,\n * fieldProps,\n * labelProps,\n * isInvalid,\n * effectiveErrorMessage,\n * } = useCoordinateField({\n * value,\n * onChange: setValue,\n * format: 'dd',\n * label: 'Location',\n * });\n *\n * return (\n * <div {...fieldProps}>\n * <label {...labelProps}>Location</label>\n * {state.editableSegmentConfigs.map((config, index) => (\n * <input\n * key={index}\n * ref={focus.segmentRefs[index]}\n * value={state.segmentValues[index]}\n * onChange={(e) => state.handleSegmentChange(index, e.target.value)}\n * />\n * ))}\n * {isInvalid && <span>{effectiveErrorMessage}</span>}\n * </div>\n * );\n * }\n * ```\n *\n * @param props - {@link CoordinateFieldProps}\n * @param customAriaLabel - Custom aria-label for the field.\n * @param customAriaDescribedby - Custom aria-describedby IDs.\n * @param customAriaDetails - Custom aria-details ID.\n * @returns {@link UseCoordinateFieldResult} Combined state, focus, copy, paste utilities and accessibility props.\n */\nexport function useCoordinateField(\n props: CoordinateFieldProps,\n customAriaLabel?: string,\n customAriaDescribedby?: string,\n customAriaDetails?: string,\n): UseCoordinateFieldResult {\n const {\n description,\n errorMessage: errorMessageProp,\n format = 'dd' as CoordinateSystem,\n value,\n defaultValue,\n onChange,\n onError,\n isDisabled = false,\n isInvalid: isInvalidProp = false,\n isRequired = false,\n id: idProp,\n } = props;\n\n const fieldId = useId(idProp);\n const labelId = useId();\n const descriptionId = useId();\n const errorId = useId();\n\n const { registerTimeout } = useTimeoutCleanup();\n\n const state = useCoordinateFieldState({\n value,\n defaultValue,\n format,\n onChange,\n onError,\n registerTimeout,\n });\n\n const focus = useCoordinateFocus({\n editableSegmentConfigs: state.editableSegmentConfigs,\n });\n\n const handlePasteValueApplied = (pastedValue: CoordinateValue) => {\n state.applyPastedCoordinate(pastedValue);\n\n // Defer focus until after React commits state updates to the DOM.\n // applyPastedCoordinate triggers setSegmentValues which updates the input\n // elements, and we need those updates to complete before focusing.\n registerTimeout(\n setTimeout(() => {\n focus.focusFirstSegment();\n }, FOCUS_DELAY_MS),\n );\n };\n\n const paste = useCoordinatePaste({\n onValueApplied: handlePasteValueApplied,\n onError,\n });\n\n const copy = useCoordinateCopy({\n currentValue: state.currentValue,\n validationErrors: state.validationErrors,\n isDisabled,\n registerTimeout,\n });\n\n const effectiveErrorMessage = useMemo(\n () => errorMessageProp || state.effectiveErrorMessage,\n [errorMessageProp, state.effectiveErrorMessage],\n );\n\n const isInvalid = isInvalidProp || effectiveErrorMessage !== null;\n\n const describedByIds = [\n description && descriptionId,\n effectiveErrorMessage && errorId,\n customAriaDescribedby,\n ].filter(Boolean);\n const describedBy =\n describedByIds.length > 0 ? describedByIds.join(' ') : undefined;\n\n const labelProps = {\n id: labelId,\n htmlFor: fieldId,\n };\n\n // Only use aria-labelledby when we have a visible label (not using aria-label)\n // When aria-label is provided (e.g., in small size), it takes precedence\n const ariaLabelledBy = customAriaLabel ? undefined : labelId;\n\n const fieldProps = {\n id: fieldId,\n role: 'group' as const,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': describedBy,\n 'aria-label': customAriaLabel || undefined,\n 'aria-details': customAriaDetails || undefined,\n 'aria-invalid': isInvalid || undefined,\n 'aria-required': isRequired || undefined,\n 'aria-disabled': isDisabled || undefined,\n };\n\n const descriptionProps = {\n id: descriptionId,\n };\n\n const errorProps = {\n id: errorId,\n };\n\n const validation: ValidationResult = useMemo(\n () => ({\n isInvalid,\n validationErrors: effectiveErrorMessage ? [effectiveErrorMessage] : [],\n validationDetails: {} as ValidityState,\n }),\n [isInvalid, effectiveErrorMessage],\n );\n\n return {\n state,\n focus,\n paste,\n copy,\n registerTimeout,\n fieldProps,\n labelProps,\n descriptionProps,\n errorProps,\n validation,\n ids: {\n fieldId,\n labelId,\n descriptionId,\n errorId,\n },\n effectiveErrorMessage,\n isInvalid,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA0BA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqGvB,SAAgB,mBACd,OACA,iBACA,uBACA,mBAC0B;CAC1B,MAAM,EACJ,aACA,cAAc,kBACd,SAAS,MACT,OACA,cACA,UACA,SACA,aAAa,OACb,WAAW,gBAAgB,OAC3B,aAAa,OACb,IAAI,WACF;CAEJ,MAAM,UAAU,MAAM,OAAO;CAC7B,MAAM,UAAU,OAAO;CACvB,MAAM,gBAAgB,OAAO;CAC7B,MAAM,UAAU,OAAO;CAEvB,MAAM,EAAE,oBAAoB,mBAAmB;CAE/C,MAAM,QAAQ,wBAAwB;EACpC;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CAEF,MAAM,QAAQ,mBAAmB,EAC/B,wBAAwB,MAAM,wBAC/B,CAAC;CAEF,MAAM,2BAA2B,gBAAiC;AAChE,QAAM,sBAAsB,YAAY;AAKxC,kBACE,iBAAiB;AACf,SAAM,mBAAmB;KACxB,eAAe,CACnB;;CAGH,MAAM,QAAQ,mBAAmB;EAC/B,gBAAgB;EAChB;EACD,CAAC;CAEF,MAAM,OAAO,kBAAkB;EAC7B,cAAc,MAAM;EACpB,kBAAkB,MAAM;EACxB;EACA;EACD,CAAC;CAEF,MAAM,wBAAwB,cACtB,oBAAoB,MAAM,uBAChC,CAAC,kBAAkB,MAAM,sBAAsB,CAChD;CAED,MAAM,YAAY,iBAAiB,0BAA0B;CAE7D,MAAM,iBAAiB;EACrB,eAAe;EACf,yBAAyB;EACzB;EACD,CAAC,OAAO,QAAQ;CACjB,MAAM,cACJ,eAAe,SAAS,IAAI,eAAe,KAAK,IAAI,GAAG;CAEzD,MAAM,aAAa;EACjB,IAAI;EACJ,SAAS;EACV;CAID,MAAM,iBAAiB,kBAAkB,SAAY;AA+BrD,QAAO;EACL;EACA;EACA;EACA;EACA;EACA,YAnCiB;GACjB,IAAI;GACJ,MAAM;GACN,mBAAmB;GACnB,oBAAoB;GACpB,cAAc,mBAAmB;GACjC,gBAAgB,qBAAqB;GACrC,gBAAgB,aAAa;GAC7B,iBAAiB,cAAc;GAC/B,iBAAiB,cAAc;GAChC;EA0BC;EACA,kBAzBuB,EACvB,IAAI,eACL;EAwBC,YAtBiB,EACjB,IAAI,SACL;EAqBC,YAnBmC,eAC5B;GACL;GACA,kBAAkB,wBAAwB,CAAC,sBAAsB,GAAG,EAAE;GACtE,mBAAmB,EAAE;GACtB,GACD,CAAC,WAAW,sBAAsB,CACnC;EAaC,KAAK;GACH;GACA;GACA;GACA;GACD;EACD;EACA;EACD"}
@@ -14,20 +14,71 @@ import { SegmentConfig } from "../../components/coordinate-field/types.js";
14
14
  import { KeyboardEvent } from "react";
15
15
 
16
16
  //#region src/hooks/coordinate-field/use-coordinate-focus.d.ts
17
+ /** Options for the useCoordinateFocus hook */
17
18
  interface UseCoordinateFocusOptions {
19
+ /** Array of editable segment configurations */
18
20
  editableSegmentConfigs: SegmentConfig[];
19
21
  }
22
+ /** Return value from the useCoordinateFocus hook */
20
23
  interface UseCoordinateFocusResult {
24
+ /** Array of refs for each input segment */
21
25
  segmentRefs: React.RefObject<HTMLInputElement>[];
26
+ /** Index of the currently focused segment (-1 if none) */
22
27
  focusedSegmentIndex: number;
28
+ /** Focus a specific segment by index */
23
29
  focusSegment: (index: number) => void;
30
+ /** Focus the next segment after the current index */
24
31
  focusNextSegment: (currentIndex: number) => void;
32
+ /** Focus the previous segment before the current index */
25
33
  focusPreviousSegment: (currentIndex: number) => void;
34
+ /** Focus the first segment */
26
35
  focusFirstSegment: () => void;
36
+ /** Focus the last segment */
27
37
  focusLastSegment: () => void;
38
+ /** Handle keyboard navigation (Home/End keys) */
28
39
  handleSegmentKeyDown: (index: number, e: KeyboardEvent<HTMLInputElement>) => void;
40
+ /** Update the focused segment index state */
29
41
  setFocusedSegmentIndex: (index: number) => void;
30
42
  }
43
+ /**
44
+ * Manages focus navigation between coordinate input segments
45
+ *
46
+ * @example
47
+ * ```tsx
48
+ * function CoordinateSegments({ configs }: { configs: SegmentConfig[] }) {
49
+ * const {
50
+ * segmentRefs,
51
+ * focusedSegmentIndex,
52
+ * focusNextSegment,
53
+ * focusPreviousSegment,
54
+ * handleSegmentKeyDown,
55
+ * setFocusedSegmentIndex,
56
+ * } = useCoordinateFocus({ editableSegmentConfigs: configs });
57
+ *
58
+ * return (
59
+ * <div>
60
+ * {configs.map((config, i) => (
61
+ * <input
62
+ * key={i}
63
+ * ref={segmentRefs[i]}
64
+ * onFocus={() => setFocusedSegmentIndex(i)}
65
+ * onKeyDown={(e) => {
66
+ * handleSegmentKeyDown(i, e);
67
+ * if (e.key === 'ArrowRight') focusNextSegment(i);
68
+ * if (e.key === 'ArrowLeft') focusPreviousSegment(i);
69
+ * }}
70
+ * aria-current={focusedSegmentIndex === i || undefined}
71
+ * />
72
+ * ))}
73
+ * </div>
74
+ * );
75
+ * }
76
+ * ```
77
+ *
78
+ * @param options - {@link UseCoordinateFocusOptions}
79
+ * @param options.editableSegmentConfigs - Array of editable segment configurations.
80
+ * @returns {@link UseCoordinateFocusResult} Focus management utilities and state.
81
+ */
31
82
  declare function useCoordinateFocus({
32
83
  editableSegmentConfigs
33
84
  }: UseCoordinateFocusOptions): UseCoordinateFocusResult;
@@ -14,6 +14,45 @@
14
14
  import { createRef, useEffect, useRef, useState } from "react";
15
15
 
16
16
  //#region src/hooks/coordinate-field/use-coordinate-focus.ts
17
+ /**
18
+ * Manages focus navigation between coordinate input segments
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * function CoordinateSegments({ configs }: { configs: SegmentConfig[] }) {
23
+ * const {
24
+ * segmentRefs,
25
+ * focusedSegmentIndex,
26
+ * focusNextSegment,
27
+ * focusPreviousSegment,
28
+ * handleSegmentKeyDown,
29
+ * setFocusedSegmentIndex,
30
+ * } = useCoordinateFocus({ editableSegmentConfigs: configs });
31
+ *
32
+ * return (
33
+ * <div>
34
+ * {configs.map((config, i) => (
35
+ * <input
36
+ * key={i}
37
+ * ref={segmentRefs[i]}
38
+ * onFocus={() => setFocusedSegmentIndex(i)}
39
+ * onKeyDown={(e) => {
40
+ * handleSegmentKeyDown(i, e);
41
+ * if (e.key === 'ArrowRight') focusNextSegment(i);
42
+ * if (e.key === 'ArrowLeft') focusPreviousSegment(i);
43
+ * }}
44
+ * aria-current={focusedSegmentIndex === i || undefined}
45
+ * />
46
+ * ))}
47
+ * </div>
48
+ * );
49
+ * }
50
+ * ```
51
+ *
52
+ * @param options - {@link UseCoordinateFocusOptions}
53
+ * @param options.editableSegmentConfigs - Array of editable segment configurations.
54
+ * @returns {@link UseCoordinateFocusResult} Focus management utilities and state.
55
+ */
17
56
  function useCoordinateFocus({ editableSegmentConfigs }) {
18
57
  const segmentRefsInternal = useRef([]);
19
58
  const [focusedSegmentIndex, setFocusedSegmentIndex] = useState(-1);
@@ -1 +1 @@
1
- {"version":3,"file":"use-coordinate-focus.js","names":[],"sources":["../../../src/hooks/coordinate-field/use-coordinate-focus.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n createRef,\n type KeyboardEvent,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type { SegmentConfig } from '../../components/coordinate-field/types';\n\nexport interface UseCoordinateFocusOptions {\n editableSegmentConfigs: SegmentConfig[];\n}\n\nexport interface UseCoordinateFocusResult {\n segmentRefs: React.RefObject<HTMLInputElement>[];\n focusedSegmentIndex: number;\n focusSegment: (index: number) => void;\n focusNextSegment: (currentIndex: number) => void;\n focusPreviousSegment: (currentIndex: number) => void;\n focusFirstSegment: () => void;\n focusLastSegment: () => void;\n handleSegmentKeyDown: (\n index: number,\n e: KeyboardEvent<HTMLInputElement>,\n ) => void;\n setFocusedSegmentIndex: (index: number) => void;\n}\n\nexport function useCoordinateFocus({\n editableSegmentConfigs,\n}: UseCoordinateFocusOptions): UseCoordinateFocusResult {\n const segmentRefsInternal = useRef<React.RefObject<HTMLInputElement>[]>([]);\n const [focusedSegmentIndex, setFocusedSegmentIndex] = useState<number>(-1);\n\n useEffect(() => {\n segmentRefsInternal.current = editableSegmentConfigs.map((_, i) => {\n const existingRef = segmentRefsInternal.current[i];\n if (existingRef) {\n return existingRef;\n }\n return createRef<HTMLInputElement>() as React.RefObject<HTMLInputElement>;\n });\n }, [editableSegmentConfigs]);\n\n const focusSegment = (index: number) => {\n if (index >= 0 && index < segmentRefsInternal.current.length) {\n segmentRefsInternal.current[index]?.current?.focus();\n }\n };\n\n const focusNextSegment = (currentIndex: number) => {\n focusSegment(currentIndex + 1);\n };\n\n const focusPreviousSegment = (currentIndex: number) => {\n focusSegment(currentIndex - 1);\n };\n\n const focusFirstSegment = () => {\n focusSegment(0);\n };\n\n const focusLastSegment = () => {\n focusSegment(segmentRefsInternal.current.length - 1);\n };\n\n const handleSegmentKeyDown = (\n _index: number,\n e: KeyboardEvent<HTMLInputElement>,\n ) => {\n if (e.key === 'Home') {\n e.preventDefault();\n focusFirstSegment();\n } else if (e.key === 'End') {\n e.preventDefault();\n focusLastSegment();\n }\n };\n\n return {\n segmentRefs: segmentRefsInternal.current,\n focusedSegmentIndex,\n focusSegment,\n focusNextSegment,\n focusPreviousSegment,\n focusFirstSegment,\n focusLastSegment,\n handleSegmentKeyDown,\n setFocusedSegmentIndex,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAwCA,SAAgB,mBAAmB,EACjC,0BACsD;CACtD,MAAM,sBAAsB,OAA4C,EAAE,CAAC;CAC3E,MAAM,CAAC,qBAAqB,0BAA0B,SAAiB,GAAG;AAE1E,iBAAgB;AACd,sBAAoB,UAAU,uBAAuB,KAAK,GAAG,MAAM;GACjE,MAAM,cAAc,oBAAoB,QAAQ;AAChD,OAAI,YACF,QAAO;AAET,UAAO,WAA6B;IACpC;IACD,CAAC,uBAAuB,CAAC;CAE5B,MAAM,gBAAgB,UAAkB;AACtC,MAAI,SAAS,KAAK,QAAQ,oBAAoB,QAAQ,OACpD,qBAAoB,QAAQ,QAAQ,SAAS,OAAO;;CAIxD,MAAM,oBAAoB,iBAAyB;AACjD,eAAa,eAAe,EAAE;;CAGhC,MAAM,wBAAwB,iBAAyB;AACrD,eAAa,eAAe,EAAE;;CAGhC,MAAM,0BAA0B;AAC9B,eAAa,EAAE;;CAGjB,MAAM,yBAAyB;AAC7B,eAAa,oBAAoB,QAAQ,SAAS,EAAE;;CAGtD,MAAM,wBACJ,QACA,MACG;AACH,MAAI,EAAE,QAAQ,QAAQ;AACpB,KAAE,gBAAgB;AAClB,sBAAmB;aACV,EAAE,QAAQ,OAAO;AAC1B,KAAE,gBAAgB;AAClB,qBAAkB;;;AAItB,QAAO;EACL,aAAa,oBAAoB;EACjC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
1
+ {"version":3,"file":"use-coordinate-focus.js","names":[],"sources":["../../../src/hooks/coordinate-field/use-coordinate-focus.ts"],"sourcesContent":["/*\n * Copyright 2025 Hypergiant Galactic Systems Inc. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n createRef,\n type KeyboardEvent,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport type { SegmentConfig } from '../../components/coordinate-field/types';\n\n/** Options for the useCoordinateFocus hook */\nexport interface UseCoordinateFocusOptions {\n /** Array of editable segment configurations */\n editableSegmentConfigs: SegmentConfig[];\n}\n\n/** Return value from the useCoordinateFocus hook */\nexport interface UseCoordinateFocusResult {\n /** Array of refs for each input segment */\n segmentRefs: React.RefObject<HTMLInputElement>[];\n /** Index of the currently focused segment (-1 if none) */\n focusedSegmentIndex: number;\n /** Focus a specific segment by index */\n focusSegment: (index: number) => void;\n /** Focus the next segment after the current index */\n focusNextSegment: (currentIndex: number) => void;\n /** Focus the previous segment before the current index */\n focusPreviousSegment: (currentIndex: number) => void;\n /** Focus the first segment */\n focusFirstSegment: () => void;\n /** Focus the last segment */\n focusLastSegment: () => void;\n /** Handle keyboard navigation (Home/End keys) */\n handleSegmentKeyDown: (\n index: number,\n e: KeyboardEvent<HTMLInputElement>,\n ) => void;\n /** Update the focused segment index state */\n setFocusedSegmentIndex: (index: number) => void;\n}\n\n/**\n * Manages focus navigation between coordinate input segments\n *\n * @example\n * ```tsx\n * function CoordinateSegments({ configs }: { configs: SegmentConfig[] }) {\n * const {\n * segmentRefs,\n * focusedSegmentIndex,\n * focusNextSegment,\n * focusPreviousSegment,\n * handleSegmentKeyDown,\n * setFocusedSegmentIndex,\n * } = useCoordinateFocus({ editableSegmentConfigs: configs });\n *\n * return (\n * <div>\n * {configs.map((config, i) => (\n * <input\n * key={i}\n * ref={segmentRefs[i]}\n * onFocus={() => setFocusedSegmentIndex(i)}\n * onKeyDown={(e) => {\n * handleSegmentKeyDown(i, e);\n * if (e.key === 'ArrowRight') focusNextSegment(i);\n * if (e.key === 'ArrowLeft') focusPreviousSegment(i);\n * }}\n * aria-current={focusedSegmentIndex === i || undefined}\n * />\n * ))}\n * </div>\n * );\n * }\n * ```\n *\n * @param options - {@link UseCoordinateFocusOptions}\n * @param options.editableSegmentConfigs - Array of editable segment configurations.\n * @returns {@link UseCoordinateFocusResult} Focus management utilities and state.\n */\nexport function useCoordinateFocus({\n editableSegmentConfigs,\n}: UseCoordinateFocusOptions): UseCoordinateFocusResult {\n const segmentRefsInternal = useRef<React.RefObject<HTMLInputElement>[]>([]);\n const [focusedSegmentIndex, setFocusedSegmentIndex] = useState<number>(-1);\n\n useEffect(() => {\n segmentRefsInternal.current = editableSegmentConfigs.map((_, i) => {\n const existingRef = segmentRefsInternal.current[i];\n if (existingRef) {\n return existingRef;\n }\n return createRef<HTMLInputElement>() as React.RefObject<HTMLInputElement>;\n });\n }, [editableSegmentConfigs]);\n\n const focusSegment = (index: number) => {\n if (index >= 0 && index < segmentRefsInternal.current.length) {\n segmentRefsInternal.current[index]?.current?.focus();\n }\n };\n\n const focusNextSegment = (currentIndex: number) => {\n focusSegment(currentIndex + 1);\n };\n\n const focusPreviousSegment = (currentIndex: number) => {\n focusSegment(currentIndex - 1);\n };\n\n const focusFirstSegment = () => {\n focusSegment(0);\n };\n\n const focusLastSegment = () => {\n focusSegment(segmentRefsInternal.current.length - 1);\n };\n\n const handleSegmentKeyDown = (\n _index: number,\n e: KeyboardEvent<HTMLInputElement>,\n ) => {\n if (e.key === 'Home') {\n e.preventDefault();\n focusFirstSegment();\n } else if (e.key === 'End') {\n e.preventDefault();\n focusLastSegment();\n }\n };\n\n return {\n segmentRefs: segmentRefsInternal.current,\n focusedSegmentIndex,\n focusSegment,\n focusNextSegment,\n focusPreviousSegment,\n focusFirstSegment,\n focusLastSegment,\n handleSegmentKeyDown,\n setFocusedSegmentIndex,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,SAAgB,mBAAmB,EACjC,0BACsD;CACtD,MAAM,sBAAsB,OAA4C,EAAE,CAAC;CAC3E,MAAM,CAAC,qBAAqB,0BAA0B,SAAiB,GAAG;AAE1E,iBAAgB;AACd,sBAAoB,UAAU,uBAAuB,KAAK,GAAG,MAAM;GACjE,MAAM,cAAc,oBAAoB,QAAQ;AAChD,OAAI,YACF,QAAO;AAET,UAAO,WAA6B;IACpC;IACD,CAAC,uBAAuB,CAAC;CAE5B,MAAM,gBAAgB,UAAkB;AACtC,MAAI,SAAS,KAAK,QAAQ,oBAAoB,QAAQ,OACpD,qBAAoB,QAAQ,QAAQ,SAAS,OAAO;;CAIxD,MAAM,oBAAoB,iBAAyB;AACjD,eAAa,eAAe,EAAE;;CAGhC,MAAM,wBAAwB,iBAAyB;AACrD,eAAa,eAAe,EAAE;;CAGhC,MAAM,0BAA0B;AAC9B,eAAa,EAAE;;CAGjB,MAAM,yBAAyB;AAC7B,eAAa,oBAAoB,QAAQ,SAAS,EAAE;;CAGtD,MAAM,wBACJ,QACA,MACG;AACH,MAAI,EAAE,QAAQ,QAAQ;AACpB,KAAE,gBAAgB;AAClB,sBAAmB;aACV,EAAE,QAAQ,OAAO;AAC1B,KAAE,gBAAgB;AAClB,qBAAkB;;;AAItB,QAAO;EACL,aAAa,oBAAoB;EACjC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
@@ -13,20 +13,83 @@
13
13
  import { CoordinateSystem, CoordinateValue, ParsedCoordinateMatch } from "../../components/coordinate-field/types.js";
14
14
 
15
15
  //#region src/hooks/coordinate-field/use-coordinate-paste.d.ts
16
+ /** Options for the useCoordinatePaste hook */
16
17
  interface UseCoordinatePasteOptions {
18
+ /** Callback when a coordinate value is successfully parsed and applied */
17
19
  onValueApplied: (value: CoordinateValue) => void;
20
+ /** Optional error callback for invalid paste attempts */
18
21
  onError?: (message: string, context?: Record<string, unknown>) => void;
19
22
  }
23
+ /** Return value from the useCoordinatePaste hook */
20
24
  interface UseCoordinatePasteResult {
25
+ /** Array of parsed coordinate matches for disambiguation */
21
26
  disambiguationMatches: ParsedCoordinateMatch[];
27
+ /** Whether the disambiguation modal is visible */
22
28
  showDisambiguationModal: boolean;
29
+ /** Currently selected format in disambiguation modal */
23
30
  selectedDisambiguationFormat: CoordinateSystem | null;
31
+ /** Paste event handler for coordinate input */
24
32
  handleInputPaste: (e: React.ClipboardEvent<HTMLDivElement>) => void;
33
+ /** Confirm selection in disambiguation modal */
25
34
  handleDisambiguationSelect: () => void;
35
+ /** Control disambiguation modal visibility */
26
36
  setShowDisambiguationModal: (show: boolean) => void;
37
+ /** Set the selected format in disambiguation modal */
27
38
  setSelectedDisambiguationFormat: (format: CoordinateSystem | null) => void;
39
+ /** Reset disambiguation modal state */
28
40
  cleanupDisambiguationModal: () => void;
29
41
  }
42
+ /**
43
+ * Handles paste events with coordinate parsing and disambiguation when multiple formats match
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * function CoordinateFieldWithPaste() {
48
+ * const [value, setValue] = useState<CoordinateValue | null>(null);
49
+ *
50
+ * const {
51
+ * disambiguationMatches,
52
+ * showDisambiguationModal,
53
+ * selectedDisambiguationFormat,
54
+ * handleInputPaste,
55
+ * handleDisambiguationSelect,
56
+ * setShowDisambiguationModal,
57
+ * setSelectedDisambiguationFormat,
58
+ * } = useCoordinatePaste({
59
+ * onValueApplied: setValue,
60
+ * onError: (msg) => console.error(msg),
61
+ * });
62
+ *
63
+ * return (
64
+ * <>
65
+ * <div onPaste={handleInputPaste}>
66
+ * // ...Coordinate input segments
67
+ * </div>
68
+ * {showDisambiguationModal && (
69
+ * <Dialog onClose={() => setShowDisambiguationModal(false)}>
70
+ * {disambiguationMatches.map((match) => (
71
+ * <Radio
72
+ * key={match.format}
73
+ * value={match.format}
74
+ * isSelected={selectedDisambiguationFormat === match.format}
75
+ * onChange={() => setSelectedDisambiguationFormat(match.format)}
76
+ * >
77
+ * {match.format}: {match.matched}
78
+ * </Radio>
79
+ * ))}
80
+ * <Button onPress={handleDisambiguationSelect}>Confirm</Button>
81
+ * </Dialog>
82
+ * )}
83
+ * </>
84
+ * );
85
+ * }
86
+ * ```
87
+ *
88
+ * @param options - {@link UseCoordinatePasteOptions}
89
+ * @param options.onValueApplied - Callback when a coordinate value is successfully parsed and applied.
90
+ * @param options.onError - Optional error callback for invalid paste attempts.
91
+ * @returns {@link UseCoordinatePasteResult} Paste handling utilities and disambiguation state.
92
+ */
30
93
  declare function useCoordinatePaste({
31
94
  onValueApplied,
32
95
  onError
@@ -15,6 +15,57 @@ import { deduplicateMatchesByLocation, isCompleteCoordinate, parseCoordinatePast
15
15
  import { useState } from "react";
16
16
 
17
17
  //#region src/hooks/coordinate-field/use-coordinate-paste.ts
18
+ /**
19
+ * Handles paste events with coordinate parsing and disambiguation when multiple formats match
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * function CoordinateFieldWithPaste() {
24
+ * const [value, setValue] = useState<CoordinateValue | null>(null);
25
+ *
26
+ * const {
27
+ * disambiguationMatches,
28
+ * showDisambiguationModal,
29
+ * selectedDisambiguationFormat,
30
+ * handleInputPaste,
31
+ * handleDisambiguationSelect,
32
+ * setShowDisambiguationModal,
33
+ * setSelectedDisambiguationFormat,
34
+ * } = useCoordinatePaste({
35
+ * onValueApplied: setValue,
36
+ * onError: (msg) => console.error(msg),
37
+ * });
38
+ *
39
+ * return (
40
+ * <>
41
+ * <div onPaste={handleInputPaste}>
42
+ * // ...Coordinate input segments
43
+ * </div>
44
+ * {showDisambiguationModal && (
45
+ * <Dialog onClose={() => setShowDisambiguationModal(false)}>
46
+ * {disambiguationMatches.map((match) => (
47
+ * <Radio
48
+ * key={match.format}
49
+ * value={match.format}
50
+ * isSelected={selectedDisambiguationFormat === match.format}
51
+ * onChange={() => setSelectedDisambiguationFormat(match.format)}
52
+ * >
53
+ * {match.format}: {match.matched}
54
+ * </Radio>
55
+ * ))}
56
+ * <Button onPress={handleDisambiguationSelect}>Confirm</Button>
57
+ * </Dialog>
58
+ * )}
59
+ * </>
60
+ * );
61
+ * }
62
+ * ```
63
+ *
64
+ * @param options - {@link UseCoordinatePasteOptions}
65
+ * @param options.onValueApplied - Callback when a coordinate value is successfully parsed and applied.
66
+ * @param options.onError - Optional error callback for invalid paste attempts.
67
+ * @returns {@link UseCoordinatePasteResult} Paste handling utilities and disambiguation state.
68
+ */
18
69
  function useCoordinatePaste({ onValueApplied, onError }) {
19
70
  const [disambiguationMatches, setDisambiguationMatches] = useState([]);
20
71
  const [showDisambiguationModal, setShowDisambiguationModal] = useState(false);
@@ -1 +1 @@
1
- {"version":3,"file":"use-coordinate-paste.js","names":[],"sources":["../../../src/hooks/coordinate-field/use-coordinate-paste.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 { useState } from 'react';\nimport {\n deduplicateMatchesByLocation,\n isCompleteCoordinate,\n parseCoordinatePaste,\n} from '../../components/coordinate-field/coordinate-utils';\nimport type {\n CoordinateSystem,\n CoordinateValue,\n ParsedCoordinateMatch,\n} from '../../components/coordinate-field/types';\n\nexport interface UseCoordinatePasteOptions {\n onValueApplied: (value: CoordinateValue) => void;\n onError?: (message: string, context?: Record<string, unknown>) => void;\n}\n\nexport interface UseCoordinatePasteResult {\n disambiguationMatches: ParsedCoordinateMatch[];\n showDisambiguationModal: boolean;\n selectedDisambiguationFormat: CoordinateSystem | null;\n handleInputPaste: (e: React.ClipboardEvent<HTMLDivElement>) => void;\n handleDisambiguationSelect: () => void;\n setShowDisambiguationModal: (show: boolean) => void;\n setSelectedDisambiguationFormat: (format: CoordinateSystem | null) => void;\n cleanupDisambiguationModal: () => void;\n}\n\nexport function useCoordinatePaste({\n onValueApplied,\n onError,\n}: UseCoordinatePasteOptions): UseCoordinatePasteResult {\n const [disambiguationMatches, setDisambiguationMatches] = useState<\n ParsedCoordinateMatch[]\n >([]);\n const [showDisambiguationModal, setShowDisambiguationModal] = useState(false);\n const [selectedDisambiguationFormat, setSelectedDisambiguationFormat] =\n useState<CoordinateSystem | null>(null);\n\n /**\n * Handles paste failure when no coordinate formats match\n * Calls onError with \"Invalid coordinate format\" message\n */\n const handlePasteNoMatches = (pastedText: string) => {\n const errorMsg = 'Invalid coordinate format';\n onError?.(errorMsg, { pastedText });\n };\n\n const handlePasteSingleMatch = (match: ParsedCoordinateMatch | undefined) => {\n if (match) {\n onValueApplied(match.value);\n }\n };\n\n const handlePasteMultipleMatches = (matches: ParsedCoordinateMatch[]) => {\n setDisambiguationMatches(matches);\n const firstMatch = matches[0];\n if (firstMatch) {\n setSelectedDisambiguationFormat(firstMatch.format);\n }\n setShowDisambiguationModal(true);\n };\n\n const handleCoordinatePaste = (pastedText: string) => {\n const allMatches = parseCoordinatePaste(pastedText);\n\n if (allMatches.length === 0) {\n handlePasteNoMatches(pastedText);\n return;\n }\n\n // Deduplicate matches by location - only show modal for different locations\n const matches = deduplicateMatchesByLocation(allMatches);\n\n if (matches.length === 1) {\n handlePasteSingleMatch(matches[0]);\n } else {\n handlePasteMultipleMatches(matches);\n }\n };\n\n const handleInputPaste = (e: React.ClipboardEvent<HTMLDivElement>) => {\n const pastedText = e.clipboardData?.getData('text/plain');\n if (pastedText && isCompleteCoordinate(pastedText)) {\n e.preventDefault();\n handleCoordinatePaste(pastedText);\n }\n };\n\n const cleanupDisambiguationModal = () => {\n setShowDisambiguationModal(false);\n setDisambiguationMatches([]);\n setSelectedDisambiguationFormat(null);\n };\n\n const handleDisambiguationSelect = () => {\n if (selectedDisambiguationFormat) {\n const match = disambiguationMatches.find(\n (m) => m.format === selectedDisambiguationFormat,\n );\n if (match) {\n onValueApplied(match.value);\n }\n }\n cleanupDisambiguationModal();\n };\n\n return {\n disambiguationMatches,\n showDisambiguationModal,\n selectedDisambiguationFormat,\n handleInputPaste,\n handleDisambiguationSelect,\n setShowDisambiguationModal,\n setSelectedDisambiguationFormat,\n cleanupDisambiguationModal,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAwCA,SAAgB,mBAAmB,EACjC,gBACA,WACsD;CACtD,MAAM,CAAC,uBAAuB,4BAA4B,SAExD,EAAE,CAAC;CACL,MAAM,CAAC,yBAAyB,8BAA8B,SAAS,MAAM;CAC7E,MAAM,CAAC,8BAA8B,mCACnC,SAAkC,KAAK;;;;;CAMzC,MAAM,wBAAwB,eAAuB;AAEnD,YADiB,6BACG,EAAE,YAAY,CAAC;;CAGrC,MAAM,0BAA0B,UAA6C;AAC3E,MAAI,MACF,gBAAe,MAAM,MAAM;;CAI/B,MAAM,8BAA8B,YAAqC;AACvE,2BAAyB,QAAQ;EACjC,MAAM,aAAa,QAAQ;AAC3B,MAAI,WACF,iCAAgC,WAAW,OAAO;AAEpD,6BAA2B,KAAK;;CAGlC,MAAM,yBAAyB,eAAuB;EACpD,MAAM,aAAa,qBAAqB,WAAW;AAEnD,MAAI,WAAW,WAAW,GAAG;AAC3B,wBAAqB,WAAW;AAChC;;EAIF,MAAM,UAAU,6BAA6B,WAAW;AAExD,MAAI,QAAQ,WAAW,EACrB,wBAAuB,QAAQ,GAAG;MAElC,4BAA2B,QAAQ;;CAIvC,MAAM,oBAAoB,MAA4C;EACpE,MAAM,aAAa,EAAE,eAAe,QAAQ,aAAa;AACzD,MAAI,cAAc,qBAAqB,WAAW,EAAE;AAClD,KAAE,gBAAgB;AAClB,yBAAsB,WAAW;;;CAIrC,MAAM,mCAAmC;AACvC,6BAA2B,MAAM;AACjC,2BAAyB,EAAE,CAAC;AAC5B,kCAAgC,KAAK;;CAGvC,MAAM,mCAAmC;AACvC,MAAI,8BAA8B;GAChC,MAAM,QAAQ,sBAAsB,MACjC,MAAM,EAAE,WAAW,6BACrB;AACD,OAAI,MACF,gBAAe,MAAM,MAAM;;AAG/B,8BAA4B;;AAG9B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}
1
+ {"version":3,"file":"use-coordinate-paste.js","names":[],"sources":["../../../src/hooks/coordinate-field/use-coordinate-paste.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 { useState } from 'react';\nimport {\n deduplicateMatchesByLocation,\n isCompleteCoordinate,\n parseCoordinatePaste,\n} from '../../components/coordinate-field/coordinate-utils';\nimport type {\n CoordinateSystem,\n CoordinateValue,\n ParsedCoordinateMatch,\n} from '../../components/coordinate-field/types';\n\n/** Options for the useCoordinatePaste hook */\nexport interface UseCoordinatePasteOptions {\n /** Callback when a coordinate value is successfully parsed and applied */\n onValueApplied: (value: CoordinateValue) => void;\n /** Optional error callback for invalid paste attempts */\n onError?: (message: string, context?: Record<string, unknown>) => void;\n}\n\n/** Return value from the useCoordinatePaste hook */\nexport interface UseCoordinatePasteResult {\n /** Array of parsed coordinate matches for disambiguation */\n disambiguationMatches: ParsedCoordinateMatch[];\n /** Whether the disambiguation modal is visible */\n showDisambiguationModal: boolean;\n /** Currently selected format in disambiguation modal */\n selectedDisambiguationFormat: CoordinateSystem | null;\n /** Paste event handler for coordinate input */\n handleInputPaste: (e: React.ClipboardEvent<HTMLDivElement>) => void;\n /** Confirm selection in disambiguation modal */\n handleDisambiguationSelect: () => void;\n /** Control disambiguation modal visibility */\n setShowDisambiguationModal: (show: boolean) => void;\n /** Set the selected format in disambiguation modal */\n setSelectedDisambiguationFormat: (format: CoordinateSystem | null) => void;\n /** Reset disambiguation modal state */\n cleanupDisambiguationModal: () => void;\n}\n\n/**\n * Handles paste events with coordinate parsing and disambiguation when multiple formats match\n *\n * @example\n * ```tsx\n * function CoordinateFieldWithPaste() {\n * const [value, setValue] = useState<CoordinateValue | null>(null);\n *\n * const {\n * disambiguationMatches,\n * showDisambiguationModal,\n * selectedDisambiguationFormat,\n * handleInputPaste,\n * handleDisambiguationSelect,\n * setShowDisambiguationModal,\n * setSelectedDisambiguationFormat,\n * } = useCoordinatePaste({\n * onValueApplied: setValue,\n * onError: (msg) => console.error(msg),\n * });\n *\n * return (\n * <>\n * <div onPaste={handleInputPaste}>\n * // ...Coordinate input segments\n * </div>\n * {showDisambiguationModal && (\n * <Dialog onClose={() => setShowDisambiguationModal(false)}>\n * {disambiguationMatches.map((match) => (\n * <Radio\n * key={match.format}\n * value={match.format}\n * isSelected={selectedDisambiguationFormat === match.format}\n * onChange={() => setSelectedDisambiguationFormat(match.format)}\n * >\n * {match.format}: {match.matched}\n * </Radio>\n * ))}\n * <Button onPress={handleDisambiguationSelect}>Confirm</Button>\n * </Dialog>\n * )}\n * </>\n * );\n * }\n * ```\n *\n * @param options - {@link UseCoordinatePasteOptions}\n * @param options.onValueApplied - Callback when a coordinate value is successfully parsed and applied.\n * @param options.onError - Optional error callback for invalid paste attempts.\n * @returns {@link UseCoordinatePasteResult} Paste handling utilities and disambiguation state.\n */\nexport function useCoordinatePaste({\n onValueApplied,\n onError,\n}: UseCoordinatePasteOptions): UseCoordinatePasteResult {\n const [disambiguationMatches, setDisambiguationMatches] = useState<\n ParsedCoordinateMatch[]\n >([]);\n const [showDisambiguationModal, setShowDisambiguationModal] = useState(false);\n const [selectedDisambiguationFormat, setSelectedDisambiguationFormat] =\n useState<CoordinateSystem | null>(null);\n\n /**\n * Handles paste failure when no coordinate formats match\n * Calls onError with \"Invalid coordinate format\" message\n */\n const handlePasteNoMatches = (pastedText: string) => {\n const errorMsg = 'Invalid coordinate format';\n onError?.(errorMsg, { pastedText });\n };\n\n const handlePasteSingleMatch = (match: ParsedCoordinateMatch | undefined) => {\n if (match) {\n onValueApplied(match.value);\n }\n };\n\n const handlePasteMultipleMatches = (matches: ParsedCoordinateMatch[]) => {\n setDisambiguationMatches(matches);\n const firstMatch = matches[0];\n if (firstMatch) {\n setSelectedDisambiguationFormat(firstMatch.format);\n }\n setShowDisambiguationModal(true);\n };\n\n const handleCoordinatePaste = (pastedText: string) => {\n const allMatches = parseCoordinatePaste(pastedText);\n\n if (allMatches.length === 0) {\n handlePasteNoMatches(pastedText);\n return;\n }\n\n // Deduplicate matches by location - only show modal for different locations\n const matches = deduplicateMatchesByLocation(allMatches);\n\n if (matches.length === 1) {\n handlePasteSingleMatch(matches[0]);\n } else {\n handlePasteMultipleMatches(matches);\n }\n };\n\n const handleInputPaste = (e: React.ClipboardEvent<HTMLDivElement>) => {\n const pastedText = e.clipboardData?.getData('text/plain');\n if (pastedText && isCompleteCoordinate(pastedText)) {\n e.preventDefault();\n handleCoordinatePaste(pastedText);\n }\n };\n\n const cleanupDisambiguationModal = () => {\n setShowDisambiguationModal(false);\n setDisambiguationMatches([]);\n setSelectedDisambiguationFormat(null);\n };\n\n const handleDisambiguationSelect = () => {\n if (selectedDisambiguationFormat) {\n const match = disambiguationMatches.find(\n (m) => m.format === selectedDisambiguationFormat,\n );\n if (match) {\n onValueApplied(match.value);\n }\n }\n cleanupDisambiguationModal();\n };\n\n return {\n disambiguationMatches,\n showDisambiguationModal,\n selectedDisambiguationFormat,\n handleInputPaste,\n handleDisambiguationSelect,\n setShowDisambiguationModal,\n setSelectedDisambiguationFormat,\n cleanupDisambiguationModal,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuGA,SAAgB,mBAAmB,EACjC,gBACA,WACsD;CACtD,MAAM,CAAC,uBAAuB,4BAA4B,SAExD,EAAE,CAAC;CACL,MAAM,CAAC,yBAAyB,8BAA8B,SAAS,MAAM;CAC7E,MAAM,CAAC,8BAA8B,mCACnC,SAAkC,KAAK;;;;;CAMzC,MAAM,wBAAwB,eAAuB;AAEnD,YADiB,6BACG,EAAE,YAAY,CAAC;;CAGrC,MAAM,0BAA0B,UAA6C;AAC3E,MAAI,MACF,gBAAe,MAAM,MAAM;;CAI/B,MAAM,8BAA8B,YAAqC;AACvE,2BAAyB,QAAQ;EACjC,MAAM,aAAa,QAAQ;AAC3B,MAAI,WACF,iCAAgC,WAAW,OAAO;AAEpD,6BAA2B,KAAK;;CAGlC,MAAM,yBAAyB,eAAuB;EACpD,MAAM,aAAa,qBAAqB,WAAW;AAEnD,MAAI,WAAW,WAAW,GAAG;AAC3B,wBAAqB,WAAW;AAChC;;EAIF,MAAM,UAAU,6BAA6B,WAAW;AAExD,MAAI,QAAQ,WAAW,EACrB,wBAAuB,QAAQ,GAAG;MAElC,4BAA2B,QAAQ;;CAIvC,MAAM,oBAAoB,MAA4C;EACpE,MAAM,aAAa,EAAE,eAAe,QAAQ,aAAa;AACzD,MAAI,cAAc,qBAAqB,WAAW,EAAE;AAClD,KAAE,gBAAgB;AAClB,yBAAsB,WAAW;;;CAIrC,MAAM,mCAAmC;AACvC,6BAA2B,MAAM;AACjC,2BAAyB,EAAE,CAAC;AAC5B,kCAAgC,KAAK;;CAGvC,MAAM,mCAAmC;AACvC,MAAI,8BAA8B;GAChC,MAAM,QAAQ,sBAAsB,MACjC,MAAM,EAAE,WAAW,6BACrB;AACD,OAAI,MACF,gBAAe,MAAM,MAAM;;AAG/B,8BAA4B;;AAG9B,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}