create-yoya-ui 0.2.1 → 0.2.3

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 (75) hide show
  1. package/README.md +11 -10
  2. package/bin/create-yoya-ui.js +1 -1
  3. package/package.json +1 -1
  4. package/templates/admin/README.md +59 -47
  5. package/templates/admin/RULES.md +105 -0
  6. package/templates/admin/src/features/dashboard/todos/pages/todo-approval-page.js +5 -0
  7. package/templates/admin/src/features/ops/deploys/pages/deploy-list-page.js +5 -0
  8. package/templates/admin/src/features/ops/services/pages/service-list-page.js +5 -0
  9. package/templates/admin/src/features/{dicts → system/dicts}/api/dict.mgr.d.ts +24 -17
  10. package/templates/admin/src/features/{dicts → system/dicts}/api/dict.mgr.js +24 -14
  11. package/templates/admin/src/features/{dicts → system/dicts}/api/dict.mock.js +22 -4
  12. package/templates/admin/src/features/{dicts → system/dicts}/api/dict.state.d.ts +5 -0
  13. package/templates/admin/src/features/{dicts → system/dicts}/api/dict.state.js +39 -8
  14. package/templates/admin/src/features/{dicts → system/dicts}/components/dict-editor-dialog.js +1 -1
  15. package/templates/admin/src/features/{dicts → system/dicts}/pages/dict-list-page.js +41 -21
  16. package/templates/admin/src/features/{members → system/members}/api/member.mgr.d.ts +10 -9
  17. package/templates/admin/src/features/{members → system/members}/api/member.mgr.js +8 -3
  18. package/templates/admin/src/features/{members → system/members}/api/member.mock.js +1 -1
  19. package/templates/admin/src/features/{members → system/members}/api/member.req.d.ts +1 -1
  20. package/templates/admin/src/features/{members → system/members}/api/member.req.js +3 -1
  21. package/templates/admin/src/features/{members → system/members}/api/member.state.js +4 -4
  22. package/templates/admin/src/features/{members → system/members}/components/member-table.js +1 -1
  23. package/templates/admin/src/features/{permissions → system/permissions}/api/permission.mgr.d.ts +11 -9
  24. package/templates/admin/src/features/{permissions → system/permissions}/api/permission.mgr.js +10 -5
  25. package/templates/admin/src/features/{permissions → system/permissions}/api/permission.mock.js +1 -1
  26. package/templates/admin/src/features/{permissions → system/permissions}/api/permission.state.js +4 -4
  27. package/templates/admin/src/features/{permissions → system/permissions}/pages/permission-list-page.js +1 -1
  28. package/templates/admin/src/features/{roles → system/roles}/api/role.mgr.d.ts +19 -6
  29. package/templates/admin/src/features/{roles → system/roles}/api/role.mgr.js +8 -3
  30. package/templates/admin/src/features/{roles → system/roles}/api/role.mock.js +1 -1
  31. package/templates/admin/src/features/{roles → system/roles}/api/role.state.js +4 -4
  32. package/templates/admin/src/features/{roles → system/roles}/components/role-table.js +1 -1
  33. package/templates/admin/src/main.js +16 -12
  34. package/templates/admin/src/{ui/row-action-button.js → shared/ui.buttons.js} +1 -0
  35. package/templates/admin/src/{ui/placeholder-page.js → shared/ui.pages.js} +1 -0
  36. package/templates/admin/src/shell/api/shell.mock.js +42 -0
  37. package/templates/admin/src/shell/api/shell.req.js +17 -0
  38. package/templates/admin/src/shell/api/shell.state.js +90 -0
  39. package/templates/admin/src/shell/api/shell.views.js +19 -0
  40. package/templates/admin/src/shell/components/admin-shell.js +42 -0
  41. package/templates/admin/src/{ui → shell/components}/app-navbar.js +11 -12
  42. package/templates/admin/src/shell/components/app-sidebar.js +44 -0
  43. package/templates/admin/src/{ui → shell/components}/sidebar-menu.js +3 -3
  44. package/templates/admin/src/shell/router.js +40 -0
  45. package/templates/admin/node_modules/.vite/deps/_metadata.json +0 -8
  46. package/templates/admin/node_modules/.vite/deps/package.json +0 -3
  47. package/templates/admin/src/app/admin-shell.js +0 -51
  48. package/templates/admin/src/app/modules.js +0 -37
  49. package/templates/admin/src/app/router.js +0 -20
  50. package/templates/admin/src/ui/app-sidebar.js +0 -27
  51. /package/templates/admin/src/features/dashboard/{components → overview/components}/dashboard-chart.js +0 -0
  52. /package/templates/admin/src/features/dashboard/{pages → overview/pages}/dashboard-overview-page.js +0 -0
  53. /package/templates/admin/src/features/{dicts → system/dicts}/api/dict.views.d.ts +0 -0
  54. /package/templates/admin/src/features/{dicts → system/dicts}/api/dict.views.js +0 -0
  55. /package/templates/admin/src/features/{dicts → system/dicts}/components/dict-item-form-dialog.js +0 -0
  56. /package/templates/admin/src/features/{dicts → system/dicts}/utils/options.js +0 -0
  57. /package/templates/admin/src/features/{members → system/members}/api/member.state.d.ts +0 -0
  58. /package/templates/admin/src/features/{members → system/members}/api/member.views.d.ts +0 -0
  59. /package/templates/admin/src/features/{members → system/members}/api/member.views.js +0 -0
  60. /package/templates/admin/src/features/{members → system/members}/components/member-form-dialog.js +0 -0
  61. /package/templates/admin/src/features/{members → system/members}/components/member-toolbar.js +0 -0
  62. /package/templates/admin/src/features/{members → system/members}/pages/member-list-page.js +0 -0
  63. /package/templates/admin/src/features/{members → system/members}/utils/options.d.ts +0 -0
  64. /package/templates/admin/src/features/{members → system/members}/utils/options.js +0 -0
  65. /package/templates/admin/src/features/{permissions → system/permissions}/api/permission.state.d.ts +0 -0
  66. /package/templates/admin/src/features/{permissions → system/permissions}/api/permission.views.d.ts +0 -0
  67. /package/templates/admin/src/features/{permissions → system/permissions}/api/permission.views.js +0 -0
  68. /package/templates/admin/src/features/{permissions → system/permissions}/components/permission-form-dialog.js +0 -0
  69. /package/templates/admin/src/features/{roles → system/roles}/api/role.state.d.ts +0 -0
  70. /package/templates/admin/src/features/{roles → system/roles}/api/role.views.d.ts +0 -0
  71. /package/templates/admin/src/features/{roles → system/roles}/api/role.views.js +0 -0
  72. /package/templates/admin/src/features/{roles → system/roles}/components/role-form-dialog.js +0 -0
  73. /package/templates/admin/src/features/{roles → system/roles}/components/role-toolbar.js +0 -0
  74. /package/templates/admin/src/features/{roles → system/roles}/pages/role-list-page.js +0 -0
  75. /package/templates/admin/src/features/{roles → system/roles}/utils/options.js +0 -0
