@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.
Files changed (223) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +232 -0
  3. package/config.d.ts +30 -0
  4. package/dist/App.esm.js +12 -0
  5. package/dist/App.esm.js.map +1 -0
  6. package/dist/api/index.esm.js +71 -0
  7. package/dist/api/index.esm.js.map +1 -0
  8. package/dist/assets/BulleyeIcon.esm.js +454 -0
  9. package/dist/assets/BulleyeIcon.esm.js.map +1 -0
  10. package/dist/assets/NoResultIcon.esm.js +146 -0
  11. package/dist/assets/NoResultIcon.esm.js.map +1 -0
  12. package/dist/assets/RiskIcon.esm.js +27 -0
  13. package/dist/assets/RiskIcon.esm.js.map +1 -0
  14. package/dist/assets/SettingIcon.esm.js +49 -0
  15. package/dist/assets/SettingIcon.esm.js.map +1 -0
  16. package/dist/assets/apiiroLogo/apiiroLogo.esm.js +21 -0
  17. package/dist/assets/apiiroLogo/apiiroLogo.esm.js.map +1 -0
  18. package/dist/assets/apiiroLogo/apiiroSidebar.esm.js +23 -0
  19. package/dist/assets/apiiroLogo/apiiroSidebar.esm.js.map +1 -0
  20. package/dist/assets/apiiroLogo/apiiroSmall.esm.js +19 -0
  21. package/dist/assets/apiiroLogo/apiiroSmall.esm.js.map +1 -0
  22. package/dist/assets/languageIcons/C.esm.js +7 -0
  23. package/dist/assets/languageIcons/C.esm.js.map +1 -0
  24. package/dist/assets/languageIcons/Cicd.esm.js +7 -0
  25. package/dist/assets/languageIcons/Cicd.esm.js.map +1 -0
  26. package/dist/assets/languageIcons/Clojure.esm.js +7 -0
  27. package/dist/assets/languageIcons/Clojure.esm.js.map +1 -0
  28. package/dist/assets/languageIcons/Cpp.esm.js +7 -0
  29. package/dist/assets/languageIcons/Cpp.esm.js.map +1 -0
  30. package/dist/assets/languageIcons/Csharp.esm.js +7 -0
  31. package/dist/assets/languageIcons/Csharp.esm.js.map +1 -0
  32. package/dist/assets/languageIcons/Dart.esm.js +7 -0
  33. package/dist/assets/languageIcons/Dart.esm.js.map +1 -0
  34. package/dist/assets/languageIcons/Go.esm.js +7 -0
  35. package/dist/assets/languageIcons/Go.esm.js.map +1 -0
  36. package/dist/assets/languageIcons/Groovy.esm.js +7 -0
  37. package/dist/assets/languageIcons/Groovy.esm.js.map +1 -0
  38. package/dist/assets/languageIcons/HTML.esm.js +7 -0
  39. package/dist/assets/languageIcons/HTML.esm.js.map +1 -0
  40. package/dist/assets/languageIcons/HclLanguage.esm.js +7 -0
  41. package/dist/assets/languageIcons/HclLanguage.esm.js.map +1 -0
  42. package/dist/assets/languageIcons/Java.esm.js +7 -0
  43. package/dist/assets/languageIcons/Java.esm.js.map +1 -0
  44. package/dist/assets/languageIcons/Javascript.esm.js +7 -0
  45. package/dist/assets/languageIcons/Javascript.esm.js.map +1 -0
  46. package/dist/assets/languageIcons/Kotlin.esm.js +7 -0
  47. package/dist/assets/languageIcons/Kotlin.esm.js.map +1 -0
  48. package/dist/assets/languageIcons/ObjectiveC.esm.js +7 -0
  49. package/dist/assets/languageIcons/ObjectiveC.esm.js.map +1 -0
  50. package/dist/assets/languageIcons/PHP.esm.js +7 -0
  51. package/dist/assets/languageIcons/PHP.esm.js.map +1 -0
  52. package/dist/assets/languageIcons/Perl.esm.js +13 -0
  53. package/dist/assets/languageIcons/Perl.esm.js.map +1 -0
  54. package/dist/assets/languageIcons/Python.esm.js +7 -0
  55. package/dist/assets/languageIcons/Python.esm.js.map +1 -0
  56. package/dist/assets/languageIcons/Ruby.esm.js +7 -0
  57. package/dist/assets/languageIcons/Ruby.esm.js.map +1 -0
  58. package/dist/assets/languageIcons/Rust.esm.js +7 -0
  59. package/dist/assets/languageIcons/Rust.esm.js.map +1 -0
  60. package/dist/assets/languageIcons/Scala.esm.js +7 -0
  61. package/dist/assets/languageIcons/Scala.esm.js.map +1 -0
  62. package/dist/assets/languageIcons/Swift.esm.js +7 -0
  63. package/dist/assets/languageIcons/Swift.esm.js.map +1 -0
  64. package/dist/assets/languageIcons/Terraform.esm.js +7 -0
  65. package/dist/assets/languageIcons/Terraform.esm.js.map +1 -0
  66. package/dist/assets/languageIcons/Typescript.esm.js +7 -0
  67. package/dist/assets/languageIcons/Typescript.esm.js.map +1 -0
  68. package/dist/assets/languageIcons/Unknown.esm.js +7 -0
  69. package/dist/assets/languageIcons/Unknown.esm.js.map +1 -0
  70. package/dist/assets/languageIcons/VB.esm.js +10 -0
  71. package/dist/assets/languageIcons/VB.esm.js.map +1 -0
  72. package/dist/assets/languageIcons/YAML.esm.js +7 -0
  73. package/dist/assets/languageIcons/YAML.esm.js.map +1 -0
  74. package/dist/assets/providerIcons/Azure.esm.js +7 -0
  75. package/dist/assets/providerIcons/Azure.esm.js.map +1 -0
  76. package/dist/assets/providerIcons/Bitbucket.esm.js +7 -0
  77. package/dist/assets/providerIcons/Bitbucket.esm.js.map +1 -0
  78. package/dist/assets/providerIcons/Gitlab.esm.js +7 -0
  79. package/dist/assets/providerIcons/Gitlab.esm.js.map +1 -0
  80. package/dist/components/ApiiroSidebar.esm.js +10 -0
  81. package/dist/components/ApiiroSidebar.esm.js.map +1 -0
  82. package/dist/components/ApplicationsList/ApplicationsList.esm.js +196 -0
  83. package/dist/components/ApplicationsList/ApplicationsList.esm.js.map +1 -0
  84. package/dist/components/CalendarDatePicker.esm.js +154 -0
  85. package/dist/components/CalendarDatePicker.esm.js.map +1 -0
  86. package/dist/components/CalendarDatePicker.styles.esm.js +198 -0
  87. package/dist/components/CalendarDatePicker.styles.esm.js.map +1 -0
  88. package/dist/components/Chip.esm.js +60 -0
  89. package/dist/components/Chip.esm.js.map +1 -0
  90. package/dist/components/ChipsList.esm.js +207 -0
  91. package/dist/components/ChipsList.esm.js.map +1 -0
  92. package/dist/components/ComponentDisplay.esm.js +42 -0
  93. package/dist/components/ComponentDisplay.esm.js.map +1 -0
  94. package/dist/components/DataGrid/CustomColumnMenu.esm.js +29 -0
  95. package/dist/components/DataGrid/CustomColumnMenu.esm.js.map +1 -0
  96. package/dist/components/DataGrid/CustomPagination.esm.js +113 -0
  97. package/dist/components/DataGrid/CustomPagination.esm.js.map +1 -0
  98. package/dist/components/DataGrid/CustomSearchToolbar.esm.js +117 -0
  99. package/dist/components/DataGrid/CustomSearchToolbar.esm.js.map +1 -0
  100. package/dist/components/DataGrid/DataGrid.esm.js +336 -0
  101. package/dist/components/DataGrid/DataGrid.esm.js.map +1 -0
  102. package/dist/components/DataGrid/PinColumnMenuItem.esm.js +24 -0
  103. package/dist/components/DataGrid/PinColumnMenuItem.esm.js.map +1 -0
  104. package/dist/components/DueDate.esm.js +34 -0
  105. package/dist/components/DueDate.esm.js.map +1 -0
  106. package/dist/components/Header.esm.js +27 -0
  107. package/dist/components/Header.esm.js.map +1 -0
  108. package/dist/components/MainContributors/MainContributors.esm.js +62 -0
  109. package/dist/components/MainContributors/MainContributors.esm.js.map +1 -0
  110. package/dist/components/MetricsGroup/TabMetricsGroup.esm.js +37 -0
  111. package/dist/components/MetricsGroup/TabMetricsGroup.esm.js.map +1 -0
  112. package/dist/components/MetricsGroup/WidgetMetricsGroup.esm.js +36 -0
  113. package/dist/components/MetricsGroup/WidgetMetricsGroup.esm.js.map +1 -0
  114. package/dist/components/RepositoryDisplay/RepositoryDisplay.esm.js +121 -0
  115. package/dist/components/RepositoryDisplay/RepositoryDisplay.esm.js.map +1 -0
  116. package/dist/components/RiskLevel.esm.js +88 -0
  117. package/dist/components/RiskLevel.esm.js.map +1 -0
  118. package/dist/components/RiskStatus.esm.js +58 -0
  119. package/dist/components/RiskStatus.esm.js.map +1 -0
  120. package/dist/components/SimpleTooltip.esm.js +24 -0
  121. package/dist/components/SimpleTooltip.esm.js.map +1 -0
  122. package/dist/components/SourcesDisplay.esm.js +47 -0
  123. package/dist/components/SourcesDisplay.esm.js.map +1 -0
  124. package/dist/components/TagsList/TagsList.esm.js +38 -0
  125. package/dist/components/TagsList/TagsList.esm.js.map +1 -0
  126. package/dist/components/TeamsDisplay.esm.js +47 -0
  127. package/dist/components/TeamsDisplay.esm.js.map +1 -0
  128. package/dist/components/charts/ColumnChart.esm.js +402 -0
  129. package/dist/components/charts/ColumnChart.esm.js.map +1 -0
  130. package/dist/components/charts/GaugeChart.esm.js +249 -0
  131. package/dist/components/charts/GaugeChart.esm.js.map +1 -0
  132. package/dist/components/charts/LineChart.esm.js +328 -0
  133. package/dist/components/charts/LineChart.esm.js.map +1 -0
  134. package/dist/components/charts/PieChart.esm.js +233 -0
  135. package/dist/components/charts/PieChart.esm.js.map +1 -0
  136. package/dist/components/common/ChartBox.esm.js +88 -0
  137. package/dist/components/common/ChartBox.esm.js.map +1 -0
  138. package/dist/components/common/CustomTooltip.esm.js +255 -0
  139. package/dist/components/common/CustomTooltip.esm.js.map +1 -0
  140. package/dist/components/common/ErrorSnackbar.esm.js +39 -0
  141. package/dist/components/common/ErrorSnackbar.esm.js.map +1 -0
  142. package/dist/components/common/NotFound.esm.js +30 -0
  143. package/dist/components/common/NotFound.esm.js.map +1 -0
  144. package/dist/components/common/SomethingWentWrong.esm.js +35 -0
  145. package/dist/components/common/SomethingWentWrong.esm.js.map +1 -0
  146. package/dist/components/common/languageIcons.esm.js +61 -0
  147. package/dist/components/common/languageIcons.esm.js.map +1 -0
  148. package/dist/components/common/logoSpinner.esm.js +28 -0
  149. package/dist/components/common/logoSpinner.esm.js.map +1 -0
  150. package/dist/components/common/scmProviders.esm.js +41 -0
  151. package/dist/components/common/scmProviders.esm.js.map +1 -0
  152. package/dist/components/filters/DiscoveredOnFilter.esm.js +284 -0
  153. package/dist/components/filters/DiscoveredOnFilter.esm.js.map +1 -0
  154. package/dist/components/filters/FilterDropdown.esm.js +325 -0
  155. package/dist/components/filters/FilterDropdown.esm.js.map +1 -0
  156. package/dist/components/filters/FilterDropdownClear.esm.js +45 -0
  157. package/dist/components/filters/FilterDropdownClear.esm.js.map +1 -0
  158. package/dist/components/filters/FilterDropdownList.esm.js +102 -0
  159. package/dist/components/filters/FilterDropdownList.esm.js.map +1 -0
  160. package/dist/components/filters/FilterDropdownSearch.esm.js +65 -0
  161. package/dist/components/filters/FilterDropdownSearch.esm.js.map +1 -0
  162. package/dist/components/filters/RiskInsightFilter.esm.js +579 -0
  163. package/dist/components/filters/RiskInsightFilter.esm.js.map +1 -0
  164. package/dist/components/tiles/MttrVsSLATile.esm.js +170 -0
  165. package/dist/components/tiles/MttrVsSLATile.esm.js.map +1 -0
  166. package/dist/components/tiles/RiskOverTimeTile.esm.js +311 -0
  167. package/dist/components/tiles/RiskOverTimeTile.esm.js.map +1 -0
  168. package/dist/components/tiles/SLAAdherenceTile.esm.js +115 -0
  169. package/dist/components/tiles/SLAAdherenceTile.esm.js.map +1 -0
  170. package/dist/components/tiles/StatusTile.esm.js +235 -0
  171. package/dist/components/tiles/StatusTile.esm.js.map +1 -0
  172. package/dist/components/tiles/TopLanguagesTile.esm.js +234 -0
  173. package/dist/components/tiles/TopLanguagesTile.esm.js.map +1 -0
  174. package/dist/components/tiles/TopRiskTile.esm.js +208 -0
  175. package/dist/components/tiles/TopRiskTile.esm.js.map +1 -0
  176. package/dist/hooks/useUrlFilters.esm.js +102 -0
  177. package/dist/hooks/useUrlFilters.esm.js.map +1 -0
  178. package/dist/index.d.ts +28 -0
  179. package/dist/index.esm.js +42 -0
  180. package/dist/index.esm.js.map +1 -0
  181. package/dist/pages/Repositories/Repositories.esm.js +102 -0
  182. package/dist/pages/Repositories/Repositories.esm.js.map +1 -0
  183. package/dist/pages/Repositories/tableConfig.esm.js +294 -0
  184. package/dist/pages/Repositories/tableConfig.esm.js.map +1 -0
  185. package/dist/pages/Risks/Risks.esm.js +258 -0
  186. package/dist/pages/Risks/Risks.esm.js.map +1 -0
  187. package/dist/pages/Risks/tableConfig.esm.js +305 -0
  188. package/dist/pages/Risks/tableConfig.esm.js.map +1 -0
  189. package/dist/pages/tab/Tab.esm.js +147 -0
  190. package/dist/pages/tab/Tab.esm.js.map +1 -0
  191. package/dist/pages/tab/TabProvider.esm.js +11 -0
  192. package/dist/pages/tab/TabProvider.esm.js.map +1 -0
  193. package/dist/pages/widget/Widget.esm.js +161 -0
  194. package/dist/pages/widget/Widget.esm.js.map +1 -0
  195. package/dist/pages/widget/WidgetProvider.esm.js +12 -0
  196. package/dist/pages/widget/WidgetProvider.esm.js.map +1 -0
  197. package/dist/plugin.esm.js +30 -0
  198. package/dist/plugin.esm.js.map +1 -0
  199. package/dist/queries/filterOptions.queries.esm.js +46 -0
  200. package/dist/queries/filterOptions.queries.esm.js.map +1 -0
  201. package/dist/queries/mttr-statistics.queries.esm.js +61 -0
  202. package/dist/queries/mttr-statistics.queries.esm.js.map +1 -0
  203. package/dist/queries/repository.queries.esm.js +60 -0
  204. package/dist/queries/repository.queries.esm.js.map +1 -0
  205. package/dist/queries/risk-score-over-time.queries.esm.js +61 -0
  206. package/dist/queries/risk-score-over-time.queries.esm.js.map +1 -0
  207. package/dist/queries/risks.queries.esm.js +65 -0
  208. package/dist/queries/risks.queries.esm.js.map +1 -0
  209. package/dist/queries/sla-breach.queries.esm.js +57 -0
  210. package/dist/queries/sla-breach.queries.esm.js.map +1 -0
  211. package/dist/queries/top-risks.queries.esm.js +47 -0
  212. package/dist/queries/top-risks.queries.esm.js.map +1 -0
  213. package/dist/routes.esm.js +8 -0
  214. package/dist/routes.esm.js.map +1 -0
  215. package/dist/theme/themeUtils.esm.js +290 -0
  216. package/dist/theme/themeUtils.esm.js.map +1 -0
  217. package/dist/utils/dateFormatter.esm.js +67 -0
  218. package/dist/utils/dateFormatter.esm.js.map +1 -0
  219. package/dist/utils/numberFormatter.esm.js +21 -0
  220. package/dist/utils/numberFormatter.esm.js.map +1 -0
  221. package/dist/utils/utils.esm.js +27 -0
  222. package/dist/utils/utils.esm.js.map +1 -0
  223. package/package.json +90 -0
