import type { Plugin } from '@puckeditor/core'; import { type PuckData } from '@pantheon-systems/css-client'; import type { UiState } from '@puckeditor/core'; import type { P1PuckContextValue } from '../core/types.js'; import type { ThumbnailMap } from './utils/buildThumbnailOverride.js'; import type { LiveThumbnailDrawerOptions } from './thumbnails/buildLiveThumbnailDrawer.js'; import type { UseP1PluginOptions } from './useP1Plugin.js'; import type { UseP1OverridesOptions } from './useP1Overrides.js'; import type { PuckOverrides } from './plugin/index.js'; /** * Options for useP1Editor. */ export interface UseP1EditorOptions { /** Document path to load */ documentPath: string; /** Puck component configuration */ puckConfig: unknown; /** Additional plugins to include after the P1 plugin */ additionalPlugins?: Plugin[]; /** * Additional overrides to merge with P1 overrides. * Merged with stable memoization to prevent Puck's appStore.setState * from firing on every render (which causes preview iframe re-renders). * Nested objects (e.g. fieldTypes) are shallow-merged. */ additionalOverrides?: PuckOverrides; /** * Map from Puck component name to a zero-argument React FC that renders a * schematic SVG wireframe thumbnail. When provided, each drawer item shows * a 48×32 thumbnail alongside the name and a drag-handle affordance. * Unknown names fall back to a generic placeholder automatically. * * @example * ```tsx * import { THUMBNAIL_MAP } from '@/data/thumbnails'; * * useP1Editor({ thumbnails: THUMBNAIL_MAP, ... }); * ``` */ thumbnails?: ThumbnailMap; /** * Live thumbnail component drawer — replaces Puck's default component list * with collapsible categories of live-rendered preview cards. Defaults to * ON for every consumer (no per-app wiring needed). Pass `false` to keep * Puck's default drawer, or an options object to tune scale / card height. * * NOTE: this changes the default drawer for all `puck-css` editors. */ liveThumbnailDrawer?: boolean | LiveThumbnailDrawerOptions; /** Customization options for overrides */ overrideOptions?: UseP1OverridesOptions; /** Customization options for the P1 plugin (versions are managed internally) */ pluginOptions?: Omit; /** Callback when user selection changes */ onSelectionChange?: (path: string | null, itemId: string | null) => void; /** Called when document loading fails. Return true to retry loading. */ onDocumentNotFound?: (documentPath: string, error: Error) => Promise; } /** * Props to spread onto component. */ export interface PuckProps { /** Puck component configuration */ config: unknown; /** Safe data (never null) */ data: PuckData; /** onChange handler wired to context saveData (disabled for historical versions) */ onChange: (data: unknown) => void; /** Plugin array with P1 plugin first */ plugins: Plugin[]; /** Overrides with header actions */ overrides: PuckOverrides; /** Permissions (locked down for historical versions) */ permissions?: Record; /** Dynamic permission resolver for template-based restrictions */ resolvePermissions?: (item: { type: string; }, appState: any) => { edit: boolean; drag: boolean; delete: boolean; insert: boolean; duplicate: boolean; }; /** Puck onAction callback — captures structural actions for template migration conflict detection */ onAction?: (action: Record) => void; /** Initial UI state (sidebar visibility etc.) — read from localStorage on each key-based remount */ ui?: Partial; } /** * Why a reload is in flight while the previous document is still on screen. * The two reads differently to the user — a workstream switch replaces the * whole site's content, a page switch only swaps the canvas — so the copy that * covers the wait has to be able to tell them apart. */ export type ReloadKind = 'branch' | 'document'; /** * Return value from useP1Editor. */ export interface UseP1EditorReturn { /** Whether there is nothing to render yet — the first document has not loaded and has not failed */ loading: boolean; /** * A reload running behind retained content, and why. Null when nothing is in * flight or when there is no prior content to keep showing (that is `loading`). */ reloading: ReloadKind | null; /** Whether a document has ever loaded successfully — i.e. `puckProps` are worth rendering */ hasContent: boolean; /** Error from document loading, if any */ error: Error | null; /** * The requested path has no document on this branch. Distinct from `error`: * nothing failed, the page simply is not there yet, so the consumer can offer * to create it instead of reporting a fault. */ notFound: boolean; /** Re-run the load for the current path — call after creating the missing document. */ retry: () => void; /** React key — pass directly as `` to force a clean remount on role change (document switches sync in place) */ puckKey: string; /** Props to spread onto */ puckProps: PuckProps; /** Full P1 context for advanced/escape-hatch use */ css: P1PuckContextValue; /** * @deprecated Always null. Branch-switch redirects have been removed; the * editor now unloads the page context and shows an empty state in the * preview area when the current document does not exist on the selected branch. */ redirectPath: string | null; } export declare function useP1Editor(options: UseP1EditorOptions): UseP1EditorReturn;