@backstage/plugin-mui-to-bui 0.0.0-nightly-20250927023623

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 ADDED
@@ -0,0 +1,16 @@
1
+ # @backstage/plugin-mui-to-bui
2
+
3
+ ## 0.0.0-nightly-20250927023623
4
+
5
+ ### Minor Changes
6
+
7
+ - d5cbdba: This is the first release of the Material UI to Backstage UI migration helper plugin. It adds a new page at `/mui-to-bui` that converts an existing MUI v5 theme into Backstage UI (BUI) CSS variables, with live preview and copy/download.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @backstage/ui@0.0.0-nightly-20250927023623
13
+ - @backstage/theme@0.0.0-nightly-20250927023623
14
+ - @backstage/core-compat-api@0.0.0-nightly-20250927023623
15
+ - @backstage/frontend-plugin-api@0.0.0-nightly-20250927023623
16
+ - @backstage/core-plugin-api@0.0.0-nightly-20250927023623
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # mui-to-bui
2
+
3
+ ## Description
4
+
5
+ The Backstage UI Themer helps you convert an existing MUI v5 theme into Backstage UI (BUI) CSS custom properties. It detects installed app themes, generates a complete set of BUI CSS variables for each theme (light and dark), and lets you preview how common BUI components look with your colors and typography. You can copy the generated CSS to the clipboard or download it as a `.css` file, and it works with both the old and new Backstage frontend systems without requiring any backend setup.
6
+
7
+ ## Installation
8
+
9
+ ### 1) Add the dependency to your app
10
+
11
+ Run this from your Backstage repo root:
12
+
13
+ ```bash
14
+ yarn add --cwd packages/app @backstage/plugin-mui-to-bui
15
+ ```
16
+
17
+ ### 2) Wire it up depending on your frontend system
18
+
19
+ #### Old frontend system (legacy `App.tsx` with `<FlatRoutes>`)
20
+
21
+ Add a route for the page in your app:
22
+
23
+ ```tsx
24
+ // packages/app/src/App.tsx
25
+ import React from 'react';
26
+ import { Route } from 'react-router-dom';
27
+ import { FlatRoutes } from '@backstage/core-app-api';
28
+ import { BuiThemerPage } from '@backstage/plugin-mui-to-bui';
29
+
30
+ export const App = () => (
31
+ <FlatRoutes>
32
+ {/* ...your other routes */}
33
+ <Route path="/mui-to-bui" element={<BuiThemerPage />} />
34
+ </FlatRoutes>
35
+ );
36
+ ```
37
+
38
+ #### New frontend system
39
+
40
+ If package discovery is enabled in your app, this plugin is picked up automatically after installation — no code changes required. Just navigate to `/mui-to-bui`.
41
+
42
+ If you prefer explicit registration (or don't use discovery), register the plugin as a feature. The page route (`/mui-to-bui`) is provided by the plugin.
43
+
44
+ ```tsx
45
+ // packages/app/src/App.tsx (or your app entry where you call createApp)
46
+ import React from 'react';
47
+ import { createApp } from '@backstage/frontend-defaults';
48
+ import buiThemerPlugin from '@backstage/plugin-mui-to-bui';
49
+
50
+ const app = createApp({
51
+ features: [
52
+ // ...other features
53
+ buiThemerPlugin,
54
+ ],
55
+ });
56
+
57
+ export default app.createRoot();
58
+ ```
59
+
60
+ ## Accessing the Themer page
61
+
62
+ - Navigate to `/mui-to-bui` in your Backstage app (for example `http://localhost:3000/mui-to-bui`).
63
+ - Optional: Add a sidebar/link in your app that points to `/mui-to-bui` if you want a permanent navigation entry.
@@ -0,0 +1,128 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { Flex, Card, CardHeader, CardBody, Button, TextField, Select, Checkbox, RadioGroup, Radio, TagGroup, Tag, Box, Text } from '@backstage/ui';
3
+
4
+ function BuiThemePreview({ mode, styleObject }) {
5
+ return /* @__PURE__ */ jsx(
6
+ "div",
7
+ {
8
+ "data-theme-mode": mode,
9
+ style: {
10
+ // Apply the generated CSS variables directly to this container
11
+ // This creates a scoped context where the variables take precedence
12
+ ...styleObject,
13
+ width: "100%",
14
+ backgroundColor: "var(--bui-bg-surface-2)",
15
+ padding: "var(--bui-space-3)",
16
+ borderRadius: "var(--bui-radius-2)",
17
+ border: "1px solid var(--bui-border)"
18
+ },
19
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "4", children: [
20
+ /* @__PURE__ */ jsxs(Card, { children: [
21
+ /* @__PURE__ */ jsx(CardHeader, { children: "Button Variants" }),
22
+ /* @__PURE__ */ jsx(CardBody, { children: /* @__PURE__ */ jsxs(Flex, { gap: "3", children: [
23
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", children: [
24
+ /* @__PURE__ */ jsx(Button, { variant: "primary", children: "Primary" }),
25
+ /* @__PURE__ */ jsx(Button, { isDisabled: true, variant: "primary", children: "Disabled" })
26
+ ] }),
27
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", children: [
28
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", children: "Secondary" }),
29
+ /* @__PURE__ */ jsx(Button, { isDisabled: true, variant: "secondary", children: "Disabled" })
30
+ ] }),
31
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "2", children: [
32
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", children: "Tertiary" }),
33
+ /* @__PURE__ */ jsx(Button, { isDisabled: true, variant: "tertiary", children: "Disabled" })
34
+ ] })
35
+ ] }) })
36
+ ] }),
37
+ /* @__PURE__ */ jsxs(Card, { children: [
38
+ /* @__PURE__ */ jsx(CardHeader, { children: "Form Inputs" }),
39
+ /* @__PURE__ */ jsx(CardBody, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "3", children: [
40
+ /* @__PURE__ */ jsx(TextField, { label: "Text Input", placeholder: "Enter some text" }),
41
+ /* @__PURE__ */ jsx(
42
+ Select,
43
+ {
44
+ label: "Select Input",
45
+ options: [
46
+ { value: "option1", label: "Option 1" },
47
+ { value: "option2", label: "Option 2" },
48
+ { value: "option3", label: "Option 3" }
49
+ ]
50
+ }
51
+ ),
52
+ /* @__PURE__ */ jsx(Checkbox, { label: "Checkbox Option" }),
53
+ /* @__PURE__ */ jsxs(RadioGroup, { label: "Radio Group", orientation: "horizontal", children: [
54
+ /* @__PURE__ */ jsx(Radio, { value: "option-1", children: "Option 1" }),
55
+ /* @__PURE__ */ jsx(Radio, { value: "option-2", children: "Option 2" }),
56
+ /* @__PURE__ */ jsx(Radio, { value: "option-3", children: "Option 3" })
57
+ ] })
58
+ ] }) })
59
+ ] }),
60
+ /* @__PURE__ */ jsxs(Card, { children: [
61
+ /* @__PURE__ */ jsx(CardHeader, { children: "Tag Variants" }),
62
+ /* @__PURE__ */ jsx(CardBody, { children: /* @__PURE__ */ jsx(Flex, { gap: "3", children: /* @__PURE__ */ jsxs(TagGroup, { children: [
63
+ /* @__PURE__ */ jsx(Tag, { children: "Default" }),
64
+ /* @__PURE__ */ jsx(
65
+ Tag,
66
+ {
67
+ style: {
68
+ backgroundColor: "var(--bui-bg-danger)",
69
+ color: "var(--bui-fg-danger)",
70
+ border: `1px solid var(--bui-border-danger)`
71
+ },
72
+ children: "Danger"
73
+ }
74
+ ),
75
+ /* @__PURE__ */ jsx(
76
+ Tag,
77
+ {
78
+ style: {
79
+ backgroundColor: "var(--bui-bg-warning)",
80
+ color: "var(--bui-fg-warning)",
81
+ border: `1px solid var(--bui-border-warning)`
82
+ },
83
+ children: "Warning"
84
+ }
85
+ ),
86
+ /* @__PURE__ */ jsx(
87
+ Tag,
88
+ {
89
+ style: {
90
+ backgroundColor: "var(--bui-bg-success)",
91
+ color: "var(--bui-fg-success)",
92
+ border: `1px solid var(--bui-border-success)`
93
+ },
94
+ children: "Success"
95
+ }
96
+ )
97
+ ] }) }) })
98
+ ] }),
99
+ /* @__PURE__ */ jsxs(Card, { children: [
100
+ /* @__PURE__ */ jsx(CardHeader, { children: "Text Variants" }),
101
+ /* @__PURE__ */ jsx(CardBody, { children: /* @__PURE__ */ jsxs(
102
+ Box,
103
+ {
104
+ style: {
105
+ display: "grid",
106
+ gridTemplateColumns: "1fr 1fr",
107
+ gap: "var(--bui-space-3)"
108
+ },
109
+ children: [
110
+ /* @__PURE__ */ jsx(Text, { variant: "title-x-small", children: "Title X Small" }),
111
+ /* @__PURE__ */ jsx(Text, { variant: "body-x-small", children: "Body X Small" }),
112
+ /* @__PURE__ */ jsx(Text, { variant: "title-small", children: "Title Small" }),
113
+ /* @__PURE__ */ jsx(Text, { variant: "body-small", children: "Body Small" }),
114
+ /* @__PURE__ */ jsx(Text, { variant: "title-medium", children: "Title Medium" }),
115
+ /* @__PURE__ */ jsx(Text, { variant: "body-medium", children: "Body Medium" }),
116
+ /* @__PURE__ */ jsx(Text, { variant: "title-large", children: "Title Large" }),
117
+ /* @__PURE__ */ jsx(Text, { variant: "body-large", children: "Body Large" })
118
+ ]
119
+ }
120
+ ) })
121
+ ] })
122
+ ] })
123
+ }
124
+ );
125
+ }
126
+
127
+ export { BuiThemePreview };
128
+ //# sourceMappingURL=BuiThemePreview.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuiThemePreview.esm.js","sources":["../../../src/components/BuiThemerPage/BuiThemePreview.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 */\n\nimport {\n Box,\n Button,\n Card,\n CardBody,\n CardHeader,\n Checkbox,\n Flex,\n Radio,\n RadioGroup,\n Select,\n Text,\n TextField,\n TagGroup,\n Tag,\n} from '@backstage/ui';\n\ninterface IsolatedPreviewProps {\n mode: 'light' | 'dark';\n styleObject: Record<string, string>;\n}\n\nexport function BuiThemePreview({ mode, styleObject }: IsolatedPreviewProps) {\n return (\n <div\n // Setting the theme mode ensures that the correct defaults are picked up from the BUI theme\n data-theme-mode={mode}\n style={{\n // Apply the generated CSS variables directly to this container\n // This creates a scoped context where the variables take precedence\n ...styleObject,\n width: '100%',\n backgroundColor: 'var(--bui-bg-surface-2)',\n padding: 'var(--bui-space-3)',\n borderRadius: 'var(--bui-radius-2)',\n border: '1px solid var(--bui-border)',\n }}\n >\n <Flex direction=\"column\" gap=\"4\">\n <Card>\n <CardHeader>Button Variants</CardHeader>\n <CardBody>\n <Flex gap=\"3\">\n <Flex direction=\"column\" gap=\"2\">\n <Button variant=\"primary\">Primary</Button>\n <Button isDisabled variant=\"primary\">\n Disabled\n </Button>\n </Flex>\n <Flex direction=\"column\" gap=\"2\">\n <Button variant=\"secondary\">Secondary</Button>\n <Button isDisabled variant=\"secondary\">\n Disabled\n </Button>\n </Flex>\n <Flex direction=\"column\" gap=\"2\">\n <Button variant=\"tertiary\">Tertiary</Button>\n <Button isDisabled variant=\"tertiary\">\n Disabled\n </Button>\n </Flex>\n </Flex>\n </CardBody>\n </Card>\n\n <Card>\n <CardHeader>Form Inputs</CardHeader>\n <CardBody>\n <Flex direction=\"column\" gap=\"3\">\n <TextField label=\"Text Input\" placeholder=\"Enter some text\" />\n <Select\n label=\"Select Input\"\n options={[\n { value: 'option1', label: 'Option 1' },\n { value: 'option2', label: 'Option 2' },\n { value: 'option3', label: 'Option 3' },\n ]}\n />\n <Checkbox label=\"Checkbox Option\" />\n <RadioGroup label=\"Radio Group\" orientation=\"horizontal\">\n <Radio value=\"option-1\">Option 1</Radio>\n <Radio value=\"option-2\">Option 2</Radio>\n <Radio value=\"option-3\">Option 3</Radio>\n </RadioGroup>\n </Flex>\n </CardBody>\n </Card>\n\n <Card>\n <CardHeader>Tag Variants</CardHeader>\n <CardBody>\n <Flex gap=\"3\">\n <TagGroup>\n <Tag>Default</Tag>\n <Tag\n style={{\n backgroundColor: 'var(--bui-bg-danger)',\n color: 'var(--bui-fg-danger)',\n border: `1px solid var(--bui-border-danger)`,\n }}\n >\n Danger\n </Tag>\n <Tag\n style={{\n backgroundColor: 'var(--bui-bg-warning)',\n color: 'var(--bui-fg-warning)',\n border: `1px solid var(--bui-border-warning)`,\n }}\n >\n Warning\n </Tag>\n <Tag\n style={{\n backgroundColor: 'var(--bui-bg-success)',\n color: 'var(--bui-fg-success)',\n border: `1px solid var(--bui-border-success)`,\n }}\n >\n Success\n </Tag>\n </TagGroup>\n </Flex>\n </CardBody>\n </Card>\n\n <Card>\n <CardHeader>Text Variants</CardHeader>\n <CardBody>\n <Box\n style={{\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n gap: 'var(--bui-space-3)',\n }}\n >\n <Text variant=\"title-x-small\">Title X Small</Text>\n <Text variant=\"body-x-small\">Body X Small</Text>\n <Text variant=\"title-small\">Title Small</Text>\n <Text variant=\"body-small\">Body Small</Text>\n <Text variant=\"title-medium\">Title Medium</Text>\n <Text variant=\"body-medium\">Body Medium</Text>\n <Text variant=\"title-large\">Title Large</Text>\n <Text variant=\"body-large\">Body Large</Text>\n </Box>\n </CardBody>\n </Card>\n </Flex>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useApi, appThemeApiRef } from '@backstage/core-plugin-api';
3
+ import { Container, HeaderPage, Box, Text, Card, Flex } from '@backstage/ui';
4
+ import { ThemeContent } from './ThemeContent.esm.js';
5
+ import { MuiThemeExtractor } from './MuiThemeExtractor.esm.js';
6
+
7
+ const BuiThemerPage = () => {
8
+ const appThemeApi = useApi(appThemeApiRef);
9
+ const installedThemes = appThemeApi.getInstalledThemes();
10
+ return /* @__PURE__ */ jsxs(Container, { children: [
11
+ /* @__PURE__ */ jsx(HeaderPage, { title: "BUI Theme Converter" }),
12
+ /* @__PURE__ */ jsx(Box, { m: "4", children: /* @__PURE__ */ jsx(Text, { variant: "body-medium", color: "secondary", children: "Convert your MUI v5 theme into BUI CSS variables. Pick a theme to view and export the generated BUI CSS variable definitions for use in your project." }) }),
13
+ /* @__PURE__ */ jsx(Box, { mt: "4", children: installedThemes.length === 0 ? /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(Box, { p: "4", children: /* @__PURE__ */ jsx(Text, { children: "No themes found. Please install some themes in your Backstage app." }) }) }) : /* @__PURE__ */ jsx(Flex, { direction: "column", gap: "4", children: installedThemes.map((theme) => /* @__PURE__ */ jsx(MuiThemeExtractor, { appTheme: theme, children: (muiTheme) => /* @__PURE__ */ jsx(
14
+ ThemeContent,
15
+ {
16
+ themeId: theme.id,
17
+ themeTitle: theme.title,
18
+ variant: theme.variant,
19
+ muiTheme
20
+ },
21
+ theme.id
22
+ ) }, theme.id)) }) })
23
+ ] });
24
+ };
25
+
26
+ export { BuiThemerPage };
27
+ //# sourceMappingURL=BuiThemerPage.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuiThemerPage.esm.js","sources":["../../../src/components/BuiThemerPage/BuiThemerPage.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 */\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport { appThemeApiRef } from '@backstage/core-plugin-api';\nimport { Box, Card, Container, Flex, HeaderPage, Text } from '@backstage/ui';\nimport { ThemeContent } from './ThemeContent';\nimport { MuiThemeExtractor } from './MuiThemeExtractor';\n\nexport const BuiThemerPage = () => {\n const appThemeApi = useApi(appThemeApiRef);\n const installedThemes = appThemeApi.getInstalledThemes();\n\n return (\n <Container>\n <HeaderPage title=\"BUI Theme Converter\" />\n <Box m=\"4\">\n <Text variant=\"body-medium\" color=\"secondary\">\n Convert your MUI v5 theme into BUI CSS variables. Pick a theme to view\n and export the generated BUI CSS variable definitions for use in your\n project.\n </Text>\n </Box>\n\n <Box mt=\"4\">\n {installedThemes.length === 0 ? (\n <Card>\n <Box p=\"4\">\n <Text>\n No themes found. Please install some themes in your Backstage\n app.\n </Text>\n </Box>\n </Card>\n ) : (\n <Flex direction=\"column\" gap=\"4\">\n {installedThemes.map(theme => (\n <MuiThemeExtractor key={theme.id} appTheme={theme}>\n {muiTheme => (\n <ThemeContent\n key={theme.id}\n themeId={theme.id}\n themeTitle={theme.title}\n variant={theme.variant}\n muiTheme={muiTheme}\n />\n )}\n </MuiThemeExtractor>\n ))}\n </Flex>\n )}\n </Box>\n </Container>\n );\n};\n"],"names":[],"mappings":";;;;;;AAsBO,MAAM,gBAAgB,MAAM;AACjC,EAAA,MAAM,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAA,MAAM,eAAA,GAAkB,YAAY,kBAAA,EAAmB;AAEvD,EAAA,4BACG,SAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAM,qBAAA,EAAsB,CAAA;AAAA,oBACxC,GAAA,CAAC,GAAA,EAAA,EAAI,CAAA,EAAE,GAAA,EACL,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,aAAA,EAAc,KAAA,EAAM,WAAA,EAAY,QAAA,EAAA,uJAAA,EAI9C,CAAA,EACF,CAAA;AAAA,oBAEA,GAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAG,GAAA,EACL,0BAAgB,MAAA,KAAW,CAAA,mBAC1B,GAAA,CAAC,IAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAI,CAAA,EAAE,GAAA,EACL,8BAAC,IAAA,EAAA,EAAK,QAAA,EAAA,oEAAA,EAGN,CAAA,EACF,CAAA,EACF,CAAA,mBAEA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,UAAS,GAAA,EAAI,GAAA,EAC1B,QAAA,EAAA,eAAA,CAAgB,GAAA,CAAI,CAAA,KAAA,qBACnB,GAAA,CAAC,iBAAA,EAAA,EAAiC,QAAA,EAAU,OACzC,QAAA,EAAA,CAAA,QAAA,qBACC,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QAEC,SAAS,KAAA,CAAM,EAAA;AAAA,QACf,YAAY,KAAA,CAAM,KAAA;AAAA,QAClB,SAAS,KAAA,CAAM,OAAA;AAAA,QACf;AAAA,OAAA;AAAA,MAJK,KAAA,CAAM;AAAA,KAKb,EAAA,EARoB,KAAA,CAAM,EAU9B,CACD,GACH,CAAA,EAEJ;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,25 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { useTheme } from '@mui/material/styles';
4
+
5
+ function MuiThemeExtractor(props) {
6
+ const { appTheme, children } = props;
7
+ const [theme, setTheme] = useState(null);
8
+ const { Provider } = appTheme;
9
+ if (theme) {
10
+ return children(theme);
11
+ }
12
+ return /* @__PURE__ */ jsx(Provider, { children: /* @__PURE__ */ jsx(MuiThemeExtractorInner, { setTheme }) });
13
+ }
14
+ function MuiThemeExtractorInner({
15
+ setTheme
16
+ }) {
17
+ const theme = useTheme();
18
+ useEffect(() => {
19
+ setTheme(theme);
20
+ }, [theme, setTheme]);
21
+ return null;
22
+ }
23
+
24
+ export { MuiThemeExtractor };
25
+ //# sourceMappingURL=MuiThemeExtractor.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MuiThemeExtractor.esm.js","sources":["../../../src/components/BuiThemerPage/MuiThemeExtractor.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 */\n\nimport { useEffect, useState, JSX } from 'react';\nimport { AppTheme } from '@backstage/core-plugin-api';\nimport { Theme, useTheme } from '@mui/material/styles';\n\nexport function MuiThemeExtractor(props: {\n appTheme: AppTheme;\n children: (theme: Theme) => JSX.Element;\n}): JSX.Element {\n const { appTheme, children } = props;\n const [theme, setTheme] = useState<Theme | null>(null);\n const { Provider } = appTheme;\n if (theme) {\n return children(theme);\n }\n\n return (\n <Provider>\n <MuiThemeExtractorInner setTheme={setTheme} />\n </Provider>\n );\n}\n\nfunction MuiThemeExtractorInner({\n setTheme,\n}: {\n setTheme: (theme: Theme) => void;\n}) {\n const theme = useTheme();\n useEffect(() => {\n setTheme(theme);\n }, [theme, setTheme]);\n return null;\n}\n"],"names":[],"mappings":";;;;AAoBO,SAAS,kBAAkB,KAAA,EAGlB;AACd,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAS,GAAI,KAAA;AAC/B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,EAAE,UAAS,GAAI,QAAA;AACrB,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAO,SAAS,KAAK,CAAA;AAAA,EACvB;AAEA,EAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,sBAAA,EAAA,EAAuB,UAAoB,CAAA,EAC9C,CAAA;AAEJ;AAEA,SAAS,sBAAA,CAAuB;AAAA,EAC9B;AACF,CAAA,EAEG;AACD,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,QAAA,CAAS,KAAK,CAAA;AAAA,EAChB,CAAA,EAAG,CAAC,KAAA,EAAO,QAAQ,CAAC,CAAA;AACpB,EAAA,OAAO,IAAA;AACT;;;;"}
@@ -0,0 +1,80 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState, useMemo, useCallback } from 'react';
3
+ import { Card, Box, Flex, Text, Button, Tabs, TabList, Tab, TabPanel } from '@backstage/ui';
4
+ import { convertMuiToBuiTheme } from './convertMuiToBuiTheme.esm.js';
5
+ import { BuiThemePreview } from './BuiThemePreview.esm.js';
6
+
7
+ function ThemeContent({
8
+ themeId,
9
+ themeTitle,
10
+ variant,
11
+ muiTheme
12
+ }) {
13
+ const [activeTab, setActiveTab] = useState("css");
14
+ const { css, styleObject } = useMemo(() => {
15
+ return convertMuiToBuiTheme(muiTheme);
16
+ }, [muiTheme]);
17
+ const handleCopy = useCallback(() => {
18
+ window.navigator.clipboard.writeText(css);
19
+ }, [css]);
20
+ const handleDownload = useCallback(() => {
21
+ const blob = new Blob([css], { type: "text/css" });
22
+ const url = URL.createObjectURL(blob);
23
+ const a = document.createElement("a");
24
+ a.href = url;
25
+ a.download = `bui-theme-${themeId}.css`;
26
+ document.body.appendChild(a);
27
+ a.click();
28
+ document.body.removeChild(a);
29
+ URL.revokeObjectURL(url);
30
+ }, [css, themeId]);
31
+ return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(Box, { p: "6", children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: "4", children: [
32
+ /* @__PURE__ */ jsxs(Flex, { justify: "between", align: "center", children: [
33
+ /* @__PURE__ */ jsx(Text, { variant: "title-medium", children: themeTitle }),
34
+ /* @__PURE__ */ jsxs(Text, { variant: "body-small", color: "secondary", children: [
35
+ variant,
36
+ " theme"
37
+ ] })
38
+ ] }),
39
+ /* @__PURE__ */ jsxs(Flex, { gap: "3", children: [
40
+ /* @__PURE__ */ jsx(Button, { onClick: handleCopy, variant: "secondary", children: "Copy CSS" }),
41
+ /* @__PURE__ */ jsx(Button, { onClick: handleDownload, variant: "secondary", children: "Download CSS" })
42
+ ] }),
43
+ /* @__PURE__ */ jsxs(
44
+ Tabs,
45
+ {
46
+ selectedKey: activeTab,
47
+ onSelectionChange: (key) => setActiveTab(key),
48
+ children: [
49
+ /* @__PURE__ */ jsxs(TabList, { children: [
50
+ /* @__PURE__ */ jsx(Tab, { id: "css", children: "Generated CSS" }),
51
+ /* @__PURE__ */ jsx(Tab, { id: "preview", children: "Live Preview" })
52
+ ] }),
53
+ /* @__PURE__ */ jsx(TabPanel, { id: "css", children: /* @__PURE__ */ jsx(
54
+ Box,
55
+ {
56
+ p: "3",
57
+ style: {
58
+ backgroundColor: "var(--bui-bg-surface-2)",
59
+ border: "1px solid var(--bui-border)",
60
+ borderRadius: "var(--bui-radius-2)",
61
+ fontFamily: "monospace",
62
+ fontSize: "14px",
63
+ lineHeight: "1.5",
64
+ height: "600px",
65
+ overflow: "auto",
66
+ whiteSpace: "pre-wrap",
67
+ wordBreak: "break-all"
68
+ },
69
+ children: css
70
+ }
71
+ ) }),
72
+ /* @__PURE__ */ jsx(TabPanel, { id: "preview", children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(BuiThemePreview, { mode: variant, styleObject }) }) })
73
+ ]
74
+ }
75
+ )
76
+ ] }) }) });
77
+ }
78
+
79
+ export { ThemeContent };
80
+ //# sourceMappingURL=ThemeContent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ThemeContent.esm.js","sources":["../../../src/components/BuiThemerPage/ThemeContent.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 */\n\nimport { useMemo, useState, useCallback } from 'react';\nimport { Theme } from '@mui/material/styles';\nimport {\n Box,\n Button,\n Card,\n Flex,\n Text,\n Tabs,\n TabList,\n Tab,\n TabPanel,\n} from '@backstage/ui';\nimport { convertMuiToBuiTheme } from './convertMuiToBuiTheme';\nimport { BuiThemePreview } from './BuiThemePreview';\n\ninterface ThemeContentProps {\n themeId: string;\n themeTitle: string;\n variant: 'light' | 'dark';\n muiTheme: Theme;\n}\n\nexport function ThemeContent({\n themeId,\n themeTitle,\n variant,\n muiTheme,\n}: ThemeContentProps) {\n const [activeTab, setActiveTab] = useState<string>('css');\n\n const { css, styleObject } = useMemo(() => {\n return convertMuiToBuiTheme(muiTheme);\n }, [muiTheme]);\n\n const handleCopy = useCallback(() => {\n window.navigator.clipboard.writeText(css);\n }, [css]);\n\n const handleDownload = useCallback(() => {\n const blob = new Blob([css], { type: 'text/css' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `bui-theme-${themeId}.css`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n }, [css, themeId]);\n\n return (\n <Card>\n <Box p=\"6\">\n <Flex direction=\"column\" gap=\"4\">\n <Flex justify=\"between\" align=\"center\">\n <Text variant=\"title-medium\">{themeTitle}</Text>\n <Text variant=\"body-small\" color=\"secondary\">\n {variant} theme\n </Text>\n </Flex>\n\n <Flex gap=\"3\">\n <Button onClick={handleCopy} variant=\"secondary\">\n Copy CSS\n </Button>\n <Button onClick={handleDownload} variant=\"secondary\">\n Download CSS\n </Button>\n </Flex>\n\n <Tabs\n selectedKey={activeTab}\n onSelectionChange={key => setActiveTab(key as string)}\n >\n <TabList>\n <Tab id=\"css\">Generated CSS</Tab>\n <Tab id=\"preview\">Live Preview</Tab>\n </TabList>\n\n <TabPanel id=\"css\">\n <Box\n p=\"3\"\n style={{\n backgroundColor: 'var(--bui-bg-surface-2)',\n border: '1px solid var(--bui-border)',\n borderRadius: 'var(--bui-radius-2)',\n fontFamily: 'monospace',\n fontSize: '14px',\n lineHeight: '1.5',\n height: '600px',\n overflow: 'auto',\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n }}\n >\n {css}\n </Box>\n </TabPanel>\n\n <TabPanel id=\"preview\">\n <Box>\n <BuiThemePreview mode={variant} styleObject={styleObject} />\n </Box>\n </TabPanel>\n </Tabs>\n </Flex>\n </Box>\n </Card>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import { alpha, blend } from '@mui/system/colorManipulator';
2
+
3
+ function convertMuiToBuiTheme(theme) {
4
+ const styleObject = generateBuiVariables(theme);
5
+ const selector = theme.palette.mode === "dark" ? "[data-theme-mode='dark']" : ":root";
6
+ const css = `${selector} {
7
+ ${Object.entries(styleObject).map(([key, value]) => ` ${key}: ${value};`).join("\n")}
8
+ }`;
9
+ return { css, styleObject };
10
+ }
11
+ function generateBuiVariables(theme) {
12
+ const styleObject = {};
13
+ if (theme.typography.fontFamily) {
14
+ styleObject["--bui-font-regular"] = theme.typography.fontFamily;
15
+ }
16
+ if (theme.typography.fontWeightRegular) {
17
+ styleObject["--bui-font-weight-regular"] = String(
18
+ theme.typography.fontWeightRegular
19
+ );
20
+ }
21
+ if (theme.typography.fontWeightBold) {
22
+ styleObject["--bui-font-weight-bold"] = String(
23
+ theme.typography.fontWeightBold
24
+ );
25
+ }
26
+ const spacing = theme.spacing(1);
27
+ if (spacing !== "8px") {
28
+ styleObject["--bui-space"] = `calc(${spacing} * 0.5)`;
29
+ }
30
+ if (theme.shape.borderRadius === 0) {
31
+ styleObject["--bui-radius-1"] = "0";
32
+ styleObject["--bui-radius-2"] = "0";
33
+ styleObject["--bui-radius-3"] = "0";
34
+ styleObject["--bui-radius-4"] = "0";
35
+ styleObject["--bui-radius-5"] = "0";
36
+ styleObject["--bui-radius-6"] = "0";
37
+ }
38
+ const palette = theme.palette;
39
+ styleObject["--bui-black"] = palette.common.black;
40
+ styleObject["--bui-white"] = palette.common.white;
41
+ Object.entries({
42
+ primary: palette.text.primary,
43
+ secondary: palette.textSubtle,
44
+ link: palette.link ?? palette.primary.main,
45
+ "link-hover": palette.linkHover ?? palette.primary.dark,
46
+ disabled: palette.text.disabled,
47
+ solid: palette.primary.contrastText,
48
+ "solid-disabled": palette.text.disabled,
49
+ tint: palette.textSubtle,
50
+ "tint-disabled": palette.textVerySubtle,
51
+ danger: palette.error.dark,
52
+ warning: palette.warning.dark,
53
+ success: palette.success.dark
54
+ }).forEach(([key, value]) => {
55
+ styleObject[`--bui-fg-${key}`] = value;
56
+ });
57
+ Object.entries({
58
+ "": palette.background.default,
59
+ "surface-1": palette.background.paper,
60
+ "surface-2": palette.background.default,
61
+ solid: palette.primary.main,
62
+ "solid-hover": blend(palette.primary.main, palette.primary.dark, 0.5),
63
+ "solid-pressed": palette.primary.dark,
64
+ "solid-disabled": palette.action.disabledBackground,
65
+ tint: "transparent",
66
+ "tint-hover": alpha(palette.primary.main, 0.4),
67
+ "tint-pressed": alpha(palette.primary.main, 0.6),
68
+ "tint-disabled": palette.action.disabledBackground,
69
+ danger: palette.error.light,
70
+ warning: palette.warning.light,
71
+ success: palette.success.light
72
+ }).forEach(([key, value]) => {
73
+ styleObject[`--bui-bg-${key}`] = value;
74
+ });
75
+ Object.entries({
76
+ danger: palette.error.main,
77
+ warning: palette.warning.main,
78
+ success: palette.success.main
79
+ }).forEach(([key, value]) => {
80
+ styleObject[`--bui-border${key ? `-${key}` : ""}`] = value;
81
+ });
82
+ styleObject["--bui-border"] = palette.border || palette.divider;
83
+ styleObject["--bui-border-danger"] = palette.error.main;
84
+ styleObject["--bui-border-warning"] = palette.warning.main;
85
+ styleObject["--bui-border-success"] = palette.success.main;
86
+ styleObject["--bui-ring"] = palette.highlight || palette.primary.main;
87
+ return styleObject;
88
+ }
89
+
90
+ export { convertMuiToBuiTheme };
91
+ //# sourceMappingURL=convertMuiToBuiTheme.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convertMuiToBuiTheme.esm.js","sources":["../../../src/components/BuiThemerPage/convertMuiToBuiTheme.ts"],"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 */\n\nimport { Theme as Mui5Theme } from '@mui/material/styles';\nimport { BackstagePaletteAdditions } from '@backstage/theme';\nimport { blend, alpha } from '@mui/system/colorManipulator';\n\nexport interface ConvertMuiToBuiThemeResult {\n css: string;\n styleObject: Record<string, string>;\n}\n\n/**\n * Converts a MUI v5 Theme to BUI CSS variables\n * @param theme - The MUI v5 theme to convert\n * @returns Object containing CSS string and style object with BUI variables\n */\nexport function convertMuiToBuiTheme(\n theme: Mui5Theme,\n): ConvertMuiToBuiThemeResult {\n const styleObject = generateBuiVariables(theme);\n\n const selector =\n theme.palette.mode === 'dark' ? \"[data-theme-mode='dark']\" : ':root';\n\n const css = `${selector} {\\n${Object.entries(styleObject)\n .map(([key, value]) => ` ${key}: ${value};`)\n .join('\\n')}\\n}`;\n\n return { css, styleObject };\n}\n\n/**\n * Generates BUI CSS variables from MUI theme\n */\nfunction generateBuiVariables(theme: Mui5Theme): Record<string, string> {\n const styleObject: Record<string, string> = {};\n\n // Font families\n if (theme.typography.fontFamily) {\n styleObject['--bui-font-regular'] = theme.typography.fontFamily;\n }\n\n // Font weights\n if (theme.typography.fontWeightRegular) {\n styleObject['--bui-font-weight-regular'] = String(\n theme.typography.fontWeightRegular,\n );\n }\n if (theme.typography.fontWeightBold) {\n styleObject['--bui-font-weight-bold'] = String(\n theme.typography.fontWeightBold,\n );\n }\n\n const spacing = theme.spacing(1);\n // Skip spacing if the theme is using the default\n if (spacing !== '8px') {\n styleObject['--bui-space'] = `calc(${spacing} * 0.5)`;\n }\n\n // Border radius, only translate a 0 radius\n if (theme.shape.borderRadius === 0) {\n styleObject['--bui-radius-1'] = '0';\n styleObject['--bui-radius-2'] = '0';\n styleObject['--bui-radius-3'] = '0';\n styleObject['--bui-radius-4'] = '0';\n styleObject['--bui-radius-5'] = '0';\n styleObject['--bui-radius-6'] = '0';\n }\n\n // Colors - map MUI palette to BUI color tokens\n const palette = theme.palette as typeof theme.palette &\n Partial<BackstagePaletteAdditions>;\n\n // Base colors\n styleObject['--bui-black'] = palette.common.black;\n styleObject['--bui-white'] = palette.common.white;\n\n // Generate foreground colors\n Object.entries({\n primary: palette.text.primary,\n secondary: palette.textSubtle,\n link: palette.link ?? palette.primary.main,\n 'link-hover': palette.linkHover ?? palette.primary.dark,\n disabled: palette.text.disabled,\n solid: palette.primary.contrastText,\n 'solid-disabled': palette.text.disabled,\n tint: palette.textSubtle,\n 'tint-disabled': palette.textVerySubtle,\n danger: palette.error.dark,\n warning: palette.warning.dark,\n success: palette.success.dark,\n }).forEach(([key, value]) => {\n styleObject[`--bui-fg-${key}`] = value;\n });\n\n // Generate surface colors\n Object.entries({\n '': palette.background.default,\n 'surface-1': palette.background.paper,\n 'surface-2': palette.background.default,\n solid: palette.primary.main,\n 'solid-hover': blend(palette.primary.main, palette.primary.dark, 0.5),\n 'solid-pressed': palette.primary.dark,\n 'solid-disabled': palette.action.disabledBackground,\n tint: 'transparent',\n 'tint-hover': alpha(palette.primary.main, 0.4),\n 'tint-pressed': alpha(palette.primary.main, 0.6),\n 'tint-disabled': palette.action.disabledBackground,\n danger: palette.error.light,\n warning: palette.warning.light,\n success: palette.success.light,\n }).forEach(([key, value]) => {\n styleObject[`--bui-bg-${key}`] = value;\n });\n\n // Border colors\n Object.entries({\n danger: palette.error.main,\n warning: palette.warning.main,\n success: palette.success.main,\n }).forEach(([key, value]) => {\n styleObject[`--bui-border${key ? `-${key}` : ''}`] = value;\n });\n\n // Base border color if available\n styleObject['--bui-border'] = palette.border || palette.divider;\n styleObject['--bui-border-danger'] = palette.error.main;\n styleObject['--bui-border-warning'] = palette.warning.main;\n styleObject['--bui-border-success'] = palette.success.main;\n\n // Special colors\n styleObject['--bui-ring'] = palette.highlight || palette.primary.main;\n\n return styleObject;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { BuiThemerPage } from './BuiThemerPage.esm.js';
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import * as react from 'react';
2
+ import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
5
+
6
+ /** @public */
7
+ declare const buiThemerPlugin: _backstage_core_plugin_api.BackstagePlugin<{
8
+ root: _backstage_core_plugin_api.RouteRef<undefined>;
9
+ }, {}>;
10
+ /** @public */
11
+ declare const BuiThemerPage: () => react_jsx_runtime.JSX.Element;
12
+ /** @public */
13
+ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{
14
+ root: _backstage_frontend_plugin_api.RouteRef<undefined>;
15
+ }, {}, {
16
+ "page:mui-to-bui": _backstage_frontend_plugin_api.ExtensionDefinition<{
17
+ kind: "page";
18
+ name: undefined;
19
+ config: {
20
+ path: string | undefined;
21
+ };
22
+ configInput: {
23
+ path?: string | undefined;
24
+ };
25
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
26
+ optional: true;
27
+ }>;
28
+ inputs: {};
29
+ params: {
30
+ defaultPath?: [Error: `Use the 'path' param instead`];
31
+ path: string;
32
+ loader: () => Promise<JSX.Element>;
33
+ routeRef?: _backstage_frontend_plugin_api.RouteRef;
34
+ };
35
+ }>;
36
+ }>;
37
+
38
+ export { BuiThemerPage, buiThemerPlugin, _default as default };
@@ -0,0 +1,2 @@
1
+ export { BuiThemerPage, buiThemerPlugin, default } from './plugin.esm.js';
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { convertLegacyRouteRefs, convertLegacyRouteRef } from '@backstage/core-compat-api';
3
+ import { createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';
4
+ import { createFrontendPlugin, PageBlueprint } from '@backstage/frontend-plugin-api';
5
+ import { rootRouteRef } from './routes.esm.js';
6
+
7
+ const buiThemerPlugin = createPlugin({
8
+ id: "mui-to-bui",
9
+ routes: {
10
+ root: rootRouteRef
11
+ }
12
+ });
13
+ const BuiThemerPage = buiThemerPlugin.provide(
14
+ createRoutableExtension({
15
+ name: "BuiThemerPage",
16
+ component: () => import('./components/BuiThemerPage/index.esm.js').then((m) => m.BuiThemerPage),
17
+ mountPoint: rootRouteRef
18
+ })
19
+ );
20
+ var plugin = createFrontendPlugin({
21
+ pluginId: "mui-to-bui",
22
+ extensions: [
23
+ PageBlueprint.make({
24
+ params: {
25
+ path: "/mui-to-bui",
26
+ loader: () => import('./components/BuiThemerPage/index.esm.js').then((m) => /* @__PURE__ */ jsx(m.BuiThemerPage, {})),
27
+ routeRef: convertLegacyRouteRef(rootRouteRef)
28
+ }
29
+ })
30
+ ],
31
+ routes: convertLegacyRouteRefs({
32
+ root: rootRouteRef
33
+ })
34
+ });
35
+
36
+ export { BuiThemerPage, buiThemerPlugin, plugin as default };
37
+ //# sourceMappingURL=plugin.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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 */\n\nimport {\n convertLegacyRouteRef,\n convertLegacyRouteRefs,\n} from '@backstage/core-compat-api';\nimport {\n createPlugin,\n createRoutableExtension,\n} from '@backstage/core-plugin-api';\nimport {\n createFrontendPlugin,\n PageBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport { rootRouteRef } from './routes';\n\n// Old system\n/** @public */\nexport const buiThemerPlugin = createPlugin({\n id: 'mui-to-bui',\n routes: {\n root: rootRouteRef,\n },\n});\n\n/** @public */\nexport const BuiThemerPage = buiThemerPlugin.provide(\n createRoutableExtension({\n name: 'BuiThemerPage',\n component: () =>\n import('./components/BuiThemerPage').then(m => m.BuiThemerPage),\n mountPoint: rootRouteRef,\n }),\n);\n\n// New system\n/** @public */\nexport default createFrontendPlugin({\n pluginId: 'mui-to-bui',\n extensions: [\n PageBlueprint.make({\n params: {\n path: '/mui-to-bui',\n loader: () =>\n import('./components/BuiThemerPage').then(m => <m.BuiThemerPage />),\n routeRef: convertLegacyRouteRef(rootRouteRef),\n },\n }),\n ],\n routes: convertLegacyRouteRefs({\n root: rootRouteRef,\n }),\n});\n"],"names":[],"mappings":";;;;;;AAgCO,MAAM,kBAAkB,YAAA,CAAa;AAAA,EAC1C,EAAA,EAAI,YAAA;AAAA,EACJ,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM;AAAA;AAEV,CAAC;AAGM,MAAM,gBAAgB,eAAA,CAAgB,OAAA;AAAA,EAC3C,uBAAA,CAAwB;AAAA,IACtB,IAAA,EAAM,eAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,yCAA4B,EAAE,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,aAAa,CAAA;AAAA,IAChE,UAAA,EAAY;AAAA,GACb;AACH;AAIA,aAAe,oBAAA,CAAqB;AAAA,EAClC,QAAA,EAAU,YAAA;AAAA,EACV,UAAA,EAAY;AAAA,IACV,cAAc,IAAA,CAAK;AAAA,MACjB,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,aAAA;AAAA,QACN,MAAA,EAAQ,MACN,OAAO,yCAA4B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,aAAA,EAAF,EAAgB,CAAE,CAAA;AAAA,QACpE,QAAA,EAAU,sBAAsB,YAAY;AAAA;AAC9C,KACD;AAAA,GACH;AAAA,EACA,QAAQ,sBAAA,CAAuB;AAAA,IAC7B,IAAA,EAAM;AAAA,GACP;AACH,CAAC,CAAA;;;;"}
@@ -0,0 +1,8 @@
1
+ import { createRouteRef } from '@backstage/core-plugin-api';
2
+
3
+ const rootRouteRef = createRouteRef({
4
+ id: "mui-to-bui"
5
+ });
6
+
7
+ export { rootRouteRef };
8
+ //# sourceMappingURL=routes.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.esm.js","sources":["../src/routes.ts"],"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 { createRouteRef } from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'mui-to-bui',\n});\n"],"names":[],"mappings":";;AAiBO,MAAM,eAAe,cAAA,CAAe;AAAA,EACzC,EAAA,EAAI;AACN,CAAC;;;;"}
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@backstage/plugin-mui-to-bui",
3
+ "version": "0.0.0-nightly-20250927023623",
4
+ "backstage": {
5
+ "role": "frontend-plugin",
6
+ "pluginId": "mui-to-bui",
7
+ "pluginPackages": [
8
+ "@backstage/plugin-mui-to-bui"
9
+ ],
10
+ "features": {
11
+ ".": "@backstage/FrontendPlugin"
12
+ }
13
+ },
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "main": "dist/index.esm.js",
17
+ "types": "dist/index.d.ts"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/backstage/backstage",
22
+ "directory": "plugins/bui-themer"
23
+ },
24
+ "license": "Apache-2.0",
25
+ "sideEffects": false,
26
+ "main": "dist/index.esm.js",
27
+ "types": "dist/index.d.ts",
28
+ "files": [
29
+ "dist"
30
+ ],
31
+ "scripts": {
32
+ "build": "backstage-cli package build",
33
+ "clean": "backstage-cli package clean",
34
+ "lint": "backstage-cli package lint",
35
+ "prepack": "backstage-cli package prepack",
36
+ "postpack": "backstage-cli package postpack",
37
+ "start": "backstage-cli package start",
38
+ "test": "backstage-cli package test"
39
+ },
40
+ "dependencies": {
41
+ "@backstage/core-compat-api": "0.0.0-nightly-20250927023623",
42
+ "@backstage/core-plugin-api": "0.0.0-nightly-20250927023623",
43
+ "@backstage/frontend-plugin-api": "0.0.0-nightly-20250927023623",
44
+ "@backstage/theme": "0.0.0-nightly-20250927023623",
45
+ "@backstage/ui": "0.0.0-nightly-20250927023623",
46
+ "@mui/material": "^5.12.2",
47
+ "@mui/system": "^5.16.14"
48
+ },
49
+ "devDependencies": {
50
+ "@backstage/cli": "0.0.0-nightly-20250927023623",
51
+ "@backstage/dev-utils": "0.0.0-nightly-20250927023623",
52
+ "@backstage/test-utils": "0.0.0-nightly-20250927023623",
53
+ "@testing-library/jest-dom": "^6.0.0",
54
+ "@testing-library/react": "^16.0.0",
55
+ "@types/react": "^18.0.0",
56
+ "react": "^18.0.2",
57
+ "react-dom": "^18.0.2",
58
+ "react-router-dom": "^6.3.0"
59
+ },
60
+ "peerDependencies": {
61
+ "@types/react": "^17.0.0 || ^18.0.0",
62
+ "react": "^17.0.0 || ^18.0.0",
63
+ "react-dom": "^17.0.0 || ^18.0.0",
64
+ "react-router-dom": "^6.3.0"
65
+ },
66
+ "peerDependenciesMeta": {
67
+ "@types/react": {
68
+ "optional": true
69
+ }
70
+ },
71
+ "typesVersions": {
72
+ "*": {
73
+ "package.json": [
74
+ "package.json"
75
+ ]
76
+ }
77
+ },
78
+ "module": "./dist/index.esm.js"
79
+ }