@a3s-lab/office 0.27.0 → 0.29.0

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 (47) hide show
  1. package/README.md +41 -1
  2. package/dist/0~1403.js +1 -1
  3. package/dist/0~4980.js +1 -1
  4. package/dist/0~5093.js +164 -5
  5. package/dist/0~7043.js +241 -241
  6. package/dist/0~7048.js +1 -1
  7. package/dist/0~7614.js +1 -1
  8. package/dist/0~document-editor.js +626 -12
  9. package/dist/0~presentation-editor.js +1 -1
  10. package/dist/0~spreadsheet-editor.js +1 -2
  11. package/dist/0~work-docx-export.js +396 -20
  12. package/dist/0~work-docx-import.js +7 -3
  13. package/dist/0~work-office-diagnostics.js +98 -4
  14. package/dist/0~work-pptx-export.js +1 -1
  15. package/dist/0~work-pptx-import.js +1 -1
  16. package/dist/0~work-presentation-charts.js +1 -1
  17. package/dist/1544.js +1 -1
  18. package/dist/4104.js +2 -2
  19. package/dist/4121.js +1510 -0
  20. package/dist/6282.js +220 -682
  21. package/dist/8715.js +1 -1
  22. package/dist/core.js +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/internal/features/work/editors/document-command-catalog.d.ts +9 -0
  25. package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +33 -2
  26. package/dist/internal/features/work/editors/document-font-dialog-run-border-model.d.ts +24 -0
  27. package/dist/internal/features/work/editors/document-font-dialog-run-border-section.d.ts +10 -0
  28. package/dist/internal/features/work/work-document-character-formatting.d.ts +4 -0
  29. package/dist/internal/features/work/work-document-format-changes.d.ts +5 -0
  30. package/dist/internal/features/work/work-document-legacy-text-effects.d.ts +27 -0
  31. package/dist/internal/features/work/work-document-run-border.d.ts +11 -0
  32. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +5 -0
  33. package/dist/internal/features/work/work-docx-hidden-text-export.d.ts +1 -0
  34. package/dist/internal/features/work/work-docx-legacy-text-effects-diagnostics.d.ts +3 -0
  35. package/dist/internal/features/work/work-docx-legacy-text-effects-export.d.ts +18 -0
  36. package/dist/internal/features/work/work-docx-legacy-text-effects.d.ts +12 -0
  37. package/dist/internal/features/work/work-docx-run-border-diagnostics.d.ts +3 -0
  38. package/dist/internal/features/work/work-docx-run-border-export.d.ts +17 -0
  39. package/dist/internal/features/work/work-docx-run-border.d.ts +20 -0
  40. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +6 -0
  41. package/dist/internal/features/work/work-docx-run-property-order.d.ts +2 -0
  42. package/dist/office-kernel.wasm +0 -0
  43. package/dist/styles.css +72 -0
  44. package/docs/latest/en/browser-editor-architecture.md +36 -0
  45. package/package.json +7 -1
  46. package/dist/5184.js +0 -649
  47. package/dist/9424.js +0 -16
