@backstage-community/plugin-apiiro 0.1.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.
- package/CHANGELOG.md +12 -0
- package/README.md +232 -0
- package/config.d.ts +30 -0
- package/dist/App.esm.js +12 -0
- package/dist/App.esm.js.map +1 -0
- package/dist/api/index.esm.js +71 -0
- package/dist/api/index.esm.js.map +1 -0
- package/dist/assets/BulleyeIcon.esm.js +454 -0
- package/dist/assets/BulleyeIcon.esm.js.map +1 -0
- package/dist/assets/NoResultIcon.esm.js +146 -0
- package/dist/assets/NoResultIcon.esm.js.map +1 -0
- package/dist/assets/RiskIcon.esm.js +27 -0
- package/dist/assets/RiskIcon.esm.js.map +1 -0
- package/dist/assets/SettingIcon.esm.js +49 -0
- package/dist/assets/SettingIcon.esm.js.map +1 -0
- package/dist/assets/apiiroLogo/apiiroLogo.esm.js +21 -0
- package/dist/assets/apiiroLogo/apiiroLogo.esm.js.map +1 -0
- package/dist/assets/apiiroLogo/apiiroSidebar.esm.js +23 -0
- package/dist/assets/apiiroLogo/apiiroSidebar.esm.js.map +1 -0
- package/dist/assets/apiiroLogo/apiiroSmall.esm.js +19 -0
- package/dist/assets/apiiroLogo/apiiroSmall.esm.js.map +1 -0
- package/dist/assets/languageIcons/C.esm.js +7 -0
- package/dist/assets/languageIcons/C.esm.js.map +1 -0
- package/dist/assets/languageIcons/Cicd.esm.js +7 -0
- package/dist/assets/languageIcons/Cicd.esm.js.map +1 -0
- package/dist/assets/languageIcons/Clojure.esm.js +7 -0
- package/dist/assets/languageIcons/Clojure.esm.js.map +1 -0
- package/dist/assets/languageIcons/Cpp.esm.js +7 -0
- package/dist/assets/languageIcons/Cpp.esm.js.map +1 -0
- package/dist/assets/languageIcons/Csharp.esm.js +7 -0
- package/dist/assets/languageIcons/Csharp.esm.js.map +1 -0
- package/dist/assets/languageIcons/Dart.esm.js +7 -0
- package/dist/assets/languageIcons/Dart.esm.js.map +1 -0
- package/dist/assets/languageIcons/Go.esm.js +7 -0
- package/dist/assets/languageIcons/Go.esm.js.map +1 -0
- package/dist/assets/languageIcons/Groovy.esm.js +7 -0
- package/dist/assets/languageIcons/Groovy.esm.js.map +1 -0
- package/dist/assets/languageIcons/HTML.esm.js +7 -0
- package/dist/assets/languageIcons/HTML.esm.js.map +1 -0
- package/dist/assets/languageIcons/HclLanguage.esm.js +7 -0
- package/dist/assets/languageIcons/HclLanguage.esm.js.map +1 -0
- package/dist/assets/languageIcons/Java.esm.js +7 -0
- package/dist/assets/languageIcons/Java.esm.js.map +1 -0
- package/dist/assets/languageIcons/Javascript.esm.js +7 -0
- package/dist/assets/languageIcons/Javascript.esm.js.map +1 -0
- package/dist/assets/languageIcons/Kotlin.esm.js +7 -0
- package/dist/assets/languageIcons/Kotlin.esm.js.map +1 -0
- package/dist/assets/languageIcons/ObjectiveC.esm.js +7 -0
- package/dist/assets/languageIcons/ObjectiveC.esm.js.map +1 -0
- package/dist/assets/languageIcons/PHP.esm.js +7 -0
- package/dist/assets/languageIcons/PHP.esm.js.map +1 -0
- package/dist/assets/languageIcons/Perl.esm.js +13 -0
- package/dist/assets/languageIcons/Perl.esm.js.map +1 -0
- package/dist/assets/languageIcons/Python.esm.js +7 -0
- package/dist/assets/languageIcons/Python.esm.js.map +1 -0
- package/dist/assets/languageIcons/Ruby.esm.js +7 -0
- package/dist/assets/languageIcons/Ruby.esm.js.map +1 -0
- package/dist/assets/languageIcons/Rust.esm.js +7 -0
- package/dist/assets/languageIcons/Rust.esm.js.map +1 -0
- package/dist/assets/languageIcons/Scala.esm.js +7 -0
- package/dist/assets/languageIcons/Scala.esm.js.map +1 -0
- package/dist/assets/languageIcons/Swift.esm.js +7 -0
- package/dist/assets/languageIcons/Swift.esm.js.map +1 -0
- package/dist/assets/languageIcons/Terraform.esm.js +7 -0
- package/dist/assets/languageIcons/Terraform.esm.js.map +1 -0
- package/dist/assets/languageIcons/Typescript.esm.js +7 -0
- package/dist/assets/languageIcons/Typescript.esm.js.map +1 -0
- package/dist/assets/languageIcons/Unknown.esm.js +7 -0
- package/dist/assets/languageIcons/Unknown.esm.js.map +1 -0
- package/dist/assets/languageIcons/VB.esm.js +10 -0
- package/dist/assets/languageIcons/VB.esm.js.map +1 -0
- package/dist/assets/languageIcons/YAML.esm.js +7 -0
- package/dist/assets/languageIcons/YAML.esm.js.map +1 -0
- package/dist/assets/providerIcons/Azure.esm.js +7 -0
- package/dist/assets/providerIcons/Azure.esm.js.map +1 -0
- package/dist/assets/providerIcons/Bitbucket.esm.js +7 -0
- package/dist/assets/providerIcons/Bitbucket.esm.js.map +1 -0
- package/dist/assets/providerIcons/Gitlab.esm.js +7 -0
- package/dist/assets/providerIcons/Gitlab.esm.js.map +1 -0
- package/dist/components/ApiiroSidebar.esm.js +10 -0
- package/dist/components/ApiiroSidebar.esm.js.map +1 -0
- package/dist/components/ApplicationsList/ApplicationsList.esm.js +196 -0
- package/dist/components/ApplicationsList/ApplicationsList.esm.js.map +1 -0
- package/dist/components/CalendarDatePicker.esm.js +154 -0
- package/dist/components/CalendarDatePicker.esm.js.map +1 -0
- package/dist/components/CalendarDatePicker.styles.esm.js +198 -0
- package/dist/components/CalendarDatePicker.styles.esm.js.map +1 -0
- package/dist/components/Chip.esm.js +60 -0
- package/dist/components/Chip.esm.js.map +1 -0
- package/dist/components/ChipsList.esm.js +207 -0
- package/dist/components/ChipsList.esm.js.map +1 -0
- package/dist/components/ComponentDisplay.esm.js +42 -0
- package/dist/components/ComponentDisplay.esm.js.map +1 -0
- package/dist/components/DataGrid/CustomColumnMenu.esm.js +29 -0
- package/dist/components/DataGrid/CustomColumnMenu.esm.js.map +1 -0
- package/dist/components/DataGrid/CustomPagination.esm.js +113 -0
- package/dist/components/DataGrid/CustomPagination.esm.js.map +1 -0
- package/dist/components/DataGrid/CustomSearchToolbar.esm.js +117 -0
- package/dist/components/DataGrid/CustomSearchToolbar.esm.js.map +1 -0
- package/dist/components/DataGrid/DataGrid.esm.js +336 -0
- package/dist/components/DataGrid/DataGrid.esm.js.map +1 -0
- package/dist/components/DataGrid/PinColumnMenuItem.esm.js +24 -0
- package/dist/components/DataGrid/PinColumnMenuItem.esm.js.map +1 -0
- package/dist/components/DueDate.esm.js +34 -0
- package/dist/components/DueDate.esm.js.map +1 -0
- package/dist/components/Header.esm.js +27 -0
- package/dist/components/Header.esm.js.map +1 -0
- package/dist/components/MainContributors/MainContributors.esm.js +62 -0
- package/dist/components/MainContributors/MainContributors.esm.js.map +1 -0
- package/dist/components/MetricsGroup/TabMetricsGroup.esm.js +37 -0
- package/dist/components/MetricsGroup/TabMetricsGroup.esm.js.map +1 -0
- package/dist/components/MetricsGroup/WidgetMetricsGroup.esm.js +36 -0
- package/dist/components/MetricsGroup/WidgetMetricsGroup.esm.js.map +1 -0
- package/dist/components/RepositoryDisplay/RepositoryDisplay.esm.js +121 -0
- package/dist/components/RepositoryDisplay/RepositoryDisplay.esm.js.map +1 -0
- package/dist/components/RiskLevel.esm.js +88 -0
- package/dist/components/RiskLevel.esm.js.map +1 -0
- package/dist/components/RiskStatus.esm.js +58 -0
- package/dist/components/RiskStatus.esm.js.map +1 -0
- package/dist/components/SimpleTooltip.esm.js +24 -0
- package/dist/components/SimpleTooltip.esm.js.map +1 -0
- package/dist/components/SourcesDisplay.esm.js +47 -0
- package/dist/components/SourcesDisplay.esm.js.map +1 -0
- package/dist/components/TagsList/TagsList.esm.js +38 -0
- package/dist/components/TagsList/TagsList.esm.js.map +1 -0
- package/dist/components/TeamsDisplay.esm.js +47 -0
- package/dist/components/TeamsDisplay.esm.js.map +1 -0
- package/dist/components/charts/ColumnChart.esm.js +402 -0
- package/dist/components/charts/ColumnChart.esm.js.map +1 -0
- package/dist/components/charts/GaugeChart.esm.js +249 -0
- package/dist/components/charts/GaugeChart.esm.js.map +1 -0
- package/dist/components/charts/LineChart.esm.js +328 -0
- package/dist/components/charts/LineChart.esm.js.map +1 -0
- package/dist/components/charts/PieChart.esm.js +233 -0
- package/dist/components/charts/PieChart.esm.js.map +1 -0
- package/dist/components/common/ChartBox.esm.js +88 -0
- package/dist/components/common/ChartBox.esm.js.map +1 -0
- package/dist/components/common/CustomTooltip.esm.js +255 -0
- package/dist/components/common/CustomTooltip.esm.js.map +1 -0
- package/dist/components/common/ErrorSnackbar.esm.js +39 -0
- package/dist/components/common/ErrorSnackbar.esm.js.map +1 -0
- package/dist/components/common/NotFound.esm.js +30 -0
- package/dist/components/common/NotFound.esm.js.map +1 -0
- package/dist/components/common/SomethingWentWrong.esm.js +35 -0
- package/dist/components/common/SomethingWentWrong.esm.js.map +1 -0
- package/dist/components/common/languageIcons.esm.js +61 -0
- package/dist/components/common/languageIcons.esm.js.map +1 -0
- package/dist/components/common/logoSpinner.esm.js +28 -0
- package/dist/components/common/logoSpinner.esm.js.map +1 -0
- package/dist/components/common/scmProviders.esm.js +41 -0
- package/dist/components/common/scmProviders.esm.js.map +1 -0
- package/dist/components/filters/DiscoveredOnFilter.esm.js +284 -0
- package/dist/components/filters/DiscoveredOnFilter.esm.js.map +1 -0
- package/dist/components/filters/FilterDropdown.esm.js +325 -0
- package/dist/components/filters/FilterDropdown.esm.js.map +1 -0
- package/dist/components/filters/FilterDropdownClear.esm.js +45 -0
- package/dist/components/filters/FilterDropdownClear.esm.js.map +1 -0
- package/dist/components/filters/FilterDropdownList.esm.js +102 -0
- package/dist/components/filters/FilterDropdownList.esm.js.map +1 -0
- package/dist/components/filters/FilterDropdownSearch.esm.js +65 -0
- package/dist/components/filters/FilterDropdownSearch.esm.js.map +1 -0
- package/dist/components/filters/RiskInsightFilter.esm.js +579 -0
- package/dist/components/filters/RiskInsightFilter.esm.js.map +1 -0
- package/dist/components/tiles/MttrVsSLATile.esm.js +170 -0
- package/dist/components/tiles/MttrVsSLATile.esm.js.map +1 -0
- package/dist/components/tiles/RiskOverTimeTile.esm.js +311 -0
- package/dist/components/tiles/RiskOverTimeTile.esm.js.map +1 -0
- package/dist/components/tiles/SLAAdherenceTile.esm.js +115 -0
- package/dist/components/tiles/SLAAdherenceTile.esm.js.map +1 -0
- package/dist/components/tiles/StatusTile.esm.js +235 -0
- package/dist/components/tiles/StatusTile.esm.js.map +1 -0
- package/dist/components/tiles/TopLanguagesTile.esm.js +234 -0
- package/dist/components/tiles/TopLanguagesTile.esm.js.map +1 -0
- package/dist/components/tiles/TopRiskTile.esm.js +208 -0
- package/dist/components/tiles/TopRiskTile.esm.js.map +1 -0
- package/dist/hooks/useUrlFilters.esm.js +102 -0
- package/dist/hooks/useUrlFilters.esm.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.esm.js +42 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/pages/Repositories/Repositories.esm.js +102 -0
- package/dist/pages/Repositories/Repositories.esm.js.map +1 -0
- package/dist/pages/Repositories/tableConfig.esm.js +294 -0
- package/dist/pages/Repositories/tableConfig.esm.js.map +1 -0
- package/dist/pages/Risks/Risks.esm.js +258 -0
- package/dist/pages/Risks/Risks.esm.js.map +1 -0
- package/dist/pages/Risks/tableConfig.esm.js +305 -0
- package/dist/pages/Risks/tableConfig.esm.js.map +1 -0
- package/dist/pages/tab/Tab.esm.js +147 -0
- package/dist/pages/tab/Tab.esm.js.map +1 -0
- package/dist/pages/tab/TabProvider.esm.js +11 -0
- package/dist/pages/tab/TabProvider.esm.js.map +1 -0
- package/dist/pages/widget/Widget.esm.js +161 -0
- package/dist/pages/widget/Widget.esm.js.map +1 -0
- package/dist/pages/widget/WidgetProvider.esm.js +12 -0
- package/dist/pages/widget/WidgetProvider.esm.js.map +1 -0
- package/dist/plugin.esm.js +30 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/queries/filterOptions.queries.esm.js +46 -0
- package/dist/queries/filterOptions.queries.esm.js.map +1 -0
- package/dist/queries/mttr-statistics.queries.esm.js +61 -0
- package/dist/queries/mttr-statistics.queries.esm.js.map +1 -0
- package/dist/queries/repository.queries.esm.js +60 -0
- package/dist/queries/repository.queries.esm.js.map +1 -0
- package/dist/queries/risk-score-over-time.queries.esm.js +61 -0
- package/dist/queries/risk-score-over-time.queries.esm.js.map +1 -0
- package/dist/queries/risks.queries.esm.js +65 -0
- package/dist/queries/risks.queries.esm.js.map +1 -0
- package/dist/queries/sla-breach.queries.esm.js +57 -0
- package/dist/queries/sla-breach.queries.esm.js.map +1 -0
- package/dist/queries/top-risks.queries.esm.js +47 -0
- package/dist/queries/top-risks.queries.esm.js.map +1 -0
- package/dist/routes.esm.js +8 -0
- package/dist/routes.esm.js.map +1 -0
- package/dist/theme/themeUtils.esm.js +290 -0
- package/dist/theme/themeUtils.esm.js.map +1 -0
- package/dist/utils/dateFormatter.esm.js +67 -0
- package/dist/utils/dateFormatter.esm.js.map +1 -0
- package/dist/utils/numberFormatter.esm.js +21 -0
- package/dist/utils/numberFormatter.esm.js.map +1 -0
- package/dist/utils/utils.esm.js +27 -0
- package/dist/utils/utils.esm.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import Box from '@mui/material/Box';
|
|
3
|
+
import { ChipsList } from './ChipsList.esm.js';
|
|
4
|
+
|
|
5
|
+
const TeamsDisplay = ({
|
|
6
|
+
teams,
|
|
7
|
+
maxVisible = 1,
|
|
8
|
+
size = "small",
|
|
9
|
+
variant = "outlined",
|
|
10
|
+
gap = 0.5
|
|
11
|
+
}) => {
|
|
12
|
+
if (!teams || teams.length === 0) {
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
const teamItems = teams.map((team) => ({
|
|
16
|
+
id: team.name,
|
|
17
|
+
label: team.name,
|
|
18
|
+
href: team.apiiroUrl,
|
|
19
|
+
target: "_blank",
|
|
20
|
+
rel: "noopener noreferrer"
|
|
21
|
+
}));
|
|
22
|
+
return /* @__PURE__ */ jsx(
|
|
23
|
+
Box,
|
|
24
|
+
{
|
|
25
|
+
sx: {
|
|
26
|
+
display: "flex",
|
|
27
|
+
justifyContent: "center",
|
|
28
|
+
alignItems: "center",
|
|
29
|
+
width: "100%",
|
|
30
|
+
height: "100%"
|
|
31
|
+
},
|
|
32
|
+
children: /* @__PURE__ */ jsx(
|
|
33
|
+
ChipsList,
|
|
34
|
+
{
|
|
35
|
+
items: teamItems,
|
|
36
|
+
maxVisible,
|
|
37
|
+
size,
|
|
38
|
+
variant,
|
|
39
|
+
gap
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { TeamsDisplay, TeamsDisplay as default };
|
|
47
|
+
//# sourceMappingURL=TeamsDisplay.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TeamsDisplay.esm.js","sources":["../../src/components/TeamsDisplay.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport Box from '@mui/material/Box';\nimport { ChipsList } from './ChipsList';\n\ninterface Team {\n name: string;\n apiiroUrl?: string;\n}\n\ninterface TeamsDisplayProps {\n /**\n * Array of team objects\n */\n teams: Team[];\n\n /**\n * Maximum number of teams to show before displaying +N\n */\n maxVisible?: number;\n\n /**\n * Size of the team chips\n */\n size?: 'small' | 'medium';\n\n /**\n * Variant of the team chips\n */\n variant?: 'filled' | 'outlined';\n\n /**\n * Gap between chips\n */\n gap?: number;\n}\n\n/**\n * TeamsDisplay component that renders team names as clickable chips\n *\n * @example\n * <TeamsDisplay\n * teams={[\n * { name: 'Team A', apiiroUrl: 'https://example.com/team-a' },\n * { name: 'Team B', apiiroUrl: 'https://example.com/team-b' }\n * ]}\n * maxVisible={2}\n * />\n */\nexport const TeamsDisplay = ({\n teams,\n maxVisible = 1,\n size = 'small',\n variant = 'outlined',\n gap = 0.5,\n}: TeamsDisplayProps) => {\n if (!teams || teams.length === 0) {\n return '';\n }\n\n const teamItems = teams.map(team => ({\n id: team.name,\n label: team.name,\n href: team.apiiroUrl,\n target: '_blank' as const,\n rel: 'noopener noreferrer',\n }));\n\n return (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n width: '100%',\n height: '100%',\n }}\n >\n <ChipsList\n items={teamItems}\n maxVisible={maxVisible}\n size={size}\n variant={variant}\n gap={gap}\n />\n </Box>\n );\n};\n\nexport default TeamsDisplay;\n"],"names":[],"mappings":";;;;AA8DO,MAAM,eAAe,CAAC;AAAA,EAC3B,KAAA;AAAA,EACA,UAAA,GAAa,CAAA;AAAA,EACb,IAAA,GAAO,OAAA;AAAA,EACP,OAAA,GAAU,UAAA;AAAA,EACV,GAAA,GAAM;AACR,CAAA,KAAyB;AACvB,EAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAChC,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,GAAA,CAAI,CAAA,IAAA,MAAS;AAAA,IACnC,IAAI,IAAA,CAAK,IAAA;AAAA,IACT,OAAO,IAAA,CAAK,IAAA;AAAA,IACZ,MAAM,IAAA,CAAK,SAAA;AAAA,IACX,MAAA,EAAQ,QAAA;AAAA,IACR,GAAA,EAAK;AAAA,GACP,CAAE,CAAA;AAEF,EAAA,uBACE,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,EAAA,EAAI;AAAA,QACF,OAAA,EAAS,MAAA;AAAA,QACT,cAAA,EAAgB,QAAA;AAAA,QAChB,UAAA,EAAY,QAAA;AAAA,QACZ,KAAA,EAAO,MAAA;AAAA,QACP,MAAA,EAAQ;AAAA,OACV;AAAA,MAEA,QAAA,kBAAA,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,SAAA;AAAA,UACP,UAAA;AAAA,UACA,IAAA;AAAA,UACA,OAAA;AAAA,UACA;AAAA;AAAA;AACF;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useState, useEffect, useMemo } from 'react';
|
|
3
|
+
import { BarChart } from '@mui/x-charts/BarChart';
|
|
4
|
+
import { axisClasses } from '@mui/x-charts/ChartsAxis';
|
|
5
|
+
import Box from '@mui/material/Box';
|
|
6
|
+
import { styled, useTheme } from '@mui/material/styles';
|
|
7
|
+
import { formatNumberWithSuffix } from '../../utils/numberFormatter.esm.js';
|
|
8
|
+
|
|
9
|
+
const formatValue = (value) => {
|
|
10
|
+
if (value === null || value === void 0) return "";
|
|
11
|
+
return formatNumberWithSuffix(value, 0);
|
|
12
|
+
};
|
|
13
|
+
const CustomLegendContainer = styled(Box)(() => ({
|
|
14
|
+
display: "flex",
|
|
15
|
+
justifyContent: "center",
|
|
16
|
+
alignItems: "center",
|
|
17
|
+
gap: "8px",
|
|
18
|
+
flexWrap: "wrap",
|
|
19
|
+
maxWidth: "100%",
|
|
20
|
+
padding: "4px 8px",
|
|
21
|
+
boxSizing: "border-box"
|
|
22
|
+
}));
|
|
23
|
+
const LegendItem = styled(Box)(() => ({
|
|
24
|
+
display: "flex",
|
|
25
|
+
alignItems: "center",
|
|
26
|
+
gap: "6px",
|
|
27
|
+
flexShrink: 0,
|
|
28
|
+
whiteSpace: "nowrap"
|
|
29
|
+
}));
|
|
30
|
+
const LegendLine = styled(Box)(({ color }) => ({
|
|
31
|
+
width: "16px",
|
|
32
|
+
height: "3px",
|
|
33
|
+
backgroundColor: color,
|
|
34
|
+
borderRadius: "1px",
|
|
35
|
+
flexShrink: 0
|
|
36
|
+
}));
|
|
37
|
+
const LegendText = styled("p")(({ theme }) => ({
|
|
38
|
+
fontSize: "11px",
|
|
39
|
+
color: theme.palette.text.secondary,
|
|
40
|
+
fontWeight: 400,
|
|
41
|
+
lineHeight: 1.2,
|
|
42
|
+
margin: 0,
|
|
43
|
+
whiteSpace: "nowrap",
|
|
44
|
+
overflow: "hidden",
|
|
45
|
+
textOverflow: "ellipsis",
|
|
46
|
+
maxWidth: "200px",
|
|
47
|
+
minWidth: "40px"
|
|
48
|
+
}));
|
|
49
|
+
const ColumnChart = ({
|
|
50
|
+
data,
|
|
51
|
+
width = 400,
|
|
52
|
+
height = 300,
|
|
53
|
+
maxValue,
|
|
54
|
+
showLegend = true,
|
|
55
|
+
legendPosition = "bottom"
|
|
56
|
+
}) => {
|
|
57
|
+
const theme = useTheme();
|
|
58
|
+
const containerRef = useRef(null);
|
|
59
|
+
const [containerWidth, setContainerWidth] = useState(width);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
const updateWidth = () => {
|
|
62
|
+
if (containerRef.current) {
|
|
63
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
64
|
+
setContainerWidth(rect.width || width);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
updateWidth();
|
|
68
|
+
window.addEventListener("resize", updateWidth);
|
|
69
|
+
return () => window.removeEventListener("resize", updateWidth);
|
|
70
|
+
}, [width]);
|
|
71
|
+
const { xAxisData, series, colors, responsiveConfig } = useMemo(() => {
|
|
72
|
+
const categories = data.map((item) => item.category);
|
|
73
|
+
const allLabels = Array.from(
|
|
74
|
+
new Set(data.flatMap((item) => item.values.map((v) => v.label)))
|
|
75
|
+
);
|
|
76
|
+
const chartSeries = allLabels.map((label) => {
|
|
77
|
+
const seriesData = data.map((item) => {
|
|
78
|
+
const value = item.values.find((v) => v.label === label);
|
|
79
|
+
return value ? value.value : 0;
|
|
80
|
+
});
|
|
81
|
+
const color = data.flatMap((item) => item.values).find((value) => value.label === label)?.color || theme.palette.grey[400];
|
|
82
|
+
return {
|
|
83
|
+
data: seriesData,
|
|
84
|
+
label,
|
|
85
|
+
id: label,
|
|
86
|
+
color,
|
|
87
|
+
valueFormatter: (v) => v !== null ? formatValue(v) : ""
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
const seriesColors = allLabels.map((label) => {
|
|
91
|
+
return data.flatMap((item) => item.values).find((value) => value.label === label)?.color || theme.palette.grey[400];
|
|
92
|
+
});
|
|
93
|
+
const numCategories = categories.length;
|
|
94
|
+
const numSeries = allLabels.length;
|
|
95
|
+
const actualWidth = typeof containerWidth === "number" ? containerWidth : width;
|
|
96
|
+
const availableWidth = actualWidth - 80;
|
|
97
|
+
const totalBarsPerCategory = numSeries;
|
|
98
|
+
const isSmall = availableWidth < 300;
|
|
99
|
+
const isMedium = availableWidth >= 300 && availableWidth < 450;
|
|
100
|
+
let minColumnWidth;
|
|
101
|
+
let maxColumnWidth;
|
|
102
|
+
let categoryGap;
|
|
103
|
+
let transformScale;
|
|
104
|
+
if (isSmall) {
|
|
105
|
+
minColumnWidth = 6;
|
|
106
|
+
maxColumnWidth = 12;
|
|
107
|
+
categoryGap = Math.max(15, availableWidth * 0.08);
|
|
108
|
+
transformScale = 0.2;
|
|
109
|
+
} else if (isMedium) {
|
|
110
|
+
minColumnWidth = 8;
|
|
111
|
+
maxColumnWidth = 16;
|
|
112
|
+
categoryGap = Math.max(20, availableWidth * 0.1);
|
|
113
|
+
transformScale = 0.25;
|
|
114
|
+
} else {
|
|
115
|
+
minColumnWidth = 10;
|
|
116
|
+
maxColumnWidth = 20;
|
|
117
|
+
categoryGap = Math.max(25, availableWidth * 0.12);
|
|
118
|
+
transformScale = 0.3;
|
|
119
|
+
}
|
|
120
|
+
const totalCategoryGaps = (numCategories - 1) * categoryGap;
|
|
121
|
+
const remainingWidth = availableWidth - totalCategoryGaps;
|
|
122
|
+
const widthPerCategory = remainingWidth / numCategories;
|
|
123
|
+
const barGapInCategory = Math.max(2, widthPerCategory * 0.05);
|
|
124
|
+
const totalBarGapsInCategory = (totalBarsPerCategory - 1) * barGapInCategory;
|
|
125
|
+
const availableWidthForBars = widthPerCategory - totalBarGapsInCategory;
|
|
126
|
+
const calculatedBarWidth = availableWidthForBars / totalBarsPerCategory;
|
|
127
|
+
const finalColumnWidth = Math.max(
|
|
128
|
+
minColumnWidth,
|
|
129
|
+
Math.min(calculatedBarWidth, maxColumnWidth)
|
|
130
|
+
);
|
|
131
|
+
if (calculatedBarWidth < minColumnWidth) {
|
|
132
|
+
transformScale = Math.max(0.15, transformScale * 0.8);
|
|
133
|
+
}
|
|
134
|
+
const leftMargin = isSmall ? 35 : 40;
|
|
135
|
+
const rightMargin = isSmall ? 5 : Math.max(10, (actualWidth - availableWidth - leftMargin) / 2);
|
|
136
|
+
return {
|
|
137
|
+
xAxisData: categories,
|
|
138
|
+
series: chartSeries,
|
|
139
|
+
colors: seriesColors,
|
|
140
|
+
responsiveConfig: {
|
|
141
|
+
columnWidth: finalColumnWidth,
|
|
142
|
+
transformScale: Math.max(0.15, Math.min(transformScale, 0.4)),
|
|
143
|
+
leftMargin,
|
|
144
|
+
rightMargin
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}, [data, width, containerWidth, theme.palette.grey]);
|
|
148
|
+
const yAxisMax = useMemo(() => {
|
|
149
|
+
if (maxValue) return maxValue;
|
|
150
|
+
const allValues = data.flatMap((item) => item.values.map((v) => v.value));
|
|
151
|
+
const max = Math.max(...allValues);
|
|
152
|
+
const paddedMax = max * 1.15;
|
|
153
|
+
const magnitude = Math.pow(10, Math.floor(Math.log10(paddedMax)) - 1);
|
|
154
|
+
const roundedMax = Math.ceil(paddedMax / magnitude) * magnitude;
|
|
155
|
+
if (roundedMax - max < max * 0.1) {
|
|
156
|
+
return roundedMax + magnitude;
|
|
157
|
+
}
|
|
158
|
+
return roundedMax;
|
|
159
|
+
}, [data, maxValue]);
|
|
160
|
+
const yTickValues = useMemo(() => {
|
|
161
|
+
const yMax = yAxisMax;
|
|
162
|
+
return [0, yMax / 3, 2 * yMax / 3, yMax].map(
|
|
163
|
+
(num) => Math.ceil(num / 10) * 10
|
|
164
|
+
);
|
|
165
|
+
}, [yAxisMax]);
|
|
166
|
+
const legendItems = useMemo(() => {
|
|
167
|
+
const labelSet = /* @__PURE__ */ new Set();
|
|
168
|
+
const items = [];
|
|
169
|
+
data.forEach((item) => {
|
|
170
|
+
item.values.forEach((value) => {
|
|
171
|
+
if (!labelSet.has(value.label)) {
|
|
172
|
+
labelSet.add(value.label);
|
|
173
|
+
items.push({ label: value.label, color: value.color });
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
return items;
|
|
178
|
+
}, [data]);
|
|
179
|
+
const customLegend = showLegend && /* @__PURE__ */ jsx(CustomLegendContainer, { children: legendItems.map((item) => {
|
|
180
|
+
return /* @__PURE__ */ jsxs(LegendItem, { children: [
|
|
181
|
+
/* @__PURE__ */ jsx(LegendLine, { color: item.color }),
|
|
182
|
+
/* @__PURE__ */ jsx(LegendText, { title: item.label, children: item.label })
|
|
183
|
+
] }, item.label);
|
|
184
|
+
}) });
|
|
185
|
+
return /* @__PURE__ */ jsxs(
|
|
186
|
+
Box,
|
|
187
|
+
{
|
|
188
|
+
ref: containerRef,
|
|
189
|
+
sx: {
|
|
190
|
+
width: "100%",
|
|
191
|
+
height: "100%",
|
|
192
|
+
display: "flex",
|
|
193
|
+
flexDirection: "column",
|
|
194
|
+
overflow: "hidden",
|
|
195
|
+
position: "relative"
|
|
196
|
+
},
|
|
197
|
+
children: [
|
|
198
|
+
legendPosition === "top" && customLegend,
|
|
199
|
+
/* @__PURE__ */ jsx(Box, { sx: { flex: 1, minHeight: 0 }, children: /* @__PURE__ */ jsx(
|
|
200
|
+
BarChart,
|
|
201
|
+
{
|
|
202
|
+
width: typeof containerWidth === "number" ? containerWidth : width,
|
|
203
|
+
height: showLegend && legendPosition === "bottom" ? height - 35 : height,
|
|
204
|
+
series: series.map((s) => ({
|
|
205
|
+
...s,
|
|
206
|
+
valueFormatter: formatValue
|
|
207
|
+
})),
|
|
208
|
+
xAxis: [
|
|
209
|
+
{
|
|
210
|
+
data: xAxisData,
|
|
211
|
+
scaleType: "band",
|
|
212
|
+
disableLine: true,
|
|
213
|
+
disableTicks: true
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
yAxis: [
|
|
217
|
+
{
|
|
218
|
+
max: yAxisMax,
|
|
219
|
+
tickNumber: yTickValues.length,
|
|
220
|
+
data: yTickValues,
|
|
221
|
+
valueFormatter: formatValue,
|
|
222
|
+
disableLine: true,
|
|
223
|
+
disableTicks: true
|
|
224
|
+
}
|
|
225
|
+
],
|
|
226
|
+
margin: {
|
|
227
|
+
left: responsiveConfig.leftMargin,
|
|
228
|
+
right: responsiveConfig.rightMargin,
|
|
229
|
+
top: 10,
|
|
230
|
+
bottom: 35
|
|
231
|
+
},
|
|
232
|
+
skipAnimation: false,
|
|
233
|
+
colors,
|
|
234
|
+
legend: { hidden: true },
|
|
235
|
+
grid: { horizontal: true, vertical: false },
|
|
236
|
+
sx: {
|
|
237
|
+
[`.${axisClasses.left} .${axisClasses.label}`]: {
|
|
238
|
+
transform: "translate(-10px, 0)"
|
|
239
|
+
},
|
|
240
|
+
[`.${axisClasses.bottom} .${axisClasses.label}`]: {
|
|
241
|
+
fontSize: "12px"
|
|
242
|
+
},
|
|
243
|
+
[`.${axisClasses.left} .${axisClasses.line}`]: {
|
|
244
|
+
display: "none"
|
|
245
|
+
},
|
|
246
|
+
[`.${axisClasses.bottom} .${axisClasses.line}`]: {
|
|
247
|
+
display: "none"
|
|
248
|
+
},
|
|
249
|
+
[`.${axisClasses.left} .${axisClasses.tick}`]: {
|
|
250
|
+
display: "none"
|
|
251
|
+
},
|
|
252
|
+
[`.${axisClasses.bottom} .${axisClasses.tick}`]: {
|
|
253
|
+
display: "none"
|
|
254
|
+
},
|
|
255
|
+
"& .MuiChartsGrid-line": {
|
|
256
|
+
strokeDasharray: "3 3",
|
|
257
|
+
stroke: theme.palette.divider,
|
|
258
|
+
strokeWidth: 1
|
|
259
|
+
},
|
|
260
|
+
"& .MuiBarElement-root": {
|
|
261
|
+
transformOrigin: "center bottom",
|
|
262
|
+
transform: `scaleX(${responsiveConfig.transformScale})`
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
tooltip: {
|
|
266
|
+
axisContent: (props) => {
|
|
267
|
+
const dataIndex = props?.dataIndex ?? 0;
|
|
268
|
+
const header = xAxisData[dataIndex] || props?.label;
|
|
269
|
+
return /* @__PURE__ */ jsx("div", { className: "MuiChartsTooltip-root", children: /* @__PURE__ */ jsx("table", { className: "MuiChartsTooltip-table", children: /* @__PURE__ */ jsxs("tbody", { children: [
|
|
270
|
+
/* @__PURE__ */ jsx("tr", { className: "MuiChartsTooltip-row", children: /* @__PURE__ */ jsx("td", { className: "MuiChartsTooltip-cell", colSpan: 2, children: header }) }),
|
|
271
|
+
series.map((s, idx) => {
|
|
272
|
+
const value = s.data?.[dataIndex];
|
|
273
|
+
let formatted;
|
|
274
|
+
if (typeof value === "number") {
|
|
275
|
+
formatted = formatValue(value);
|
|
276
|
+
} else if (value === null || value === void 0) {
|
|
277
|
+
formatted = "0";
|
|
278
|
+
} else {
|
|
279
|
+
formatted = String(value);
|
|
280
|
+
}
|
|
281
|
+
return /* @__PURE__ */ jsxs("tr", { className: "MuiChartsTooltip-row", children: [
|
|
282
|
+
/* @__PURE__ */ jsx(
|
|
283
|
+
"td",
|
|
284
|
+
{
|
|
285
|
+
className: "MuiChartsTooltip-labelCell",
|
|
286
|
+
style: {
|
|
287
|
+
"--series-color": s.color
|
|
288
|
+
},
|
|
289
|
+
children: s.label
|
|
290
|
+
}
|
|
291
|
+
),
|
|
292
|
+
/* @__PURE__ */ jsx("td", { className: "MuiChartsTooltip-valueCell", children: formatted })
|
|
293
|
+
] }, idx);
|
|
294
|
+
})
|
|
295
|
+
] }) }) });
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
slotProps: {
|
|
299
|
+
popper: {
|
|
300
|
+
placement: "auto",
|
|
301
|
+
modifiers: [
|
|
302
|
+
{
|
|
303
|
+
name: "flip",
|
|
304
|
+
enabled: true,
|
|
305
|
+
options: {
|
|
306
|
+
fallbackPlacements: ["top", "bottom", "right", "left"],
|
|
307
|
+
allowedAutoPlacements: ["top", "bottom"]
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
name: "preventOverflow",
|
|
312
|
+
enabled: true,
|
|
313
|
+
options: {
|
|
314
|
+
boundary: "clippingParents",
|
|
315
|
+
padding: 8
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
name: "offset",
|
|
320
|
+
enabled: true,
|
|
321
|
+
options: {
|
|
322
|
+
offset: [-100, 10]
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
name: "arrow",
|
|
327
|
+
enabled: false
|
|
328
|
+
}
|
|
329
|
+
],
|
|
330
|
+
sx: {
|
|
331
|
+
"& .MuiChartsTooltip-root": {
|
|
332
|
+
backgroundColor: theme.palette.background.paper,
|
|
333
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
334
|
+
borderRadius: "12px",
|
|
335
|
+
filter: theme.palette.mode === "dark" ? "drop-shadow(0 4px 12px rgba(0,0,0,0.3))" : "drop-shadow(0 4px 12px rgba(0,0,0,0.1))",
|
|
336
|
+
padding: "12px 16px",
|
|
337
|
+
minWidth: "140px",
|
|
338
|
+
fontSize: "12px"
|
|
339
|
+
},
|
|
340
|
+
"& .MuiChartsTooltip-table": {
|
|
341
|
+
margin: 0,
|
|
342
|
+
borderSpacing: 0,
|
|
343
|
+
width: "100%"
|
|
344
|
+
},
|
|
345
|
+
"& .MuiChartsTooltip-row": {
|
|
346
|
+
"&:first-of-type": {
|
|
347
|
+
"& .MuiChartsTooltip-cell": {
|
|
348
|
+
fontSize: "16px",
|
|
349
|
+
fontWeight: 600,
|
|
350
|
+
color: theme.palette.text.secondary,
|
|
351
|
+
paddingBottom: "16px",
|
|
352
|
+
borderBottom: "none"
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
"&:not(:first-of-type)": {
|
|
356
|
+
"& .MuiChartsTooltip-cell": {
|
|
357
|
+
padding: "4px 0",
|
|
358
|
+
borderBottom: "none"
|
|
359
|
+
},
|
|
360
|
+
"& .MuiChartsTooltip-labelCell": {
|
|
361
|
+
position: "relative",
|
|
362
|
+
paddingLeft: "16px",
|
|
363
|
+
paddingRight: "4px",
|
|
364
|
+
paddingBottom: "8px",
|
|
365
|
+
fontSize: "14px",
|
|
366
|
+
color: theme.palette.text.secondary,
|
|
367
|
+
verticalAlign: "middle",
|
|
368
|
+
"&::before": {
|
|
369
|
+
content: '""',
|
|
370
|
+
position: "absolute",
|
|
371
|
+
left: "0",
|
|
372
|
+
top: "10%",
|
|
373
|
+
width: "3px",
|
|
374
|
+
height: "16px",
|
|
375
|
+
backgroundColor: "var(--series-color)",
|
|
376
|
+
borderRadius: "2px"
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
"& .MuiChartsTooltip-valueCell": {
|
|
380
|
+
fontSize: "14px",
|
|
381
|
+
fontWeight: 600,
|
|
382
|
+
color: theme.palette.text.secondary,
|
|
383
|
+
textAlign: "right",
|
|
384
|
+
paddingLeft: "4px",
|
|
385
|
+
paddingBottom: "8px",
|
|
386
|
+
verticalAlign: "middle"
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
) }),
|
|
395
|
+
legendPosition === "bottom" && customLegend
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
);
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
export { ColumnChart, ColumnChart as default };
|
|
402
|
+
//# sourceMappingURL=ColumnChart.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColumnChart.esm.js","sources":["../../../src/components/charts/ColumnChart.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useMemo, useRef, useEffect, useState } from 'react';\nimport { BarChart } from '@mui/x-charts/BarChart';\nimport { axisClasses } from '@mui/x-charts/ChartsAxis';\nimport Box from '@mui/material/Box';\nimport { styled, useTheme } from '@mui/material/styles';\nimport { formatNumberWithSuffix } from '../../utils/numberFormatter';\n\nexport interface ColumnData {\n category: string;\n values: {\n label: string;\n value: number;\n color: string;\n }[];\n}\n\nexport interface ColumnChartProps {\n data: ColumnData[];\n width?: number;\n height?: number;\n maxValue?: number;\n showLegend?: boolean;\n legendPosition?: 'top' | 'bottom';\n}\n\nconst formatValue = (value: number | null | undefined): string => {\n if (value === null || value === undefined) return '';\n return formatNumberWithSuffix(value, 0);\n};\n\nconst CustomLegendContainer = styled(Box)(() => ({\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n gap: '8px',\n flexWrap: 'wrap',\n maxWidth: '100%',\n padding: '4px 8px',\n boxSizing: 'border-box',\n}));\n\nconst LegendItem = styled(Box)(() => ({\n display: 'flex',\n alignItems: 'center',\n gap: '6px',\n flexShrink: 0,\n whiteSpace: 'nowrap',\n}));\n\nconst LegendLine = styled(Box)<{ color: string }>(({ color }) => ({\n width: '16px',\n height: '3px',\n backgroundColor: color,\n borderRadius: '1px',\n flexShrink: 0,\n}));\n\nconst LegendText = styled('p')(({ theme }) => ({\n fontSize: '11px',\n color: theme.palette.text.secondary,\n fontWeight: 400,\n lineHeight: 1.2,\n margin: 0,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n maxWidth: '200px',\n minWidth: '40px',\n}));\n\nexport const ColumnChart = ({\n data,\n width = 400,\n height = 300,\n maxValue,\n showLegend = true,\n legendPosition = 'bottom',\n}: ColumnChartProps) => {\n const theme = useTheme();\n const containerRef = useRef<HTMLDivElement>(null);\n const [containerWidth, setContainerWidth] = useState(width);\n\n // Track container width changes\n useEffect(() => {\n const updateWidth = () => {\n if (containerRef.current) {\n const rect = containerRef.current.getBoundingClientRect();\n setContainerWidth(rect.width || width);\n }\n };\n\n updateWidth();\n window.addEventListener('resize', updateWidth);\n return () => window.removeEventListener('resize', updateWidth);\n }, [width]);\n // Calculate responsive dimensions based on container width\n const { xAxisData, series, colors, responsiveConfig } = useMemo(() => {\n const categories = data.map(item => item.category);\n const allLabels = Array.from(\n new Set(data.flatMap(item => item.values.map(v => v.label))),\n );\n\n const chartSeries = allLabels.map(label => {\n const seriesData = data.map(item => {\n const value = item.values.find(v => v.label === label);\n return value ? value.value : 0;\n });\n\n const color =\n data.flatMap(item => item.values).find(value => value.label === label)\n ?.color || theme.palette.grey[400];\n\n return {\n data: seriesData,\n label,\n id: label,\n color,\n valueFormatter: (v: number | null) =>\n v !== null ? formatValue(v) : '',\n };\n });\n\n const seriesColors = allLabels.map(label => {\n return (\n data.flatMap(item => item.values).find(value => value.label === label)\n ?.color || theme.palette.grey[400]\n );\n });\n\n // Calculate responsive configuration\n const numCategories = categories.length;\n const numSeries = allLabels.length;\n const actualWidth =\n typeof containerWidth === 'number' ? containerWidth : width;\n const availableWidth = actualWidth - 80; // Reserve space for Y-axis labels and padding\n\n // Improved responsive calculation\n const totalBarsPerCategory = numSeries;\n\n // Define responsive breakpoints\n const isSmall = availableWidth < 300;\n const isMedium = availableWidth >= 300 && availableWidth < 450;\n\n // Adjust parameters based on container size\n let minColumnWidth;\n let maxColumnWidth;\n let categoryGap;\n let transformScale;\n\n if (isSmall) {\n // Small containers: prioritize fitting everything\n minColumnWidth = 6;\n maxColumnWidth = 12;\n categoryGap = Math.max(15, availableWidth * 0.08);\n transformScale = 0.2;\n } else if (isMedium) {\n // Medium containers: balanced approach\n minColumnWidth = 8;\n maxColumnWidth = 16;\n categoryGap = Math.max(20, availableWidth * 0.1);\n transformScale = 0.25;\n } else {\n // Large containers: optimal spacing\n minColumnWidth = 10;\n maxColumnWidth = 20;\n categoryGap = Math.max(25, availableWidth * 0.12);\n transformScale = 0.3;\n }\n\n // Calculate space distribution\n const totalCategoryGaps = (numCategories - 1) * categoryGap;\n const remainingWidth = availableWidth - totalCategoryGaps;\n const widthPerCategory = remainingWidth / numCategories;\n\n // Ensure minimum spacing between bars in same category\n const barGapInCategory = Math.max(2, widthPerCategory * 0.05);\n const totalBarGapsInCategory =\n (totalBarsPerCategory - 1) * barGapInCategory;\n const availableWidthForBars = widthPerCategory - totalBarGapsInCategory;\n const calculatedBarWidth = availableWidthForBars / totalBarsPerCategory;\n\n // Apply constraints\n const finalColumnWidth = Math.max(\n minColumnWidth,\n Math.min(calculatedBarWidth, maxColumnWidth),\n );\n\n // Adjust transform scale based on final calculations\n if (calculatedBarWidth < minColumnWidth) {\n transformScale = Math.max(0.15, transformScale * 0.8);\n }\n\n // Calculate responsive margins\n const leftMargin = isSmall ? 35 : 40;\n const rightMargin = isSmall\n ? 5\n : Math.max(10, (actualWidth - availableWidth - leftMargin) / 2);\n\n return {\n xAxisData: categories,\n series: chartSeries,\n colors: seriesColors,\n responsiveConfig: {\n columnWidth: finalColumnWidth,\n transformScale: Math.max(0.15, Math.min(transformScale, 0.4)),\n leftMargin,\n rightMargin,\n },\n };\n }, [data, width, containerWidth, theme.palette.grey]);\n\n const yAxisMax = useMemo(() => {\n if (maxValue) return maxValue;\n\n const allValues = data.flatMap(item => item.values.map(v => v.value));\n const max = Math.max(...allValues);\n\n // Add modest padding (15%) to ensure there's space above the highest bar\n const paddedMax = max * 1.15;\n\n // Find a nice round number that's close to the padded max\n const magnitude = Math.pow(10, Math.floor(Math.log10(paddedMax)) - 1);\n const roundedMax = Math.ceil(paddedMax / magnitude) * magnitude;\n\n // Ensure minimum padding - if rounded value is too close to max, add one more step\n if (roundedMax - max < max * 0.1) {\n return roundedMax + magnitude;\n }\n\n return roundedMax;\n }, [data, maxValue]);\n\n // Calculate custom Y-axis tick values\n const yTickValues = useMemo(() => {\n const yMax = yAxisMax;\n return [0, yMax / 3, (2 * yMax) / 3, yMax].map(\n num => Math.ceil(num / 10) * 10,\n );\n }, [yAxisMax]);\n\n // Get unique labels for custom legend\n const legendItems = useMemo(() => {\n const labelSet = new Set<string>();\n const items: { label: string; color: string }[] = [];\n\n data.forEach(item => {\n item.values.forEach(value => {\n if (!labelSet.has(value.label)) {\n labelSet.add(value.label);\n items.push({ label: value.label, color: value.color });\n }\n });\n });\n\n return items;\n }, [data]);\n\n // Create responsive legend based on container width\n const customLegend = showLegend && (\n <CustomLegendContainer>\n {legendItems.map(item => {\n return (\n <LegendItem key={item.label}>\n <LegendLine color={item.color} />\n <LegendText title={item.label}>{item.label}</LegendText>\n </LegendItem>\n );\n })}\n </CustomLegendContainer>\n );\n\n return (\n <Box\n ref={containerRef}\n sx={{\n width: '100%',\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n overflow: 'hidden',\n position: 'relative',\n }}\n >\n {legendPosition === 'top' && customLegend}\n\n <Box sx={{ flex: 1, minHeight: 0 }}>\n <BarChart\n width={typeof containerWidth === 'number' ? containerWidth : width}\n height={\n showLegend && legendPosition === 'bottom' ? height - 35 : height\n }\n series={series.map(s => ({\n ...s,\n valueFormatter: formatValue,\n }))}\n xAxis={[\n {\n data: xAxisData,\n scaleType: 'band',\n disableLine: true,\n disableTicks: true,\n },\n ]}\n yAxis={[\n {\n max: yAxisMax,\n tickNumber: yTickValues.length,\n data: yTickValues,\n valueFormatter: formatValue,\n disableLine: true,\n disableTicks: true,\n },\n ]}\n margin={{\n left: responsiveConfig.leftMargin,\n right: responsiveConfig.rightMargin,\n top: 10,\n bottom: 35,\n }}\n skipAnimation={false}\n colors={colors}\n legend={{ hidden: true }}\n grid={{ horizontal: true, vertical: false }}\n sx={{\n [`.${axisClasses.left} .${axisClasses.label}`]: {\n transform: 'translate(-10px, 0)',\n },\n [`.${axisClasses.bottom} .${axisClasses.label}`]: {\n fontSize: '12px',\n },\n [`.${axisClasses.left} .${axisClasses.line}`]: {\n display: 'none',\n },\n [`.${axisClasses.bottom} .${axisClasses.line}`]: {\n display: 'none',\n },\n [`.${axisClasses.left} .${axisClasses.tick}`]: {\n display: 'none',\n },\n [`.${axisClasses.bottom} .${axisClasses.tick}`]: {\n display: 'none',\n },\n '& .MuiChartsGrid-line': {\n strokeDasharray: '3 3',\n stroke: theme.palette.divider,\n strokeWidth: 1,\n },\n '& .MuiBarElement-root': {\n transformOrigin: 'center bottom',\n transform: `scaleX(${responsiveConfig.transformScale})`,\n },\n }}\n tooltip={{\n axisContent: (props: any) => {\n const dataIndex = props?.dataIndex ?? 0;\n const header = xAxisData[dataIndex] || props?.label;\n\n return (\n <div className=\"MuiChartsTooltip-root\">\n <table className=\"MuiChartsTooltip-table\">\n <tbody>\n <tr className=\"MuiChartsTooltip-row\">\n <td className=\"MuiChartsTooltip-cell\" colSpan={2}>\n {header}\n </td>\n </tr>\n {series.map((s, idx) => {\n const value = s.data?.[dataIndex];\n let formatted: string;\n if (typeof value === 'number') {\n formatted = formatValue(value);\n } else if (value === null || value === undefined) {\n formatted = '0';\n } else {\n formatted = String(value);\n }\n return (\n <tr key={idx} className=\"MuiChartsTooltip-row\">\n <td\n className=\"MuiChartsTooltip-labelCell\"\n style={\n {\n '--series-color': s.color,\n } as React.CSSProperties\n }\n >\n {s.label}\n </td>\n <td className=\"MuiChartsTooltip-valueCell\">\n {formatted}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n },\n }}\n slotProps={{\n popper: {\n placement: 'auto',\n modifiers: [\n {\n name: 'flip',\n enabled: true,\n options: {\n fallbackPlacements: ['top', 'bottom', 'right', 'left'],\n allowedAutoPlacements: ['top', 'bottom'],\n },\n },\n {\n name: 'preventOverflow',\n enabled: true,\n options: {\n boundary: 'clippingParents',\n padding: 8,\n },\n },\n {\n name: 'offset',\n enabled: true,\n options: {\n offset: [-100, 10],\n },\n },\n {\n name: 'arrow',\n enabled: false,\n },\n ],\n sx: {\n '& .MuiChartsTooltip-root': {\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: '12px',\n filter:\n theme.palette.mode === 'dark'\n ? 'drop-shadow(0 4px 12px rgba(0,0,0,0.3))'\n : 'drop-shadow(0 4px 12px rgba(0,0,0,0.1))',\n padding: '12px 16px',\n minWidth: '140px',\n fontSize: '12px',\n },\n '& .MuiChartsTooltip-table': {\n margin: 0,\n borderSpacing: 0,\n width: '100%',\n },\n '& .MuiChartsTooltip-row': {\n '&:first-of-type': {\n '& .MuiChartsTooltip-cell': {\n fontSize: '16px',\n fontWeight: 600,\n color: theme.palette.text.secondary,\n paddingBottom: '16px',\n borderBottom: 'none',\n },\n },\n '&:not(:first-of-type)': {\n '& .MuiChartsTooltip-cell': {\n padding: '4px 0',\n borderBottom: 'none',\n },\n '& .MuiChartsTooltip-labelCell': {\n position: 'relative',\n paddingLeft: '16px',\n paddingRight: '4px',\n paddingBottom: '8px',\n fontSize: '14px',\n color: theme.palette.text.secondary,\n verticalAlign: 'middle',\n '&::before': {\n content: '\"\"',\n position: 'absolute',\n left: '0',\n top: '10%',\n width: '3px',\n height: '16px',\n backgroundColor: 'var(--series-color)',\n borderRadius: '2px',\n },\n },\n '& .MuiChartsTooltip-valueCell': {\n fontSize: '14px',\n fontWeight: 600,\n color: theme.palette.text.secondary,\n textAlign: 'right',\n paddingLeft: '4px',\n paddingBottom: '8px',\n verticalAlign: 'middle',\n },\n },\n },\n },\n },\n }}\n />\n </Box>\n\n {legendPosition === 'bottom' && customLegend}\n </Box>\n );\n};\n\nexport default ColumnChart;\n"],"names":[],"mappings":"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"}
|