@modern-js/devtools-client 2.34.0 → 2.35.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 (124) hide show
  1. package/.turbo/turbo-build.log +133 -17
  2. package/CHANGELOG.md +9 -0
  3. package/build.sh +5 -0
  4. package/dist/html/main/index.html +5 -0
  5. package/dist/modern.config.json +30 -10
  6. package/dist/nestedRoutes.json +1 -1
  7. package/dist/route.json +3 -3
  8. package/dist/routes-manifest.json +198 -16
  9. package/dist/static/css/main.d8cf90b5.css +1 -0
  10. package/dist/static/css/vendors~node_modules_pnpm_emotion_styled_11_11_0__emotion_react_11_11_1__types_react_18_0_21_~8b4e97.f2739ed5.css +51 -0
  11. package/dist/static/js/async/config/builder/resolved/page.5c4715c4.js +1 -0
  12. package/dist/static/js/async/config/builder/resolved/page.5c4715c4.js.map +1 -0
  13. package/dist/static/js/async/config/builder/transformed/page.a05d2c7f.js +1 -0
  14. package/dist/static/js/async/config/builder/transformed/page.a05d2c7f.js.map +1 -0
  15. package/dist/static/js/async/config/bundler/resolved/page.2bc07a42.js +1 -0
  16. package/dist/static/js/async/config/bundler/resolved/page.2bc07a42.js.map +1 -0
  17. package/dist/static/js/async/config/bundler/transformed/page.704303d4.js +1 -0
  18. package/dist/static/js/async/config/bundler/transformed/page.704303d4.js.map +1 -0
  19. package/dist/static/js/async/config/framework/resolved/page.c78a652b.js +1 -0
  20. package/dist/static/js/async/config/framework/resolved/page.c78a652b.js.map +1 -0
  21. package/dist/static/js/async/config/framework/transformed/page.acd03a20.js +1 -0
  22. package/dist/static/js/async/config/framework/transformed/page.acd03a20.js.map +1 -0
  23. package/dist/static/js/async/config/layout.c988e6cc.js +1 -0
  24. package/dist/static/js/async/config/layout.c988e6cc.js.map +1 -0
  25. package/dist/static/js/async/config/page.6183831d.js +1 -0
  26. package/dist/static/js/async/config/page.6183831d.js.map +1 -0
  27. package/dist/static/js/async/context/builder/page.af1058db.js +1 -0
  28. package/dist/static/js/async/context/builder/page.af1058db.js.map +1 -0
  29. package/dist/static/js/async/context/framework/page.65d0c64b.js +1 -0
  30. package/dist/static/js/async/context/framework/page.65d0c64b.js.map +1 -0
  31. package/dist/static/js/async/context/layout.69e165a7.js +1 -0
  32. package/dist/static/js/async/context/layout.69e165a7.js.map +1 -0
  33. package/dist/static/js/async/context/page.d7bb42e1.js +1 -0
  34. package/dist/static/js/async/context/page.d7bb42e1.js.map +1 -0
  35. package/dist/static/js/async/overview/page.d26d09d5.js +1 -0
  36. package/dist/static/js/async/overview/page.d26d09d5.js.map +1 -0
  37. package/dist/static/js/async/page.3a64325e.js +1 -0
  38. package/dist/static/js/async/page.3a64325e.js.map +1 -0
  39. package/dist/static/js/async/pages/layout.45470473.js +1 -0
  40. package/dist/static/js/async/pages/layout.45470473.js.map +1 -0
  41. package/dist/static/js/async/pages/page.27267daf.js +1 -0
  42. package/dist/static/js/async/pages/page.27267daf.js.map +1 -0
  43. package/dist/static/js/lib-lodash.d4590abd.js +1 -0
  44. package/dist/static/js/lib-lodash.d4590abd.js.map +1 -0
  45. package/dist/static/js/lib-polyfill.6e913595.js +1 -0
  46. package/dist/static/js/lib-polyfill.6e913595.js.map +1 -0
  47. package/dist/static/js/lib-react.e7e80806.js +1 -0
  48. package/dist/static/js/{lib-react.be1fdbe9.js.LICENSE.txt → lib-react.e7e80806.js.LICENSE.txt} +11 -1
  49. package/dist/static/js/lib-react.e7e80806.js.map +1 -0
  50. package/dist/static/js/lib-router.a49a7033.js +1 -0
  51. package/dist/static/js/{lib-router.7b48a0f0.js.LICENSE.txt → lib-router.a49a7033.js.LICENSE.txt} +3 -3
  52. package/dist/static/js/{lib-router.7b48a0f0.js.map → lib-router.a49a7033.js.map} +1 -1
  53. package/dist/static/js/main.31be2b44.js +1 -0
  54. package/dist/static/js/main.31be2b44.js.map +1 -0
  55. package/dist/static/js/vendors~node_modules_pnpm_emotion_styled_11_11_0__emotion_react_11_11_1__types_react_18_0_21_~8b4e97.a3a62da9.js +1 -0
  56. package/dist/static/js/vendors~node_modules_pnpm_emotion_styled_11_11_0__emotion_react_11_11_1__types_react_18_0_21_~8b4e97.a3a62da9.js.LICENSE.txt +39 -0
  57. package/dist/static/js/vendors~node_modules_pnpm_emotion_styled_11_11_0__emotion_react_11_11_1__types_react_18_0_21_~8b4e97.a3a62da9.js.map +1 -0
  58. package/modern.config.ts +42 -3
  59. package/package.json +28 -8
  60. package/scripts/build-redirects.js +32 -0
  61. package/scripts/deploy-netlify.js +0 -0
  62. package/src/.eslintrc.js +4 -0
  63. package/src/components/Breadcrumbs.tsx +43 -0
  64. package/src/components/ObjectInspector.tsx +37 -0
  65. package/src/constants.tsx +34 -0
  66. package/src/routes/RootTabs.tsx +148 -0
  67. package/src/routes/config/builder/resolved/page.tsx +17 -0
  68. package/src/routes/config/builder/transformed/page.tsx +17 -0
  69. package/src/routes/config/bundler/resolved/page.tsx +17 -0
  70. package/src/routes/config/bundler/transformed/page.tsx +17 -0
  71. package/src/routes/config/framework/resolved/page.tsx +17 -0
  72. package/src/routes/config/framework/transformed/page.tsx +17 -0
  73. package/src/routes/config/layout.tsx +68 -0
  74. package/src/routes/config/page.loader.ts +7 -0
  75. package/src/routes/config/page.tsx +1 -0
  76. package/src/routes/context/builder/page.tsx +12 -0
  77. package/src/routes/context/framework/page.tsx +14 -0
  78. package/src/routes/context/layout.tsx +38 -0
  79. package/src/routes/context/page.loader.ts +7 -0
  80. package/src/routes/context/page.tsx +1 -0
  81. package/src/routes/layout.css +3 -0
  82. package/src/routes/layout.tsx +25 -0
  83. package/src/routes/overview/heading.svg +12 -0
  84. package/src/routes/overview/page.tsx +122 -0
  85. package/src/routes/page.loader.ts +7 -0
  86. package/src/routes/page.tsx +1 -0
  87. package/src/routes/pages/BaseRoute.tsx +87 -0
  88. package/src/routes/pages/EntryRoute/ClientRouteStats/ClientRouteStats.tsx +42 -0
  89. package/src/routes/pages/EntryRoute/ClientRouteStats/LegacyRouteStats.tsx +6 -0
  90. package/src/routes/pages/EntryRoute/ClientRouteStats/RemixRoute.tsx +85 -0
  91. package/src/routes/pages/EntryRoute/ClientRouteStats/RemixRouteStats.tsx +44 -0
  92. package/src/routes/pages/EntryRoute/ClientRouteStats/index.ts +1 -0
  93. package/src/routes/pages/EntryRoute/EntryRoute.tsx +25 -0
  94. package/src/routes/pages/EntryRoute/EntryStats.tsx +44 -0
  95. package/src/routes/pages/EntryRoute/MatchRemixRouteContext.ts +6 -0
  96. package/src/routes/pages/EntryRoute/index.ts +1 -0
  97. package/src/routes/pages/MatchUrl.tsx +3 -0
  98. package/src/routes/pages/ServerRoute.tsx +21 -0
  99. package/src/routes/pages/UnknownRoute.tsx +20 -0
  100. package/src/routes/pages/layout.tsx +13 -0
  101. package/src/routes/pages/page.tsx +54 -0
  102. package/src/rpc/index.ts +36 -0
  103. package/src/stores/index.tsx +141 -0
  104. package/src/types/index.ts +62 -0
  105. package/src/utils/context.tsx +22 -0
  106. package/src/utils/hooks.ts +23 -0
  107. package/src/utils/index.ts +1 -0
  108. package/dist/html/devtools/index.html +0 -5
  109. package/dist/static/css/async/devtools_page.215ea1d3.css +0 -1
  110. package/dist/static/js/async/devtools_page.8337a013.js +0 -1
  111. package/dist/static/js/async/devtools_page.8337a013.js.map +0 -1
  112. package/dist/static/js/devtools.56bf0fe9.js +0 -1
  113. package/dist/static/js/devtools.56bf0fe9.js.map +0 -1
  114. package/dist/static/js/lib-polyfill.db4711e8.js +0 -1
  115. package/dist/static/js/lib-polyfill.db4711e8.js.map +0 -1
  116. package/dist/static/js/lib-react.be1fdbe9.js +0 -1
  117. package/dist/static/js/lib-react.be1fdbe9.js.map +0 -1
  118. package/dist/static/js/lib-router.7b48a0f0.js +0 -1
  119. package/dist/static/js/vendors~node_modules_pnpm_loadable_component_5_15_3_react_18_2_0_node_modules_loadable_compon~2b20fe.2a50a754.js +0 -1
  120. package/dist/static/js/vendors~node_modules_pnpm_loadable_component_5_15_3_react_18_2_0_node_modules_loadable_compon~2b20fe.2a50a754.js.LICENSE.txt +0 -24
  121. package/dist/static/js/vendors~node_modules_pnpm_loadable_component_5_15_3_react_18_2_0_node_modules_loadable_compon~2b20fe.2a50a754.js.map +0 -1
  122. package/src/devtools/routes/index.css +0 -115
  123. package/src/devtools/routes/layout.tsx +0 -9
  124. package/src/devtools/routes/page.tsx +0 -19
