@galaxy-io/dls 1.2.6 → 1.3.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 (297) hide show
  1. package/README.md +2 -0
  2. package/dist/avatar/Avatar.d.ts +2 -1
  3. package/dist/avatar/Avatar.js +103 -14
  4. package/dist/buttons/Button.d.ts +6 -1
  5. package/dist/buttons/Button.js +8 -4
  6. package/dist/charts/BarChart.d.ts +30 -20
  7. package/dist/charts/BarChart.js +216 -250
  8. package/dist/charts/ChartAxis.d.ts +47 -22
  9. package/dist/charts/ChartAxis.js +81 -60
  10. package/dist/charts/ChartEmptyState.d.ts +17 -0
  11. package/dist/charts/ChartEmptyState.js +29 -0
  12. package/dist/charts/ChartFrame.d.ts +82 -0
  13. package/dist/charts/ChartFrame.js +86 -0
  14. package/dist/charts/ChartLegend.d.ts +27 -4
  15. package/dist/charts/ChartLegend.js +46 -23
  16. package/dist/charts/ChartPrimitives.d.ts +195 -0
  17. package/dist/charts/ChartPrimitives.js +268 -0
  18. package/dist/charts/ChartTooltip.d.ts +27 -6
  19. package/dist/charts/ChartTooltip.js +56 -50
  20. package/dist/charts/LineChart.d.ts +42 -20
  21. package/dist/charts/LineChart.js +186 -237
  22. package/dist/charts/PieChart.d.ts +48 -32
  23. package/dist/charts/PieChart.js +159 -171
  24. package/dist/charts/barChartGeometry.d.ts +87 -0
  25. package/dist/charts/barChartGeometry.js +218 -0
  26. package/dist/charts/chartFormat.d.ts +19 -0
  27. package/dist/charts/chartFormat.js +59 -0
  28. package/dist/charts/chartScales.d.ts +84 -0
  29. package/dist/charts/chartScales.js +111 -0
  30. package/dist/charts/chartTheme.d.ts +18 -0
  31. package/dist/charts/chartTheme.js +26 -0
  32. package/dist/charts/constants.d.ts +225 -18
  33. package/dist/charts/constants.js +240 -32
  34. package/dist/charts/lineChartGeometry.d.ts +54 -0
  35. package/dist/charts/lineChartGeometry.js +143 -0
  36. package/dist/charts/pieChartGeometry.d.ts +48 -0
  37. package/dist/charts/pieChartGeometry.js +89 -0
  38. package/dist/charts/types.d.ts +522 -54
  39. package/dist/charts/types.js +136 -0
  40. package/dist/charts/useChartDimensions.d.ts +40 -0
  41. package/dist/charts/useChartDimensions.js +53 -0
  42. package/dist/charts/useChartFormatters.d.ts +19 -0
  43. package/dist/charts/useChartFormatters.js +20 -0
  44. package/dist/charts/useChartInteraction.d.ts +71 -0
  45. package/dist/charts/useChartInteraction.js +130 -0
  46. package/dist/charts/useChartTooltipPosition.d.ts +53 -0
  47. package/dist/charts/useChartTooltipPosition.js +39 -0
  48. package/dist/hooks/useElementClientSize.d.ts +20 -0
  49. package/dist/hooks/useElementClientSize.js +43 -0
  50. package/dist/inputs/CheckboxInput.d.ts +7 -2
  51. package/dist/inputs/CheckboxInput.js +30 -14
  52. package/dist/inputs/Input.d.ts +5 -2
  53. package/dist/inputs/Input.js +20 -17
  54. package/dist/inputs/MultiSelectInput.js +1 -1
  55. package/dist/inputs/RadioInput.js +7 -2
  56. package/dist/styles.css +68 -75
  57. package/dist/table/InfiniteSpreadsheet.d.ts +6 -0
  58. package/dist/table/InfiniteSpreadsheet.js +235 -0
  59. package/dist/table/InfiniteTable.d.ts +7 -88
  60. package/dist/table/InfiniteTable.js +366 -577
  61. package/dist/{spreadsheet → table}/SpreadsheetCell.d.ts +6 -4
  62. package/dist/table/SpreadsheetCell.js +71 -0
  63. package/dist/{spreadsheet → table}/SpreadsheetCellEditor.js +27 -21
  64. package/dist/table/SpreadsheetHeaderCell.d.ts +23 -0
  65. package/dist/table/SpreadsheetHeaderCell.js +91 -0
  66. package/dist/table/SpreadsheetMenuItem.d.ts +14 -0
  67. package/dist/table/SpreadsheetMenuItem.js +33 -0
  68. package/dist/table/SpreadsheetPrimitives.d.ts +172 -0
  69. package/dist/table/SpreadsheetPrimitives.js +105 -0
  70. package/dist/table/SpreadsheetRow.d.ts +33 -0
  71. package/dist/table/SpreadsheetRow.js +73 -0
  72. package/dist/{spreadsheet → table}/SpreadsheetRowActionCell.d.ts +5 -7
  73. package/dist/table/SpreadsheetRowActionCell.js +51 -0
  74. package/dist/table/TableExpandCell.d.ts +11 -0
  75. package/dist/table/TableExpandCell.js +24 -0
  76. package/dist/table/TableExpandedRow.d.ts +16 -0
  77. package/dist/table/TableExpandedRow.js +77 -0
  78. package/dist/table/TableHeaderCellContent.d.ts +30 -0
  79. package/dist/table/TableHeaderCellContent.js +48 -0
  80. package/dist/table/TablePrimitives.d.ts +307 -0
  81. package/dist/table/TablePrimitives.js +298 -0
  82. package/dist/table/TableSelectCell.d.ts +18 -0
  83. package/dist/table/TableSelectCell.js +26 -0
  84. package/dist/table/TableStatusRow.d.ts +18 -0
  85. package/dist/table/TableStatusRow.js +50 -0
  86. package/dist/table/VirtualizedInfiniteTable.d.ts +11 -27
  87. package/dist/table/VirtualizedInfiniteTable.js +182 -317
  88. package/dist/table/types.d.ts +249 -0
  89. package/dist/table/types.js +51 -0
  90. package/dist/table/useInfiniteScrollSentinel.d.ts +24 -0
  91. package/dist/table/useInfiniteScrollSentinel.js +53 -0
  92. package/dist/{spreadsheet/hooks → table}/useSpreadsheetEditing.d.ts +1 -1
  93. package/dist/{spreadsheet/hooks → table}/useSpreadsheetEditing.js +1 -1
  94. package/dist/table/useTableColumnLayout.d.ts +28 -0
  95. package/dist/table/useTableColumnLayout.js +63 -0
  96. package/dist/table/useTableColumnResize.d.ts +38 -0
  97. package/dist/table/useTableColumnResize.js +155 -0
  98. package/dist/table/useTableKeyboardNavigation.d.ts +25 -0
  99. package/dist/table/useTableKeyboardNavigation.js +83 -0
  100. package/dist/table/useTableRowExpansion.d.ts +24 -0
  101. package/dist/table/useTableRowExpansion.js +62 -0
  102. package/dist/table/useTableRowSelection.d.ts +27 -0
  103. package/dist/table/useTableRowSelection.js +94 -0
  104. package/dist/table/utils.d.ts +50 -0
  105. package/dist/table/utils.js +78 -0
  106. package/dist/text/MarkdownText.js +45 -27
  107. package/dist/theme/variants/dark.js +1 -1
  108. package/dist/widget/Widget.d.ts +2 -0
  109. package/dist/widget/Widget.js +14 -7
  110. package/package.json +1 -5
  111. package/dist/assets/components/enrichment/PerplexityIcon.d.ts +0 -3
  112. package/dist/assets/components/enrichment/PerplexityIcon.js +0 -35
  113. package/dist/assets/components/enrichment/TavilyIcon.d.ts +0 -3
  114. package/dist/assets/components/enrichment/TavilyIcon.js +0 -15
  115. package/dist/assets/components/onboarding/TenantSetupDark.d.ts +0 -3
  116. package/dist/assets/components/onboarding/TenantSetupDark.js +0 -498
  117. package/dist/assets/components/onboarding/TenantSetupLight.d.ts +0 -3
  118. package/dist/assets/components/onboarding/TenantSetupLight.js +0 -482
  119. package/dist/assets/components/onboarding/UserSetupDark.d.ts +0 -3
  120. package/dist/assets/components/onboarding/UserSetupDark.js +0 -1086
  121. package/dist/assets/components/onboarding/UserSetupLight.d.ts +0 -3
  122. package/dist/assets/components/onboarding/UserSetupLight.js +0 -1024
  123. package/dist/assets/components/onboarding/WorkspaceSetupBuildDark.d.ts +0 -3
  124. package/dist/assets/components/onboarding/WorkspaceSetupBuildDark.js +0 -466
  125. package/dist/assets/components/onboarding/WorkspaceSetupBuildLight.d.ts +0 -3
  126. package/dist/assets/components/onboarding/WorkspaceSetupBuildLight.js +0 -460
  127. package/dist/assets/components/onboarding/WorkspaceSetupConnectDark.d.ts +0 -3
  128. package/dist/assets/components/onboarding/WorkspaceSetupConnectDark.js +0 -336
  129. package/dist/assets/components/onboarding/WorkspaceSetupConnectLight.d.ts +0 -3
  130. package/dist/assets/components/onboarding/WorkspaceSetupConnectLight.js +0 -336
  131. package/dist/assets/components/onboarding/WorkspaceSetupIntegrateDark.d.ts +0 -3
  132. package/dist/assets/components/onboarding/WorkspaceSetupIntegrateDark.js +0 -153
  133. package/dist/assets/components/onboarding/WorkspaceSetupIntegrateLight.d.ts +0 -3
  134. package/dist/assets/components/onboarding/WorkspaceSetupIntegrateLight.js +0 -153
  135. package/dist/assets/components/projects/MappingMethodAutoIntrospectDark.d.ts +0 -3
  136. package/dist/assets/components/projects/MappingMethodAutoIntrospectDark.js +0 -117
  137. package/dist/assets/components/projects/MappingMethodAutoIntrospectLight.d.ts +0 -3
  138. package/dist/assets/components/projects/MappingMethodAutoIntrospectLight.js +0 -117
  139. package/dist/assets/components/projects/MappingMethodBlankDark.d.ts +0 -3
  140. package/dist/assets/components/projects/MappingMethodBlankDark.js +0 -150
  141. package/dist/assets/components/projects/MappingMethodBlankDarkHovered.d.ts +0 -3
  142. package/dist/assets/components/projects/MappingMethodBlankDarkHovered.js +0 -150
  143. package/dist/assets/components/projects/MappingMethodBlankLight.d.ts +0 -3
  144. package/dist/assets/components/projects/MappingMethodBlankLight.js +0 -150
  145. package/dist/assets/components/projects/MappingMethodBlankLightHovered.d.ts +0 -3
  146. package/dist/assets/components/projects/MappingMethodBlankLightHovered.js +0 -150
  147. package/dist/assets/components/projects/MappingMethodJsonDark.d.ts +0 -3
  148. package/dist/assets/components/projects/MappingMethodJsonDark.js +0 -90
  149. package/dist/assets/components/projects/MappingMethodJsonDarkHovered.d.ts +0 -3
  150. package/dist/assets/components/projects/MappingMethodJsonDarkHovered.js +0 -90
  151. package/dist/assets/components/projects/MappingMethodJsonLight.d.ts +0 -3
  152. package/dist/assets/components/projects/MappingMethodJsonLight.js +0 -90
  153. package/dist/assets/components/projects/MappingMethodJsonLightHovered.d.ts +0 -3
  154. package/dist/assets/components/projects/MappingMethodJsonLightHovered.js +0 -90
  155. package/dist/assets/components/projects/ProjectsEmptyStateDark.d.ts +0 -3
  156. package/dist/assets/components/projects/ProjectsEmptyStateDark.js +0 -454
  157. package/dist/assets/components/projects/ProjectsEmptyStateLight.d.ts +0 -3
  158. package/dist/assets/components/projects/ProjectsEmptyStateLight.js +0 -456
  159. package/dist/assets/components/root/CreateProjectActionCardDark.d.ts +0 -3
  160. package/dist/assets/components/root/CreateProjectActionCardDark.js +0 -1796
  161. package/dist/assets/components/root/CreateProjectActionCardDarkHovered.d.ts +0 -3
  162. package/dist/assets/components/root/CreateProjectActionCardDarkHovered.js +0 -1796
  163. package/dist/assets/components/root/CreateProjectActionCardLight.d.ts +0 -3
  164. package/dist/assets/components/root/CreateProjectActionCardLight.js +0 -1786
  165. package/dist/assets/components/root/CreateProjectActionCardLightHovered.d.ts +0 -3
  166. package/dist/assets/components/root/CreateProjectActionCardLightHovered.js +0 -1786
  167. package/dist/assets/components/root/CreateSourceActionCardDark.d.ts +0 -3
  168. package/dist/assets/components/root/CreateSourceActionCardDark.js +0 -879
  169. package/dist/assets/components/root/CreateSourceActionCardDarkHovered.d.ts +0 -3
  170. package/dist/assets/components/root/CreateSourceActionCardDarkHovered.js +0 -879
  171. package/dist/assets/components/root/CreateSourceActionCardLight.d.ts +0 -3
  172. package/dist/assets/components/root/CreateSourceActionCardLight.js +0 -889
  173. package/dist/assets/components/root/CreateSourceActionCardLightHovered.d.ts +0 -3
  174. package/dist/assets/components/root/CreateSourceActionCardLightHovered.js +0 -889
  175. package/dist/assets/components/sources/AttioIcon.d.ts +0 -3
  176. package/dist/assets/components/sources/AttioIcon.js +0 -11
  177. package/dist/assets/components/sources/BigquerySourceIcon.d.ts +0 -3
  178. package/dist/assets/components/sources/BigquerySourceIcon.js +0 -39
  179. package/dist/assets/components/sources/BrowserbaseSourceIcon.d.ts +0 -3
  180. package/dist/assets/components/sources/BrowserbaseSourceIcon.js +0 -35
  181. package/dist/assets/components/sources/ClickhouseLogoSourceIconDark.d.ts +0 -3
  182. package/dist/assets/components/sources/ClickhouseLogoSourceIconDark.js +0 -13
  183. package/dist/assets/components/sources/ClickhouseLogoSourceIconLight.d.ts +0 -3
  184. package/dist/assets/components/sources/ClickhouseLogoSourceIconLight.js +0 -13
  185. package/dist/assets/components/sources/ConfluenceSourceIcon.d.ts +0 -3
  186. package/dist/assets/components/sources/ConfluenceSourceIcon.js +0 -30
  187. package/dist/assets/components/sources/GithubSourceIcon.d.ts +0 -3
  188. package/dist/assets/components/sources/GithubSourceIcon.js +0 -27
  189. package/dist/assets/components/sources/GoogleDriveIcon.d.ts +0 -3
  190. package/dist/assets/components/sources/GoogleDriveIcon.js +0 -45
  191. package/dist/assets/components/sources/HubspotSourceIcon.d.ts +0 -3
  192. package/dist/assets/components/sources/HubspotSourceIcon.js +0 -14
  193. package/dist/assets/components/sources/JiraSourceIcon.d.ts +0 -3
  194. package/dist/assets/components/sources/JiraSourceIcon.js +0 -54
  195. package/dist/assets/components/sources/LinearSourceIcon.d.ts +0 -3
  196. package/dist/assets/components/sources/LinearSourceIcon.js +0 -14
  197. package/dist/assets/components/sources/MysqlLogoSourceIconDark.d.ts +0 -3
  198. package/dist/assets/components/sources/MysqlLogoSourceIconDark.js +0 -17
  199. package/dist/assets/components/sources/NetsuiteSourceIcon.d.ts +0 -3
  200. package/dist/assets/components/sources/NetsuiteSourceIcon.js +0 -32
  201. package/dist/assets/components/sources/NotionIcon.d.ts +0 -3
  202. package/dist/assets/components/sources/NotionIcon.js +0 -20
  203. package/dist/assets/components/sources/PostgresqlIcon.d.ts +0 -3
  204. package/dist/assets/components/sources/PostgresqlIcon.js +0 -61
  205. package/dist/assets/components/sources/S3Icon.d.ts +0 -3
  206. package/dist/assets/components/sources/S3Icon.js +0 -76
  207. package/dist/assets/components/sources/SalesforceSourceIcon.d.ts +0 -3
  208. package/dist/assets/components/sources/SalesforceSourceIcon.js +0 -23
  209. package/dist/assets/components/sources/SlackIcon.d.ts +0 -3
  210. package/dist/assets/components/sources/SlackIcon.js +0 -32
  211. package/dist/assets/components/sources/SnowflakeLogoSourceIconDark.d.ts +0 -3
  212. package/dist/assets/components/sources/SnowflakeLogoSourceIconDark.js +0 -14
  213. package/dist/assets/components/sources/SnowflakeLogoSourceIconLight.d.ts +0 -3
  214. package/dist/assets/components/sources/SnowflakeLogoSourceIconLight.js +0 -14
  215. package/dist/assets/components/sources/WikipediaSourceIcon.d.ts +0 -3
  216. package/dist/assets/components/sources/WikipediaSourceIcon.js +0 -1490
  217. package/dist/avatar/AvatarEmpty.d.ts +0 -7
  218. package/dist/avatar/AvatarEmpty.js +0 -99
  219. package/dist/avatar/types.d.ts +0 -5
  220. package/dist/avatar/types.js +0 -9
  221. package/dist/charts/utils.d.ts +0 -29
  222. package/dist/charts/utils.js +0 -62
  223. package/dist/icons/BackIcon.d.ts +0 -3
  224. package/dist/icons/BackIcon.js +0 -13
  225. package/dist/icons/CloseIcon.d.ts +0 -3
  226. package/dist/icons/CloseIcon.js +0 -13
  227. package/dist/icons/CreateIcon.d.ts +0 -3
  228. package/dist/icons/CreateIcon.js +0 -13
  229. package/dist/icons/ForwardIcon.d.ts +0 -3
  230. package/dist/icons/ForwardIcon.js +0 -13
  231. package/dist/icons/HelpIcon.d.ts +0 -3
  232. package/dist/icons/HelpIcon.js +0 -14
  233. package/dist/icons/ProjectsIcon.d.ts +0 -3
  234. package/dist/icons/ProjectsIcon.js +0 -12
  235. package/dist/icons/SearchIcon.d.ts +0 -3
  236. package/dist/icons/SearchIcon.js +0 -12
  237. package/dist/icons/SourcesIcon.d.ts +0 -3
  238. package/dist/icons/SourcesIcon.js +0 -12
  239. package/dist/icons/TextIcon.d.ts +0 -4
  240. package/dist/icons/TextIcon.js +0 -22
  241. package/dist/icons/WebScrapeIcon.d.ts +0 -4
  242. package/dist/icons/WebScrapeIcon.js +0 -22
  243. package/dist/icons/WebhookIcon.d.ts +0 -4
  244. package/dist/icons/WebhookIcon.js +0 -22
  245. package/dist/icons/sources/AttioLogomark.d.ts +0 -4
  246. package/dist/icons/sources/AttioLogomark.js +0 -8
  247. package/dist/icons/sources/BrowserbaseLogomark.d.ts +0 -4
  248. package/dist/icons/sources/BrowserbaseLogomark.js +0 -8
  249. package/dist/icons/sources/ClickhouseLogomark.d.ts +0 -4
  250. package/dist/icons/sources/ClickhouseLogomark.js +0 -16
  251. package/dist/icons/sources/ConfluenceLogomark.d.ts +0 -4
  252. package/dist/icons/sources/ConfluenceLogomark.js +0 -8
  253. package/dist/icons/sources/GithubLogomark.d.ts +0 -4
  254. package/dist/icons/sources/GithubLogomark.js +0 -8
  255. package/dist/icons/sources/GoogleBigqueryLogomark.d.ts +0 -4
  256. package/dist/icons/sources/GoogleBigqueryLogomark.js +0 -8
  257. package/dist/icons/sources/GoogleDriveLogomark.d.ts +0 -4
  258. package/dist/icons/sources/GoogleDriveLogomark.js +0 -8
  259. package/dist/icons/sources/HubspotLogomark.d.ts +0 -4
  260. package/dist/icons/sources/HubspotLogomark.js +0 -8
  261. package/dist/icons/sources/JiraLogomark.d.ts +0 -4
  262. package/dist/icons/sources/JiraLogomark.js +0 -8
  263. package/dist/icons/sources/LinearLogomark.d.ts +0 -4
  264. package/dist/icons/sources/LinearLogomark.js +0 -8
  265. package/dist/icons/sources/MySQLLogomark.d.ts +0 -4
  266. package/dist/icons/sources/MySQLLogomark.js +0 -8
  267. package/dist/icons/sources/NetsuiteLogomark.d.ts +0 -4
  268. package/dist/icons/sources/NetsuiteLogomark.js +0 -8
  269. package/dist/icons/sources/NotionLogomark.d.ts +0 -4
  270. package/dist/icons/sources/NotionLogomark.js +0 -8
  271. package/dist/icons/sources/PostgresLogomark.d.ts +0 -4
  272. package/dist/icons/sources/PostgresLogomark.js +0 -8
  273. package/dist/icons/sources/S3Logomark.d.ts +0 -4
  274. package/dist/icons/sources/S3Logomark.js +0 -8
  275. package/dist/icons/sources/SalesforceLogomark.d.ts +0 -4
  276. package/dist/icons/sources/SalesforceLogomark.js +0 -8
  277. package/dist/icons/sources/SlackLogoIconmark.d.ts +0 -4
  278. package/dist/icons/sources/SlackLogoIconmark.js +0 -8
  279. package/dist/icons/sources/SnowflakeLogomark.d.ts +0 -4
  280. package/dist/icons/sources/SnowflakeLogomark.js +0 -16
  281. package/dist/icons/sources/WikipediaLogomark.d.ts +0 -4
  282. package/dist/icons/sources/WikipediaLogomark.js +0 -8
  283. package/dist/spreadsheet/InfiniteSpreadsheet.d.ts +0 -3
  284. package/dist/spreadsheet/InfiniteSpreadsheet.js +0 -265
  285. package/dist/spreadsheet/SpreadsheetAddColumnButton.d.ts +0 -6
  286. package/dist/spreadsheet/SpreadsheetAddColumnButton.js +0 -32
  287. package/dist/spreadsheet/SpreadsheetCell.js +0 -115
  288. package/dist/spreadsheet/SpreadsheetHeaderCell.d.ts +0 -18
  289. package/dist/spreadsheet/SpreadsheetHeaderCell.js +0 -141
  290. package/dist/spreadsheet/SpreadsheetRow.d.ts +0 -21
  291. package/dist/spreadsheet/SpreadsheetRow.js +0 -68
  292. package/dist/spreadsheet/SpreadsheetRowActionCell.js +0 -78
  293. package/dist/spreadsheet/hooks/useColumnResize.d.ts +0 -6
  294. package/dist/spreadsheet/hooks/useColumnResize.js +0 -46
  295. package/dist/spreadsheet/types.d.ts +0 -92
  296. package/dist/spreadsheet/types.js +0 -21
  297. /package/dist/{spreadsheet → table}/SpreadsheetCellEditor.d.ts +0 -0
