oasis-editor 0.0.41 → 0.0.42

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.
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { n as normalizeSelection, g as getParagraphs, c as createEditorParagraphFromRuns, a as getParagraphLength, b as createEditorRun, d as getDocumentSections, e as createEditorStyledRun, f as getParagraphText, h as getActiveZone, i as getActiveSectionIndex, p as positionToParagraphOffset, j as paragraphOffsetToPosition, k as clampPosition, l as findParagraphIndex, m as createCollapsedSelection, o as isSelectionCollapsed, q as createEditorParagraph, r as getBlockParagraphs, s as findParagraphTableLocation, t as buildTableCellLayout, u as createEditorTableCell, v as createEditorTableRow, w as createEditorTable, x as underlineStyleToCssDecorationStyle, y as resolveImageSrc, z as createEditorFootnote, A as createFootnoteReferenceRun, B as renumberFootnotes, C as iterateFootnoteReferenceRuns, D as getFootnoteDisplayMarker, E as createSignal, F as createEffect, G as onCleanup, H as buildCanvasLayoutSnapshot, I as on, J as onMount, K as debounce, L as unwrap, M as getDocumentParagraphs, N as getDocumentSectionsCanonical, O as createEditorDocument, P as getPageContentWidth, Q as getDocumentPageSettings, R as getTableCellContentWidthForParagraph, S as resolveResizedDimensions, T as resolveTextBoxRenderHeight, U as resolveEffectiveParagraphStyle, V as resolveEffectiveTextStyleForParagraph, W as iterateEndnoteReferenceRuns, X as JSZip, Y as imageContentTypeDefaults, Z as imageExtensionFromMime, _ as pxToPt$1, $ as resolveFloatingObjectRect, a0 as getTextBoxFloatingGeometry, a1 as getPresetPathSegments, a2 as projectBlocksLayout, a3 as buildListLabels, a4 as textStyleToFontSizePt, a5 as PX_PER_POINT, a6 as DEFAULT_FONT_SIZE_PX, a7 as isDoubleUnderlineStyle, a8 as isWavyUnderlineStyle, a9 as underlineStyleLineWidthPx, aa as underlineStyleDashArray, ab as resolveListLabel, ac as getListLabelInset, ad as getAlignedListLabelInset, ae as getParagraphBorderInsets, af as buildSegmentTable, ag as buildCanvasTableLayout, ah as normalizeFamily, ai as ROBOTO_FONT_FILES, aj as loadFontAsset, ak as OFFICE_COMPAT_FONT_FAMILIES, al as buildSfnt, am as defaultFontDecoderRegistry, an as SfntFontProgram, ao as collectPdfFontFamilies, ap as projectDocumentLayout, aq as getPageHeaderZoneTop, ar as getPageBodyTop, as as getPageColumnRects, at as findFootnoteReference, au as FOOTNOTE_MARKER_GUTTER_PX, av as resolveImporterForFile, aw as createEditorStateFromDocument, ax as getDocumentParagraphsCanonical, ay as getToolbarStyleState, az as STANDARD_FONT_SIZES_PT, aA as fontSizePxToPt, aB as probeLocalFontFamilies, aC as createInitialEditorState, aD as parseFontSizePtToPx, aE as formatFontSizePt, aF as listKindForTag, aG as isParagraphTag, aH as collectInlineRuns, aI as parseParagraphStyle, aJ as getHeadingLevel, aK as preciseFontModeVersion, aL as isPreciseFontModeEnabled, aM as togglePreciseFontMode, aN as nextFontSizePt, aO as previousFontSizePt, aP as fontSizePtToPx, aQ as createDefaultToolbarPreset, aR as MenuRegistry, aS as createToolbarRegistry, aT as Editor, aU as resolveCommandRef, aV as commandRefName, aW as InlineShell, aX as BalloonShell, aY as DocumentShell, aZ as createMemo, a_ as getCaretRectFromSnapshot, a$ as getParagraphRectFromSnapshot, b0 as createComponent, b1 as CaretOverlay, b2 as Show, b3 as createRenderEffect, b4 as style, b5 as setAttribute, b6 as setStyleProperty, b7 as memo, b8 as template, b9 as useI18n, ba as insert, bb as use, bc as addEventListener, bd as Dialog, be as delegateEvents, bf as className, bg as For, bh as UNDERLINE_STYLE_OPTIONS, bi as Tabs, bj as measureParagraphMinContentWidthPx, bk as getEditableBlocksForZone, bl as findParagraphLocation, bm as createSectionBoundaryParagraph, bn as normalizePageSettings, bo as DEFAULT_EDITOR_PAGE_SETTINGS, bp as markStart, bq as markEnd, br as getParagraphEntries, bs as getParagraphById, bt as PluginUiHost, bu as OasisEditorEditor, bv as perfTimer, bw as OasisBrandMark, bx as setPreciseFontPreference, by as setWelcomeSeen, bz as enablePreciseFontMode, bA as createOasisEditorClient, bB as createEditorZoom, bC as startLongTaskObserver, bD as installGlobalReport, bE as applyStoredPreciseFontPreference, bF as getWelcomeSeen, bG as isLocalFontAccessSupported, bH as EDITOR_SCROLL_PADDING_PX, bI as Toolbar, bJ as OasisEditorLoading, bK as I18nProvider, bL as createEditorLogger, bM as createTranslator, bN as getCachedCanvasImage, bO as registerDomStatsSurface } from "./index-CEIWNJ4A.js";
4
+ import { n as normalizeSelection, g as getParagraphs, c as createEditorParagraphFromRuns, a as getParagraphLength, b as createEditorRun, d as getDocumentSections, e as createEditorStyledRun, f as getParagraphText, h as getActiveZone, i as getActiveSectionIndex, p as positionToParagraphOffset, j as paragraphOffsetToPosition, k as clampPosition, l as findParagraphIndex, m as createCollapsedSelection, o as isSelectionCollapsed, q as createEditorParagraph, r as getBlockParagraphs, s as findParagraphTableLocation, t as buildTableCellLayout, u as createEditorTableCell, v as createEditorTableRow, w as createEditorTable, x as underlineStyleToCssDecorationStyle, y as resolveImageSrc, z as createEditorFootnote, A as createFootnoteReferenceRun, B as renumberFootnotes, C as iterateFootnoteReferenceRuns, D as getFootnoteDisplayMarker, E as createSignal, F as createEffect, G as onCleanup, H as buildCanvasLayoutSnapshot, I as on, J as onMount, K as debounce, L as unwrap, M as getDocumentParagraphs, N as getDocumentSectionsCanonical, O as createEditorDocument, P as getPageContentWidth, Q as getDocumentPageSettings, R as getTableCellContentWidthForParagraph, S as resolveResizedDimensions, T as resolveTextBoxRenderHeight, U as resolveEffectiveParagraphStyle, V as resolveEffectiveTextStyleForParagraph, W as iterateEndnoteReferenceRuns, X as JSZip, Y as imageContentTypeDefaults, Z as imageExtensionFromMime, _ as pxToPt$1, $ as resolveFloatingObjectRect, a0 as getTextBoxFloatingGeometry, a1 as getPresetPathSegments, a2 as projectBlocksLayout, a3 as buildListLabels, a4 as textStyleToFontSizePt, a5 as PX_PER_POINT, a6 as DEFAULT_FONT_SIZE_PX, a7 as isDoubleUnderlineStyle, a8 as isWavyUnderlineStyle, a9 as underlineStyleLineWidthPx, aa as underlineStyleDashArray, ab as resolveListLabel, ac as getListLabelInset, ad as getAlignedListLabelInset, ae as getParagraphBorderInsets, af as buildSegmentTable, ag as buildCanvasTableLayout, ah as normalizeFamily, ai as ROBOTO_FONT_FILES, aj as loadFontAsset, ak as OFFICE_COMPAT_FONT_FAMILIES, al as buildSfnt, am as defaultFontDecoderRegistry, an as SfntFontProgram, ao as collectPdfFontFamilies, ap as projectDocumentLayout, aq as getPageHeaderZoneTop, ar as getPageBodyTop, as as getPageColumnRects, at as findFootnoteReference, au as FOOTNOTE_MARKER_GUTTER_PX, av as resolveImporterForFile, aw as createEditorStateFromDocument, ax as getDocumentParagraphsCanonical, ay as getToolbarStyleState, az as STANDARD_FONT_SIZES_PT, aA as fontSizePxToPt, aB as probeLocalFontFamilies, aC as createInitialEditorState, aD as parseFontSizePtToPx, aE as formatFontSizePt, aF as listKindForTag, aG as isParagraphTag, aH as collectInlineRuns, aI as parseParagraphStyle, aJ as getCachedCanvasImage, aK as getHeadingLevel, aL as preciseFontModeVersion, aM as isPreciseFontModeEnabled, aN as togglePreciseFontMode, aO as nextFontSizePt, aP as previousFontSizePt, aQ as fontSizePtToPx, aR as createDefaultToolbarPreset, aS as MenuRegistry, aT as createToolbarRegistry, aU as Editor, aV as resolveCommandRef, aW as commandRefName, aX as InlineShell, aY as BalloonShell, aZ as DocumentShell, a_ as createMemo, a$ as getCaretRectFromSnapshot, b0 as getParagraphRectFromSnapshot, b1 as createComponent, b2 as CaretOverlay, b3 as Show, b4 as createRenderEffect, b5 as style, b6 as setAttribute, b7 as setStyleProperty, b8 as memo, b9 as template, ba as useI18n, bb as insert, bc as use, bd as addEventListener, be as Dialog, bf as delegateEvents, bg as className, bh as For, bi as UNDERLINE_STYLE_OPTIONS, bj as Tabs, bk as measureParagraphMinContentWidthPx, bl as getEditableBlocksForZone, bm as findParagraphLocation, bn as createSectionBoundaryParagraph, bo as normalizePageSettings, bp as DEFAULT_EDITOR_PAGE_SETTINGS, bq as markStart, br as markEnd, bs as getParagraphEntries, bt as getParagraphById, bu as PluginUiHost, bv as OasisEditorEditor, bw as perfTimer, bx as OasisBrandMark, by as setPreciseFontPreference, bz as setWelcomeSeen, bA as enablePreciseFontMode, bB as createOasisEditorClient, bC as createEditorZoom, bD as startLongTaskObserver, bE as installGlobalReport, bF as applyStoredPreciseFontPreference, bG as getWelcomeSeen, bH as isLocalFontAccessSupported, bI as EDITOR_SCROLL_PADDING_PX, bJ as Toolbar, bK as OasisEditorLoading, bL as I18nProvider, bM as createEditorLogger, bN as createTranslator, bO as registerDomStatsSurface } from "./index-CTh8mekn.js";
5
5
  function getSelectedObjectRun(state, predicate) {
6
6
  const normalized = normalizeSelection(state);
7
7
  if (normalized.isCollapsed || normalized.startIndex !== normalized.endIndex || normalized.endParagraphOffset - normalized.startParagraphOffset !== 1) {
@@ -3840,186 +3840,6 @@ function insertFootnote(state) {
3840
3840
  activeFootnoteId: footnote.id
3841
3841
  };
3842
3842
  }
3843
- const RECTANGLE = [
3844
- { x: 0, y: 0 },
3845
- { x: 1, y: 0 },
3846
- { x: 1, y: 1 },
3847
- { x: 0, y: 1 }
3848
- ];
3849
- const MAX_SIDE = 256;
3850
- const ALPHA_THRESHOLD = 128;
3851
- const OPAQUE_RATIO = 0.985;
3852
- const MAX_POINTS = 40;
3853
- const contourCache = /* @__PURE__ */ new Map();
3854
- function rectangle() {
3855
- return RECTANGLE.map((point) => ({ ...point }));
3856
- }
3857
- const DIRS = [
3858
- [0, -1],
3859
- [1, -1],
3860
- [1, 0],
3861
- [1, 1],
3862
- [0, 1],
3863
- [-1, 1],
3864
- [-1, 0],
3865
- [-1, -1]
3866
- ];
3867
- function buildAlphaMask(img) {
3868
- const naturalW = img.naturalWidth || img.width;
3869
- const naturalH = img.naturalHeight || img.height;
3870
- if (!naturalW || !naturalH) {
3871
- return null;
3872
- }
3873
- const scale = Math.min(1, MAX_SIDE / Math.max(naturalW, naturalH));
3874
- const width = Math.max(1, Math.round(naturalW * scale));
3875
- const height = Math.max(1, Math.round(naturalH * scale));
3876
- const canvas = document.createElement("canvas");
3877
- canvas.width = width;
3878
- canvas.height = height;
3879
- const ctx = canvas.getContext("2d", { willReadFrequently: true });
3880
- if (!ctx) {
3881
- return null;
3882
- }
3883
- ctx.drawImage(img, 0, 0, width, height);
3884
- let pixels;
3885
- try {
3886
- pixels = ctx.getImageData(0, 0, width, height).data;
3887
- } catch {
3888
- return null;
3889
- }
3890
- const mask = new Uint8Array(width * height);
3891
- let foreground = 0;
3892
- for (let i = 0; i < mask.length; i += 1) {
3893
- if (pixels[i * 4 + 3] >= ALPHA_THRESHOLD) {
3894
- mask[i] = 1;
3895
- foreground += 1;
3896
- }
3897
- }
3898
- return { mask, width, height, foreground };
3899
- }
3900
- function traceBoundary(mask, width, height) {
3901
- const at = (x, y) => x >= 0 && x < width && y >= 0 && y < height && mask[y * width + x] === 1;
3902
- let startX = -1;
3903
- let startY = -1;
3904
- for (let y = 0; y < height && startY < 0; y += 1) {
3905
- for (let x = 0; x < width; x += 1) {
3906
- if (mask[y * width + x] === 1) {
3907
- startX = x;
3908
- startY = y;
3909
- break;
3910
- }
3911
- }
3912
- }
3913
- if (startX < 0) {
3914
- return [];
3915
- }
3916
- const contour = [];
3917
- let bx = startX;
3918
- let by = startY;
3919
- let backtrack = 6;
3920
- const maxSteps = width * height * 4;
3921
- for (let step = 0; step < maxSteps; step += 1) {
3922
- let moved = false;
3923
- for (let k = 1; k <= 8; k += 1) {
3924
- const dir = (backtrack + k) % 8;
3925
- const [dx, dy] = DIRS[dir];
3926
- const nx = bx + dx;
3927
- const ny = by + dy;
3928
- if (at(nx, ny)) {
3929
- contour.push([bx, by]);
3930
- backtrack = (dir + 4) % 8;
3931
- bx = nx;
3932
- by = ny;
3933
- moved = true;
3934
- break;
3935
- }
3936
- }
3937
- if (!moved) {
3938
- contour.push([bx, by]);
3939
- break;
3940
- }
3941
- if (bx === startX && by === startY && contour.length > 1) {
3942
- break;
3943
- }
3944
- }
3945
- return contour;
3946
- }
3947
- function perpendicularDistance(point, lineStart, lineEnd) {
3948
- const [px, py] = point;
3949
- const [ax, ay] = lineStart;
3950
- const [bx, by] = lineEnd;
3951
- const dx = bx - ax;
3952
- const dy = by - ay;
3953
- const lengthSq = dx * dx + dy * dy;
3954
- if (lengthSq === 0) {
3955
- return Math.hypot(px - ax, py - ay);
3956
- }
3957
- const cross = Math.abs(dx * (ay - py) - dy * (ax - px));
3958
- return cross / Math.sqrt(lengthSq);
3959
- }
3960
- function douglasPeucker(points, tolerance) {
3961
- if (points.length < 3) {
3962
- return points.slice();
3963
- }
3964
- let maxDist = 0;
3965
- let index = 0;
3966
- const first = points[0];
3967
- const last = points[points.length - 1];
3968
- for (let i = 1; i < points.length - 1; i += 1) {
3969
- const dist = perpendicularDistance(points[i], first, last);
3970
- if (dist > maxDist) {
3971
- maxDist = dist;
3972
- index = i;
3973
- }
3974
- }
3975
- if (maxDist <= tolerance) {
3976
- return [first, last];
3977
- }
3978
- const left = douglasPeucker(points.slice(0, index + 1), tolerance);
3979
- const right = douglasPeucker(points.slice(index), tolerance);
3980
- return [...left.slice(0, -1), ...right];
3981
- }
3982
- function traceAlphaMaskContour(mask, width, height) {
3983
- let foreground = 0;
3984
- for (let i = 0; i < mask.length; i += 1) {
3985
- if (mask[i] === 1) foreground += 1;
3986
- }
3987
- if (width <= 0 || height <= 0 || foreground === 0 || foreground / (width * height) >= OPAQUE_RATIO) {
3988
- return rectangle();
3989
- }
3990
- const boundary = traceBoundary(mask, width, height);
3991
- if (boundary.length < 3) {
3992
- return rectangle();
3993
- }
3994
- const tolerance = Math.max(width, height) * 0.012;
3995
- let simplified = douglasPeucker(boundary, tolerance);
3996
- let extraTolerance = tolerance;
3997
- while (simplified.length > MAX_POINTS) {
3998
- extraTolerance *= 1.6;
3999
- simplified = douglasPeucker(boundary, extraTolerance);
4000
- }
4001
- if (simplified.length < 3) {
4002
- return rectangle();
4003
- }
4004
- return simplified.map(([x, y]) => ({
4005
- x: Math.min(1, Math.max(0, x / width)),
4006
- y: Math.min(1, Math.max(0, y / height))
4007
- }));
4008
- }
4009
- function traceImageAlphaContour(img) {
4010
- const cacheKey = img.src;
4011
- const cached = contourCache.get(cacheKey);
4012
- if (cached) {
4013
- return cached.map((point) => ({ ...point }));
4014
- }
4015
- const built = buildAlphaMask(img);
4016
- if (!built) {
4017
- return rectangle();
4018
- }
4019
- const polygon = traceAlphaMaskContour(built.mask, built.width, built.height);
4020
- contourCache.set(cacheKey, polygon);
4021
- return polygon.map((point) => ({ ...point }));
4022
- }
4023
3843
  function cloneBlock(block) {
4024
3844
  return block.type === "paragraph" ? {
4025
3845
  ...block,
@@ -40916,6 +40736,249 @@ function createEditorTableContextMenuActions(deps) {
40916
40736
  )
40917
40737
  };
40918
40738
  }
40739
+ const RECTANGLE = [
40740
+ { x: 0, y: 0 },
40741
+ { x: 1, y: 0 },
40742
+ { x: 1, y: 1 },
40743
+ { x: 0, y: 1 }
40744
+ ];
40745
+ const MAX_SIDE = 256;
40746
+ const ALPHA_THRESHOLD = 128;
40747
+ const OPAQUE_RATIO = 0.985;
40748
+ const MAX_POINTS = 40;
40749
+ const contourCache = /* @__PURE__ */ new Map();
40750
+ function rectangle() {
40751
+ return RECTANGLE.map((point) => ({ ...point }));
40752
+ }
40753
+ const DIRS = [
40754
+ [0, -1],
40755
+ [1, -1],
40756
+ [1, 0],
40757
+ [1, 1],
40758
+ [0, 1],
40759
+ [-1, 1],
40760
+ [-1, 0],
40761
+ [-1, -1]
40762
+ ];
40763
+ function buildAlphaMask(img) {
40764
+ const naturalW = img.naturalWidth || img.width;
40765
+ const naturalH = img.naturalHeight || img.height;
40766
+ if (!naturalW || !naturalH) {
40767
+ return null;
40768
+ }
40769
+ const scale = Math.min(1, MAX_SIDE / Math.max(naturalW, naturalH));
40770
+ const width = Math.max(1, Math.round(naturalW * scale));
40771
+ const height = Math.max(1, Math.round(naturalH * scale));
40772
+ const canvas = document.createElement("canvas");
40773
+ canvas.width = width;
40774
+ canvas.height = height;
40775
+ const ctx = canvas.getContext("2d", { willReadFrequently: true });
40776
+ if (!ctx) {
40777
+ return null;
40778
+ }
40779
+ ctx.drawImage(img, 0, 0, width, height);
40780
+ let pixels;
40781
+ try {
40782
+ pixels = ctx.getImageData(0, 0, width, height).data;
40783
+ } catch {
40784
+ return null;
40785
+ }
40786
+ const mask = new Uint8Array(width * height);
40787
+ let foreground = 0;
40788
+ for (let i = 0; i < mask.length; i += 1) {
40789
+ if (pixels[i * 4 + 3] >= ALPHA_THRESHOLD) {
40790
+ mask[i] = 1;
40791
+ foreground += 1;
40792
+ }
40793
+ }
40794
+ return { mask, width, height, foreground };
40795
+ }
40796
+ function traceBoundary(mask, width, height) {
40797
+ const at = (x, y) => x >= 0 && x < width && y >= 0 && y < height && mask[y * width + x] === 1;
40798
+ let startX = -1;
40799
+ let startY = -1;
40800
+ for (let y = 0; y < height && startY < 0; y += 1) {
40801
+ for (let x = 0; x < width; x += 1) {
40802
+ if (mask[y * width + x] === 1) {
40803
+ startX = x;
40804
+ startY = y;
40805
+ break;
40806
+ }
40807
+ }
40808
+ }
40809
+ if (startX < 0) {
40810
+ return [];
40811
+ }
40812
+ const contour = [];
40813
+ let bx = startX;
40814
+ let by = startY;
40815
+ let backtrack = 6;
40816
+ const maxSteps = width * height * 4;
40817
+ for (let step = 0; step < maxSteps; step += 1) {
40818
+ let moved = false;
40819
+ for (let k = 1; k <= 8; k += 1) {
40820
+ const dir = (backtrack + k) % 8;
40821
+ const [dx, dy] = DIRS[dir];
40822
+ const nx = bx + dx;
40823
+ const ny = by + dy;
40824
+ if (at(nx, ny)) {
40825
+ contour.push([bx, by]);
40826
+ backtrack = (dir + 4) % 8;
40827
+ bx = nx;
40828
+ by = ny;
40829
+ moved = true;
40830
+ break;
40831
+ }
40832
+ }
40833
+ if (!moved) {
40834
+ contour.push([bx, by]);
40835
+ break;
40836
+ }
40837
+ if (bx === startX && by === startY && contour.length > 1) {
40838
+ break;
40839
+ }
40840
+ }
40841
+ return contour;
40842
+ }
40843
+ function perpendicularDistance(point, lineStart, lineEnd) {
40844
+ const [px, py] = point;
40845
+ const [ax, ay] = lineStart;
40846
+ const [bx, by] = lineEnd;
40847
+ const dx = bx - ax;
40848
+ const dy = by - ay;
40849
+ const lengthSq = dx * dx + dy * dy;
40850
+ if (lengthSq === 0) {
40851
+ return Math.hypot(px - ax, py - ay);
40852
+ }
40853
+ const cross = Math.abs(dx * (ay - py) - dy * (ax - px));
40854
+ return cross / Math.sqrt(lengthSq);
40855
+ }
40856
+ function douglasPeucker(points, tolerance) {
40857
+ if (points.length < 3) {
40858
+ return points.slice();
40859
+ }
40860
+ let maxDist = 0;
40861
+ let index = 0;
40862
+ const first = points[0];
40863
+ const last = points[points.length - 1];
40864
+ for (let i = 1; i < points.length - 1; i += 1) {
40865
+ const dist = perpendicularDistance(points[i], first, last);
40866
+ if (dist > maxDist) {
40867
+ maxDist = dist;
40868
+ index = i;
40869
+ }
40870
+ }
40871
+ if (maxDist <= tolerance) {
40872
+ return [first, last];
40873
+ }
40874
+ const left = douglasPeucker(points.slice(0, index + 1), tolerance);
40875
+ const right = douglasPeucker(points.slice(index), tolerance);
40876
+ return [...left.slice(0, -1), ...right];
40877
+ }
40878
+ function traceAlphaMaskContour(mask, width, height) {
40879
+ let foreground = 0;
40880
+ for (let i = 0; i < mask.length; i += 1) {
40881
+ if (mask[i] === 1) foreground += 1;
40882
+ }
40883
+ if (width <= 0 || height <= 0 || foreground === 0 || foreground / (width * height) >= OPAQUE_RATIO) {
40884
+ return rectangle();
40885
+ }
40886
+ const boundary = traceBoundary(mask, width, height);
40887
+ if (boundary.length < 3) {
40888
+ return rectangle();
40889
+ }
40890
+ const tolerance = Math.max(width, height) * 0.012;
40891
+ let simplified = douglasPeucker(boundary, tolerance);
40892
+ let extraTolerance = tolerance;
40893
+ while (simplified.length > MAX_POINTS) {
40894
+ extraTolerance *= 1.6;
40895
+ simplified = douglasPeucker(boundary, extraTolerance);
40896
+ }
40897
+ if (simplified.length < 3) {
40898
+ return rectangle();
40899
+ }
40900
+ return simplified.map(([x, y]) => ({
40901
+ x: Math.min(1, Math.max(0, x / width)),
40902
+ y: Math.min(1, Math.max(0, y / height))
40903
+ }));
40904
+ }
40905
+ function traceImageAlphaContour(img) {
40906
+ const cacheKey = img.src;
40907
+ const cached = contourCache.get(cacheKey);
40908
+ if (cached) {
40909
+ return cached.map((point) => ({ ...point }));
40910
+ }
40911
+ const built = buildAlphaMask(img);
40912
+ if (!built) {
40913
+ return rectangle();
40914
+ }
40915
+ const polygon = traceAlphaMaskContour(built.mask, built.width, built.height);
40916
+ contourCache.set(cacheKey, polygon);
40917
+ return polygon.map((point) => ({ ...point }));
40918
+ }
40919
+ function createEditorLayoutOptionsController(deps) {
40920
+ const { state, resetTransactionGrouping, applyTransactionalState, focusInput } = deps;
40921
+ const layoutOptionsTarget = () => {
40922
+ if (getSelectedImageRun(state())) return "image";
40923
+ if (getSelectedTextBoxRun(state())) return "textBox";
40924
+ return null;
40925
+ };
40926
+ const applyLayoutOptionPatch = (mergeKey, apply) => {
40927
+ const target = layoutOptionsTarget();
40928
+ if (!target) return;
40929
+ resetTransactionGrouping();
40930
+ applyTransactionalState((current) => apply(current, target), { mergeKey });
40931
+ focusInput();
40932
+ };
40933
+ const ensureImageWrapContour = (runId, src) => {
40934
+ const resolved = resolveImageSrc(state().document, src);
40935
+ const applyContour = (img2) => {
40936
+ const polygon = traceImageAlphaContour(img2);
40937
+ applyTransactionalState(
40938
+ (current) => setImageWrapPolygon(current, runId, polygon),
40939
+ { mergeKey: "layoutWrapPolygon" }
40940
+ );
40941
+ };
40942
+ const img = getCachedCanvasImage(resolved, () => {
40943
+ if (img.naturalWidth > 0) applyContour(img);
40944
+ });
40945
+ if (img.complete && img.naturalWidth > 0) {
40946
+ applyContour(img);
40947
+ }
40948
+ };
40949
+ return {
40950
+ target: layoutOptionsTarget,
40951
+ preset: () => {
40952
+ const target = layoutOptionsTarget();
40953
+ if (target === "image") return getSelectedImageWrapPreset(state());
40954
+ if (target === "textBox") return getSelectedTextBoxWrapPreset(state());
40955
+ return null;
40956
+ },
40957
+ fixedPosition: () => {
40958
+ const target = layoutOptionsTarget();
40959
+ if (target === "image") return isSelectedImageFixedPosition(state());
40960
+ if (target === "textBox") return isSelectedTextBoxFixedPosition(state());
40961
+ return false;
40962
+ },
40963
+ setPreset: (preset) => {
40964
+ applyLayoutOptionPatch(
40965
+ "layoutWrapPreset",
40966
+ (current, target) => target === "image" ? setSelectedImageWrapPreset(current, preset) : setSelectedTextBoxWrapPreset(current, preset)
40967
+ );
40968
+ if (preset === "tight" || preset === "through") {
40969
+ const selected = getSelectedImageRun(state());
40970
+ const image = selected == null ? void 0 : selected.run.image;
40971
+ if (image && !image.wrapPolygon) {
40972
+ ensureImageWrapContour(selected.run.id, image.src);
40973
+ }
40974
+ }
40975
+ },
40976
+ setFixedPosition: (fixed) => applyLayoutOptionPatch(
40977
+ "layoutFixedPosition",
40978
+ (current, target) => target === "image" ? setSelectedImageFixedPosition(current, fixed) : setSelectedTextBoxFixedPosition(current, fixed)
40979
+ )
40980
+ };
40981
+ }
40919
40982
  const DEFAULT_TOC_MAX_LEVEL = 3;
40920
40983
  const TOC_INSTRUCTION = ' TOC \\o "1-3" \\h \\z \\u ';
40921
40984
  const PX_TO_PT = 72 / 96;
@@ -47129,62 +47192,12 @@ function OasisEditorApp(props = {}) {
47129
47192
  runtimeClient.emit("selectionChange", snapshot.selection);
47130
47193
  });