package/modern.config.ts CHANGED
@@ -1,18 +1,56 @@
1
+ import { URL } from 'url';
2
+ import path from 'path/posix';
3
+ import { execSync } from 'child_process';
4
+ import { logger } from '@modern-js/builder-shared';
1
5
  import { appTools, defineConfig } from '@modern-js/app-tools';
2
6
  import { proxyPlugin } from '@modern-js/plugin-proxy';
7
+ import { version } from './package.json';
8
+
9
+ const commitShort = execSync('git rev-parse --short=10 HEAD').toString().trim();
10
+ if (!commitShort.match(/^\w{10}$/)) {
11
+ throw new Error("Can't resolve git commit hash.");
12
+ }
13
+
14
+ const basename = new URL(process.env.DEPLOY_HOST || 'https://modernjs.dev');
15
+ if (process.env.BASENAME === 'version' || !process.env.BASENAME) {
16
+ basename.pathname = `/devtools/${version}`;
17
+ } else if (process.env.BASENAME === 'commit') {
18
+ basename.pathname = `/devtools/${commitShort}`;
19
+ } else if (process.env.BASENAME === 'false') {
20
+ basename.pathname = '/devtools';
21
+ } else {
22
+ basename.pathname = path.resolve('/devtools', process.env.BASENAME);
23
+ }
24
+
25
+ logger.info(
26
+ `Access client:`,
27
+ `${basename.href}?src=ws://localhost:8080/_modern_js/devtools/rpc`,
28
+ );
3
29
 