@@ -1,183 +1,171 @@
1
- import { useGalaxyTheme, withTheme } from "../theme/GalaxyTheme.js";
2
- import Text, { TextSize, TextWeight } from "../text/Text.js";
1
+ import { useGalaxyTheme } from "../theme/GalaxyTheme.js";
3
2
  import FlexWrapper, { AlignItems, FlexDirection, JustifyContent } from "../containers/FlexWrapper.js";
4
- import { useElementWidth } from "../hooks/useElementWidth.js";
5
- import Wrapper from "../containers/Wrapper.js";
6
- import { getChartPalette } from "./constants.js";
7
- import { defaultLabelFormatter, defaultValueFormatter } from "./utils.js";
8
- import ChartLegend from "./ChartLegend.js";
9
- import ChartTooltip from "./ChartTooltip.js";
10
- /* empty css */
11
- import { styled } from "@linaria/react";
12
- import { useCallback, useMemo, useRef, useState } from "react";
13
- import { jsx, jsxs } from "react/jsx-runtime";
14
- import { arc, pie } from "d3-shape";
3
+ import { ChartMarkState } from "./types.js";
4
+ import { PIE_CHART_MARGIN, PIE_MIN_SLICE_SHARE } from "./constants.js";
5
+ import { ChartTooltipVerticalAlign } from "./useChartTooltipPosition.js";
6
+ import { useChartInteraction } from "./useChartInteraction.js";
7
+ import { useChartFormatters } from "./useChartFormatters.js";
8
+ import { useChartDimensions } from "./useChartDimensions.js";
9
+ import { buildPieChartGeometry } from "./pieChartGeometry.js";
10
+ import { resolveChartPaletteColor, resolveSeriesColor } from "./chartTheme.js";
11
+ import { ChartArcPath, ChartCenterBox } from "./ChartPrimitives.js";
12
+ import ChartFrame from "./ChartFrame.js";
13
+ import { useCallback, useMemo, useRef } from "react";
14
+ import { jsx } from "react/jsx-runtime";
15
15
  //#region src/charts/PieChart.tsx