@@ -0,0 +1,42 @@
1
+ // 演示用内存 mock(接入真实后端后删除本文件)。
2
+ import { mockRequest } from '../../api/domain.api.js';
3
+
4
+ const delay = (ms = 200) => new Promise((resolve) => setTimeout(resolve, ms));
5
+
6
+ mockRequest('GET', '/menus', async () => {
7
+ await delay();
8
+ return {
9
+ ok: true,
10
+ data: [
11
+ {
12
+ key: 'dashboard',
13
+ label: '工作台',
14
+ icon: 'D',
15
+ routes: [
16
+ { path: '/dashboard/overview', title: '数据概览', viewKey: 'dashboard-overview' },
17
+ { path: '/dashboard/todos', title: '待办审批', viewKey: 'todo-approval' }
18
+ ]
19
+ },
20
+ {
21
+ key: 'ops',
22
+ label: '运维',
23
+ icon: 'O',
24
+ routes: [
25
+ { path: '/ops/services', title: '服务清单', viewKey: 'service-list' },
26
+ { path: '/ops/deploys', title: '部署任务', viewKey: 'deploy-list' }
27
+ ]
28
+ },
29
+ {
30
+ key: 'system',
31
+ label: '系统',
32
+ icon: 'S',
33
+ routes: [
34
+ { path: '/system/members', title: '成员管理', viewKey: 'member-list' },
35
+ { path: '/system/roles', title: '角色管理', viewKey: 'role-list' },
36
+ { path: '/system/permissions', title: '权限管理', viewKey: 'permission-list' },
37
+ { path: '/system/dicts', title: '字典管理', viewKey: 'dict-list' }
38
+ ]
39
+ }
40
+ ]
41
+ };
42
+ });
@@ -0,0 +1,17 @@
1
+ // 外壳请求命令:其他模块(启动装配)调用本域能力的入口,方便后续替换为服务端接口(去掉 mock 即可)。
2
+ import { RequestBase } from '@yoyaflow/yoya-ui';
3
+ import Shell from './shell.views.js';
4
+
5
+ class QueryMenus extends RequestBase {
6
+ address() {
7
+ return '/menus';
8
+ }
9
+
10
+ toItem(row) {
11
+ return new Shell.Module(row);
12
+ }
13
+ }
14
+
15
+ export default {
16
+ QueryMenus: (init) => new QueryMenus(init)
17
+ };
@@ -0,0 +1,90 @@
1
+ // 外壳状态类:菜单数据 + 导航状态(当前模块 / 当前路径)的唯一事实源,
2
+ // 加载时创建并持有路由,暴露导航动作(switchModule / navigate),由路由订阅驱动 syncFromPath。
3
+ import ShellReq from './shell.req.js';
4
+ import { createAppRouter } from '../router.js';
5
+
6
+ export default class ShellState {
7
+ constructor() {
8
+ this._menus = [];
9
+ this._router = null;
10
+ this._activeModuleKey = null;
11
+ this._activePath = null;
12
+ this._listeners = new Set();
13
+ this._unsubscribeRouter = null;
14
+ }
15
+
16
+ menus() {
17
+ return this._menus;
18
+ }
19
+
20
+ router() {
21
+ return this._router;
22
+ }
23
+
24
+ activeModuleKey() {
25
+ return this._activeModuleKey;
26
+ }
27
+
28
+ activePath() {
29
+ return this._activePath;
30
+ }
31
+
32
+ subscribe(listener) {
33
+ this._listeners.add(listener);
34
+ return () => this._listeners.delete(listener);
35
+ }
36
+
37
+ async load() {
38
+ const result = await ShellReq.QueryMenus().submit();
39
+ this._menus = result.data;
40
+ this._router = createAppRouter(this._menus);
41
+ this._unsubscribeRouter = this._router.subscribe((context) => this.syncFromPath(context.path));
42
+ this._emit();
43
+ return result;
44
+ }
45
+
46
+ start() {
47
+ this._router?.start();
48
+ return this;
49
+ }
50
+
51
+ // 顶栏切换模块:进入模块首个路由。
52
+ switchModule(module) {
53
+ const first = module?.routes?.[0];
54
+ if (first) {
55
+ this._router?.navigate(first.path);
56
+ }
57
+ return this;
58
+ }
59
+
60
+ // 侧栏 / 任意入口:打开指定路径。
61
+ navigate(path) {
62
+ this._router?.navigate(path);
63
+ return this;
64
+ }
65
+
66
+ syncFromPath(path) {
67
+ const module = this._menus.find((entry) =>
68
+ entry.routes.some((route) => route.path === path)
69
+ );
70
+ const changed =
71
+ this._activePath !== path || (module && this._activeModuleKey !== module.key);
72
+ this._activePath = path;
73
+ if (module) {
74
+ this._activeModuleKey = module.key;
75
+ }
76
+ if (changed) {
77
+ this._emit();
78
+ }
79
+ return this;
80
+ }
81
+
82
+ destroy() {
83
+ this._unsubscribeRouter?.();
84
+ this._listeners.clear();
85
+ }
86
+
87
+ _emit() {
88
+ this._listeners.forEach((listener) => listener());
89
+ }
90
+ }
@@ -0,0 +1,19 @@
1
+ // 外壳结果结构(纯数据):菜单模块与路由,服务端返回后由 toItem 映射。
2
+ class Route {
3
+ constructor({ path, title, viewKey }) {
4
+ this.path = path;
5
+ this.title = title;
6
+ this.viewKey = viewKey;
7
+ }
8
+ }
9
+
10
+ class Module {
11
+ constructor({ key, label, icon, routes = [] }) {
12
+ this.key = key;
13
+ this.label = label;
14
+ this.icon = icon;
15
+ this.routes = routes.map((route) => new Route(route));
16
+ }
17
+ }
18
+
19
+ export default { Module, Route };
@@ -0,0 +1,42 @@
1
+ import { vBody, vRouterViews } from '@yoyaflow/yoya-ui';
2
+ import { AppNavbar } from './app-navbar.js';
3
+ import { AppSidebar } from './app-sidebar.js';
4
+
5
+ // 外壳装配:只做布局组装与状态接线。路由与导航动作都在 ShellState。
6
+ // URL 变化 → state.syncFromPath() → 状态通知 → 顶栏 / 侧栏从状态派生高亮。
7
+ export function AdminShell({ state }) {
8
+ const navbar = AppNavbar({ state });
9
+ const sidebar = AppSidebar({ state });
10
+
11
+ const unsubscribe = state.subscribe(() => {
12
+ navbar.applyState();
13
+ sidebar.applyState();
14
+ });
15
+
16
+ return {
17
+ render() {
18
+ return vBody((shell) => {
19
+ shell.gap(0);
20
+ shell.maxWidth('100%');
21
+ shell.padding(0);
22
+ shell.vContainer((frame) => {
23
+ frame.viewport(true);
24
+ frame.vHeader({ height: 56 }, (header) => {
25
+ header.style('padding', '0');
26
+ header.child(navbar);
27
+ });
28
+ frame.vContainer((body) => {
29
+ body.style({ flex: '1 1 auto', minHeight: '0' });
30
+ body.child(sidebar);
31
+ body.vMain((main) => {
32
+ main.child(vRouterViews(state.router(), { lockTitle: true, title: '内容区' }));
33
+ });
34
+ });
35
+ });
36
+ });
37
+ },
38
+ destroy() {
39
+ unsubscribe();
40
+ }
41
+ };
42
+ }
@@ -1,8 +1,14 @@
1
1
  import { vAvatar, vNavbar } from '@yoyaflow/yoya-ui';
