@simplysm/solid 13.0.48 → 13.0.50

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 CHANGED
@@ -206,7 +206,7 @@ import "@simplysm/solid/tailwind.css";
206
206
  ## Styling
207
207
 
208
208
  - [Semantic Colors](docs/styling.md#semantic-colors) - primary, info, success, warning, danger, base
209
- - [Custom Sizes](docs/styling.md#custom-sizes) - Field height classes (h-field, h-field-sm, h-field-lg, h-field-xl)
209
+ - [Custom Sizes](docs/styling.md#custom-sizes) - Field height classes (h-field, h-field-xs, h-field-sm, h-field-lg, h-field-xl)
210
210
  - [z-index Layers](docs/styling.md#z-index-layers) - Sidebar, dropdown, modal z-index values
211
211
  - [Dark Mode](docs/styling.md#dark-mode) - Class-based dark mode with auto-toggle
212
212
  - [Styling Patterns](docs/styling.md#styling-patterns) - clsx + twMerge usage patterns
@@ -45,10 +45,14 @@ export interface AppFlatPerm<TModule = string> {
45
45
  titleChain: string[];
46
46
  code: string;
47
47
  modulesChain: TModule[][];
48
+ requiredModulesChain: TModule[][];
48
49
  }
49
- export interface AppRoute {
50
+ export interface AppRoute<TModule = string> {
50
51
  path: string;
51
52
  component: Component;
53
+ permCode?: string;
54
+ modulesChain: TModule[][];
55
+ requiredModulesChain: TModule[][];
52
56
  }
53
57
  export interface AppFlatMenu {
54
58
  titleChain: string[];
@@ -56,11 +60,12 @@ export interface AppFlatMenu {
56
60
  }
57
61
  export interface AppStructure<TModule> {
58
62
  items: AppStructureItem<TModule>[];
59
- usableRoutes: Accessor<AppRoute[]>;
63
+ allRoutes: AppRoute<TModule>[];
60
64
  usableMenus: Accessor<AppMenu[]>;
61
65
  usableFlatMenus: Accessor<AppFlatMenu[]>;
62
66
  usablePerms: Accessor<AppPerm<TModule>[]>;
63
- flatPerms: AppFlatPerm<TModule>[];
67
+ allFlatPerms: AppFlatPerm<TModule>[];
68
+ checkRouteAccess(route: AppRoute<TModule>): boolean;
64
69
  getTitleChainByHref(href: string): string[];
65
70
  }
66
71
  type PermKey<TItem> = TItem extends {
@@ -1 +1 @@
1
- {"version":3,"file":"createAppStructure.d.ts","sourceRoot":"","sources":["..\\..\\src\\helpers\\createAppStructure.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createAppStructure.d.ts","sourceRoot":"","sources":["..\\..\\src\\helpers\\createAppStructure.ts"],"names":[],"mappings":"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"}
@@ -12,21 +12,32 @@ function checkModules(modules, requiredModules, usableModules) {
12
12
  }
13
13
  return true;
14
14
  }
15
- function buildUsableRoutes(items, routeBasePath, permBasePath, usableModules, permRecord) {
15
+ function buildAllRoutes(items, routeBasePath, permBasePath, modulesChain, requiredModulesChain) {
16
16
  var _a;
17
17
  const result = [];
18
18
  for (const item of items) {
19
- if (!checkModules(item.modules, item.requiredModules, usableModules)) continue;
19
+ const currModulesChain = item.modules ? [...modulesChain, item.modules] : modulesChain;
20
+ const currRequiredModulesChain = item.requiredModules ? [...requiredModulesChain, item.requiredModules] : requiredModulesChain;
20
21
  const routePath = routeBasePath + "/" + item.code;
21
22
  const permPath = permBasePath + "/" + item.code;
22
23
  if (isGroupItem(item)) {
23
24
  result.push(
24
- ...buildUsableRoutes(item.children, routePath, permPath, usableModules, permRecord)
25
+ ...buildAllRoutes(
26
+ item.children,
27
+ routePath,
28
+ permPath,
29
+ currModulesChain,
30
+ currRequiredModulesChain
31
+ )
25
32
  );
26
33
  } else if (item.component !== void 0) {
27
- if (permRecord !== void 0 && ((_a = item.perms) == null ? void 0 : _a.includes("use")) && !permRecord[permPath + "/use"])
28
- continue;
29
- result.push({ path: routePath, component: item.component });
34
+ result.push({
35
+ path: routePath,
36
+ component: item.component,
37
+ permCode: ((_a = item.perms) == null ? void 0 : _a.includes("use")) ? permPath + "/use" : void 0,
38
+ modulesChain: currModulesChain,
39
+ requiredModulesChain: currRequiredModulesChain
40
+ });
30
41
  }
31
42
  }
32
43
  return result;
@@ -98,20 +109,23 @@ function collectFlatPerms(items) {
98
109
  item,
99
110
  titleChain: [],
100
111
  codePath: "",
101
- modulesChain: []
112
+ modulesChain: [],
113
+ requiredModulesChain: []
102
114
  }));
103
115
  while (queue.length > 0) {
104
- const { item, titleChain, codePath, modulesChain } = queue.shift();
116
+ const { item, titleChain, codePath, modulesChain, requiredModulesChain } = queue.shift();
105
117
  const currTitleChain = [...titleChain, item.title];
106
118
  const currCodePath = codePath + "/" + item.code;
107
119
  const currModulesChain = item.modules ? [...modulesChain, item.modules] : modulesChain;
120
+ const currRequiredModulesChain = item.requiredModules ? [...requiredModulesChain, item.requiredModules] : requiredModulesChain;
108
121
  if (isGroupItem(item)) {
109
122
  for (const child of item.children) {
110
123
  queue.push({
111
124
  item: child,
112
125
  titleChain: currTitleChain,
113
126
  codePath: currCodePath,
114
- modulesChain: currModulesChain
127
+ modulesChain: currModulesChain,
128
+ requiredModulesChain: currRequiredModulesChain
115
129
  });
116
130
  }
117
131
  } else {
@@ -120,18 +134,21 @@ function collectFlatPerms(items) {
120
134
  results.push({
121
135
  titleChain: currTitleChain,
122
136
  code: currCodePath + "/" + perm,
123
- modulesChain: currModulesChain
137
+ modulesChain: currModulesChain,
138
+ requiredModulesChain: currRequiredModulesChain
124
139
  });
125
140
  }
126
141
  }
127
142
  if (item.subPerms) {
128
143
  for (const subPerm of item.subPerms) {
129
144
  const subModulesChain = subPerm.modules ? [...currModulesChain, subPerm.modules] : currModulesChain;
145
+ const subRequiredModulesChain = subPerm.requiredModules ? [...currRequiredModulesChain, subPerm.requiredModules] : currRequiredModulesChain;
130
146
  for (const perm of subPerm.perms) {
131
147
  results.push({
132
148
  titleChain: currTitleChain,
133
149
  code: currCodePath + "/" + subPerm.code + "/" + perm,
134
- modulesChain: subModulesChain
150
+ modulesChain: subModulesChain,
151
+ requiredModulesChain: subRequiredModulesChain
135
152
  });
136
153
  }
137
154
  }
@@ -196,26 +213,24 @@ function findItemChainByCodes(items, codes) {
196
213
  return result;
197
214
  }
198
215
  function createAppStructure(opts) {
199
- const flatPerms = collectFlatPerms(opts.items);
216
+ const allFlatPerms = collectFlatPerms(opts.items);
217
+ const allRoutes = [];
218
+ for (const top of opts.items) {
219
+ if (isGroupItem(top)) {
220
+ const topModulesChain = top.modules ? [top.modules] : [];
221
+ const topRequiredModulesChain = top.requiredModules ? [top.requiredModules] : [];
222
+ allRoutes.push(
223
+ ...buildAllRoutes(
224
+ top.children,
225
+ "",
226
+ "/" + top.code,
227
+ topModulesChain,
228
+ topRequiredModulesChain
229
+ )
230
+ );
231
+ }
232
+ }
200
233
  const memos = createRoot(() => {
201
- const usableRoutes = createMemo(() => {
202
- var _a, _b;
203
- const routes = [];
204
- for (const top of opts.items) {
205
- if (isGroupItem(top)) {
206
- routes.push(
207
- ...buildUsableRoutes(
208
- top.children,
209
- "",
210
- "/" + top.code,
211
- (_a = opts.usableModules) == null ? void 0 : _a.call(opts),
212
- (_b = opts.permRecord) == null ? void 0 : _b.call(opts)
213
- )
214
- );
215
- }
216
- }
217
- return routes;
218
- });
219
234
  const usableMenus = createMemo(() => {
220
235
  var _a, _b;
221
236
  const menus = [];
@@ -238,16 +253,39 @@ function createAppStructure(opts) {
238
253
  var _a;
239
254
  return buildPerms(opts.items, "", (_a = opts.usableModules) == null ? void 0 : _a.call(opts));
240
255
  });
241
- return { usableRoutes, usableMenus, usableFlatMenus, usablePerms };
256
+ return { usableMenus, usableFlatMenus, usablePerms };
242
257
  });
243
258
  const permsObj = buildPermsObject(opts.items, "", opts.permRecord);
244
259
  return {
245
260
  items: opts.items,
246
- usableRoutes: memos.usableRoutes,
261
+ allRoutes,
247
262
  usableMenus: memos.usableMenus,
248
263
  usableFlatMenus: memos.usableFlatMenus,
249
264
  usablePerms: memos.usablePerms,
250
- flatPerms,
265
+ allFlatPerms,
266
+ checkRouteAccess(route) {
267
+ var _a, _b;
268
+ const usableModules = (_a = opts.usableModules) == null ? void 0 : _a.call(opts);
269
+ if (usableModules !== void 0) {
270
+ for (const modules of route.modulesChain) {
271
+ if (modules.length > 0 && !modules.some((m) => usableModules.includes(m))) {
272
+ return false;
273
+ }
274
+ }
275
+ for (const modules of route.requiredModulesChain) {
276
+ if (modules.length > 0 && !modules.every((m) => usableModules.includes(m))) {
277
+ return false;
278
+ }
279
+ }
280
+ }
281
+ if (route.permCode !== void 0) {
282
+ const permRecord = (_b = opts.permRecord) == null ? void 0 : _b.call(opts);
283
+ if (permRecord !== void 0) {
284
+ return permRecord[route.permCode] ?? false;
285
+ }
286
+ }
287
+ return true;
288
+ },
251
289
  perms: permsObj,
252
290
  getTitleChainByHref(href) {
253
291
  const codes = href.split("/").filter(Boolean);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/helpers/createAppStructure.ts"],
4
- "mappings": "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",
4
+ "mappings": "AACA,SAAwB,YAAY,kBAAkB;AAyHtD,SAAS,YACP,MACwC;AACxC,SAAO,cAAc;AACvB;AAEA,SAAS,aACP,SACA,iBACA,eACS;AACT,MAAI,kBAAkB,OAAW,QAAO;AAExC,MAAI,YAAY,UAAa,QAAQ,SAAS,GAAG;AAC/C,QAAI,CAAC,QAAQ,KAAK,CAAC,MAAM,cAAc,SAAS,CAAC,CAAC,EAAG,QAAO;AAAA,EAC9D;AAEA,MAAI,oBAAoB,UAAa,gBAAgB,SAAS,GAAG;AAC/D,QAAI,CAAC,gBAAgB,MAAM,CAAC,MAAM,cAAc,SAAS,CAAC,CAAC,EAAG,QAAO;AAAA,EACvE;AAEA,SAAO;AACT;AAIA,SAAS,eACP,OACA,eACA,cACA,cACA,sBACqB;AA1JvB;AA2JE,QAAM,SAA8B,CAAC;AAErC,aAAW,QAAQ,OAAO;AACxB,UAAM,mBAAgC,KAAK,UACvC,CAAC,GAAG,cAAc,KAAK,OAAO,IAC9B;AACJ,UAAM,2BAAwC,KAAK,kBAC/C,CAAC,GAAG,sBAAsB,KAAK,eAAe,IAC9C;AAEJ,UAAM,YAAY,gBAAgB,MAAM,KAAK;AAC7C,UAAM,WAAW,eAAe,MAAM,KAAK;AAE3C,QAAI,YAAY,IAAI,GAAG;AACrB,aAAO;AAAA,QACL,GAAG;AAAA,UACD,KAAK;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,KAAK,cAAc,QAAW;AACvC,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,QAChB,YAAU,UAAK,UAAL,mBAAY,SAAS,UAAS,WAAW,SAAS;AAAA,QAC5D,cAAc;AAAA,QACd,sBAAsB;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAIA,SAAS,WACP,OACA,UACA,eACA,YACW;AAvMb;AAwME,QAAM,SAAoB,CAAC;AAE3B,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,aAAa,KAAK,SAAS,KAAK,iBAAiB,aAAa,EAAG;AAEtE,UAAM,OAAO,WAAW,MAAM,KAAK;AAEnC,QAAI,YAAY,IAAI,GAAG;AACrB,YAAM,WAAW,WAAW,KAAK,UAAU,MAAM,eAAe,UAAU;AAC1E,UAAI,SAAS,SAAS,GAAG;AACvB,eAAO,KAAK,EAAE,OAAO,KAAK,OAAO,MAAM,KAAK,MAAM,SAAS,CAAC;AAAA,MAC9D;AAAA,IACF,OAAO;AACL,UAAI,KAAK,UAAW;AACpB,YAAI,UAAK,UAAL,mBAAY,SAAS,WAAU,EAAC,yCAAa,OAAO,SAAS;AAEjE,aAAO,KAAK,EAAE,OAAO,KAAK,OAAO,MAAM,MAAM,KAAK,KAAK,CAAC;AAAA,IAC1D;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,aAAa,OAAkB,aAAuB,CAAC,GAAkB;AAChF,QAAM,SAAwB,CAAC;AAE/B,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,CAAC,GAAG,YAAY,KAAK,KAAK;AAExC,QAAI,KAAK,aAAa,QAAW;AAC/B,aAAO,KAAK,GAAG,aAAa,KAAK,UAAU,KAAK,CAAC;AAAA,IACnD,WAAW,KAAK,SAAS,QAAW;AAClC,aAAO,KAAK,EAAE,YAAY,OAAO,MAAM,KAAK,KAAK,CAAC;AAAA,IACpD;AAAA,EACF;AAEA,SAAO;AACT;AAIA,SAAS,WACP,OACA,UACA,eACoB;AArPtB;AAsPE,QAAM,SAA6B,CAAC;AAEpC,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,aAAa,KAAK,SAAS,KAAK,iBAAiB,aAAa,EAAG;AAEtE,UAAM,OAAO,WAAW,MAAM,KAAK;AAEnC,QAAI,YAAY,IAAI,GAAG;AACrB,YAAM,WAAW,WAAW,KAAK,UAAU,MAAM,aAAa;AAC9D,aAAO,KAAK;AAAA,QACV,OAAO,KAAK;AAAA,QACZ,SAAS,KAAK;AAAA,QACd;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,aAAO,KAAK;AAAA,QACV,OAAO,KAAK;AAAA,QACZ;AAAA,QACA,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,WAAU,UAAK,aAAL,mBACN,OAAO,CAAC,OAAO,aAAa,GAAG,SAAS,GAAG,iBAAiB,aAAa,GAC1E,IAAI,CAAC,QAAQ;AAAA,UACZ,OAAO,GAAG;AAAA,UACV,MAAM,OAAO,MAAM,GAAG;AAAA,UACtB,SAAS,GAAG;AAAA,UACZ,OAAO,GAAG;AAAA,QACZ;AAAA,MACJ,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,iBAA0B,OAA4D;AAC7F,QAAM,UAAkC,CAAC;AAUzC,QAAM,QAAqB,MAAM,IAAI,CAAC,UAAU;AAAA,IAC9C;AAAA,IACA,YAAY,CAAC;AAAA,IACb,UAAU;AAAA,IACV,cAAc,CAAC;AAAA,IACf,sBAAsB,CAAC;AAAA,EACzB,EAAE;AAEF,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,EAAE,MAAM,YAAY,UAAU,cAAc,qBAAqB,IAAI,MAAM,MAAM;AAEvF,UAAM,iBAAiB,CAAC,GAAG,YAAY,KAAK,KAAK;AACjD,UAAM,eAAe,WAAW,MAAM,KAAK;AAC3C,UAAM,mBAAgC,KAAK,UACvC,CAAC,GAAG,cAAc,KAAK,OAAO,IAC9B;AACJ,UAAM,2BAAwC,KAAK,kBAC/C,CAAC,GAAG,sBAAsB,KAAK,eAAe,IAC9C;AAEJ,QAAI,YAAY,IAAI,GAAG;AACrB,iBAAW,SAAS,KAAK,UAAU;AACjC,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,UAAU;AAAA,UACV,cAAc;AAAA,UACd,sBAAsB;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,UAAI,KAAK,OAAO;AACd,mBAAW,QAAQ,KAAK,OAAO;AAC7B,kBAAQ,KAAK;AAAA,YACX,YAAY;AAAA,YACZ,MAAM,eAAe,MAAM;AAAA,YAC3B,cAAc;AAAA,YACd,sBAAsB;AAAA,UACxB,CAAC;AAAA,QACH;AAAA,MACF;AAEA,UAAI,KAAK,UAAU;AACjB,mBAAW,WAAW,KAAK,UAAU;AACnC,gBAAM,kBAA+B,QAAQ,UACzC,CAAC,GAAG,kBAAkB,QAAQ,OAAO,IACrC;AACJ,gBAAM,0BAAuC,QAAQ,kBACjD,CAAC,GAAG,0BAA0B,QAAQ,eAAe,IACrD;AAEJ,qBAAW,QAAQ,QAAQ,OAAO;AAChC,oBAAQ,KAAK;AAAA,cACX,YAAY;AAAA,cACZ,MAAM,eAAe,MAAM,QAAQ,OAAO,MAAM;AAAA,cAChD,cAAc;AAAA,cACd,sBAAsB;AAAA,YACxB,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,OACA,UACA,YACyB;AACzB,QAAM,MAA+B,CAAC;AAEtC,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,WAAW,MAAM,KAAK;AAEnC,QAAI,YAAY,IAAI,GAAG;AACrB,YAAM,QAAQ,iBAAiB,KAAK,UAAU,MAAM,UAAU;AAC9D,UAAI,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AACjC,YAAI,KAAK,IAAI,IAAI;AAAA,MACnB;AAAA,IACF,WAAW,KAAK,UAAU,UAAa,KAAK,aAAa,QAAW;AAClE,YAAM,OAAgC,CAAC;AAEvC,UAAI,KAAK,UAAU,QAAW;AAC5B,mBAAW,QAAQ,KAAK,OAAO;AAC7B,gBAAM,WAAW,OAAO,MAAM;AAC9B,iBAAO,eAAe,MAAM,MAAM;AAAA,YAChC,MAAM;AA7XlB;AA8Xc,uBAAO,uEAAiB,cAAa;AAAA,YACvC;AAAA,YACA,YAAY;AAAA,UACd,CAAC;AAAA,QACH;AAAA,MACF;AAEA,UAAI,KAAK,aAAa,QAAW;AAC/B,mBAAW,OAAO,KAAK,UAAU;AAC/B,gBAAM,SAAkC,CAAC;AACzC,qBAAW,KAAK,IAAI,OAAO;AACzB,kBAAM,cAAc,OAAO,MAAM,IAAI,OAAO,MAAM;AAClD,mBAAO,eAAe,QAAQ,GAAG;AAAA,cAC/B,MAAM;AA3YpB;AA4YgB,yBAAO,uEAAiB,iBAAgB;AAAA,cAC1C;AAAA,cACA,YAAY;AAAA,YACd,CAAC;AAAA,UACH;AACA,eAAK,IAAI,IAAI,IAAI;AAAA,QACnB;AAAA,MACF;AAEA,UAAI,KAAK,IAAI,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;AAIA,SAAS,qBACP,OACA,OAC6B;AAC7B,QAAM,SAAsC,CAAC;AAE7C,MAAI,eAAe;AACnB,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,aAAa,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI;AAC5D,QAAI,UAAU,OAAW;AACzB,WAAO,KAAK,KAAK;AACjB,mBAAe,YAAY,KAAK,IAAI,MAAM,WAAW,CAAC;AAAA,EACxD;AAEA,SAAO;AACT;AAIO,SAAS,mBAGd,MAIwD;AACxD,QAAM,eAAe,iBAAiB,KAAK,KAAK;AAEhD,QAAM,YAAiC,CAAC;AACxC,aAAW,OAAO,KAAK,OAAO;AAC5B,QAAI,YAAY,GAAG,GAAG;AACpB,YAAM,kBAA+B,IAAI,UAAU,CAAC,IAAI,OAAO,IAAI,CAAC;AACpE,YAAM,0BAAuC,IAAI,kBAAkB,CAAC,IAAI,eAAe,IAAI,CAAC;AAC5F,gBAAU;AAAA,QACR,GAAG;AAAA,UACD,IAAI;AAAA,UACJ;AAAA,UACA,MAAM,IAAI;AAAA,UACV;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,WAAW,MAAM;AAC7B,UAAM,cAAc,WAAW,MAAM;AA7czC;AA8cM,YAAM,QAAmB,CAAC;AAC1B,iBAAW,OAAO,KAAK,OAAO;AAC5B,YAAI,YAAY,GAAG,GAAG;AACpB,gBAAM;AAAA,YACJ,GAAG;AAAA,cACD,IAAI;AAAA,cACJ,MAAM,IAAI;AAAA,eACV,UAAK,kBAAL;AAAA,eACA,UAAK,eAAL;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,kBAAkB,WAAW,MAAM,aAAa,YAAY,CAAC,CAAC;AAEpE,UAAM,cAAc,WAAW,MAAG;AAhetC;AAgeyC,wBAAW,KAAK,OAAO,KAAI,UAAK,kBAAL,6BAAsB;AAAA,KAAC;AAEvF,WAAO,EAAE,aAAa,iBAAiB,YAAY;AAAA,EACrD,CAAC;AAED,QAAM,WAAW,iBAAiB,KAAK,OAAO,IAAI,KAAK,UAAU;AAEjE,SAAO;AAAA,IACL,OAAO,KAAK;AAAA,IACZ;AAAA,IACA,aAAa,MAAM;AAAA,IACnB,iBAAiB,MAAM;AAAA,IACvB,aAAa,MAAM;AAAA,IACnB;AAAA,IACA,iBAAiB,OAAmC;AA9exD;AA+eM,YAAM,iBAAgB,UAAK,kBAAL;AACtB,UAAI,kBAAkB,QAAW;AAC/B,mBAAW,WAAW,MAAM,cAAc;AACxC,cAAI,QAAQ,SAAS,KAAK,CAAC,QAAQ,KAAK,CAAC,MAAM,cAAc,SAAS,CAAC,CAAC,GAAG;AACzE,mBAAO;AAAA,UACT;AAAA,QACF;AACA,mBAAW,WAAW,MAAM,sBAAsB;AAChD,cAAI,QAAQ,SAAS,KAAK,CAAC,QAAQ,MAAM,CAAC,MAAM,cAAc,SAAS,CAAC,CAAC,GAAG;AAC1E,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAEA,UAAI,MAAM,aAAa,QAAW;AAChC,cAAM,cAAa,UAAK,eAAL;AACnB,YAAI,eAAe,QAAW;AAC5B,iBAAO,WAAW,MAAM,QAAQ,KAAK;AAAA,QACvC;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,IACA,OAAO;AAAA,IACP,oBAAoB,MAAwB;AAC1C,YAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5C,aAAO,qBAAqB,KAAK,OAAO,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK;AAAA,IACzE;AAAA,EACF;AACF;",
5
5
  "names": []
6
6
  }
@@ -193,7 +193,7 @@ import { List } from "@simplysm/solid";
193
193
  | `readonly` | `boolean` | - | Read-only (click disabled, normal color) |
194
194
  | `disabled` | `boolean` | - | Disabled state (click disabled, dimmed) |
195
195
  | `selectedIcon` | `Component<IconProps>` | - | Selected state icon (shown when no nested list) |
196
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
196
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
197
197
  | `onClick` | `(e: MouseEvent) => void` | - | Click handler (called when no nested list) |
198
198
 
199
199
  **Sub-components:**
@@ -18,7 +18,7 @@ import { Tabs } from "@simplysm/solid";
18
18
  |------|------|---------|-------------|
19
19
  | `value` | `string` | - | Selected tab value |
20
20
  | `onValueChange` | `(value: string) => void` | - | Tab change callback |
21
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
21
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
22
22
  | `class` | `string` | - | Additional CSS class |
23
23
  | `style` | `JSX.CSSProperties` | - | Inline style |
24
24
 
@@ -17,7 +17,7 @@ import { Button } from "@simplysm/solid";
17
17
  |------|------|---------|-------------|
18
18
  | `theme` | `"primary" \| "info" \| "success" \| "warning" \| "danger" \| "base"` | `"base"` | Color theme |
19
19
  | `variant` | `"solid" \| "outline" \| "ghost"` | `"outline"` | Style variant |
20
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
20
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
21
21
  | `inset` | `boolean` | - | Inset style (removes border/rounded corners) |
22
22
  | `disabled` | `boolean` | - | Disabled state |
23
23
 
@@ -62,7 +62,7 @@ import { TextInput } from "@simplysm/solid";
62
62
  | `autocomplete` | `JSX.HTMLAutocomplete` | - | HTML autocomplete attribute |
63
63
  | `disabled` | `boolean` | - | Disabled state |
64
64
  | `readonly` | `boolean` | - | Read-only state |
65
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
65
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
66
66
  | `inset` | `boolean` | - | Inset style |
67
67
  | `class` | `string` | - | Additional CSS class |
68
68
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -106,7 +106,7 @@ import { NumberInput } from "@simplysm/solid";
106
106
  | `title` | `string` | - | Tooltip title |
107
107
  | `disabled` | `boolean` | - | Disabled state |
108
108
  | `readonly` | `boolean` | - | Read-only state |
109
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
109
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
110
110
  | `inset` | `boolean` | - | Inset style |
111
111
  | `class` | `string` | - | Additional CSS class |
112
112
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -158,7 +158,7 @@ import { DateOnly } from "@simplysm/core-common";
158
158
  | `title` | `string` | - | Tooltip title |
159
159
  | `disabled` | `boolean` | - | Disabled state |
160
160
  | `readonly` | `boolean` | - | Read-only state |
161
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
161
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
162
162
  | `inset` | `boolean` | - | Inset style |
163
163
  | `class` | `string` | - | Additional CSS class |
164
164
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -205,7 +205,7 @@ import { DateTime } from "@simplysm/core-common";
205
205
  | `title` | `string` | - | Tooltip title |
206
206
  | `disabled` | `boolean` | - | Disabled state |
207
207
  | `readonly` | `boolean` | - | Read-only state |
208
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
208
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
209
209
  | `inset` | `boolean` | - | Inset style |
210
210
  | `class` | `string` | - | Additional CSS class |
211
211
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -252,7 +252,7 @@ import { Time } from "@simplysm/core-common";
252
252
  | `title` | `string` | - | Tooltip title |
253
253
  | `disabled` | `boolean` | - | Disabled state |
254
254
  | `readonly` | `boolean` | - | Read-only state |
255
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
255
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
256
256
  | `inset` | `boolean` | - | Inset style |
257
257
  | `class` | `string` | - | Additional CSS class |
258
258
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -295,7 +295,7 @@ const [to, setTo] = createSignal<DateOnly>();
295
295
  | `onToChange` | `(value: DateOnly \| undefined) => void` | - | End date change callback |
296
296
  | `required` | `boolean` | - | Required field |
297
297
  | `disabled` | `boolean` | - | Disabled state |
298
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
298
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
299
299
  | `periodLabels` | `Partial<Record<DateRangePeriodType, string>>` | `{ day: "일", month: "월", range: "범위" }` | Period type labels (Korean by default) |
300
300
  | `class` | `string` | - | Additional CSS class |
301
301
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -327,7 +327,7 @@ import { Textarea } from "@simplysm/solid";
327
327
  | `minRows` | `number` | `1` | Minimum number of rows |
328
328
  | `disabled` | `boolean` | - | Disabled state |
329
329
  | `readonly` | `boolean` | - | Read-only state |
330
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
330
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
331
331
  | `inset` | `boolean` | - | Inset style |
332
332
  | `class` | `string` | - | Additional CSS class |
333
333
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -405,7 +405,7 @@ import { Select } from "@simplysm/solid";
405
405
  | `placeholder` | `string` | - | Placeholder |
406
406
  | `disabled` | `boolean` | - | Disabled state |
407
407
  | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
408
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
408
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
409
409
  | `inset` | `boolean` | - | Inset style |
410
410
  | `class` | `string` | - | Additional CSS class |
411
411
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -458,7 +458,7 @@ import { Combobox } from "@simplysm/solid";
458
458
  | `parseCustomValue` | `(text: string) => T` | - | Custom value parsing function |
459
459
  | `placeholder` | `string` | - | Placeholder |
460
460
  | `disabled` | `boolean` | - | Disabled state |
461
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
461
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
462
462
  | `inset` | `boolean` | - | Inset style |
463
463
  | `class` | `string` | - | Additional CSS class |
464
464
  | `style` | `JSX.CSSProperties` | - | Inline style |
@@ -492,7 +492,7 @@ import { Checkbox, Radio } from "@simplysm/solid";
492
492
  |------|------|---------|-------------|
493
493
  | `value` | `boolean` | `false` | Checked state |
494
494
  | `onValueChange` | `(value: boolean) => void` | - | Value change callback |
495
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
495
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
496
496
  | `disabled` | `boolean` | - | Disabled state |
497
497
  | `inset` | `boolean` | - | Inset style |
498
498
  | `inline` | `boolean` | - | Inline style |
@@ -537,7 +537,7 @@ import { CheckboxGroup, RadioGroup } from "@simplysm/solid";
537
537
  |------|------|---------|-------------|
538
538
  | `value` | `T[]` | `[]` | Selected values array |
539
539
  | `onValueChange` | `(value: T[]) => void` | - | Value change callback |
540
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
540
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
541
541
  | `disabled` | `boolean` | - | Disable all items |
542
542
  | `inline` | `boolean` | - | Inline style |
543
543
  | `inset` | `boolean` | - | Inset style |
@@ -551,7 +551,7 @@ import { CheckboxGroup, RadioGroup } from "@simplysm/solid";
551
551
  |------|------|---------|-------------|
552
552
  | `value` | `T` | - | Selected value |
553
553
  | `onValueChange` | `(value: T) => void` | - | Value change callback |
554
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
554
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
555
555
  | `disabled` | `boolean` | - | Disable all items |
556
556
  | `inline` | `boolean` | - | Inline style |
557
557
  | `inset` | `boolean` | - | Inset style |
@@ -579,6 +579,7 @@ import { ColorPicker } from "@simplysm/solid";
579
579
  |------|------|---------|-------------|
580
580
  | `value` | `string` | `"#000000"` | Color value (#RRGGBB format) |
581
581
  | `onValueChange` | `(value: string) => void` | - | Value change callback |
582
+ | `title` | `string` | - | Tooltip title |
582
583
  | `size` | `"sm" \| "lg"` | - | Size |
583
584
  | `disabled` | `boolean` | - | Disabled state |
584
585
  | `required` | `boolean` | - | Required field (error: "필수 입력 항목입니다") |
@@ -622,7 +623,7 @@ import { RichTextEditor } from "@simplysm/solid";
622
623
  | `value` | `string` | - | HTML string value |
623
624
  | `onValueChange` | `(value: string) => void` | - | Value change callback |
624
625
  | `disabled` | `boolean` | - | Disabled state |
625
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
626
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
626
627
 
627
628
  ---
628
629
 
@@ -765,7 +766,9 @@ import { Numpad } from "@simplysm/solid";
765
766
  | `useEnterButton` | `boolean` | - | Show ENT button |
766
767
  | `useMinusButton` | `boolean` | - | Show minus button |
767
768
  | `onEnterButtonClick` | `() => void` | - | ENT click callback |
768
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
769
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
770
+ | `class` | `string` | - | Additional CSS class |
771
+ | `style` | `JSX.CSSProperties` | - | Inline style |
769
772
 
770
773
  ---
771
774
 
@@ -788,4 +791,6 @@ import { StatePreset } from "@simplysm/solid";
788
791
  | `presetKey` | `string` | **(required)** | Preset storage key |
789
792
  | `value` | `T` | **(required)** | Current state value |
790
793
  | `onValueChange` | `(value: T) => void` | **(required)** | State restore callback |
791
- | `size` | `"sm" \| "lg" \| "xl"` | - | Size |
794
+ | `size` | `"xs" \| "sm" \| "lg" \| "xl"` | - | Size |
795
+ | `class` | `string` | - | Additional CSS class |
796
+ | `style` | `JSX.CSSProperties` | - | Inline style |
package/docs/hooks.md CHANGED
@@ -241,11 +241,12 @@ const structure = createAppStructure({
241
241
  permRecord: () => userPermissions(), // optional: Record<string, boolean> permission state
242
242
  });
243
243
 
244
- // structure.usableRoutes() -- Accessor<AppRoute[]> - filtered route array (pass to @solidjs/router)
245
- // structure.usableMenus() -- Accessor<AppMenu[]> - filtered menu array for Sidebar.Menu
246
- // structure.usableFlatMenus() -- Accessor<AppFlatMenu[]> - flat filtered menu list
247
- // structure.usablePerms() -- Accessor<AppPerm[]> - filtered permission tree
248
- // structure.flatPerms -- AppFlatPerm[] - all flat perm entries (static, not reactive)
244
+ // structure.allRoutes -- AppRoute[] - all routes with permCode + module info (static)
245
+ // structure.usableMenus() -- Accessor<AppMenu[]> - filtered menu array for Sidebar.Menu
246
+ // structure.usableFlatMenus() -- Accessor<AppFlatMenu[]> - flat filtered menu list
247
+ // structure.usablePerms() -- Accessor<AppPerm[]> - filtered permission tree
248
+ // structure.allFlatPerms -- AppFlatPerm[] - all flat perm entries (static)
249
+ // structure.checkRouteAccess(r) -- boolean - check if route is accessible
249
250
  ```
250
251
 
251
252
  **Routing integration with `@solidjs/router`:**
@@ -253,7 +254,6 @@ const structure = createAppStructure({
253
254
  ```tsx
254
255
  import { render } from "solid-js/web";
255
256
  import { HashRouter, Navigate, Route } from "@solidjs/router";
256
- import { For } from "solid-js";
257
257
  import { appStructure } from "./appStructure";
258
258
 
259
259
  render(
@@ -262,9 +262,17 @@ render(
262
262
  <Route path="/" component={App}>
263
263
  <Route path="/home" component={Home}>
264
264
  <Route path="/" component={() => <Navigate href="/home/main" />} />
265
- <For each={appStructure.usableRoutes()}>
266
- {(r) => <Route path={r.path} component={r.component} />}
267
- </For>
265
+ {appStructure.allRoutes.map((r) => (
266
+ <Route
267
+ path={r.path}
268
+ component={() => {
269
+ if (!appStructure.checkRouteAccess(r)) {
270
+ return <Navigate href="/login" />;
271
+ }
272
+ return <r.component />;
273
+ }}
274
+ />
275
+ ))}
268
276
  <Route path="/*" component={NotFoundPage} />
269
277
  </Route>
270
278
  <Route path="/" component={() => <Navigate href="/home" />} />
@@ -275,25 +283,29 @@ render(
275
283
  );
276
284
  ```
277
285
 
278
- Each route object in `structure.usableRoutes()` has `path` (derived from nested `code` values) and `component` properties, ready to pass directly to `<Route>`. Note that `usableRoutes` is a reactive accessor it re-evaluates when `usableModules` or `permRecord` signals change.
286
+ `allRoutes` is a static (non-reactive) array containing all routes with `permCode` and module chain information. Use `checkRouteAccess(route)` to reactively verify access based on `permRecord` and `usableModules` signals.
279
287
 
280
288
  **AppStructure return type:**
281
289
 
282
290
  ```typescript
283
291
  interface AppStructure<TModule> {
284
292
  items: AppStructureItem<TModule>[];
285
- usableRoutes: Accessor<AppRoute[]>; // reactive, filtered by modules + permRecord
286
- usableMenus: Accessor<AppMenu[]>; // reactive, filtered by modules + permRecord
287
- usableFlatMenus: Accessor<AppFlatMenu[]>; // reactive, flat version of usableMenus
288
- usablePerms: Accessor<AppPerm<TModule>[]>; // reactive, filtered permission tree
289
- flatPerms: AppFlatPerm<TModule>[]; // static, all perm entries (not reactive)
293
+ allRoutes: AppRoute<TModule>[]; // static, all routes with perm/module info
294
+ usableMenus: Accessor<AppMenu[]>; // reactive, filtered by modules + permRecord
295
+ usableFlatMenus: Accessor<AppFlatMenu[]>; // reactive, flat version of usableMenus
296
+ usablePerms: Accessor<AppPerm<TModule>[]>; // reactive, filtered permission tree
297
+ allFlatPerms: AppFlatPerm<TModule>[]; // static, all perm entries (not reactive)
298
+ checkRouteAccess(route: AppRoute<TModule>): boolean; // reactive access check
290
299
  getTitleChainByHref(href: string): string[];
291
- perms: InferPerms<TItems>; // typed permission accessor (getter-based reactive booleans)
300
+ perms: InferPerms<TItems>; // typed permission accessor (getter-based reactive booleans)
292
301
  }
293
302
 
294
- interface AppRoute {
303
+ interface AppRoute<TModule = string> {
295
304
  path: string;
296
305
  component: Component;
306
+ permCode?: string;
307
+ modulesChain: TModule[][];
308
+ requiredModulesChain: TModule[][];
297
309
  }
298
310
 
299
311
  interface AppMenu {
@@ -320,6 +332,7 @@ interface AppFlatPerm<TModule = string> {
320
332
  titleChain: string[];
321
333
  code: string;
322
334
  modulesChain: TModule[][];
335
+ requiredModulesChain: TModule[][];
323
336
  }
324
337
  ```
325
338
 
package/docs/layout.md CHANGED
@@ -273,7 +273,7 @@ const handleDrop = (info: KanbanDropInfo) => {
273
273
  | `selectedValues` | `unknown[]` | - | Selected card values |
274
274
  | `onSelectedValuesChange` | `(values: unknown[]) => void` | - | Selection change callback |
275
275
 
276
- `KanbanDropInfo`: `{ sourceValue: unknown; targetLaneValue: unknown; targetCardValue: unknown | undefined; position: "before" | "after" | undefined }`
276
+ `KanbanDropInfo`: `{ sourceValue?: unknown; targetLaneValue?: unknown; targetCardValue?: unknown; position?: "before" | "after" }`
277
277
 
278
278
  **Kanban.Lane Props:**
279
279
 
package/docs/styling.md CHANGED
@@ -20,10 +20,12 @@
20
20
  | Class | Description |
21
21
  |-------|-------------|
22
22
  | `h-field` / `size-field` | Default field height (based on `py-1`) |
23
+ | `h-field-xs` / `size-field-xs` | Extra-small field height (based on `py-0`) |
23
24
  | `h-field-sm` / `size-field-sm` | Small field height (based on `py-0.5`) |
24
25
  | `h-field-lg` / `size-field-lg` | Large field height (based on `py-2`) |
25
26
  | `h-field-xl` / `size-field-xl` | Extra-large field height (based on `py-3`) |
26
27
  | `h-field-inset` / `size-field-inset` | Inset field height (excludes border) |
28
+ | `h-field-inset-xs` / `size-field-inset-xs` | Extra-small inset field height |
27
29
  | `h-field-inset-sm` / `size-field-inset-sm` | Small inset field height |
28
30
  | `h-field-inset-lg` / `size-field-inset-lg` | Large inset field height |
29
31
  | `h-field-inset-xl` / `size-field-inset-xl` | Extra-large inset field height |
@@ -76,7 +78,7 @@ const className = twMerge(baseClass, props.class);
76
78
 
77
79
  ```typescript
78
80
  import {
79
- type ComponentSize, // "sm" | "lg" | "xl"
81
+ type ComponentSize, // "xs" | "sm" | "lg" | "xl"
80
82
  type ComponentSizeCompact, // "sm" | "lg" (used by ColorPicker, Progress)
81
83
  type SemanticTheme, // "primary" | "info" | "success" | "warning" | "danger" | "base"
82
84
  borderDefault, // Tailwind classes for default border color
@@ -86,6 +88,7 @@ import {
86
88
  textMuted, // Tailwind classes for muted text color
87
89
  textPlaceholder, // Tailwind classes for placeholder text color
88
90
  disabledOpacity, // Tailwind classes for disabled state opacity
91
+ paddingXs, // Tailwind classes for extra-small padding (px-1 py-0)
89
92
  paddingSm, // Tailwind classes for small padding (px-1.5 py-0.5)
90
93
  paddingLg, // Tailwind classes for large padding (px-3 py-2)
91
94
  paddingXl, // Tailwind classes for extra-large padding (px-4 py-3)
@@ -110,7 +113,7 @@ import {
110
113
 
111
114
  ```typescript
112
115
  import {
113
- type FieldSize, // "sm" | "lg" | "xl"
116
+ type FieldSize, // "xs" | "sm" | "lg" | "xl"
114
117
  fieldBaseClass, // Base wrapper classes (inline-flex, field surface, h-field)
115
118
  fieldSizeClasses, // Size variant classes per FieldSize
116
119
  fieldInsetClass, // Inset mode wrapper classes
@@ -140,7 +143,7 @@ import {
140
143
 
141
144
  ```typescript
142
145
  import {
143
- type CheckboxSize, // "sm" | "lg" | "xl"
146
+ type CheckboxSize, // "xs" | "sm" | "lg" | "xl"
144
147
  checkboxBaseClass, // Base wrapper classes
145
148
  indicatorBaseClass, // Base indicator (box) classes
146
149
  checkedClass, // Checked state classes (primary color)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/solid",
3
- "version": "13.0.48",
3
+ "version": "13.0.50",
4
4
  "description": "심플리즘 패키지 - SolidJS 라이브러리",
5
5
  "author": "김석래",
6
6
  "license": "Apache-2.0",
@@ -49,8 +49,8 @@
49
49
  "solid-tiptap": "^0.8.0",
50
50
  "tailwind-merge": "^3.5.0",
51
51
  "tailwindcss": "^3.4.19",
52
- "@simplysm/core-common": "13.0.48",
53
- "@simplysm/core-browser": "13.0.48"
52
+ "@simplysm/core-common": "13.0.50",
53
+ "@simplysm/core-browser": "13.0.50"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@solidjs/testing-library": "^0.8.10"
@@ -58,11 +58,15 @@ export interface AppFlatPerm<TModule = string> {
58
58
  titleChain: string[];
59
59
  code: string;
60
60
  modulesChain: TModule[][];
61
+ requiredModulesChain: TModule[][];
61
62
  }
62
63
 
63
- export interface AppRoute {
64
+ export interface AppRoute<TModule = string> {
64
65
  path: string;
65
66
  component: Component;
67
+ permCode?: string;
68
+ modulesChain: TModule[][];
69
+ requiredModulesChain: TModule[][];
66
70
  }
67
71
 
68
72
  export interface AppFlatMenu {
@@ -72,11 +76,12 @@ export interface AppFlatMenu {
72
76
 
73
77
  export interface AppStructure<TModule> {
74
78
  items: AppStructureItem<TModule>[];
75
- usableRoutes: Accessor<AppRoute[]>;
79
+ allRoutes: AppRoute<TModule>[];
76
80
  usableMenus: Accessor<AppMenu[]>;
77
81
  usableFlatMenus: Accessor<AppFlatMenu[]>;
78
82
  usablePerms: Accessor<AppPerm<TModule>[]>;
79
- flatPerms: AppFlatPerm<TModule>[];
83
+ allFlatPerms: AppFlatPerm<TModule>[];
84
+ checkRouteAccess(route: AppRoute<TModule>): boolean;
80
85
  getTitleChainByHref(href: string): string[];
81
86
  }
82
87
 
@@ -141,29 +146,44 @@ function checkModules<TModule>(
141
146
 
142
147
  // ── Routes ──
143
148
 
144
- function buildUsableRoutes<TModule>(
149
+ function buildAllRoutes<TModule>(
145
150
  items: AppStructureItem<TModule>[],
146
151
  routeBasePath: string,
147
152
  permBasePath: string,
148
- usableModules?: TModule[],
149
- permRecord?: Record<string, boolean>,
150
- ): AppRoute[] {
151
- const result: AppRoute[] = [];
153
+ modulesChain: TModule[][],
154
+ requiredModulesChain: TModule[][],
155
+ ): AppRoute<TModule>[] {
156
+ const result: AppRoute<TModule>[] = [];
152
157
 
153
158
  for (const item of items) {
154
- if (!checkModules(item.modules, item.requiredModules, usableModules)) continue;
159
+ const currModulesChain: TModule[][] = item.modules
160
+ ? [...modulesChain, item.modules]
161
+ : modulesChain;
162
+ const currRequiredModulesChain: TModule[][] = item.requiredModules
163
+ ? [...requiredModulesChain, item.requiredModules]
164
+ : requiredModulesChain;
155
165
 
156
166
  const routePath = routeBasePath + "/" + item.code;
157
167
  const permPath = permBasePath + "/" + item.code;
158
168
 
159
169
  if (isGroupItem(item)) {
160
170
  result.push(
161
- ...buildUsableRoutes(item.children, routePath, permPath, usableModules, permRecord),
171
+ ...buildAllRoutes(
172
+ item.children,
173
+ routePath,
174
+ permPath,
175
+ currModulesChain,
176
+ currRequiredModulesChain,
177
+ ),
162
178
  );
163
179
  } else if (item.component !== undefined) {
164
- if (permRecord !== undefined && item.perms?.includes("use") && !permRecord[permPath + "/use"])
165
- continue;
166
- result.push({ path: routePath, component: item.component });
180
+ result.push({
181
+ path: routePath,
182
+ component: item.component,
183
+ permCode: item.perms?.includes("use") ? permPath + "/use" : undefined,
184
+ modulesChain: currModulesChain,
185
+ requiredModulesChain: currRequiredModulesChain,
186
+ });
167
187
  }
168
188
  }
169
189
 
@@ -267,6 +287,7 @@ function collectFlatPerms<TModule>(items: AppStructureItem<TModule>[]): AppFlatP
267
287
  titleChain: string[];
268
288
  codePath: string;
269
289
  modulesChain: TModule[][];
290
+ requiredModulesChain: TModule[][];
270
291
  }
271
292
 
272
293
  const queue: QueueItem[] = items.map((item) => ({
@@ -274,16 +295,20 @@ function collectFlatPerms<TModule>(items: AppStructureItem<TModule>[]): AppFlatP
274
295
  titleChain: [],
275
296
  codePath: "",
276
297
  modulesChain: [],
298
+ requiredModulesChain: [],
277
299
  }));
278
300
 
279
301
  while (queue.length > 0) {
280
- const { item, titleChain, codePath, modulesChain } = queue.shift()!;
302
+ const { item, titleChain, codePath, modulesChain, requiredModulesChain } = queue.shift()!;
281
303
 
282
304
  const currTitleChain = [...titleChain, item.title];
283
305
  const currCodePath = codePath + "/" + item.code;
284
306
  const currModulesChain: TModule[][] = item.modules
285
307
  ? [...modulesChain, item.modules]
286
308
  : modulesChain;
309
+ const currRequiredModulesChain: TModule[][] = item.requiredModules
310
+ ? [...requiredModulesChain, item.requiredModules]
311
+ : requiredModulesChain;
287
312
 
288
313
  if (isGroupItem(item)) {
289
314
  for (const child of item.children) {
@@ -292,6 +317,7 @@ function collectFlatPerms<TModule>(items: AppStructureItem<TModule>[]): AppFlatP
292
317
  titleChain: currTitleChain,
293
318
  codePath: currCodePath,
294
319
  modulesChain: currModulesChain,
320
+ requiredModulesChain: currRequiredModulesChain,
295
321
  });
296
322
  }
297
323
  } else {
@@ -301,6 +327,7 @@ function collectFlatPerms<TModule>(items: AppStructureItem<TModule>[]): AppFlatP
301
327
  titleChain: currTitleChain,
302
328
  code: currCodePath + "/" + perm,
303
329
  modulesChain: currModulesChain,
330
+ requiredModulesChain: currRequiredModulesChain,
304
331
  });
305
332
  }
306
333
  }
@@ -310,12 +337,16 @@ function collectFlatPerms<TModule>(items: AppStructureItem<TModule>[]): AppFlatP
310
337
  const subModulesChain: TModule[][] = subPerm.modules
311
338
  ? [...currModulesChain, subPerm.modules]
312
339
  : currModulesChain;
340
+ const subRequiredModulesChain: TModule[][] = subPerm.requiredModules
341
+ ? [...currRequiredModulesChain, subPerm.requiredModules]
342
+ : currRequiredModulesChain;
313
343
 
314
344
  for (const perm of subPerm.perms) {
315
345
  results.push({
316
346
  titleChain: currTitleChain,
317
347
  code: currCodePath + "/" + subPerm.code + "/" + perm,
318
348
  modulesChain: subModulesChain,
349
+ requiredModulesChain: subRequiredModulesChain,
319
350
  });
320
351
  }
321
352
  }
@@ -408,27 +439,26 @@ export function createAppStructure<
408
439
  usableModules?: Accessor<TModule[] | undefined>;
409
440
  permRecord?: Accessor<Record<string, boolean> | undefined>;
410
441
  }): AppStructure<TModule> & { perms: InferPerms<TItems> } {
411
- const flatPerms = collectFlatPerms(opts.items);
442
+ const allFlatPerms = collectFlatPerms(opts.items);
443
+
444
+ const allRoutes: AppRoute<TModule>[] = [];
445
+ for (const top of opts.items) {
446
+ if (isGroupItem(top)) {
447
+ const topModulesChain: TModule[][] = top.modules ? [top.modules] : [];
448
+ const topRequiredModulesChain: TModule[][] = top.requiredModules ? [top.requiredModules] : [];
449
+ allRoutes.push(
450
+ ...buildAllRoutes(
451
+ top.children,
452
+ "",
453
+ "/" + top.code,
454
+ topModulesChain,
455
+ topRequiredModulesChain,
456
+ ),
457
+ );
458
+ }
459
+ }
412
460
 
413
461
  const memos = createRoot(() => {
414
- const usableRoutes = createMemo(() => {
415
- const routes: AppRoute[] = [];
416
- for (const top of opts.items) {
417
- if (isGroupItem(top)) {
418
- routes.push(
419
- ...buildUsableRoutes(
420
- top.children,
421
- "",
422
- "/" + top.code,
423
- opts.usableModules?.(),
424
- opts.permRecord?.(),
425
- ),
426
- );
427
- }
428
- }
429
- return routes;
430
- });
431
-
432
462
  const usableMenus = createMemo(() => {
433
463
  const menus: AppMenu[] = [];
434
464
  for (const top of opts.items) {
@@ -450,18 +480,42 @@ export function createAppStructure<
450
480
 
451
481
  const usablePerms = createMemo(() => buildPerms(opts.items, "", opts.usableModules?.()));
452
482
 
453
- return { usableRoutes, usableMenus, usableFlatMenus, usablePerms };
483
+ return { usableMenus, usableFlatMenus, usablePerms };
454
484
  });
455
485
 
456
486
  const permsObj = buildPermsObject(opts.items, "", opts.permRecord);
457
487
 
458
488
  return {
459
489
  items: opts.items,
460
- usableRoutes: memos.usableRoutes,
490
+ allRoutes,
461
491
  usableMenus: memos.usableMenus,
462
492
  usableFlatMenus: memos.usableFlatMenus,
463
493
  usablePerms: memos.usablePerms,
464
- flatPerms,
494
+ allFlatPerms,
495
+ checkRouteAccess(route: AppRoute<TModule>): boolean {
496
+ const usableModules = opts.usableModules?.();
497
+ if (usableModules !== undefined) {
498
+ for (const modules of route.modulesChain) {
499
+ if (modules.length > 0 && !modules.some((m) => usableModules.includes(m))) {
500
+ return false;
501
+ }
502
+ }
503
+ for (const modules of route.requiredModulesChain) {
504
+ if (modules.length > 0 && !modules.every((m) => usableModules.includes(m))) {
505
+ return false;
506
+ }
507
+ }
508
+ }
509
+
510
+ if (route.permCode !== undefined) {
511
+ const permRecord = opts.permRecord?.();
512
+ if (permRecord !== undefined) {
513
+ return permRecord[route.permCode] ?? false;
514
+ }
515
+ }
516
+
517
+ return true;
518
+ },
465
519
  perms: permsObj as InferPerms<TItems>,
466
520
  getTitleChainByHref(href: string): string[] {
467
521
  const codes = href.split("/").filter(Boolean);