{
  "version": 1,
  "comment": "Cross-adapter parity contract between @eigenpal/docx-editor-react and @eigenpal/docx-editor-vue. Tracked in issue #475 Phase 3. Drives `bun run check:parity-contract`, which parses each adapter's docs/api/<slug>/index.api.md, applies this contract, and fails on undocumented drift. Adding a new prop or ref method to either adapter forces a contract update \u2014 there is no way to silently introduce divergence.",
  "props": {
    "paired": [
      "author",
      "className",
      "colorMode",
      "disableFindReplaceShortcuts",
      "document",
      "documentBuffer",
      "documentName",
      "documentNameEditable",
      "externalPlugins",
      "fontFamilies",
      "fonts",
      "i18n",
      "initialZoom",
      "mode",
      "onChange",
      "onCommentAdd",
      "onCommentDelete",
      "onCommentReply",
      "onCommentResolve",
      "onCommentsChange",
      "onDocumentNameChange",
      "onEditorViewReady",
      "onError",
      "onModeChange",
      "onPrint",
      "onSelectionChange",
      "readOnly",
      "renderLogo",
      "renderTitleBarRight",
      "showOutline",
      "showOutlineButton",
      "showRuler",
      "showToolbar",
      "showZoomControl",
      "style",
      "theme",
      "toolbarExtra",
      "watermarkPresets"
    ],
    "deferredInVue": {
      "agentPanel": "AI agent panel UI. Vue adapter ships without the agent surface; React-only until the Vue agent components land.",
      "comments": "Comment threads. Part of the Vue comments API gap.",
      "externalContent": "Sandboxed external-content rendering mode. React-only escape hatch.",
      "loadingIndicator": "Custom loading slot. Vue uses default slot via VNodeChild.",
      "marginGuideColor": "Pairs with showMarginGuides \u2014 both deferred together.",
      "onCopy": "Clipboard event hooks. Vue exposes via useClipboard composable instead.",
      "onCut": "Clipboard event hooks. Vue exposes via useClipboard composable instead.",
      "onFontsLoaded": "Font-load lifecycle. Vue-deferred.",
      "onPaste": "Clipboard event hook. Vue exposes via useClipboard composable instead.",
      "onRenderedDomContextReady": "Plugin host ready callback. Pairs with pluginRenderedDomContext.",
      "onSave": "Save-to-buffer callback. Critical parity gap \u2014 Vue uses useDocxEditor().save() that returns a Blob, not a prop callback.",
      "placeholder": "Empty-state slot. Vue uses default slot pattern.",
      "pluginOverlays": "Plugin overlay slot. Pairs with pluginRenderedDomContext.",
      "pluginRenderedDomContext": "Plugin host hand-off. Vue plugin-api is a smaller surface.",
      "pluginSidebarItems": "Sidebar plugin items. Pairs with the Vue plugin-api gap.",
      "printOptions": "Print configuration. Vue uses onPrint without options object.",
      "rulerUnit": "Ruler unit toggle (inch/cm). Vue uses inch only currently.",
      "showMarginGuides": "Margin guide overlay. Pairs with marginGuideColor \u2014 both deferred together."
    },
    "vueExclusive": {
      "showMenuBar": "Vue adapter ships a Google-Docs-style menu bar above the toolbar. React uses a single toolbar with no menu-bar concept."
    }
  },
  "ref": {
    "comment": "DocxEditorRef parity. React's DocxEditorRef declares every member directly. Vue's DocxEditorRef intersects EditorRefLike (from @eigenpal/docx-editor-agents/bridge) plus its own additions \u2014 so members inherited via EditorRefLike are NOT enumerated in Vue's snapshot, but ARE callable at runtime. The contract uses three buckets: `paired` (explicit on both sides), `pairedViaInheritance` (explicit on React, inherited via EditorRefLike on Vue), and `vueExclusive` (only on Vue's DocxEditorRef).",
    "paired": [
      "focus",
      "getAgent",
      "getContentControls",
      "getZoom",
      "highlightRange",
      "loadDocument",
      "loadDocumentBuffer",
      "openPrintPreview",
      "print",
      "removeContentControl",
      "save",
      "scrollToChangeId",
      "scrollToCommentId",
      "scrollToContentControl",
      "scrollToPage",
      "scrollToPosition",
      "setContentControlContent",
      "setContentControlValue",
      "setZoom"
    ],
    "pairedViaInheritance": {
      "addComment": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "applyFormatting": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "findInDocument": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "getComments": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "getCurrentPage": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "getDocument": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "getEditorRef": "Inherited via EditorRefLike. Returns the inner editor handle (React: PagedEditorRef; Vue: useDocxEditor() composable handle).",
      "getPageContent": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "getSelectionInfo": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "getTotalPages": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "insertBreak": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "onContentChange": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "onSelectionChange": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "proposeChange": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "replyToComment": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "resolveComment": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "scrollToParaId": "Inherited via EditorRefLike. Identical signature on both adapters.",
      "setParagraphStyle": "Inherited via EditorRefLike. Identical signature on both adapters."
    },
    "vueExclusive": {
      "destroy": "Vue's component-level imperative teardown. React's DocxEditorRef omits this because React handles unmount automatically; both adapters expose `destroy` via their `renderAsync()` return (DocxEditorHandle from core's EditorHandle base)."
    }
  }
}
