@cdx-ui/components 0.3.5 → 0.3.7

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 (416) hide show
  1. package/README.md +1 -1
  2. package/coverage.svg +1 -1
  3. package/docs/components/bar-chart/content.md +703 -0
  4. package/docs/components/content.md +10 -1
  5. package/docs/components/country-flag/content.md +232 -0
  6. package/docs/components/data-grid/content.md +3 -1
  7. package/docs/components/icon/content.md +1 -1
  8. package/docs/components/input/content.md +1 -0
  9. package/docs/components/line-chart/content.md +567 -0
  10. package/docs/components/pie-chart/content.md +493 -0
  11. package/docs/components/progress-bar/content.md +164 -3
  12. package/docs/components/progress-segmented/content.md +1 -1
  13. package/docs/components/select/content.md +1 -0
  14. package/docs/components/stepper/content.md +599 -0
  15. package/docs/components/system-alert/content.md +533 -0
  16. package/docs/foundations/expressions/icons/content.md +2 -1
  17. package/docs/foundations/styles/tokens/all-tokens/content.md +2 -1
  18. package/docs/getting-started/developers/content.md +1 -1
  19. package/docs/llms.txt +12 -0
  20. package/docs/patterns/content.md +1 -0
  21. package/docs/patterns/dashboard/content.md +423 -19
  22. package/docs/patterns/insights/content.md +659 -0
  23. package/docs/resources/content.md +1 -0
  24. package/docs/resources/release-notes/0.3.5/content.md +7 -0
  25. package/docs/resources/release-notes/0.3.6/content.md +29 -0
  26. package/docs/resources/release-notes/content.md +2 -0
  27. package/docs/resources/skills/content.md +66 -0
  28. package/lib/commonjs/components/BarChart/geometry.js +1130 -0
  29. package/lib/commonjs/components/BarChart/geometry.js.map +1 -0
  30. package/lib/commonjs/components/BarChart/index.js +935 -0
  31. package/lib/commonjs/components/BarChart/index.js.map +1 -0
  32. package/lib/commonjs/components/BarChart/styles.js +26 -0
  33. package/lib/commonjs/components/BarChart/styles.js.map +1 -0
  34. package/lib/commonjs/components/Button/index.js +2 -2
  35. package/lib/commonjs/components/Button/index.js.map +1 -1
  36. package/lib/commonjs/components/CountryFlag/index.js +56 -0
  37. package/lib/commonjs/components/CountryFlag/index.js.map +1 -0
  38. package/lib/commonjs/components/Input/index.js.map +1 -1
  39. package/lib/commonjs/components/LineChart/geometry.js +698 -0
  40. package/lib/commonjs/components/LineChart/geometry.js.map +1 -0
  41. package/lib/commonjs/components/LineChart/index.js +744 -0
  42. package/lib/commonjs/components/LineChart/index.js.map +1 -0
  43. package/lib/commonjs/components/LineChart/styles.js +25 -0
  44. package/lib/commonjs/components/LineChart/styles.js.map +1 -0
  45. package/lib/commonjs/components/PieChart/geometry.js +216 -0
  46. package/lib/commonjs/components/PieChart/geometry.js.map +1 -0
  47. package/lib/commonjs/components/PieChart/index.js +476 -0
  48. package/lib/commonjs/components/PieChart/index.js.map +1 -0
  49. package/lib/commonjs/components/PieChart/styles.js +88 -0
  50. package/lib/commonjs/components/PieChart/styles.js.map +1 -0
  51. package/lib/commonjs/components/ProgressBar/index.js +44 -12
  52. package/lib/commonjs/components/ProgressBar/index.js.map +1 -1
  53. package/lib/commonjs/components/ProgressBar/styles.js +31 -2
  54. package/lib/commonjs/components/ProgressBar/styles.js.map +1 -1
  55. package/lib/commonjs/components/ProgressCircle/ProgressCircleRing.js +9 -31
  56. package/lib/commonjs/components/ProgressCircle/ProgressCircleRing.js.map +1 -1
  57. package/lib/commonjs/components/ProgressCircle/ProgressRing.js +52 -0
  58. package/lib/commonjs/components/ProgressCircle/ProgressRing.js.map +1 -0
  59. package/lib/commonjs/components/ScrollShadow/useScrollShadow.js +8 -7
  60. package/lib/commonjs/components/ScrollShadow/useScrollShadow.js.map +1 -1
  61. package/lib/commonjs/components/Select/index.js.map +1 -1
  62. package/lib/commonjs/components/Stepper/index.js +369 -0
  63. package/lib/commonjs/components/Stepper/index.js.map +1 -0
  64. package/lib/commonjs/components/Stepper/styles.js +211 -0
  65. package/lib/commonjs/components/Stepper/styles.js.map +1 -0
  66. package/lib/commonjs/components/Stepper/useStepperLabelFit.js +22 -0
  67. package/lib/commonjs/components/Stepper/useStepperLabelFit.js.map +1 -0
  68. package/lib/commonjs/components/Stepper/useStepperLabelFit.web.js +52 -0
  69. package/lib/commonjs/components/Stepper/useStepperLabelFit.web.js.map +1 -0
  70. package/lib/commonjs/components/Stepper/useStepperRingColors.js +31 -0
  71. package/lib/commonjs/components/Stepper/useStepperRingColors.js.map +1 -0
  72. package/lib/commonjs/components/SystemAlert/animation.js +218 -0
  73. package/lib/commonjs/components/SystemAlert/animation.js.map +1 -0
  74. package/lib/commonjs/components/SystemAlert/index.js +525 -0
  75. package/lib/commonjs/components/SystemAlert/index.js.map +1 -0
  76. package/lib/commonjs/components/SystemAlert/styles.js +178 -0
  77. package/lib/commonjs/components/SystemAlert/styles.js.map +1 -0
  78. package/lib/commonjs/components/SystemAlert/useSystemAlertStatusBarStyle.js +53 -0
  79. package/lib/commonjs/components/SystemAlert/useSystemAlertStatusBarStyle.js.map +1 -0
  80. package/lib/commonjs/components/Tabs/index.js +4 -0
  81. package/lib/commonjs/components/Tabs/index.js.map +1 -1
  82. package/lib/commonjs/components/Tabs/styles.js +1 -1
  83. package/lib/commonjs/components/Tabs/styles.js.map +1 -1
  84. package/lib/commonjs/components/chart/ChartInspector.js +610 -0
  85. package/lib/commonjs/components/chart/ChartInspector.js.map +1 -0
  86. package/lib/commonjs/components/chart/format.js +93 -0
  87. package/lib/commonjs/components/chart/format.js.map +1 -0
  88. package/lib/commonjs/components/chart/hiddenSvgProps.js +23 -0
  89. package/lib/commonjs/components/chart/hiddenSvgProps.js.map +1 -0
  90. package/lib/commonjs/components/chart/index.js +2 -0
  91. package/lib/commonjs/components/chart/index.js.map +1 -0
  92. package/lib/commonjs/components/chart/motion.js +97 -0
  93. package/lib/commonjs/components/chart/motion.js.map +1 -0
  94. package/lib/commonjs/components/chart/palette.js +178 -0
  95. package/lib/commonjs/components/chart/palette.js.map +1 -0
  96. package/lib/commonjs/components/chart/size.js +34 -0
  97. package/lib/commonjs/components/chart/size.js.map +1 -0
  98. package/lib/commonjs/components/chart/ticks.js +59 -0
  99. package/lib/commonjs/components/chart/ticks.js.map +1 -0
  100. package/lib/commonjs/components/chart/types.js +6 -0
  101. package/lib/commonjs/components/chart/types.js.map +1 -0
  102. package/lib/commonjs/components/chart/useChartHostWidth.js +27 -0
  103. package/lib/commonjs/components/chart/useChartHostWidth.js.map +1 -0
  104. package/lib/commonjs/components/index.js +72 -0
  105. package/lib/commonjs/components/index.js.map +1 -1
  106. package/lib/commonjs/figma/Accordion.figma.js +2 -2
  107. package/lib/commonjs/figma/Accordion.figma.js.map +1 -1
  108. package/lib/commonjs/figma/Alert.figma.js +7 -7
  109. package/lib/commonjs/figma/Alert.figma.js.map +1 -1
  110. package/lib/commonjs/figma/Badge.Indicator.figma.js +6 -5
  111. package/lib/commonjs/figma/Badge.Indicator.figma.js.map +1 -1
  112. package/lib/commonjs/figma/Badge.figma.js +22 -22
  113. package/lib/commonjs/figma/Badge.figma.js.map +1 -1
  114. package/lib/commonjs/figma/Button.figma.js +5 -2
  115. package/lib/commonjs/figma/Button.figma.js.map +1 -1
  116. package/lib/commonjs/figma/CLAUDE.md +1 -0
  117. package/lib/commonjs/figma/Card.Header.figma.js +8 -4
  118. package/lib/commonjs/figma/Card.Header.figma.js.map +1 -1
  119. package/lib/commonjs/figma/Card.figma.js +2 -1
  120. package/lib/commonjs/figma/Card.figma.js.map +1 -1
  121. package/lib/commonjs/figma/Chip.figma.js +2 -2
  122. package/lib/commonjs/figma/Chip.figma.js.map +1 -1
  123. package/lib/commonjs/figma/CurrencyInput.figma.js +1 -1
  124. package/lib/commonjs/figma/CurrencyInput.figma.js.map +1 -1
  125. package/lib/commonjs/figma/Dialog.figma.js +5 -2
  126. package/lib/commonjs/figma/Dialog.figma.js.map +1 -1
  127. package/lib/commonjs/figma/Divider.figma.js +1 -1
  128. package/lib/commonjs/figma/Divider.figma.js.map +1 -1
  129. package/lib/commonjs/figma/Drawer.figma.js +3 -3
  130. package/lib/commonjs/figma/Drawer.figma.js.map +1 -1
  131. package/lib/commonjs/figma/IconButton.figma.js +10 -4
  132. package/lib/commonjs/figma/IconButton.figma.js.map +1 -1
  133. package/lib/commonjs/figma/Input.figma.js +2 -1
  134. package/lib/commonjs/figma/Input.figma.js.map +1 -1
  135. package/lib/commonjs/figma/Insight.figma.js +3 -3
  136. package/lib/commonjs/figma/Insight.figma.js.map +1 -1
  137. package/lib/commonjs/figma/ProgressBar.figma.js +11 -2
  138. package/lib/commonjs/figma/ProgressBar.figma.js.map +1 -1
  139. package/lib/commonjs/figma/ProgressSegmented.figma.js +9 -1
  140. package/lib/commonjs/figma/ProgressSegmented.figma.js.map +1 -1
  141. package/lib/commonjs/figma/Select.figma.js +2 -1
  142. package/lib/commonjs/figma/Select.figma.js.map +1 -1
  143. package/lib/commonjs/figma/SystemAlert.Button.figma.js +28 -0
  144. package/lib/commonjs/figma/SystemAlert.Button.figma.js.map +1 -0
  145. package/lib/commonjs/figma/SystemAlert.Close.figma.js +22 -0
  146. package/lib/commonjs/figma/SystemAlert.Close.figma.js.map +1 -0
  147. package/lib/commonjs/figma/SystemAlert.Description.figma.js +20 -0
  148. package/lib/commonjs/figma/SystemAlert.Description.figma.js.map +1 -0
  149. package/lib/commonjs/figma/SystemAlert.IconButton.figma.js +31 -0
  150. package/lib/commonjs/figma/SystemAlert.IconButton.figma.js.map +1 -0
  151. package/lib/commonjs/figma/SystemAlert.figma.js +47 -0
  152. package/lib/commonjs/figma/SystemAlert.figma.js.map +1 -0
  153. package/lib/commonjs/styles.css +0 -1
  154. package/lib/module/components/BarChart/geometry.js +1110 -0
  155. package/lib/module/components/BarChart/geometry.js.map +1 -0
  156. package/lib/module/components/BarChart/index.js +929 -0
  157. package/lib/module/components/BarChart/index.js.map +1 -0
  158. package/lib/module/components/BarChart/styles.js +22 -0
  159. package/lib/module/components/BarChart/styles.js.map +1 -0
  160. package/lib/module/components/Button/index.js +2 -2
  161. package/lib/module/components/Button/index.js.map +1 -1
  162. package/lib/module/components/CountryFlag/index.js +52 -0
  163. package/lib/module/components/CountryFlag/index.js.map +1 -0
  164. package/lib/module/components/Input/index.js.map +1 -1
  165. package/lib/module/components/LineChart/geometry.js +685 -0
  166. package/lib/module/components/LineChart/geometry.js.map +1 -0
  167. package/lib/module/components/LineChart/index.js +738 -0
  168. package/lib/module/components/LineChart/index.js.map +1 -0
  169. package/lib/module/components/LineChart/styles.js +21 -0
  170. package/lib/module/components/LineChart/styles.js.map +1 -0
  171. package/lib/module/components/PieChart/geometry.js +209 -0
  172. package/lib/module/components/PieChart/geometry.js.map +1 -0
  173. package/lib/module/components/PieChart/index.js +471 -0
  174. package/lib/module/components/PieChart/index.js.map +1 -0
  175. package/lib/module/components/PieChart/styles.js +84 -0
  176. package/lib/module/components/PieChart/styles.js.map +1 -0
  177. package/lib/module/components/ProgressBar/index.js +47 -15
  178. package/lib/module/components/ProgressBar/index.js.map +1 -1
  179. package/lib/module/components/ProgressBar/styles.js +31 -2
  180. package/lib/module/components/ProgressBar/styles.js.map +1 -1
  181. package/lib/module/components/ProgressCircle/ProgressCircleRing.js +10 -32
  182. package/lib/module/components/ProgressCircle/ProgressCircleRing.js.map +1 -1
  183. package/lib/module/components/ProgressCircle/ProgressRing.js +48 -0
  184. package/lib/module/components/ProgressCircle/ProgressRing.js.map +1 -0
  185. package/lib/module/components/ScrollShadow/useScrollShadow.js +8 -7
  186. package/lib/module/components/ScrollShadow/useScrollShadow.js.map +1 -1
  187. package/lib/module/components/Select/index.js.map +1 -1
  188. package/lib/module/components/Stepper/index.js +360 -0
  189. package/lib/module/components/Stepper/index.js.map +1 -0
  190. package/lib/module/components/Stepper/styles.js +206 -0
  191. package/lib/module/components/Stepper/styles.js.map +1 -0
  192. package/lib/module/components/Stepper/useStepperLabelFit.js +18 -0
  193. package/lib/module/components/Stepper/useStepperLabelFit.js.map +1 -0
  194. package/lib/module/components/Stepper/useStepperLabelFit.web.js +48 -0
  195. package/lib/module/components/Stepper/useStepperLabelFit.web.js.map +1 -0
  196. package/lib/module/components/Stepper/useStepperRingColors.js +28 -0
  197. package/lib/module/components/Stepper/useStepperRingColors.js.map +1 -0
  198. package/lib/module/components/SystemAlert/animation.js +213 -0
  199. package/lib/module/components/SystemAlert/animation.js.map +1 -0
  200. package/lib/module/components/SystemAlert/index.js +515 -0
  201. package/lib/module/components/SystemAlert/index.js.map +1 -0
  202. package/lib/module/components/SystemAlert/styles.js +174 -0
  203. package/lib/module/components/SystemAlert/styles.js.map +1 -0
  204. package/lib/module/components/SystemAlert/useSystemAlertStatusBarStyle.js +49 -0
  205. package/lib/module/components/SystemAlert/useSystemAlertStatusBarStyle.js.map +1 -0
  206. package/lib/module/components/Tabs/index.js +4 -0
  207. package/lib/module/components/Tabs/index.js.map +1 -1
  208. package/lib/module/components/Tabs/styles.js +1 -1
  209. package/lib/module/components/Tabs/styles.js.map +1 -1
  210. package/lib/module/components/chart/ChartInspector.js +600 -0
  211. package/lib/module/components/chart/ChartInspector.js.map +1 -0
  212. package/lib/module/components/chart/format.js +84 -0
  213. package/lib/module/components/chart/format.js.map +1 -0
  214. package/lib/module/components/chart/hiddenSvgProps.js +20 -0
  215. package/lib/module/components/chart/hiddenSvgProps.js.map +1 -0
  216. package/lib/module/components/chart/index.js +2 -0
  217. package/lib/module/components/chart/index.js.map +1 -0
  218. package/lib/module/components/chart/motion.js +89 -0
  219. package/lib/module/components/chart/motion.js.map +1 -0
  220. package/lib/module/components/chart/palette.js +168 -0
  221. package/lib/module/components/chart/palette.js.map +1 -0
  222. package/lib/module/components/chart/size.js +29 -0
  223. package/lib/module/components/chart/size.js.map +1 -0
  224. package/lib/module/components/chart/ticks.js +55 -0
  225. package/lib/module/components/chart/ticks.js.map +1 -0
  226. package/lib/module/components/chart/types.js +4 -0
  227. package/lib/module/components/chart/types.js.map +1 -0
  228. package/lib/module/components/chart/useChartHostWidth.js +23 -0
  229. package/lib/module/components/chart/useChartHostWidth.js.map +1 -0
  230. package/lib/module/components/index.js +6 -0
  231. package/lib/module/components/index.js.map +1 -1
  232. package/lib/module/figma/Accordion.figma.js +2 -2
  233. package/lib/module/figma/Accordion.figma.js.map +1 -1
  234. package/lib/module/figma/Alert.figma.js +7 -7
  235. package/lib/module/figma/Alert.figma.js.map +1 -1
  236. package/lib/module/figma/Badge.Indicator.figma.js +6 -5
  237. package/lib/module/figma/Badge.Indicator.figma.js.map +1 -1
  238. package/lib/module/figma/Badge.figma.js +22 -22
  239. package/lib/module/figma/Badge.figma.js.map +1 -1
  240. package/lib/module/figma/Button.figma.js +5 -2
  241. package/lib/module/figma/Button.figma.js.map +1 -1
  242. package/lib/module/figma/CLAUDE.md +1 -0
  243. package/lib/module/figma/Card.Header.figma.js +8 -4
  244. package/lib/module/figma/Card.Header.figma.js.map +1 -1
  245. package/lib/module/figma/Card.figma.js +2 -1
  246. package/lib/module/figma/Card.figma.js.map +1 -1
  247. package/lib/module/figma/Chip.figma.js +2 -2
  248. package/lib/module/figma/Chip.figma.js.map +1 -1
  249. package/lib/module/figma/CurrencyInput.figma.js +1 -1
  250. package/lib/module/figma/CurrencyInput.figma.js.map +1 -1
  251. package/lib/module/figma/Dialog.figma.js +5 -2
  252. package/lib/module/figma/Dialog.figma.js.map +1 -1
  253. package/lib/module/figma/Divider.figma.js +1 -1
  254. package/lib/module/figma/Divider.figma.js.map +1 -1
  255. package/lib/module/figma/Drawer.figma.js +3 -3
  256. package/lib/module/figma/Drawer.figma.js.map +1 -1
  257. package/lib/module/figma/IconButton.figma.js +10 -4
  258. package/lib/module/figma/IconButton.figma.js.map +1 -1
  259. package/lib/module/figma/Input.figma.js +2 -1
  260. package/lib/module/figma/Input.figma.js.map +1 -1
  261. package/lib/module/figma/Insight.figma.js +3 -3
  262. package/lib/module/figma/Insight.figma.js.map +1 -1
  263. package/lib/module/figma/ProgressBar.figma.js +12 -2
  264. package/lib/module/figma/ProgressBar.figma.js.map +1 -1
  265. package/lib/module/figma/ProgressSegmented.figma.js +9 -1
  266. package/lib/module/figma/ProgressSegmented.figma.js.map +1 -1
  267. package/lib/module/figma/Select.figma.js +2 -1
  268. package/lib/module/figma/Select.figma.js.map +1 -1
  269. package/lib/module/figma/SystemAlert.Button.figma.js +22 -0
  270. package/lib/module/figma/SystemAlert.Button.figma.js.map +1 -0
  271. package/lib/module/figma/SystemAlert.Close.figma.js +18 -0
  272. package/lib/module/figma/SystemAlert.Close.figma.js.map +1 -0
  273. package/lib/module/figma/SystemAlert.Description.figma.js +14 -0
  274. package/lib/module/figma/SystemAlert.Description.figma.js.map +1 -0
  275. package/lib/module/figma/SystemAlert.IconButton.figma.js +25 -0
  276. package/lib/module/figma/SystemAlert.IconButton.figma.js.map +1 -0
  277. package/lib/module/figma/SystemAlert.figma.js +41 -0
  278. package/lib/module/figma/SystemAlert.figma.js.map +1 -0
  279. package/lib/module/styles.css +0 -1
  280. package/lib/typescript/components/BarChart/geometry.d.ts +236 -0
  281. package/lib/typescript/components/BarChart/geometry.d.ts.map +1 -0
  282. package/lib/typescript/components/BarChart/index.d.ts +193 -0
  283. package/lib/typescript/components/BarChart/index.d.ts.map +1 -0
  284. package/lib/typescript/components/BarChart/styles.d.ts +32 -0
  285. package/lib/typescript/components/BarChart/styles.d.ts.map +1 -0
  286. package/lib/typescript/components/CountryFlag/index.d.ts +35 -0
  287. package/lib/typescript/components/CountryFlag/index.d.ts.map +1 -0
  288. package/lib/typescript/components/Input/index.d.ts +2 -0
  289. package/lib/typescript/components/Input/index.d.ts.map +1 -1
  290. package/lib/typescript/components/LineChart/geometry.d.ts +248 -0
  291. package/lib/typescript/components/LineChart/geometry.d.ts.map +1 -0
  292. package/lib/typescript/components/LineChart/index.d.ts +105 -0
  293. package/lib/typescript/components/LineChart/index.d.ts.map +1 -0
  294. package/lib/typescript/components/LineChart/styles.d.ts +12 -0
  295. package/lib/typescript/components/LineChart/styles.d.ts.map +1 -0
  296. package/lib/typescript/components/PieChart/geometry.d.ts +43 -0
  297. package/lib/typescript/components/PieChart/geometry.d.ts.map +1 -0
  298. package/lib/typescript/components/PieChart/index.d.ts +147 -0
  299. package/lib/typescript/components/PieChart/index.d.ts.map +1 -0
  300. package/lib/typescript/components/PieChart/styles.d.ts +27 -0
  301. package/lib/typescript/components/PieChart/styles.d.ts.map +1 -0
  302. package/lib/typescript/components/ProgressBar/index.d.ts +16 -1
  303. package/lib/typescript/components/ProgressBar/index.d.ts.map +1 -1
  304. package/lib/typescript/components/ProgressBar/styles.d.ts +7 -2
  305. package/lib/typescript/components/ProgressBar/styles.d.ts.map +1 -1
  306. package/lib/typescript/components/ProgressCircle/ProgressCircleRing.d.ts.map +1 -1
  307. package/lib/typescript/components/ProgressCircle/ProgressRing.d.ts +17 -0
  308. package/lib/typescript/components/ProgressCircle/ProgressRing.d.ts.map +1 -0
  309. package/lib/typescript/components/ScrollShadow/useScrollShadow.d.ts.map +1 -1
  310. package/lib/typescript/components/Select/index.d.ts +2 -0
  311. package/lib/typescript/components/Select/index.d.ts.map +1 -1
  312. package/lib/typescript/components/Stepper/index.d.ts +68 -0
  313. package/lib/typescript/components/Stepper/index.d.ts.map +1 -0
  314. package/lib/typescript/components/Stepper/styles.d.ts +46 -0
  315. package/lib/typescript/components/Stepper/styles.d.ts.map +1 -0
  316. package/lib/typescript/components/Stepper/useStepperLabelFit.d.ts +15 -0
  317. package/lib/typescript/components/Stepper/useStepperLabelFit.d.ts.map +1 -0
  318. package/lib/typescript/components/Stepper/useStepperLabelFit.web.d.ts +10 -0
  319. package/lib/typescript/components/Stepper/useStepperLabelFit.web.d.ts.map +1 -0
  320. package/lib/typescript/components/Stepper/useStepperRingColors.d.ts +6 -0
  321. package/lib/typescript/components/Stepper/useStepperRingColors.d.ts.map +1 -0
  322. package/lib/typescript/components/SystemAlert/animation.d.ts +56 -0
  323. package/lib/typescript/components/SystemAlert/animation.d.ts.map +1 -0
  324. package/lib/typescript/components/SystemAlert/index.d.ts +110 -0
  325. package/lib/typescript/components/SystemAlert/index.d.ts.map +1 -0
  326. package/lib/typescript/components/SystemAlert/styles.d.ts +38 -0
  327. package/lib/typescript/components/SystemAlert/styles.d.ts.map +1 -0
  328. package/lib/typescript/components/SystemAlert/useSystemAlertStatusBarStyle.d.ts +14 -0
  329. package/lib/typescript/components/SystemAlert/useSystemAlertStatusBarStyle.d.ts.map +1 -0
  330. package/lib/typescript/components/Tabs/index.d.ts.map +1 -1
  331. package/lib/typescript/components/chart/ChartInspector.d.ts +101 -0
  332. package/lib/typescript/components/chart/ChartInspector.d.ts.map +1 -0
  333. package/lib/typescript/components/chart/format.d.ts +16 -0
  334. package/lib/typescript/components/chart/format.d.ts.map +1 -0
  335. package/lib/typescript/components/chart/hiddenSvgProps.d.ts +17 -0
  336. package/lib/typescript/components/chart/hiddenSvgProps.d.ts.map +1 -0
  337. package/lib/typescript/components/chart/index.d.ts +3 -0
  338. package/lib/typescript/components/chart/index.d.ts.map +1 -0
  339. package/lib/typescript/components/chart/motion.d.ts +27 -0
  340. package/lib/typescript/components/chart/motion.d.ts.map +1 -0
  341. package/lib/typescript/components/chart/palette.d.ts +44 -0
  342. package/lib/typescript/components/chart/palette.d.ts.map +1 -0
  343. package/lib/typescript/components/chart/size.d.ts +25 -0
  344. package/lib/typescript/components/chart/size.d.ts.map +1 -0
  345. package/lib/typescript/components/chart/ticks.d.ts +3 -0
  346. package/lib/typescript/components/chart/ticks.d.ts.map +1 -0
  347. package/lib/typescript/components/chart/types.d.ts +163 -0
  348. package/lib/typescript/components/chart/types.d.ts.map +1 -0
  349. package/lib/typescript/components/chart/useChartHostWidth.d.ts +9 -0
  350. package/lib/typescript/components/chart/useChartHostWidth.d.ts.map +1 -0
  351. package/lib/typescript/components/index.d.ts +6 -0
  352. package/lib/typescript/components/index.d.ts.map +1 -1
  353. package/lib/typescript/figma/Alert.figma.d.ts.map +1 -1
  354. package/lib/typescript/figma/Badge.Indicator.figma.d.ts.map +1 -1
  355. package/lib/typescript/figma/Badge.figma.d.ts.map +1 -1
  356. package/lib/typescript/figma/Button.figma.d.ts.map +1 -1
  357. package/lib/typescript/figma/Card.Header.figma.d.ts.map +1 -1
  358. package/lib/typescript/figma/Card.figma.d.ts.map +1 -1
  359. package/lib/typescript/figma/Dialog.figma.d.ts.map +1 -1
  360. package/lib/typescript/figma/IconButton.figma.d.ts.map +1 -1
  361. package/lib/typescript/figma/Input.figma.d.ts.map +1 -1
  362. package/lib/typescript/figma/ProgressBar.figma.d.ts.map +1 -1
  363. package/lib/typescript/figma/ProgressSegmented.figma.d.ts.map +1 -1
  364. package/lib/typescript/figma/Select.figma.d.ts.map +1 -1
  365. package/lib/typescript/figma/SystemAlert.Button.figma.d.ts +11 -0
  366. package/lib/typescript/figma/SystemAlert.Button.figma.d.ts.map +1 -0
  367. package/lib/typescript/figma/SystemAlert.Close.figma.d.ts +11 -0
  368. package/lib/typescript/figma/SystemAlert.Close.figma.d.ts.map +1 -0
  369. package/lib/typescript/figma/SystemAlert.Description.figma.d.ts +8 -0
  370. package/lib/typescript/figma/SystemAlert.Description.figma.d.ts.map +1 -0
  371. package/lib/typescript/figma/SystemAlert.IconButton.figma.d.ts +11 -0
  372. package/lib/typescript/figma/SystemAlert.IconButton.figma.d.ts.map +1 -0
  373. package/lib/typescript/figma/SystemAlert.figma.d.ts +8 -0
  374. package/lib/typescript/figma/SystemAlert.figma.d.ts.map +1 -0
  375. package/package.json +5 -5
  376. package/src/components/BarChart/geometry.ts +1469 -0
  377. package/src/components/BarChart/index.tsx +1417 -0
  378. package/src/components/BarChart/styles.ts +31 -0
  379. package/src/components/Button/index.tsx +1 -1
  380. package/src/components/CountryFlag/index.tsx +53 -0
  381. package/src/components/Input/index.tsx +2 -0
  382. package/src/components/LineChart/geometry.ts +957 -0
  383. package/src/components/LineChart/index.tsx +1106 -0
  384. package/src/components/LineChart/styles.ts +26 -0
  385. package/src/components/PieChart/geometry.ts +295 -0
  386. package/src/components/PieChart/index.tsx +715 -0
  387. package/src/components/PieChart/styles.ts +101 -0
  388. package/src/components/ProgressBar/index.tsx +66 -14
  389. package/src/components/ProgressBar/styles.ts +35 -4
  390. package/src/components/ProgressCircle/ProgressCircleRing.tsx +10 -39
  391. package/src/components/ProgressCircle/ProgressRing.tsx +60 -0
  392. package/src/components/ScrollShadow/useScrollShadow.ts +12 -11
  393. package/src/components/Select/index.tsx +2 -0
  394. package/src/components/Stepper/index.tsx +452 -0
  395. package/src/components/Stepper/styles.ts +234 -0
  396. package/src/components/Stepper/useStepperLabelFit.ts +21 -0
  397. package/src/components/Stepper/useStepperLabelFit.web.ts +53 -0
  398. package/src/components/Stepper/useStepperRingColors.ts +29 -0
  399. package/src/components/SystemAlert/animation.ts +252 -0
  400. package/src/components/SystemAlert/index.tsx +684 -0
  401. package/src/components/SystemAlert/styles.ts +212 -0
  402. package/src/components/SystemAlert/useSystemAlertStatusBarStyle.ts +57 -0
  403. package/src/components/Tabs/index.tsx +4 -0
  404. package/src/components/Tabs/styles.ts +1 -1
  405. package/src/components/chart/ChartInspector.tsx +726 -0
  406. package/src/components/chart/format.ts +95 -0
  407. package/src/components/chart/hiddenSvgProps.ts +15 -0
  408. package/src/components/chart/index.ts +24 -0
  409. package/src/components/chart/motion.ts +98 -0
  410. package/src/components/chart/palette.tsx +247 -0
  411. package/src/components/chart/size.ts +21 -0
  412. package/src/components/chart/ticks.ts +53 -0
  413. package/src/components/chart/types.ts +183 -0
  414. package/src/components/chart/useChartHostWidth.ts +26 -0
  415. package/src/components/index.ts +6 -0
  416. package/src/styles.css +0 -1
