superdoc 1.0.0-beta.30 → 1.0.0-beta.32

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.
Files changed (27) hide show
  1. package/dist/chunks/{PdfViewer-BADCvUNL.cjs → PdfViewer-CTKbqDWv.cjs} +1 -1
  2. package/dist/chunks/{PdfViewer-C2nY5qD8.es.js → PdfViewer-edjIRb_p.es.js} +1 -1
  3. package/dist/chunks/{index-DTgPk1zO.cjs → index-Cajp7-Xa.cjs} +3 -3
  4. package/dist/chunks/{index-DmelLGEj.es.js → index-Pwv0a9G5.es.js} +3 -3
  5. package/dist/chunks/{index-DUzV7kkk-BvBMF_lo.es.js → index-SGV4U12y-BPGxOtvI.es.js} +1 -1
  6. package/dist/chunks/{index-DUzV7kkk-CM3uwGCb.cjs → index-SGV4U12y-Dh5jaROA.cjs} +1 -1
  7. package/dist/chunks/{super-editor.es-463G9jKM.cjs → super-editor.es-BbbbKgEs.cjs} +1729 -105
  8. package/dist/chunks/{super-editor.es-Be9785LD.es.js → super-editor.es-CdGsYGU1.es.js} +1729 -105
  9. package/dist/super-editor/ai-writer.es.js +2 -2
  10. package/dist/super-editor/chunks/{converter-U59bT3FO.js → converter-CpuOoAUa.js} +1 -1
  11. package/dist/super-editor/chunks/{docx-zipper-DSnoGkju.js → docx-zipper-Dk99r397.js} +1 -1
  12. package/dist/super-editor/chunks/{editor-DRHVtMIR.js → editor-CFv-RJI-.js} +1776 -90
  13. package/dist/super-editor/chunks/{index-DUzV7kkk.js → index-SGV4U12y.js} +1 -1
  14. package/dist/super-editor/chunks/{toolbar-DbBLxo6N.js → toolbar-CQr3Xnx9.js} +2 -2
  15. package/dist/super-editor/converter.es.js +1 -1
  16. package/dist/super-editor/docx-zipper.es.js +2 -2
  17. package/dist/super-editor/editor.es.js +3 -3
  18. package/dist/super-editor/file-zipper.es.js +1 -1
  19. package/dist/super-editor/super-editor.es.js +6 -6
  20. package/dist/super-editor/toolbar.es.js +2 -2
  21. package/dist/super-editor.cjs +1 -1
  22. package/dist/super-editor.es.js +1 -1
  23. package/dist/superdoc.cjs +2 -2
  24. package/dist/superdoc.es.js +2 -2
  25. package/dist/superdoc.umd.js +1715 -91
  26. package/dist/superdoc.umd.js.map +1 -1
  27. package/package.json +1 -1
@@ -9,11 +9,11 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
9
9
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
10
10
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
11
11
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
12
- var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, dispatchWithFallback_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, getPluginKeyName_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, checkFonts_fn, determineUnsupportedFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _map, _editor2, _descriptors, _collections, _editorEntries, _maxCachedEditors, _editorAccessOrder, _pendingCreations, _cacheHits, _cacheMisses, _evictions, _HeaderFooterEditorManager_instances, hasConverter_fn, extractCollections_fn, collectDescriptors_fn, teardownMissingEditors_fn, teardownEditors_fn, createEditor_fn, createEditorContainer_fn, registerConverterEditor_fn, unregisterConverterEditor_fn, updateAccessOrder_fn, enforceCacheSizeLimit_fn, _manager, _mediaFiles, _blockCache, _HeaderFooterLayoutAdapter_instances, getBlocks_fn, getConverterContext_fn, _selectionOverlay, _activeEditorHost, _activeDecorationContainer, _activeRegion, _borderLine, _dimmingOverlay, _EditorOverlayManager_instances, findDecorationContainer_fn, ensureEditorHost_fn, positionEditorHost_fn, hideDimmingOverlay_fn, showHeaderFooterBorder_fn, hideHeaderFooterBorder_fn, _instances, _options, _editor3, _visibleHost, _viewportHost, _painterHost, _selectionOverlay2, _hiddenHost, _layoutOptions, _layoutState, _domPainter, _layoutError, _layoutErrorState, _errorBanner, _errorBannerMessage, _telemetryEmitter, _renderScheduled, _pendingDocChange, _isRerendering, _selectionUpdateScheduled, _remoteCursorUpdateScheduled, _rafHandle, _editorListeners, _sectionMetadata, _documentMode, _inputBridge, _trackedChangesMode, _trackedChangesEnabled, _trackedChangesOverrides, _headerFooterManager, _headerFooterAdapter, _headerFooterIdentifier, _multiSectionIdentifier, _headerLayoutResults, _footerLayoutResults, _headerLayoutsByRId, _footerLayoutsByRId, _headerDecorationProvider, _footerDecorationProvider, _headerFooterManagerCleanups, _headerRegions, _footerRegions, _session, _activeHeaderFooterEditor, _overlayManager, _hoverOverlay, _hoverTooltip, _modeBanner, _ariaLiveRegion, _hoverRegion, _clickCount, _lastClickTime, _lastClickPosition, _lastSelectedImageBlockId, _remoteCursorState, _remoteCursorDirty, _remoteCursorOverlay, _localSelectionLayer, _awarenessCleanup, _scrollCleanup, _remoteCursorRafHandle, _scrollTimeout, _PresentationEditor_instances, aggregateLayoutBounds_fn, safeCleanup_fn, setupEditorListeners_fn, setupCollaborationCursors_fn, normalizeAwarenessStates_fn, getFallbackColor_fn, getValidatedColor_fn, scheduleRemoteCursorUpdate_fn, scheduleRemoteCursorReRender_fn, updateRemoteCursors_fn, renderRemoteCursors_fn, renderRemoteCaret_fn, renderRemoteCursorLabel_fn, renderRemoteSelection_fn, setupPointerHandlers_fn, setupInputBridge_fn, initHeaderFooterRegistry_fn, _handlePointerDown, getFirstTextPosition_fn, registerPointerClick_fn, selectWordAt_fn, selectParagraphAt_fn, isWordCharacter_fn, _handlePointerMove, _handlePointerLeave, _handleDoubleClick, _handleKeyDown, focusHeaderFooterShortcut_fn, scheduleRerender_fn, flushRerenderQueue_fn, rerender_fn, ensurePainter_fn, scheduleSelectionUpdate_fn, updateSelection_fn, resolveLayoutOptions_fn, buildHeaderFooterInput_fn, computeHeaderFooterConstraints_fn, layoutPerRIdHeaderFooters_fn, updateDecorationProviders_fn, createDecorationProvider_fn, findHeaderFooterPageForPageNumber_fn, computeDecorationBox_fn, rebuildHeaderFooterRegions_fn, hitTestHeaderFooterRegion_fn, pointInRegion_fn, activateHeaderFooterRegion_fn, enterHeaderFooterMode_fn, exitHeaderFooterMode_fn, getActiveDomTarget_fn, emitHeaderFooterModeChanged_fn, emitHeaderFooterEditingContext_fn, updateAwarenessSession_fn, updateModeBanner_fn, announce_fn, validateHeaderFooterEditPermission_fn, emitHeaderFooterEditBlocked_fn, resolveDescriptorForRegion_fn, createDefaultHeaderFooter_fn, getPageElement_fn, scrollPageIntoView_fn, waitForPageMount_fn, getBodyPageHeight_fn, getHeaderFooterPageHeight_fn, renderSelectionRects_fn, renderHoverRegion_fn, clearHoverRegion_fn, renderCaretOverlay_fn, getHeaderFooterContext_fn, computeHeaderFooterSelectionRects_fn, syncTrackedChangesPreferences_fn, deriveTrackedChangesMode_fn, deriveTrackedChangesEnabled_fn, getTrackChangesPluginState_fn, computeDefaultLayoutDefaults_fn, parseColumns_fn, inchesToPx_fn, applyZoom_fn, createLayoutMetrics_fn, convertPageLocalToOverlayCoords_fn, normalizeClientPoint_fn, computeCaretLayoutRect_fn, computeCaretLayoutRectFromDOM_fn, computeTableCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _layoutSurfaces, _getTargetDom, _isEditable, _onTargetChanged, _listeners, _currentTarget, _destroyed, _useWindowFallback, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, shouldSkipSurface_fn, isInLayoutSurface_fn, getListenerTargets_fn, isPlainCharacterKey_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, checkShouldUpdate_fn, updateHTMLAttributes_fn, updateDOMStyles_fn, resolveNeighborParagraphProperties_fn, updateListStyles_fn, initList_fn, checkIsList_fn, createMarker_fn, createSeparator_fn, calculateTabSeparatorStyle_fn, calculateMarkerStyle_fn, removeList_fn, getParagraphContext_fn, scheduleAnimation_fn, cancelScheduledAnimation_fn, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn, _VectorShapeView_instances, ensureParentPositioned_fn, _ShapeGroupView_instances, ensureParentPositioned_fn2;
12
+ var _Attribute_static, getGlobalAttributes_fn, getNodeAndMarksAttributes_fn, _Schema_static, createNodesSchema_fn, createMarksSchema_fn, _events, _ExtensionService_instances, setupExtensions_fn, attachEditorEvents_fn, _editor, _stateValidators, _xmlValidators, _requiredNodeTypes, _requiredMarkTypes, _SuperValidator_instances, initializeValidators_fn, collectValidatorRequirements_fn, analyzeDocument_fn, dispatchWithFallback_fn, _commandService, _Editor_instances, initContainerElement_fn, init_fn, initRichText_fn, onFocus_fn, checkHeadless_fn, registerCopyHandler_fn, insertNewFileData_fn, getPluginKeyName_fn, createExtensionService_fn, createCommandService_fn, createConverter_fn, initMedia_fn, initFonts_fn, checkFonts_fn, determineUnsupportedFonts_fn, createSchema_fn, generatePmData_fn, createView_fn, onCollaborationReady_fn, initComments_fn, dispatchTransaction_fn, handleNodeSelection_fn, prepareDocumentForImport_fn, prepareDocumentForExport_fn, endCollaboration_fn, validateDocumentInit_fn, validateDocumentExport_fn, initDevTools_fn, _map, _editor2, _descriptors, _collections, _editorEntries, _maxCachedEditors, _editorAccessOrder, _pendingCreations, _cacheHits, _cacheMisses, _evictions, _HeaderFooterEditorManager_instances, hasConverter_fn, extractCollections_fn, collectDescriptors_fn, teardownMissingEditors_fn, teardownEditors_fn, createEditor_fn, createEditorContainer_fn, registerConverterEditor_fn, unregisterConverterEditor_fn, updateAccessOrder_fn, enforceCacheSizeLimit_fn, _manager, _mediaFiles, _blockCache, _HeaderFooterLayoutAdapter_instances, getBlocks_fn, getConverterContext_fn, _selectionOverlay, _activeEditorHost, _activeDecorationContainer, _activeRegion, _borderLine, _dimmingOverlay, _EditorOverlayManager_instances, findDecorationContainer_fn, ensureEditorHost_fn, positionEditorHost_fn, hideDimmingOverlay_fn, showHeaderFooterBorder_fn, hideHeaderFooterBorder_fn, _instances, _options, _editor3, _visibleHost, _viewportHost, _painterHost, _selectionOverlay2, _hiddenHost, _layoutOptions, _layoutState, _domPainter, _dragHandlerCleanup, _layoutError, _layoutErrorState, _errorBanner, _errorBannerMessage, _telemetryEmitter, _renderScheduled, _pendingDocChange, _isRerendering, _selectionUpdateScheduled, _remoteCursorUpdateScheduled, _rafHandle, _editorListeners, _sectionMetadata, _documentMode, _inputBridge, _trackedChangesMode, _trackedChangesEnabled, _trackedChangesOverrides, _headerFooterManager, _headerFooterAdapter, _headerFooterIdentifier, _multiSectionIdentifier, _headerLayoutResults, _footerLayoutResults, _headerLayoutsByRId, _footerLayoutsByRId, _headerDecorationProvider, _footerDecorationProvider, _headerFooterManagerCleanups, _headerRegions, _footerRegions, _session, _activeHeaderFooterEditor, _overlayManager, _hoverOverlay, _hoverTooltip, _modeBanner, _ariaLiveRegion, _hoverRegion, _clickCount, _lastClickTime, _lastClickPosition, _lastSelectedImageBlockId, _dragAnchor, _isDragging, _dragExtensionMode, _remoteCursorState, _remoteCursorDirty, _remoteCursorOverlay, _localSelectionLayer, _awarenessCleanup, _scrollCleanup, _remoteCursorRafHandle, _scrollTimeout, _PresentationEditor_instances, aggregateLayoutBounds_fn, safeCleanup_fn, setupEditorListeners_fn, setupCollaborationCursors_fn, normalizeAwarenessStates_fn, getFallbackColor_fn, getValidatedColor_fn, scheduleRemoteCursorUpdate_fn, scheduleRemoteCursorReRender_fn, updateRemoteCursors_fn, renderRemoteCursors_fn, renderRemoteCaret_fn, renderRemoteCursorLabel_fn, renderRemoteSelection_fn, setupPointerHandlers_fn, setupDragHandlers_fn, setupInputBridge_fn, initHeaderFooterRegistry_fn, _handlePointerDown, getFirstTextPosition_fn, registerPointerClick_fn, selectWordAt_fn, selectParagraphAt_fn, calculateExtendedSelection_fn, isWordCharacter_fn, _handlePointerMove, _handlePointerLeave, _handlePointerUp, _handleDragOver, _handleDrop, _handleDoubleClick, _handleKeyDown, focusHeaderFooterShortcut_fn, scheduleRerender_fn, flushRerenderQueue_fn, rerender_fn, ensurePainter_fn, scheduleSelectionUpdate_fn, updateSelection_fn, resolveLayoutOptions_fn, buildHeaderFooterInput_fn, computeHeaderFooterConstraints_fn, layoutPerRIdHeaderFooters_fn, updateDecorationProviders_fn, createDecorationProvider_fn, findHeaderFooterPageForPageNumber_fn, computeDecorationBox_fn, rebuildHeaderFooterRegions_fn, hitTestHeaderFooterRegion_fn, pointInRegion_fn, activateHeaderFooterRegion_fn, enterHeaderFooterMode_fn, exitHeaderFooterMode_fn, getActiveDomTarget_fn, emitHeaderFooterModeChanged_fn, emitHeaderFooterEditingContext_fn, updateAwarenessSession_fn, updateModeBanner_fn, announce_fn, validateHeaderFooterEditPermission_fn, emitHeaderFooterEditBlocked_fn, resolveDescriptorForRegion_fn, createDefaultHeaderFooter_fn, getPageElement_fn, scrollPageIntoView_fn, waitForPageMount_fn, getBodyPageHeight_fn, getHeaderFooterPageHeight_fn, renderSelectionRects_fn, renderHoverRegion_fn, clearHoverRegion_fn, renderCaretOverlay_fn, getHeaderFooterContext_fn, computeHeaderFooterSelectionRects_fn, syncTrackedChangesPreferences_fn, deriveTrackedChangesMode_fn, deriveTrackedChangesEnabled_fn, getTrackChangesPluginState_fn, computeDefaultLayoutDefaults_fn, parseColumns_fn, inchesToPx_fn, applyZoom_fn, createLayoutMetrics_fn, convertPageLocalToOverlayCoords_fn, normalizeClientPoint_fn, computeCaretLayoutRect_fn, computeCaretLayoutRectFromDOM_fn, computeTableCaretLayoutRect_fn, findLineContainingPos_fn, lineHeightBeforeIndex_fn, getCurrentPageIndex_fn, findRegionForPage_fn, handleLayoutError_fn, decorateError_fn, showLayoutErrorBanner_fn, dismissErrorBanner_fn, createHiddenHost_fn, _windowRoot, _layoutSurfaces, _getTargetDom, _isEditable, _onTargetChanged, _listeners, _currentTarget, _destroyed, _useWindowFallback, _PresentationInputBridge_instances, addListener_fn, dispatchToTarget_fn, forwardKeyboardEvent_fn, forwardTextEvent_fn, forwardCompositionEvent_fn, forwardContextMenu_fn, isEventOnActiveTarget_fn, shouldSkipSurface_fn, isInLayoutSurface_fn, getListenerTargets_fn, isPlainCharacterKey_fn, _DocumentSectionView_instances, init_fn2, addToolTip_fn, _ParagraphNodeView_instances, checkShouldUpdate_fn, updateHTMLAttributes_fn, updateDOMStyles_fn, resolveNeighborParagraphProperties_fn, updateListStyles_fn, initList_fn, checkIsList_fn, createMarker_fn, createSeparator_fn, calculateTabSeparatorStyle_fn, calculateMarkerStyle_fn, removeList_fn, getParagraphContext_fn, scheduleAnimation_fn, cancelScheduledAnimation_fn, _FieldAnnotationView_instances, createAnnotation_fn, _AutoPageNumberNodeView_instances, renderDom_fn, scheduleUpdateNodeStyle_fn, _VectorShapeView_instances, ensureParentPositioned_fn, _ShapeGroupView_instances, ensureParentPositioned_fn2;
13
13
  import * as Y from "yjs";
14
14
  import { UndoManager, Item as Item$1, ContentType, Text as Text$1, XmlElement, encodeStateAsUpdate } from "yjs";