4
30
  // https://modernjs.dev/en/configure/app/usage
5
31
  export default defineConfig<'rspack'>({
6
32
  runtime: {
7
- router: true,
33
+ router: {
34
+ basename: basename.pathname,
35
+ },
8
36
  },
9
37
  dev: {
10
38
  port: 8780,
11
- assetPrefix: '/devtools',
39
+ assetPrefix: basename.pathname,
12
40
  proxy: {
13
- 'https://modernjs.dev/devtools': 'http://localhost:8780/devtools',
41
+ [basename.href]: new URL(basename.pathname, 'http://localhost:8780').href,
14
42
  },
15
43
  },
44
+ source: {
45
+ preEntry: [require.resolve('modern-normalize/modern-normalize.css')],
46
+ globalVars: {
47
+ 'process.env.PKG_VERSION': `${version}-${commitShort}`,
48
+ },
49
+ },
50
+ output: {
51
+ assetPrefix: basename.href,
52
+ enableCssModuleTSDeclaration: true,
53
+ },
16
54
  tools: {
17
55
  devServer: {
18
56
  client: {
@@ -21,6 +59,7 @@ export default defineConfig<'rspack'>({
21
59
  },
22
60
  },
23
61
  },
62
+ html: {},
24
63
  plugins: [
25
64
  appTools({
26
65
  bundler: 'experimental-rspack',
package/package.json CHANGED
@@ -1,15 +1,33 @@
1
1
  {
2
2
  "name": "@modern-js/devtools-client",
3
- "version": "2.34.0",
3
+ "version": "2.35.0",
4
4
  "main": "./index.js",
5
5
  "engines": {
6
6
  "node": ">=14.0.0"
7
7
  },
8
8
  "dependencies": {
9
+ "birpc": "0.2.13",
10
+ "@emotion/react": "^11.11.1",
11
+ "@emotion/styled": "^11.11.0",
12
+ "@radix-ui/react-collapsible": "^1.0.3",
13
+ "@radix-ui/react-icons": "^1.3.0",
14
+ "@radix-ui/react-popover": "^1.0.6",
15
+ "@radix-ui/react-tabs": "^1.0.4",
16
+ "@radix-ui/themes": "^1.1.2",
9
17
  "lodash": "^4.17.21",
18
+ "p-defer": "3.0.0",
10
19
  "react": "~18.2.0",
20
+ "react-base16-styling": "^0.9.1",
11
21
  "react-dom": "~18.2.0",
12
- "@modern-js/runtime": "2.34.0"
22
+ "react-json-tree": "^0.18.0",
23
+ "react-json-view": "^1.21.3",
24
+ "react-use": "^17.4.0",
25
+ "suspend-react": "^0.1.3",
26
+ "ufo": "^1.2.0",
27
+ "valtio": "^1.11.1",
28
+ "@modern-js/devtools-kit": "2.35.0",
29
+ "@modern-js/runtime": "2.35.0",
30
+ "@modern-js/types": "2.35.0"
13
31
  },
14
32
  "devDependencies": {
15
33
  "@types/jest": "~29.2.4",
@@ -20,17 +38,19 @@
20
38
  "rimraf": "~3.0.2",
21
39
  "type-fest": "^4.1.0",
22
40
  "typescript": "~5.0.4",
23
- "@modern-js/eslint-config": "2.34.0",
24
- "@modern-js/plugin-proxy": "2.34.0",
25
- "@modern-js/tsconfig": "2.34.0",
26
- "@modern-js-app/eslint-config": "2.34.0",
27
- "@modern-js/app-tools": "2.34.0",
28
- "@modern-js/builder-rspack-provider": "2.34.0"
41
+ "@modern-js-app/eslint-config": "2.35.0",
42
+ "@modern-js/builder-shared": "2.35.0",
43
+ "@modern-js/builder-rspack-provider": "2.35.0",
44
+ "@modern-js/eslint-config": "2.35.0",
45
+ "@modern-js/plugin-proxy": "2.35.0",
46
+ "@modern-js/tsconfig": "2.35.0",
47
+ "@modern-js/app-tools": "2.35.0"
29
48
  },
30
49
  "scripts": {
31
50
  "reset": "npx rimraf ./**/node_modules",
32
51
  "dev": "modern dev",
33
52
  "build": "modern build",
53
+ "deploy": "pnpm build && node scripts/build-redirects.js",
34
54
  "start": "modern start",
35
55
  "serve": "modern serve",
36
56
  "new": "modern new",
@@ -0,0 +1,32 @@
1
+ const fs = require('fs');
2
+ const path = require('path/posix');
3
+ const { routes } = require('../dist/route.json');
4
+
5
+ /** @type {{ from: string; to: string; code: number; force?: boolean }[]} */
6
+ const redirects = [];
7
+
8
+ for (const route of routes) {
9
+ if (route.isSSR) {
10
+ // Unimplemented.
11
+ } else if (route.isStream) {
12
+ // Unimplemented.
13
+ } else if (route.isSPA) {
14
+ redirects.push({
15
+ from: path.join(route.urlPath, '*'),
16
+ to: route.entryPath,
17
+ code: 200,
18
+ });
19
+ } else {
20
+ // Unimplemented.
21
+ }
22
+ }
23
+
24
+ const output = redirects
25
+ .map(r => `${r.from} ${r.to} ${r.code}${r.force ? '!' : ''}`)
26
+ .join('\n');
27
+ fs.writeFileSync(
28
+ path.resolve(__dirname, '../dist/_redirects'),
29
+ output,
30
+ 'utf-8',
31
+ );
32
+ console.log(`Created _redirects file with rules:\n`, output);
File without changes
package/src/.eslintrc.js CHANGED
@@ -1,3 +1,4 @@
1
+ /** @type {import('eslint').Linter.Config} */
1
2
  // eslint-disable-next-line import/no-commonjs
2
3
  module.exports = {
3
4
  root: true,
@@ -6,4 +7,7 @@ module.exports = {
6
7
  tsconfigRootDir: __dirname,
7
8
  project: ['../tsconfig.json'],
8
9
  },
10
+ rules: {
11
+ curly: 'off',
12
+ },
9
13
  };
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import styled from '@emotion/styled';
3
+ import { Button, Flex } from '@radix-ui/themes';
4
+ import { ChevronRightIcon } from '@radix-ui/react-icons';
5
+ import type { ButtonProps } from '@radix-ui/themes/dist/cjs/components/button';
6
+
7
+ export type BreadcrumbButtonProps = ButtonProps &
8
+ React.RefAttributes<HTMLButtonElement>;
9
+
10
+ export const BreadcrumbButton: React.FC<BreadcrumbButtonProps> = props => {
11
+ return <Button color="gray" size="1" variant="ghost" {...props} />;
12
+ };
13
+
14
+ export interface BreadcrumbsProps {
15
+ children?: React.ReactElement[];
16
+ }
17
+
18
+ export const Breadcrumbs: React.FC<BreadcrumbsProps> = ({ children = [] }) => {
19
+ const elements: React.ReactElement[] = [];
20
+ for (const child of children) {
21
+ elements.push(child);
22
+ if (child !== children.at(-1)) {
23
+ elements.push(<Connector key={`${child.key}__connector`} />);
24
+ }
25
+ }
26
+ return (
27
+ <Flex align="center" gap="1">
28
+ {elements}
29
+ </Flex>
30
+ );
31
+ };
32
+
33
+ (Breadcrumbs as any).Button = BreadcrumbButton;
34
+
35
+ export default Breadcrumbs as typeof Breadcrumbs & {
36
+ Button: typeof BreadcrumbButton;
37
+ };
38
+
39
+ const Connector = styled(ChevronRightIcon)({
40
+ width: 'var(--font-size-2)',
41
+ height: 'var(--font-size-2)',
42
+ color: 'var(--gray-6)',
43
+ });
@@ -0,0 +1,37 @@
1
+ import styled from '@emotion/styled';
2
+ import { Box } from '@radix-ui/themes';
3
+ import type { Theme } from 'react-base16-styling';
4
+ import { JSONTree } from 'react-json-tree';
5
+
6
+ const theme: Theme = {
7
+ scheme: 'tomorrow',
8
+ author: 'chris kempson (http://chriskempson.com)',
9
+ base00: 'transparent',
10
+ base01: '#282a2e',
11
+ base02: '#373b41',
12
+ base03: '#969896',
13
+ base04: '#b4b7b4',
14
+ base05: '#c5c8c6',
15
+ base06: '#e0e0e0',
16
+ base07: '#ffffff',
17
+ base08: '#cc6666',
18
+ base09: '#de935f',
19
+ base0A: '#f0c674',
20
+ base0B: '#b5bd68',
21
+ base0C: '#8abeb7',
22
+ base0D: '#81a2be',
23
+ base0E: '#b294bb',
24
+ base0F: '#a3685a',
25
+ };
26
+
27
+ const Container = styled(Box)({
28
+ fontSize: 'var(--font-size-2)',
29
+ });
30
+
31
+ export const ObjectInspector: typeof JSONTree = props => {
32
+ return (
33
+ <Container>
34
+ <JSONTree theme={theme} {...props} />
35
+ </Container>
36
+ );
37
+ };
@@ -0,0 +1,34 @@
1
+ import {
2
+ HomeIcon,
3
+ MixerHorizontalIcon,
4
+ FileTextIcon,
5
+ CubeIcon,
6
+ } from '@radix-ui/react-icons';
7
+ import { InternalTab } from './types';
8
+
9
+ export const getDefaultTabs = (): InternalTab[] => [
10
+ {
11
+ name: 'overview',
12
+ title: 'Overview',
13
+ icon: <HomeIcon />,
14
+ view: { type: 'builtin', url: '/overview' },
15
+ },
16
+ {
17
+ name: 'config',
18
+ title: 'Config',
19
+ icon: <MixerHorizontalIcon />,
20
+ view: { type: 'builtin', url: '/config' },
21
+ },
22
+ {
23
+ name: 'pages',
24
+ title: 'Pages',
25
+ icon: <FileTextIcon />,
26
+ view: { type: 'builtin', url: '/pages' },
27
+ },
28
+ {
29
+ name: 'context',
30
+ title: 'Context',
31
+ icon: <CubeIcon />,
32
+ view: { type: 'builtin', url: '/context' },
33
+ },
34
+ ];
@@ -0,0 +1,148 @@
1
+ import { Suspense } from 'react';
2
+ import styled from '@emotion/styled';
3
+ import { useSnapshot } from 'valtio';
4
+ import { Outlet, useNavigate, useLocation } from '@modern-js/runtime/router';
5
+ import { Box, Text, Button } from '@radix-ui/themes';
6
+ import _ from 'lodash';
7
+ import { GearIcon, HomeIcon } from '@radix-ui/react-icons';
8
+ import { useStore } from '@/stores';
9
+ import { InternalTab } from '@/types';
10
+ import Breadcrumbs from '@/components/Breadcrumbs';
11
+
12
+ export const RootTabs: React.FC = () => {
13
+ const $store = useStore();
14
+ const tabs = useSnapshot($store.tabs);
15
+
16
+ const navigate = useNavigate();
17
+ const location = useLocation();
18
+ const currentTabName = location.pathname.split('/').filter(Boolean)[0];
19
+ const currentTab = _.find(tabs, { name: currentTabName });
20
+
21
+ const handleClick = (tab: InternalTab) => {
22
+ if (tab.view.type === 'builtin') {
23
+ navigate(tab.view.url);
24
+ } else {
25
+ throw new Error('Unimplemented.');
26
+ }
27
+ };
28
+
29
+ return (
30
+ <TabRoot>
31
+ <TabNavigator>
32
+ <TabList style={{ touchAction: 'none' }}>
33
+ <TabBrand>
34
+ <IconBox>🌰</IconBox>
35
+ DevTools
36
+ </TabBrand>
37
+ </TabList>
38
+ <TabList>
39
+ {tabs.map(tab => (
40
+ <TabTrigger
41
+ key={tab.name}
42
+ value={tab.name}
43
+ onClick={() => handleClick(tab as any)}
44
+ >
45
+ <IconBox>{tab.icon as any}</IconBox>
46
+ {tab.title}
47
+ </TabTrigger>
48
+ ))}
49
+ </TabList>
50
+ <Box grow="1" />
51
+ <SettingButton>
52
+ <GearIcon />
53
+ <Text>Settings</Text>
54
+ </SettingButton>
55
+ </TabNavigator>
56
+ <TabContent>
57
+ <Box grow="0">
58
+ <Breadcrumbs>
59
+ <Breadcrumbs.Button onClick={() => navigate('overview')}>
60
+ <HomeIcon />
61
+ </Breadcrumbs.Button>
62
+ <Breadcrumbs.Button>{currentTab?.title}</Breadcrumbs.Button>
63
+ </Breadcrumbs>
64
+ </Box>
65
+ <Box grow="1" style={{ overflow: 'hidden' }}>
66
+ <Suspense fallback={<div>loading...</div>}>
67
+ <Outlet />
68
+ </Suspense>
69
+ </Box>
70
+ </TabContent>
71
+ </TabRoot>
72
+ );
73
+ };
74
+
75
+ const SettingButton = styled(Button)({
76
+ '--accent-9': 'var(--gray-5)',
77
+ '--accent-10': 'var(--gray-6)',
78
+ });
79
+
80
+ const IconBox = styled(Box)({
81
+ width: '2rem',
82
+ height: '2rem',
83
+ display: 'flex',
84
+ justifyContent: 'center',
85
+ alignItems: 'center',
86
+ });
87
+
88
+ const TabNavigator = styled(Box)({
89
+ display: 'flex',
90
+ flexDirection: 'column',
91
+ gap: 'var(--block-gap)',
92
+ });
93
+
94
+ const TabRoot = styled(Box)({
95
+ '--block-gap': '0.5rem',
96
+ '--block-color': '#121212',
97
+ display: 'flex',
98
+ padding: 'var(--block-gap)',
99
+ gap: 'var(--block-gap)',
100
+ alignItems: 'stretch',
101
+ height: '100%',
102
+ width: '100%',
103
+ });
104
+
105
+ const TabList = styled(Box)({
106
+ flex: 'none',
107
+ width: '10rem',
108
+ height: 'min-content',
109
+ backgroundColor: 'var(--block-color)',
110
+ borderRadius: 'var(--radius-4)',
111
+ });
112
+
113
+ const TabTrigger = styled.button({
114
+ border: 'none',
115
+ backgroundColor: 'transparent',
116
+ display: 'flex',
117
+ alignItems: 'center',
118
+ height: '3rem',
119
+ width: '100%',
120
+ color: 'var(--gray-11)',
121
+ fontSize: 'var(--font-size-2)',
122
+ transition: 'color 200ms',
123
+ fontWeight: 'bold',
124
+ cursor: 'pointer',
125
+ ':focus': {
126
+ color: 'white',
127
+ },
128
+ });
129
+
130
+ const TabBrand = styled(TabTrigger)({
131
+ color: 'var(--gray-10)',
132
+ cursor: 'default',
133
+ ':focus': {
134
+ color: 'var(--gray-10)',
135
+ },
136
+ });
137
+
138
+ const TabContent = styled(Box)({
139
+ flex: 1,
140
+ flexDirection: 'column',
141
+ alignItems: 'stretch',
142
+ display: 'flex',
143
+ gap: 'var(--space-3)',
144
+ overflow: 'hidden',
145
+ backgroundColor: 'var(--block-color)',
146
+ borderRadius: 'var(--radius-4)',
147
+ padding: '1rem',
148
+ });
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useSnapshot } from 'valtio';
3
+ import { useStore } from '@/stores';
4
+ import { ObjectInspector } from '@/components/ObjectInspector';
5
+
6
+ const Page: React.FC = () => {
7
+ const $store = useStore();
8
+ const store = useSnapshot($store);
9
+ return (
10
+ <ObjectInspector
11
+ data={store.builder.config.resolved}
12
+ sortObjectKeys={true}
13
+ />
14
+ );
15
+ };
16
+
17
+ export default Page;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useSnapshot } from 'valtio';
3
+ import { useStore } from '@/stores';
4
+ import { ObjectInspector } from '@/components/ObjectInspector';
5
+
6
+ const Page: React.FC = () => {
7
+ const $store = useStore();
8
+ const store = useSnapshot($store);
9
+ return (
10
+ <ObjectInspector
11
+ data={store.builder.config.transformed}
12
+ sortObjectKeys={true}
13
+ />
14
+ );
15
+ };
16
+
17
+ export default Page;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useSnapshot } from 'valtio';
3
+ import { useStore } from '@/stores';
4
+ import { ObjectInspector } from '@/components/ObjectInspector';
5
+
6
+ const Page: React.FC = () => {
7
+ const $store = useStore();
8
+ const store = useSnapshot($store);
9
+ return (
10
+ <ObjectInspector
11
+ data={store.bundler.config.resolved}
12
+ sortObjectKeys={true}
13
+ />
14
+ );
15
+ };
16
+
17
+ export default Page;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useSnapshot } from 'valtio';
3
+ import { useStore } from '@/stores';
4
+ import { ObjectInspector } from '@/components/ObjectInspector';
5
+
6
+ const Page: React.FC = () => {
7
+ const $store = useStore();
8
+ const store = useSnapshot($store);
9
+ return (
10
+ <ObjectInspector
11
+ data={store.bundler.config.transformed}
12
+ sortObjectKeys={true}
13
+ />
14
+ );
15
+ };
16
+
17
+ export default Page;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useSnapshot } from 'valtio';
3
+ import { useStore } from '@/stores';
4
+ import { ObjectInspector } from '@/components/ObjectInspector';
5
+
6
+ const Page: React.FC = () => {
7
+ const $store = useStore();
8
+ const store = useSnapshot($store);
9
+ return (
10
+ <ObjectInspector
11
+ data={store.framework.config.resolved}
12
+ sortObjectKeys={true}
13
+ />
14
+ );
15
+ };
16
+
17
+ export default Page;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { useSnapshot } from 'valtio';
3
+ import { useStore } from '@/stores';
4
+ import { ObjectInspector } from '@/components/ObjectInspector';
5
+
6
+ const Page: React.FC = () => {
7
+ const $store = useStore();
8
+ const store = useSnapshot($store);
9
+ return (
10
+ <ObjectInspector
11
+ data={store.framework.config.transformed}
12
+ sortObjectKeys={true}
13
+ />
14
+ );
15
+ };
16
+
17
+ export default Page;
@@ -0,0 +1,68 @@
1
+ import { Suspense } from 'react';
2
+ import { Outlet, useNavigate } from '@modern-js/runtime/router';
3
+ import { Box, ScrollArea, Select } from '@radix-ui/themes';
4
+ import styled from '@emotion/styled';
5
+
6
+ export default function Layout() {
7
+ const navigate = useNavigate();
8
+ const handleSelect = (route: string) => {
9
+ navigate(route);
10
+ };
11
+ return (
12
+ <Container>
13
+ <Box grow="0">
14
+ <Select.Root
15
+ onValueChange={handleSelect}
16
+ defaultValue="builder/transformed"
17
+ >
18
+ <Select.Trigger />
19
+ <Select.Content position="popper">
20
+ <Select.Group>
21
+ <Select.Label>Framework</Select.Label>
22
+ <Select.Item value="framework/resolved">
23
+ Resolved Framework Config
24
+ </Select.Item>
25
+ <Select.Item value="framework/transformed">
26
+ Transformed Framework Config
27
+ </Select.Item>
28
+ </Select.Group>
29
+ <Select.Separator />
30
+ <Select.Group>
31
+ <Select.Label>Builder</Select.Label>
32
+ <Select.Item value="builder/resolved">
33
+ Resolved Builder Config
34
+ </Select.Item>
35
+ <Select.Item value="builder/transformed">
36
+ Transformed Builder Config
37
+ </Select.Item>
38
+ </Select.Group>
39
+ <Select.Separator />
40
+ <Select.Group>
41
+ <Select.Label>Bundler</Select.Label>
42
+ <Select.Item value="bundler/resolved">
43
+ Resolved Bundler Configs
44
+ </Select.Item>
45
+ <Select.Item value="bundler/transformed">
46
+ Transformed Bundler Configs
47
+ </Select.Item>
48
+ </Select.Group>
49
+ </Select.Content>
50
+ </Select.Root>
51
+ </Box>
52
+ <Box grow="1" asChild>
53
+ <ScrollArea scrollbars="both">
54
+ <Suspense fallback={'loading...'}>
55
+ <Outlet />
56
+ </Suspense>
57
+ </ScrollArea>
58
+ </Box>
59
+ </Container>
60
+ );
61
+ }
62
+
63
+ const Container = styled(Box)({
64
+ height: '100%',
65
+ display: 'flex',
66
+ flexDirection: 'column',
67
+ alignItems: 'stretch',
68
+ });
@@ -0,0 +1,7 @@
1
+ import { LoaderFunctionArgs, redirect } from '@modern-js/runtime/router';
2
+ import { resolveURL } from 'ufo';
3
+
4
+ export default ({ request }: LoaderFunctionArgs) => {
5
+ const target = resolveURL(request.url, './builder/transformed');
6
+ return redirect(target);
7
+ };
@@ -0,0 +1 @@
1
+ export default null;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { useSnapshot } from 'valtio';
3
+ import { useStore } from '@/stores';
4
+ import { ObjectInspector } from '@/components/ObjectInspector';
5
+
6
+ const Page: React.FC = () => {
7
+ const $store = useStore();
8
+ const store = useSnapshot($store);
9
+ return <ObjectInspector data={store.builder.context} sortObjectKeys={true} />;
10
+ };
11
+
12
+ export default Page;
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { useSnapshot } from 'valtio';
3
+ import { useStore } from '@/stores';
4
+ import { ObjectInspector } from '@/components/ObjectInspector';
5
+
6
+ const Page: React.FC = () => {
7
+ const $store = useStore();
8
+ const store = useSnapshot($store);
9
+ return (
10
+ <ObjectInspector data={store.framework.context} sortObjectKeys={true} />
11
+ );
12
+ };
13
+
14
+ export default Page;