@@ -6,7 +6,7 @@ import { Fragment as external_react_Fragment, forwardRef, useCallback, useEffect
6
6
  import { Extension, createNodeFromContent } from "@tiptap/core";
7
7
  import { NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
8
8
  import { Decoration, DecorationSet } from "@tiptap/pm/view";
9
- import { AArrowDown, AArrowUp, ALargeSmall, AlignCenter, AlignJustify, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowUp, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, BookMarked, BookOpen, Bookmark, CaseUpper, Check, CheckCheck, CheckCircle2, ChevronDown, ChevronRight, ChevronUp, ClipboardCopy, ClipboardPaste, Cloud, Columns3, Eraser, Eye, FileDiff, FilePlus2, FileText, Globe2, Grid2X2, Hash, Highlighter, Image, IndentDecrease, IndentIncrease, Italic, Link2, List, ListChecks, ListOrdered, MessageSquarePlus, MessageSquareReply, MessagesSquare, MoveVertical, Paintbrush, Palette, PanelBottom, PanelBottomOpen, PanelLeftOpen, PanelTop, PanelTopOpen, Pilcrow, PilcrowLeft, PilcrowRight, Plus, Quote, Redo2, RefreshCw, Replace, ReplaceAll, RotateCcw, Rows3, Ruler, Scan, Search, Settings2, StretchHorizontal, Strikethrough, Subscript, Superscript, Table2, TableCellsMerge, TableCellsSplit, TableProperties, TextWrap, Trash2, TriangleAlert, Type, Underline, Undo2, Unlink, Unlink2, X, XCircle, ZoomIn, ZoomOut } from "lucide-react";
9
+ import { AArrowDown, AArrowUp, ALargeSmall, AlignCenter, AlignJustify, AlignLeft, AlignRight, AlignVerticalJustifyCenter, AlignVerticalJustifyEnd, AlignVerticalJustifyStart, ArrowDown, ArrowUp, BetweenHorizontalEnd, BetweenHorizontalStart, BetweenVerticalEnd, BetweenVerticalStart, Bold, BookMarked, BookOpen, Bookmark, CaseUpper, Check, CheckCheck, CheckCircle2, ChevronDown, ChevronRight, ChevronUp, ClipboardCopy, ClipboardPaste, Cloud, Columns3, Eraser, Eye, FileDiff, FilePlus2, FileText, Globe2, Grid2X2, Hash, Highlighter, Image, IndentDecrease, IndentIncrease, Italic, Link2, List, ListChecks, ListOrdered, MessageSquarePlus, MessageSquareReply, MessagesSquare, MoveVertical, Paintbrush, Palette, PanelBottom, PanelBottomOpen, PanelLeftOpen, PanelTop, PanelTopOpen, Pilcrow, PilcrowLeft, PilcrowRight, Plus, Quote, Redo2, RefreshCw, Replace, ReplaceAll, RotateCcw, Rows3, Ruler, Scan, Search, Settings2, Square, StretchHorizontal, Strikethrough, Subscript, Superscript, Table2, TableCellsMerge, TableCellsSplit, TableProperties, TextWrap, Trash2, TriangleAlert, Type, Underline, Undo2, Unlink, Unlink2, X, XCircle, ZoomIn, ZoomOut } from "lucide-react";
10
10
  import { Node as model_Node } from "@tiptap/pm/model";
11
11
  import extension_color from "@tiptap/extension-color";
12
12
  import { TableKit } from "@tiptap/extension-table";
@@ -15,11 +15,11 @@ import font_size from "@tiptap/extension-text-style/font-size";
15
15
  import starter_kit from "@tiptap/starter-kit";
16
16
  import { BubbleMenu } from "@tiptap/react/menus";
17
17
  import { TableMap, isInTable, selectedRect } from "@tiptap/pm/tables";
18
- import { documentTableSizing, transferChangedDocumentTextStatistics, documentPageBordersVisible, documentUnderlineStyle, DOCUMENT_PAGE_BORDER_EDGES, documentScriptFontDirectFamily, normalizeDocumentColumns, clampDocumentMargin, materializeLazyDocumentEditorRoot, patchDocumentScriptFonts, documentKerningThresholdPoints, nextDocumentTabAlignment, documentTableRowOptions, normalizedTabPosition, DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE, documentCitationCount, isDocumentParagraphArtBorderStyle, resolveDocumentPageBorders, documentLazyHtmlChunkFragment, DocumentFontFamily, normalizeDocumentHiddenText, DOCUMENT_CHUNK_VISIBLE_IDS_META, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT, retainAnchoredDocumentComments, DocumentTableRowIdentity, work_document_page_margins_twipsToMillimeters, DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, resolveWorkDocumentEditorInput, documentCharacterPositionPoints, documentBulletListStyle, collectDocumentTextLayoutParagraphs, readOfficeDocumentCollaboration as readWorkOfficeDocumentCollaboration, normalizeDocumentCharacterScalePercent, documentOrderedListState, normalizeDocumentPageChrome, documentTextStatistics, documentPageMarginsForLayout, invalidateDocumentLazyHtmlProjection, documentTableCellFormat, normalizeDocumentPageGeometry, normalizeDocumentImageLayer, documentImageProperties, isValidDocumentCitationTag, sanitizeDocumentPageChromeHtml, pageTwipsToMillimeters, normalizeDocumentPageBorders, parseDocumentScriptFonts, DocumentParagraphFormatting, activeDocumentSection, normalizeDocumentHtml, documentInitialSectionLayout, documentModelHasTrustedInitialIntegrityFeatures, documentParagraphDirection, documentParagraphPagination, documentModelUsesWindowing, documentPageChromeLegacyFields, documentChunkMountedIds, collectDocumentCommentAnchors, documentTextCaseKeyboardShortcuts, DocumentTextStyle, canChangeDocumentIndent, cssDocumentFontFamily, documentCharacterSpacingPoints, documentKerningIsEffective, DocumentSuperscript, documentSectionById, activeDocumentBookmark, DocumentEquation, documentLazyHtmlProjectionFingerprint, documentLazyHtmlProjection, normalizeDocumentParagraphIndent, updateDocumentGutterPosition, DocumentStrike, mountWorkLiveDocumentCapture, registerDocumentPageSurfaceGeometry, documentHiddenTextKeyboardShortcut, syncDocumentContentFromHtml, documentScriptFontSlotFromHint, editorDocumentCaptionTargets, resolveDocumentPageChrome, documentScriptFontFamilyForRendering, documentImageLayoutOptions, MAX_DOCUMENT_NUMBERING_START, resolveDocumentPageSize, editorDocumentBookmarkReferenceTargets, serializeWorkDocumentNode, DOCUMENT_CHUNK_PAGINATION_META, createOfficeDocumentCollaborationBinding as createWorkOfficeDocumentCollaborationBinding, documentModelForContent, normalizeDocumentEmphasisMark, selectedDocumentChunkId, documentCommentViews, documentParagraphSpacing, normalizeDocumentTabStops, patchDocumentLazyHtmlProjection, normalizeDocumentTextCase, serializeDocumentScriptFonts, documentUnderlineColor, documentBookmarkNameExists, collectDocumentChanges, DocumentImage, resolveDocumentPageMargins, updateDocumentPageMarginMode, canSetDocumentTableRowRepeatHeader, normalizeDocumentCharacterSpacingTwips, DocumentCharacterFormatting, millimetersToPixels as work_document_layout_millimetersToPixels, DOCUMENT_CHUNK_HYDRATION_META, documentTabLeaderLabel, createSchemaDerivedWorkDocumentModel, updateDocumentCustomPageMillimeters, DocumentUnderline, documentCommentDraftRange, documentParagraphTabStops, documentScriptFontSegments, documentUnderlineKeyboardShortcuts, documentParagraphIndent, documentFontNameFromCssFamily, DocumentScriptFontFormatting, canInsertDocumentComment, documentTableHorizontalAlignment, documentTextLayoutBatches, normalizeDocumentImageWrapSide, updateDocumentPageOrientation, documentCitationStyleDetails, validateDocumentBookmarkName, setCustomDocumentColumns, updateDocumentPageMarginMillimeters, documentCitationStyle, normalizeDocumentCharacterPositionHalfPoints, documentTransactionsOnlyHydrateChunks, normalizeDocumentKerningThresholdHalfPoints, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, DOCUMENT_TABLE_STYLE_OPTIONS, updateDocumentColumnWidth, updateDocumentPaperSizePreset, documentPageMetrics, documentStrikeStyle, createDocumentBibliography, DocumentSubscript, DocumentParagraphIdentity, updateDocumentPageChromeVariant, updateDocumentMirrorMargins, activeDocumentTableStyle, normalizeDocumentScriptFontSlot, measureDocumentLayoutBlocksIncrementally, documentWordLineHeightFactor, createWorkDocumentExtensions } from "./6282.js";
18
+ import { documentTableSizing, transferChangedDocumentTextStatistics, documentPageBordersVisible, documentUnderlineStyle, DOCUMENT_PAGE_BORDER_EDGES, documentScriptFontDirectFamily, normalizeDocumentColumns, clampDocumentMargin, materializeLazyDocumentEditorRoot, patchDocumentScriptFonts, documentKerningThresholdPoints, nextDocumentTabAlignment, documentTableRowOptions, normalizedTabPosition, DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE, documentCitationCount, resolveDocumentPageBorders, documentLazyHtmlChunkFragment, DocumentFontFamily, normalizeDocumentHiddenText, documentLegacyTextEffectsConflict, DOCUMENT_CHUNK_VISIBLE_IDS_META, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT, retainAnchoredDocumentComments, DocumentTableRowIdentity, work_document_page_margins_twipsToMillimeters, DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, resolveWorkDocumentEditorInput, documentCharacterPositionPoints, documentBulletListStyle, collectDocumentTextLayoutParagraphs, readOfficeDocumentCollaboration as readWorkOfficeDocumentCollaboration, normalizeDocumentCharacterScalePercent, documentOrderedListState, normalizeDocumentPageChrome, documentTextStatistics, documentPageMarginsForLayout, invalidateDocumentLazyHtmlProjection, documentTableCellFormat, normalizeDocumentPageGeometry, normalizeDocumentImageLayer, documentImageProperties, isValidDocumentCitationTag, sanitizeDocumentPageChromeHtml, pageTwipsToMillimeters, normalizeDocumentPageBorders, parseDocumentScriptFonts, DocumentParagraphFormatting, activeDocumentSection, normalizeDocumentHtml, documentInitialSectionLayout, documentModelHasTrustedInitialIntegrityFeatures, documentParagraphDirection, documentParagraphPagination, documentModelUsesWindowing, documentPageChromeLegacyFields, documentChunkMountedIds, collectDocumentCommentAnchors, documentTextCaseKeyboardShortcuts, DocumentTextStyle, canChangeDocumentIndent, cssDocumentFontFamily, documentCharacterSpacingPoints, documentKerningIsEffective, DocumentSuperscript, documentSectionById, activeDocumentBookmark, DocumentEquation, documentLazyHtmlProjectionFingerprint, documentLazyHtmlProjection, normalizeDocumentParagraphIndent, updateDocumentGutterPosition, DocumentStrike, mountWorkLiveDocumentCapture, registerDocumentPageSurfaceGeometry, documentHiddenTextKeyboardShortcut, syncDocumentContentFromHtml, documentLegacyTextEffectsCss, documentScriptFontSlotFromHint, editorDocumentCaptionTargets, resolveDocumentPageChrome, documentScriptFontFamilyForRendering, documentImageLayoutOptions, MAX_DOCUMENT_NUMBERING_START, resolveDocumentPageSize, editorDocumentBookmarkReferenceTargets, serializeWorkDocumentNode, DOCUMENT_CHUNK_PAGINATION_META, createOfficeDocumentCollaborationBinding as createWorkOfficeDocumentCollaborationBinding, documentModelForContent, documentLegacyTextEffectsFromTextStyleAttributes, normalizeDocumentEmphasisMark, selectedDocumentChunkId, documentCommentViews, documentParagraphSpacing, normalizeDocumentTabStops, patchDocumentLazyHtmlProjection, normalizeDocumentTextCase, serializeDocumentScriptFonts, documentUnderlineColor, documentBookmarkNameExists, collectDocumentChanges, DocumentImage, resolveDocumentPageMargins, updateDocumentPageMarginMode, canSetDocumentTableRowRepeatHeader, normalizeDocumentCharacterSpacingTwips, DocumentCharacterFormatting, millimetersToPixels as work_document_layout_millimetersToPixels, DOCUMENT_CHUNK_HYDRATION_META, documentTabLeaderLabel, createSchemaDerivedWorkDocumentModel, updateDocumentCustomPageMillimeters, DocumentUnderline, documentCommentDraftRange, documentParagraphTabStops, documentScriptFontSegments, documentUnderlineKeyboardShortcuts, documentParagraphIndent, documentFontNameFromCssFamily, DocumentScriptFontFormatting, canInsertDocumentComment, documentTableHorizontalAlignment, documentTextLayoutBatches, normalizeDocumentImageWrapSide, updateDocumentPageOrientation, documentCitationStyleDetails, validateDocumentBookmarkName, setCustomDocumentColumns, updateDocumentPageMarginMillimeters, documentCitationStyle, normalizeDocumentCharacterPositionHalfPoints, documentTransactionsOnlyHydrateChunks, normalizeDocumentKerningThresholdHalfPoints, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, DOCUMENT_TABLE_STYLE_OPTIONS, updateDocumentColumnWidth, updateDocumentPaperSizePreset, documentPageMetrics, documentStrikeStyle, createDocumentBibliography, DocumentSubscript, DocumentParagraphIdentity, updateDocumentPageChromeVariant, updateDocumentMirrorMargins, activeDocumentTableStyle, normalizeDocumentScriptFontSlot, measureDocumentLayoutBlocksIncrementally, documentWordLineHeightFactor, normalizeDocumentLegacyTextEffect, createWorkDocumentExtensions } from "./6282.js";
19
19
  import { useOfficeTaskPaneEscape, normalizeOfficeFontFamily, OfficeCheckbox, useOfficeDialog, useOfficeTaskPaneModal, CommittedOfficeNumberField, officeFontFamilyLabel, officeFontFamilies, CollectionState, createOfficeKernelClient, OfficeNumberField } from "./0~7048.js";
20
20
  import { moveOfficeMenuFocus, office_text_field_OfficeTextArea, Popover, officeOverlayPortalRoot, button_Button, useOfficePublishPresenceLocation, OfficeTiptapPresenceLayer, icon_button_IconButton, office_text_field_OfficeTextField, useDialogFocusScope, useOfficeEditorWheelZoom, office_text_field_OfficeFileInput } from "./0~6090.js";
21
21
  import { WorkOfficePreviewBar, isWorkspaceContextMenuKeyboardEvent, Tabs, WorkOfficeZoomControls, WorkOfficeStatusBar, Dialog, WorkOfficeRibbon, workspaceContextMenuPosition, OfficeSelect, WorkspaceContextMenu, WorkOfficeRibbonGroup, WorkOfficeRibbonButton } from "./0~4595.js";
22
- import { createOfficeId as createWorkId } from "./5184.js";
22
+ import { documentBorderPresentation, normalizeDocumentRunBorder, parseDocumentRunBorder, DOCUMENT_RUN_BORDER_STYLES, isDocumentParagraphArtBorderStyle, serializeDocumentRunBorder, createOfficeId as createWorkId, documentRunBorderIsVisible } from "./4121.js";
23
23
  import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
24
24
  import { OfficeColorPicker, isOfficeShortcutBlocked } from "./0~3635.js";
25
25
  import { OfficeTableInsertPopover, readOfficeFileAsDataUrl } from "./0~9445.js";
@@ -7222,6 +7222,15 @@ const documentCommandCatalog = {
7222
7222
  ]
7223
7223
  }
7224
7224
  },