15
- import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as htmlHandler, E as ReplaceStep, G as twipsToInches, H as inchesToTwips, I as ptToTwips, J as getResolvedParagraphProperties, K as linesToTwips, L as changeListLevel, O as findParentNode, Q as isList, U as updateNumberingProperties, V as ListHelpers, W as isMacOS, X as isIOS, Y as getSchemaTypeByName, Z as inputRulesPlugin, _ as TrackDeleteMarkName, $ as TrackInsertMarkName, a0 as v4, a1 as TrackFormatMarkName, a2 as comments_module_events, a3 as findMark, a4 as objectIncludes, a5 as AddMarkStep, a6 as RemoveMarkStep, a7 as twipsToLines, a8 as pixelsToTwips, a9 as helpers, aa as posToDOMRect, ab as CommandService, ac as SuperConverter, ad as createDocument, ae as createDocFromMarkdown, af as createDocFromHTML, ag as EditorState, ah as isActive, ai as unflattenListsInHtml, aj as resolveParagraphProperties, ak as _getReferencedTableStyles, al as parseSizeUnit, am as minMax, an as updateDOMAttributes, ao as findChildren$5, ap as generateRandomSigned32BitIntStrId, aq as decodeRPrFromMarks, ar as calculateResolvedParagraphProperties, as as encodeCSSFromPPr, at as twipsToPixels$2, au as resolveRunProperties, av as encodeCSSFromRPr, aw as generateOrderedListIndex, ax as docxNumberingHelpers, ay as InputRule, az as convertSizeToCSS, aA as SelectionRange, aB as Transform, aC as findParentNodeClosestToPos, aD as isInTable$1, aE as generateDocxRandomId, aF as insertNewRelationship, aG as inchesToPixels, aH as kebabCase, aI as getUnderlineCssString } from "./converter-U59bT3FO.js";
16
- import { D as DocxZipper } from "./docx-zipper-DSnoGkju.js";
15
+ import { P as PluginKey, a as Plugin, M as Mapping, N as NodeSelection, S as Selection, T as TextSelection, b as Slice, D as DOMSerializer, F as Fragment, c as DOMParser$1, d as Mark$1, e as dropPoint, A as AllSelection, p as process$1, B as Buffer2, f as callOrGet, g as getExtensionConfigField, h as getMarkType, i as getMarksFromSelection, j as getNodeType, k as getSchemaTypeNameByName, l as Schema$1, m as cleanSchemaItem, n as canSplit, o as defaultBlockAt$1, q as liftTarget, r as canJoin, s as joinPoint, t as replaceStep$1, R as ReplaceAroundStep$1, u as isTextSelection, v as getMarkRange, w as isMarkActive, x as isNodeActive, y as deleteProps, z as processContent, C as htmlHandler, E as ReplaceStep, G as twipsToInches, H as inchesToTwips, I as ptToTwips, J as getResolvedParagraphProperties, K as linesToTwips, L as changeListLevel, O as findParentNode, Q as isList, U as updateNumberingProperties, V as ListHelpers, W as isMacOS, X as isIOS, Y as getSchemaTypeByName, Z as inputRulesPlugin, _ as TrackDeleteMarkName, $ as TrackInsertMarkName, a0 as v4, a1 as TrackFormatMarkName, a2 as comments_module_events, a3 as findMark, a4 as objectIncludes, a5 as AddMarkStep, a6 as RemoveMarkStep, a7 as twipsToLines, a8 as pixelsToTwips, a9 as helpers, aa as posToDOMRect, ab as CommandService, ac as SuperConverter, ad as createDocument, ae as createDocFromMarkdown, af as createDocFromHTML, ag as EditorState, ah as isActive, ai as unflattenListsInHtml, aj as resolveParagraphProperties, ak as _getReferencedTableStyles, al as parseSizeUnit, am as minMax, an as updateDOMAttributes, ao as findChildren$5, ap as generateRandomSigned32BitIntStrId, aq as decodeRPrFromMarks, ar as calculateResolvedParagraphProperties, as as encodeCSSFromPPr, at as twipsToPixels$2, au as resolveRunProperties, av as encodeCSSFromRPr, aw as generateOrderedListIndex, ax as docxNumberingHelpers, ay as InputRule, az as convertSizeToCSS, aA as SelectionRange, aB as Transform, aC as findParentNodeClosestToPos, aD as isInTable$1, aE as generateDocxRandomId, aF as insertNewRelationship, aG as inchesToPixels, aH as kebabCase, aI as getUnderlineCssString } from "./converter-CpuOoAUa.js";
16
+ import { D as DocxZipper } from "./docx-zipper-Dk99r397.js";
17
17
  import { ref, computed, createElementBlock, openBlock, withModifiers, Fragment as Fragment$1, renderList, normalizeClass, createCommentVNode, toDisplayString, createElementVNode, createApp } from "vue";
18
18
  var GOOD_LEAF_SIZE = 200;