2
2
 
3
- export function AppNavbar({ modules, onModuleChange }) {
3
+ export function AppNavbar({ state }) {
4
4
  const items = new Map();
5
- let activeKey = null;
5
+
6
+ function applyState() {
7
+ const activeKey = state.activeModuleKey();
8
+ items.forEach((item, key) => {
9
+ item.active(key === activeKey);
10
+ });
11
+ }
6
12
 
7
13
  return {
8
14
  render() {
@@ -39,11 +45,11 @@ export function AppNavbar({ modules, onModuleChange }) {
39
45
  });
40
46
  });
41
47
  nav.menuContent((menu) => {
42
- modules.forEach((module) => {
48
+ state.menus().forEach((module) => {
43
49
  menu.vMenuItem((item) => {
44
50
  item.text(module.label);
45
51
  items.set(module.key, item);
46
- item.on('click', () => onModuleChange(module));
52
+ item.on('click', () => state.switchModule(module));
47
53
  });
48
54
  });
49
55
  });
@@ -55,13 +61,6 @@ export function AppNavbar({ modules, onModuleChange }) {
55
61
  });
56
62
  });
57
63
  },
58
- activate(key) {
59
- if (activeKey && activeKey !== key) {
60
- items.get(activeKey)?.active(false);
61
- }
62
- activeKey = key;
63
- items.get(key)?.active(true);
64
- return this;
65
- }
64
+ applyState
66
65
  };