16
- var DEFAULT_PAD_ANGLE = .02;
17
- var DEFAULT_CORNER_RADIUS = 2;
18
- var PIE_MARGIN = 8;
19
- var _exp = () => ({ $fillWidth }) => $fillWidth ? "flex" : "inline-flex";
20
- var _exp2 = () => ({ $fillWidth }) => $fillWidth ? "100%" : "auto";
21
- var ChartWrapper = withTheme(/*#__PURE__*/ styled("div")({
22
- name: "ChartWrapper",
23
- class: "c1ez9f1",
24
- propsAsIs: false,
25
- vars: {
26
- "c1ez9f1-0": [_exp()],
27
- "c1ez9f1-1": [_exp2()]
28
- }
29
- }));
30
- var resolveSliceColor = (slice, index, palette) => slice.color ?? palette[index % palette.length];
31
- var PieChart = ({ slices, width, height, fillWidth = false, aspectRatio, innerRadius = 0, padAngle = DEFAULT_PAD_ANGLE, cornerRadius = DEFAULT_CORNER_RADIUS, valueFormatter = defaultValueFormatter, labelFormatter = defaultLabelFormatter, tooltipRenderer, noTooltip = false, showLegend = true, showLabels = false, ariaLabel }) => {
16
+ /**
17
+ * Pie and donut chart.
18
+ *
19
+ * Unlike the cartesian charts there is no category axis to hit-test against, so
20
+ * each arc is its own target. Small slices are folded into an "Other" bucket by
21
+ * default, which keeps every remaining arc large enough to actually hit.
22
+ */
23
+ var PieChart = ({ series, slices, width, height, fillWidth, fillHeight, aspectRatio, margin, innerRadiusRatio, padAngle, cornerRadius, minSliceShare = PIE_MIN_SLICE_SHARE, aggregatedLabel, centerContent, valueUnit, valueFormatter, labelFormatter, showLegend = true, noTooltip = false, tooltipRenderer, isLoading = false, contentWhenEmpty, ariaLabel, ariaDescription, onPinnedChange }) => {
32
24
  const { theme } = useGalaxyTheme();
33
25
  const containerRef = useRef(null);
34
- const svgRef = useRef(null);
35
- const [tooltip, setTooltip] = useState(null);
36
- const [hoveredSliceIndex, setHoveredSliceIndex] = useState(null);
37
- const measuredWidth = useElementWidth(containerRef);
38
- const resolvedWidth = fillWidth ? measuredWidth ?? 0 : width ?? 0;
39
- const resolvedHeight = aspectRatio ? resolvedWidth / aspectRatio : height ?? 0;
40
- const palette = useMemo(() => getChartPalette(theme), [theme]);
41
- const outerRadius = useMemo(() => Math.min(resolvedWidth, resolvedHeight) / 2 - PIE_MARGIN, [resolvedWidth, resolvedHeight]);
42
- const effectivePadAngle = innerRadius > 0 ? padAngle : 0;
43
- const pieGen = useMemo(() => pie().value((d) => d.value).sort(null).padAngle(effectivePadAngle), [effectivePadAngle]);
44
- const arcs = useMemo(() => pieGen(slices), [pieGen, slices]);
45
- const arcGen = useMemo(() => arc().innerRadius(innerRadius).outerRadius(outerRadius).cornerRadius(cornerRadius), [
46
- innerRadius,
47
- outerRadius,
48
- cornerRadius
49
- ]);
50
- const labelArc = useMemo(() => {
51
- const mid = innerRadius > 0 ? (innerRadius + outerRadius) / 2 : outerRadius * .65;
52
- return arc().innerRadius(mid).outerRadius(mid);
53
- }, [innerRadius, outerRadius]);
54
- const total = useMemo(() => slices.reduce((sum, s) => sum + s.value, 0), [slices]);
55
- const handleSliceMouseEnter = useCallback((sliceIndex, event) => {
56
- const slice = slices[sliceIndex];
57
- if (!slice) return;
58
- const svgRect = svgRef.current?.getBoundingClientRect();
59
- if (!svgRect) return;
60
- setHoveredSliceIndex(sliceIndex);
61
- setTooltip({
62
- label: labelFormatter(slice.label),
63
- items: [{
64
- seriesKey: slice.label,
65
- seriesName: labelFormatter(slice.label),
66
- value: slice.value,
67
- color: resolveSliceColor(slice, sliceIndex, palette)
68
- }],
69
- x: event.clientX - svgRect.left,
70
- y: event.clientY - svgRect.top
71
- });
72
- }, [
73
- slices,
74
- palette,
26
+ const dimensions = useChartDimensions({
27
+ containerRef,
28
+ width,
29
+ height,
30
+ fillWidth,
31
+ fillHeight,
32
+ aspectRatio,
33
+ margin: margin ?? PIE_CHART_MARGIN
34
+ });
35
+ const { plotWidth, plotHeight } = dimensions;
36
+ const { formatValue, formatLabel } = useChartFormatters({
37
+ valueFormatter,
38
+ valueUnit,
75
39
  labelFormatter
76
- ]);
77
- const handleSliceMouseMove = useCallback((event) => {
78
- if (hoveredSliceIndex === null) return;
79
- const svgRect = svgRef.current?.getBoundingClientRect();
80
- if (!svgRect) return;
81
- setTooltip((prev) => prev ? {
82
- ...prev,
83
- x: event.clientX - svgRect.left,
84
- y: event.clientY - svgRect.top
85
- } : null);
86
- }, [hoveredSliceIndex]);
87
- const handleSliceMouseLeave = useCallback(() => {
88
- setHoveredSliceIndex(null);
89
- setTooltip(null);
90
- }, []);
91
- const legendSeries = useMemo(() => slices.map((s, i) => ({
92
- key: s.label,
93
- name: labelFormatter(s.label),
94
- color: resolveSliceColor(s, i, palette)
95
- })), [
40
+ });
41
+ const sliceKeys = useMemo(() => Object.keys(series), [series]);
42
+ const getSliceLabel = useCallback((sliceKey) => series[sliceKey]?.label ?? sliceKey, [series]);
43
+ const getSliceColor = useCallback((sliceKey) => series[sliceKey]?.color, [series]);
44
+ const resolveColor = useCallback(({ sliceKey, index, explicit }) => {
45
+ if (explicit) return resolveChartPaletteColor(theme, explicit);
46
+ if (sliceKey === null) return theme.color.text.tertiary;
47
+ const slotIndex = sliceKeys.indexOf(sliceKey);
48
+ return resolveSeriesColor(theme, slotIndex >= 0 ? slotIndex : index);
49
+ }, [theme, sliceKeys]);
50
+ const geometry = useMemo(() => buildPieChartGeometry({
96
51
  slices,
97
- palette,
98
- labelFormatter
52
+ plotWidth,
53
+ plotHeight,
54
+ innerRadiusRatio,
55
+ padAngle,
56
+ cornerRadius,
57
+ minSliceShare,
58
+ aggregatedLabel,
59
+ resolveColor,
60
+ getSliceColor,
61
+ getSliceLabel
62
+ }), [
63
+ slices,
64
+ plotWidth,
65
+ plotHeight,
66
+ innerRadiusRatio,
67
+ padAngle,
68
+ cornerRadius,
69
+ minSliceShare,
70
+ aggregatedLabel,
71
+ resolveColor,
72
+ getSliceColor,
73
+ getSliceLabel
99
74
  ]);
100
- if (resolvedWidth === 0 || resolvedHeight === 0) return /* @__PURE__ */ jsx(ChartWrapper, {
101
- ref: containerRef,
102
- $fillWidth: fillWidth
75
+ const isEmpty = geometry.arcs.length === 0;
76
+ const legendItems = useMemo(() => geometry.arcs.map((chartArc) => ({
77
+ key: chartArc.id,
78
+ label: formatLabel(chartArc.label),
79
+ color: chartArc.color
80
+ })), [geometry.arcs, formatLabel]);
81
+ const legendKeys = useMemo(() => legendItems.map((item) => item.key), [legendItems]);
82
+ const interaction = useChartInteraction({
83
+ categoryCount: geometry.arcs.length,
84
+ seriesKeys: legendKeys,
85
+ disabled: noTooltip || isLoading || isEmpty,
86
+ onPinnedChange
103
87
  });
104
- const cx = resolvedWidth / 2;
105
- const cy = resolvedHeight / 2;
106
- const defaultAriaLabel = `Pie chart with ${slices.length} slices`;
107
- return /* @__PURE__ */ jsxs(ChartWrapper, {
108
- ref: containerRef,
109
- $fillWidth: fillWidth,
110
- children: [/* @__PURE__ */ jsxs(Wrapper, {
111
- position: "relative",
112
- children: [/* @__PURE__ */ jsx("svg", {
113
- ref: svgRef,
114
- width: resolvedWidth,
115
- height: resolvedHeight,
116
- role: "img",
117
- "aria-label": ariaLabel ?? defaultAriaLabel,
118
- children: /* @__PURE__ */ jsx("g", {
119
- transform: `translate(${cx}, ${cy})`,
120
- children: arcs.map((d, i) => {
121
- const color = resolveSliceColor(d.data, i, palette);
122
- const isDimmed = hoveredSliceIndex !== null && hoveredSliceIndex !== i;
123
- const path = arcGen(d) ?? "";
124
- const pct = total > 0 ? Math.round(d.data.value / total * 100) : 0;
125
- return /* @__PURE__ */ jsxs("g", { children: [/* @__PURE__ */ jsx("path", {
126
- d: path,
127
- fill: color,
128
- opacity: isDimmed ? .3 : 1,
129
- style: {
130
- transition: `opacity 150ms ease-in-out`,
131
- cursor: "pointer"
132
- },
133
- onMouseEnter: (e) => handleSliceMouseEnter(i, e),
134
- onMouseMove: handleSliceMouseMove,
135
- onMouseLeave: handleSliceMouseLeave,
136
- onFocus: (e) => handleSliceMouseEnter(i, e),
137
- onBlur: handleSliceMouseLeave,
138
- tabIndex: 0,
139
- role: "graphics-symbol",
140
- "aria-roledescription": "slice",
141
- "aria-label": `${labelFormatter(d.data.label)}: ${valueFormatter(d.data.value)} (${pct}%)`
142
- }), showLabels && pct > 5 && (() => {
143
- const [lx, ly] = labelArc.centroid(d);
144
- const labelW = 48;
145
- const labelH = 20;
146
- return /* @__PURE__ */ jsx("foreignObject", {
147
- x: lx - labelW / 2,
148
- y: ly - labelH / 2,
149
- width: labelW,
150
- height: labelH,
151
- style: { pointerEvents: "none" },
152
- children: /* @__PURE__ */ jsx(FlexWrapper, {
153
- justifyContent: JustifyContent.CENTER,
154
- alignItems: AlignItems.CENTER,
155
- fillWidth: true,
156
- fillHeight: true,
157
- children: /* @__PURE__ */ jsx(Text, {
158
- size: TextSize.CAPTION,
159
- weight: TextWeight.MEDIUM,
160
- hex: theme.color.text.primaryAlt,
161
- children: `${pct}%`
162
- })
163
- })
164
- });
165
- })()] }, d.data.label);
166
- })
167
- })
168
- }), !noTooltip && (tooltipRenderer ? tooltip && tooltipRenderer(tooltip) : /* @__PURE__ */ jsx(ChartTooltip, {
169
- data: tooltip,
170
- valueFormatter
171
- }))]
172
- }), showLegend && /* @__PURE__ */ jsx(FlexWrapper, {
173
- direction: FlexDirection.ROW,
174
- gap: 0,
175
- children: /* @__PURE__ */ jsx(ChartLegend, {
176
- series: legendSeries,
177
- palette
178
- })
179
- })]
88
+ const tooltipModel = useMemo(() => {
89
+ if (noTooltip || interaction.activeIndex === null) return null;
90
+ const chartArc = geometry.arcs[interaction.activeIndex];
91
+ if (!chartArc) return null;
92
+ return {
93
+ label: formatLabel(chartArc.label),
94
+ rows: [{
95
+ key: chartArc.id,
96
+ label: `${Math.round(chartArc.share * 1e3) / 10}% of total`,
97
+ value: chartArc.value,
98
+ formattedValue: formatValue(chartArc.value),
99
+ color: chartArc.color
100
+ }],
101
+ anchorX: chartArc.anchorX,
102
+ anchorY: chartArc.anchorY
103
+ };
104
+ }, [
105
+ noTooltip,
106
+ interaction.activeIndex,
107
+ geometry.arcs,
108
+ formatValue,
109
+ formatLabel
110
+ ]);
111
+ const showCenter = centerContent && (innerRadiusRatio ?? .62) > 0;
112
+ return /* @__PURE__ */ jsx(ChartFrame, {
113
+ containerRef,
114
+ dimensions,
115
+ fillWidth,
116
+ fillHeight,
117
+ interaction,
118
+ ariaLabel: ariaLabel ?? `Pie chart with ${geometry.arcs.length} slices`,
119
+ ariaDescription,
120
+ noTooltip,
121
+ tooltipModel,
122
+ tooltipRenderer,
123
+ placeAwayFromX: geometry.centerX,
124
+ verticalAlign: ChartTooltipVerticalAlign.CENTERED,
125
+ isEmpty,
126
+ isLoading,
127
+ contentWhenEmpty,
128
+ showLegend,
129
+ legendItems,
130
+ legendInset: 0,
131
+ plotOverlay: showCenter && !isEmpty ? /* @__PURE__ */ jsx(ChartDonutCenter, {
132
+ centerX: dimensions.margin.left + geometry.centerX,
133
+ centerY: dimensions.margin.top + geometry.centerY,
134
+ diameter: geometry.innerRadius * 2,
135
+ children: centerContent
136
+ }) : null,
137
+ children: /* @__PURE__ */ jsx("g", {
138
+ transform: `translate(${geometry.centerX}, ${geometry.centerY})`,
139
+ children: geometry.arcs.map((chartArc, index) => /* @__PURE__ */ jsx(ChartArcPath, {
140
+ d: chartArc.path,
141
+ fill: chartArc.color,
142
+ "data-state": isLoading ? ChartMarkState.MUTED : interaction.getMarkState({
143
+ categoryIndex: index,
144
+ seriesKey: chartArc.id
145
+ }),
146
+ "data-interactive": noTooltip || isLoading ? "false" : "true",
147
+ onMouseEnter: () => interaction.onCategoryEnter(index),
148
+ onMouseLeave: interaction.onCategoryLeave,
149
+ onClick: () => interaction.onCategoryClick(index),
150
+ "aria-label": `${chartArc.label}: ${formatValue(chartArc.value)}`
151
+ }, chartArc.id))
152
+ })
180
153
  });
181
154
  };
155
+ /** Positions arbitrary content inside the donut hole. */
156
+ var ChartDonutCenter = ({ centerX, centerY, diameter, children }) => /* @__PURE__ */ jsx(ChartCenterBox, {
157
+ $centerX: centerX,
158
+ $centerY: centerY,
159
+ $diameter: diameter,
160
+ children: /* @__PURE__ */ jsx(FlexWrapper, {
161
+ direction: FlexDirection.COLUMN,
162
+ justifyContent: JustifyContent.CENTER,
163
+ alignItems: AlignItems.CENTER,
164
+ gap: 2,
165
+ fillWidth: true,
166
+ fillHeight: true,
167
+ children
168
+ })
169
+ });
182
170
  //#endregion
183
171
  export { PieChart as default };
@@ -0,0 +1,87 @@
1
+ import { buildValueScale } from "./chartScales";
2
+ import { BarChartNormalization, BarCorners } from "./types";
3
+ import type { BarChartGroupBand, BarChartGroupDatum, BarChartRect, ChartPalette, ChartValueDomain } from "./types";
4
+ /**
5
+ * Bar chart geometry.
6
+ *
7
+ * Flattens the group → bar → component hierarchy into a flat array of
8
+ * rectangles plus one hit band per group, so the component body is a `.map()`
9
+ * with no nested loops or running accumulators.
10
+ *
11
+ * Pure: no React, no theme access. Colors arrive through a resolver callback so
12
+ * this module never has to know how the palette maps to the theme.
13
+ */
14
+ interface BarSpacing {
15
+ /** Px between neighbouring groups. */
16
+ groupGap: number;
17
+ /** Px between bars inside a group. */
18
+ barGap: number;
19
+ }
20
+ /**
21
+ * Pick gap sizes from how crowded the chart is.
22
+ *
23
+ * Sparse charts stay roomy regardless of width; once there are enough bars to
24
+ * matter, the gaps tighten as the plot narrows.
25
+ */
26
+ export declare function getBarSpacing(plotWidth: number, totalBars: number): BarSpacing;
27
+ /**
28
+ * Rectangle with one pair of corners rounded.
29
+ *
30
+ * The radius is clamped to half the height as well as half the width, so a very
31
+ * short bar renders as a symmetric cap instead of a lopsided half-pill.
32
+ */
33
+ export declare function roundedRectPath(x: number, y: number, width: number, height: number, radius: number, corners: BarCorners): string;
34
+ /**
35
+ * Signed value domain across every group.
36
+ *
37
+ * Percent-normalized charts always span 0–1, so the axis is stable no matter
38
+ * what the underlying totals are.
39
+ */
40
+ export declare function getBarValueDomain<TMetric extends string, TPivot extends string, TComponentKey extends string>(groups: BarChartGroupDatum<TMetric, TPivot, TComponentKey>[], normalization: BarChartNormalization): [number, number];
41
+ export interface BarChartGeometry<TMetric extends string, TComponentKey extends string = string> {
42
+ /** Every rendered rectangle, in draw order. */
43
+ rects: BarChartRect<TMetric, TComponentKey>[];
44
+ /** One hit target per group, tiling the plot with no gaps. */
45
+ bands: BarChartGroupBand[];
46
+ /** The resolved value scale, shared with the axis. */
47
+ valueScale: ReturnType<typeof buildValueScale>;
48
+ /** Pixel y of value zero — where bars meet the baseline. */
49
+ baselineY: number;
50
+ }
51
+ interface BuildBarChartGeometryArgs<TMetric extends string, TPivot extends string, TComponentKey extends string> {
52
+ groups: BarChartGroupDatum<TMetric, TPivot, TComponentKey>[];
53
+ plotWidth: number;
54
+ plotHeight: number;
55
+ normalization: BarChartNormalization;
56
+ /**
57
+ * Whether the chart as a whole is stacked.
58
+ *
59
+ * Chart-wide, not per bar, because it decides the *colour rule* and the legend
60
+ * lists one domain for the whole chart. Deriving it per bar would colour a
61
+ * single-component bar by metric while the legend named components.
62
+ */
63
+ isStacked: boolean;
64
+ valueDomain?: Partial<ChartValueDomain>;
65
+ /**
66
+ * Maps one segment to a concrete color.
67
+ *
68
+ * The geometry deliberately does not decide the rule — it only reports what
69
+ * it knows about the segment. Whether a stack is coloured by component or a
70
+ * group by metric is a presentation question, and it needs the `series`
71
+ * record to answer, which this module has no business importing.
72
+ */
73
+ resolveColor: (args: ResolveBarColorArgs<TMetric>) => string;
74
+ }
75
+ export interface ResolveBarColorArgs<TMetric extends string> {
76
+ metric: TMetric;
77
+ /** Index of the bar within its group. */
78
+ barIndex: number;
79
+ /** Index of the component within its bar. */
80
+ componentIndex: number;
81
+ /** True when the *chart* is stacked — see the option of the same name. */
82
+ isStacked: boolean;
83
+ /** The component's own palette override, if it declared one. */
84
+ explicit?: ChartPalette;
85
+ }
86
+ export declare function buildBarChartGeometry<TMetric extends string, TPivot extends string = string, TComponentKey extends string = string>({ groups, plotWidth, plotHeight, normalization, isStacked, valueDomain, resolveColor, }: BuildBarChartGeometryArgs<TMetric, TPivot, TComponentKey>): BarChartGeometry<TMetric, TComponentKey>;
87
+ export {};
@@ -0,0 +1,218 @@
1
+ import { BarChartNormalization, BarCorners } from "./types.js";
2
+ import { BAR_WIDTH_RATIO, MAX_GAP_SHARE } from "./constants.js";
3
+ import { applyDomainOverride, buildValueScale, sanitizeValue } from "./chartScales.js";
4
+ //#region src/charts/barChartGeometry.ts
5
+ /**
6
+ * Pick gap sizes from how crowded the chart is.
7
+ *
8
+ * Sparse charts stay roomy regardless of width; once there are enough bars to
9
+ * matter, the gaps tighten as the plot narrows.
10
+ */
11
+ function getBarSpacing(plotWidth, totalBars) {
12
+ if (totalBars < 13 || plotWidth > 650) return {
13
+ groupGap: 24,
14
+ barGap: 6
15
+ };
16
+ if (plotWidth > 500) return {
17
+ groupGap: 16,
18
+ barGap: 4
19
+ };
20
+ return {
21
+ groupGap: 12,
22
+ barGap: 3
23
+ };
24
+ }
25
+ /**
26
+ * Rectangle with one pair of corners rounded.
27
+ *
28
+ * The radius is clamped to half the height as well as half the width, so a very
29
+ * short bar renders as a symmetric cap instead of a lopsided half-pill.
30
+ */
31
+ function roundedRectPath(x, y, width, height, radius, corners) {
32
+ const r = corners === BarCorners.NONE ? 0 : Math.max(0, Math.min(radius, width / 2, height / 2));
33
+ if (r === 0) return `M${x},${y} h${width} v${height} h${-width} z`;
34
+ if (corners === BarCorners.TOP) return [
35
+ `M${x},${y + r}`,
36
+ `a${r},${r} 0 0 1 ${r},${-r}`,
37
+ `h${width - 2 * r}`,
38
+ `a${r},${r} 0 0 1 ${r},${r}`,
39
+ `v${height - r}`,
40
+ `h${-width}`,
41
+ `z`
42
+ ].join(" ");
43
+ return [
44
+ `M${x},${y}`,
45
+ `h${width}`,
46
+ `v${height - r}`,
47
+ `a${r},${r} 0 0 1 ${-r},${r}`,
48
+ `h${-(width - 2 * r)}`,
49
+ `a${r},${r} 0 0 1 ${-r},${-r}`,
50
+ `z`
51
+ ].join(" ");
52
+ }
53
+ /**
54
+ * Turn one bar's components into stacked `[from, to]` intervals.
55
+ *
56
+ * Positive and negative values accumulate on separate cursors, which is what
57
+ * lets a bar mixing both stack upward and downward from the baseline without
58
+ * any special-casing downstream — and is also why percent normalization is a
59
+ * one-line division rather than a second code path.
60
+ */
61
+ function stackComponents(values, normalization) {
62
+ let positiveCursor = 0;
63
+ let negativeCursor = 0;
64
+ const intervals = values.map((value) => {
65
+ if (value >= 0) {
66
+ const from = positiveCursor;
67
+ positiveCursor += value;
68
+ return {
69
+ value,
70
+ from,
71
+ to: positiveCursor
72
+ };
73
+ }
74
+ const to = negativeCursor;
75
+ negativeCursor += value;
76
+ return {
77
+ value,
78
+ from: negativeCursor,
79
+ to
80
+ };
81
+ });
82
+ if (normalization !== BarChartNormalization.PERCENT) return intervals;
83
+ const magnitude = positiveCursor - negativeCursor;
84
+ if (magnitude === 0) return intervals;
85
+ return intervals.map((interval) => ({
86
+ value: interval.value,
87
+ from: interval.from / magnitude,
88
+ to: interval.to / magnitude
89
+ }));
90
+ }
91
+ /**
92
+ * Signed value domain across every group.
93
+ *
94
+ * Percent-normalized charts always span 0–1, so the axis is stable no matter
95
+ * what the underlying totals are.
96
+ */
97
+ function getBarValueDomain(groups, normalization) {
98
+ if (normalization === BarChartNormalization.PERCENT) return [0, 1];
99
+ let min = 0;
100
+ let max = 0;
101
+ for (const group of groups) for (const bar of group.bars) {
102
+ let positive = 0;
103
+ let negative = 0;
104
+ for (const component of bar.components) {
105
+ const value = sanitizeValue(component.value);
106
+ if (value >= 0) positive += value;
107
+ else negative += value;
108
+ }
109
+ if (positive > max) max = positive;
110
+ if (negative < min) min = negative;
111
+ }
112
+ return [min, max];
113
+ }
114
+ function buildBarChartGeometry({ groups, plotWidth, plotHeight, normalization, isStacked, valueDomain, resolveColor }) {
115
+ const valueScale = buildValueScale(applyDomainOverride(getBarValueDomain(groups, normalization), valueDomain), [plotHeight, 0]);
116
+ const baselineY = valueScale(0);
117
+ const rects = [];
118
+ const bands = [];
119
+ if (groups.length === 0 || plotWidth <= 0 || plotHeight <= 0) return {
120
+ rects,
121
+ bands,
122
+ valueScale,
123
+ baselineY
124
+ };
125
+ const { groupGap, barGap } = getBarSpacing(plotWidth, groups.reduce((sum, group) => sum + group.bars.length, 0));
126
+ const step = plotWidth / groups.length;
127
+ const effectiveGroupGap = Math.min(groupGap, step * MAX_GAP_SHARE);
128
+ const groupWidth = Math.max(1, step - effectiveGroupGap);
129
+ groups.forEach((group, groupIndex) => {
130
+ const bandX = groupIndex * step;
131
+ const groupX = bandX + (step - groupWidth) / 2;
132
+ const barCount = Math.max(1, group.bars.length);
133
+ const effectiveBarGap = Math.min(barGap, groupWidth / barCount * MAX_GAP_SHARE);
134
+ const slotWidth = (groupWidth - (barCount - 1) * effectiveBarGap) / barCount;
135
+ const barWidth = Math.max(1, Math.min(slotWidth * BAR_WIDTH_RATIO, 44));
136
+ const radius = barWidth < 40 ? 2 : 4;
137
+ const barsStartX = groupX + (groupWidth - (barCount * barWidth + (barCount - 1) * effectiveBarGap)) / 2;
138
+ let groupTopY = baselineY;
139
+ let hasValue = false;
140
+ group.bars.forEach((bar, barIndex) => {
141
+ const barX = barsStartX + barIndex * (barWidth + effectiveBarGap);
142
+ const values = bar.components.map((component) => sanitizeValue(component.value));
143
+ const intervals = stackComponents(values, normalization);
144
+ let firstPositive = -1;
145
+ let lastPositive = -1;
146
+ let firstNegative = -1;
147
+ let lastNegative = -1;
148
+ values.forEach((value, index) => {
149
+ if (value > 0) {
150
+ if (firstPositive === -1) firstPositive = index;
151
+ lastPositive = index;
152
+ }
153
+ if (value < 0) {
154
+ if (firstNegative === -1) firstNegative = index;
155
+ lastNegative = index;
156
+ }
157
+ });
158
+ bar.components.forEach((component, componentIndex) => {
159
+ const { value, from, to } = intervals[componentIndex];
160
+ if (value === 0) return;
161
+ hasValue = true;
162
+ const isNegative = value < 0;
163
+ const isCap = componentIndex === (isNegative ? lastNegative : lastPositive);
164
+ const fromY = Math.round(valueScale(from));
165
+ const toY = Math.round(valueScale(to));
166
+ const topY = Math.min(fromY, toY);
167
+ const rawHeight = Math.abs(fromY - toY);
168
+ const isStackedBar = bar.components.length > 1;
169
+ const shave = componentIndex === (isNegative ? firstNegative : firstPositive) ? 0 : 2;
170
+ const height = Math.max(isStackedBar ? 0 : 2, rawHeight - shave);
171
+ const y = isNegative ? topY + shave : topY;
172
+ if (!isNegative && y < groupTopY) groupTopY = y;
173
+ rects.push({
174
+ id: `${groupIndex}:${barIndex}:${component.key}`,
175
+ groupIndex,
176
+ barIndex,
177
+ metric: bar.metric,
178
+ componentKey: component.key,
179
+ label: component.label,
180
+ value,
181
+ valueRange: [from, to],
182
+ x: barX,
183
+ y,
184
+ width: barWidth,
185
+ height,
186
+ color: resolveColor({
187
+ metric: bar.metric,
188
+ barIndex,
189
+ componentIndex,
190
+ isStacked,
191
+ explicit: component.color
192
+ }),
193
+ corners: isCap ? isNegative ? BarCorners.BOTTOM : BarCorners.TOP : BarCorners.NONE,
194
+ radius
195
+ });
196
+ });
197
+ });
198
+ bands.push({
199
+ groupIndex,
200
+ label: group.label,
201
+ x: bandX,
202
+ y: 0,
203
+ width: step,
204
+ height: plotHeight,
205
+ anchorX: bandX + step / 2,
206
+ anchorY: groupTopY,
207
+ isEmpty: !hasValue
208
+ });
209
+ });
210
+ return {
211
+ rects,
212
+ bands,
213
+ valueScale,
214
+ baselineY
215
+ };
216
+ }
217
+ //#endregion
218
+ export { buildBarChartGeometry, getBarSpacing, getBarValueDomain, roundedRectPath };
@@ -0,0 +1,19 @@
1
+ import { ChartValueUnit } from "./types";
2
+ import type { ChartLabelFormatter, ChartValueFormatter } from "./types";
3
+ /**
4
+ * Format a value with a built-in unit.
5
+ *
6
+ * `PERCENT` takes a 0–100 value rather than a 0–1 fraction, matching how
7
+ * percentage data usually arrives, and appends the sign itself instead of using
8
+ * `style: "percent"` (which would divide by 100).
9
+ */
10
+ export declare function formatChartValue(value: number, unit: ChartValueUnit): string;
11
+ /**
12
+ * Pick the effective value formatter.
13
+ *
14
+ * An explicit `valueFormatter` always wins; otherwise the unit supplies a
15
+ * default, and `PLAIN` is the fallback when neither is given.
16
+ */
17
+ export declare function resolveValueFormatter(valueFormatter?: ChartValueFormatter, unit?: ChartValueUnit): ChartValueFormatter;
18
+ /** Pick the effective label formatter, defaulting to identity. */
19
+ export declare function resolveLabelFormatter(labelFormatter?: ChartLabelFormatter): ChartLabelFormatter;