@asteby/metacore-runtime-react 30.0.1 → 30.0.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.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/permissions-manager.d.ts +22 -0
- package/dist/permissions-manager.d.ts.map +1 -1
- package/dist/permissions-manager.js +56 -7
- package/package.json +4 -4
- package/src/__tests__/permissions-manager.test.tsx +14 -0
- package/src/index.ts +1 -0
- package/src/permissions-manager.tsx +172 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 30.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 05d1cef: Permisos: labels de acciones sin truncate (wrap) y grid a 2 columnas; soporta description en PermissionActionDef.
|
|
8
|
+
|
|
9
|
+
## 30.0.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- a5ca1a8: Permisos: agrupar acciones en secciones desplegables (action.group)
|
|
14
|
+
|
|
3
15
|
## 30.0.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export * from './slot';
|
|
|
23
23
|
export * from './capability-gate';
|
|
24
24
|
export { PermissionsProvider, useCan, usePermissionsActive, makeCan, capabilityForActionKey, modelCapability, gateTableMetadata, resolveRowActions, type CanFn, type PermissionsProviderProps, } from './permissions-context';
|
|
25
25
|
export { useDynamicRowActions, type UseDynamicRowActionsParams, type DynamicRowActions, } from './dynamic-row-actions';
|
|
26
|
-
export { PermissionsManager, moduleActionCapability, moduleCapabilities, grantedCountForModule, capabilitySetsEqual, defaultActionIcon, normalizeCatalogGroups, flattenGroups, filterModuleGroups, type PermissionsManagerProps, type PermissionsCatalog, type GroupedPermissionsCatalog, type FlatPermissionsCatalog, type ModuleGroup, type PermissionModuleDef, type PermissionActionDef, type GeneralPermissionDef, type RoleDef, type RoleInput, } from './permissions-manager';
|
|
26
|
+
export { PermissionsManager, moduleActionCapability, moduleCapabilities, grantedCountForModule, capabilitySetsEqual, defaultActionIcon, normalizeCatalogGroups, flattenGroups, filterModuleGroups, groupModuleActions, type PermissionsManagerProps, type PermissionsCatalog, type GroupedPermissionsCatalog, type FlatPermissionsCatalog, type ModuleGroup, type PermissionModuleDef, type PermissionActionDef, type GeneralPermissionDef, type RoleDef, type RoleInput, } from './permissions-manager';
|
|
27
27
|
export * from './org-runtime-context';
|
|
28
28
|
export * from './org-runtime-provider';
|
|
29
29
|
export * from './navigation-builder';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ export * from './slot';
|
|
|
28
28
|
export * from './capability-gate';
|
|
29
29
|
export { PermissionsProvider, useCan, usePermissionsActive, makeCan, capabilityForActionKey, modelCapability, gateTableMetadata, resolveRowActions, } from './permissions-context';
|
|
30
30
|
export { useDynamicRowActions, } from './dynamic-row-actions';
|
|
31
|
-
export { PermissionsManager, moduleActionCapability, moduleCapabilities, grantedCountForModule, capabilitySetsEqual, defaultActionIcon, normalizeCatalogGroups, flattenGroups, filterModuleGroups, } from './permissions-manager';
|
|
31
|
+
export { PermissionsManager, moduleActionCapability, moduleCapabilities, grantedCountForModule, capabilitySetsEqual, defaultActionIcon, normalizeCatalogGroups, flattenGroups, filterModuleGroups, groupModuleActions, } from './permissions-manager';
|
|
32
32
|
export * from './org-runtime-context';
|
|
33
33
|
export * from './org-runtime-provider';
|
|
34
34
|
export * from './navigation-builder';
|
|
@@ -4,6 +4,11 @@ export interface PermissionActionDef {
|
|
|
4
4
|
key: string;
|
|
5
5
|
/** Localized label ("Listar", "Pagar", "Acceder"). */
|
|
6
6
|
label: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional secondary line under the label (e.g. action name when the label
|
|
9
|
+
* is the module — used by screen → API shortcut checkboxes).
|
|
10
|
+
*/
|
|
11
|
+
description?: string;
|
|
7
12
|
/** Lucide icon name from the manifest action (optional). */
|
|
8
13
|
icon?: string;
|
|
9
14
|
/**
|
|
@@ -20,6 +25,12 @@ export interface PermissionActionDef {
|
|
|
20
25
|
* shortcuts without inventing `screen….product.index`.
|
|
21
26
|
*/
|
|
22
27
|
capability?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Optional section title for the action grid (e.g. "Catálogo", "Ventas").
|
|
30
|
+
* When any action on a module sets `group`, the right-hand panel renders
|
|
31
|
+
* collapsible sections instead of one flat checkbox grid.
|
|
32
|
+
*/
|
|
33
|
+
group?: string;
|
|
23
34
|
}
|
|
24
35
|
export interface PermissionModuleDef {
|
|
25
36
|
/**
|
|
@@ -109,6 +120,17 @@ export interface PermissionsManagerProps {
|
|
|
109
120
|
export declare function moduleActionCapability(moduleKey: string, actionKey: string, capability?: string): string;
|
|
110
121
|
/** All capabilities of one module. */
|
|
111
122
|
export declare function moduleCapabilities(module: PermissionModuleDef): string[];
|
|
123
|
+
export interface ActionGroupSection {
|
|
124
|
+
/** Empty string = ungrouped actions rendered above the collapsibles. */
|
|
125
|
+
title: string;
|
|
126
|
+
actions: PermissionActionDef[];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Split a module's actions into an optional ungrouped prefix + named sections
|
|
130
|
+
* (first-seen order of `action.group`). Modules without any `group` yield a
|
|
131
|
+
* single untitled section (flat grid, backward compatible).
|
|
132
|
+
*/
|
|
133
|
+
export declare function groupModuleActions(actions: PermissionActionDef[]): ActionGroupSection[];
|
|
112
134
|
/** How many of the module's capabilities are in the granted set. */
|
|
113
135
|
export declare function grantedCountForModule(granted: ReadonlySet<string>, module: PermissionModuleDef): number;
|
|
114
136
|
export declare function capabilitySetsEqual(a: ReadonlySet<string>, b: ReadonlySet<string>): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions-manager.d.ts","sourceRoot":"","sources":["../src/permissions-manager.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"permissions-manager.d.ts","sourceRoot":"","sources":["../src/permissions-manager.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA6D9B,MAAM,WAAW,mBAAmB;IAChC,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAA;IACX,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,MAAM,CAAA;IAC3D;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAChC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAA;IACX,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAA;IACb,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gEAAgE;IAChE,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;IACzB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,mBAAmB,EAAE,CAAA;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,mBAAmB,EAAE,CAAA;CACjC;AAED,MAAM,WAAW,oBAAoB;IACjC,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,yBAAyB;IACtC,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,OAAO,EAAE,oBAAoB,EAAE,CAAA;CAClC;AAED,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,mBAAmB,EAAE,CAAA;IAC9B,OAAO,EAAE,oBAAoB,EAAE,CAAA;CAClC;AAED,MAAM,MAAM,kBAAkB,GAAG,yBAAyB,GAAG,sBAAsB,CAAA;AAEnF,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,uBAAuB;IACpC,0EAA0E;IAC1E,WAAW,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC9C,mCAAmC;IACnC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IACnC,0DAA0D;IAC1D,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAC1D,0DAA0D;IAC1D,mBAAmB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9E,2DAA2D;IAC3D,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IAC1D,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IAC1E,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACrB;AAMD;;eAEe;AACf,wBAAgB,sBAAsB,CAClC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GACpB,MAAM,CAGR;AAED,sCAAsC;AACtC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,EAAE,CAIxE;AAED,MAAM,WAAW,kBAAkB;IAC/B,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,mBAAmB,EAAE,CAAA;CACjC;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,kBAAkB,EAAE,CAwBvF;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,CACjC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,EAC5B,MAAM,EAAE,mBAAmB,GAC5B,MAAM,CAER;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAI3F;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAsB1E;AAoCD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,EAAE,CA0BjF;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,mBAAmB,EAAE,CAE1E;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAYtF;AAmHD,wBAAgB,kBAAkB,CAAC,EAC/B,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,UAAU,EACV,UAAU,EACV,KAA0B,EAC1B,SAAS,GACZ,EAAE,uBAAuB,qBAguBzB"}
|
|
@@ -25,10 +25,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
25
25
|
// state is tracked against the loaded baseline and surfaced next to the
|
|
26
26
|
// save button.
|
|
27
27
|
import * as React from 'react';
|
|
28
|
-
import { Check, ChevronsUpDown, CheckCheck, Eraser, Pencil, Plus, Save, Shield, Trash2, } from 'lucide-react';
|
|
28
|
+
import { Check, ChevronsUpDown, CheckCheck, ChevronDown, Eraser, Pencil, Plus, Save, Shield, Trash2, } from 'lucide-react';
|
|
29
29
|
import { toast } from 'sonner';
|
|
30
30
|
import { cn } from '@asteby/metacore-ui/lib';
|
|
31
|
-
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Checkbox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Popover, PopoverContent, PopoverTrigger, Separator, Skeleton, } from '@asteby/metacore-ui/primitives';
|
|
31
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Checkbox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Popover, PopoverContent, PopoverTrigger, Separator, Skeleton, Collapsible, CollapsibleContent, CollapsibleTrigger, } from '@asteby/metacore-ui/primitives';
|
|
32
32
|
import { DynamicIcon } from './dynamic-icon';
|
|
33
33
|
// ---------------------------------------------------------------------------
|
|
34
34
|
// Pure helpers (exported for hosts/tests)
|
|
@@ -45,6 +45,37 @@ export function moduleActionCapability(moduleKey, actionKey, capability) {
|
|
|
45
45
|
export function moduleCapabilities(module) {
|
|
46
46
|
return module.actions.map((a) => moduleActionCapability(module.key, a.key, a.capability));
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Split a module's actions into an optional ungrouped prefix + named sections
|
|
50
|
+
* (first-seen order of `action.group`). Modules without any `group` yield a
|
|
51
|
+
* single untitled section (flat grid, backward compatible).
|
|
52
|
+
*/
|
|
53
|
+
export function groupModuleActions(actions) {
|
|
54
|
+
const ungrouped = [];
|
|
55
|
+
const byTitle = new Map();
|
|
56
|
+
const order = [];
|
|
57
|
+
for (const action of actions) {
|
|
58
|
+
const title = (action.group ?? '').trim();
|
|
59
|
+
if (!title) {
|
|
60
|
+
ungrouped.push(action);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
let list = byTitle.get(title);
|
|
64
|
+
if (!list) {
|
|
65
|
+
list = [];
|
|
66
|
+
byTitle.set(title, list);
|
|
67
|
+
order.push(title);
|
|
68
|
+
}
|
|
69
|
+
list.push(action);
|
|
70
|
+
}
|
|
71
|
+
const out = [];
|
|
72
|
+
if (ungrouped.length > 0)
|
|
73
|
+
out.push({ title: '', actions: ungrouped });
|
|
74
|
+
for (const title of order) {
|
|
75
|
+
out.push({ title, actions: byTitle.get(title) });
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
48
79
|
/** How many of the module's capabilities are in the granted set. */
|
|
49
80
|
export function grantedCountForModule(granted, module) {
|
|
50
81
|
return moduleCapabilities(module).filter((c) => granted.has(c)).length;
|
|
@@ -179,7 +210,7 @@ function CapabilityCheck({ checked, disabled, onToggle, icon, label, description
|
|
|
179
210
|
e.preventDefault();
|
|
180
211
|
onToggle();
|
|
181
212
|
}
|
|
182
|
-
}, className: cn('flex items-start gap-2.5 rounded-md border border-border/60 bg-card px-3 py-2.5 text-sm transition-colors', disabled ? 'opacity-50' : 'cursor-pointer hover:bg-muted/40', checked && 'border-primary/40 bg-primary/5'), children: [_jsx(Checkbox, { checked: checked, "aria-hidden": "true", tabIndex: -1, className: "pointer-events-none mt-0.5 shrink-0" }), icon && (_jsx(DynamicIcon, { name: icon, className: "mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" })), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block
|
|
213
|
+
}, className: cn('flex items-start gap-2.5 rounded-md border border-border/60 bg-card px-3 py-2.5 text-sm transition-colors', disabled ? 'opacity-50' : 'cursor-pointer hover:bg-muted/40', checked && 'border-primary/40 bg-primary/5'), children: [_jsx(Checkbox, { checked: checked, "aria-hidden": "true", tabIndex: -1, className: "pointer-events-none mt-0.5 shrink-0" }), icon && (_jsx(DynamicIcon, { name: icon, className: "mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" })), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block break-words font-medium leading-snug text-foreground", children: label }), description && (_jsx("span", { className: "mt-0.5 block break-words text-xs leading-snug text-muted-foreground", children: description }))] })] }));
|
|
183
214
|
}
|
|
184
215
|
/** One clickable module row in the flat list (mirrors a sidebar item). */
|
|
185
216
|
function ModuleRow({ module, active, granted, total, onSelect, }) {
|
|
@@ -450,10 +481,7 @@ export function PermissionsManager({ loadModules, loadRoles, loadRolePermissions
|
|
|
450
481
|
0 && (_jsxs(Badge, { variant: "secondary", className: "ml-auto shrink-0 tabular-nums", children: [grantedCountForModule(draft, mod), "/", mod.actions.length] })), mod.key === activeModuleKey && (_jsx(Check, { className: "ml-2 h-4 w-4 shrink-0" }))] }, mod.key))) }, group.title || `__untitled_${gi}`)))] })] }) })] }) })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { className: "flex flex-wrap items-start justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [activeModule && (_jsx(DynamicIcon, { name: activeModule.icon ||
|
|
451
482
|
(activeModule.kind === 'screen' ? 'Eye' : 'Square'), className: "h-4 w-4 shrink-0 text-primary" })), _jsx("span", { className: "truncate", children: activeModule ? activeModule.label : 'Acciones permitidas' })] }), _jsx(CardDescription, { children: activeModule
|
|
452
483
|
? `${activeModuleGroupTitle || 'Sistema'} · configura las acciones permitidas`
|
|
453
|
-
: 'Configura los permisos del módulo seleccionado.' })] }), activeRole && activeModule && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Badge, { variant: "secondary", className: "tabular-nums", children: [moduleGranted, "/", moduleTotal] }), _jsxs(Button, { variant: "outline", size: "sm", className: "h-8", disabled: checksDisabled || moduleGranted === moduleTotal, onClick: () => setModuleAll(true), children: [_jsx(CheckCheck, { className: "mr-1.5 h-3.5 w-3.5" }), " Marcar todo"] }), _jsxs(Button, { variant: "outline", size: "sm", className: "h-8", disabled: checksDisabled || moduleGranted === 0, onClick: () => setModuleAll(false), children: [_jsx(Eraser, { className: "mr-1.5 h-3.5 w-3.5" }), " Limpiar"] })] }))] }) }), _jsx(CardContent, { children: !activeRole ? (_jsx(EmptyHint, { text: "Selecciona un rol para configurar sus permisos." })) : loadingPerms ? (_jsx("div", { className: "grid gap-2 sm:grid-cols-2
|
|
454
|
-
const cap = moduleActionCapability(activeModule.key, action.key, action.capability);
|
|
455
|
-
return (_jsx(CapabilityCheck, { checked: draft?.has(cap) ?? false, disabled: checksDisabled, onToggle: () => toggleCapability(cap), icon: action.icon || defaultActionIcon(action.key, action.kind), label: action.label }, action.capability ?? action.key));
|
|
456
|
-
}) })) })] })] }), _jsx(AlertDialog, { open: pendingRoleId !== null, onOpenChange: (open) => !open && setPendingRoleId(null), children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Cambios sin guardar" }), _jsx(AlertDialogDescription, { children: "Tienes cambios sin guardar en este rol. Si cambias de rol se descartar\u00E1n." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Cancelar" }), _jsx(AlertDialogAction, { onClick: () => {
|
|
484
|
+
: 'Configura los permisos del módulo seleccionado.' })] }), activeRole && activeModule && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Badge, { variant: "secondary", className: "tabular-nums", children: [moduleGranted, "/", moduleTotal] }), _jsxs(Button, { variant: "outline", size: "sm", className: "h-8", disabled: checksDisabled || moduleGranted === moduleTotal, onClick: () => setModuleAll(true), children: [_jsx(CheckCheck, { className: "mr-1.5 h-3.5 w-3.5" }), " Marcar todo"] }), _jsxs(Button, { variant: "outline", size: "sm", className: "h-8", disabled: checksDisabled || moduleGranted === 0, onClick: () => setModuleAll(false), children: [_jsx(Eraser, { className: "mr-1.5 h-3.5 w-3.5" }), " Limpiar"] })] }))] }) }), _jsx(CardContent, { children: !activeRole ? (_jsx(EmptyHint, { text: "Selecciona un rol para configurar sus permisos." })) : loadingPerms ? (_jsx("div", { className: "grid gap-2 sm:grid-cols-2", children: Array.from({ length: 6 }).map((_, i) => (_jsx(Skeleton, { className: "h-14 w-full" }, i))) })) : !activeModule ? (_jsx(EmptyHint, { text: "Selecciona un m\u00F3dulo de la lista para ver sus acciones." })) : (_jsx(ModuleActionsPanel, { module: activeModule, draft: draft, checksDisabled: checksDisabled, onToggle: toggleCapability })) })] })] }), _jsx(AlertDialog, { open: pendingRoleId !== null, onOpenChange: (open) => !open && setPendingRoleId(null), children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Cambios sin guardar" }), _jsx(AlertDialogDescription, { children: "Tienes cambios sin guardar en este rol. Si cambias de rol se descartar\u00E1n." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Cancelar" }), _jsx(AlertDialogAction, { onClick: () => {
|
|
457
485
|
setActiveRoleId(pendingRoleId);
|
|
458
486
|
setPendingRoleId(null);
|
|
459
487
|
}, children: "Descartar y cambiar" })] })] }) }), _jsx(Dialog, { open: roleDialog.open, onOpenChange: (open) => setRoleDialog((d) => ({ ...d, open })), children: _jsxs(DialogContent, { className: "sm:max-w-md", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: roleDialog.mode === 'create' ? 'Nuevo rol' : 'Editar rol' }) }), _jsxs("div", { className: "flex flex-col gap-4 py-2", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { htmlFor: "pm-role-name", children: "Nombre del rol" }), _jsx(Input, { id: "pm-role-name", value: roleDialog.label, placeholder: "Ej. Cajero", onChange: (e) => setRoleDialog((d) => ({ ...d, label: e.target.value })) })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Label, { children: "Color" }), _jsx("div", { className: "flex flex-wrap gap-2", children: ROLE_COLORS.map((c) => (_jsx("button", { type: "button", "aria-label": `Color ${c}`, onClick: () => setRoleDialog((d) => ({ ...d, color: c })), className: cn('h-7 w-7 rounded-full border-2 transition-transform', roleDialog.color === c
|
|
@@ -467,6 +495,27 @@ export function PermissionsManager({ loadModules, loadRoles, loadRolePermissions
|
|
|
467
495
|
handleDeleteRole();
|
|
468
496
|
}, children: deleting ? 'Eliminando…' : 'Eliminar' })] })] }) })] }));
|
|
469
497
|
}
|
|
498
|
+
function ActionCheckGrid({ moduleKey, actions, draft, checksDisabled, onToggle, }) {
|
|
499
|
+
return (_jsx("div", { className: "grid gap-2 sm:grid-cols-2", children: actions.map((action) => {
|
|
500
|
+
const cap = moduleActionCapability(moduleKey, action.key, action.capability);
|
|
501
|
+
return (_jsx(CapabilityCheck, { checked: draft?.has(cap) ?? false, disabled: checksDisabled, onToggle: () => onToggle(cap), icon: action.icon || defaultActionIcon(action.key, action.kind), label: action.label, description: action.description }, action.capability ?? action.key));
|
|
502
|
+
}) }));
|
|
503
|
+
}
|
|
504
|
+
/** Flat grid, or collapsible sections when actions declare `group`. */
|
|
505
|
+
function ModuleActionsPanel({ module, draft, checksDisabled, onToggle, }) {
|
|
506
|
+
const sections = React.useMemo(() => groupModuleActions(module.actions), [module.actions]);
|
|
507
|
+
const hasNamedGroups = sections.some((s) => s.title.length > 0);
|
|
508
|
+
if (!hasNamedGroups) {
|
|
509
|
+
return (_jsx(ActionCheckGrid, { moduleKey: module.key, actions: module.actions, draft: draft, checksDisabled: checksDisabled, onToggle: onToggle }));
|
|
510
|
+
}
|
|
511
|
+
return (_jsx("div", { className: "flex flex-col gap-3", children: sections.map((section) => {
|
|
512
|
+
if (!section.title) {
|
|
513
|
+
return (_jsx(ActionCheckGrid, { moduleKey: module.key, actions: section.actions, draft: draft, checksDisabled: checksDisabled, onToggle: onToggle }, "__ungrouped"));
|
|
514
|
+
}
|
|
515
|
+
const granted = section.actions.filter((a) => draft?.has(moduleActionCapability(module.key, a.key, a.capability))).length;
|
|
516
|
+
return (_jsxs(Collapsible, { defaultOpen: true, className: "rounded-md border border-border/60", children: [_jsxs(CollapsibleTrigger, { className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm font-medium hover:bg-muted/40 [&[data-state=open]>svg]:rotate-180", children: [_jsx(ChevronDown, { className: "h-4 w-4 shrink-0 text-muted-foreground transition-transform" }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: section.title }), _jsxs(Badge, { variant: "secondary", className: "tabular-nums", children: [granted, "/", section.actions.length] })] }), _jsx(CollapsibleContent, { className: "border-t border-border/60 px-3 py-3", children: _jsx(ActionCheckGrid, { moduleKey: module.key, actions: section.actions, draft: draft, checksDisabled: checksDisabled, onToggle: onToggle }) })] }, section.title));
|
|
517
|
+
}) }));
|
|
518
|
+
}
|
|
470
519
|
function EmptyHint({ text }) {
|
|
471
520
|
return (_jsxs("div", { className: "flex flex-col items-center justify-center gap-2 py-12 text-muted-foreground", children: [_jsx(Shield, { className: "h-8 w-8 opacity-40" }), _jsx("p", { className: "text-sm", children: text })] }));
|
|
472
521
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "30.0.
|
|
3
|
+
"version": "30.0.3",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"react-i18next": ">=13",
|
|
38
38
|
"sonner": ">=1.7",
|
|
39
39
|
"zustand": ">=5",
|
|
40
|
-
"@asteby/metacore-
|
|
41
|
-
"@asteby/metacore-
|
|
40
|
+
"@asteby/metacore-ui": "^2.14.1",
|
|
41
|
+
"@asteby/metacore-sdk": "^3.4.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependenciesMeta": {
|
|
44
44
|
"@tanstack/react-router": {
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"vitest": "^4.0.0",
|
|
69
69
|
"zustand": "^5.0.0",
|
|
70
70
|
"@asteby/metacore-sdk": "3.4.0",
|
|
71
|
-
"@asteby/metacore-ui": "2.14.
|
|
71
|
+
"@asteby/metacore-ui": "2.14.1"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "tsc -p tsconfig.json",
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
flattenGroups,
|
|
15
15
|
filterModuleGroups,
|
|
16
16
|
defaultActionIcon,
|
|
17
|
+
groupModuleActions,
|
|
17
18
|
type PermissionsCatalog,
|
|
18
19
|
type GroupedPermissionsCatalog,
|
|
19
20
|
type FlatPermissionsCatalog,
|
|
@@ -142,6 +143,19 @@ describe('helpers puros', () => {
|
|
|
142
143
|
])
|
|
143
144
|
})
|
|
144
145
|
|
|
146
|
+
it('groupModuleActions keeps Acceder ungrouped and sections by group', () => {
|
|
147
|
+
const sections = groupModuleActions([
|
|
148
|
+
{ key: 'access', label: 'Acceder', kind: 'screen' },
|
|
149
|
+
{ key: 'product.index', label: 'Productos', group: 'Catálogo', capability: 'product.index' },
|
|
150
|
+
{ key: 'stock.index', label: 'Stock', group: 'Catálogo', capability: 'stock.index' },
|
|
151
|
+
{ key: 'salesorder.create', label: 'Venta', group: 'Ventas', capability: 'salesorder.create' },
|
|
152
|
+
])
|
|
153
|
+
expect(sections.map((s) => s.title)).toEqual(['', 'Catálogo', 'Ventas'])
|
|
154
|
+
expect(sections[0].actions).toHaveLength(1)
|
|
155
|
+
expect(sections[1].actions).toHaveLength(2)
|
|
156
|
+
expect(sections[2].actions).toHaveLength(1)
|
|
157
|
+
})
|
|
158
|
+
|
|
145
159
|
it('moduleCapabilities y grantedCountForModule', () => {
|
|
146
160
|
const mod = grouped.groups[1].modules[0] // pos_orders
|
|
147
161
|
expect(moduleCapabilities(mod)).toEqual([
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
Check,
|
|
29
29
|
ChevronsUpDown,
|
|
30
30
|
CheckCheck,
|
|
31
|
+
ChevronDown,
|
|
31
32
|
Eraser,
|
|
32
33
|
Pencil,
|
|
33
34
|
Plus,
|
|
@@ -73,6 +74,9 @@ import {
|
|
|
73
74
|
PopoverTrigger,
|
|
74
75
|
Separator,
|
|
75
76
|
Skeleton,
|
|
77
|
+
Collapsible,
|
|
78
|
+
CollapsibleContent,
|
|
79
|
+
CollapsibleTrigger,
|
|
76
80
|
} from '@asteby/metacore-ui/primitives'
|
|
77
81
|
import { DynamicIcon } from './dynamic-icon'
|
|
78
82
|
|
|
@@ -85,6 +89,11 @@ export interface PermissionActionDef {
|
|
|
85
89
|
key: string
|
|
86
90
|
/** Localized label ("Listar", "Pagar", "Acceder"). */
|
|
87
91
|
label: string
|
|
92
|
+
/**
|
|
93
|
+
* Optional secondary line under the label (e.g. action name when the label
|
|
94
|
+
* is the module — used by screen → API shortcut checkboxes).
|
|
95
|
+
*/
|
|
96
|
+
description?: string
|
|
88
97
|
/** Lucide icon name from the manifest action (optional). */
|
|
89
98
|
icon?: string
|
|
90
99
|
/**
|
|
@@ -101,6 +110,12 @@ export interface PermissionActionDef {
|
|
|
101
110
|
* shortcuts without inventing `screen….product.index`.
|
|
102
111
|
*/
|
|
103
112
|
capability?: string
|
|
113
|
+
/**
|
|
114
|
+
* Optional section title for the action grid (e.g. "Catálogo", "Ventas").
|
|
115
|
+
* When any action on a module sets `group`, the right-hand panel renders
|
|
116
|
+
* collapsible sections instead of one flat checkbox grid.
|
|
117
|
+
*/
|
|
118
|
+
group?: string
|
|
104
119
|
}
|
|
105
120
|
|
|
106
121
|
export interface PermissionModuleDef {
|
|
@@ -217,6 +232,43 @@ export function moduleCapabilities(module: PermissionModuleDef): string[] {
|
|
|
217
232
|
)
|
|
218
233
|
}
|
|
219
234
|
|
|
235
|
+
export interface ActionGroupSection {
|
|
236
|
+
/** Empty string = ungrouped actions rendered above the collapsibles. */
|
|
237
|
+
title: string
|
|
238
|
+
actions: PermissionActionDef[]
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Split a module's actions into an optional ungrouped prefix + named sections
|
|
243
|
+
* (first-seen order of `action.group`). Modules without any `group` yield a
|
|
244
|
+
* single untitled section (flat grid, backward compatible).
|
|
245
|
+
*/
|
|
246
|
+
export function groupModuleActions(actions: PermissionActionDef[]): ActionGroupSection[] {
|
|
247
|
+
const ungrouped: PermissionActionDef[] = []
|
|
248
|
+
const byTitle = new Map<string, PermissionActionDef[]>()
|
|
249
|
+
const order: string[] = []
|
|
250
|
+
for (const action of actions) {
|
|
251
|
+
const title = (action.group ?? '').trim()
|
|
252
|
+
if (!title) {
|
|
253
|
+
ungrouped.push(action)
|
|
254
|
+
continue
|
|
255
|
+
}
|
|
256
|
+
let list = byTitle.get(title)
|
|
257
|
+
if (!list) {
|
|
258
|
+
list = []
|
|
259
|
+
byTitle.set(title, list)
|
|
260
|
+
order.push(title)
|
|
261
|
+
}
|
|
262
|
+
list.push(action)
|
|
263
|
+
}
|
|
264
|
+
const out: ActionGroupSection[] = []
|
|
265
|
+
if (ungrouped.length > 0) out.push({ title: '', actions: ungrouped })
|
|
266
|
+
for (const title of order) {
|
|
267
|
+
out.push({ title, actions: byTitle.get(title)! })
|
|
268
|
+
}
|
|
269
|
+
return out
|
|
270
|
+
}
|
|
271
|
+
|
|
220
272
|
/** How many of the module's capabilities are in the granted set. */
|
|
221
273
|
export function grantedCountForModule(
|
|
222
274
|
granted: ReadonlySet<string>,
|
|
@@ -399,10 +451,14 @@ function CapabilityCheck({
|
|
|
399
451
|
{icon && (
|
|
400
452
|
<DynamicIcon name={icon} className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground" />
|
|
401
453
|
)}
|
|
402
|
-
<span className="min-w-0">
|
|
403
|
-
<span className="block
|
|
454
|
+
<span className="min-w-0 flex-1">
|
|
455
|
+
<span className="block break-words font-medium leading-snug text-foreground">
|
|
456
|
+
{label}
|
|
457
|
+
</span>
|
|
404
458
|
{description && (
|
|
405
|
-
<span className="mt-0.5 block text-xs text-muted-foreground">
|
|
459
|
+
<span className="mt-0.5 block break-words text-xs leading-snug text-muted-foreground">
|
|
460
|
+
{description}
|
|
461
|
+
</span>
|
|
406
462
|
)}
|
|
407
463
|
</span>
|
|
408
464
|
</div>
|
|
@@ -1060,33 +1116,20 @@ export function PermissionsManager({
|
|
|
1060
1116
|
{!activeRole ? (
|
|
1061
1117
|
<EmptyHint text="Selecciona un rol para configurar sus permisos." />
|
|
1062
1118
|
) : loadingPerms ? (
|
|
1063
|
-
<div className="grid gap-2 sm:grid-cols-2
|
|
1119
|
+
<div className="grid gap-2 sm:grid-cols-2">
|
|
1064
1120
|
{Array.from({ length: 6 }).map((_, i) => (
|
|
1065
|
-
<Skeleton key={i} className="h-
|
|
1121
|
+
<Skeleton key={i} className="h-14 w-full" />
|
|
1066
1122
|
))}
|
|
1067
1123
|
</div>
|
|
1068
1124
|
) : !activeModule ? (
|
|
1069
1125
|
<EmptyHint text="Selecciona un módulo de la lista para ver sus acciones." />
|
|
1070
1126
|
) : (
|
|
1071
|
-
<
|
|
1072
|
-
{activeModule
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
)
|
|
1078
|
-
return (
|
|
1079
|
-
<CapabilityCheck
|
|
1080
|
-
key={action.capability ?? action.key}
|
|
1081
|
-
checked={draft?.has(cap) ?? false}
|
|
1082
|
-
disabled={checksDisabled}
|
|
1083
|
-
onToggle={() => toggleCapability(cap)}
|
|
1084
|
-
icon={action.icon || defaultActionIcon(action.key, action.kind)}
|
|
1085
|
-
label={action.label}
|
|
1086
|
-
/>
|
|
1087
|
-
)
|
|
1088
|
-
})}
|
|
1089
|
-
</div>
|
|
1127
|
+
<ModuleActionsPanel
|
|
1128
|
+
module={activeModule}
|
|
1129
|
+
draft={draft}
|
|
1130
|
+
checksDisabled={checksDisabled}
|
|
1131
|
+
onToggle={toggleCapability}
|
|
1132
|
+
/>
|
|
1090
1133
|
)}
|
|
1091
1134
|
</CardContent>
|
|
1092
1135
|
</Card>
|
|
@@ -1217,6 +1260,111 @@ export function PermissionsManager({
|
|
|
1217
1260
|
)
|
|
1218
1261
|
}
|
|
1219
1262
|
|
|
1263
|
+
function ActionCheckGrid({
|
|
1264
|
+
moduleKey,
|
|
1265
|
+
actions,
|
|
1266
|
+
draft,
|
|
1267
|
+
checksDisabled,
|
|
1268
|
+
onToggle,
|
|
1269
|
+
}: {
|
|
1270
|
+
moduleKey: string
|
|
1271
|
+
actions: PermissionActionDef[]
|
|
1272
|
+
draft: ReadonlySet<string> | null | undefined
|
|
1273
|
+
checksDisabled: boolean
|
|
1274
|
+
onToggle: (cap: string) => void
|
|
1275
|
+
}) {
|
|
1276
|
+
return (
|
|
1277
|
+
<div className="grid gap-2 sm:grid-cols-2">
|
|
1278
|
+
{actions.map((action) => {
|
|
1279
|
+
const cap = moduleActionCapability(moduleKey, action.key, action.capability)
|
|
1280
|
+
return (
|
|
1281
|
+
<CapabilityCheck
|
|
1282
|
+
key={action.capability ?? action.key}
|
|
1283
|
+
checked={draft?.has(cap) ?? false}
|
|
1284
|
+
disabled={checksDisabled}
|
|
1285
|
+
onToggle={() => onToggle(cap)}
|
|
1286
|
+
icon={action.icon || defaultActionIcon(action.key, action.kind)}
|
|
1287
|
+
label={action.label}
|
|
1288
|
+
description={action.description}
|
|
1289
|
+
/>
|
|
1290
|
+
)
|
|
1291
|
+
})}
|
|
1292
|
+
</div>
|
|
1293
|
+
)
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
/** Flat grid, or collapsible sections when actions declare `group`. */
|
|
1297
|
+
function ModuleActionsPanel({
|
|
1298
|
+
module,
|
|
1299
|
+
draft,
|
|
1300
|
+
checksDisabled,
|
|
1301
|
+
onToggle,
|
|
1302
|
+
}: {
|
|
1303
|
+
module: PermissionModuleDef
|
|
1304
|
+
draft: ReadonlySet<string> | null | undefined
|
|
1305
|
+
checksDisabled: boolean
|
|
1306
|
+
onToggle: (cap: string) => void
|
|
1307
|
+
}) {
|
|
1308
|
+
const sections = React.useMemo(
|
|
1309
|
+
() => groupModuleActions(module.actions),
|
|
1310
|
+
[module.actions],
|
|
1311
|
+
)
|
|
1312
|
+
const hasNamedGroups = sections.some((s) => s.title.length > 0)
|
|
1313
|
+
if (!hasNamedGroups) {
|
|
1314
|
+
return (
|
|
1315
|
+
<ActionCheckGrid
|
|
1316
|
+
moduleKey={module.key}
|
|
1317
|
+
actions={module.actions}
|
|
1318
|
+
draft={draft}
|
|
1319
|
+
checksDisabled={checksDisabled}
|
|
1320
|
+
onToggle={onToggle}
|
|
1321
|
+
/>
|
|
1322
|
+
)
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
return (
|
|
1326
|
+
<div className="flex flex-col gap-3">
|
|
1327
|
+
{sections.map((section) => {
|
|
1328
|
+
if (!section.title) {
|
|
1329
|
+
return (
|
|
1330
|
+
<ActionCheckGrid
|
|
1331
|
+
key="__ungrouped"
|
|
1332
|
+
moduleKey={module.key}
|
|
1333
|
+
actions={section.actions}
|
|
1334
|
+
draft={draft}
|
|
1335
|
+
checksDisabled={checksDisabled}
|
|
1336
|
+
onToggle={onToggle}
|
|
1337
|
+
/>
|
|
1338
|
+
)
|
|
1339
|
+
}
|
|
1340
|
+
const granted = section.actions.filter((a) =>
|
|
1341
|
+
draft?.has(moduleActionCapability(module.key, a.key, a.capability)),
|
|
1342
|
+
).length
|
|
1343
|
+
return (
|
|
1344
|
+
<Collapsible key={section.title} defaultOpen className="rounded-md border border-border/60">
|
|
1345
|
+
<CollapsibleTrigger className="flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm font-medium hover:bg-muted/40 [&[data-state=open]>svg]:rotate-180">
|
|
1346
|
+
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground transition-transform" />
|
|
1347
|
+
<span className="min-w-0 flex-1 truncate">{section.title}</span>
|
|
1348
|
+
<Badge variant="secondary" className="tabular-nums">
|
|
1349
|
+
{granted}/{section.actions.length}
|
|
1350
|
+
</Badge>
|
|
1351
|
+
</CollapsibleTrigger>
|
|
1352
|
+
<CollapsibleContent className="border-t border-border/60 px-3 py-3">
|
|
1353
|
+
<ActionCheckGrid
|
|
1354
|
+
moduleKey={module.key}
|
|
1355
|
+
actions={section.actions}
|
|
1356
|
+
draft={draft}
|
|
1357
|
+
checksDisabled={checksDisabled}
|
|
1358
|
+
onToggle={onToggle}
|
|
1359
|
+
/>
|
|
1360
|
+
</CollapsibleContent>
|
|
1361
|
+
</Collapsible>
|
|
1362
|
+
)
|
|
1363
|
+
})}
|
|
1364
|
+
</div>
|
|
1365
|
+
)
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1220
1368
|
function EmptyHint({ text }: { text: string }) {
|
|
1221
1369
|
return (
|
|
1222
1370
|
<div className="flex flex-col items-center justify-center gap-2 py-12 text-muted-foreground">
|