47131
47194
  const selectedImageRun = () => getSelectedImageRun(state);
47132
- const selectedTextBoxRun = () => getSelectedTextBoxRun(state);
47133
- const layoutOptionsTarget = () => {
47134
- if (selectedImageRun()) return "image";
47135
- if (selectedTextBoxRun()) return "textBox";
47136
- return null;
47137
- };
47138
- const applyLayoutOptionPatch = (mergeKey, apply) => {
47139
- const target = layoutOptionsTarget();
47140
- if (!target) return;
47141
- resetTransactionGrouping();
47142
- applyTransactionalState((current) => apply(current, target), {
47143
- mergeKey
47144
- });
47145
- focusInput();
47146
- };
47147
- const ensureImageWrapContour = (runId, src) => {
47148
- const resolved = resolveImageSrc(state.document, src);
47149
- const applyContour = (img2) => {
47150
- const polygon = traceImageAlphaContour(img2);
47151
- applyTransactionalState((current) => setImageWrapPolygon(current, runId, polygon), {
47152
- mergeKey: "layoutWrapPolygon"
47153
- });
47154
- };
47155
- const img = getCachedCanvasImage(resolved, () => {
47156
- if (img.naturalWidth > 0) applyContour(img);
47157
- });
47158
- if (img.complete && img.naturalWidth > 0) {
47159
- applyContour(img);
47160
- }
47161
- };
47162
- const layoutOptionsOverlay = {
47163
- target: layoutOptionsTarget,
47164
- preset: () => {
47165
- const target = layoutOptionsTarget();
47166
- if (target === "image") return getSelectedImageWrapPreset(state);
47167
- if (target === "textBox") return getSelectedTextBoxWrapPreset(state);
47168
- return null;
47169
- },
47170
- fixedPosition: () => {
47171
- const target = layoutOptionsTarget();
47172
- if (target === "image") return isSelectedImageFixedPosition(state);
47173
- if (target === "textBox") return isSelectedTextBoxFixedPosition(state);
47174
- return false;
47175
- },
47176
- setPreset: (preset) => {
47177
- applyLayoutOptionPatch("layoutWrapPreset", (current, target) => target === "image" ? setSelectedImageWrapPreset(current, preset) : setSelectedTextBoxWrapPreset(current, preset));
47178
- if (preset === "tight" || preset === "through") {
47179
- const selected = getSelectedImageRun(state);
47180
- const image = selected == null ? void 0 : selected.run.image;
47181
- if (image && !image.wrapPolygon) {
47182
- ensureImageWrapContour(selected.run.id, image.src);
47183
- }
47184
- }
47185
- },
47186
- setFixedPosition: (fixed) => applyLayoutOptionPatch("layoutFixedPosition", (current, target) => target === "image" ? setSelectedImageFixedPosition(current, fixed) : setSelectedTextBoxFixedPosition(current, fixed))
47187
- };
47195
+ const layoutOptionsOverlay = createEditorLayoutOptionsController({
47196
+ state: () => state,
47197
+ resetTransactionGrouping,
47198
+ applyTransactionalState,
47199
+ focusInput
47200
+ });
47188
47201
  const canvasHitResolver = createCanvasSurfaceHitResolver({
47189
47202
  state: () => state,
47190
47203
  surfaceRef: () => surfaceRef() ?? null,