@@ -0,0 +1,726 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import { PanResponder, Platform, Pressable, Text, View } from 'react-native';
3
+ import { dataAttributes } from '@cdx-ui/primitives';
4
+ import type { ChartTooltipContent, ChartTooltipItem } from './types';
5
+
6
+ export interface ChartInspectorTarget {
7
+ readonly key: string;
8
+ /** Hit box in overlay coordinates. */
9
+ readonly left: number;
10
+ readonly top: number;
11
+ readonly width: number;
12
+ readonly height: number;
13
+ /** Point the tooltip sits beside. */
14
+ readonly anchorX: number;
15
+ readonly anchorY: number;
16
+ /** Half-width of the mark at the anchor, so the tooltip clears it. */
17
+ readonly anchorRadius?: number;
18
+ readonly tooltip: ChartTooltipContent;
19
+ readonly accessibilityLabel: string;
20
+ readonly selected: boolean;
21
+ /** Keyboard focus ring. Defaults to the hit box. */
22
+ readonly outline?: {
23
+ readonly left: number;
24
+ readonly top: number;
25
+ readonly width: number;
26
+ readonly height: number;
27
+ };
28
+ }
29
+
30
+ interface InspectorKeyEvent {
31
+ readonly nativeEvent: { readonly key: string; readonly shiftKey?: boolean };
32
+ readonly key?: string;
33
+ readonly shiftKey?: boolean;
34
+ readonly preventDefault?: () => void;
35
+ }
36
+
37
+ interface InspectorBlurEvent {
38
+ nativeEvent: { relatedTarget?: unknown };
39
+ relatedTarget?: unknown;
40
+ }
41
+
42
+ const TOOLTIP_GAP = 8;
43
+ const TOOLTIP_MAX_WIDTH = 192;
44
+ /** WCAG 2.5.8 (AA) is 24px; 44px matches Apple HIG / WCAG 2.5.5 for touch. */
45
+ export const MIN_POINTER_TARGET_PX = 44;
46
+ /** Hold before scrubbing a scrollable plot, so a flick can still scroll (Apple Health). */
47
+ export const CHART_SCRUB_HOLD_MS = 250;
48
+ const SCRUB_MOVE_SLOP_PX = 10;
49
+
50
+ interface InspectorTouchEvent {
51
+ nativeEvent: {
52
+ locationX?: number;
53
+ locationY?: number;
54
+ pageX?: number;
55
+ pageY?: number;
56
+ touches?: readonly {
57
+ locationX?: number;
58
+ locationY?: number;
59
+ pageX?: number;
60
+ pageY?: number;
61
+ }[];
62
+ };
63
+ }
64
+
65
+ function touchPoint(event: InspectorTouchEvent): {
66
+ locationX: number;
67
+ locationY: number;
68
+ pageX: number;
69
+ pageY: number;
70
+ } {
71
+ const touch = event.nativeEvent.touches?.[0];
72
+ const locationX = touch?.locationX ?? event.nativeEvent.locationX ?? 0;
73
+ const locationY = touch?.locationY ?? event.nativeEvent.locationY ?? 0;
74
+ return {
75
+ locationX,
76
+ locationY,
77
+ pageX: touch?.pageX ?? event.nativeEvent.pageX ?? locationX,
78
+ pageY: touch?.pageY ?? event.nativeEvent.pageY ?? locationY,
79
+ };
80
+ }
81
+
82
+ export function expandHitBox(
83
+ left: number,
84
+ top: number,
85
+ width: number,
86
+ height: number,
87
+ minSize: number = MIN_POINTER_TARGET_PX,
88
+ ): { left: number; top: number; width: number; height: number } {
89
+ const nextWidth = Math.max(width, minSize);
90
+ const nextHeight = Math.max(height, minSize);
91
+ return {
92
+ left: left - (nextWidth - width) / 2,
93
+ top: top - (nextHeight - height) / 2,
94
+ width: nextWidth,
95
+ height: nextHeight,
96
+ };
97
+ }
98
+
99
+ function targetIndexAt(
100
+ targets: readonly ChartInspectorTarget[],
101
+ x: number,
102
+ y: number,
103
+ ): number | null {
104
+ const hit = targets.findIndex(
105
+ (target) =>
106
+ x >= target.left &&
107
+ x <= target.left + target.width &&
108
+ y >= target.top &&
109
+ y <= target.top + target.height,
110
+ );
111
+ return hit >= 0 ? hit : null;
112
+ }
113
+
114
+ export function chartValueText(item: ChartTooltipItem): string {
115
+ return item.label.length > 0 ? `${item.label} ${item.formattedValue}` : item.formattedValue;
116
+ }
117
+
118
+ interface ChartTooltipSize {
119
+ readonly width: number;
120
+ readonly height: number;
121
+ }
122
+
123
+ function clampInto(value: number, min: number, max: number): number {
124
+ // Wider than the frame: center it so it overflows both edges equally.
125
+ if (max < min) {
126
+ return (min + max) / 2;
127
+ }
128
+ return Math.min(Math.max(value, min), max);
129
+ }
130
+
131
+ /**
132
+ * Top-left of a tooltip in frame coordinates. Beside the anchor on the roomier side when it
133
+ * fits, otherwise above or below it; always clamped inside the frame so a clipping ancestor
134
+ * (a `Card`, a `ScrollView`) cannot cut it off.
135
+ */
136
+ export function placeChartTooltip(
137
+ anchor: { readonly x: number; readonly y: number; readonly radius?: number },
138
+ tip: ChartTooltipSize,
139
+ frame: ChartTooltipSize,
140
+ ): { left: number; top: number } {
141
+ const gap = TOOLTIP_GAP + (anchor.radius ?? 0);
142
+ const rightOf = anchor.x + gap;
143
+ const leftOf = anchor.x - gap - tip.width;
144
+ const fitsRight = rightOf + tip.width <= frame.width;
145
+ const fitsLeft = leftOf >= 0;
146
+ const maxLeft = frame.width - tip.width;
147
+ const maxTop = frame.height - tip.height;
148
+ if (fitsLeft || fitsRight) {
149
+ const useLeft = anchor.x > frame.width / 2 ? fitsLeft : !fitsRight;
150
+ const top = anchor.y > frame.height / 2 ? anchor.y - tip.height : anchor.y;
151
+ return { left: useLeft ? leftOf : rightOf, top: clampInto(top, 0, maxTop) };
152
+ }
153
+ const above = anchor.y - TOOLTIP_GAP - tip.height;
154
+ const top = above >= 0 ? above : anchor.y + TOOLTIP_GAP;
155
+ return {
156
+ left: clampInto(anchor.x - tip.width / 2, 0, maxLeft),
157
+ top: clampInto(top, 0, maxTop),
158
+ };
159
+ }
160
+
161
+ /** Renders only from `content`, so a consumer tooltip slot can replace it later. */
162
+ function ChartTooltip({
163
+ content,
164
+ noValueText,
165
+ slot,
166
+ onSize,
167
+ }: {
168
+ content: ChartTooltipContent;
169
+ noValueText: string;
170
+ slot: string;
171
+ onSize: (size: ChartTooltipSize) => void;
172
+ }) {
173
+ return (
174
+ <View
175
+ className="gap-1 rounded-md bg-surface-neutral-strong px-3 py-2 shadow-lg"
176
+ onLayout={(event) => {
177
+ const { width, height } = event.nativeEvent.layout;
178
+ onSize({ width, height });
179
+ }}
180
+ aria-hidden
181
+ accessibilityElementsHidden
182
+ importantForAccessibility="no-hide-descendants"
183
+ {...dataAttributes({ slot: `${slot}-tooltip` })}
184
+ >
185
+ <Text className="body-sm font-medium text-content-neutral-on-strong">{content.title}</Text>
186
+ {content.items.length === 0 ? (
187
+ <Text className="body-sm text-content-neutral-on-strong">{noValueText}</Text>
188
+ ) : (
189
+ content.items.map((item) => (
190
+ <View key={item.seriesId} className="flex-row items-center gap-1.5">
191
+ <View className="size-2 rounded-full" style={{ backgroundColor: item.color }} />
192
+ <Text className="body-sm text-content-neutral-on-strong">{chartValueText(item)}</Text>
193
+ </View>
194
+ ))
195
+ )}
196
+ </View>
197
+ );
198
+ }
199
+
200
+ /**
201
+ * Chart tooltip, measured and clamped inside `width` × `height`. Mount it in the chart's
202
+ * outer plot frame, never inside the plot `ScrollView`, which clips its content.
203
+ */
204
+ export function ChartTooltipLayer({
205
+ content,
206
+ noValueText,
207
+ slot,
208
+ anchorX,
209
+ anchorY,
210
+ anchorRadius,
211
+ width,
212
+ height,
213
+ }: {
214
+ content: ChartTooltipContent;
215
+ noValueText: string;
216
+ slot: string;
217
+ /** Anchor in frame coordinates. */
218
+ anchorX: number;
219
+ anchorY: number;
220
+ anchorRadius?: number;
221
+ width: number;
222
+ height: number;
223
+ }) {
224
+ const [size, setSize] = useState<ChartTooltipSize | null>(null);
225
+ const position =
226
+ size === null
227
+ ? { left: 0, top: 0 }
228
+ : placeChartTooltip({ x: anchorX, y: anchorY, radius: anchorRadius }, size, {
229
+ width,
230
+ height,
231
+ });
232
+ // A fixed-width box at the frame origin lets the tooltip take its natural width wherever it
233
+ // lands; `left`/`right` offsets shrink it to the space left before the frame edge.
234
+ return (
235
+ <View
236
+ pointerEvents="none"
237
+ className="absolute left-0 top-0 z-20 items-start"
238
+ style={{
239
+ width: TOOLTIP_MAX_WIDTH,
240
+ opacity: size === null ? 0 : 1,
241
+ transform: [{ translateX: position.left }, { translateY: position.top }],
242
+ }}
243
+ >
244
+ <ChartTooltip
245
+ content={content}
246
+ noValueText={noValueText}
247
+ slot={slot}
248
+ onSize={(next) => {
249
+ setSize((prev) =>
250
+ prev?.width === next.width && prev.height === next.height ? prev : next,
251
+ );
252
+ }}
253
+ />
254
+ </View>
255
+ );
256
+ }
257
+
258
+ /**
259
+ * Host-element hit targets over an SVG plot. SVG nodes are poor focus and hover targets under
260
+ * React Native Web, so each target is a `Pressable` with roving focus: one tab stop per chart.
261
+ * Web: native `mousemove` (RN Web `Pressable` has no hover). Native: press-and-drag on the
262
+ * overlay; the tooltip tracks the finger and clears on lift. When the plot itself scrolls,
263
+ * scrubbing waits for a short hold so a flick can still pan. Keyboard and VoiceOver still use
264
+ * the buttons (Escape / two-finger Z).
265
+ */
266
+ export function ChartInspector({
267
+ targets,
268
+ summary,
269
+ selectable,
270
+ activeIndex,
271
+ selectedIndex,
272
+ slot,
273
+ holdToScrub = false,
274
+ onActivate,
275
+ onDeactivate,
276
+ onDismiss,
277
+ onSelectIndex,
278
+ hitTest,
279
+ neighborIndex,
280
+ onScrubLockChange,
281
+ }: {
282
+ targets: readonly ChartInspectorTarget[];
283
+ summary: string;
284
+ selectable: boolean;
285
+ activeIndex: number | null;
286
+ selectedIndex: number | null;
287
+ slot: string;
288
+ /** Wait for a hold before capturing the pan, so a scrollable plot can still flick-scroll. */
289
+ holdToScrub?: boolean;
290
+ onActivate: (index: number) => void;
291
+ /** Called with the target that lost hover or focus. Ignore it if another target is already active. */
292
+ onDeactivate: (index: number) => void;
293
+ onDismiss: () => void;
294
+ onSelectIndex: (index: number) => void;
295
+ /** When set, pointer hits use this instead of the rectangular target boxes (line charts). */
296
+ hitTest?: (x: number, y: number) => number | null;
297
+ /** Override linear arrow-key movement (grouped / stacked bar charts). */
298
+ neighborIndex?: (index: number, key: string) => number | null;
299
+ /**
300
+ * Fires when a hold locks the finger to scrubbing (`true`) and when it lifts (`false`).
301
+ * The parent must disable its `ScrollView` while locked, or the native pan steals the drag.
302
+ */
303
+ onScrubLockChange?: (locked: boolean) => void;
304
+ }) {
305
+ const refs = useRef<(View | null)[]>([]);
306
+ const overlayRef = useRef<View>(null);
307
+ const [keyboardFocus, setKeyboardFocus] = useState(false);
308
+ const pointerRef = useRef({
309
+ targets,
310
+ hitTest,
311
+ selectable,
312
+ holdToScrub,
313
+ onActivate,
314
+ onDeactivate,
315
+ onDismiss,
316
+ onSelectIndex,
317
+ activeIndex,
318
+ neighborIndex,
319
+ onScrubLockChange,
320
+ });
321
+ pointerRef.current = {
322
+ targets,
323
+ hitTest,
324
+ selectable,
325
+ holdToScrub,
326
+ onActivate,
327
+ onDeactivate,
328
+ onDismiss,
329
+ onSelectIndex,
330
+ activeIndex,
331
+ neighborIndex,
332
+ onScrubLockChange,
333
+ };
334
+ const scrubRef = useRef({
335
+ locked: false,
336
+ holdTimer: null as ReturnType<typeof setTimeout> | null,
337
+ startPageX: 0,
338
+ startPageY: 0,
339
+ lastX: 0,
340
+ lastY: 0,
341
+ });
342
+
343
+ const hitAtPoint = (x: number, y: number) => {
344
+ const { targets: nextTargets, hitTest: test } = pointerRef.current;
345
+ return test ? test(x, y) : targetIndexAt(nextTargets, x, y);
346
+ };
347
+ const activateAtPoint = (x: number, y: number) => {
348
+ const next = hitAtPoint(x, y);
349
+ const {
350
+ onActivate: activate,
351
+ activeIndex: index,
352
+ onDeactivate: deactivate,
353
+ } = pointerRef.current;
354
+ if (next === null) {
355
+ if (index !== null) {
356
+ deactivate(index);
357
+ }
358
+ return;
359
+ }
360
+ activate(next);
361
+ };
362
+ const clearHoldTimer = () => {
363
+ if (scrubRef.current.holdTimer != null) {
364
+ clearTimeout(scrubRef.current.holdTimer);
365
+ scrubRef.current.holdTimer = null;
366
+ }
367
+ };
368
+ const clearPointer = () => {
369
+ const { activeIndex: index, onDeactivate: deactivate, onDismiss: dismiss } = pointerRef.current;
370
+ dismiss();
371
+ if (index !== null) {
372
+ deactivate(index);
373
+ }
374
+ };
375
+ const finishScrub = () => {
376
+ const wasLocked = scrubRef.current.locked;
377
+ // A tap that never passed the scroll slop still selects. A move that cancelled the
378
+ // hold is a scroll and leaves the chart alone.
379
+ const wasTap =
380
+ pointerRef.current.holdToScrub && !wasLocked && scrubRef.current.holdTimer != null;
381
+ clearHoldTimer();
382
+ const shouldFinish = wasLocked || wasTap || !pointerRef.current.holdToScrub;
383
+ scrubRef.current.locked = false;
384
+ if (wasLocked) {
385
+ pointerRef.current.onScrubLockChange?.(false);
386
+ }
387
+ if (!shouldFinish) {
388
+ return;
389
+ }
390
+ const {
391
+ activeIndex: index,
392
+ selectable: canSelect,
393
+ onSelectIndex: select,
394
+ onActivate: activate,
395
+ } = pointerRef.current;
396
+ const hit = wasTap ? hitAtPoint(scrubRef.current.lastX, scrubRef.current.lastY) : index;
397
+ if (wasTap && hit !== null) {
398
+ activate(hit);
399
+ }
400
+ if (canSelect && hit !== null) {
401
+ select(hit);
402
+ }
403
+ clearPointer();
404
+ };
405
+ const beginHold = (event: InspectorTouchEvent) => {
406
+ if (Platform.OS === 'web') {
407
+ return;
408
+ }
409
+ const point = touchPoint(event);
410
+ clearHoldTimer();
411
+ scrubRef.current.locked = false;
412
+ scrubRef.current.startPageX = point.pageX;
413
+ scrubRef.current.startPageY = point.pageY;
414
+ scrubRef.current.lastX = point.locationX;
415
+ scrubRef.current.lastY = point.locationY;
416
+ if (!pointerRef.current.holdToScrub) {
417
+ activateAtPoint(point.locationX, point.locationY);
418
+ return;
419
+ }
420
+ scrubRef.current.holdTimer = setTimeout(() => {
421
+ scrubRef.current.holdTimer = null;
422
+ scrubRef.current.locked = true;
423
+ pointerRef.current.onScrubLockChange?.(true);
424
+ activateAtPoint(scrubRef.current.lastX, scrubRef.current.lastY);
425
+ }, CHART_SCRUB_HOLD_MS);
426
+ };
427
+ const noteHoldMove = (event: InspectorTouchEvent) => {
428
+ const point = touchPoint(event);
429
+ scrubRef.current.lastX = point.locationX;
430
+ scrubRef.current.lastY = point.locationY;
431
+ if (!pointerRef.current.holdToScrub) {
432
+ activateAtPoint(point.locationX, point.locationY);
433
+ return;
434
+ }
435
+ if (scrubRef.current.locked || scrubRef.current.holdTimer == null) {
436
+ return;
437
+ }
438
+ const dist = Math.hypot(
439
+ point.pageX - scrubRef.current.startPageX,
440
+ point.pageY - scrubRef.current.startPageY,
441
+ );
442
+ if (dist > SCRUB_MOVE_SLOP_PX) {
443
+ clearHoldTimer();
444
+ }
445
+ };
446
+
447
+ const panResponder = useRef(
448
+ PanResponder.create({
449
+ onStartShouldSetPanResponder: () => false,
450
+ onMoveShouldSetPanResponder: () => {
451
+ if (Platform.OS === 'web') {
452
+ return false;
453
+ }
454
+ return pointerRef.current.holdToScrub && scrubRef.current.locked;
455
+ },
456
+ onPanResponderTerminationRequest: () => !scrubRef.current.locked,
457
+ onPanResponderGrant: (event) => {
458
+ activateAtPoint(event.nativeEvent.locationX, event.nativeEvent.locationY);
459
+ },
460
+ onPanResponderMove: (event) => {
461
+ activateAtPoint(event.nativeEvent.locationX, event.nativeEvent.locationY);
462
+ },
463
+ onPanResponderRelease: finishScrub,
464
+ onPanResponderTerminate: finishScrub,
465
+ }),
466
+ ).current;
467
+
468
+ const count = targets.length;
469
+ const rovingIndex = Math.min(activeIndex ?? selectedIndex ?? 0, Math.max(count - 1, 0));
470
+
471
+ // RN Web Pressable does not emit hover. Bind the DOM node directly so mousemove
472
+ // along the line (and across category bands) opens the tooltip.
473
+ useEffect(() => {
474
+ const node = overlayRef.current as unknown as HTMLElement | null;
475
+ if (node == null || typeof node.addEventListener !== 'function') {
476
+ return;
477
+ }
478
+ const hitAt = (event: MouseEvent) => {
479
+ const { targets: nextTargets, hitTest: test } = pointerRef.current;
480
+ const rect = node.getBoundingClientRect();
481
+ const x = event.clientX - rect.left;
482
+ const y = event.clientY - rect.top;
483
+ return test ? test(x, y) : targetIndexAt(nextTargets, x, y);
484
+ };
485
+ const clearActive = () => {
486
+ const {
487
+ activeIndex: index,
488
+ onDeactivate: deactivate,
489
+ onDismiss: dismiss,
490
+ } = pointerRef.current;
491
+ dismiss();
492
+ if (index !== null) {
493
+ deactivate(index);
494
+ }
495
+ };
496
+ const move = (event: MouseEvent) => {
497
+ setKeyboardFocus(false);
498
+ const next = hitAt(event);
499
+ const {
500
+ onActivate: activate,
501
+ activeIndex: index,
502
+ onDeactivate: deactivate,
503
+ } = pointerRef.current;
504
+ if (next === null) {
505
+ if (index !== null) {
506
+ deactivate(index);
507
+ }
508
+ return;
509
+ }
510
+ activate(next);
511
+ };
512
+ const down = (event: MouseEvent) => {
513
+ if (event.button !== 0) {
514
+ return;
515
+ }
516
+ setKeyboardFocus(false);
517
+ const next = hitAt(event);
518
+ const {
519
+ onActivate: activate,
520
+ selectable: canSelect,
521
+ onSelectIndex: select,
522
+ } = pointerRef.current;
523
+ if (next === null) {
524
+ clearActive();
525
+ return;
526
+ }
527
+ activate(next);
528
+ if (canSelect) {
529
+ select(next);
530
+ }
531
+ };
532
+ const leave = (event: MouseEvent) => {
533
+ if (node.contains(event.relatedTarget as Node | null)) {
534
+ return;
535
+ }
536
+ const { activeIndex: index, onDeactivate: deactivate } = pointerRef.current;
537
+ if (index !== null) {
538
+ deactivate(index);
539
+ }
540
+ };
541
+ const docDown = (event: MouseEvent) => {
542
+ if (node.contains(event.target as Node | null)) {
543
+ return;
544
+ }
545
+ clearActive();
546
+ };
547
+ node.addEventListener('mousemove', move);
548
+ node.addEventListener('mousedown', down);
549
+ node.addEventListener('mouseleave', leave);
550
+ document.addEventListener('mousedown', docDown);
551
+ return () => {
552
+ node.removeEventListener('mousemove', move);
553
+ node.removeEventListener('mousedown', down);
554
+ node.removeEventListener('mouseleave', leave);
555
+ document.removeEventListener('mousedown', docDown);
556
+ if (scrubRef.current.holdTimer != null) {
557
+ clearTimeout(scrubRef.current.holdTimer);
558
+ scrubRef.current.holdTimer = null;
559
+ }
560
+ };
561
+ }, []);
562
+
563
+ const handleKeyDown = (index: number, event: InspectorKeyEvent) => {
564
+ const key = event.nativeEvent.key ?? event.key ?? '';
565
+ const shiftKey = event.shiftKey === true || event.nativeEvent.shiftKey === true;
566
+ if (
567
+ key === 'Escape' ||
568
+ key === 'Enter' ||
569
+ key === ' ' ||
570
+ key === 'Tab' ||
571
+ key === 'ArrowRight' ||
572
+ key === 'ArrowLeft' ||
573
+ key === 'ArrowUp' ||
574
+ key === 'ArrowDown' ||
575
+ key === 'Home' ||
576
+ key === 'End'
577
+ ) {
578
+ setKeyboardFocus(true);
579
+ }
580
+ if (key === 'Escape') {
581
+ event.preventDefault?.();
582
+ onDismiss();
583
+ return;
584
+ }
585
+ if (key === 'Enter' || key === ' ') {
586
+ event.preventDefault?.();
587
+ onActivate(index);
588
+ if (selectable) {
589
+ onSelectIndex(index);
590
+ }
591
+ return;
592
+ }
593
+ if (key === 'Tab') {
594
+ const next = neighborIndex?.(index, shiftKey ? 'Shift+Tab' : 'Tab');
595
+ if (next === undefined || next === null || next === index) {
596
+ return;
597
+ }
598
+ event.preventDefault?.();
599
+ onActivate(next);
600
+ refs.current[next]?.focus();
601
+ return;
602
+ }
603
+ let next: number | null = neighborIndex?.(index, key) ?? null;
604
+ if (next === null) {
605
+ if (key === 'ArrowRight' || key === 'ArrowDown') {
606
+ next = Math.min(index + 1, count - 1);
607
+ } else if (key === 'ArrowLeft' || key === 'ArrowUp') {
608
+ next = Math.max(index - 1, 0);
609
+ } else if (key === 'Home') {
610
+ next = 0;
611
+ } else if (key === 'End') {
612
+ next = count - 1;
613
+ }
614
+ }
615
+ if (next === null) {
616
+ return;
617
+ }
618
+ event.preventDefault?.();
619
+ onActivate(next);
620
+ refs.current[next]?.focus();
621
+ };
622
+
623
+ const blurInspector = (event: InspectorBlurEvent | undefined) => {
624
+ const related = event?.nativeEvent?.relatedTarget ?? event?.relatedTarget;
625
+ const node = overlayRef.current as unknown as {
626
+ contains?: (target: unknown) => boolean;
627
+ } | null;
628
+ if (node?.contains?.(related) === true) {
629
+ return;
630
+ }
631
+ setKeyboardFocus(false);
632
+ if (activeIndex !== null) {
633
+ onDeactivate(activeIndex);
634
+ }
635
+ };
636
+
637
+ const outline =
638
+ keyboardFocus && activeIndex !== null
639
+ ? (targets.at(activeIndex)?.outline ?? targets.at(activeIndex))
640
+ : undefined;
641
+
642
+ return (
643
+ <View
644
+ ref={overlayRef}
645
+ className="absolute inset-0 z-10"
646
+ role="group"
647
+ aria-label={summary}
648
+ accessibilityLabel={summary}
649
+ onAccessibilityEscape={onDismiss}
650
+ {...(Platform.OS === 'web'
651
+ ? {}
652
+ : {
653
+ ...panResponder.panHandlers,
654
+ onTouchStart: beginHold,
655
+ onTouchMove: noteHoldMove,
656
+ onTouchEnd: finishScrub,
657
+ onTouchCancel: finishScrub,
658
+ })}
659
+ {...dataAttributes({ slot: `${slot}-inspector` })}
660
+ >
661
+ {outline !== undefined ? (
662
+ <View
663
+ pointerEvents="none"
664
+ className="absolute rounded-sm border-2 border-[var(--color-stroke-ring)]"
665
+ style={{
666
+ left: outline.left,
667
+ top: outline.top,
668
+ width: outline.width,
669
+ height: outline.height,
670
+ }}
671
+ accessibilityElementsHidden
672
+ importantForAccessibility="no-hide-descendants"
673
+ {...dataAttributes({ slot: `${slot}-focus` })}
674
+ />
675
+ ) : null}
676
+ {targets.map((target, index) => (
677
+ <Pressable
678
+ key={target.key}
679
+ ref={(node) => {
680
+ refs.current[index] = node;
681
+ }}
682
+ className="absolute rounded-sm web:outline-none"
683
+ style={{
684
+ left: target.left,
685
+ top: target.top,
686
+ width: target.width,
687
+ height: target.height,
688
+ }}
689
+ accessibilityRole="button"
690
+ accessibilityLabel={target.accessibilityLabel}
691
+ accessibilityState={
692
+ selectable && Platform.OS !== 'web' ? { selected: target.selected } : undefined
693
+ }
694
+ aria-pressed={selectable && Platform.OS === 'web' ? target.selected : undefined}
695
+ pointerEvents="none"
696
+ focusable={Platform.OS !== 'web' || index === rovingIndex}
697
+ tabIndex={index === rovingIndex ? 0 : -1}
698
+ onHoverIn={() => {
699
+ onActivate(index);
700
+ }}
701
+ onHoverOut={() => {
702
+ onDeactivate(index);
703
+ }}
704
+ onFocus={() => {
705
+ setKeyboardFocus(true);
706
+ onActivate(index);
707
+ }}
708
+ onBlur={(event: unknown) => blurInspector(event as InspectorBlurEvent)}
709
+ onPress={() => {
710
+ onActivate(index);
711
+ if (selectable) {
712
+ onSelectIndex(index);
713
+ }
714
+ }}
715
+ onAccessibilityEscape={onDismiss}
716
+ {...{
717
+ onKeyDown: (event: InspectorKeyEvent) => {
718
+ handleKeyDown(index, event);
719
+ },
720
+ }}
721
+ {...dataAttributes({ slot: `${slot}-point`, selected: target.selected })}
722
+ />
723
+ ))}
724
+ </View>
725
+ );
726
+ }