@allahjs/umi-plugin-layout-lite 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # @allahjs/umi-plugin-layout-lite
2
+
3
+ 轻量版 Umi Layout 插件,替代官方 layout 插件并保留常用能力:
4
+
5
+ - 自动注入全局布局(基于 `ProLayout`)
6
+ - 支持 `export const layout = (...) => ({ ... })` 运行时配置
7
+ - 支持 `rightRender` / `rightContentRender`
8
+ - 兼容 `@ant-design/pro-components` 3.x:内部自动把 `rightContentRender` 适配为 `actionsRender`
9
+ - 支持路由 `icon` 字符串自动映射
10
+
11
+ ## 安装
12
+
13
+ ```bash
14
+ npm i @allahjs/umi-plugin-layout-lite
15
+ ```
16
+
17
+ ## 使用
18
+
19
+ 在 `config/config.ts` 中:
20
+
21
+ ```ts
22
+ import { defineConfig } from '@umijs/max'
23
+
24
+ export default defineConfig({
25
+ layout: false,
26
+ plugins: [require.resolve('@allahjs/umi-plugin-layout-lite')],
27
+ })
28
+ ```
29
+
30
+ 在 `src/app.tsx` 中:
31
+
32
+ ```tsx
33
+ export const layout = ({ initialState }: any) => ({
34
+ title: '管理系统',
35
+ rightContentRender: (_layoutProps: any, _dom: any, _meta: any) => {
36
+ return <div>自定义右上角</div>
37
+ },
38
+ })
39
+ ```
40
+
41
+ ## 发布
42
+
43
+ ```bash
44
+ cd packages/umi-plugin-layout-lite
45
+ npm publish --access public
46
+ ```
@@ -0,0 +1,5 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ declare function LayoutLite(props: any): react_jsx_runtime.JSX.Element;
4
+
5
+ export { LayoutLite as default };
package/dist/Layout.js ADDED
@@ -0,0 +1,127 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var max = require('@umijs/max');
6
+ var proComponents = require('@ant-design/pro-components');
7
+ var antd = require('antd');
8
+
9
+ const Exception = props => {
10
+ var _a, _b;
11
+ return ((!props.route && (props.noFound || props.notFound)) ||
12
+ (((_a = props.route) === null || _a === void 0 ? void 0 : _a.unaccessible) &&
13
+ (props.unAccessible || props.noAccessible)) ||
14
+ ((!props.route || ((_b = props.route) === null || _b === void 0 ? void 0 : _b.unaccessible)) && (jsxRuntime.jsx(antd.Result, { status: props.route ? '403' : '404', title: props.route ? '403' : '404', subTitle: props.route ? '抱歉,你无权访问该页面' : '抱歉,你访问的页面不存在', extra: jsxRuntime.jsx(antd.Button, { type: "primary", onClick: () => max.history.push('/'), children: "\u8FD4\u56DE\u9996\u9875" }) }))) ||
15
+ props.children);
16
+ };
17
+ function getRightRenderContent(opts) {
18
+ if (opts.runtimeConfig.rightRender) {
19
+ return opts.runtimeConfig.rightRender(opts.initialState, opts.setInitialState, opts.runtimeConfig);
20
+ }
21
+ if (opts.loading) {
22
+ return jsxRuntime.jsx(antd.Spin, { size: "small", style: { marginLeft: 8, marginRight: 8 } });
23
+ }
24
+ return null;
25
+ }
26
+ const filterRoutes = (routes, filterFn) => {
27
+ if (routes.length === 0)
28
+ return [];
29
+ const nextRoutes = [];
30
+ for (const route of routes) {
31
+ const nextRoute = { ...route };
32
+ if (filterFn(route)) {
33
+ if (Array.isArray(nextRoute.routes)) {
34
+ nextRoutes.push(...filterRoutes(nextRoute.routes, filterFn));
35
+ }
36
+ }
37
+ else {
38
+ if (Array.isArray(nextRoute.children)) {
39
+ nextRoute.children = filterRoutes(nextRoute.children, filterFn);
40
+ nextRoute.routes = nextRoute.children;
41
+ }
42
+ nextRoutes.push(nextRoute);
43
+ }
44
+ }
45
+ return nextRoutes;
46
+ };
47
+ const mapRoutes = (routes) => {
48
+ if (routes.length === 0)
49
+ return [];
50
+ return routes.map(route => {
51
+ const nextRoute = { ...route };
52
+ if (route.originPath) {
53
+ nextRoute.path = route.originPath;
54
+ }
55
+ if (Array.isArray(route.routes)) {
56
+ nextRoute.routes = mapRoutes(route.routes);
57
+ }
58
+ if (Array.isArray(route.children)) {
59
+ nextRoute.children = mapRoutes(route.children);
60
+ }
61
+ return nextRoute;
62
+ });
63
+ };
64
+ function LayoutLite(props) {
65
+ const location = max.useLocation();
66
+ const navigate = max.useNavigate();
67
+ const { clientRoutes, pluginManager } = max.useAppData();
68
+ const initialInfo = max.useModel('@@initialState') || {
69
+ initialState: undefined,
70
+ loading: false,
71
+ setInitialState: null,
72
+ };
73
+ const { initialState, loading, setInitialState } = initialInfo;
74
+ const runtimeConfig = pluginManager.applyPlugins({
75
+ key: 'layout',
76
+ type: 'modify',
77
+ initialValue: {
78
+ ...initialInfo,
79
+ },
80
+ });
81
+ const userConfig = {};
82
+ const newRoutes = filterRoutes(clientRoutes.filter((route) => route.id === 'layout-lite'), route => (route.isLayout && route.id !== 'layout-lite') || !!route.isWrapper);
83
+ const route = mapRoutes(newRoutes)[0];
84
+ const matchedRoute = React.useMemo(() => { var _a, _b, _c; return (_c = (_b = (_a = max.matchRoutes((route === null || route === void 0 ? void 0 : route.children) || [], location.pathname)) === null || _a === void 0 ? void 0 : _a.pop) === null || _b === void 0 ? void 0 : _b.call(_a)) === null || _c === void 0 ? void 0 : _c.route; }, [route, location.pathname]);
85
+ const renderRightActions = (layoutProps) => {
86
+ const dom = getRightRenderContent({
87
+ runtimeConfig,
88
+ loading,
89
+ initialState,
90
+ setInitialState,
91
+ });
92
+ if (runtimeConfig.rightContentRender) {
93
+ return runtimeConfig.rightContentRender(layoutProps, dom, {
94
+ userConfig,
95
+ runtimeConfig,
96
+ loading,
97
+ initialState,
98
+ setInitialState,
99
+ });
100
+ }
101
+ return dom;
102
+ };
103
+ return (jsxRuntime.jsx(proComponents.ProLayout, { route: route, location: location, title: runtimeConfig.title || 'layout-lite', menu: { locale: runtimeConfig.locale }, onMenuHeaderClick: event => {
104
+ event.stopPropagation();
105
+ event.preventDefault();
106
+ navigate('/');
107
+ }, menuItemRender: (menuItemProps, defaultDom) => {
108
+ if (menuItemProps.isUrl || menuItemProps.children) {
109
+ return defaultDom;
110
+ }
111
+ if (menuItemProps.path && location.pathname !== menuItemProps.path) {
112
+ return (jsxRuntime.jsx(max.Link, { to: menuItemProps.path.replace('/*', ''), target: menuItemProps.target, children: defaultDom }));
113
+ }
114
+ return defaultDom;
115
+ }, itemRender: (currentRoute, _, routes) => {
116
+ const label = currentRoute.title || currentRoute.breadcrumbName;
117
+ const lastRoute = routes[routes.length - 1];
118
+ if (lastRoute && (lastRoute.path === currentRoute.path || lastRoute.linkPath === currentRoute.path)) {
119
+ return jsxRuntime.jsx("span", { children: label });
120
+ }
121
+ return jsxRuntime.jsx(max.Link, { to: currentRoute.path || '/', children: label });
122
+ }, actionsRender: renderRightActions, ...runtimeConfig, children: jsxRuntime.jsx(Exception, { route: matchedRoute, noFound: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.noFound, notFound: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.notFound, unAccessible: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.unAccessible, noAccessible: runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.noAccessible, children: runtimeConfig.childrenRender
123
+ ? runtimeConfig.childrenRender(jsxRuntime.jsx(max.Outlet, {}), props)
124
+ : jsxRuntime.jsx(max.Outlet, {}) }) }));
125
+ }
126
+
127
+ module.exports = LayoutLite;
@@ -0,0 +1,5 @@
1
+ import { IApi } from 'umi';
2
+
3
+ declare const _default: (api: IApi) => void;
4
+
5
+ export { _default as default };
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ var index = (api) => {
4
+ api.addLayouts(() => {
5
+ return [
6
+ {
7
+ id: 'layout-lite',
8
+ file: require.resolve('./Layout'),
9
+ test: (route) => route.layout !== false,
10
+ },
11
+ ];
12
+ });
13
+ api.addRuntimePluginKey(() => ['layout']);
14
+ api.addRuntimePlugin(() => {
15
+ return [require.resolve('./runtime')];
16
+ });
17
+ };
18
+
19
+ module.exports = index;
@@ -0,0 +1,3 @@
1
+ declare function patchRoutes({ routes }: any): void;
2
+
3
+ export { patchRoutes };
@@ -0,0 +1,44 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var Icons = require('@ant-design/icons');
5
+
6
+ function _interopNamespaceDefault(e) {
7
+ var n = Object.create(null);
8
+ if (e) {
9
+ Object.keys(e).forEach(function (k) {
10
+ if (k !== 'default') {
11
+ var d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: function () { return e[k]; }
15
+ });
16
+ }
17
+ });
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+
23
+ var Icons__namespace = /*#__PURE__*/_interopNamespaceDefault(Icons);
24
+
25
+ function formatIcon(name) {
26
+ return name
27
+ .replace(name[0], name[0].toUpperCase())
28
+ .replace(/-(\w)/g, (_all, letter) => letter.toUpperCase());
29
+ }
30
+ function patchRoutes({ routes }) {
31
+ Object.keys(routes).forEach(key => {
32
+ var _a;
33
+ const icon = (_a = routes[key]) === null || _a === void 0 ? void 0 : _a.icon;
34
+ if (!icon || typeof icon !== 'string')
35
+ return;
36
+ const iconName = formatIcon(icon);
37
+ const IconComponent = Icons__namespace[iconName] || Icons__namespace[`${iconName}Outlined`];
38
+ if (IconComponent) {
39
+ routes[key].icon = React.createElement(IconComponent);
40
+ }
41
+ });
42
+ }
43
+
44
+ exports.patchRoutes = patchRoutes;
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@allahjs/umi-plugin-layout-lite",
3
+ "version": "0.1.0",
4
+ "description": "A lightweight Umi layout plugin with ProLayout and rightContentRender compatibility.",
5
+ "repository": "https://github.com/allah-prime/umi-plugin-layout-lite",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md"
11
+ ],
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.js"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "build": "rimraf dist && rollup -c",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "umi",
25
+ "umijs",
26
+ "plugin",
27
+ "layout",
28
+ "prolayout",
29
+ "antd"
30
+ ],
31
+ "peerDependencies": {
32
+ "@ant-design/icons": ">=6",
33
+ "@ant-design/pro-components": ">=3.0.0-0",
34
+ "@umijs/max": ">=4",
35
+ "antd": ">=6",
36
+ "react": ">=18",
37
+ "react-dom": ">=18",
38
+ "umi": ">=4"
39
+ },
40
+ "devDependencies": {
41
+ "@rollup/plugin-commonjs": "^28.0.9",
42
+ "@rollup/plugin-node-resolve": "^16.0.3",
43
+ "@rollup/plugin-typescript": "^12.3.0",
44
+ "@types/node": "^24.3.0",
45
+ "@types/react": "^19.2.0",
46
+ "rimraf": "^6.0.1",
47
+ "rollup": "^4.50.1",
48
+ "rollup-plugin-dts": "^6.2.3",
49
+ "rollup-plugin-peer-deps-external": "^2.2.4",
50
+ "tslib": "^2.8.1",
51
+ "typescript": "^5.9.0"
52
+ },
53
+ "license": "MIT"
54
+ }