7225
+ runBorder: {
7226
+ id: 'font.runBorder',
7227
+ label: '字符边框',
7228
+ location: {
7229
+ area: 'ribbon',
7230
+ tab: 'home',
7231
+ group: 'font'
7232
+ }
7233
+ },
7225
7234
  clearFormatting: {
7226
7235
  id: 'font.clearFormatting',
7227
7236
  label: '清除格式',
@@ -8949,6 +8958,14 @@ function DocumentHomeRibbon({ editor, findReplaceMode, layoutFonts = [], onFindT
8949
8958
  size: 16
8950
8959
  })
8951
8960
  }),
8961
+ /*#__PURE__*/ jsx(ToolbarButton, {
8962
+ label: "字符边框",
8963
+ active: documentRunBorderIsVisible(parseDocumentRunBorder(editor.getAttributes('textStyle').runBorder)),
8964
+ onClick: ()=>editor.commands.toggleDocumentRunBorder(),
8965
+ children: /*#__PURE__*/ jsx(Square, {
8966
+ size: 16
8967
+ })
8968
+ }),
8952
8969
  /*#__PURE__*/ jsx(ToolbarButton, {
8953
8970
  label: "清除格式",
8954
8971
  onClick: ()=>editor.commands.clearDocumentFormatting(),
@@ -9243,6 +9260,89 @@ function addFontValue(values, value) {
9243
9260
  const normalized = value?.trim() || null;
9244
9261
  values.set(normalized?.toLocaleLowerCase() ?? 'inherited', normalized);
9245
9262
  }
9263
+ function addDocumentFontDialogRunBorderValue(values, source) {
9264
+ const border = parseDocumentRunBorder(source);
9265
+ const serialized = serializeDocumentRunBorder(border);
9266
+ values.set(serialized ?? 'inherited', border);
9267
+ }
9268
+ function selectedDocumentFontDialogRunBorderValue(values) {
9269
+ return 1 === values.size ? {
9270
+ mixed: false,
9271
+ value: values.values().next().value ?? null
9272
+ } : {
9273
+ mixed: true,
9274
+ value: null
9275
+ };
9276
+ }
9277
+ function createDocumentFontDialogRunBorderDraft(source) {
9278
+ const border = source.value;
9279
+ const visible = border && 'nil' !== border.style && 'none' !== border.style;
9280
+ return {
9281
+ runBorderMode: source.mixed ? 'mixed' : border ? visible ? 'value' : 'none' : 'inherit',
9282
+ runBorderStyle: visible ? border.style : 'single',
9283
+ runBorderColor: border?.color?.value ?? 'auto',
9284
+ runBorderWidthPoints: formatPoints((border?.size ?? 4) / 8),
9285
+ runBorderSpacingPoints: String(border?.space ?? 1),
9286
+ runBorderShadow: border?.shadow ?? false,
9287
+ runBorderFrame: border?.frame ?? false
9288
+ };
9289
+ }
9290
+ function documentFontDialogRunBorderDraftError(draft) {
9291
+ if ('value' !== draft.runBorderMode) return null;
9292
+ if (!DOCUMENT_RUN_BORDER_STYLES.includes(draft.runBorderStyle) || 'nil' === draft.runBorderStyle || 'none' === draft.runBorderStyle) return '请选择有效的字符边框线型。';
9293
+ if ('auto' !== draft.runBorderColor && !/^#[0-9a-f]{6}$/i.test(draft.runBorderColor)) return '请选择有效的字符边框颜色。';
9294
+ if (null === runBorderSizeFromDraft(draft)) return '请输入 0.25 至 12 磅、以 0.125 磅递增的字符边框宽度。';
9295
+ if (null === runBorderSpaceFromDraft(draft)) return '请输入 0 至 31 磅的整数字符边框间距。';
9296
+ return null;
9297
+ }
9298
+ function documentFontDialogRunBorderPatch(source, draft, touched) {
9299
+ if (!touched || 'mixed' === draft.runBorderMode) return {};
9300
+ if ('inherit' === draft.runBorderMode) return source.mixed || source.value ? {
9301
+ runBorder: null
9302
+ } : {};
9303
+ const border = 'none' === draft.runBorderMode ? {
9304
+ style: 'nil'
9305
+ } : documentFontDialogRunBorderFromDraft(source, draft);
9306
+ if (!border) return {};
9307
+ return serializeDocumentRunBorder(source.value) === serializeDocumentRunBorder(border) ? {} : {
9308
+ runBorder: border
9309
+ };
9310
+ }
9311
+ function documentFontDialogRunBorderFromDraft(source, draft) {
9312
+ if ('none' === draft.runBorderMode) return {
9313
+ style: 'nil'
9314
+ };
9315
+ if ('value' !== draft.runBorderMode) return source.value;
9316
+ const size = runBorderSizeFromDraft(draft);
9317
+ const space = runBorderSpaceFromDraft(draft);
9318
+ if (null === size || null === space) return null;
9319
+ const sourceColor = source.value?.color;
9320
+ return normalizeDocumentRunBorder({
9321
+ style: draft.runBorderStyle,
9322
+ color: {
9323
+ value: draft.runBorderColor,
9324
+ ...sourceColor?.theme && sourceColor.value === draft.runBorderColor ? {
9325
+ theme: sourceColor.theme
9326
+ } : {}
9327
+ },
9328
+ size,
9329
+ space,
9330
+ shadow: draft.runBorderShadow,
9331
+ frame: draft.runBorderFrame
9332
+ });
9333
+ }
9334
+ function runBorderSizeFromDraft(draft) {
9335
+ const points = Number(draft.runBorderWidthPoints);
9336
+ const size = Math.round(8 * points);
9337
+ return Number.isFinite(points) && size >= 2 && size <= 96 && 8 * points === size ? size : null;
9338
+ }
9339
+ function runBorderSpaceFromDraft(draft) {
9340
+ const space = Number(draft.runBorderSpacingPoints);
9341
+ return Number.isSafeInteger(space) && space >= 0 && space <= 31 ? space : null;
9342
+ }
9343
+ function formatPoints(value) {
9344
+ return Number(value.toFixed(3)).toString();
9345
+ }
9246
9346
  function documentFontDialogSource(editor) {
9247
9347
  const { doc, selection } = editor.state;
9248
9348
  const scaleValues = new Map();
@@ -9251,6 +9351,11 @@ function documentFontDialogSource(editor) {
9251
9351
  const kerningValues = new Map();
9252
9352
  const emphasisValues = new Map();
9253
9353
  const hiddenTextValues = new Map();
9354
+ const legacyTextOutlineValues = new Map();
9355
+ const legacyTextShadowValues = new Map();
9356
+ const legacyTextEmbossValues = new Map();
9357
+ const legacyTextImprintValues = new Map();
9358
+ const runBorderValues = new Map();
9254
9359
  const latinFontValues = new Map();
9255
9360
  const eastAsiaFontValues = new Map();
9256
9361
  const complexScriptFontValues = new Map();
@@ -9261,6 +9366,11 @@ function documentFontDialogSource(editor) {
9261
9366
  addKerningValue(kerningValues, attributes.kerningThresholdHalfPoints);
9262
9367
  addEmphasisValue(emphasisValues, attributes.emphasisMark);
9263
9368
  addHiddenTextValue(hiddenTextValues, attributes.hiddenText);
9369
+ addLegacyTextEffectValue(legacyTextOutlineValues, attributes.legacyTextOutline);
9370
+ addLegacyTextEffectValue(legacyTextShadowValues, attributes.legacyTextShadow);
9371
+ addLegacyTextEffectValue(legacyTextEmbossValues, attributes.legacyTextEmboss);
9372
+ addLegacyTextEffectValue(legacyTextImprintValues, attributes.legacyTextImprint);
9373
+ addDocumentFontDialogRunBorderValue(runBorderValues, attributes.runBorder);
9264
9374
  addDocumentScriptFontValues(latinFontValues, eastAsiaFontValues, complexScriptFontValues, attributes);
9265
9375
  };
9266
9376
  if (selection.empty) addValues(editor.getAttributes('textStyle'));
@@ -9269,13 +9379,18 @@ function documentFontDialogSource(editor) {
9269
9379
  const textStyle = node.marks.find((mark)=>'textStyle' === mark.type.name);
9270
9380
  addValues(textStyle?.attrs ?? {});
9271
9381
  });
9272
- if (!scaleValues.size || !spacingValues.size || !positionValues.size || !kerningValues.size || !emphasisValues.size || !hiddenTextValues.size || !latinFontValues.size || !eastAsiaFontValues.size || !complexScriptFontValues.size) addValues(editor.getAttributes('textStyle'));
9382
+ if (!scaleValues.size || !spacingValues.size || !positionValues.size || !kerningValues.size || !emphasisValues.size || !hiddenTextValues.size || !legacyTextOutlineValues.size || !legacyTextShadowValues.size || !legacyTextEmbossValues.size || !legacyTextImprintValues.size || !runBorderValues.size || !latinFontValues.size || !eastAsiaFontValues.size || !complexScriptFontValues.size) addValues(editor.getAttributes('textStyle'));
9273
9383
  const characterScale = selectedValue(scaleValues);
9274
9384
  const characterPosition = selectedValue(positionValues);
9275
9385
  const characterSpacing = selectedValue(spacingValues);
9276
9386
  const kerningThreshold = selectedValue(kerningValues);
9277
9387
  const emphasisMark = selectedValue(emphasisValues);
9278
9388
  const hiddenText = selectedValue(hiddenTextValues);
9389
+ const legacyTextOutline = selectedValue(legacyTextOutlineValues);
9390
+ const legacyTextShadow = selectedValue(legacyTextShadowValues);
9391
+ const legacyTextEmboss = selectedValue(legacyTextEmbossValues);
9392
+ const legacyTextImprint = selectedValue(legacyTextImprintValues);
9393
+ const runBorder = selectedDocumentFontDialogRunBorderValue(runBorderValues);
9279
9394
  const latinFont = selectedValue(latinFontValues);
9280
9395
  const eastAsiaFont = selectedValue(eastAsiaFontValues);
9281
9396
  const complexScriptFont = selectedValue(complexScriptFontValues);
@@ -9288,6 +9403,11 @@ function documentFontDialogSource(editor) {
9288
9403
  kerningThreshold,
9289
9404
  emphasisMark,
9290
9405
  hiddenText,
9406
+ legacyTextOutline,
9407
+ legacyTextShadow,
9408
+ legacyTextEmboss,
9409
+ legacyTextImprint,
9410
+ runBorder,
9291
9411
  latinFont,
9292
9412
  eastAsiaFont,
9293
9413
  complexScriptFont,
@@ -9308,19 +9428,26 @@ function createDocumentFontDialogDraft(source) {
9308
9428
  characterScaleMode: source.characterScale.mixed ? 'mixed' : 'value',
9309
9429
  characterScalePercent: source.characterScale.mixed ? '' : String(scale ?? 100),
9310
9430
  characterPositionMode: source.characterPosition.mixed ? 'mixed' : null !== position && position < 0 ? 'lowered' : null !== position && position > 0 ? 'raised' : 'normal',
9311
- characterPositionPoints: formatPoints(positionPoints || 1),
9431
+ characterPositionPoints: document_font_dialog_model_formatPoints(positionPoints || 1),
9312
9432
  characterSpacingMode: source.characterSpacing.mixed ? 'mixed' : null !== spacing && spacing < 0 ? 'condensed' : null !== spacing && spacing > 0 ? 'expanded' : 'normal',
9313
- characterSpacingPoints: formatPoints(spacingPoints || 1),
9433
+ characterSpacingPoints: document_font_dialog_model_formatPoints(spacingPoints || 1),
9314
9434
  kerningEnabled: !source.kerningThreshold.mixed && null !== kerningThreshold,
9315
- kerningThresholdPoints: formatPoints(documentKerningThresholdPoints(kerningThreshold) ?? 12),
9435
+ kerningThresholdPoints: document_font_dialog_model_formatPoints(documentKerningThresholdPoints(kerningThreshold) ?? 12),
9316
9436
  emphasisMark: source.emphasisMark.mixed ? 'mixed' : source.emphasisMark.value ?? 'inherit',
9317
9437
  hiddenText: source.hiddenText.value ?? false,
9438
+ legacyTextOutline: source.legacyTextOutline.value ?? false,
9439
+ legacyTextShadow: source.legacyTextShadow.value ?? false,
9440
+ legacyTextEmboss: source.legacyTextEmboss.value ?? false,
9441
+ legacyTextImprint: source.legacyTextImprint.value ?? false,
9442
+ ...createDocumentFontDialogRunBorderDraft(source.runBorder),
9318
9443
  latinFont: documentFontFamilyDraftValue(source.latinFont),
9319
9444
  eastAsiaFont: documentFontFamilyDraftValue(source.eastAsiaFont),
9320
9445
  complexScriptFont: documentFontFamilyDraftValue(source.complexScriptFont)
9321
9446
  };
9322
9447
  }
9323
9448
  function documentFontDialogDraftError(draft) {
9449
+ const runBorderError = documentFontDialogRunBorderDraftError(draft);
9450
+ if (runBorderError) return runBorderError;
9324
9451
  if ('mixed' !== draft.characterScaleMode && null === characterScalePercentFromDraft(draft)) return "请输入 1 至 600 的整数缩放比例。";
9325
9452
  if ('mixed' !== draft.characterSpacingMode && 'normal' !== draft.characterSpacingMode && null === characterSpacingTwipsFromDraft(draft)) return "请输入 0.05 至 1584 磅的间距。";
9326
9453
  if ('mixed' !== draft.characterPositionMode && 'normal' !== draft.characterPositionMode && null === characterPositionHalfPointsFromDraft(draft)) return "请输入 0.5 至 1584 磅、以 0.5 磅递增的位置值。";
@@ -9354,6 +9481,11 @@ function documentFontDialogPatch(source, draft, touched) {
9354
9481
  }
9355
9482
  }
9356
9483
  if (touched.hiddenText && (source.hiddenText.mixed || source.hiddenText.value !== draft.hiddenText)) patch.hiddenText = draft.hiddenText;
9484
+ appendLegacyTextEffectPatch(patch, 'legacyTextOutline', source.legacyTextOutline, draft.legacyTextOutline, touched.legacyTextOutline);
9485
+ Object.assign(patch, documentFontDialogRunBorderPatch(source.runBorder, draft, touched.runBorder));
9486
+ appendLegacyTextEffectPatch(patch, 'legacyTextShadow', source.legacyTextShadow, draft.legacyTextShadow, touched.legacyTextShadow);
9487
+ appendLegacyTextEffectPatch(patch, 'legacyTextEmboss', source.legacyTextEmboss, draft.legacyTextEmboss, touched.legacyTextEmboss);
9488
+ appendLegacyTextEffectPatch(patch, 'legacyTextImprint', source.legacyTextImprint, draft.legacyTextImprint, touched.legacyTextImprint);
9357
9489
  appendDocumentFontDialogScriptFontPatch(patch, 'latinFont', source.latinFont, draft.latinFont, touched.latinFont);
9358
9490
  appendDocumentFontDialogScriptFontPatch(patch, 'eastAsiaFont', source.eastAsiaFont, draft.eastAsiaFont, touched.eastAsiaFont);
9359
9491
  appendDocumentFontDialogScriptFontPatch(patch, 'complexScriptFont', source.complexScriptFont, draft.complexScriptFont, touched.complexScriptFont);
@@ -9366,6 +9498,12 @@ function applyDocumentFontDialogPatch(editor, selection, patch) {
9366
9498
  const hasKerning = void 0 !== patch.kerningThresholdHalfPoints;
9367
9499
  const hasEmphasis = void 0 !== patch.emphasisMark;
9368
9500
  const hasHiddenText = void 0 !== patch.hiddenText;
9501
+ const hasLegacyTextOutline = void 0 !== patch.legacyTextOutline;
9502
+ const hasLegacyTextShadow = void 0 !== patch.legacyTextShadow;
9503
+ const hasLegacyTextEmboss = void 0 !== patch.legacyTextEmboss;
9504
+ const hasLegacyTextImprint = void 0 !== patch.legacyTextImprint;
9505
+ const hasRunBorder = void 0 !== patch.runBorder;
9506
+ const hasLegacyTextEffects = hasLegacyTextOutline || hasLegacyTextShadow || hasLegacyTextEmboss || hasLegacyTextImprint;
9369
9507
  const scriptFontPatch = {
9370
9508
  ...void 0 !== patch.latinFont ? {
9371
9509
  latin: patch.latinFont
@@ -9383,8 +9521,9 @@ function applyDocumentFontDialogPatch(editor, selection, patch) {
9383
9521
  const spacing = hasSpacing ? normalizeDocumentCharacterSpacingTwips(patch.characterSpacingTwips) : null;
9384
9522
  const kerningThreshold = hasKerning && null !== patch.kerningThresholdHalfPoints ? normalizeDocumentKerningThresholdHalfPoints(patch.kerningThresholdHalfPoints) : null;
9385
9523
  const emphasisMark = hasEmphasis && null !== patch.emphasisMark ? normalizeDocumentEmphasisMark(patch.emphasisMark) : null;
9524
+ const runBorder = hasRunBorder && null !== patch.runBorder ? normalizeDocumentRunBorder(patch.runBorder) : null;
9386
9525
  const maximum = editor.state.doc.content.size;
9387
- if (editor.isDestroyed || !hasScale && !hasPosition && !hasSpacing && !hasKerning && !hasEmphasis && !hasHiddenText && !hasScriptFonts || hasScale && null === scale || hasPosition && null === position || hasSpacing && null === spacing || hasKerning && null !== patch.kerningThresholdHalfPoints && null === kerningThreshold || hasEmphasis && null !== patch.emphasisMark && null === emphasisMark || hasHiddenText && 'boolean' != typeof patch.hiddenText || !Number.isSafeInteger(selection.from) || !Number.isSafeInteger(selection.to) || selection.from < 0 || selection.to < selection.from || selection.to > maximum) return false;
9526
+ if (editor.isDestroyed || !hasScale && !hasPosition && !hasSpacing && !hasKerning && !hasEmphasis && !hasHiddenText && !hasLegacyTextEffects && !hasRunBorder && !hasScriptFonts || hasScale && null === scale || hasPosition && null === position || hasSpacing && null === spacing || hasKerning && null !== patch.kerningThresholdHalfPoints && null === kerningThreshold || hasEmphasis && null !== patch.emphasisMark && null === emphasisMark || hasRunBorder && null !== patch.runBorder && null === runBorder || hasHiddenText && 'boolean' != typeof patch.hiddenText || hasLegacyTextOutline && null === normalizeDocumentLegacyTextEffect(patch.legacyTextOutline) || hasLegacyTextShadow && null === normalizeDocumentLegacyTextEffect(patch.legacyTextShadow) || hasLegacyTextEmboss && null === normalizeDocumentLegacyTextEffect(patch.legacyTextEmboss) || hasLegacyTextImprint && null === normalizeDocumentLegacyTextEffect(patch.legacyTextImprint) || !Number.isSafeInteger(selection.from) || !Number.isSafeInteger(selection.to) || selection.from < 0 || selection.to < selection.from || selection.to > maximum || hasLegacyTextEffects && !documentFontDialogLegacyTextEffectsAreSafe(editor, selection, patch)) return false;
9388
9527
  const attributes = {};
9389
9528
  if (null !== scale) attributes.characterScalePercent = scale;
9390
9529
  if (null !== position) attributes.characterPositionHalfPoints = position;
@@ -9392,6 +9531,11 @@ function applyDocumentFontDialogPatch(editor, selection, patch) {
9392
9531
  if (hasKerning) attributes.kerningThresholdHalfPoints = kerningThreshold;
9393
9532
  if (hasEmphasis) attributes.emphasisMark = emphasisMark;
9394
9533
  if (hasHiddenText) attributes.hiddenText = patch.hiddenText ?? false;
9534
+ if (hasLegacyTextOutline) attributes.legacyTextOutline = patch.legacyTextOutline ?? false;
9535
+ if (hasLegacyTextShadow) attributes.legacyTextShadow = patch.legacyTextShadow ?? false;
9536
+ if (hasLegacyTextEmboss) attributes.legacyTextEmboss = patch.legacyTextEmboss ?? false;
9537
+ if (hasLegacyTextImprint) attributes.legacyTextImprint = patch.legacyTextImprint ?? false;
9538
+ if (hasRunBorder) attributes.runBorder = null === patch.runBorder ? null : serializeDocumentRunBorder(runBorder) ?? null;
9395
9539
  if (hasScriptFonts) return applyDocumentScriptFontPatch(editor, selection, attributes, scriptFontPatch);
9396
9540
  return editor.chain().setTextSelection(selection).setMark('textStyle', attributes).removeEmptyTextStyle().focus().scrollIntoView().run();
9397
9541
  }
@@ -9399,6 +9543,39 @@ function addScaleValue(values, value) {
9399
9543
  const scale = normalizeDocumentCharacterScalePercent(value);
9400
9544
  values.set(null === scale ? 'inherited' : String(scale), scale);
9401
9545
  }
9546
+ function documentFontDialogLegacyTextEffectsAreSafe(editor, selection, patch) {
9547
+ const patchEffects = {
9548
+ ...void 0 !== patch.legacyTextOutline ? {
9549
+ outline: patch.legacyTextOutline
9550
+ } : {},
9551
+ ...void 0 !== patch.legacyTextShadow ? {
9552
+ shadow: patch.legacyTextShadow
9553
+ } : {},
9554
+ ...void 0 !== patch.legacyTextEmboss ? {
9555
+ emboss: patch.legacyTextEmboss
9556
+ } : {},
9557
+ ...void 0 !== patch.legacyTextImprint ? {
9558
+ imprint: patch.legacyTextImprint
9559
+ } : {}
9560
+ };
9561
+ const attributesAreSafe = (attributes)=>{
9562
+ const current = documentLegacyTextEffectsFromTextStyleAttributes(attributes);
9563
+ return null !== current && !documentLegacyTextEffectsConflict({
9564
+ ...current,
9565
+ ...patchEffects
9566
+ });
9567
+ };
9568
+ if (selection.from === selection.to) return attributesAreSafe(editor.getAttributes('textStyle'));
9569
+ let sawText = false;
9570
+ let safe = true;
9571
+ editor.state.doc.nodesBetween(selection.from, selection.to, (node, position)=>{
9572
+ if (!safe || !node.isText || position >= selection.to || position + node.nodeSize <= selection.from) return;
9573
+ sawText = true;
9574
+ const textStyle = node.marks.find((mark)=>'textStyle' === mark.type.name);
9575
+ safe = attributesAreSafe(textStyle?.attrs ?? {});
9576
+ });
9577
+ return safe && (sawText || attributesAreSafe(editor.getAttributes('textStyle')));
9578
+ }
9402
9579
  function addPositionValue(values, value) {
9403
9580
  const position = normalizeDocumentCharacterPositionHalfPoints(value);
9404
9581
  values.set(null === position ? 'inherited' : String(position), position);
@@ -9419,6 +9596,13 @@ function addHiddenTextValue(values, value) {
9419
9596
  const hiddenText = normalizeDocumentHiddenText(value);
9420
9597
  values.set(null === hiddenText ? 'inherited' : String(hiddenText), hiddenText);
9421
9598
  }
9599
+ function appendLegacyTextEffectPatch(patch, name, source, value, touched) {
9600
+ if (touched && (source.mixed || source.value !== value)) patch[name] = value;
9601
+ }
9602
+ function addLegacyTextEffectValue(values, value) {
9603
+ const effect = normalizeDocumentLegacyTextEffect(value);
9604
+ values.set(null === effect ? 'inherited' : String(effect), effect);
9605
+ }
9422
9606
  function characterSpacingTwipsFromDraft(draft) {
9423
9607
  if ('normal' === draft.characterSpacingMode) return 0;
9424
9608
  if ('mixed' === draft.characterSpacingMode) return null;
@@ -9456,9 +9640,307 @@ function selectedValue(values) {
9456
9640
  value: mixed ? null : values.values().next().value ?? null
9457
9641
  };
9458
9642
  }
9459
- function formatPoints(value) {
9643
+ function document_font_dialog_model_formatPoints(value) {
9460
9644
  return String(Number(value.toFixed(2)));
9461
9645
  }
9646
+ const runBorderModes = [
9647
+ {
9648
+ value: 'mixed',
9649
+ label: '混合(保持不变)',
9650
+ disabled: true
9651
+ },
9652
+ {
9653
+ value: 'inherit',
9654
+ label: '跟随样式'
9655
+ },
9656
+ {
9657
+ value: 'none',
9658
+ label: '无(显式重置)'
9659
+ },
9660
+ {
9661
+ value: 'value',
9662
+ label: '边框'
9663
+ }
9664
+ ];
9665
+ const runBorderStyles = [
9666
+ {
9667
+ value: 'single',
9668
+ label: '单实线'
9669
+ },
9670
+ {
9671
+ value: 'thick',
9672
+ label: '粗实线'
9673
+ },
9674
+ {
9675
+ value: 'double',
9676
+ label: '双线'
9677
+ },
9678
+ {
9679
+ value: 'dotted',
9680
+ label: '点线'
9681
+ },
9682
+ {
9683
+ value: 'dashed',
9684
+ label: '虚线'
9685
+ },
9686
+ {
9687
+ value: 'dotDash',
9688
+ label: '点划线'
9689
+ },
9690
+ {
9691
+ value: 'dotDotDash',
9692
+ label: '双点划线'
9693
+ },
9694
+ {
9695
+ value: 'triple',
9696
+ label: '三线'
9697
+ },
9698
+ {
9699
+ value: 'thinThickSmallGap',
9700
+ label: '细粗线(小间距)'
9701
+ },
9702
+ {
9703
+ value: 'thickThinSmallGap',
9704
+ label: '粗细线(小间距)'
9705
+ },
9706
+ {
9707
+ value: 'thinThickThinSmallGap',
9708
+ label: '细粗细线(小间距)'
9709
+ },
9710
+ {
9711
+ value: 'thinThickMediumGap',
9712
+ label: '细粗线(中间距)'
9713
+ },
9714
+ {
9715
+ value: 'thickThinMediumGap',
9716
+ label: '粗细线(中间距)'
9717
+ },
9718
+ {
9719
+ value: 'thinThickThinMediumGap',
9720
+ label: '细粗细线(中间距)'
9721
+ },
9722
+ {
9723
+ value: 'thinThickLargeGap',
9724
+ label: '细粗线(大间距)'
9725
+ },
9726
+ {
9727
+ value: 'thickThinLargeGap',
9728
+ label: '粗细线(大间距)'
9729
+ },
9730
+ {
9731
+ value: 'thinThickThinLargeGap',
9732
+ label: '细粗细线(大间距)'
9733
+ },
9734
+ {
9735
+ value: 'wave',
9736
+ label: '波浪线'
9737
+ },
9738
+ {
9739
+ value: 'doubleWave',
9740
+ label: '双波浪线'
9741
+ },
9742
+ {
9743
+ value: 'dashSmallGap',
9744
+ label: '短划线'
9745
+ },
9746
+ {
9747
+ value: 'dashDotStroked',
9748
+ label: '粗点划线'
9749
+ },
9750
+ {
9751
+ value: 'threeDEmboss',
9752
+ label: '三维浮雕'
9753
+ },
9754
+ {
9755
+ value: 'threeDEngrave',
9756
+ label: '三维凹刻'
9757
+ },
9758
+ {
9759
+ value: 'outset',
9760
+ label: '外凸'
9761
+ },
9762
+ {
9763
+ value: 'inset',
9764
+ label: '内凹'
9765
+ }
9766
+ ];
9767
+ function DocumentFontDialogRunBorderSection({ source, draft, touched, onDraftChange, onTouched }) {
9768
+ const enabled = 'value' === draft.runBorderMode;
9769
+ const update = (patch)=>{
9770
+ onDraftChange(patch);
9771
+ onTouched();
9772
+ };
9773
+ return /*#__PURE__*/ jsxs("fieldset", {
9774
+ className: "work-document-font-dialog-run-border",
9775
+ "aria-label": "字符边框设置",
9776
+ children: [
9777
+ /*#__PURE__*/ jsx("legend", {
9778
+ children: "字符边框"
9779
+ }),
9780
+ /*#__PURE__*/ jsxs("div", {
9781
+ className: "work-document-font-dialog-field",
9782
+ children: [
9783
+ /*#__PURE__*/ jsx("span", {
9784
+ children: "应用方式"
9785
+ }),
9786
+ /*#__PURE__*/ jsx(OfficeSelect, {
9787
+ ariaLabel: "字符边框",
9788
+ value: draft.runBorderMode,
9789
+ options: runBorderModes,
9790
+ onValueChange: (runBorderMode)=>update({
9791
+ runBorderMode
9792
+ })
9793
+ })
9794
+ ]
9795
+ }),
9796
+ /*#__PURE__*/ jsxs("div", {
9797
+ className: "work-document-font-dialog-field",
9798
+ children: [
9799
+ /*#__PURE__*/ jsx("span", {
9800
+ children: "线型"
9801
+ }),
9802
+ /*#__PURE__*/ jsx(OfficeSelect, {
9803
+ ariaLabel: "字符边框线型",
9804
+ value: draft.runBorderStyle,
9805
+ options: runBorderStyles,
9806
+ disabled: !enabled,
9807
+ onValueChange: (runBorderStyle)=>update({
9808
+ runBorderMode: 'value',
9809
+ runBorderStyle
9810
+ })
9811
+ })
9812
+ ]
9813
+ }),
9814
+ /*#__PURE__*/ jsxs("div", {
9815
+ className: "work-document-font-dialog-field",
9816
+ children: [
9817
+ /*#__PURE__*/ jsx("span", {
9818
+ children: "颜色"
9819
+ }),
9820
+ /*#__PURE__*/ jsx(OfficeColorPicker, {
9821
+ ariaLabel: "字符边框颜色",
9822
+ value: 'auto' === draft.runBorderColor ? '#000000' : draft.runBorderColor,
9823
+ disabled: !enabled,
9824
+ resetAction: {
9825
+ kind: 'automatic',
9826
+ label: '自动颜色',
9827
+ onSelect: ()=>update({
9828
+ runBorderMode: 'value',
9829
+ runBorderColor: 'auto'
9830
+ })
9831
+ },
9832
+ onValueChange: (runBorderColor)=>update({
9833
+ runBorderMode: 'value',
9834
+ runBorderColor: runBorderColor
9835
+ })
9836
+ })
9837
+ ]
9838
+ }),
9839
+ /*#__PURE__*/ jsxs("div", {
9840
+ className: "work-document-font-dialog-field",
9841
+ children: [
9842
+ /*#__PURE__*/ jsx("span", {
9843
+ children: "宽度"
9844
+ }),
9845
+ /*#__PURE__*/ jsxs("span", {
9846
+ className: "work-document-font-dialog-measure",
9847
+ children: [
9848
+ /*#__PURE__*/ jsx(OfficeNumberField, {
9849
+ ariaLabel: "字符边框宽度(磅)",
9850
+ value: draft.runBorderWidthPoints,
9851
+ min: 0.25,
9852
+ max: 12,
9853
+ step: 0.125,
9854
+ disabled: !enabled,
9855
+ onValueChange: (runBorderWidthPoints)=>update({
9856
+ runBorderMode: 'value',
9857
+ runBorderWidthPoints
9858
+ })
9859
+ }),
9860
+ /*#__PURE__*/ jsx("span", {
9861
+ "aria-hidden": "true",
9862
+ children: "磅"
9863
+ })
9864
+ ]
9865
+ })
9866
+ ]
9867
+ }),
9868
+ /*#__PURE__*/ jsxs("div", {
9869
+ className: "work-document-font-dialog-field",
9870
+ children: [
9871
+ /*#__PURE__*/ jsx("span", {
9872
+ children: "文字间距"
9873
+ }),
9874
+ /*#__PURE__*/ jsxs("span", {
9875
+ className: "work-document-font-dialog-measure",
9876
+ children: [
9877
+ /*#__PURE__*/ jsx(OfficeNumberField, {
9878
+ ariaLabel: "字符边框间距(磅)",
9879
+ value: draft.runBorderSpacingPoints,
9880
+ min: 0,
9881
+ max: 31,
9882
+ step: 1,
9883
+ disabled: !enabled,
9884
+ onValueChange: (runBorderSpacingPoints)=>update({
9885
+ runBorderMode: 'value',
9886
+ runBorderSpacingPoints
9887
+ })
9888
+ }),
9889
+ /*#__PURE__*/ jsx("span", {
9890
+ "aria-hidden": "true",
9891
+ children: "磅"
9892
+ })
9893
+ ]
9894
+ })
9895
+ ]
9896
+ }),
9897
+ /*#__PURE__*/ jsxs("div", {
9898
+ className: "work-document-font-dialog-run-border-effects",
9899
+ children: [
9900
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
9901
+ ariaLabel: "字符边框阴影",
9902
+ checked: draft.runBorderShadow,
9903
+ disabled: !enabled,
9904
+ onCheckedChange: (runBorderShadow)=>update({
9905
+ runBorderMode: 'value',
9906
+ runBorderShadow
9907
+ }),
9908
+ children: "阴影"
9909
+ }),
9910
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
9911
+ ariaLabel: "字符边框框架",
9912
+ checked: draft.runBorderFrame,
9913
+ disabled: !enabled,
9914
+ onCheckedChange: (runBorderFrame)=>update({
9915
+ runBorderMode: 'value',
9916
+ runBorderFrame
9917
+ }),
9918
+ children: "框架"
9919
+ })
9920
+ ]
9921
+ }),
9922
+ source.mixed && !touched ? /*#__PURE__*/ jsx("p", {
9923
+ className: "work-document-font-dialog-mixed",
9924
+ role: "status",
9925
+ children: "当前选区包含不同的字符边框。选择一种应用方式后才会统一修改。"
9926
+ }) : null
9927
+ ]
9928
+ });
9929
+ }
9930
+ function documentFontDialogRunBorderPreviewStyle(source, draft) {
9931
+ const border = documentFontDialogRunBorderFromDraft(source, draft);
9932
+ if (!border) return {};
9933
+ const presentation = documentBorderPresentation(border);
9934
+ return {
9935
+ border: `${presentation.width}px ${presentation.style} ${presentation.color}`,
9936
+ padding: `${(border.space ?? 0) * (96 / 72)}px`,
9937
+ boxDecorationBreak: 'clone',
9938
+ WebkitBoxDecorationBreak: 'clone',
9939
+ ...border.shadow && presentation.width > 0 ? {
9940
+ boxShadow: `2px 2px 0 ${presentation.color}`
9941
+ } : {}
9942
+ };
9943
+ }
9462
9944
  const characterSpacingModes = [
9463
9945
  {
9464
9946
  value: 'mixed',
@@ -9536,6 +10018,11 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
9536
10018
  const [kerningTouched, setKerningTouched] = useState(false);
9537
10019
  const [emphasisTouched, setEmphasisTouched] = useState(false);
9538
10020
  const [hiddenTextTouched, setHiddenTextTouched] = useState(false);
10021
+ const [legacyTextOutlineTouched, setLegacyTextOutlineTouched] = useState(false);
10022
+ const [legacyTextShadowTouched, setLegacyTextShadowTouched] = useState(false);
10023
+ const [legacyTextEmbossTouched, setLegacyTextEmbossTouched] = useState(false);
10024
+ const [legacyTextImprintTouched, setLegacyTextImprintTouched] = useState(false);
10025
+ const [runBorderTouched, setRunBorderTouched] = useState(false);
9539
10026
  const [latinFontTouched, setLatinFontTouched] = useState(false);
9540
10027
  const [eastAsiaFontTouched, setEastAsiaFontTouched] = useState(false);
9541
10028
  const [complexScriptFontTouched, setComplexScriptFontTouched] = useState(false);
@@ -9549,6 +10036,11 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
9549
10036
  eastAsiaFont: eastAsiaFontTouched,
9550
10037
  emphasisMark: emphasisTouched,
9551
10038
  hiddenText: hiddenTextTouched,
10039
+ legacyTextOutline: legacyTextOutlineTouched,
10040
+ legacyTextShadow: legacyTextShadowTouched,
10041
+ legacyTextEmboss: legacyTextEmbossTouched,
10042
+ legacyTextImprint: legacyTextImprintTouched,
10043
+ runBorder: runBorderTouched,
9552
10044
  kerning: kerningTouched,
9553
10045
  latinFont: latinFontTouched
9554
10046
  });
@@ -9558,6 +10050,13 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
9558
10050
  const previewPosition = previewCharacterPosition(draft);
9559
10051
  const previewKerning = previewDocumentKerning(draft, source.fontSize);
9560
10052
  const previewEmphasis = previewDocumentEmphasis(draft.emphasisMark);
10053
+ const previewLegacyTextEffects = documentLegacyTextEffectsCss({
10054
+ outline: draft.legacyTextOutline,
10055
+ shadow: draft.legacyTextShadow,
10056
+ emboss: draft.legacyTextEmboss,
10057
+ imprint: draft.legacyTextImprint
10058
+ });
10059
+ const previewRunBorder = documentFontDialogRunBorderPreviewStyle(source.runBorder, draft);
9561
10060
  const submit = (event)=>{
9562
10061
  event?.preventDefault();
9563
10062
  if (!hasChanges || error) return;
@@ -9677,7 +10176,7 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
9677
10176
  className: "work-document-font-dialog-spacing",
9678
10177
  children: [
9679
10178
  /*#__PURE__*/ jsx("legend", {
9680
- children: "字符缩放、间距、字距调整、位置、着重号与隐藏文字"
10179
+ children: "字符缩放、间距、字距调整、位置与文字效果"
9681
10180
  }),
9682
10181
  /*#__PURE__*/ jsxs("div", {
9683
10182
  className: "work-document-font-dialog-field",
@@ -9899,6 +10398,114 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
9899
10398
  children: "隐藏文字"
9900
10399
  })
9901
10400
  }),
10401
+ /*#__PURE__*/ jsxs("fieldset", {
10402
+ className: "work-document-font-dialog-legacy-effects",
10403
+ "aria-label": "文字效果",
10404
+ children: [
10405
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
10406
+ ariaLabel: "空心",
10407
+ checked: draft.legacyTextOutline,
10408
+ indeterminate: source.legacyTextOutline.mixed && !legacyTextOutlineTouched,
10409
+ onCheckedChange: (legacyTextOutline)=>{
10410
+ setDraft((current)=>legacyTextOutline ? {
10411
+ ...current,
10412
+ legacyTextOutline,
10413
+ legacyTextEmboss: false,
10414
+ legacyTextImprint: false
10415
+ } : {
10416
+ ...current,
10417
+ legacyTextOutline
10418
+ });
10419
+ setLegacyTextOutlineTouched(true);
10420
+ if (legacyTextOutline) {
10421
+ setLegacyTextEmbossTouched(true);
10422
+ setLegacyTextImprintTouched(true);
10423
+ }
10424
+ },
10425
+ children: "空心"
10426
+ }),
10427
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
10428
+ ariaLabel: "阴影",
10429
+ checked: draft.legacyTextShadow,
10430
+ indeterminate: source.legacyTextShadow.mixed && !legacyTextShadowTouched,
10431
+ onCheckedChange: (legacyTextShadow)=>{
10432
+ setDraft((current)=>legacyTextShadow ? {
10433
+ ...current,
10434
+ legacyTextShadow,
10435
+ legacyTextEmboss: false,
10436
+ legacyTextImprint: false
10437
+ } : {
10438
+ ...current,
10439
+ legacyTextShadow
10440
+ });
10441
+ setLegacyTextShadowTouched(true);
10442
+ if (legacyTextShadow) {
10443
+ setLegacyTextEmbossTouched(true);
10444
+ setLegacyTextImprintTouched(true);
10445
+ }
10446
+ },
10447
+ children: "阴影"
10448
+ }),
10449
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
10450
+ ariaLabel: "阳文",
10451
+ checked: draft.legacyTextEmboss,
10452
+ indeterminate: source.legacyTextEmboss.mixed && !legacyTextEmbossTouched,
10453
+ onCheckedChange: (legacyTextEmboss)=>{
10454
+ setDraft((current)=>legacyTextEmboss ? {
10455
+ ...current,
10456
+ legacyTextOutline: false,
10457
+ legacyTextShadow: false,
10458
+ legacyTextEmboss,
10459
+ legacyTextImprint: false
10460
+ } : {
10461
+ ...current,
10462
+ legacyTextEmboss
10463
+ });
10464
+ setLegacyTextEmbossTouched(true);
10465
+ if (legacyTextEmboss) {
10466
+ setLegacyTextOutlineTouched(true);
10467
+ setLegacyTextShadowTouched(true);
10468
+ setLegacyTextImprintTouched(true);
10469
+ }
10470
+ },
10471
+ children: "阳文"
10472
+ }),
10473
+ /*#__PURE__*/ jsx(OfficeCheckbox, {
10474
+ ariaLabel: "阴文",
10475
+ checked: draft.legacyTextImprint,
10476
+ indeterminate: source.legacyTextImprint.mixed && !legacyTextImprintTouched,
10477
+ onCheckedChange: (legacyTextImprint)=>{
10478
+ setDraft((current)=>legacyTextImprint ? {
10479
+ ...current,
10480
+ legacyTextOutline: false,
10481
+ legacyTextShadow: false,
10482
+ legacyTextEmboss: false,
10483
+ legacyTextImprint
10484
+ } : {
10485
+ ...current,
10486
+ legacyTextImprint
10487
+ });
10488
+ setLegacyTextImprintTouched(true);
10489
+ if (legacyTextImprint) {
10490
+ setLegacyTextOutlineTouched(true);
10491
+ setLegacyTextShadowTouched(true);
10492
+ setLegacyTextEmbossTouched(true);
10493
+ }
10494
+ },
10495
+ children: "阴文"
10496
+ })
10497
+ ]
10498
+ }),
10499
+ /*#__PURE__*/ jsx(DocumentFontDialogRunBorderSection, {
10500
+ source: source.runBorder,
10501
+ draft: draft,
10502
+ touched: runBorderTouched,
10503
+ onDraftChange: (runBorderDraft)=>setDraft((current)=>({
10504
+ ...current,
10505
+ ...runBorderDraft
10506
+ })),
10507
+ onTouched: ()=>setRunBorderTouched(true)
10508
+ }),
9902
10509
  source.characterScale.mixed && !characterScaleTouched && /*#__PURE__*/ jsx("p", {
9903
10510
  className: "work-document-font-dialog-mixed",
9904
10511
  role: "status",
@@ -9929,7 +10536,12 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
9929
10536
  role: "status",
9930
10537
  children: "当前选区同时包含隐藏和可见文字。勾选或取消后才会统一修改。"
9931
10538
  }),
