{
  "tag": "ed-page-editor",
  "kind": "component",
  "summary": "Edits the pages of one or more scanned files — rotate, delete, split, reorder — with\noptional AI suggestions. The generic page editor behind DMS scan workflows; place it in a dialog.",
  "status": "experimental",
  "level": "organism",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/page-editor/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/page-editor/usage/",
  "playwright": "getByTestId('…')",
  "dependencies": [
    "ed-badge",
    "ed-button",
    "ed-checkbox",
    "ed-dialog",
    "ed-document-viewer",
    "ed-icon",
    "ed-progress-ring",
    "ed-skeleton",
    "ed-slider",
    "ed-switch"
  ],
  "use": [
    "Cleaning up and structuring scans before archiving — rotating skewed pages, deleting blanks, splitting a stack into separate documents, reordering",
    "Splitting a scanned stack of invoices into single documents before they are sent to the archive",
    "Removing blank or duplicate pages and fixing upside-down pages from a scanner, in one dialog before saving",
    "Checking page changes suggested by an AI service, such as detected splits, and accepting or correcting them"
  ],
  "notFor": [
    {
      "when": "Only reading or reviewing a document",
      "instead": "[Document Viewer](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/document-viewer)"
    },
    {
      "when": "Editing the content of a document, such as text or numbers",
      "instead": "the product's own editor; this only arranges pages"
    }
  ],
  "rules": [
    {
      "id": "page-editor/persist-from-edit-event",
      "rule": "Wire saving to the edit event and persist the outcome yourself — the editor manipulates pages, it never saves them. Every change surfaces through that event with the edited files, a dirty and a valid flag; reading it and persisting the outcome is entirely your job.",
      "why": "Nothing the user does here reaches a backend until you send it.",
      "check": "warning"
    },
    {
      "id": "page-editor/in-dialog",
      "rule": "Place the editor inside a [Dialog](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/dialog) and give it a height — it fills its container.",
      "check": "error"
    },
    {
      "id": "page-editor/supply-images",
      "rule": "Never expect the editor to fetch anything — pages arrive rendered through your code, and lazily requested images come back through the preview-request event."
    },
    {
      "id": "page-editor/preview-images",
      "rule": "Provide a higher-resolution preview image per page where available — the built-in full-screen zoom uses it and falls back to the page image otherwise."
    },
    {
      "id": "page-editor/ai-only-with-service",
      "rule": "Enable AI suggestions only when a service actually provides them — never ship the AI controls visible without a suggestion service behind them.",
      "why": "The toggle is off by default for a reason — without suggestions the controls are dead UI.",
      "check": "warning"
    },
    {
      "id": "page-editor/stream-suggestions",
      "rule": "Stream AI suggestions in as they arrive, and show the pending hint while they are on the way. Don't add your own guard for pages the user already edited — the component never lets a suggestion override one."
    }
  ],
  "api": {
    "attributes": [
      {
        "name": "ai-suggestions",
        "property": "aiSuggestions",
        "type": "boolean",
        "default": "false",
        "description": "Opt-in: show the AI-suggestion controls and provenance chips. Off by default — set it only when\nthe document type carries AI suggestions (always on in ed-scan, usually off in DMS)."
      },
      {
        "name": "suggestions-pending",
        "property": "suggestionsPending",
        "type": "boolean",
        "default": "false",
        "description": "Set while AI suggestions are still being computed (e.g. a slow analysis running after the pages\nare already shown). The AI section shows a loading hint instead of the toggles. Clear it once the\nsuggestions are delivered via `provideSuggestions()`. Only meaningful with `ai-suggestions`."
      },
      {
        "name": "hide-deleted",
        "property": "hideDeleted",
        "type": "boolean",
        "default": "false",
        "description": "Hide pages marked for deletion instead of dimming them in place."
      },
      {
        "name": "zoom",
        "property": "zoom",
        "type": "number",
        "default": "1",
        "description": "Thumbnail zoom factor (1 = the default page size)."
      },
      {
        "name": "disabled",
        "property": "disabled",
        "type": "boolean",
        "default": "false",
        "description": "Render the whole editor read-only."
      },
      {
        "name": "dir",
        "property": "dir",
        "type": "string"
      },
      {
        "name": "lang",
        "property": "lang",
        "type": "string"
      }
    ],
    "properties": [
      {
        "name": "files",
        "type": "PageEditorFile[]",
        "description": "The files to edit. Provide as a property, not an attribute."
      }
    ],
    "methods": [
      {
        "name": "providePagePreview",
        "parameters": [
          {
            "name": "page",
            "type": "PageEditorPage"
          },
          {
            "name": "src",
            "type": "string"
          },
          {
            "name": "variant",
            "type": "'thumbnail' | 'preview'"
          }
        ],
        "returns": "void",
        "description": "Injects a fetched preview for a page (in response to `ed-request-preview`). Pass the `page` and the\n`variant` from the event — identifying by reference (not an index) survives a reorder that happened\nwhile the preview was loading. `'thumbnail'` (default) sets the grid image; `'preview'` sets the\nhigher-resolution source the zoom lightbox uses. Set in place, so in-progress edits are preserved."
      },
      {
        "name": "provideSuggestions",
        "parameters": [
          {
            "name": "suggestions",
            "type": "{ id: string; suggestion: PageEditorSuggestion }[]"
          }
        ],
        "returns": "void",
        "description": "Injects AI suggestions that arrived after the pages were set — e.g. a slow analysis completing\nwhile the editor is already interactive. Each entry targets a page by its `id`; the suggestion is\nmerged onto that page and the enabled toggles are re-applied. Pages the user has already rotated,\ndeleted or split keep their edit (provenance is preserved). Unknown ids are ignored, and it is a\nno-op when nothing matched. Pair with the `suggestions-pending` attribute to show a loading hint."
      },
      {
        "name": "getResult",
        "returns": "PageEditorFile[]",
        "description": "The current edited state — the same `files` shape carried by `ed-edit`, including edits applied\nfrom AI suggestions on load. Read it at save time so you capture the result even when the user\naccepted the suggestions without making a manual edit (which wouldn't have fired `ed-edit`)."
      },
      {
        "name": "isDirty",
        "returns": "boolean",
        "description": "Returns true once any editable field differs from the input (used as the `ed-edit` dirty flag)."
      },
      {
        "name": "getPropertyDescriptor",
        "static": true,
        "parameters": [
          {
            "name": "name",
            "type": "PropertyKey"
          },
          {
            "name": "key",
            "type": "string | symbol"
          },
          {
            "name": "options",
            "type": "PropertyDeclaration"
          }
        ],
        "returns": "PropertyDescriptor | undefined",
        "description": "Wraps the accessor of reflected properties so they always hold a valid value, as a native\nreflected IDL attribute does (`button.type = undefined` reads `submit`):\n\n- A property that declares `useDefault` takes the first value set on an element for its\n  default. That value is its field initializer's: the constructor has finished before markup,\n  a framework or any other code can set anything. Every later `null` or `undefined` means what\n  a dropped prop means on a native element — the attribute is removed: with the attribute\n  there, it is removed and Lit's `useDefault` restores the default without writing it; without\n  one, the property is set to the default. A value set and cleared again before the element\n  updates still writes the default once, from the pending reflection.\n- A Boolean is coerced with `Boolean()`, so `undefined` is `false`.\n\nLit's `useDefault` keeps the initial default out of the DOM. Setting the default explicitly\nwrites it, as `button.type = 'submit'` writes `type`."
      }
    ],
    "events": [
      {
        "name": "ed-edit",
        "react": "onEdEdit",
        "type": "{ files: PageEditorFile[], dirty: boolean, valid: boolean }",
        "description": "Emitted on every edit. `detail` is `{ files, dirty, valid }`."
      },
      {
        "name": "ed-request-preview",
        "react": "onEdRequestPreview",
        "type": "{ fileId: string, page: PageEditorPage, variant: 'thumbnail' | 'preview', signal: AbortSignal }",
        "description": "Emitted when a page image is needed: a `'thumbnail'` when a page without a `src` nears the grid viewport, or a `'preview'` (higher-resolution) when a page is opened in the zoom lightbox. Fetch the matching source and call `providePagePreview(page, src, variant)`. `detail` is `{ fileId, page, variant, signal }`; `signal` aborts when the request is superseded."
      }
    ],
    "slots": [
      {
        "name": "header",
        "description": "Optional content shown at the start of the toolbar (defaults to the first file's name)."
      },
      {
        "name": "actions",
        "description": "Optional extra controls shown at the end of the toolbar."
      }
    ],
    "cssProperties": [
      {
        "name": "--ed-page-editor-page-width",
        "description": "The page card width; derived from `zoom`."
      }
    ],
    "parts": [
      {
        "name": "toolbar",
        "description": "The top bar (file name, zoom, hide-deleted toggle)."
      },
      {
        "name": "subbar",
        "description": "The action bar (select all, bulk actions, AI suggestions)."
      },
      {
        "name": "canvas",
        "description": "The scrollable area that lays out the page cards."
      },
      {
        "name": "page",
        "description": "Each page card."
      },
      {
        "name": "cut-marker",
        "description": "The split marker shown between two pages."
      }
    ],
    "states": [
      {
        "name": "empty",
        "description": "Applied when there are no files to edit."
      },
      {
        "name": "disabled",
        "description": "Applied when the editor is read-only."
      }
    ]
  },
  "import": "import '@eurodata/eurodata-ui/dist/components/page-editor/page-editor.js';",
  "react": {
    "component": "EdPageEditor",
    "import": "import EdPageEditor from '@eurodata/eurodata-ui/dist/react/page-editor/index.js';"
  }
}
