/** * Puck Permissions Resolver * * Creates a resolvePermissions function for Puck that enforces template constraints. */ import type { Template, TemplateSummary } from '../types.js'; /** * Puck permission flags for a component. */ export interface PuckPermissions { /** Can edit component props */ edit: boolean; /** Can drag/reorder component */ drag: boolean; /** Can delete component */ delete: boolean; /** Can insert new components */ insert: boolean; /** Can duplicate component */ duplicate: boolean; } /** * Item passed to resolvePermissions by Puck. */ export interface PuckItem { type: string; props?: { id?: string; [key: string]: unknown; }; } /** * App state passed to resolvePermissions by Puck. */ export type PuckAppState = Record; /** * Permission resolver function type for Puck. */ export type PuckPermissionResolver = (item: PuckItem, appState: unknown) => PuckPermissions; /** * Create a Puck permissions resolver from the template and the user's backend * permissions. * * A canvas component is pinned when its own `props.id` is a slot id that maps * to `true` in `root.props._pinMap` and has a matching component instance * anywhere in the template, including zones and slot children. A same-typed * component with a different id (a local copy or duplicate) is never locked. * * Permission logic: * - **Pinned components**: * - canOverridePins true: resolved like a non-pinned component * - canOverridePins false: no edit, drag, delete or duplicate * - canOverridePins omitted: drag=false, delete=false for all roles; edit * and duplicate follow the normal rules * - **Components containing a pinned component** (canOverridePins false), * found in the document Puck passes as appState (the template's layout when * none is passed), so a pin an admin moved locks its new container: * edit=false, drag=false, delete=false, so the pinned child cannot be moved, * removed or hidden by changing the container's fields; insert and * duplicate follow the normal rules * - **Components inside a pinned component** (canOverridePins false), found * the same way: edit=false, drag=false, delete=false, duplicate=false, so * the pinned block's slot content is as locked as the block itself * - **Non-pinned components**: * - canEditDocuments: full permissions * - otherwise: no structural permissions (drag/delete/insert/duplicate) * - **Blank pages (no template)**: * - canEditDocuments: full permissions * - otherwise: no structural permissions * - **Historical versions**: all structural permissions false for all roles * * @param template - Template this document is bound to (null for blank pages; * a metadata-only summary carries no pins) * @param canEditDocuments - The backend flag; false locks all structural edits * @param isHistoricalVersion - Whether viewing a historical version (read-only) * @param canEditProps - Overrides prop-editing access when given. Omitted keeps * the previous behavior, for callers on the three-argument signature. * @param canOverridePins - Whether the user may edit, move and remove pinned * components, typically the `canManageTemplates` permission. When omitted, * pinned components cannot be moved or removed by any role, and their props * and duplication follow the normal rules. * @returns Permission resolver function for Puck * * @example * ```tsx * const resolvePermissions = createPuckPermissions(template, true, false); * * * ``` */ export declare function createPuckPermissions(template: Template | TemplateSummary | null, canEditDocuments: boolean, isHistoricalVersion: boolean, canEditProps?: boolean, canOverridePins?: boolean): PuckPermissionResolver;