67
66
  }
@@ -0,0 +1,44 @@
1
+ import { vSidebar } from '@yoyaflow/yoya-ui';
2
+ import { SidebarMenu } from './sidebar-menu.js';
3
+
4
+ export function AppSidebar({ state }) {
5
+ let sidebar = null;
6
+
7
+ function render() {
8
+ sidebar = vSidebar((side) => {
9
+ side.ariaLabel('左侧菜单');
10
+ side.title('导航');
11
+ side.collapsible(false);
12
+ side.style({
13
+ flex: '0 0 auto',
14
+ width: '220px',
15
+ gridTemplateRows: 'auto minmax(0, 1fr)'
16
+ });
17
+ });
18
+ return sidebar;
19
+ }
20
+
21
+ function applyState() {
22
+ if (!sidebar) {
23
+ return;
24
+ }
25
+ const module = state.menus().find((entry) => entry.key === state.activeModuleKey());
26
+ if (!module) {
27
+ return;
28
+ }
29
+ sidebar.menuContent((menu) => {
30
+ menu.child(
31
+ SidebarMenu({
32
+ module,
33
+ activePath: state.activePath(),
34
+ onNavigate: (path) => state.navigate(path)
35
+ })
36
+ );
37
+ });
38
+ }
39
+
40
+ return {
41
+ render,
42
+ applyState
43
+ };
44
+ }
@@ -1,13 +1,13 @@
1
1
  import { vMenuGroup } from '@yoyaflow/yoya-ui';