19
19
  var RopeSequence = function RopeSequence2() {
@@ -13913,7 +13913,7 @@ const isHeadless = (editor) => {
13913
13913
  const shouldSkipNodeView = (editor) => {
13914
13914
  return isHeadless(editor);
13915
13915
  };
13916
- const summaryVersion = "1.0.0-beta.30";
13916
+ const summaryVersion = "1.0.0-beta.32";
13917
13917
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
13918
13918
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
13919
13919
  function mapAttributes(attrs) {
@@ -14705,7 +14705,7 @@ const _Editor = class _Editor extends EventEmitter {
14705
14705
  { default: remarkStringify },
14706
14706
  { default: remarkGfm }
14707
14707
  ] = await Promise.all([
14708
- import("./index-DUzV7kkk.js"),
14708
+ import("./index-SGV4U12y.js"),
14709
14709
  import("./index-DRCvimau.js"),
14710
14710
  import("./index-C_x_N6Uh.js"),
14711
14711
  import("./index-D_sWOSiG.js"),
@@ -14910,7 +14910,7 @@ const _Editor = class _Editor extends EventEmitter {
14910
14910
  * Process collaboration migrations
14911
14911
  */
14912
14912
  processCollaborationMigrations() {
14913
- console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.30");
14913
+ console.debug("[checkVersionMigrations] Current editor version", "1.0.0-beta.32");
14914
14914
  if (!this.options.ydoc) return;
14915
14915
  const metaMap = this.options.ydoc.getMap("meta");
14916
14916
  let docVersion = metaMap.get("version");
@@ -17035,9 +17035,11 @@ const applyMarksToRun = (run, marks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG,
17035
17035
  case TRACK_INSERT_MARK:
17036
17036
  case TRACK_DELETE_MARK:
17037
17037
  case TRACK_FORMAT_MARK: {
17038
- const tracked = buildTrackedChangeMetaFromMark(mark);
17039
- if (tracked) {
17040
- run.trackedChange = selectTrackedChangeMeta(run.trackedChange, tracked);
17038
+ if (!isTabRun2) {
17039
+ const tracked = buildTrackedChangeMetaFromMark(mark);
17040
+ if (tracked) {
17041
+ run.trackedChange = selectTrackedChangeMeta(run.trackedChange, tracked);
17042
+ }
17041
17043
  }
17042
17044
  break;
17043
17045
  }
@@ -20138,7 +20140,27 @@ function handleStructuredContentBlockNode(node, context) {
20138
20140
  blocks.push(block);
20139
20141
  recordBlockKind(block.kind);
20140
20142
  });
20141
- } else if (child.type === "table") ;
20143
+ } else if (child.type === "table") {
20144
+ const tableNodeToBlock2 = converters?.tableNodeToBlock;
20145
+ if (tableNodeToBlock2) {
20146
+ const tableBlock = tableNodeToBlock2(
20147
+ child,
20148
+ nextBlockId,
20149
+ positions,
20150
+ defaultFont,
20151
+ defaultSize,
20152
+ styleContext,
20153
+ trackedChangesConfig,
20154
+ bookmarks,
20155
+ hyperlinkConfig
20156
+ );
20157
+ if (tableBlock) {
20158
+ applySdtMetadataToTableBlock(tableBlock, structuredContentMetadata);
20159
+ blocks.push(tableBlock);
20160
+ recordBlockKind(tableBlock.kind);
20161
+ }
20162
+ }
20163
+ }
20142
20164
  });
20143
20165
  }
20144
20166
  function processParagraphChild(child, sectionMetadata, context, output, converters) {
@@ -20608,6 +20630,65 @@ function imageNodeToRun(node, positions, activeSdt) {
20608
20630
  }
20609
20631
  return run;
20610
20632
  }
20633
+ function fieldAnnotationNodeToRun(node, positions, fieldMetadata) {
20634
+ const attrs = node.attrs ?? {};
20635
+ const rawVariant = attrs.type ?? fieldMetadata?.variant ?? "text";
20636
+ const validVariants = ["text", "image", "signature", "checkbox", "html", "link"];
20637
+ const variant = validVariants.includes(rawVariant) ? rawVariant : "text";
20638
+ const displayLabel = (typeof attrs.displayLabel === "string" ? attrs.displayLabel : void 0) || (typeof attrs.defaultDisplayLabel === "string" ? attrs.defaultDisplayLabel : void 0) || (typeof fieldMetadata?.displayLabel === "string" ? fieldMetadata.displayLabel : void 0) || (typeof fieldMetadata?.defaultDisplayLabel === "string" ? fieldMetadata.defaultDisplayLabel : void 0) || (typeof attrs.alias === "string" ? attrs.alias : void 0) || (typeof fieldMetadata?.alias === "string" ? fieldMetadata.alias : void 0) || "";
20639
+ const run = {
20640
+ kind: "fieldAnnotation",
20641
+ variant,
20642
+ displayLabel
20643
+ };
20644
+ const fieldId = typeof attrs.fieldId === "string" ? attrs.fieldId : fieldMetadata?.fieldId;
20645
+ if (fieldId) run.fieldId = fieldId;
20646
+ const fieldType = typeof attrs.fieldType === "string" ? attrs.fieldType : fieldMetadata?.fieldType;
20647
+ if (fieldType) run.fieldType = fieldType;
20648
+ const fieldColor = typeof attrs.fieldColor === "string" ? attrs.fieldColor : fieldMetadata?.fieldColor;
20649
+ if (fieldColor) run.fieldColor = fieldColor;
20650
+ const borderColor = typeof attrs.borderColor === "string" ? attrs.borderColor : fieldMetadata?.borderColor;
20651
+ if (borderColor) run.borderColor = borderColor;
20652
+ const highlighted = attrs.highlighted ?? fieldMetadata?.highlighted;
20653
+ if (highlighted === false) run.highlighted = false;
20654
+ if (attrs.hidden === true || fieldMetadata?.hidden === true) run.hidden = true;
20655
+ const visibility = attrs.visibility ?? fieldMetadata?.visibility;
20656
+ if (visibility === "hidden") run.visibility = "hidden";
20657
+ const imageSrc = typeof attrs.imageSrc === "string" ? attrs.imageSrc : fieldMetadata?.imageSrc;
20658
+ if (imageSrc) run.imageSrc = imageSrc;
20659
+ const linkUrl = typeof attrs.linkUrl === "string" ? attrs.linkUrl : fieldMetadata?.linkUrl;
20660
+ if (linkUrl) run.linkUrl = linkUrl;
20661
+ const rawHtml = attrs.rawHtml ?? fieldMetadata?.rawHtml;
20662
+ if (typeof rawHtml === "string") run.rawHtml = rawHtml;
20663
+ const size = attrs.size ?? fieldMetadata?.size;
20664
+ if (size && (typeof size.width === "number" || typeof size.height === "number")) {
20665
+ run.size = {
20666
+ width: typeof size.width === "number" ? size.width : void 0,
20667
+ height: typeof size.height === "number" ? size.height : void 0
20668
+ };
20669
+ }
20670
+ const fontFamily = attrs.fontFamily ?? fieldMetadata?.fontFamily;
20671
+ if (typeof fontFamily === "string") run.fontFamily = fontFamily;
20672
+ const fontSize = attrs.fontSize ?? fieldMetadata?.fontSize;
20673
+ if (typeof fontSize === "string" || typeof fontSize === "number") run.fontSize = fontSize;
20674
+ const textColor = attrs.textColor ?? fieldMetadata?.textColor;
20675
+ if (typeof textColor === "string") run.textColor = textColor;
20676
+ const textHighlight = attrs.textHighlight ?? fieldMetadata?.textHighlight;
20677
+ if (typeof textHighlight === "string") run.textHighlight = textHighlight;
20678
+ const formatting = fieldMetadata?.formatting;
20679
+ if (attrs.bold === true || formatting?.bold === true) run.bold = true;
20680
+ if (attrs.italic === true || formatting?.italic === true) run.italic = true;
20681
+ if (attrs.underline === true || formatting?.underline === true) run.underline = true;
20682
+ const pos = positions.get(node);
20683
+ if (pos) {
20684
+ run.pmStart = pos.start;
20685
+ run.pmEnd = pos.end;
20686
+ }
20687
+ if (fieldMetadata) {
20688
+ run.sdt = fieldMetadata;
20689
+ }
20690
+ return run;
20691
+ }
20611
20692
  const isTextRun$1 = (run) => run.kind !== "tab";
20612
20693
  const dataAttrsCompatible = (a, b) => {
20613
20694
  const aAttrs = a.dataAttrs;
@@ -20903,28 +20984,20 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
20903
20984
  }
20904
20985
  if (node.type === "fieldAnnotation") {
20905
20986
  const fieldMetadata = resolveNodeSdtMetadata(node, "fieldAnnotation");
20987
+ let contentText;
20906
20988
  if (Array.isArray(node.content) && node.content.length > 0) {
20907
- node.content.forEach((child) => visitNode(child, inheritedMarks, fieldMetadata ?? activeSdt, activeRunStyleId));
20908
- } else {
20909
- const nodeAttrs = typeof node.attrs === "object" && node.attrs !== null ? node.attrs : {};
20910
- const label = (typeof nodeAttrs.displayLabel === "string" ? nodeAttrs.displayLabel : void 0) || (typeof nodeAttrs.defaultDisplayLabel === "string" ? nodeAttrs.defaultDisplayLabel : void 0) || (typeof nodeAttrs.alias === "string" ? nodeAttrs.alias : void 0) || "";
20911
- if (label && typeof label === "string") {
20912
- const run = textNodeToRun(
20913
- { type: "text", text: label },
20914
- positions,
20915
- defaultFont,
20916
- defaultSize,
20917
- inheritedMarks,
20918
- fieldMetadata ?? activeSdt,
20919
- hyperlinkConfig,
20920
- themeColors
20921
- );
20922
- const inlineStyleId = getInlineStyleId(inheritedMarks);
20923
- applyRunStyles2(run, inlineStyleId, activeRunStyleId);
20924
- applyBaseRunDefaults(run, baseRunDefaults, defaultFont, defaultSize);
20925
- currentRuns.push(run);
20926
- }
20989
+ const extractText = (n) => {
20990
+ if (n.type === "text" && typeof n.text === "string") return n.text;
20991
+ if (Array.isArray(n.content)) {
20992
+ return n.content.map(extractText).join("");
20993
+ }
20994
+ return "";
20995
+ };
20996
+ contentText = node.content.map(extractText).join("");
20927
20997
  }
20998
+ const nodeForRun = contentText && contentText.length > 0 ? { ...node, attrs: { ...node.attrs ?? {}, displayLabel: contentText } } : node;
20999
+ const run = fieldAnnotationNodeToRun(nodeForRun, positions, fieldMetadata);
21000
+ currentRuns.push(run);
20928
21001
  return;
20929
21002
  }
20930
21003
  if (node.type === "pageReference") {
@@ -21761,9 +21834,9 @@ const extractTableStyleParagraphProps = (styleId, docx) => {
21761
21834
  }
21762
21835
  const attrs = spacingEl.attributes;
21763
21836
  const spacing = {};
21764
- const before = parseIntSafe(attrs["w:before"]);
21765
- const after = parseIntSafe(attrs["w:after"]);
21766
- const line = parseIntSafe(attrs["w:line"]);
21837
+ const before = parseIntSafe$1(attrs["w:before"]);
21838
+ const after = parseIntSafe$1(attrs["w:after"]);
21839
+ const line = parseIntSafe$1(attrs["w:line"]);
21767
21840
  const rawLineRule = attrs["w:lineRule"];
21768
21841
  const lineRule = rawLineRule === "auto" || rawLineRule === "exact" || rawLineRule === "atLeast" ? rawLineRule : void 0;
21769
21842
  if (before != null) spacing.before = twipsToPx$1(before);
@@ -21778,11 +21851,11 @@ const extractTableStyleParagraphProps = (styleId, docx) => {
21778
21851
  if (lineRule) spacing.lineRule = lineRule;
21779
21852
  const result = Object.keys(spacing).length > 0 ? { spacing } : void 0;
21780
21853
  return result;
21781
- } catch (err) {
21854
+ } catch {
21782
21855
  return void 0;
21783
21856
  }
21784
21857
  };
21785
- const parseIntSafe = (value) => {
21858
+ const parseIntSafe$1 = (value) => {
21786
21859
  if (value == null) return void 0;
21787
21860
  const num = typeof value === "number" ? value : parseInt(String(value), 10);
21788
21861
  return Number.isFinite(num) ? num : void 0;
@@ -22434,7 +22507,7 @@ function getMeasurementContext() {
22434
22507
  return measurementCtx;
22435
22508
  }
22436
22509
  function getRunFontString(run) {
22437
- if (run.kind === "tab" || run.kind === "lineBreak" || run.kind === "break" || "src" in run) {
22510
+ if (run.kind === "tab" || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" || "src" in run) {
22438
22511
  return "normal normal 16px Arial";
22439
22512
  }
22440
22513
  const style = run.italic ? "italic" : "normal";
@@ -22465,6 +22538,10 @@ function sliceRunsForLine$1(block, line) {
22465
22538
  result.push(run);
22466
22539
  continue;
22467
22540
  }
22541
+ if (run.kind === "fieldAnnotation") {
22542
+ result.push(run);
22543
+ continue;
22544
+ }
22468
22545
  const text = run.text ?? "";
22469
22546
  const isFirstRun = runIndex === line.fromRun;
22470
22547
  const isLastRun = runIndex === line.toRun;
@@ -22498,7 +22575,8 @@ function measureCharacterX(block, line, charOffset) {
22498
22575
  1,
22499
22576
  runs2.reduce((sum, run) => {
22500
22577
  if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
22501
- if ("src" in run || run.kind === "lineBreak" || run.kind === "break") return sum;
22578
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation")
22579
+ return sum;
22502
22580
  return sum + (run.text ?? "").length;
22503
22581
  }, 0)
22504
22582
  );
@@ -22519,7 +22597,7 @@ function measureCharacterX(block, line, charOffset) {
22519
22597
  currentCharOffset += runLength2;
22520
22598
  continue;
22521
22599
  }
22522
- const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
22600
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text ?? "";
22523
22601
  const runLength = text.length;
22524
22602
  if (currentCharOffset + runLength >= charOffset) {
22525
22603
  const offsetInRun = charOffset - currentCharOffset;
@@ -22562,7 +22640,7 @@ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
22562
22640
  if (isTabRun$1(run)) {
22563
22641
  return segmentBaseX + (offsetInSegment > 0 ? segment.width ?? 0 : 0);
22564
22642
  }
22565
- if ("src" in run || run.kind === "lineBreak" || run.kind === "break") {
22643
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation") {
22566
22644
  return segmentBaseX + (offsetInSegment >= segmentChars ? segment.width ?? 0 : 0);
22567
22645
  }
22568
22646
  const text = run.text ?? "";
@@ -22577,6 +22655,38 @@ function measureCharacterXSegmentBased(block, line, charOffset, ctx2) {
22577
22655
  }
22578
22656
  return line.width;
22579
22657
  }
22658
+ function charOffsetToPm(block, line, charOffset, fallbackPmStart) {
22659
+ if (!Number.isFinite(charOffset) || !Number.isFinite(fallbackPmStart)) {
22660
+ console.warn("[charOffsetToPm] Invalid input:", { charOffset, fallbackPmStart });
22661
+ return fallbackPmStart;
22662
+ }
22663
+ const safeCharOffset = Math.max(0, charOffset);
22664
+ if (block.kind !== "paragraph") {
22665
+ return fallbackPmStart + safeCharOffset;
22666
+ }
22667
+ const runs = sliceRunsForLine$1(block, line);
22668
+ let cursor = 0;
22669
+ let lastPm = fallbackPmStart;
22670
+ for (const run of runs) {
22671
+ const isTab = isTabRun$1(run);
22672
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text ?? "";
22673
+ const runLength = isTab ? TAB_CHAR_LENGTH : text.length;
22674
+ const runPmStart = typeof run.pmStart === "number" ? run.pmStart : null;
22675
+ const runPmEnd = typeof run.pmEnd === "number" ? run.pmEnd : runPmStart != null ? runPmStart + runLength : null;
22676
+ if (runPmStart != null) {
22677
+ lastPm = runPmStart;
22678
+ }
22679
+ if (safeCharOffset <= cursor + runLength) {
22680
+ const offsetInRun = Math.max(0, safeCharOffset - cursor);
22681
+ return runPmStart != null ? runPmStart + Math.min(offsetInRun, runLength) : fallbackPmStart + safeCharOffset;
22682
+ }
22683
+ if (runPmEnd != null) {
22684
+ lastPm = runPmEnd;
22685
+ }
22686
+ cursor += runLength;
22687
+ }
22688
+ return lastPm;
22689
+ }
22580
22690
  function findCharacterAtX(block, line, x, pmStart) {
22581
22691
  const ctx2 = getMeasurementContext();
22582
22692
  if (!ctx2) {
@@ -22585,15 +22695,17 @@ function findCharacterAtX(block, line, x, pmStart) {
22585
22695
  1,
22586
22696
  runs2.reduce((sum, run) => {
22587
22697
  if (isTabRun$1(run)) return sum + TAB_CHAR_LENGTH;
22588
- if ("src" in run || run.kind === "lineBreak" || run.kind === "break") return sum;
22698
+ if ("src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation")
22699
+ return sum;
22589
22700
  return sum + (run.text ?? "").length;
22590
22701
  }, 0)
22591
22702
  );
22592
22703
  const ratio = Math.max(0, Math.min(1, x / line.width));
22593
22704
  const charOffset = Math.round(ratio * charsInLine);
22705
+ const pmPosition2 = charOffsetToPm(block, line, charOffset, pmStart);
22594
22706
  return {
22595
22707
  charOffset,
22596
- pmPosition: pmStart + charOffset
22708
+ pmPosition: pmPosition2
22597
22709
  };
22598
22710
  }
22599
22711
  const runs = sliceRunsForLine$1(block, line);
@@ -22609,18 +22721,17 @@ function findCharacterAtX(block, line, x, pmStart) {
22609
22721
  const midpoint = startX + tabWidth / 2;
22610
22722
  const offsetInRun = safeX < midpoint ? 0 : TAB_CHAR_LENGTH;
22611
22723
  const charOffset = currentCharOffset + offsetInRun;
22612
- const pmBase = run.pmStart ?? pmStart + currentCharOffset;
22613
- const pmPosition = pmBase + offsetInRun;
22724
+ const pmPosition2 = charOffsetToPm(block, line, charOffset, pmStart);
22614
22725
  return {
22615
22726
  charOffset,
22616
- pmPosition
22727
+ pmPosition: pmPosition2
22617
22728
  };
22618
22729
  }
22619
22730
  currentX = endX;
22620
22731
  currentCharOffset += TAB_CHAR_LENGTH;
22621
22732
  continue;
22622
22733
  }
22623
- const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
22734
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text ?? "";
22624
22735
  const runLength = text.length;
22625
22736
  if (runLength === 0) continue;
22626
22737
  ctx2.font = getRunFontString(run);
@@ -22630,9 +22741,10 @@ function findCharacterAtX(block, line, x, pmStart) {
22630
22741
  const charX = currentX + measured2.width + computeLetterSpacingWidth(run, i, runLength);
22631
22742
  if (charX >= safeX) {
22632
22743
  if (i === 0) {
22744
+ const pmPosition3 = charOffsetToPm(block, line, currentCharOffset, pmStart);
22633
22745
  return {
22634
22746
  charOffset: currentCharOffset,
22635
- pmPosition: pmStart + currentCharOffset
22747
+ pmPosition: pmPosition3
22636
22748
  };
22637
22749
  }
22638
22750
  const prevText = text.slice(0, i - 1);
@@ -22641,9 +22753,10 @@ function findCharacterAtX(block, line, x, pmStart) {
22641
22753
  const distToPrev = Math.abs(safeX - prevX);
22642
22754
  const distToCurrent = Math.abs(safeX - charX);
22643
22755
  const charOffset = distToPrev < distToCurrent ? currentCharOffset + i - 1 : currentCharOffset + i;
22756
+ const pmPosition2 = charOffsetToPm(block, line, charOffset, pmStart);
22644
22757
  return {
22645
22758
  charOffset,
22646
- pmPosition: pmStart + charOffset
22759
+ pmPosition: pmPosition2
22647
22760
  };
22648
22761
  }
22649
22762
  }
@@ -22651,13 +22764,14 @@ function findCharacterAtX(block, line, x, pmStart) {
22651
22764
  currentX += measured.width + computeLetterSpacingWidth(run, runLength, runLength);
22652
22765
  currentCharOffset += runLength;
22653
22766
  }
22767
+ const pmPosition = charOffsetToPm(block, line, currentCharOffset, pmStart);
22654
22768
  return {
22655
22769
  charOffset: currentCharOffset,
22656
- pmPosition: pmStart + currentCharOffset
22770
+ pmPosition
22657
22771
  };
22658
22772
  }
22659
22773
  const computeLetterSpacingWidth = (run, precedingChars, runLength) => {
22660
- if (isTabRun$1(run) || "src" in run || !("letterSpacing" in run) || !run.letterSpacing) {
22774
+ if (isTabRun$1(run) || "src" in run || run.kind === "fieldAnnotation" || !("letterSpacing" in run) || !run.letterSpacing) {
22661
22775
  return 0;
22662
22776
  }
22663
22777
  const maxGaps = Math.max(runLength - 1, 0);
@@ -22754,6 +22868,17 @@ function clickToPositionDom(domContainer, clientX, clientY) {
22754
22868
  pmStart: fragmentEl.dataset.pmStart,
22755
22869
  pmEnd: fragmentEl.dataset.pmEnd
22756
22870
  });
22871
+ const hitChainLine = hitChain.find(
22872
+ (el) => el.classList?.contains?.(CLASS_NAMES$1.line) && el.dataset?.pmStart !== void 0 && el.dataset?.pmEnd !== void 0
22873
+ );
22874
+ if (hitChainLine) {
22875
+ log("Using hit chain line directly:", {
22876
+ pmStart: hitChainLine.dataset.pmStart,
22877
+ pmEnd: hitChainLine.dataset.pmEnd
22878
+ });
22879
+ const result2 = processLineElement(hitChainLine, viewX);
22880
+ return result2;
22881
+ }
22757
22882
  const result = processFragment(fragmentEl, viewX, viewY);
22758
22883
  return result;
22759
22884
  }
@@ -22819,7 +22944,82 @@ function processFragment(fragmentEl, viewX, viewY) {
22819
22944
  if (!Number.isFinite(lineStart) || !Number.isFinite(lineEnd)) {
22820
22945
  return null;
22821
22946
  }
22822
- const spanEls = Array.from(lineEl.querySelectorAll("span, a"));
22947
+ const spanEls = Array.from(lineEl.querySelectorAll("span, a")).filter(
22948
+ (el) => el.dataset.pmStart !== void 0 && el.dataset.pmEnd !== void 0
22949
+ );
22950
+ log(
22951
+ "Spans/anchors in line:",
22952
+ spanEls.map((el, i) => {
22953
+ const rect = el.getBoundingClientRect();
22954
+ return {
22955
+ index: i,
22956
+ tag: el.tagName,
22957
+ pmStart: el.dataset.pmStart,
22958
+ pmEnd: el.dataset.pmEnd,
22959
+ text: el.textContent?.substring(0, 20) + (el.textContent && el.textContent.length > 20 ? "..." : ""),
22960
+ visibility: el.style.visibility,
22961
+ rect: { left: rect.left, right: rect.right, width: rect.width }
22962
+ };
22963
+ })
22964
+ );
22965
+ if (spanEls.length === 0) {
22966
+ return lineStart;
22967
+ }
22968
+ const firstRect = spanEls[0].getBoundingClientRect();
22969
+ if (viewX <= firstRect.left) {
22970
+ return lineStart;
22971
+ }
22972
+ const lastRect = spanEls[spanEls.length - 1].getBoundingClientRect();
22973
+ if (viewX >= lastRect.right) {
22974
+ return lineEnd;
22975
+ }
22976
+ const targetEl = findSpanAtX(spanEls, viewX);
22977
+ if (!targetEl) {
22978
+ return lineStart;
22979
+ }
22980
+ const spanStart = Number(targetEl.dataset.pmStart ?? "NaN");
22981
+ const spanEnd = Number(targetEl.dataset.pmEnd ?? "NaN");
22982
+ const targetRect = targetEl.getBoundingClientRect();
22983
+ log("Target element:", {
22984
+ tag: targetEl.tagName,
22985
+ pmStart: spanStart,
22986
+ pmEnd: spanEnd,
22987
+ text: targetEl.textContent?.substring(0, 30),
22988
+ visibility: targetEl.style.visibility,
22989
+ rect: { left: targetRect.left, right: targetRect.right, width: targetRect.width },
22990
+ pageX: viewX,
22991
+ pageY: viewY
22992
+ });
22993
+ if (!Number.isFinite(spanStart) || !Number.isFinite(spanEnd)) {
22994
+ return null;
22995
+ }
22996
+ const firstChild = targetEl.firstChild;
22997
+ if (!firstChild || firstChild.nodeType !== Node.TEXT_NODE || !firstChild.textContent) {
22998
+ const elRect = targetEl.getBoundingClientRect();
22999
+ const closerToLeft = Math.abs(viewX - elRect.left) <= Math.abs(viewX - elRect.right);
23000
+ const snapPos = closerToLeft ? spanStart : spanEnd;
23001
+ return snapPos;
23002
+ }
23003
+ const textNode = firstChild;
23004
+ const charIndex = findCharIndexAtX(textNode, targetEl, viewX);
23005
+ const pos = spanStart + charIndex;
23006
+ return pos;
23007
+ }
23008
+ function processLineElement(lineEl, viewX) {
23009
+ const lineStart = Number(lineEl.dataset.pmStart ?? "NaN");
23010
+ const lineEnd = Number(lineEl.dataset.pmEnd ?? "NaN");
23011
+ const lineRect = lineEl.getBoundingClientRect();
23012
+ log("processLineElement:", {
23013
+ pmStart: lineStart,
23014
+ pmEnd: lineEnd,
23015
+ rect: { top: lineRect.top, bottom: lineRect.bottom, left: lineRect.left, right: lineRect.right }
23016
+ });
23017
+ if (!Number.isFinite(lineStart) || !Number.isFinite(lineEnd)) {
23018
+ return null;
23019
+ }
23020
+ const spanEls = Array.from(lineEl.querySelectorAll("span, a")).filter(
23021
+ (el) => el.dataset.pmStart !== void 0 && el.dataset.pmEnd !== void 0
23022
+ );
22823
23023
  log(
22824
23024
  "Spans/anchors in line:",
22825
23025
  spanEls.map((el, i) => {
@@ -25766,7 +25966,7 @@ const hashRuns = (block) => {
25766
25966
  return `img:${srcHash}:${imgRun.width}x${imgRun.height}`;
25767
25967
  }
25768
25968
  const text = normalizeText(
25769
- "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? ""
25969
+ "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text ?? ""
25770
25970
  );
25771
25971
  const bold = "bold" in run ? run.bold : false;
25772
25972
  const italic = "italic" in run ? run.italic : false;
@@ -26425,6 +26625,88 @@ async function layoutHeaderFooterWithCache(sections, constraints, measureBlock2,
26425
26625
  }
26426
26626
  return result;
26427
26627
  }
26628
+ function findWordBoundaries(blocks, pos) {
26629
+ const blockInfo = findBlockAtPosition(blocks, pos);
26630
+ if (!blockInfo) return null;
26631
+ const { block, localPos } = blockInfo;
26632
+ if (block.kind !== "paragraph") return null;
26633
+ const { text, pmStart } = extractBlockText(block);
26634
+ if (text.length === 0) return null;
26635
+ const clampedPos = Math.max(0, Math.min(localPos, text.length));
26636
+ let wordStart = clampedPos;
26637
+ while (wordStart > 0 && isWordChar(text[wordStart - 1])) {
26638
+ wordStart--;
26639
+ }
26640
+ let wordEnd = clampedPos;
26641
+ while (wordEnd < text.length && isWordChar(text[wordEnd])) {
26642
+ wordEnd++;
26643
+ }
26644
+ if (wordStart === wordEnd) {
26645
+ while (wordStart > 0 && isWhitespace(text[wordStart - 1])) {
26646
+ wordStart--;
26647
+ }
26648
+ while (wordEnd < text.length && isWhitespace(text[wordEnd])) {
26649
+ wordEnd++;
26650
+ }
26651
+ if (wordStart === wordEnd) {
26652
+ return null;
26653
+ }
26654
+ }
26655
+ return {
26656
+ from: pmStart + wordStart,
26657
+ to: pmStart + wordEnd
26658
+ };
26659
+ }
26660
+ function findParagraphBoundaries(blocks, pos) {
26661
+ const blockInfo = findBlockAtPosition(blocks, pos);
26662
+ if (!blockInfo) return null;
26663
+ const { block } = blockInfo;
26664
+ if (block.kind === "paragraph") {
26665
+ const { pmStart, pmEnd } = extractBlockText(block);
26666
+ return { from: pmStart, to: pmEnd };
26667
+ }
26668
+ if (block.kind === "image") {
26669
+ return { from: pos, to: pos + 1 };
26670
+ }
26671
+ return null;
26672
+ }
26673
+ function extractBlockText(block) {
26674
+ if (block.kind !== "paragraph") {
26675
+ return { text: "", pmStart: 0, pmEnd: 0 };
26676
+ }
26677
+ let text = "";
26678
+ let pmStart = Infinity;
26679
+ let pmEnd = 0;
26680
+ for (const run of block.runs) {
26681
+ text += "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text;
26682
+ if (run.pmStart !== void 0) {
26683
+ pmStart = Math.min(pmStart, run.pmStart);
26684
+ }
26685
+ if (run.pmEnd !== void 0) {
26686
+ pmEnd = Math.max(pmEnd, run.pmEnd);
26687
+ }
26688
+ }
26689
+ if (pmStart === Infinity) pmStart = 0;
26690
+ if (pmEnd === 0 && text.length > 0) pmEnd = pmStart + text.length;
26691
+ return { text, pmStart, pmEnd };
26692
+ }
26693
+ function findBlockAtPosition(blocks, pos) {
26694
+ for (const block of blocks) {
26695
+ if (block.kind === "paragraph") {
26696
+ const { pmStart, pmEnd } = extractBlockText(block);
26697
+ if (pos >= pmStart && pos <= pmEnd) {
26698
+ return { block, localPos: pos - pmStart };
26699
+ }
26700
+ }
26701
+ }
26702
+ return null;
26703
+ }
26704
+ function isWordChar(char) {
26705
+ return /[\p{L}\p{N}_]/u.test(char);
26706
+ }
26707
+ function isWhitespace(char) {
26708
+ return /\s/.test(char);
26709
+ }
26428
26710
  let canvas = null;
26429
26711
  let ctx = null;
26430
26712
  function getCtx() {
@@ -26446,7 +26728,7 @@ function fontString(run) {
26446
26728
  return `${italic}${bold}${size}px ${family}`.trim();
26447
26729
  }
26448
26730
  function runText(run) {
26449
- return "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
26731
+ return "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text ?? "";
26450
26732
  }
26451
26733
  function measureRunSliceWidth(run, fromChar, toChar) {
26452
26734
  const context = getCtx();
@@ -26608,7 +26890,7 @@ const paragraphBlocksEqual = (a, b) => {
26608
26890
  for (let i = 0; i < a.runs.length; i += 1) {
26609
26891
  const runA = a.runs[i];
26610
26892
  const runB = b.runs[i];
26611
- if (("src" in runA || runA.kind === "lineBreak" || runA.kind === "break" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" || runB.kind === "break" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
26893
+ if (("src" in runA || runA.kind === "lineBreak" || runA.kind === "break" || runA.kind === "fieldAnnotation" ? "" : runA.text) !== ("src" in runB || runB.kind === "lineBreak" || runB.kind === "break" || runB.kind === "fieldAnnotation" ? "" : runB.text) || ("bold" in runA ? runA.bold : false) !== ("bold" in runB ? runB.bold : false) || ("italic" in runA ? runA.italic : false) !== ("italic" in runB ? runB.italic : false) || ("color" in runA ? runA.color : void 0) !== ("color" in runB ? runB.color : void 0) || getTrackedChangeKey(runA) !== getTrackedChangeKey(runB)) {
26612
26894
  return false;
26613
26895
  }
26614
26896
  }
@@ -26728,7 +27010,7 @@ function computeHeaderFooterContentHash(blocks) {
26728
27010
  parts.push(block.id);
26729
27011
  if (block.kind === "paragraph") {
26730
27012
  for (const run of block.runs) {
26731
- if (!("src" in run) && run.kind !== "lineBreak" && run.kind !== "break") {
27013
+ if (!("src" in run) && run.kind !== "lineBreak" && run.kind !== "break" && run.kind !== "fieldAnnotation") {
26732
27014
  parts.push(run.text ?? "");
26733
27015
  }
26734
27016
  if ("bold" in run && run.bold) parts.push("b");
@@ -27213,11 +27495,266 @@ var Priority = /* @__PURE__ */ ((Priority2) => {
27213
27495
  /** P3: Heavy debounce for full document layout */
27214
27496
  [Priority.P3]: 150
27215
27497
  });
27498
+ const DEFAULT_MIME_TYPE$1 = "application/x-field-annotation";
27499
+ const LEGACY_MIME_TYPE = "fieldAnnotation";
27500
+ function parseIntSafe(value) {
27501
+ if (!value) return void 0;
27502
+ const parsed = parseInt(value, 10);
27503
+ return Number.isFinite(parsed) ? parsed : void 0;
27504
+ }
27505
+ function extractFieldAnnotationData(element) {
27506
+ const dataset = element.dataset;
27507
+ const attributes = {};
27508
+ for (const key2 in dataset) {
27509
+ const value = dataset[key2];
27510
+ if (value !== void 0) {
27511
+ attributes[key2] = value;
27512
+ }
27513
+ }
27514
+ return {
27515
+ fieldId: dataset.fieldId,
27516
+ fieldType: dataset.fieldType,
27517
+ variant: dataset.variant ?? dataset.type,
27518
+ displayLabel: dataset.displayLabel,
27519
+ pmStart: parseIntSafe(dataset.pmStart),
27520
+ pmEnd: parseIntSafe(dataset.pmEnd),
27521
+ attributes
27522
+ };
27523
+ }
27524
+ class DragHandler {
27525
+ /**
27526
+ * Creates a new DragHandler instance.
27527
+ *
27528
+ * @param container - The DOM container element (typically .superdoc-layout)
27529
+ * @param config - Configuration options and callbacks
27530
+ */
27531
+ constructor(container, config = {}) {
27532
+ this.container = container;
27533
+ this.config = config;
27534
+ this.mimeType = config.mimeType ?? DEFAULT_MIME_TYPE$1;
27535
+ this.boundHandlers = {
27536
+ dragstart: this.handleDragStart.bind(this),
27537
+ dragover: this.handleDragOver.bind(this),
27538
+ drop: this.handleDrop.bind(this),
27539
+ dragend: this.handleDragEnd.bind(this),
27540
+ dragleave: this.handleDragLeave.bind(this)
27541
+ };
27542
+ this.windowDragoverHandler = this.handleWindowDragOver.bind(this);
27543
+ this.windowDropHandler = this.handleWindowDrop.bind(this);
27544
+ this.attachListeners();
27545
+ }
27546
+ /**
27547
+ * Attaches event listeners to the container and window.
27548
+ */
27549
+ attachListeners() {
27550
+ this.container.addEventListener("dragstart", this.boundHandlers.dragstart);
27551
+ this.container.addEventListener("dragover", this.boundHandlers.dragover);
27552
+ this.container.addEventListener("drop", this.boundHandlers.drop);
27553
+ this.container.addEventListener("dragend", this.boundHandlers.dragend);
27554
+ this.container.addEventListener("dragleave", this.boundHandlers.dragleave);
27555
+ window.addEventListener("dragover", this.windowDragoverHandler, false);
27556
+ window.addEventListener("drop", this.windowDropHandler, false);
27557
+ }
27558
+ /**
27559
+ * Removes event listeners from the container and window.
27560
+ */
27561
+ removeListeners() {
27562
+ this.container.removeEventListener("dragstart", this.boundHandlers.dragstart);
27563
+ this.container.removeEventListener("dragover", this.boundHandlers.dragover);
27564
+ this.container.removeEventListener("drop", this.boundHandlers.drop);
27565
+ this.container.removeEventListener("dragend", this.boundHandlers.dragend);
27566
+ this.container.removeEventListener("dragleave", this.boundHandlers.dragleave);
27567
+ window.removeEventListener("dragover", this.windowDragoverHandler, false);
27568
+ window.removeEventListener("drop", this.windowDropHandler, false);
27569
+ }
27570
+ /**
27571
+ * Handles dragover at window level to allow drops on overlay elements.
27572
+ * This ensures preventDefault is called even when dragging over selection
27573
+ * highlights or other UI elements that sit on top of the layout content.
27574
+ */
27575
+ handleWindowDragOver(event) {
27576
+ if (this.hasFieldAnnotationData(event)) {
27577
+ event.preventDefault();
27578
+ if (event.dataTransfer) {
27579
+ event.dataTransfer.dropEffect = "move";
27580
+ }
27581
+ const target = event.target;
27582
+ if (!this.container.contains(target)) {
27583
+ this.config.onDragOver?.({
27584
+ event,
27585
+ clientX: event.clientX,
27586
+ clientY: event.clientY,
27587
+ hasFieldAnnotation: true
27588
+ });
27589
+ }
27590
+ }
27591
+ }
27592
+ /**
27593
+ * Handles drop at window level to catch drops on overlay elements.
27594
+ * If the drop target is outside the container, we process it here.
27595
+ */
27596
+ handleWindowDrop(event) {
27597
+ if (this.hasFieldAnnotationData(event)) {
27598
+ const target = event.target;
27599
+ if (!this.container.contains(target)) {
27600
+ this.handleDrop(event);
27601
+ }
27602
+ }
27603
+ }
27604
+ /**
27605
+ * Handles the dragstart event.
27606
+ * Sets up dataTransfer with field annotation data and drag image.
27607
+ */
27608
+ handleDragStart(event) {
27609
+ const target = event.target;
27610
+ if (!target?.dataset?.draggable || target.dataset.draggable !== "true") {
27611
+ return;
27612
+ }
27613
+ const data = extractFieldAnnotationData(target);
27614
+ if (event.dataTransfer) {
27615
+ const jsonData = JSON.stringify({
27616
+ attributes: data.attributes,
27617
+ sourceField: data
27618
+ });
27619
+ event.dataTransfer.setData(this.mimeType, jsonData);
27620
+ event.dataTransfer.setData(LEGACY_MIME_TYPE, jsonData);
27621
+ event.dataTransfer.setData("text/plain", data.displayLabel ?? "Field Annotation");
27622
+ event.dataTransfer.setDragImage(target, 0, 0);
27623
+ event.dataTransfer.effectAllowed = "move";
27624
+ }
27625
+ this.config.onDragStart?.({
27626
+ event,
27627
+ element: target,
27628
+ data
27629
+ });
27630
+ }
27631
+ /**
27632
+ * Handles the dragover event.
27633
+ * Provides visual feedback and determines if drop is allowed.
27634
+ */
27635
+ handleDragOver(event) {
27636
+ const hasFieldAnnotation = this.hasFieldAnnotationData(event);
27637
+ if (hasFieldAnnotation) {
27638
+ event.preventDefault();
27639
+ if (event.dataTransfer) {
27640
+ event.dataTransfer.dropEffect = "move";
27641
+ }
27642
+ this.container.classList.add("drag-over");
27643
+ }
27644
+ this.config.onDragOver?.({
27645
+ event,
27646
+ clientX: event.clientX,
27647
+ clientY: event.clientY,
27648
+ hasFieldAnnotation
27649
+ });
27650
+ }
27651
+ /**
27652
+ * Handles the dragleave event.
27653
+ * Removes visual feedback when drag leaves the container.
27654
+ */
27655
+ handleDragLeave(event) {
27656
+ const relatedTarget = event.relatedTarget;
27657
+ if (!relatedTarget || !this.container.contains(relatedTarget)) {
27658
+ this.container.classList.remove("drag-over");
27659
+ }
27660
+ }
27661
+ /**
27662
+ * Handles the drop event.
27663
+ * Maps drop coordinates to ProseMirror position and emits drop event.
27664
+ */
27665
+ handleDrop(event) {
27666
+ this.container.classList.remove("drag-over");
27667
+ if (!this.hasFieldAnnotationData(event)) {
27668
+ return;
27669
+ }
27670
+ event.preventDefault();
27671
+ const data = this.extractDragData(event);
27672
+ if (!data) {
27673
+ return;
27674
+ }
27675
+ const pmPosition = clickToPositionDom(this.container, event.clientX, event.clientY);
27676
+ this.config.onDrop?.({
27677
+ event,
27678
+ data,
27679
+ pmPosition,
27680
+ clientX: event.clientX,
27681
+ clientY: event.clientY
27682
+ });
27683
+ }
27684
+ /**
27685
+ * Handles the dragend event.
27686
+ * Cleans up drag state.
27687
+ */
27688
+ handleDragEnd(event) {
27689
+ this.container.classList.remove("drag-over");
27690
+ this.config.onDragEnd?.(event);
27691
+ }
27692
+ /**
27693
+ * Checks if a drag event contains field annotation data.
27694
+ */
27695
+ hasFieldAnnotationData(event) {
27696
+ if (!event.dataTransfer) {
27697
+ return false;
27698
+ }
27699
+ const types = event.dataTransfer.types;
27700
+ return types.includes(this.mimeType) || types.includes(LEGACY_MIME_TYPE);
27701
+ }
27702
+ /**
27703
+ * Extracts field annotation data from a drag event's dataTransfer.
27704
+ */
27705
+ extractDragData(event) {
27706
+ if (!event.dataTransfer) {
27707
+ return null;
27708
+ }
27709
+ let jsonData = event.dataTransfer.getData(this.mimeType);
27710
+ if (!jsonData) {
27711
+ jsonData = event.dataTransfer.getData(LEGACY_MIME_TYPE);
27712
+ }
27713
+ if (!jsonData) {
27714
+ return null;
27715
+ }
27716
+ try {
27717
+ const parsed = JSON.parse(jsonData);
27718
+ return parsed.sourceField ?? parsed.attributes ?? parsed;
27719
+ } catch {
27720
+ return null;
27721
+ }
27722
+ }
27723
+ /**
27724
+ * Updates the configuration options.
27725
+ *
27726
+ * @param config - New configuration options to merge
27727
+ */
27728
+ updateConfig(config) {
27729
+ this.config = { ...this.config, ...config };
27730
+ if (config.mimeType) {
27731
+ this.mimeType = config.mimeType;
27732
+ }
27733
+ }
27734
+ /**
27735
+ * Destroys the drag handler and removes all event listeners.
27736
+ * Call this when the layout engine is unmounted or the container is removed.
27737
+ */
27738
+ destroy() {
27739
+ this.removeListeners();
27740
+ this.container.classList.remove("drag-over");
27741
+ }
27742
+ }
27743
+ function createDragHandler(container, config = {}) {
27744
+ const handler = new DragHandler(container, config);
27745
+ return () => handler.destroy();
27746
+ }
27216
27747
  const isAtomicFragment = (fragment) => {
27217
27748
  return fragment.kind === "drawing" || fragment.kind === "image";
27218
27749
  };
27219
27750
  const logClickStage = (_level, _stage, _payload) => {
27220
27751
  };
27752
+ const logPositionDebug = (payload) => {
27753
+ return;
27754
+ };
27755
+ const logSelectionMapDebug = (payload) => {
27756
+ return;
27757
+ };
27221
27758
  const blockPmRangeFromAttrs = (block) => {
27222
27759
  const attrs = block?.attrs;
27223
27760
  const pmStart = typeof attrs?.pmStart === "number" ? attrs.pmStart : void 0;
@@ -27487,6 +28024,10 @@ function clickToPosition(layout, blocks, measures, containerPoint, domContainer,
27487
28024
  return null;
27488
28025
  }
27489
28026
  const column = determineColumn(layout, fragment.x);
28027
+ logPositionDebug({
28028
+ blockId: fragment.blockId,
28029
+ x: pageRelativePoint.x - fragment.x
28030
+ });
27490
28031
  logClickStage("log", "success", {
27491
28032
  blockId: fragment.blockId
27492
28033
  });
@@ -27595,10 +28136,13 @@ function selectionToRects(layout, blocks, measures, from2, to) {
27595
28136
  const sliceFrom = Math.max(range.pmStart, from2);
27596
28137
  const sliceTo = Math.min(range.pmEnd, to);
27597
28138
  if (sliceFrom >= sliceTo) return;
27598
- const x1 = mapPmToX(block, line, sliceFrom - range.pmStart, fragment.width);
27599
- const x2 = mapPmToX(block, line, sliceTo - range.pmStart, fragment.width);
27600
- const rectX = fragment.x + Math.min(x1, x2);
27601
- const rectWidth = Math.max(1, Math.abs(x2 - x1));
28139
+ const charOffsetFrom = pmPosToCharOffset(block, line, sliceFrom);
28140
+ const charOffsetTo = pmPosToCharOffset(block, line, sliceTo);
28141
+ const startX = mapPmToX(block, line, charOffsetFrom, fragment.width);
28142
+ const endX = mapPmToX(block, line, charOffsetTo, fragment.width);
28143
+ const markerWidth = fragment.markerWidth ?? measure.marker?.markerWidth ?? 0;
28144
+ const rectX = fragment.x + markerWidth + Math.min(startX, endX);
28145
+ const rectWidth = Math.max(1, Math.abs(endX - startX));
27602
28146
  const lineOffset = lineHeightBeforeIndex(measure, index2) - lineHeightBeforeIndex(measure, fragment.fromLine);
27603
28147
  const rectY = fragment.y + lineOffset;
27604
28148
  rects.push({
@@ -27738,7 +28282,7 @@ function computeLinePmRange$1(block, line) {
27738
28282
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
27739
28283
  const run = block.runs[runIndex];
27740
28284
  if (!run) continue;
27741
- const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" ? "" : run.text ?? "";
28285
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text ?? "";
27742
28286
  const runLength = text.length;
27743
28287
  const runPmStart = run.pmStart ?? null;
27744
28288
  const runPmEnd = run.pmEnd ?? (runPmStart != null ? runPmStart + runLength : null);
@@ -27756,6 +28300,57 @@ function computeLinePmRange$1(block, line) {
27756
28300
  }
27757
28301
  return { pmStart, pmEnd };
27758
28302
  }
28303
+ function pmPosToCharOffset(block, line, pmPos) {
28304
+ if (block.kind !== "paragraph") return 0;
28305
+ let charOffset = 0;
28306
+ for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
28307
+ const run = block.runs[runIndex];
28308
+ if (!run) continue;
28309
+ const text = "src" in run || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation" ? "" : run.text ?? "";
28310
+ const runTextLength = text.length;
28311
+ const runPmStart = run.pmStart ?? null;
28312
+ const runPmEnd = run.pmEnd ?? (runPmStart != null ? runPmStart + runTextLength : null);
28313
+ if (runPmStart == null || runPmEnd == null || runTextLength === 0) continue;
28314
+ const isFirstRun = runIndex === line.fromRun;
28315
+ const isLastRun = runIndex === line.toRun;
28316
+ const lineStartChar = isFirstRun ? line.fromChar : 0;
28317
+ const lineEndChar = isLastRun ? line.toChar : runTextLength;
28318
+ const runSliceCharCount = lineEndChar - lineStartChar;
28319
+ const runPmRange = runPmEnd - runPmStart;
28320
+ const runSlicePmStart = runPmStart + lineStartChar / runTextLength * runPmRange;
28321
+ const runSlicePmEnd = runPmStart + lineEndChar / runTextLength * runPmRange;
28322
+ if (pmPos >= runSlicePmStart && pmPos <= runSlicePmEnd) {
28323
+ const runSlicePmRange = runSlicePmEnd - runSlicePmStart;
28324
+ if (runSlicePmRange > 0) {
28325
+ const pmOffsetInSlice = pmPos - runSlicePmStart;
28326
+ const charOffsetInSlice = Math.round(pmOffsetInSlice / runSlicePmRange * runSliceCharCount);
28327
+ const result = charOffset + Math.min(charOffsetInSlice, runSliceCharCount);
28328
+ const runText2 = text;
28329
+ const offsetInRun = result - charOffset - (isFirstRun ? 0 : 0);
28330
+ logSelectionMapDebug({
28331
+ blockId: block.id,
28332
+ lineFromRun: line.fromRun,
28333
+ lineToRun: line.toRun,
28334
+ runTextPreview: runText2.slice(Math.max(0, offsetInRun - 10), Math.min(runText2.length, offsetInRun + 10))
28335
+ });
28336
+ return result;
28337
+ }
28338
+ logSelectionMapDebug({
28339
+ blockId: block.id
28340
+ });
28341
+ return charOffset;
28342
+ }
28343
+ if (pmPos > runSlicePmEnd) {
28344
+ charOffset += runSliceCharCount;
28345
+ }
28346
+ }
28347
+ logSelectionMapDebug({
28348
+ blockId: block.id,
28349
+ lineFromRun: line.fromRun,
28350
+ lineToRun: line.toRun
28351
+ });
28352
+ return charOffset;
28353
+ }
27759
28354
  const determineColumn = (layout, fragmentX) => {
27760
28355
  const columns = layout.columns;
27761
28356
  if (!columns || columns.count <= 1) return 0;
@@ -27800,8 +28395,8 @@ const mapPointToPm = (block, line, x, isRTL) => {
27800
28395
  if (isRTL) {
27801
28396
  const charOffset = result.charOffset;
27802
28397
  const charsInLine = Math.max(1, line.toChar - line.fromChar);
27803
- const reversedOffset = charsInLine - charOffset;
27804
- return range.pmStart + reversedOffset;
28398
+ const reversedOffset = Math.max(0, Math.min(charsInLine, charsInLine - charOffset));
28399
+ return charOffsetToPm(block, line, reversedOffset, range.pmStart);
27805
28400
  }
27806
28401
  return result.pmPosition;
27807
28402
  };
@@ -30244,9 +30839,227 @@ const TRACK_CHANGE_STYLES = `
30244
30839
  border-bottom: 2px solid gold;
30245
30840
  }
30246
30841
  `;
30842
+ const SDT_CONTAINER_STYLES = `
30843
+ /* Document Section - Block-level container with gray border and hover tooltip */
30844
+ .superdoc-document-section {
30845
+ background-color: #fafafa;
30846
+ border: 1px solid #ababab;
30847
+ border-radius: 4px;
30848
+ position: relative;
30849
+ box-sizing: border-box;
30850
+ }
30851
+
30852
+ /* Document section tooltip - positioned above the fragment */
30853
+ .superdoc-document-section__tooltip {
30854
+ position: absolute;
30855
+ top: -19px;
30856
+ left: -1px;
30857
+ max-width: 100px;
30858
+ min-width: 0;
30859
+ height: 18px;
30860
+ border: 1px solid #ababab;
30861
+ border-bottom: none;
30862
+ border-radius: 6px 6px 0 0;
30863
+ padding: 0 8px;
30864
+ align-items: center;
30865
+ font-size: 10px;
30866
+ display: none;
30867
+ z-index: 100;
30868
+ background-color: #fafafa;
30869
+ pointer-events: none;
30870
+ }
30871
+
30872
+ .superdoc-document-section__tooltip span {
30873
+ max-width: 100%;
30874
+ overflow: hidden;
30875
+ white-space: nowrap;
30876
+ text-overflow: ellipsis;
30877
+ }
30878
+
30879
+ /* Show tooltip on hover - adjust border radius to connect with tooltip tab */
30880
+ .superdoc-document-section:hover {
30881
+ border-radius: 0 4px 4px 4px;
30882
+ }
30883
+
30884
+ .superdoc-document-section:hover .superdoc-document-section__tooltip {
30885
+ display: flex;
30886
+ align-items: center;
30887
+ }
30888
+
30889
+ /* Continuation styling: first fragment has top corners, last has bottom corners */
30890
+ .superdoc-document-section[data-sdt-container-start="true"] {
30891
+ border-radius: 4px 4px 0 0;
30892
+ }
30893
+
30894
+ .superdoc-document-section[data-sdt-container-end="true"] {
30895
+ border-radius: 0 0 4px 4px;
30896
+ }
30897
+
30898
+ .superdoc-document-section[data-sdt-container-start="true"][data-sdt-container-end="true"] {
30899
+ border-radius: 4px;
30900
+ }
30901
+
30902
+ .superdoc-document-section[data-sdt-container-start="true"]:hover {
30903
+ border-radius: 0 4px 0 0;
30904
+ }
30905
+
30906
+ /* Middle fragments have no border radius */
30907
+ .superdoc-document-section:not([data-sdt-container-start="true"]):not([data-sdt-container-end="true"]) {
30908
+ border-radius: 0;
30909
+ border-top: none;
30910
+ }
30911
+
30912
+ /* Structured Content Block - Blue border container */
30913
+ .superdoc-structured-content-block {
30914
+ padding: 1px;
30915
+ box-sizing: border-box;
30916
+ border-radius: 4px;
30917
+ border: 1px solid #629be7;
30918
+ position: relative;
30919
+ }
30920
+
30921
+ /* Structured content drag handle/label - positioned above */
30922
+ .superdoc-structured-content__label {
30923
+ font-size: 10px;
30924
+ align-items: center;
30925
+ justify-content: center;
30926
+ position: absolute;
30927
+ left: 2px;
30928
+ top: -19px;
30929
+ width: calc(100% - 4px);
30930
+ max-width: 110px;
30931
+ min-width: 0;
30932
+ height: 18px;
30933
+ padding: 0 4px;
30934
+ border: 1px solid #629be7;
30935
+ border-bottom: none;
30936
+ border-radius: 6px 6px 0 0;
30937
+ background-color: #629be7dd;
30938
+ box-sizing: border-box;
30939
+ z-index: 10;
30940
+ display: none;
30941
+ pointer-events: none;
30942
+ }
30943
+
30944
+ .superdoc-structured-content__label span {
30945
+ max-width: 100%;
30946
+ overflow: hidden;
30947
+ white-space: nowrap;
30948
+ text-overflow: ellipsis;
30949
+ }
30950
+
30951
+ .superdoc-structured-content-block:hover .superdoc-structured-content__label {
30952
+ display: inline-flex;
30953
+ }
30954
+
30955
+ /* Continuation styling for structured content blocks */
30956
+ .superdoc-structured-content-block[data-sdt-container-start="true"] {
30957
+ border-radius: 4px 4px 0 0;
30958
+ }
30959
+
30960
+ .superdoc-structured-content-block[data-sdt-container-end="true"] {
30961
+ border-radius: 0 0 4px 4px;
30962
+ }
30963
+
30964
+ .superdoc-structured-content-block[data-sdt-container-start="true"][data-sdt-container-end="true"] {
30965
+ border-radius: 4px;
30966
+ }
30967
+
30968
+ .superdoc-structured-content-block:not([data-sdt-container-start="true"]):not([data-sdt-container-end="true"]) {
30969
+ border-radius: 0;
30970
+ border-top: none;
30971
+ }
30972
+
30973
+ /* Structured Content Inline - Inline wrapper with blue border */
30974
+ .superdoc-structured-content-inline {
30975
+ padding: 1px;
30976
+ box-sizing: border-box;
30977
+ border-radius: 4px;
30978
+ border: 1px solid #629be7;
30979
+ position: relative;
30980
+ display: inline;
30981
+ }
30982
+
30983
+ /* Hover effect for inline structured content */
30984
+ .superdoc-structured-content-inline:hover {
30985
+ background-color: rgba(98, 155, 231, 0.15);
30986
+ border-color: #4a8ad9;
30987
+ }
30988
+
30989
+ /* Inline structured content label - shown on hover */
30990
+ .superdoc-structured-content-inline__label {
30991
+ position: absolute;
30992
+ bottom: calc(100% + 2px);
30993
+ left: 50%;
30994
+ transform: translateX(-50%);
30995
+ font-size: 10px;
30996
+ padding: 2px 6px;
30997
+ background-color: #629be7dd;
30998
+ color: white;
30999
+ border-radius: 4px;
31000
+ white-space: nowrap;
31001
+ z-index: 100;
31002
+ display: none;
31003
+ pointer-events: none;
31004
+ }
31005
+
31006
+ .superdoc-structured-content-inline:hover .superdoc-structured-content-inline__label {
31007
+ display: block;
31008
+ }
31009
+
31010
+ /* Print mode: hide visual styling for SDT containers */
31011
+ @media print {
31012
+ .superdoc-document-section,
31013
+ .superdoc-structured-content-block,
31014
+ .superdoc-structured-content-inline {
31015
+ background: none;
31016
+ border: none;
31017
+ padding: 0;
31018
+ }
31019
+
31020
+ .superdoc-document-section__tooltip,
31021
+ .superdoc-structured-content__label,
31022
+ .superdoc-structured-content-inline__label {
31023
+ display: none !important;
31024
+ }
31025
+ }
31026
+ `;
31027
+ const FIELD_ANNOTATION_STYLES = `
31028
+ /* Field annotation draggable styles */
31029
+ .superdoc-layout .annotation[data-draggable="true"] {
31030
+ cursor: grab;
31031
+ user-select: none;
31032
+ -webkit-user-select: none;
31033
+ }
31034
+
31035
+ .superdoc-layout .annotation[data-draggable="true"]:hover {
31036
+ opacity: 0.9;
31037
+ }
31038
+
31039
+ .superdoc-layout .annotation[data-draggable="true"]:active {
31040
+ cursor: grabbing;
31041
+ }
31042
+
31043
+ /* Drag over indicator for drop targets */
31044
+ .superdoc-layout.drag-over {
31045
+ outline: 2px dashed #b015b3;
31046
+ outline-offset: -2px;
31047
+ }
31048
+
31049
+ /* Drop zone indicator */
31050
+ .superdoc-layout .superdoc-drop-indicator {
31051
+ position: absolute;
31052
+ width: 2px;
31053
+ background-color: #b015b3;
31054
+ pointer-events: none;
31055
+ z-index: 1000;
31056
+ }
31057
+ `;
30247
31058
  let printStylesInjected = false;
30248
31059
  let linkStylesInjected = false;
30249
31060
  let trackChangeStylesInjected = false;
31061
+ let sdtContainerStylesInjected = false;
31062
+ let fieldAnnotationStylesInjected = false;
30250
31063
  const ensurePrintStyles = (doc2) => {
30251
31064
  if (printStylesInjected || !doc2) return;
30252
31065
  const styleEl = doc2.createElement("style");
@@ -30271,6 +31084,22 @@ const ensureTrackChangeStyles = (doc2) => {
30271
31084
  doc2.head?.appendChild(styleEl);
30272
31085
  trackChangeStylesInjected = true;
30273
31086
  };
31087
+ const ensureSdtContainerStyles = (doc2) => {
31088
+ if (sdtContainerStylesInjected || !doc2) return;
31089
+ const styleEl = doc2.createElement("style");
31090
+ styleEl.setAttribute("data-superdoc-sdt-container-styles", "true");
31091
+ styleEl.textContent = SDT_CONTAINER_STYLES;
31092
+ doc2.head?.appendChild(styleEl);
31093
+ sdtContainerStylesInjected = true;
31094
+ };
31095
+ const ensureFieldAnnotationStyles = (doc2) => {
31096
+ if (fieldAnnotationStylesInjected || !doc2) return;
31097
+ const styleEl = doc2.createElement("style");
31098
+ styleEl.setAttribute("data-superdoc-field-annotation-styles", "true");
31099
+ styleEl.textContent = FIELD_ANNOTATION_STYLES;
31100
+ doc2.head?.appendChild(styleEl);
31101
+ fieldAnnotationStylesInjected = true;
31102
+ };
30274
31103
  const ALLOWED_BORDER_STYLES = /* @__PURE__ */ new Set([
30275
31104
  "none",
30276
31105
  "single",
@@ -30600,6 +31429,50 @@ const renderTableRow = (deps) => {
30600
31429
  container.appendChild(cellElement);
30601
31430
  }
30602
31431
  };
31432
+ function isStructuredContentMetadata(sdt) {
31433
+ return sdt !== null && sdt !== void 0 && typeof sdt === "object" && "type" in sdt && sdt.type === "structuredContent";
31434
+ }
31435
+ function isDocumentSectionMetadata(sdt) {
31436
+ return sdt !== null && sdt !== void 0 && typeof sdt === "object" && "type" in sdt && sdt.type === "documentSection";
31437
+ }
31438
+ function getSdtContainerConfig(sdt) {
31439
+ if (isDocumentSectionMetadata(sdt)) {
31440
+ return {
31441
+ className: "superdoc-document-section",
31442
+ labelText: sdt.title ?? "Document section",
31443
+ labelClassName: "superdoc-document-section__tooltip",
31444
+ isStart: true,
31445
+ isEnd: true
31446
+ };
31447
+ }
31448
+ if (isStructuredContentMetadata(sdt) && sdt.scope === "block") {
31449
+ return {
31450
+ className: "superdoc-structured-content-block",
31451
+ labelText: sdt.alias ?? "Structured content",
31452
+ labelClassName: "superdoc-structured-content__label",
31453
+ isStart: true,
31454
+ isEnd: true
31455
+ };
31456
+ }
31457
+ return null;
31458
+ }
31459
+ function applySdtContainerStyling(doc2, container, sdt, containerSdt) {
31460
+ let config = getSdtContainerConfig(sdt);
31461
+ if (!config && containerSdt) {
31462
+ config = getSdtContainerConfig(containerSdt);
31463
+ }
31464
+ if (!config) return;
31465
+ container.classList.add(config.className);
31466
+ container.dataset.sdtContainerStart = String(config.isStart);
31467
+ container.dataset.sdtContainerEnd = String(config.isEnd);
31468
+ container.style.overflow = "visible";
31469
+ const labelEl = doc2.createElement("div");
31470
+ labelEl.className = config.labelClassName;
31471
+ const labelText = doc2.createElement("span");
31472
+ labelText.textContent = config.labelText;
31473
+ labelEl.appendChild(labelText);
31474
+ container.appendChild(labelEl);
31475
+ }
30603
31476
  const renderTableFragment = (deps) => {
30604
31477
  const { doc: doc2, fragment, blockLookup, context, renderLine, applyFragmentFrame, applySdtDataset, applyStyles: applyStyles2 } = deps;
30605
31478
  if (!doc2) {
@@ -30636,6 +31509,7 @@ const renderTableFragment = (deps) => {
30636
31509
  applyFragmentFrame(container, fragment);
30637
31510
  container.style.height = `${fragment.height}px`;
30638
31511
  applySdtDataset(container, block.attrs?.sdt);
31512
+ applySdtContainerStyling(doc2, container, block.attrs?.sdt);
30639
31513
  container.classList.add("superdoc-table-fragment");
30640
31514
  if (fragment.metadata?.columnBoundaries) {
30641
31515
  const columnCount = measure.columnWidths.length;
@@ -31102,6 +31976,8 @@ const _DomPainter = class _DomPainter {
31102
31976
  ensurePrintStyles(doc2);
31103
31977
  ensureLinkStyles(doc2);
31104
31978
  ensureTrackChangeStyles(doc2);
31979
+ ensureFieldAnnotationStyles(doc2);
31980
+ ensureSdtContainerStyles(doc2);
31105
31981
  mount.classList.add(CLASS_NAMES.container);
31106
31982
  if (this.mount && this.mount !== mount) {
31107
31983
  this.resetState();
@@ -31624,7 +32500,8 @@ const _DomPainter = class _DomPainter {
31624
32500
  fragmentEl.classList.add(CLASS_NAMES.fragment);
31625
32501
  const isTocEntry = block.attrs?.isTocEntry;
31626
32502
  const hasMarker = !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
31627
- const styles = isTocEntry ? { ...fragmentStyles, whiteSpace: "nowrap" } : hasMarker ? { ...fragmentStyles, overflow: "visible" } : fragmentStyles;
32503
+ const hasSdtContainer = block.attrs?.sdt?.type === "documentSection" || block.attrs?.sdt?.type === "structuredContent" || block.attrs?.containerSdt?.type === "documentSection" || block.attrs?.containerSdt?.type === "structuredContent";
32504
+ const styles = isTocEntry ? { ...fragmentStyles, whiteSpace: "nowrap" } : hasMarker || hasSdtContainer ? { ...fragmentStyles, overflow: "visible" } : fragmentStyles;
31628
32505
  applyStyles$2(fragmentEl, styles);
31629
32506
  this.applyFragmentFrame(fragmentEl, fragment, context.section);
31630
32507
  if (isTocEntry) {
@@ -31644,6 +32521,7 @@ const _DomPainter = class _DomPainter {
31644
32521
  }
31645
32522
  this.applySdtDataset(fragmentEl, block.attrs?.sdt);
31646
32523
  this.applyContainerSdtDataset(fragmentEl, block.attrs?.containerSdt);
32524
+ applySdtContainerStyling(this.doc, fragmentEl, block.attrs?.sdt, block.attrs?.containerSdt);
31647
32525
  const dropCapDescriptor = block.attrs?.dropCapDescriptor;
31648
32526
  const dropCapMeasure = measure.dropCap;
31649
32527
  if (dropCapDescriptor && dropCapMeasure && !fragment.continuesFromPrev) {
@@ -31658,8 +32536,22 @@ const _DomPainter = class _DomPainter {
31658
32536
  const paraIndentRight = paraIndent?.right ?? 0;
31659
32537
  const suppressFirstLineIndent = block.attrs?.suppressFirstLineIndent === true;
31660
32538
  const firstLineOffset = suppressFirstLineIndent ? 0 : (paraIndent?.firstLine ?? 0) - (paraIndent?.hanging ?? 0);
32539
+ const isListParagraph = !!(fragment.markerWidth && wordLayout?.marker);
32540
+ const lastRun = block.runs.length > 0 ? block.runs[block.runs.length - 1] : null;
32541
+ const paragraphEndsWithLineBreak = lastRun?.kind === "lineBreak";
31661
32542
  lines.forEach((line, index2) => {
31662
- const lineEl = this.renderLine(block, line, context);
32543
+ const availableWidthOverride = Math.max(0, fragment.width - (paraIndentLeft + paraIndentRight));
32544
+ const isLastLineOfFragment = index2 === lines.length - 1;
32545
+ const isLastLineOfParagraph = isLastLineOfFragment && !fragment.continuesOnNext;
32546
+ const shouldSkipJustifyForLastLine = isLastLineOfParagraph && !paragraphEndsWithLineBreak;
32547
+ const lineEl = this.renderLine(
32548
+ block,
32549
+ line,
32550
+ context,
32551
+ availableWidthOverride,
32552
+ fragment.fromLine + index2,
32553
+ isListParagraph || shouldSkipJustifyForLastLine
32554
+ );
31663
32555
  const isListFirstLine = index2 === 0 && !fragment.continuesFromPrev && fragment.markerWidth && wordLayout?.marker;
31664
32556
  const hasExplicitSegmentPositioning = line.segments?.some((seg) => seg.x !== void 0);
31665
32557
  const isFirstLine = index2 === 0 && !fragment.continuesFromPrev;
@@ -31848,6 +32740,7 @@ const _DomPainter = class _DomPainter {
31848
32740
  fragmentEl.dataset.itemId = fragment.itemId;
31849
32741
  const paragraphMetadata = item.paragraph.attrs?.sdt;
31850
32742
  this.applySdtDataset(fragmentEl, paragraphMetadata);
32743
+ applySdtContainerStyling(this.doc, fragmentEl, paragraphMetadata, item.paragraph.attrs?.containerSdt);
31851
32744
  if (fragment.continuesFromPrev) {
31852
32745
  fragmentEl.dataset.continuesFromPrev = "true";
31853
32746
  }
@@ -31888,8 +32781,13 @@ const _DomPainter = class _DomPainter {
31888
32781
  const lines = itemMeasure.paragraph.lines.slice(fragment.fromLine, fragment.toLine);
31889
32782
  const contentAttrs = wordLayout ? item.paragraph.attrs : stripListIndent(item.paragraph.attrs);
31890
32783
  applyParagraphBlockStyles(contentEl, contentAttrs);
31891
- lines.forEach((line) => {
31892
- const lineEl = this.renderLine(item.paragraph, line, context);
32784
+ contentEl.style.textAlign = "left";
32785
+ const paraForList = {
32786
+ ...item.paragraph,
32787
+ attrs: { ...item.paragraph.attrs || {}, alignment: "left" }
32788
+ };
32789
+ lines.forEach((line, idx) => {
32790
+ const lineEl = this.renderLine(paraForList, line, context, fragment.width, fragment.fromLine + idx, true);
31893
32791
  contentEl.appendChild(lineEl);
31894
32792
  });
31895
32793
  fragmentEl.appendChild(contentEl);
@@ -32411,12 +33309,15 @@ const _DomPainter = class _DomPainter {
32411
33309
  const applyFragmentFrameWithSection = (el, frag) => {
32412
33310
  this.applyFragmentFrame(el, frag, context.section);
32413
33311
  };
33312
+ const renderLineForTableCell = (block, line, ctx2) => {
33313
+ return this.renderLine(block, line, ctx2, void 0, void 0, true);
33314
+ };
32414
33315
  return renderTableFragment({
32415
33316
  doc: this.doc,
32416
33317
  fragment,
32417
33318
  context,
32418
33319
  blockLookup: this.blockLookup,
32419
- renderLine: this.renderLine.bind(this),
33320
+ renderLine: renderLineForTableCell,
32420
33321
  applyFragmentFrame: applyFragmentFrameWithSection,
32421
33322
  applySdtDataset: this.applySdtDataset.bind(this),
32422
33323
  applyStyles: applyStyles$2
@@ -32611,10 +33512,19 @@ const _DomPainter = class _DomPainter {
32611
33512
  isBreakRun(run) {
32612
33513
  return run.kind === "break";
32613
33514
  }
33515
+ /**
33516
+ * Type guard to check if a run is a field annotation run.
33517
+ */
33518
+ isFieldAnnotationRun(run) {
33519
+ return run.kind === "fieldAnnotation";
33520
+ }
32614
33521
  renderRun(run, context, trackedConfig) {
32615
33522
  if (this.isImageRun(run)) {
32616
33523
  return this.renderImageRun(run);
32617
33524
  }
33525
+ if (this.isFieldAnnotationRun(run)) {
33526
+ return this.renderFieldAnnotationRun(run);
33527
+ }
32618
33528
  if (this.isLineBreakRun(run)) {
32619
33529
  return null;
32620
33530
  }
@@ -32751,7 +33661,212 @@ const _DomPainter = class _DomPainter {
32751
33661
  }
32752
33662
  return img;
32753
33663
  }
32754
- renderLine(block, line, context) {
33664
+ /**
33665
+ * Renders a FieldAnnotationRun as an inline "pill" element matching super-editor's visual appearance.
33666
+ *
33667
+ * Field annotations are styled inline elements that display form fields with:
33668
+ * - Outer span with border, border-radius, padding, and background color
33669
+ * - Inner span containing the displayLabel or type-specific content (image, link, etc.)
33670
+ *
33671
+ * @param run - The FieldAnnotationRun to render containing field configuration and styling
33672
+ * @returns HTMLElement (span) or null if document is not available
33673
+ *
33674
+ * @example
33675
+ * ```typescript
33676
+ * // Text variant
33677
+ * renderFieldAnnotationRun({ kind: 'fieldAnnotation', variant: 'text', displayLabel: 'Full Name', fieldColor: '#980043' })
33678
+ * // Returns: <span class="annotation" style="border: 2px solid #b015b3; ..."><span class="annotation-content">Full Name</span></span>
33679
+ *
33680
+ * // Image variant with imageSrc
33681
+ * renderFieldAnnotationRun({ kind: 'fieldAnnotation', variant: 'image', displayLabel: 'Photo', imageSrc: 'data:image/png;...' })
33682
+ * // Returns: <span class="annotation"><span class="annotation-content"><img src="..." /></span></span>
33683
+ *
33684
+ * // Link variant
33685
+ * renderFieldAnnotationRun({ kind: 'fieldAnnotation', variant: 'link', displayLabel: 'Website', linkUrl: 'https://example.com' })
33686
+ * // Returns: <span class="annotation"><span class="annotation-content"><a href="...">https://example.com</a></span></span>
33687
+ * ```
33688
+ */
33689
+ renderFieldAnnotationRun(run) {
33690
+ if (!this.doc) {
33691
+ return null;
33692
+ }
33693
+ if (run.hidden) {
33694
+ const hidden = this.doc.createElement("span");
33695
+ hidden.style.display = "none";
33696
+ if (run.pmStart != null) hidden.dataset.pmStart = String(run.pmStart);
33697
+ if (run.pmEnd != null) hidden.dataset.pmEnd = String(run.pmEnd);
33698
+ return hidden;
33699
+ }
33700
+ const defaultBorderColor = "#b015b3";
33701
+ const defaultFieldColor = "#980043";
33702
+ const annotation = this.doc.createElement("span");
33703
+ annotation.classList.add("annotation");
33704
+ annotation.setAttribute("aria-label", "Field annotation");
33705
+ const showHighlight = run.highlighted !== false;
33706
+ if (showHighlight) {
33707
+ const borderColor = run.borderColor || defaultBorderColor;
33708
+ annotation.style.border = `2px solid ${borderColor}`;
33709
+ annotation.style.borderRadius = "2px";
33710
+ annotation.style.padding = "1px 2px";
33711
+ annotation.style.boxSizing = "border-box";
33712
+ const fieldColor = run.fieldColor || defaultFieldColor;
33713
+ const bgColor = fieldColor.length === 7 ? `${fieldColor}33` : fieldColor;
33714
+ if (run.textHighlight) {
33715
+ annotation.style.backgroundColor = run.textHighlight;
33716
+ } else {
33717
+ annotation.style.backgroundColor = bgColor;
33718
+ }
33719
+ }
33720
+ if (run.visibility === "hidden") {
33721
+ annotation.style.visibility = "hidden";
33722
+ }
33723
+ if (run.size) {
33724
+ if (run.size.width) {
33725
+ annotation.style.width = `${run.size.width}px`;
33726
+ annotation.style.display = "inline-block";
33727
+ annotation.style.overflow = "hidden";
33728
+ }
33729
+ if (run.size.height) {
33730
+ annotation.style.height = `${run.size.height}px`;
33731
+ }
33732
+ }
33733
+ if (run.fontFamily) {
33734
+ annotation.style.fontFamily = run.fontFamily;
33735
+ }
33736
+ if (run.fontSize) {
33737
+ const fontSize = typeof run.fontSize === "number" ? `${run.fontSize}pt` : run.fontSize;
33738
+ annotation.style.fontSize = fontSize;
33739
+ }
33740
+ if (run.textColor) {
33741
+ annotation.style.color = run.textColor;
33742
+ }
33743
+ if (run.bold) {
33744
+ annotation.style.fontWeight = "bold";
33745
+ }
33746
+ if (run.italic) {
33747
+ annotation.style.fontStyle = "italic";
33748
+ }
33749
+ if (run.underline) {
33750
+ annotation.style.textDecoration = "underline";
33751
+ }
33752
+ annotation.style.zIndex = "1";
33753
+ const content = this.doc.createElement("span");
33754
+ content.classList.add("annotation-content");
33755
+ content.style.pointerEvents = "none";
33756
+ content.setAttribute("contenteditable", "false");
33757
+ switch (run.variant) {
33758
+ case "image":
33759
+ case "signature": {
33760
+ if (run.imageSrc) {
33761
+ const img = this.doc.createElement("img");
33762
+ const isDataUrl = run.imageSrc.startsWith("data:");
33763
+ if (isDataUrl) {
33764
+ if (run.imageSrc.length <= MAX_DATA_URL_LENGTH && VALID_IMAGE_DATA_URL.test(run.imageSrc)) {
33765
+ img.src = run.imageSrc;
33766
+ } else {
33767
+ content.textContent = run.displayLabel;
33768
+ break;
33769
+ }
33770
+ } else {
33771
+ const sanitized = sanitizeHref(run.imageSrc);
33772
+ if (sanitized) {
33773
+ img.src = sanitized.href;
33774
+ } else {
33775
+ content.textContent = run.displayLabel;
33776
+ break;
33777
+ }
33778
+ }
33779
+ img.alt = run.displayLabel;
33780
+ img.style.height = "auto";
33781
+ img.style.maxWidth = "100%";
33782
+ img.style.pointerEvents = "none";
33783
+ img.style.verticalAlign = "middle";
33784
+ if (run.variant === "signature") {
33785
+ img.style.maxHeight = "28px";
33786
+ }
33787
+ content.appendChild(img);
33788
+ annotation.style.display = "inline-block";
33789
+ content.style.display = "inline-block";
33790
+ } else {
33791
+ content.textContent = run.displayLabel || (run.variant === "signature" ? "Signature" : "");
33792
+ }
33793
+ break;
33794
+ }
33795
+ case "link": {
33796
+ if (run.linkUrl) {
33797
+ const link = this.doc.createElement("a");
33798
+ const sanitized = sanitizeHref(run.linkUrl);
33799
+ if (sanitized) {
33800
+ link.href = sanitized.href;
33801
+ link.target = "_blank";
33802
+ link.rel = "noopener noreferrer";
33803
+ link.textContent = run.linkUrl;
33804
+ link.style.textDecoration = "none";
33805
+ content.style.pointerEvents = "all";
33806
+ content.appendChild(link);
33807
+ } else {
33808
+ content.textContent = run.displayLabel;
33809
+ }
33810
+ } else {
33811
+ content.textContent = run.displayLabel;
33812
+ }
33813
+ break;
33814
+ }
33815
+ case "html": {
33816
+ if (run.rawHtml && typeof run.rawHtml === "string") {
33817
+ content.textContent = run.displayLabel;
33818
+ annotation.style.display = "inline-block";
33819
+ content.style.display = "inline-block";
33820
+ } else {
33821
+ content.textContent = run.displayLabel;
33822
+ }
33823
+ break;
33824
+ }
33825
+ case "text":
33826
+ case "checkbox":
33827
+ default: {
33828
+ content.textContent = run.displayLabel;
33829
+ break;
33830
+ }
33831
+ }
33832
+ annotation.appendChild(content);
33833
+ annotation.dataset.type = run.variant;
33834
+ if (run.fieldId) {
33835
+ annotation.dataset.fieldId = run.fieldId;
33836
+ }
33837
+ if (run.fieldType) {
33838
+ annotation.dataset.fieldType = run.fieldType;
33839
+ }
33840
+ annotation.draggable = true;
33841
+ annotation.dataset.draggable = "true";
33842
+ if (run.displayLabel) {
33843
+ annotation.dataset.displayLabel = run.displayLabel;
33844
+ }
33845
+ if (run.variant) {
33846
+ annotation.dataset.variant = run.variant;
33847
+ }
33848
+ assertPmPositions(run, "field annotation run");
33849
+ if (run.pmStart != null) {
33850
+ annotation.dataset.pmStart = String(run.pmStart);
33851
+ }
33852
+ if (run.pmEnd != null) {
33853
+ annotation.dataset.pmEnd = String(run.pmEnd);
33854
+ }
33855
+ this.applySdtDataset(annotation, run.sdt);
33856
+ return annotation;
33857
+ }
33858
+ /**
33859
+ * Renders a single line of a paragraph block.
33860
+ *
33861
+ * @param block - The paragraph block containing the line
33862
+ * @param line - The line measurement data
33863
+ * @param context - Rendering context with fragment information
33864
+ * @param availableWidthOverride - Optional override for available width used in justification calculations
33865
+ * @param lineIndex - Optional zero-based index of the line within the fragment
33866
+ * @param skipJustify - When true, prevents justification even if alignment is 'justify'
33867
+ * @returns The rendered line element
33868
+ */
33869
+ renderLine(block, line, context, availableWidthOverride, lineIndex, skipJustify) {
32755
33870
  if (!this.doc) {
32756
33871
  throw new Error("DomPainter: document is not available");
32757
33872
  }
@@ -32763,8 +33878,10 @@ const _DomPainter = class _DomPainter {
32763
33878
  el.setAttribute("styleid", styleId);
32764
33879
  }
32765
33880
  const alignment = block.attrs?.alignment;
32766
- if (alignment === "center" || alignment === "right" || alignment === "justify") {
32767
- el.style.textAlign = alignment === "justify" ? "justify" : alignment;
33881
+ if (alignment === "center" || alignment === "right") {
33882
+ el.style.textAlign = alignment;
33883
+ } else if (alignment === "justify") {
33884
+ el.style.textAlign = "left";
32768
33885
  } else {
32769
33886
  el.style.textAlign = "left";
32770
33887
  }
@@ -32777,6 +33894,7 @@ const _DomPainter = class _DomPainter {
32777
33894
  }
32778
33895
  const runsForLine = sliceRunsForLine(block, line);
32779
33896
  const trackedConfig = this.resolveTrackedChangesConfig(block);
33897
+ const textSlices = runsForLine.length > 0 ? runsForLine.filter((r2) => (r2.kind === "text" || r2.kind === void 0) && "text" in r2 && r2.text != null).map((r2) => r2.text) : gatherTextSlicesForLine(block, line);
32780
33898
  if (runsForLine.length === 0) {
32781
33899
  const span = this.doc.createElement("span");
32782
33900
  span.innerHTML = "&nbsp;";
@@ -32823,6 +33941,19 @@ const _DomPainter = class _DomPainter {
32823
33941
  });
32824
33942
  }
32825
33943
  const hasExplicitPositioning = line.segments?.some((seg) => seg.x !== void 0);
33944
+ const availableWidth = availableWidthOverride ?? line.maxWidth ?? line.width;
33945
+ const shouldJustify = !skipJustify && alignment === "justify" && !hasExplicitPositioning;
33946
+ if (shouldJustify) {
33947
+ const spaceCount = textSlices.reduce(
33948
+ (sum, s2) => sum + Array.from(s2).filter((ch) => ch === " " || ch === " ").length,
33949
+ 0
33950
+ );
33951
+ const slack = Math.max(0, availableWidth - line.width);
33952
+ if (spaceCount > 0 && slack > 0) {
33953
+ const extraPerSpace = slack / spaceCount;
33954
+ el.style.wordSpacing = `${extraPerSpace}px`;
33955
+ }
33956
+ }
32826
33957
  if (hasExplicitPositioning && line.segments) {
32827
33958
  let cumulativeX = 0;
32828
33959
  const segmentsByRun = /* @__PURE__ */ new Map();
@@ -32901,6 +34032,22 @@ const _DomPainter = class _DomPainter {
32901
34032
  if (this.isBreakRun(baseRun)) {
32902
34033
  continue;
32903
34034
  }
34035
+ if (this.isFieldAnnotationRun(baseRun)) {
34036
+ const elem = this.renderRun(baseRun, context, trackedConfig);
34037
+ if (elem) {
34038
+ if (styleId) {
34039
+ elem.setAttribute("styleid", styleId);
34040
+ }
34041
+ const runSegments2 = segmentsByRun.get(runIndex);
34042
+ const segX = runSegments2 && runSegments2[0]?.x !== void 0 ? runSegments2[0].x : cumulativeX;
34043
+ const segWidth = (runSegments2 && runSegments2[0]?.width !== void 0 ? runSegments2[0].width : 0) ?? 0;
34044
+ elem.style.position = "absolute";
34045
+ elem.style.left = `${segX}px`;
34046
+ el.appendChild(elem);
34047
+ cumulativeX = segX + segWidth;
34048
+ }
34049
+ continue;
34050
+ }
32904
34051
  const runSegments = segmentsByRun.get(runIndex);
32905
34052
  if (!runSegments || runSegments.length === 0) {
32906
34053
  continue;
@@ -32946,7 +34093,22 @@ const _DomPainter = class _DomPainter {
32946
34093
  });
32947
34094
  }
32948
34095
  } else {
34096
+ let currentInlineSdtWrapper = null;
34097
+ let currentInlineSdtId = null;
34098
+ const closeCurrentWrapper = () => {
34099
+ if (currentInlineSdtWrapper) {
34100
+ el.appendChild(currentInlineSdtWrapper);
34101
+ currentInlineSdtWrapper = null;
34102
+ currentInlineSdtId = null;
34103
+ }
34104
+ };
32949
34105
  runsForLine.forEach((run) => {
34106
+ const runSdt = run.sdt;
34107
+ const isInlineSdt = runSdt?.type === "structuredContent" && runSdt?.scope === "inline";
34108
+ const runSdtId = isInlineSdt && runSdt?.id ? String(runSdt.id) : null;
34109
+ if (runSdtId !== currentInlineSdtId) {
34110
+ closeCurrentWrapper();
34111
+ }
32950
34112
  if (run.kind === "tab") {
32951
34113
  const tabEl = this.doc.createElement("span");
32952
34114
  tabEl.classList.add("superdoc-tab");
@@ -32974,9 +34136,37 @@ const _DomPainter = class _DomPainter {
32974
34136
  if (styleId) {
32975
34137
  elem.setAttribute("styleid", styleId);
32976
34138
  }
32977
- el.appendChild(elem);
34139
+ if (isInlineSdt && runSdtId && this.doc) {
34140
+ if (!currentInlineSdtWrapper) {
34141
+ currentInlineSdtWrapper = this.doc.createElement("span");
34142
+ currentInlineSdtWrapper.className = "superdoc-structured-content-inline";
34143
+ currentInlineSdtId = runSdtId;
34144
+ this.applySdtDataset(currentInlineSdtWrapper, runSdt);
34145
+ const alias = runSdt?.alias || "Inline content";
34146
+ const labelEl = this.doc.createElement("span");
34147
+ labelEl.className = "superdoc-structured-content-inline__label";
34148
+ labelEl.textContent = alias;
34149
+ currentInlineSdtWrapper.appendChild(labelEl);
34150
+ }
34151
+ const wrapperPmStart = currentInlineSdtWrapper.dataset.pmStart;
34152
+ const wrapperPmEnd = currentInlineSdtWrapper.dataset.pmEnd;
34153
+ if (run.pmStart != null) {
34154
+ if (!wrapperPmStart || run.pmStart < parseInt(wrapperPmStart, 10)) {
34155
+ currentInlineSdtWrapper.dataset.pmStart = String(run.pmStart);
34156
+ }
34157
+ }
34158
+ if (run.pmEnd != null) {
34159
+ if (!wrapperPmEnd || run.pmEnd > parseInt(wrapperPmEnd, 10)) {
34160
+ currentInlineSdtWrapper.dataset.pmEnd = String(run.pmEnd);
34161
+ }
34162
+ }
34163
+ currentInlineSdtWrapper.appendChild(elem);
34164
+ } else {
34165
+ el.appendChild(elem);
34166
+ }
32978
34167
  }
32979
34168
  });
34169
+ closeCurrentWrapper();
32980
34170
  }
32981
34171
  const anchors = el.querySelectorAll("a[href]");
32982
34172
  anchors.forEach((anchor) => {
@@ -33484,7 +34674,7 @@ const deriveBlockVersion = (block) => {
33484
34674
  return block.id;
33485
34675
  };
33486
34676
  const applyRunStyles = (element, run, _isLink = false) => {
33487
- if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak" || run.kind === "break") {
34677
+ if (run.kind === "tab" || run.kind === "image" || run.kind === "lineBreak" || run.kind === "break" || run.kind === "fieldAnnotation") {
33488
34678
  return;
33489
34679
  }
33490
34680
  element.style.fontFamily = run.fontFamily;
@@ -33606,6 +34796,23 @@ const applyParagraphShadingStyles = (element, shading) => {
33606
34796
  if (!shading?.fill) return;
33607
34797
  element.style.backgroundColor = shading.fill;
33608
34798
  };
34799
+ const gatherTextSlicesForLine = (block, line) => {
34800
+ const slices = [];
34801
+ const startRun = line.fromRun ?? 0;
34802
+ const endRun = line.toRun ?? startRun;
34803
+ for (let runIndex = startRun; runIndex <= endRun; runIndex += 1) {
34804
+ const run = block.runs[runIndex];
34805
+ if (!run || run.kind !== "text" && run.kind !== void 0 || !("text" in run) || !run.text) continue;
34806
+ const isFirst = runIndex === startRun;
34807
+ const isLast = runIndex === endRun;
34808
+ const start2 = isFirst ? line.fromChar ?? 0 : 0;
34809
+ const end2 = isLast ? line.toChar ?? run.text.length : run.text.length;
34810
+ if (start2 >= end2) continue;
34811
+ const slice2 = run.text.slice(start2, end2);
34812
+ if (slice2) slices.push(slice2);
34813
+ }
34814
+ return slices;
34815
+ };
33609
34816
  const sliceRunsForLine = (block, line) => {
33610
34817
  const result = [];
33611
34818
  for (let runIndex = line.fromRun; runIndex <= line.toRun; runIndex += 1) {
@@ -33627,6 +34834,10 @@ const sliceRunsForLine = (block, line) => {
33627
34834
  result.push(run);
33628
34835
  continue;
33629
34836
  }
34837
+ if (run.kind === "fieldAnnotation") {
34838
+ result.push(run);
34839
+ continue;
34840
+ }
33630
34841
  if (!("text" in run)) {
33631
34842
  continue;
33632
34843
  }
@@ -33942,6 +35153,10 @@ const DEFAULT_TAB_INTERVAL_PX = twipsToPx(DEFAULT_TAB_INTERVAL_TWIPS);
33942
35153
  const TAB_EPSILON = 0.1;
33943
35154
  const DEFAULT_DECIMAL_SEPARATOR = ".";
33944
35155
  const ALLOWED_TAB_VALS = /* @__PURE__ */ new Set(["start", "center", "end", "decimal", "bar", "clear"]);
35156
+ const FIELD_ANNOTATION_PILL_PADDING = 8;
35157
+ const FIELD_ANNOTATION_LINE_HEIGHT_MULTIPLIER = 1.2;
35158
+ const FIELD_ANNOTATION_VERTICAL_PADDING = 6;
35159
+ const DEFAULT_FIELD_ANNOTATION_FONT_SIZE = 16;
33945
35160
  const roundValue = (value) => value;
33946
35161
  function getCanvasContext() {
33947
35162
  if (!canvasContext) {
@@ -34021,6 +35236,9 @@ function isImageRun(run) {
34021
35236
  function isLineBreakRun(run) {
34022
35237
  return run.kind === "lineBreak";
34023
35238
  }
35239
+ function isFieldAnnotationRun(run) {
35240
+ return run.kind === "fieldAnnotation";
35241
+ }
34024
35242
  async function measureBlock(block, constraints) {
34025
35243
  const normalized = normalizeConstraints(constraints);
34026
35244
  if (block.kind === "drawing") {
@@ -34387,6 +35605,92 @@ async function measureParagraphBlock(block, maxWidth) {
34387
35605
  lastAppliedTabAlign = null;
34388
35606
  continue;
34389
35607
  }
35608
+ if (isFieldAnnotationRun(run)) {
35609
+ const displayText = run.displayLabel || "";
35610
+ const annotationFontSize = typeof run.fontSize === "number" ? run.fontSize : typeof run.fontSize === "string" ? parseFloat(run.fontSize) || DEFAULT_FIELD_ANNOTATION_FONT_SIZE : DEFAULT_FIELD_ANNOTATION_FONT_SIZE;
35611
+ const annotationFontFamily = run.fontFamily || "Arial, sans-serif";
35612
+ const fontWeight = run.bold ? "bold" : "normal";
35613
+ const fontStyle = run.italic ? "italic" : "normal";
35614
+ const annotationFont = `${fontStyle} ${fontWeight} ${annotationFontSize}px ${annotationFontFamily}`;
35615
+ ctx2.font = annotationFont;
35616
+ const textWidth = displayText ? ctx2.measureText(displayText).width : 0;
35617
+ const annotationWidth = textWidth + FIELD_ANNOTATION_PILL_PADDING;
35618
+ const annotationHeight = annotationFontSize * FIELD_ANNOTATION_LINE_HEIGHT_MULTIPLIER + FIELD_ANNOTATION_VERTICAL_PADDING;
35619
+ let annotationStartX;
35620
+ if (pendingTabAlignment && currentLine) {
35621
+ annotationStartX = alignPendingTabForWidth(annotationWidth);
35622
+ }
35623
+ if (!currentLine) {
35624
+ currentLine = {
35625
+ fromRun: runIndex,
35626
+ fromChar: 0,
35627
+ toRun: runIndex,
35628
+ toChar: 1,
35629
+ // Field annotations are atomic units
35630
+ width: annotationWidth,
35631
+ maxFontSize: annotationHeight,
35632
+ maxWidth: getEffectiveWidth(initialAvailableWidth),
35633
+ segments: [
35634
+ {
35635
+ runIndex,
35636
+ fromChar: 0,
35637
+ toChar: 1,
35638
+ width: annotationWidth,
35639
+ ...annotationStartX !== void 0 ? { x: annotationStartX } : {}
35640
+ }
35641
+ ]
35642
+ };
35643
+ continue;
35644
+ }
35645
+ if (currentLine.width + annotationWidth > currentLine.maxWidth && currentLine.width > 0) {
35646
+ const metrics = calculateTypographyMetrics(currentLine.maxFontSize, spacing, currentLine.maxFontInfo);
35647
+ const completedLine = {
35648
+ ...currentLine,
35649
+ ...metrics
35650
+ };
35651
+ addBarTabsToLine(completedLine);
35652
+ lines.push(completedLine);
35653
+ tabStopCursor = 0;
35654
+ pendingTabAlignment = null;
35655
+ lastAppliedTabAlign = null;
35656
+ currentLine = {
35657
+ fromRun: runIndex,
35658
+ fromChar: 0,
35659
+ toRun: runIndex,
35660
+ toChar: 1,
35661
+ width: annotationWidth,
35662
+ maxFontSize: annotationHeight,
35663
+ maxWidth: getEffectiveWidth(contentWidth),
35664
+ segments: [
35665
+ {
35666
+ runIndex,
35667
+ fromChar: 0,
35668
+ toChar: 1,
35669
+ width: annotationWidth
35670
+ }
35671
+ ]
35672
+ };
35673
+ } else {
35674
+ currentLine.toRun = runIndex;
35675
+ currentLine.toChar = 1;
35676
+ currentLine.width = roundValue(currentLine.width + annotationWidth);
35677
+ currentLine.maxFontSize = Math.max(currentLine.maxFontSize, annotationHeight);
35678
+ if (!currentLine.segments) currentLine.segments = [];
35679
+ currentLine.segments.push({
35680
+ runIndex,
35681
+ fromChar: 0,
35682
+ toChar: 1,
35683
+ width: annotationWidth,
35684
+ ...annotationStartX !== void 0 ? { x: annotationStartX } : {}
35685
+ });
35686
+ }
35687
+ const tabAlign = lastAppliedTabAlign;
35688
+ if (tabAlign && currentLine && tabAlign.val === "end") {
35689
+ currentLine.width = roundValue(tabAlign.target);
35690
+ }
35691
+ lastAppliedTabAlign = null;
35692
+ continue;
35693
+ }
34390
35694
  if (!("text" in run) || !("fontSize" in run)) {
34391
35695
  continue;
34392
35696
  }
@@ -36460,6 +37764,12 @@ function isInRegisteredSurface(event) {
36460
37764
  }
36461
37765
  return false;
36462
37766
  }
37767
+ function isValidFieldAnnotationAttributes(attrs) {
37768
+ if (!attrs || typeof attrs !== "object") return false;
37769
+ const a = attrs;
37770
+ return typeof a.fieldId === "string" && typeof a.fieldType === "string" && typeof a.displayLabel === "string" && typeof a.type === "string";
37771
+ }
37772
+ const FIELD_ANNOTATION_DATA_TYPE = "fieldAnnotation";
36463
37773
  const DEFAULT_PAGE_SIZE = { w: 612, h: 792 };
36464
37774
  const DEFAULT_MARGINS = { top: 72, right: 72, bottom: 72, left: 72 };
36465
37775
  const WORD_CHARACTER_REGEX = /[\p{L}\p{N}''_~-]/u;
@@ -36485,6 +37795,7 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36485
37795
  __privateAdd(this, _layoutOptions);
36486
37796
  __privateAdd(this, _layoutState, { blocks: [], measures: [], layout: null });
36487
37797
  __privateAdd(this, _domPainter, null);
37798
+ __privateAdd(this, _dragHandlerCleanup, null);
36488
37799
  __privateAdd(this, _layoutError, null);
36489
37800
  __privateAdd(this, _layoutErrorState, "healthy");
36490
37801
  __privateAdd(this, _errorBanner, null);
@@ -36529,6 +37840,10 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36529
37840
  __privateAdd(this, _lastClickTime, 0);
36530
37841
  __privateAdd(this, _lastClickPosition, { x: 0, y: 0 });
36531
37842
  __privateAdd(this, _lastSelectedImageBlockId, null);
37843
+ // Drag selection state
37844
+ __privateAdd(this, _dragAnchor, null);
37845
+ __privateAdd(this, _isDragging, false);
37846
+ __privateAdd(this, _dragExtensionMode, "char");
36532
37847
  // Remote cursor/presence state management
36533
37848
  /** Map of clientId -> normalized remote cursor state */
36534
37849
  __privateAdd(this, _remoteCursorState, /* @__PURE__ */ new Map());
@@ -36550,8 +37865,12 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36550
37865
  if (event.button !== 0) {
36551
37866
  return;
36552
37867
  }
37868
+ const target = event.target;
37869
+ const isDraggableAnnotation = target?.closest?.('[data-draggable="true"]') != null;
36553
37870
  if (!__privateGet(this, _layoutState).layout) {
36554
- event.preventDefault();
37871
+ if (!isDraggableAnnotation) {
37872
+ event.preventDefault();
37873
+ }
36555
37874
  if (document.activeElement instanceof HTMLElement) {
36556
37875
  document.activeElement.blur();
36557
37876
  }
@@ -36560,10 +37879,10 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36560
37879
  return;
36561
37880
  }
36562
37881
  const validPos = __privateMethod(this, _PresentationEditor_instances, getFirstTextPosition_fn).call(this);
36563
- const doc2 = __privateGet(this, _editor3)?.state?.doc;
36564
- if (doc2) {
37882
+ const doc22 = __privateGet(this, _editor3)?.state?.doc;
37883
+ if (doc22) {
36565
37884
  try {
36566
- const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(doc2, validPos));
37885
+ const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(doc22, validPos));
36567
37886
  __privateGet(this, _editor3).view?.dispatch(tr);
36568
37887
  } catch (error) {
36569
37888
  if (process$1.env.NODE_ENV === "development") {
@@ -36599,7 +37918,7 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36599
37918
  if (headerFooterRegion) {
36600
37919
  return;
36601
37920
  }
36602
- const hit = clickToPosition(
37921
+ const rawHit = clickToPosition(
36603
37922
  __privateGet(this, _layoutState).layout,
36604
37923
  __privateGet(this, _layoutState).blocks,
36605
37924
  __privateGet(this, _layoutState).measures,
@@ -36608,7 +37927,11 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36608
37927
  event.clientX,
36609
37928
  event.clientY
36610
37929
  );
36611
- event.preventDefault();
37930
+ const doc2 = __privateGet(this, _editor3).state?.doc;
37931
+ const hit = rawHit && doc2 ? { ...rawHit, pos: Math.max(0, Math.min(rawHit.pos, doc2.content.size)) } : rawHit;
37932
+ if (!isDraggableAnnotation) {
37933
+ event.preventDefault();
37934
+ }
36612
37935
  if (!hit) {
36613
37936
  if (document.activeElement instanceof HTMLElement) {
36614
37937
  document.activeElement.blur();
@@ -36616,10 +37939,10 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36616
37939
  const editorDom2 = __privateGet(this, _editor3).view?.dom;
36617
37940
  if (editorDom2) {
36618
37941
  const validPos = __privateMethod(this, _PresentationEditor_instances, getFirstTextPosition_fn).call(this);
36619
- const doc2 = __privateGet(this, _editor3)?.state?.doc;
36620
- if (doc2) {
37942
+ const doc22 = __privateGet(this, _editor3)?.state?.doc;
37943
+ if (doc22) {
36621
37944
  try {
36622
- const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(doc2, validPos));
37945
+ const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(doc22, validPos));
36623
37946
  __privateGet(this, _editor3).view?.dispatch(tr);
36624
37947
  } catch (error) {
36625
37948
  if (process$1.env.NODE_ENV === "development") {
@@ -36640,9 +37963,9 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36640
37963
  hit.pos
36641
37964
  );
36642
37965
  if (fragmentHit && (fragmentHit.fragment.kind === "image" || fragmentHit.fragment.kind === "drawing")) {
36643
- const doc2 = __privateGet(this, _editor3).state.doc;
37966
+ const doc22 = __privateGet(this, _editor3).state.doc;
36644
37967
  try {
36645
- const tr = __privateGet(this, _editor3).state.tr.setSelection(NodeSelection.create(doc2, hit.pos));
37968
+ const tr = __privateGet(this, _editor3).state.tr.setSelection(NodeSelection.create(doc22, hit.pos));
36646
37969
  __privateGet(this, _editor3).view?.dispatch(tr);
36647
37970
  if (__privateGet(this, _lastSelectedImageBlockId) && __privateGet(this, _lastSelectedImageBlockId) !== fragmentHit.fragment.blockId) {
36648
37971
  this.emit("imageDeselected", { blockId: __privateGet(this, _lastSelectedImageBlockId) });
@@ -36680,18 +38003,61 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36680
38003
  this.emit("imageDeselected", { blockId: __privateGet(this, _lastSelectedImageBlockId) });
36681
38004
  __privateSet(this, _lastSelectedImageBlockId, null);
36682
38005
  }
38006
+ if (event.shiftKey && __privateGet(this, _editor3).state.selection.$anchor) {
38007
+ const anchor = __privateGet(this, _editor3).state.selection.anchor;
38008
+ const head = hit.pos;
38009
+ const { selAnchor, selHead } = __privateMethod(this, _PresentationEditor_instances, calculateExtendedSelection_fn).call(this, anchor, head, __privateGet(this, _dragExtensionMode));
38010
+ try {
38011
+ const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(__privateGet(this, _editor3).state.doc, selAnchor, selHead));
38012
+ __privateGet(this, _editor3).view?.dispatch(tr);
38013
+ __privateMethod(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
38014
+ } catch (error) {
38015
+ console.warn("[SELECTION] Failed to extend selection on shift+click:", {
38016
+ error,
38017
+ anchor,
38018
+ head,
38019
+ selAnchor,
38020
+ selHead,
38021
+ mode: __privateGet(this, _dragExtensionMode)
38022
+ });
38023
+ }
38024
+ if (document.activeElement instanceof HTMLElement) {
38025
+ document.activeElement.blur();
38026
+ }
38027
+ const editorDom2 = __privateGet(this, _editor3).view?.dom;
38028
+ if (editorDom2) {
38029
+ editorDom2.focus();
38030
+ __privateGet(this, _editor3).view?.focus();
38031
+ }
38032
+ return;
38033
+ }
36683
38034
  const clickDepth = __privateMethod(this, _PresentationEditor_instances, registerPointerClick_fn).call(this, event);
38035
+ if (clickDepth === 1) {
38036
+ __privateSet(this, _dragAnchor, hit.pos);
38037
+ }
38038
+ __privateSet(this, _isDragging, true);
38039
+ if (clickDepth >= 3) {
38040
+ __privateSet(this, _dragExtensionMode, "para");
38041
+ } else if (clickDepth === 2) {
38042
+ __privateSet(this, _dragExtensionMode, "word");
38043
+ } else {
38044
+ __privateSet(this, _dragExtensionMode, "char");
38045
+ }
38046
+ if (typeof __privateGet(this, _viewportHost).setPointerCapture === "function") {
38047
+ __privateGet(this, _viewportHost).setPointerCapture(event.pointerId);
38048
+ }
36684
38049
  let handledByDepth = false;
36685
38050
  if (__privateGet(this, _session).mode === "body") {
38051
+ const selectionPos = clickDepth >= 2 && __privateGet(this, _dragAnchor) !== null ? __privateGet(this, _dragAnchor) : hit.pos;
36686
38052
  if (clickDepth >= 3) {
36687
- handledByDepth = __privateMethod(this, _PresentationEditor_instances, selectParagraphAt_fn).call(this, hit.pos);
38053
+ handledByDepth = __privateMethod(this, _PresentationEditor_instances, selectParagraphAt_fn).call(this, selectionPos);
36688
38054
  } else if (clickDepth === 2) {
36689
- handledByDepth = __privateMethod(this, _PresentationEditor_instances, selectWordAt_fn).call(this, hit.pos);
38055
+ handledByDepth = __privateMethod(this, _PresentationEditor_instances, selectWordAt_fn).call(this, selectionPos);
36690
38056
  }
36691
38057
  }
36692
38058
  if (!handledByDepth) {
36693
- const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(__privateGet(this, _editor3).state.doc, hit.pos));
36694
38059
  try {
38060
+ const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(__privateGet(this, _editor3).state.doc, hit.pos));
36695
38061
  __privateGet(this, _editor3).view?.dispatch(tr);
36696
38062
  } catch {
36697
38063
  }
@@ -36711,6 +38077,36 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36711
38077
  if (!__privateGet(this, _layoutState).layout) return;
36712
38078
  const normalized = __privateMethod(this, _PresentationEditor_instances, normalizeClientPoint_fn).call(this, event.clientX, event.clientY);
36713
38079
  if (!normalized) return;
38080
+ if (__privateGet(this, _isDragging) && __privateGet(this, _dragAnchor) !== null && event.buttons & 1) {
38081
+ const hit = clickToPosition(
38082
+ __privateGet(this, _layoutState).layout,
38083
+ __privateGet(this, _layoutState).blocks,
38084
+ __privateGet(this, _layoutState).measures,
38085
+ { x: normalized.x, y: normalized.y },
38086
+ __privateGet(this, _viewportHost),
38087
+ event.clientX,
38088
+ event.clientY
38089
+ );
38090
+ if (!hit) return;
38091
+ const anchor = __privateGet(this, _dragAnchor);
38092
+ const head = hit.pos;
38093
+ const { selAnchor, selHead } = __privateMethod(this, _PresentationEditor_instances, calculateExtendedSelection_fn).call(this, anchor, head, __privateGet(this, _dragExtensionMode));
38094
+ try {
38095
+ const tr = __privateGet(this, _editor3).state.tr.setSelection(TextSelection.create(__privateGet(this, _editor3).state.doc, selAnchor, selHead));
38096
+ __privateGet(this, _editor3).view?.dispatch(tr);
38097
+ __privateMethod(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
38098
+ } catch (error) {
38099
+ console.warn("[SELECTION] Failed to extend selection during drag:", {
38100
+ error,
38101
+ anchor,
38102
+ head,
38103
+ selAnchor,
38104
+ selHead,
38105
+ mode: __privateGet(this, _dragExtensionMode)
38106
+ });
38107
+ }
38108
+ return;
38109
+ }
36714
38110
  if (__privateGet(this, _session).mode !== "body") {
36715
38111
  __privateMethod(this, _PresentationEditor_instances, clearHoverRegion_fn).call(this);
36716
38112
  return;
@@ -36729,6 +38125,140 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36729
38125
  __privateAdd(this, _handlePointerLeave, () => {
36730
38126
  __privateMethod(this, _PresentationEditor_instances, clearHoverRegion_fn).call(this);
36731
38127
  });
38128
+ __privateAdd(this, _handlePointerUp, (event) => {
38129
+ if (!__privateGet(this, _isDragging)) return;
38130
+ if (typeof __privateGet(this, _viewportHost).hasPointerCapture === "function" && typeof __privateGet(this, _viewportHost).releasePointerCapture === "function" && __privateGet(this, _viewportHost).hasPointerCapture(event.pointerId)) {
38131
+ __privateGet(this, _viewportHost).releasePointerCapture(event.pointerId);
38132
+ }
38133
+ __privateSet(this, _isDragging, false);
38134
+ });
38135
+ /**
38136
+ * Handles dragover events for field annotation drag-and-drop operations.
38137
+ * Updates the cursor position during drag to provide visual feedback.
38138
+ *
38139
+ * @param event - The dragover event from the browser
38140
+ *
38141
+ * Side effects:
38142
+ * - Prevents default browser drag behavior
38143
+ * - Sets dropEffect to 'copy' to indicate the drag operation type
38144
+ * - Updates the editor's text selection to follow the drag cursor
38145
+ * - Triggers selection overlay updates via #scheduleSelectionUpdate
38146
+ *
38147
+ * Early returns:
38148
+ * - If the editor is not editable
38149
+ * - If no field annotation data is present in the drag
38150
+ * - If hit testing fails or document is unavailable
38151
+ * - If the cursor position hasn't changed
38152
+ */
38153
+ __privateAdd(this, _handleDragOver, (event) => {
38154
+ const activeEditor = this.getActiveEditor();
38155
+ if (!activeEditor?.isEditable) {
38156
+ return;
38157
+ }
38158
+ event.preventDefault();
38159
+ if (event.dataTransfer) {
38160
+ event.dataTransfer.dropEffect = "copy";
38161
+ }
38162
+ const dt = event.dataTransfer;
38163
+ const hasFieldAnnotation = dt?.types?.includes(FIELD_ANNOTATION_DATA_TYPE) || Boolean(dt?.getData?.(FIELD_ANNOTATION_DATA_TYPE));
38164
+ if (!hasFieldAnnotation) {
38165
+ return;
38166
+ }
38167
+ const hit = this.hitTest(event.clientX, event.clientY);
38168
+ const doc2 = activeEditor.state?.doc;
38169
+ if (!hit || !doc2) {
38170
+ return;
38171
+ }
38172
+ const pos = Math.min(Math.max(hit.pos, 1), doc2.content.size);
38173
+ const currentSelection = activeEditor.state.selection;
38174
+ const isSameCursor = currentSelection instanceof TextSelection && currentSelection.from === pos && currentSelection.to === pos;
38175
+ if (isSameCursor) {
38176
+ return;
38177
+ }
38178
+ try {
38179
+ const tr = activeEditor.state.tr.setSelection(TextSelection.create(doc2, pos)).setMeta("addToHistory", false);
38180
+ activeEditor.view?.dispatch(tr);
38181
+ __privateMethod(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
38182
+ } catch (error) {
38183
+ if (process$1.env.NODE_ENV === "development") {
38184
+ console.debug("[PresentationEditor] Drag position update skipped:", error);
38185
+ }
38186
+ }
38187
+ });
38188
+ /**
38189
+ * Handles drop events for field annotation drag-and-drop operations.
38190
+ * Inserts a field annotation at the drop position and emits events for tracking.
38191
+ *
38192
+ * @param event - The drop event from the browser
38193
+ *
38194
+ * Side effects:
38195
+ * - Prevents default browser drop behavior and stops event propagation
38196
+ * - Inserts a field annotation node at the drop position
38197
+ * - Moves the cursor to just after the inserted node
38198
+ * - Emits 'fieldAnnotationDropped' event with drop metadata
38199
+ * - Focuses the editor view
38200
+ * - Triggers selection overlay updates via #scheduleSelectionUpdate
38201
+ *
38202
+ * Early returns:
38203
+ * - If the editor is not editable
38204
+ * - If no field annotation data is present in the drop
38205
+ * - If JSON parsing of the payload fails
38206
+ * - If hit testing and fallback position both fail
38207
+ * - If the parsed attributes fail validation
38208
+ *
38209
+ * Fallback behavior:
38210
+ * - If hit testing fails (e.g., during a reflow), falls back to current selection position
38211
+ * - If selection is unavailable, falls back to end of document
38212
+ */
38213
+ __privateAdd(this, _handleDrop, (event) => {
38214
+ const activeEditor = this.getActiveEditor();
38215
+ if (!activeEditor?.isEditable) {
38216
+ return;
38217
+ }
38218
+ if (event.dataTransfer?.types?.includes("application/x-field-annotation")) {
38219
+ return;
38220
+ }
38221
+ event.preventDefault();
38222
+ event.stopPropagation();
38223
+ const fieldAnnotationData = event.dataTransfer?.getData(FIELD_ANNOTATION_DATA_TYPE);
38224
+ if (!fieldAnnotationData) {
38225
+ return;
38226
+ }
38227
+ const hit = this.hitTest(event.clientX, event.clientY);
38228
+ const selection = activeEditor.state?.selection;
38229
+ const fallbackPos = selection?.from ?? activeEditor.state?.doc?.content.size ?? null;
38230
+ const pos = hit?.pos ?? fallbackPos;
38231
+ if (pos == null) {
38232
+ return;
38233
+ }
38234
+ let parsedData = null;
38235
+ try {
38236
+ parsedData = JSON.parse(fieldAnnotationData);
38237
+ } catch {
38238
+ return;
38239
+ }
38240
+ const { attributes, sourceField } = parsedData ?? {};
38241
+ activeEditor.emit?.("fieldAnnotationDropped", {
38242
+ sourceField,
38243
+ editor: activeEditor,
38244
+ coordinates: hit,
38245
+ pos
38246
+ });
38247
+ if (attributes && isValidFieldAnnotationAttributes(attributes)) {
38248
+ activeEditor.commands?.addFieldAnnotation?.(pos, attributes, true);
38249
+ const posAfter = Math.min(pos + 1, activeEditor.state?.doc?.content.size ?? pos + 1);
38250
+ const tr = activeEditor.state?.tr.setSelection(TextSelection.create(activeEditor.state.doc, posAfter));
38251
+ if (tr) {
38252
+ activeEditor.view?.dispatch(tr);
38253
+ }
38254
+ __privateMethod(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
38255
+ }
38256
+ const editorDom = activeEditor.view?.dom;
38257
+ if (editorDom) {
38258
+ editorDom.focus();
38259
+ activeEditor.view?.focus();
38260
+ }
38261
+ });
36732
38262
  __privateAdd(this, _handleDoubleClick, (event) => {
36733
38263
  if (event.button !== 0) return;
36734
38264
  if (!__privateGet(this, _layoutState).layout) return;
@@ -36918,6 +38448,7 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
36918
38448
  __privateMethod(this, _PresentationEditor_instances, applyZoom_fn).call(this);
36919
38449
  __privateMethod(this, _PresentationEditor_instances, setupEditorListeners_fn).call(this);
36920
38450
  __privateMethod(this, _PresentationEditor_instances, setupPointerHandlers_fn).call(this);
38451
+ __privateMethod(this, _PresentationEditor_instances, setupDragHandlers_fn).call(this);
36921
38452
  __privateMethod(this, _PresentationEditor_instances, setupInputBridge_fn).call(this);
36922
38453
  __privateMethod(this, _PresentationEditor_instances, syncTrackedChangesPreferences_fn).call(this);
36923
38454
  if (options.documentId) {
@@ -37629,6 +39160,7 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
37629
39160
  * Safe to call during partial initialization.
37630
39161
  */
37631
39162
  destroy() {
39163
+ var _a;
37632
39164
  if (__privateGet(this, _rafHandle) != null) {
37633
39165
  __privateMethod(this, _PresentationEditor_instances, safeCleanup_fn).call(this, () => {
37634
39166
  const win = __privateGet(this, _visibleHost)?.ownerDocument?.defaultView ?? window;
@@ -37648,7 +39180,10 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
37648
39180
  __privateGet(this, _viewportHost)?.removeEventListener("pointerdown", __privateGet(this, _handlePointerDown));
37649
39181
  __privateGet(this, _viewportHost)?.removeEventListener("dblclick", __privateGet(this, _handleDoubleClick));
37650
39182
  __privateGet(this, _viewportHost)?.removeEventListener("pointermove", __privateGet(this, _handlePointerMove));
39183
+ __privateGet(this, _viewportHost)?.removeEventListener("pointerup", __privateGet(this, _handlePointerUp));
37651
39184
  __privateGet(this, _viewportHost)?.removeEventListener("pointerleave", __privateGet(this, _handlePointerLeave));
39185
+ __privateGet(this, _viewportHost)?.removeEventListener("dragover", __privateGet(this, _handleDragOver));
39186
+ __privateGet(this, _viewportHost)?.removeEventListener("drop", __privateGet(this, _handleDrop));
37652
39187
  __privateGet(this, _visibleHost)?.removeEventListener("keydown", __privateGet(this, _handleKeyDown));
37653
39188
  __privateGet(this, _inputBridge)?.notifyTargetChanged();
37654
39189
  __privateGet(this, _inputBridge)?.destroy();
@@ -37687,6 +39222,8 @@ const _PresentationEditor = class _PresentationEditor extends EventEmitter {
37687
39222
  __privateSet(this, _session, { mode: "body" });
37688
39223
  __privateSet(this, _activeHeaderFooterEditor, null);
37689
39224
  __privateSet(this, _domPainter, null);
39225
+ (_a = __privateGet(this, _dragHandlerCleanup)) == null ? void 0 : _a.call(this);
39226
+ __privateSet(this, _dragHandlerCleanup, null);
37690
39227
  __privateGet(this, _selectionOverlay2)?.remove();
37691
39228
  __privateGet(this, _painterHost)?.remove();
37692
39229
  __privateGet(this, _hiddenHost)?.remove();
@@ -37714,6 +39251,7 @@ _hiddenHost = new WeakMap();
37714
39251
  _layoutOptions = new WeakMap();
37715
39252
  _layoutState = new WeakMap();
37716
39253
  _domPainter = new WeakMap();
39254
+ _dragHandlerCleanup = new WeakMap();
37717
39255
  _layoutError = new WeakMap();
37718
39256
  _layoutErrorState = new WeakMap();
37719
39257
  _errorBanner = new WeakMap();
@@ -37757,6 +39295,9 @@ _clickCount = new WeakMap();
37757
39295
  _lastClickTime = new WeakMap();
37758
39296
  _lastClickPosition = new WeakMap();
37759
39297
  _lastSelectedImageBlockId = new WeakMap();
39298
+ _dragAnchor = new WeakMap();
39299
+ _isDragging = new WeakMap();
39300
+ _dragExtensionMode = new WeakMap();
37760
39301
  _remoteCursorState = new WeakMap();
37761
39302
  _remoteCursorDirty = new WeakMap();
37762
39303
  _remoteCursorOverlay = new WeakMap();
@@ -38209,9 +39750,106 @@ setupPointerHandlers_fn = function() {
38209
39750
  __privateGet(this, _viewportHost).addEventListener("pointerdown", __privateGet(this, _handlePointerDown));
38210
39751
  __privateGet(this, _viewportHost).addEventListener("dblclick", __privateGet(this, _handleDoubleClick));
38211
39752
  __privateGet(this, _viewportHost).addEventListener("pointermove", __privateGet(this, _handlePointerMove));
39753
+ __privateGet(this, _viewportHost).addEventListener("pointerup", __privateGet(this, _handlePointerUp));
38212
39754
  __privateGet(this, _viewportHost).addEventListener("pointerleave", __privateGet(this, _handlePointerLeave));
39755
+ __privateGet(this, _viewportHost).addEventListener("dragover", __privateGet(this, _handleDragOver));
39756
+ __privateGet(this, _viewportHost).addEventListener("drop", __privateGet(this, _handleDrop));
38213
39757
  __privateGet(this, _visibleHost).addEventListener("keydown", __privateGet(this, _handleKeyDown));
38214
39758
  };
39759
+ /**
39760
+ * Sets up drag and drop handlers for field annotations in the layout engine view.
39761
+ * Uses the DragHandler from layout-bridge to handle drag events and map drop
39762
+ * coordinates to ProseMirror positions.
39763
+ */
39764
+ setupDragHandlers_fn = function() {
39765
+ var _a;
39766
+ (_a = __privateGet(this, _dragHandlerCleanup)) == null ? void 0 : _a.call(this);
39767
+ __privateSet(this, _dragHandlerCleanup, null);
39768
+ __privateSet(this, _dragHandlerCleanup, createDragHandler(__privateGet(this, _painterHost), {
39769
+ onDragOver: (event) => {
39770
+ if (!event.hasFieldAnnotation || event.event.clientX === 0) {
39771
+ return;
39772
+ }
39773
+ const activeEditor = this.getActiveEditor();
39774
+ if (!activeEditor?.isEditable) {
39775
+ return;
39776
+ }
39777
+ const hit = this.hitTest(event.clientX, event.clientY);
39778
+ const doc2 = activeEditor.state?.doc;
39779
+ if (!hit || !doc2) {
39780
+ return;
39781
+ }
39782
+ const pos = Math.min(Math.max(hit.pos, 1), doc2.content.size);
39783
+ const currentSelection = activeEditor.state.selection;
39784
+ if (currentSelection instanceof TextSelection && currentSelection.from === pos && currentSelection.to === pos) {
39785
+ return;
39786
+ }
39787
+ try {
39788
+ const tr = activeEditor.state.tr.setSelection(TextSelection.create(doc2, pos)).setMeta("addToHistory", false);
39789
+ activeEditor.view?.dispatch(tr);
39790
+ __privateMethod(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
39791
+ } catch {
39792
+ }
39793
+ },
39794
+ onDrop: (event) => {
39795
+ event.event.preventDefault();
39796
+ event.event.stopPropagation();
39797
+ if (event.pmPosition === null) {
39798
+ return;
39799
+ }
39800
+ const activeEditor = this.getActiveEditor();
39801
+ const { state, view } = activeEditor;
39802
+ if (!state || !view) {
39803
+ return;
39804
+ }
39805
+ const fieldId = event.data.fieldId;
39806
+ if (fieldId) {
39807
+ const targetPos = event.pmPosition;
39808
+ let sourceStart = null;
39809
+ let sourceEnd = null;
39810
+ let sourceNode = null;
39811
+ state.doc.descendants((node, pos) => {
39812
+ if (node.type.name === "fieldAnnotation" && node.attrs.fieldId === fieldId) {
39813
+ sourceStart = pos;
39814
+ sourceEnd = pos + node.nodeSize;
39815
+ sourceNode = node;
39816
+ return false;
39817
+ }
39818
+ return true;
39819
+ });
39820
+ if (sourceStart === null || sourceEnd === null || !sourceNode) {
39821
+ return;
39822
+ }
39823
+ if (targetPos >= sourceStart && targetPos <= sourceEnd) {
39824
+ return;
39825
+ }
39826
+ const tr = state.tr;
39827
+ tr.delete(sourceStart, sourceEnd);
39828
+ const mappedTarget = tr.mapping.map(targetPos);
39829
+ if (mappedTarget < 0 || mappedTarget > tr.doc.content.size) {
39830
+ return;
39831
+ }
39832
+ tr.insert(mappedTarget, sourceNode);
39833
+ tr.setMeta("uiEvent", "drop");
39834
+ view.dispatch(tr);
39835
+ return;
39836
+ }
39837
+ const attrs = event.data.attributes;
39838
+ if (attrs && isValidFieldAnnotationAttributes(attrs)) {
39839
+ const inserted = activeEditor.commands?.addFieldAnnotation?.(event.pmPosition, attrs, true);
39840
+ if (inserted) {
39841
+ __privateMethod(this, _PresentationEditor_instances, scheduleSelectionUpdate_fn).call(this);
39842
+ }
39843
+ return;
39844
+ }
39845
+ activeEditor.emit("fieldAnnotationDropped", {
39846
+ sourceField: event.data,
39847
+ editor: activeEditor,
39848
+ coordinates: { pos: event.pmPosition }
39849
+ });
39850
+ }
39851
+ }));
39852
+ };
38215
39853
  setupInputBridge_fn = function() {
38216
39854
  __privateGet(this, _inputBridge)?.destroy();
38217
39855
  const win = __privateGet(this, _visibleHost).ownerDocument?.defaultView ?? window;
@@ -38309,8 +39947,11 @@ getFirstTextPosition_fn = function() {
38309
39947
  registerPointerClick_fn = function(event) {
38310
39948
  const MAX_CLICK_COUNT = 3;
38311
39949
  const time = event.timeStamp ?? performance.now();
38312
- const withinTime = time - __privateGet(this, _lastClickTime) <= MULTI_CLICK_TIME_THRESHOLD_MS;
38313
- const withinDistance = Math.abs(event.clientX - __privateGet(this, _lastClickPosition).x) <= MULTI_CLICK_DISTANCE_THRESHOLD_PX && Math.abs(event.clientY - __privateGet(this, _lastClickPosition).y) <= MULTI_CLICK_DISTANCE_THRESHOLD_PX;
39950
+ const timeDelta = time - __privateGet(this, _lastClickTime);
39951
+ const withinTime = timeDelta <= MULTI_CLICK_TIME_THRESHOLD_MS;
39952
+ const distanceX = Math.abs(event.clientX - __privateGet(this, _lastClickPosition).x);
39953
+ const distanceY = Math.abs(event.clientY - __privateGet(this, _lastClickPosition).y);
39954
+ const withinDistance = distanceX <= MULTI_CLICK_DISTANCE_THRESHOLD_PX && distanceY <= MULTI_CLICK_DISTANCE_THRESHOLD_PX;
38314
39955
  if (withinTime && withinDistance) {
38315
39956
  __privateSet(this, _clickCount, Math.min(__privateGet(this, _clickCount) + 1, MAX_CLICK_COUNT));
38316
39957
  } else {
@@ -38343,6 +39984,9 @@ selectWordAt_fn = function(pos) {
38343
39984
  if (!state?.doc) {
38344
39985
  return false;
38345
39986
  }
39987
+ if (pos < 0 || pos > state.doc.content.size) {
39988
+ return false;
39989
+ }
38346
39990
  const $pos = state.doc.resolve(pos);
38347
39991
  let textblockPos = $pos;
38348
39992
  while (textblockPos.depth > 0) {
@@ -38444,6 +40088,43 @@ selectParagraphAt_fn = function(pos) {
38444
40088
  return false;
38445
40089
  }
38446
40090
  };
40091
+ /**
40092
+ * Calculates extended selection boundaries based on the current extension mode.
40093
+ *
40094
+ * This helper method consolidates the logic for extending selections to word or paragraph
40095
+ * boundaries, used by both shift+click and drag selection handlers. It preserves selection
40096
+ * directionality by placing the head on the side where the user is clicking/dragging.
40097
+ *
40098
+ * @param anchor - The anchor position of the selection (fixed point)
40099
+ * @param head - The head position of the selection (moving point)
40100
+ * @param mode - The extension mode: 'char' (no extension), 'word', or 'para'
40101
+ * @returns Object with selAnchor and selHead positions after applying extension
40102
+ * @private
40103
+ */
40104
+ calculateExtendedSelection_fn = function(anchor, head, mode) {
40105
+ if (mode === "word") {
40106
+ const anchorBounds = findWordBoundaries(__privateGet(this, _layoutState).blocks, anchor);
40107
+ const headBounds = findWordBoundaries(__privateGet(this, _layoutState).blocks, head);
40108
+ if (anchorBounds && headBounds) {
40109
+ if (head >= anchor) {
40110
+ return { selAnchor: anchorBounds.from, selHead: headBounds.to };
40111
+ } else {
40112
+ return { selAnchor: anchorBounds.to, selHead: headBounds.from };
40113
+ }
40114
+ }
40115
+ } else if (mode === "para") {
40116
+ const anchorBounds = findParagraphBoundaries(__privateGet(this, _layoutState).blocks, anchor);
40117
+ const headBounds = findParagraphBoundaries(__privateGet(this, _layoutState).blocks, head);
40118
+ if (anchorBounds && headBounds) {
40119
+ if (head >= anchor) {
40120
+ return { selAnchor: anchorBounds.from, selHead: headBounds.to };
40121
+ } else {
40122
+ return { selAnchor: anchorBounds.to, selHead: headBounds.from };
40123
+ }
40124
+ }
40125
+ }
40126
+ return { selAnchor: anchor, selHead: head };
40127
+ };
38447
40128
  /**
38448
40129
  * Determines if a character is considered part of a word for selection purposes.
38449
40130
  *
@@ -38466,6 +40147,9 @@ isWordCharacter_fn = function(char) {
38466
40147
  };
38467
40148
  _handlePointerMove = new WeakMap();
38468
40149
  _handlePointerLeave = new WeakMap();
40150
+ _handlePointerUp = new WeakMap();
40151
+ _handleDragOver = new WeakMap();
40152
+ _handleDrop = new WeakMap();
38469
40153
  _handleDoubleClick = new WeakMap();
38470
40154
  _handleKeyDown = new WeakMap();
38471
40155
  focusHeaderFooterShortcut_fn = function(kind) {
@@ -39681,10 +41365,12 @@ convertPageLocalToOverlayCoords_fn = function(pageIndex, pageLocalX, pageLocalY)
39681
41365
  }
39682
41366
  const pageRect = pageEl.getBoundingClientRect();
39683
41367
  const overlayRect = __privateGet(this, _selectionOverlay2).getBoundingClientRect();
39684
- const zoom = __privateGet(this, _layoutOptions).zoom ?? 1;
41368
+ const layoutPageSize = __privateGet(this, _layoutState).layout?.pageSize;
41369
+ const scaleX = layoutPageSize && typeof layoutPageSize.w === "number" && layoutPageSize.w > 0 ? pageRect.width / layoutPageSize.w : 1;
41370
+ const scaleY = layoutPageSize && typeof layoutPageSize.h === "number" && layoutPageSize.h > 0 ? pageRect.height / layoutPageSize.h : 1;
39685
41371
  return {
39686
- x: pageRect.left - overlayRect.left + pageLocalX * zoom,
39687
- y: pageRect.top - overlayRect.top + pageLocalY * zoom
41372
+ x: pageRect.left - overlayRect.left + pageLocalX * scaleX,
41373
+ y: pageRect.top - overlayRect.top + pageLocalY * scaleY
39688
41374
  };
39689
41375
  };
39690
41376
  normalizeClientPoint_fn = function(clientX, clientY) {