9932
- (characterScaleTouched || characterSpacingTouched || characterPositionTouched || kerningTouched || emphasisTouched || hiddenTextTouched) && error && /*#__PURE__*/ jsx("p", {
10539
+ (source.legacyTextOutline.mixed && !legacyTextOutlineTouched || source.legacyTextShadow.mixed && !legacyTextShadowTouched || source.legacyTextEmboss.mixed && !legacyTextEmbossTouched || source.legacyTextImprint.mixed && !legacyTextImprintTouched) && /*#__PURE__*/ jsx("p", {
10540
+ className: "work-document-font-dialog-mixed",
10541
+ role: "status",
10542
+ children: "当前选区包含不同的空心、阴影、阳文或阴文设置。勾选或取消对应选项后才会统一修改。"
10543
+ }),
10544
+ (characterScaleTouched || characterSpacingTouched || characterPositionTouched || kerningTouched || emphasisTouched || hiddenTextTouched || legacyTextOutlineTouched || legacyTextShadowTouched || legacyTextEmbossTouched || legacyTextImprintTouched || runBorderTouched) && error && /*#__PURE__*/ jsx("p", {
9933
10545
  className: "work-document-font-dialog-error",
9934
10546
  role: "alert",
9935
10547
  children: error
@@ -9955,6 +10567,8 @@ function DocumentFontDialog({ source, layoutFonts = [], restoreFocusTarget, onAp
9955
10567
  style: {
9956
10568
  verticalAlign: `${previewPosition}pt`,
9957
10569
  ...previewEmphasis,
10570
+ ...previewLegacyTextEffects,
10571
+ ...previewRunBorder,
9958
10572
  ...draft.hiddenText ? {
9959
10573
  textDecorationColor: 'currentColor',
9960
10574
  textDecorationLine: 'underline',
@@ -10032,7 +10646,7 @@ function previewScriptFontFamily(value, fallback) {
10032
10646
  return 'mixed' === value || 'inherit' === value ? fallback ?? void 0 : value;
10033
10647
  }
10034
10648
  function fontDialogDescription(source) {
10035
- return source.selectedCharacters ? `分别设置当前选中内容的拉丁、东亚和复杂文字字体,以及原生字符缩放、间距、字距调整阈值、位置、着重号和隐藏文字(${source.selectedCharacters} 个字符)。` : '分别设置当前位置后续输入文字的拉丁、东亚和复杂文字字体,以及原生字符缩放、间距、字距调整阈值、位置、着重号和隐藏文字。';
10649
+ return source.selectedCharacters ? `分别设置当前选中内容的拉丁、东亚和复杂文字字体,以及原生字符缩放、间距、字距调整阈值、位置、着重号、隐藏文字、空心、阴影、阳文和阴文(${source.selectedCharacters} 个字符)。` : '分别设置当前位置后续输入文字的拉丁、东亚和复杂文字字体,以及原生字符缩放、间距、字距调整阈值、位置、着重号、隐藏文字、空心、阴影、阳文和阴文。';
10036
10650
  }
10037
10651
  function DocumentPageChromeRibbon({ editor, editingPart, showPageNumber, onEditingPartChange, onTogglePageNumber, onOpenFontDialog, onClose }) {
10038
10652
  const imageInputRef = useRef(null);