@@ -0,0 +1,117 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import Box from '@mui/material/Box';
4
+ import TextField from '@mui/material/TextField';
5
+ import InputAdornment from '@mui/material/InputAdornment';
6
+ import SearchIcon from '@mui/icons-material/Search';
7
+ import ClearIcon from '@mui/icons-material/Clear';
8
+ import IconButton from '@mui/material/IconButton';
9
+ import { useTheme } from '@mui/material/styles';
10
+ import { getSearchToolbarColors } from '../../theme/themeUtils.esm.js';
11
+
12
+ function CustomSearchToolbar({
13
+ apiRef,
14
+ placeholder,
15
+ customFilters
16
+ }) {
17
+ const theme = useTheme();
18
+ const searchColors = getSearchToolbarColors(theme);
19
+ const getInitialSearchValue = () => {
20
+ if (typeof window !== "undefined") {
21
+ const urlParams = new URLSearchParams(window.location.search);
22
+ return urlParams.get("search") || "";
23
+ }
24
+ return "";
25
+ };
26
+ const [searchText, setSearchText] = useState(getInitialSearchValue);
27
+ useEffect(() => {
28
+ const initialSearch = getInitialSearchValue();
29
+ if (initialSearch) {
30
+ setSearchText(initialSearch);
31
+ apiRef?.current?.setQuickFilterValues([initialSearch]);
32
+ }
33
+ }, [apiRef]);
34
+ const updateURL = (searchValue) => {
35
+ if (typeof window !== "undefined") {
36
+ const url = new URL(window.location.href);
37
+ if (searchValue) {
38
+ url.searchParams.set("search", searchValue);
39
+ } else {
40
+ url.searchParams.delete("search");
41
+ }
42
+ window.history.replaceState({}, "", url.toString());
43
+ }
44
+ };
45
+ useEffect(() => {
46
+ const handler = setTimeout(() => {
47
+ updateURL(searchText);
48
+ }, 300);
49
+ return () => clearTimeout(handler);
50
+ }, [searchText]);
51
+ const handleSearchChange = (value) => {
52
+ setSearchText(value);
53
+ apiRef?.current?.setQuickFilterValues([value]);
54
+ };
55
+ const handleClearSearch = () => {
56
+ setSearchText("");
57
+ apiRef?.current?.setQuickFilterValues([""]);
58
+ };
59
+ return /* @__PURE__ */ jsx(Box, { sx: { py: 2 }, children: /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", gap: 1.5 }, children: [
60
+ /* @__PURE__ */ jsx(
61
+ TextField,
62
+ {
63
+ placeholder,
64
+ value: searchText,
65
+ onChange: (e) => handleSearchChange(e.target.value),
66
+ variant: "outlined",
67
+ size: "small",
68
+ InputProps: {
69
+ sx: {
70
+ borderRadius: "40px"
71
+ },
72
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(SearchIcon, { sx: { color: searchColors.iconColor } }) }),
73
+ endAdornment: searchText && /* @__PURE__ */ jsx(InputAdornment, { position: "end", children: /* @__PURE__ */ jsx(
74
+ IconButton,
75
+ {
76
+ onClick: handleClearSearch,
77
+ size: "small",
78
+ sx: { color: searchColors.iconColor },
79
+ children: /* @__PURE__ */ jsx(ClearIcon, { fontSize: "small" })
80
+ }
81
+ ) })
82
+ },
83
+ sx: {
84
+ minWidth: 300,
85
+ maxWidth: 400,
86
+ "& .MuiOutlinedInput-root": {
87
+ backgroundColor: searchColors.backgroundColor,
88
+ "& fieldset": {
89
+ borderColor: searchColors.borderColor
90
+ },
91
+ "&:hover fieldset": {
92
+ borderColor: searchColors.hoverBorderColor
93
+ },
94
+ "&.Mui-focused fieldset": {
95
+ borderColor: searchColors.focusBorderColor
96
+ }
97
+ }
98
+ }
99
+ }
100
+ ),
101
+ customFilters && /* @__PURE__ */ jsx(
102
+ Box,
103
+ {
104
+ sx: {
105
+ display: "flex",
106
+ gap: 1,
107
+ alignItems: "center",
108
+ flexWrap: "wrap"
109
+ },
110
+ children: customFilters
111
+ }
112
+ )
113
+ ] }) });
114
+ }
115
+
116
+ export { CustomSearchToolbar };
117
+ //# sourceMappingURL=CustomSearchToolbar.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CustomSearchToolbar.esm.js","sources":["../../../src/components/DataGrid/CustomSearchToolbar.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 { useState, useEffect } from 'react';\nimport Box from '@mui/material/Box';\nimport TextField from '@mui/material/TextField';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport SearchIcon from '@mui/icons-material/Search';\nimport ClearIcon from '@mui/icons-material/Clear';\nimport IconButton from '@mui/material/IconButton';\nimport { useTheme } from '@mui/material/styles';\nimport { CustomSearchToolbarProps } from './types';\nimport { getSearchToolbarColors } from '../../theme/themeUtils';\n\nexport function CustomSearchToolbar({\n apiRef,\n placeholder,\n customFilters,\n}: CustomSearchToolbarProps) {\n const theme = useTheme();\n const searchColors = getSearchToolbarColors(theme);\n // Get initial search value from URL parameter\n const getInitialSearchValue = (): string => {\n if (typeof window !== 'undefined') {\n const urlParams = new URLSearchParams(window.location.search);\n return urlParams.get('search') || '';\n }\n return '';\n };\n\n const [searchText, setSearchText] = useState<string>(getInitialSearchValue);\n\n // Initialize search from URL on component mount\n useEffect(() => {\n const initialSearch = getInitialSearchValue();\n if (initialSearch) {\n setSearchText(initialSearch);\n apiRef?.current?.setQuickFilterValues([initialSearch]);\n }\n }, [apiRef]);\n\n const updateURL = (searchValue: string) => {\n if (typeof window !== 'undefined') {\n const url = new URL(window.location.href);\n if (searchValue) {\n url.searchParams.set('search', searchValue);\n } else {\n url.searchParams.delete('search');\n }\n window.history.replaceState({}, '', url.toString());\n }\n };\n\n // Debounced URL update effect\n useEffect(() => {\n const handler = setTimeout(() => {\n // Update URL only after 300ms of inactivity\n updateURL(searchText);\n }, 300);\n\n return () => clearTimeout(handler);\n }, [searchText]);\n\n const handleSearchChange = (value: string) => {\n setSearchText(value);\n // Use MUI's built-in quick filter API (immediate)\n apiRef?.current?.setQuickFilterValues([value]);\n // URL update is now debounced via useEffect\n };\n\n const handleClearSearch = () => {\n setSearchText('');\n apiRef?.current?.setQuickFilterValues(['']);\n // URL parameter will be cleared by debounced effect\n };\n\n return (\n <Box sx={{ py: 2 }}>\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>\n <TextField\n placeholder={placeholder}\n value={searchText}\n onChange={e => handleSearchChange(e.target.value)}\n variant=\"outlined\"\n size=\"small\"\n InputProps={{\n sx: {\n borderRadius: '40px',\n },\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon sx={{ color: searchColors.iconColor }} />\n </InputAdornment>\n ),\n endAdornment: searchText && (\n <InputAdornment position=\"end\">\n <IconButton\n onClick={handleClearSearch}\n size=\"small\"\n sx={{ color: searchColors.iconColor }}\n >\n <ClearIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ),\n }}\n sx={{\n minWidth: 300,\n maxWidth: 400,\n '& .MuiOutlinedInput-root': {\n backgroundColor: searchColors.backgroundColor,\n '& fieldset': {\n borderColor: searchColors.borderColor,\n },\n '&:hover fieldset': {\n borderColor: searchColors.hoverBorderColor,\n },\n '&.Mui-focused fieldset': {\n borderColor: searchColors.focusBorderColor,\n },\n },\n }}\n />\n {customFilters && (\n <Box\n sx={{\n display: 'flex',\n gap: 1,\n alignItems: 'center',\n flexWrap: 'wrap',\n }}\n >\n {customFilters}\n </Box>\n )}\n </Box>\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,336 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState, useEffect, useCallback } from 'react';
3
+ import { useGridApiRef, DataGrid as DataGrid$1 } from '@mui/x-data-grid';
4
+ import Box from '@mui/material/Box';
5
+ import { useTheme } from '@mui/material/styles';
6
+ import { CustomColumnMenu } from './CustomColumnMenu.esm.js';
7
+ import { CustomPagination } from './CustomPagination.esm.js';
8
+ import { CustomSearchToolbar } from './CustomSearchToolbar.esm.js';
9
+ import '../common/ChartBox.esm.js';
10
+ import 'react-dom';
11
+ import { NotFound } from '../common/NotFound.esm.js';
12
+ import '@mui/material/Typography';
13
+ import { LogoSpinner } from '../common/logoSpinner.esm.js';
14
+
15
+ function DataGrid({
16
+ // Required props
17
+ tableKey,
18
+ columns: propColumns,
19
+ rows: propRows,
20
+ // Optional configuration
21
+ dataLabel = "items",
22
+ searchBarPlaceHolder = "Search",
23
+ features = {},
24
+ styling = {},
25
+ // Pagination
26
+ initialPageSize = 20,
27
+ pageSizeOptions = [20, 50, 100],
28
+ // Event handlers
29
+ onRowClick,
30
+ onSelectionChange,
31
+ // Custom components
32
+ customFilters,
33
+ columnVisibility,
34
+ // Loading state
35
+ loading,
36
+ // custom Row ID
37
+ getRowId,
38
+ // Initial Table state
39
+ initialState
40
+ }) {
41
+ const theme = useTheme();
42
+ const apiRef = useGridApiRef();
43
+ const {
44
+ quickSearch = true,
45
+ columnPinning = true,
46
+ columnReordering = true,
47
+ customPagination = true,
48
+ columnMenu = true,
49
+ persistLayout = true
50
+ } = features;
51
+ const {
52
+ borderRadius = "12px",
53
+ headerBackgroundColor = theme.palette.mode === "dark" ? theme.palette.background.paper : theme.palette.grey[100],
54
+ backgroundColor = theme.palette.background.paper,
55
+ height = "auto"
56
+ } = styling;
57
+ const [columns, setColumns] = useState(propColumns);
58
+ const [pinned, setPinned] = useState([]);
59
+ const [dragCol, setDragCol] = useState(null);
60
+ const [dropTarget, setDropTarget] = useState(null);
61
+ const [dropSide, setDropSide] = useState(null);
62
+ const [paginationModel, setPaginationModel] = useState({
63
+ page: 0,
64
+ pageSize: initialPageSize
65
+ });
66
+ const [columnVisibilityModel, setColumnVisibilityModel] = useState(columnVisibility || {});
67
+ useEffect(() => {
68
+ if (!persistLayout) return;
69
+ try {
70
+ const saved = localStorage.getItem(`apiiro-gridLayout-${tableKey}`);
71
+ if (saved) {
72
+ const {
73
+ order,
74
+ pinned: savedPinned,
75
+ columnVisibility: savedVisibility
76
+ } = JSON.parse(saved);
77
+ setPinned(savedPinned || []);
78
+ if (savedVisibility) {
79
+ setColumnVisibilityModel(savedVisibility);
80
+ }
81
+ const orderedColumns2 = order.map((field) => propColumns.find((c) => c.field === field)).filter((c) => !!c);
82
+ setColumns(orderedColumns2);
83
+ }
84
+ } catch (error) {
85
+ }
86
+ }, [propColumns, persistLayout, tableKey]);
87
+ const saveLayout = useCallback(
88
+ (cols, pinnedCols, visibility) => {
89
+ if (!persistLayout) return;
90
+ const layout = {
91
+ order: cols.map((c) => c.field),
92
+ pinned: pinnedCols,
93
+ columnVisibility: visibility || columnVisibilityModel
94
+ };
95
+ localStorage.setItem(
96
+ `apiiro-gridLayout-${tableKey}`,
97
+ JSON.stringify(layout)
98
+ );
99
+ },
100
+ [persistLayout, tableKey, columnVisibilityModel]
101
+ );
102
+ useEffect(() => {
103
+ if (persistLayout) {
104
+ saveLayout(columns, pinned, columnVisibilityModel);
105
+ }
106
+ }, [columnVisibilityModel, persistLayout, saveLayout, columns, pinned]);
107
+ const handleDragStart = (field) => setDragCol(field);
108
+ const handleDragOver = (e, targetField) => {
109
+ e.preventDefault();
110
+ if (dragCol === targetField) return;
111
+ const targetRect = e.currentTarget.getBoundingClientRect();
112
+ const x = e.clientX - targetRect.left;
113
+ setDropTarget(targetField);
114
+ setDropSide(x < targetRect.width / 2 ? "left" : "right");
115
+ };
116
+ const handleDragLeave = () => setDropTarget(null);
117
+ const handleDrop = (targetField) => {
118
+ if (!dragCol || dragCol === targetField) return;
119
+ const dragIsPinned = pinned.includes(dragCol);
120
+ const targetIsPinned = pinned.includes(targetField);
121
+ if (dragIsPinned !== targetIsPinned) {
122
+ setDragCol(null);
123
+ setDropTarget(null);
124
+ return;
125
+ }
126
+ const currentList = dragIsPinned ? columns.filter((c) => pinned.includes(c.field)) : columns.filter((c) => !pinned.includes(c.field));
127
+ const dragIndex = currentList.findIndex((c) => c.field === dragCol);
128
+ const targetIndex = currentList.findIndex((c) => c.field === targetField);
129
+ const newIndex = dropSide === "left" ? targetIndex : targetIndex + 1;
130
+ const reordered = [...currentList];
131
+ const [moved] = reordered.splice(dragIndex, 1);
132
+ reordered.splice(newIndex, 0, moved);
133
+ const finalColumns2 = dragIsPinned ? [...reordered, ...columns.filter((c) => !pinned.includes(c.field))] : [...columns.filter((c) => pinned.includes(c.field)), ...reordered];
134
+ setColumns(finalColumns2);
135
+ setDragCol(null);
136
+ setDropTarget(null);
137
+ saveLayout(finalColumns2, pinned);
138
+ };
139
+ const togglePin = useCallback(
140
+ (field) => {
141
+ setPinned((prev) => {
142
+ const next = prev.includes(field) ? prev.filter((f) => f !== field) : [...prev, field];
143
+ saveLayout(columns, next);
144
+ return next;
145
+ });
146
+ },
147
+ [columns, saveLayout]
148
+ );
149
+ const CustomColumnMenuWithProps = useCallback(
150
+ (props) => {
151
+ return /* @__PURE__ */ jsx(
152
+ CustomColumnMenu,
153
+ {
154
+ ...props,
155
+ isPinned: pinned.includes(props.colDef.field),
156
+ onTogglePin: togglePin
157
+ }
158
+ );
159
+ },
160
+ [pinned, togglePin]
161
+ );
162
+ const CustomPaginationComponent = useCallback(
163
+ () => /* @__PURE__ */ jsx(
164
+ CustomPagination,
165
+ {
166
+ onPageSizeChange: (pageSize) => setPaginationModel({ page: 0, pageSize }),
167
+ pageSizeOptions,
168
+ dataLabel
169
+ }
170
+ ),
171
+ [dataLabel, pageSizeOptions]
172
+ );
173
+ const finalColumns = columnReordering ? columns.map((col) => ({
174
+ ...col,
175
+ renderHeader: () => /* @__PURE__ */ jsx(
176
+ Box,
177
+ {
178
+ draggable: columnReordering,
179
+ onDragStart: () => handleDragStart(col.field),
180
+ onDragOver: (e) => handleDragOver(e, col.field),
181
+ onDragLeave: handleDragLeave,
182
+ onDrop: () => handleDrop(col.field),
183
+ sx: {
184
+ display: "flex",
185
+ justifyContent: "center",
186
+ alignItems: "center",
187
+ cursor: columnReordering ? "grab" : "default",
188
+ userSelect: "none",
189
+ position: "relative",
190
+ fontWeight: columnPinning && pinned.includes(col.field) ? "bold" : "normal",
191
+ px: 1,
192
+ "&::before": columnReordering ? {
193
+ content: '""',
194
+ position: "absolute",
195
+ top: 0,
196
+ bottom: 0,
197
+ left: dropTarget === col.field && dropSide === "left" ? 0 : "auto",
198
+ right: dropTarget === col.field && dropSide === "right" ? 0 : "auto",
199
+ width: "3px",
200
+ backgroundColor: dropTarget === col.field ? theme.palette.primary.main : "transparent",
201
+ transition: "background 0.1s ease"
202
+ } : {}
203
+ },
204
+ children: col.headerName
205
+ }
206
+ )
207
+ })) : columns;
208
+ const orderedColumns = columnPinning ? [
209
+ ...finalColumns.filter((c) => pinned.includes(c.field)).map((col) => ({ ...col, resizable: false })),
210
+ ...finalColumns.filter((c) => !pinned.includes(c.field))
211
+ ] : finalColumns;
212
+ const pinnedOffsets = {};
213
+ let leftOffset = 0;
214
+ for (const col of orderedColumns) {
215
+ if (pinned.includes(col.field)) {
216
+ pinnedOffsets[col.field] = leftOffset;
217
+ leftOffset += col.minWidth || col.width || 200;
218
+ }
219
+ }
220
+ const pinnedColumnStyles = {};
221
+ if (columnPinning) {
222
+ pinned.forEach((field) => {
223
+ pinnedColumnStyles[`& [data-field="${field}"]`] = {
224
+ position: "sticky",
225
+ left: pinnedOffsets[field],
226
+ zIndex: 9999,
227
+ backgroundColor,
228
+ boxShadow: "2px 0 2px rgba(0,0,0,0.05)"
229
+ };
230
+ });
231
+ }
232
+ return /* @__PURE__ */ jsxs(
233
+ Box,
234
+ {
235
+ sx: {
236
+ height,
237
+ width: "100%",
238
+ overflowX: "auto"
239
+ },
240
+ children: [
241
+ quickSearch && /* @__PURE__ */ jsx(
242
+ CustomSearchToolbar,
243
+ {
244
+ apiRef,
245
+ placeholder: searchBarPlaceHolder,
246
+ customFilters
247
+ }
248
+ ),
249
+ /* @__PURE__ */ jsx(
250
+ DataGrid$1,
251
+ {
252
+ apiRef,
253
+ rows: propRows,
254
+ columns: orderedColumns,
255
+ initialState: {
256
+ ...initialState
257
+ },
258
+ columnVisibilityModel,
259
+ onColumnVisibilityModelChange: setColumnVisibilityModel,
260
+ disableVirtualization: true,
261
+ getRowId,
262
+ loading,
263
+ paginationModel,
264
+ onPaginationModelChange: setPaginationModel,
265
+ pageSizeOptions,
266
+ onRowClick: onRowClick ? (params) => onRowClick(params.row) : void 0,
267
+ onRowSelectionModelChange: onSelectionChange ? (selectionModel) => {
268
+ const selectedIds = selectionModel.ids ? Array.from(selectionModel.ids) : [];
269
+ const selectedRows = propRows.filter(
270
+ (row) => selectedIds.some(
271
+ (id) => String(getRowId ? getRowId(row) : row.id) === String(id)
272
+ )
273
+ );
274
+ onSelectionChange(selectedRows);
275
+ } : void 0,
276
+ slots: {
277
+ ...columnMenu && { columnMenu: CustomColumnMenuWithProps },
278
+ ...customPagination && { pagination: CustomPaginationComponent },
279
+ noResultsOverlay: () => /* @__PURE__ */ jsx(NotFound, {}),
280
+ loadingOverlay: () => /* @__PURE__ */ jsx(
281
+ Box,
282
+ {
283
+ display: "flex",
284
+ height: "100%",
285
+ justifyContent: "center",
286
+ alignItems: "center",
287
+ children: /* @__PURE__ */ jsx(LogoSpinner, {})
288
+ }
289
+ )
290
+ },
291
+ slotProps: {
292
+ loadingOverlay: {
293
+ variant: "linear-progress",
294
+ noRowsVariant: "skeleton"
295
+ },
296
+ columnsManagement: {
297
+ disableResetButton: true,
298
+ searchInputProps: {
299
+ type: "text"
300
+ }
301
+ }
302
+ },
303
+ sx: {
304
+ backgroundColor,
305
+ "&.MuiDataGrid-root": {
306
+ borderRadius,
307
+ minWidth: "auto"
308
+ },
309
+ "& .MuiDataGrid-columnHeader:focus, & .MuiDataGrid-columnHeader:focus-within": {
310
+ outline: "none"
311
+ },
312
+ "&.MuiDataGrid-root .MuiDataGrid-columnHeader, &.MuiDataGrid-root .MuiDataGrid-filler": {
313
+ backgroundColor: headerBackgroundColor
314
+ },
315
+ // Column resize line styling
316
+ "& .MuiDataGrid-columnSeparator--resizable": {
317
+ "&:hover": {
318
+ color: theme.palette.primary.main
319
+ }
320
+ },
321
+ "& .MuiDataGrid-columnSeparator--resizing": {
322
+ color: theme.palette.primary.main,
323
+ opacity: 1
324
+ },
325
+ ...pinnedColumnStyles
326
+ }
327
+ },
328
+ tableKey
329
+ )
330
+ ]
331
+ }
332
+ );
333
+ }
334
+
335
+ export { DataGrid };
336
+ //# sourceMappingURL=DataGrid.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataGrid.esm.js","sources":["../../../src/components/DataGrid/DataGrid.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 { useEffect, useState, useCallback } from 'react';\nimport {\n DataGrid as DataGridMUI,\n GridColDef,\n GridPaginationModel,\n useGridApiRef,\n GridValidRowModel,\n} from '@mui/x-data-grid';\nimport Box from '@mui/material/Box';\nimport { useTheme } from '@mui/material/styles';\nimport { CustomColumnMenu } from './CustomColumnMenu';\nimport { CustomPagination } from './CustomPagination';\nimport { CustomSearchToolbar } from './CustomSearchToolbar';\nimport { DataGridProps, GridLayout } from './types';\nimport { NotFound } from '../common';\nimport { LogoSpinner } from '../common/logoSpinner';\n\nexport function DataGrid<T extends GridValidRowModel>({\n // Required props\n tableKey,\n columns: propColumns,\n rows: propRows,\n\n // Optional configuration\n dataLabel = 'items',\n searchBarPlaceHolder = 'Search',\n features = {},\n styling = {},\n\n // Pagination\n initialPageSize = 20,\n pageSizeOptions = [20, 50, 100],\n\n // Event handlers\n onRowClick,\n onSelectionChange,\n\n // Custom components\n customFilters,\n columnVisibility,\n\n // Loading state\n loading,\n\n // custom Row ID\n getRowId,\n\n // Initial Table state\n initialState,\n}: DataGridProps<T>) {\n const theme = useTheme();\n const apiRef = useGridApiRef();\n\n // Default feature flags\n const {\n quickSearch = true,\n columnPinning = true,\n columnReordering = true,\n customPagination = true,\n columnMenu = true,\n persistLayout = true,\n } = features;\n\n // Default styling\n const {\n borderRadius = '12px',\n headerBackgroundColor = theme.palette.mode === 'dark'\n ? theme.palette.background.paper\n : theme.palette.grey[100],\n backgroundColor = theme.palette.background.paper,\n height = 'auto',\n } = styling;\n\n const [columns, setColumns] = useState<GridColDef<T>[]>(propColumns);\n const [pinned, setPinned] = useState<string[]>([]);\n const [dragCol, setDragCol] = useState<string | null>(null);\n const [dropTarget, setDropTarget] = useState<string | null>(null);\n const [dropSide, setDropSide] = useState<'left' | 'right' | null>(null);\n const [paginationModel, setPaginationModel] = useState<GridPaginationModel>({\n page: 0,\n pageSize: initialPageSize,\n });\n\n const [columnVisibilityModel, setColumnVisibilityModel] = useState<\n Record<string, boolean>\n >(columnVisibility || {});\n\n // Load saved layout\n useEffect(() => {\n if (!persistLayout) return;\n\n try {\n const saved = localStorage.getItem(`apiiro-gridLayout-${tableKey}`);\n if (saved) {\n const {\n order,\n pinned: savedPinned,\n columnVisibility: savedVisibility,\n } = JSON.parse(saved) as GridLayout;\n setPinned(savedPinned || []);\n\n // Restore column visibility if saved\n if (savedVisibility) {\n setColumnVisibilityModel(savedVisibility);\n }\n\n const orderedColumns = order\n .map(field => propColumns.find(c => c.field === field))\n .filter((c): c is GridColDef<T> => !!c);\n setColumns(orderedColumns);\n }\n } catch (error) {\n // Failed to load grid layout - using default\n }\n }, [propColumns, persistLayout, tableKey]);\n\n const saveLayout = useCallback(\n (\n cols: GridColDef<T>[],\n pinnedCols: string[],\n visibility?: Record<string, boolean>,\n ) => {\n if (!persistLayout) return;\n\n const layout: GridLayout = {\n order: cols.map(c => c.field),\n pinned: pinnedCols,\n columnVisibility: visibility || columnVisibilityModel,\n };\n localStorage.setItem(\n `apiiro-gridLayout-${tableKey}`,\n JSON.stringify(layout),\n );\n },\n [persistLayout, tableKey, columnVisibilityModel],\n );\n\n // Save column visibility changes to gridLayout\n useEffect(() => {\n if (persistLayout) {\n saveLayout(columns, pinned, columnVisibilityModel);\n }\n }, [columnVisibilityModel, persistLayout, saveLayout, columns, pinned]);\n\n const handleDragStart = (field: string) => setDragCol(field);\n\n const handleDragOver = (\n e: React.DragEvent<HTMLDivElement>,\n targetField: string,\n ) => {\n e.preventDefault();\n if (dragCol === targetField) return;\n const targetRect = e.currentTarget.getBoundingClientRect();\n const x = e.clientX - targetRect.left;\n setDropTarget(targetField);\n setDropSide(x < targetRect.width / 2 ? 'left' : 'right');\n };\n\n const handleDragLeave = () => setDropTarget(null);\n\n const handleDrop = (targetField: string) => {\n if (!dragCol || dragCol === targetField) return;\n\n const dragIsPinned = pinned.includes(dragCol);\n const targetIsPinned = pinned.includes(targetField);\n\n if (dragIsPinned !== targetIsPinned) {\n setDragCol(null);\n setDropTarget(null);\n return;\n }\n\n const currentList = dragIsPinned\n ? columns.filter(c => pinned.includes(c.field))\n : columns.filter(c => !pinned.includes(c.field));\n\n const dragIndex = currentList.findIndex(c => c.field === dragCol);\n const targetIndex = currentList.findIndex(c => c.field === targetField);\n\n const newIndex = dropSide === 'left' ? targetIndex : targetIndex + 1;\n const reordered = [...currentList];\n const [moved] = reordered.splice(dragIndex, 1);\n reordered.splice(newIndex, 0, moved);\n\n const finalColumns = dragIsPinned\n ? [...reordered, ...columns.filter(c => !pinned.includes(c.field))]\n : [...columns.filter(c => pinned.includes(c.field)), ...reordered];\n\n setColumns(finalColumns);\n setDragCol(null);\n setDropTarget(null);\n saveLayout(finalColumns, pinned);\n };\n\n const togglePin = useCallback(\n (field: string) => {\n setPinned(prev => {\n const next = prev.includes(field)\n ? prev.filter(f => f !== field)\n : [...prev, field];\n saveLayout(columns, next);\n return next;\n });\n },\n [columns, saveLayout],\n );\n\n const CustomColumnMenuWithProps = useCallback(\n (props: any) => {\n return (\n <CustomColumnMenu\n {...props}\n isPinned={pinned.includes(props.colDef.field)}\n onTogglePin={togglePin}\n />\n );\n },\n [pinned, togglePin],\n );\n\n const CustomPaginationComponent = useCallback(\n () => (\n <CustomPagination\n onPageSizeChange={pageSize => setPaginationModel({ page: 0, pageSize })}\n pageSizeOptions={pageSizeOptions}\n dataLabel={dataLabel}\n />\n ),\n [dataLabel, pageSizeOptions],\n );\n\n const finalColumns = columnReordering\n ? columns.map(col => ({\n ...col,\n renderHeader: () => (\n <Box\n draggable={columnReordering}\n onDragStart={() => handleDragStart(col.field)}\n onDragOver={e => handleDragOver(e, col.field)}\n onDragLeave={handleDragLeave}\n onDrop={() => handleDrop(col.field)}\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n cursor: columnReordering ? 'grab' : 'default',\n userSelect: 'none',\n position: 'relative',\n fontWeight:\n columnPinning && pinned.includes(col.field) ? 'bold' : 'normal',\n px: 1,\n '&::before': columnReordering\n ? {\n content: '\"\"',\n position: 'absolute',\n top: 0,\n bottom: 0,\n left:\n dropTarget === col.field && dropSide === 'left'\n ? 0\n : 'auto',\n right:\n dropTarget === col.field && dropSide === 'right'\n ? 0\n : 'auto',\n width: '3px',\n backgroundColor:\n dropTarget === col.field\n ? theme.palette.primary.main\n : 'transparent',\n transition: 'background 0.1s ease',\n }\n : {},\n }}\n >\n {col.headerName}\n </Box>\n ),\n }))\n : columns;\n\n const orderedColumns = columnPinning\n ? [\n ...finalColumns\n .filter(c => pinned.includes(c.field))\n .map(col => ({ ...col, resizable: false })),\n ...finalColumns.filter(c => !pinned.includes(c.field)),\n ]\n : finalColumns;\n\n // Sticky offsets\n const pinnedOffsets: Record<string, number> = {};\n let leftOffset = 0;\n for (const col of orderedColumns) {\n if (pinned.includes(col.field)) {\n pinnedOffsets[col.field] = leftOffset;\n leftOffset += col.minWidth || col.width || 200;\n }\n }\n\n // Create pinned column styles\n const pinnedColumnStyles: Record<string, any> = {};\n if (columnPinning) {\n pinned.forEach(field => {\n pinnedColumnStyles[`& [data-field=\"${field}\"]`] = {\n position: 'sticky',\n left: pinnedOffsets[field],\n zIndex: 9999,\n backgroundColor: backgroundColor,\n boxShadow: '2px 0 2px rgba(0,0,0,0.05)',\n };\n });\n }\n\n return (\n <Box\n sx={{\n height,\n width: '100%',\n overflowX: 'auto',\n }}\n >\n {quickSearch && (\n <CustomSearchToolbar\n apiRef={apiRef}\n placeholder={searchBarPlaceHolder}\n customFilters={customFilters}\n />\n )}\n <DataGridMUI\n key={tableKey}\n apiRef={apiRef}\n rows={propRows}\n columns={orderedColumns}\n initialState={{\n ...initialState,\n }}\n columnVisibilityModel={columnVisibilityModel}\n onColumnVisibilityModelChange={setColumnVisibilityModel}\n disableVirtualization\n getRowId={getRowId}\n loading={loading}\n paginationModel={paginationModel}\n onPaginationModelChange={setPaginationModel}\n pageSizeOptions={pageSizeOptions}\n onRowClick={onRowClick ? params => onRowClick(params.row) : undefined}\n onRowSelectionModelChange={\n onSelectionChange\n ? selectionModel => {\n const selectedIds = selectionModel.ids\n ? Array.from(selectionModel.ids)\n : [];\n const selectedRows = propRows.filter(row =>\n selectedIds.some(\n id =>\n String(getRowId ? getRowId(row) : row.id) === String(id),\n ),\n );\n onSelectionChange(selectedRows);\n }\n : undefined\n }\n slots={{\n ...(columnMenu && { columnMenu: CustomColumnMenuWithProps }),\n ...(customPagination && { pagination: CustomPaginationComponent }),\n noResultsOverlay: () => <NotFound />,\n loadingOverlay: () => (\n <Box\n display=\"flex\"\n height=\"100%\"\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <LogoSpinner />\n </Box>\n ),\n }}\n slotProps={{\n loadingOverlay: {\n variant: 'linear-progress',\n noRowsVariant: 'skeleton',\n },\n columnsManagement: {\n disableResetButton: true,\n searchInputProps: {\n type: 'text',\n },\n },\n }}\n sx={{\n backgroundColor,\n '&.MuiDataGrid-root': {\n borderRadius,\n minWidth: 'auto',\n },\n '& .MuiDataGrid-columnHeader:focus, & .MuiDataGrid-columnHeader:focus-within':\n {\n outline: 'none',\n },\n '&.MuiDataGrid-root .MuiDataGrid-columnHeader, &.MuiDataGrid-root .MuiDataGrid-filler':\n {\n backgroundColor: headerBackgroundColor,\n },\n // Column resize line styling\n '& .MuiDataGrid-columnSeparator--resizable': {\n '&:hover': {\n color: theme.palette.primary.main,\n },\n },\n '& .MuiDataGrid-columnSeparator--resizing': {\n color: theme.palette.primary.main,\n opacity: 1,\n },\n ...pinnedColumnStyles,\n }}\n />\n </Box>\n );\n}\n"],"names":["orderedColumns","finalColumns","DataGridMUI"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import MenuItem from '@mui/material/MenuItem';
3
+ import ListItemIcon from '@mui/material/ListItemIcon';
4
+ import ListItemText from '@mui/material/ListItemText';
5
+ import { PushPin, PushPinOutlined } from '@mui/icons-material';
6
+
7
+ function PinColumnMenuItem({
8
+ colDef,
9
+ onClick,
10
+ isPinned,
11
+ onTogglePin
12
+ }) {
13
+ const handleClick = (event) => {
14
+ onTogglePin(colDef.field);
15
+ onClick(event);
16
+ };
17
+ return /* @__PURE__ */ jsxs(MenuItem, { onClick: handleClick, children: [
18
+ /* @__PURE__ */ jsx(ListItemIcon, { children: isPinned ? /* @__PURE__ */ jsx(PushPin, { fontSize: "small" }) : /* @__PURE__ */ jsx(PushPinOutlined, { fontSize: "small" }) }),
19
+ /* @__PURE__ */ jsx(ListItemText, { children: isPinned ? "Remove Pin" : "Pin to left" })
20
+ ] });
21
+ }
22
+
23
+ export { PinColumnMenuItem };
24
+ //# sourceMappingURL=PinColumnMenuItem.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PinColumnMenuItem.esm.js","sources":["../../../src/components/DataGrid/PinColumnMenuItem.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 { MouseEvent } from 'react';\nimport MenuItem from '@mui/material/MenuItem';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport { PushPin, PushPinOutlined } from '@mui/icons-material';\nimport { PinColumnMenuItemProps } from './types';\n\nexport function PinColumnMenuItem({\n colDef,\n onClick,\n isPinned,\n onTogglePin,\n}: PinColumnMenuItemProps) {\n const handleClick = (event: MouseEvent<HTMLLIElement>) => {\n onTogglePin(colDef.field);\n onClick(event);\n };\n\n return (\n <MenuItem onClick={handleClick}>\n <ListItemIcon>\n {isPinned ? (\n <PushPin fontSize=\"small\" />\n ) : (\n <PushPinOutlined fontSize=\"small\" />\n )}\n </ListItemIcon>\n <ListItemText>{isPinned ? 'Remove Pin' : 'Pin to left'}</ListItemText>\n </MenuItem>\n );\n}\n"],"names":[],"mappings":";;;;;;AAsBO,SAAS,iBAAA,CAAkB;AAAA,EAChC,MAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA2B;AACzB,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAqC;AACxD,IAAA,WAAA,CAAY,OAAO,KAAK,CAAA;AACxB,IAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,EACf,CAAA;AAEA,EAAA,uBACE,IAAA,CAAC,QAAA,EAAA,EAAS,OAAA,EAAS,WAAA,EACjB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,YAAA,EAAA,EACE,QAAA,EAAA,QAAA,mBACC,GAAA,CAAC,OAAA,EAAA,EAAQ,QAAA,EAAS,OAAA,EAAQ,CAAA,mBAE1B,GAAA,CAAC,eAAA,EAAA,EAAgB,QAAA,EAAS,OAAA,EAAQ,CAAA,EAEtC,CAAA;AAAA,oBACA,GAAA,CAAC,YAAA,EAAA,EAAc,QAAA,EAAA,QAAA,GAAW,YAAA,GAAe,aAAA,EAAc;AAAA,GAAA,EACzD,CAAA;AAEJ;;;;"}
@@ -0,0 +1,34 @@
1
+ import { jsx, Fragment } from 'react/jsx-runtime';
2
+ import Box from '@mui/material/Box';
3
+ import { useTheme } from '@mui/material/styles';
4
+ import { formatDate } from '../utils/dateFormatter.esm.js';
5
+ import { SimpleTooltip } from './SimpleTooltip.esm.js';
6
+
7
+ const DueDateDisplay = ({ dateString }) => {
8
+ const theme = useTheme();
9
+ const rawDate = dateString;
10
+ if (!rawDate) {
11
+ return /* @__PURE__ */ jsx(SimpleTooltip, { title: "Not Set", centered: true, children: "Not Set" });
12
+ }
13
+ const dueDate = new Date(rawDate);
14
+ const isValidDate = !Number.isNaN(dueDate.getTime());
15
+ if (!isValidDate) {
16
+ return /* @__PURE__ */ jsx(SimpleTooltip, { title: "Not Set", centered: true, children: "Not Set" });
17
+ }
18
+ const formattedDate = formatDate(rawDate);
19
+ const isOverdue = dueDate < /* @__PURE__ */ new Date();
20
+ const tooltip = isOverdue ? "SLA due date exceeded" : "SLA due date";
21
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(SimpleTooltip, { title: tooltip, centered: true, children: /* @__PURE__ */ jsx(
22
+ Box,
23
+ {
24
+ component: "span",
25
+ sx: {
26
+ color: isOverdue ? theme.palette.error.main : "inherit"
27
+ },
28
+ children: formattedDate
29
+ }
30
+ ) }) });
31
+ };
32
+
33
+ export { DueDateDisplay };
34
+ //# sourceMappingURL=DueDate.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DueDate.esm.js","sources":["../../src/components/DueDate.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 { useTheme } from '@mui/material/styles';\nimport { formatDate } from '../utils/dateFormatter';\nimport SimpleTooltip from './SimpleTooltip';\n\nexport const DueDateDisplay = ({ dateString }: { dateString: string }) => {\n const theme = useTheme();\n const rawDate = dateString;\n\n if (!rawDate) {\n return (\n <SimpleTooltip title=\"Not Set\" centered>\n Not Set\n </SimpleTooltip>\n );\n }\n\n const dueDate = new Date(rawDate);\n const isValidDate = !Number.isNaN(dueDate.getTime());\n\n if (!isValidDate) {\n return (\n <SimpleTooltip title=\"Not Set\" centered>\n Not Set\n </SimpleTooltip>\n );\n }\n\n const formattedDate = formatDate(rawDate);\n const isOverdue = dueDate < new Date();\n const tooltip = isOverdue ? 'SLA due date exceeded' : 'SLA due date';\n\n return (\n <>\n <SimpleTooltip title={tooltip} centered>\n <Box\n component=\"span\"\n sx={{\n color: isOverdue ? theme.palette.error.main : 'inherit',\n }}\n >\n {formattedDate}\n </Box>\n </SimpleTooltip>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;AAoBO,MAAM,cAAA,GAAiB,CAAC,EAAE,UAAA,EAAW,KAA8B;AACxE,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,OAAA,GAAU,UAAA;AAEhB,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,2BACG,aAAA,EAAA,EAAc,KAAA,EAAM,SAAA,EAAU,QAAA,EAAQ,MAAC,QAAA,EAAA,SAAA,EAExC,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,CAAK,OAAO,CAAA;AAChC,EAAA,MAAM,cAAc,CAAC,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA;AAEnD,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,2BACG,aAAA,EAAA,EAAc,KAAA,EAAM,SAAA,EAAU,QAAA,EAAQ,MAAC,QAAA,EAAA,SAAA,EAExC,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,aAAA,GAAgB,WAAW,OAAO,CAAA;AACxC,EAAA,MAAM,SAAA,GAAY,OAAA,mBAAU,IAAI,IAAA,EAAK;AACrC,EAAA,MAAM,OAAA,GAAU,YAAY,uBAAA,GAA0B,cAAA;AAEtD,EAAA,uCAEI,QAAA,kBAAA,GAAA,CAAC,aAAA,EAAA,EAAc,KAAA,EAAO,OAAA,EAAS,UAAQ,IAAA,EACrC,QAAA,kBAAA,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,MAAA;AAAA,MACV,EAAA,EAAI;AAAA,QACF,KAAA,EAAO,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,MAAM,IAAA,GAAO;AAAA,OAChD;AAAA,MAEC,QAAA,EAAA;AAAA;AAAA,KAEL,CAAA,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,27 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Header as Header$1 } from '@backstage/core-components';
3
+ import { useTheme } from '@mui/material/styles';
4
+ import { ApiiroLogo } from '../assets/apiiroLogo/apiiroLogo.esm.js';
5
+ import '@mui/material/SvgIcon';
6
+ import { getHeaderBackground } from '../theme/themeUtils.esm.js';
7
+
8
+ const Header = () => {
9
+ const theme = useTheme();
10
+ const headerBackground = getHeaderBackground(theme);
11
+ return /* @__PURE__ */ jsx(
12
+ Header$1,
13
+ {
14
+ title: /* @__PURE__ */ jsx("div", { style: { justifyContent: "center", alignItems: "center" }, children: /* @__PURE__ */ jsx(ApiiroLogo, {}) }),
15
+ pageTitleOverride: "Apiiro",
16
+ style: {
17
+ backgroundImage: "none",
18
+ backgroundColor: headerBackground,
19
+ justifyContent: "center",
20
+ alignItems: "center"
21
+ }
22
+ }
23
+ );
24
+ };
25
+
26
+ export { Header };
27
+ //# sourceMappingURL=Header.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Header.esm.js","sources":["../../src/components/Header.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 { Header as CoreHeader } from '@backstage/core-components';\nimport { useTheme } from '@mui/material/styles';\nimport { ApiiroLogo } from '../assets/apiiroLogo';\nimport { getHeaderBackground } from '../theme/themeUtils';\n\nexport const Header = () => {\n const theme = useTheme();\n const headerBackground = getHeaderBackground(theme);\n\n return (\n <CoreHeader\n title={\n <div style={{ justifyContent: 'center', alignItems: 'center' }}>\n <ApiiroLogo />\n </div>\n }\n pageTitleOverride=\"Apiiro\"\n style={{\n backgroundImage: 'none',\n backgroundColor: headerBackground,\n justifyContent: 'center',\n alignItems: 'center',\n }}\n />\n );\n};\n"],"names":["CoreHeader"],"mappings":";;;;;;;AAoBO,MAAM,SAAS,MAAM;AAC1B,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,gBAAA,GAAmB,oBAAoB,KAAK,CAAA;AAElD,EAAA,uBACE,GAAA;AAAA,IAACA,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,kBACE,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,cAAA,EAAgB,QAAA,EAAU,UAAA,EAAY,QAAA,EAAS,EAC3D,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,CAAA,EACd,CAAA;AAAA,MAEF,iBAAA,EAAkB,QAAA;AAAA,MAClB,KAAA,EAAO;AAAA,QACL,eAAA,EAAiB,MAAA;AAAA,QACjB,eAAA,EAAiB,gBAAA;AAAA,QACjB,cAAA,EAAgB,QAAA;AAAA,QAChB,UAAA,EAAY;AAAA;AACd;AAAA,GACF;AAEJ;;;;"}