2
2
 
3
- export function SidebarMenu({ module, router }) {
3
+ export function SidebarMenu({ module, activePath, onNavigate }) {
4
4
  return vMenuGroup((group) => {
5
5
  group.label(module.label);
6
6
  module.routes.forEach((route) => {
7
7
  group.vMenuItem((item) => {
8
8
  item.text(route.title);
9
- item.active(route.path === router.currentPath());
10
- item.on('click', () => router.navigate(route.path));
9
+ item.active(route.path === activePath);
10
+ item.on('click', () => onNavigate(route.path));
11
11
  });
12
12
  });
13
13
  });
@@ -0,0 +1,40 @@
1
+ import { createRouter } from '@yoyaflow/yoya-ui';
2
+ import { PlaceholderPage } from '../shared/ui.pages.js';
3
+ import { DashboardOverviewPage } from '../features/dashboard/overview/pages/dashboard-overview-page.js';
4
+ import { TodoApprovalPage } from '../features/dashboard/todos/pages/todo-approval-page.js';
5
+ import { ServiceListPage } from '../features/ops/services/pages/service-list-page.js';
6
+ import { DeployListPage } from '../features/ops/deploys/pages/deploy-list-page.js';
7
+ import { MemberListPage } from '../features/system/members/pages/member-list-page.js';
8
+ import { RoleListPage } from '../features/system/roles/pages/role-list-page.js';
9
+ import { PermissionListPage } from '../features/system/permissions/pages/permission-list-page.js';
10
+ import { DictListPage } from '../features/system/dicts/pages/dict-list-page.js';
11
+
12
+ // 菜单视图注册表:服务端菜单只返回 viewKey,由这里映射到客户端页面组件。
13
+ const viewRegistry = {
14
+ 'dashboard-overview': DashboardOverviewPage,
15
+ 'todo-approval': TodoApprovalPage,
16
+ 'service-list': ServiceListPage,
17
+ 'deploy-list': DeployListPage,
18
+ 'member-list': MemberListPage,
19
+ 'role-list': RoleListPage,
20
+ 'permission-list': PermissionListPage,
21
+ 'dict-list': DictListPage
22
+ };
23
+
24
+ export function createAppRouter(menus) {
25
+ const router = createRouter((r) => {
26
+ menus.forEach((module) => {
27
+ module.routes.forEach((route) => {
28
+ const Page = viewRegistry[route.viewKey];
29
+ r.route(route.path, {
30
+ title: route.title,
31
+ view: () =>
32
+ Page ? Page() : PlaceholderPage({ title: route.title, text: '该页面待开发。' })
33
+ });
34
+ });
35
+ });
36
+ r.notFound(() => PlaceholderPage({ title: '未找到', text: '该页面不存在。' }));
37
+ });
38
+ router.default(menus[0].routes[0].path);
39
+ return router;
40
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "hash": "307bbf2f",
3
- "configHash": "670dd850",
4
- "lockfileHash": "7fb7e123",
5
- "browserHash": "54e0f4b6",
6
- "optimized": {},
7
- "chunks": {}
8
- }
@@ -1,3 +0,0 @@
1
- {
2
- "type": "module"
3
- }
@@ -1,51 +0,0 @@
1
- import { vBody, vRouterViews } from '@yoyaflow/yoya-ui';
2
- import { AppNavbar } from '../ui/app-navbar.js';
3
- import { AppSidebar } from '../ui/app-sidebar.js';
4
-
5
- export function AdminShell({ router, modules }) {
6
- const navbar = AppNavbar({ modules, onModuleChange: switchModule });
7
- const sidebar = AppSidebar({ router });
8
-
9
- function switchModule(module) {
10
- navbar.activate(module.key);
11
- router.navigate(module.routes[0].path);
12
- sidebar.showModule(module);
13
- }
14
-
15
- function syncModuleFromUrl() {
16
- const path = router.currentPath();
17
- const module = modules.find((entry) => entry.routes.some((route) => route.path === path));
18
- if (!module) {
19
- return;
20
- }
21
- navbar.activate(module.key);
22
- sidebar.showModule(module);
23
- }
24
-
25
- return {
26
- render() {
27
- return vBody((shell) => {
28
- shell.gap(0);
29
- shell.maxWidth('100%');
30
- shell.padding(0);
31
- shell.vContainer((frame) => {
32
- frame.viewport(true);
33
- frame.vHeader({ height: 56 }, (header) => {
34
- header.style('padding', '0');
35
- header.child(navbar);
36
- });
37
- frame.vContainer((body) => {
38
- body.style({ flex: '1 1 auto', minHeight: '0' });
39
- body.child(sidebar);
40
- body.vMain((main) => {
41
- main.child(vRouterViews(router, { lockTitle: true, title: '内容区' }));
42
- });
43
- });
44
- });
45
- });
46
- },
47
- syncFromUrl() {
48
- syncModuleFromUrl();
49
- }
50
- };
51
- }
@@ -1,37 +0,0 @@
1
- import { MemberListPage } from '../features/members/pages/member-list-page.js';
2
- import { PermissionListPage } from '../features/permissions/pages/permission-list-page.js';
3
- import { RoleListPage } from '../features/roles/pages/role-list-page.js';
4
- import { DictListPage } from '../features/dicts/pages/dict-list-page.js';
5
- import { DashboardOverviewPage } from '../features/dashboard/pages/dashboard-overview-page.js';
6
-
7
- export const modules = [
8
- {
9
- key: 'dashboard',
10
- label: '工作台',
11
- icon: 'D',
12
- routes: [
13
- { path: '/dashboard/overview', title: '数据概览', view: DashboardOverviewPage },
14
- { path: '/dashboard/todos', title: '待办审批', text: '待处理审批与任务。' }
15
- ]
16
- },
17
- {
18
- key: 'ops',
19
- label: '运维',
20
- icon: 'O',
21
- routes: [
22
- { path: '/ops/services', title: '服务清单', text: '服务列表与健康状态。' },
23
- { path: '/ops/deploys', title: '部署任务', text: '发布记录与执行状态。' }
24
- ]
25
- },
26
- {
27
- key: 'system',
28
- label: '系统',
29
- icon: 'S',
30
- routes: [
31
- { path: '/system/members', title: '成员管理', view: MemberListPage },
32
- { path: '/system/roles', title: '角色管理', view: RoleListPage },
33
- { path: '/system/permissions', title: '权限管理', view: PermissionListPage },
34
- { path: '/system/dicts', title: '字典管理', view: DictListPage }
35
- ]
36
- }
37
- ];
@@ -1,20 +0,0 @@
1
- import { createRouter } from '@yoyaflow/yoya-ui';
2
- import { modules } from './modules.js';
3
- import { PlaceholderPage } from '../ui/placeholder-page.js';
4
-
5
- export function createAppRouter() {
6
- const router = createRouter((r) => {
7
- modules.forEach((module) => {
8
- module.routes.forEach((route) => {
9
- r.route(route.path, {
10
- title: route.title,
11
- view: () =>
12
- route.view ? route.view() : PlaceholderPage({ title: route.title, text: route.text })
13
- });
14
- });
15
- });
16
- r.notFound(() => PlaceholderPage({ title: '未找到', text: '该页面不存在。' }));
17
- });
18
- router.default(modules[0].routes[0].path);
19
- return router;
20
- }
@@ -1,27 +0,0 @@
1
- import { vSidebar } from '@yoyaflow/yoya-ui';
2
- import { SidebarMenu } from './sidebar-menu.js';
3
-
4
- export function AppSidebar({ router }) {
5
- const sidebar = vSidebar((side) => {
6
- side.ariaLabel('左侧菜单');
7
- side.title('导航');
8
- side.collapsible(false);
9
- });
10
- sidebar.style({
11
- flex: '0 0 auto',
12
- width: '220px',
13
- gridTemplateRows: 'auto minmax(0, 1fr)'
14
- });
15
-
16
- return {
17
- render() {
18
- return sidebar;
19
- },
20
- showModule(module) {
21
- sidebar.menuContent((menu) => {
22
- menu.child(SidebarMenu({ module, router }));
23
- });
24
- return this;
25
- }
26
- };
27
- }