@docx-editor.dev/core 2.31.0 → 2.32.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.
- package/README.md +24 -0
- package/dist/automation.cjs +1 -1
- package/dist/automation.d.ts +16 -16
- package/dist/automation.js +1 -1
- package/dist/binding.cjs +1 -1
- package/dist/binding.d.ts +17 -15
- package/dist/binding.js +1 -1
- package/dist/{chrome-print-BWvaVEhD.d.ts → chrome-print-CznJ0ucN.d.ts} +58 -23
- package/dist/chunk-25EXMBV2.cjs +5 -0
- package/dist/chunk-2CWQY27B.cjs +1 -0
- package/dist/chunk-3IEXDEFH.cjs +7 -0
- package/dist/chunk-65XBN67F.cjs +2 -0
- package/dist/{chunk-5JPIEN54.cjs → chunk-6NVZNB7O.cjs} +2 -2
- package/dist/chunk-6UDJUI3W.cjs +2 -0
- package/dist/chunk-ACLR4DMK.js +1 -0
- package/dist/{chunk-2E2RPEKX.js → chunk-B2BEELUE.js} +1 -1
- package/dist/chunk-DDFHKQFU.js +30 -0
- package/dist/{chunk-MOYYRVFV.cjs → chunk-E4IAO4CY.cjs} +1 -1
- package/dist/chunk-ETDZFNMI.js +2 -0
- package/dist/chunk-FDSL5OJU.cjs +30 -0
- package/dist/chunk-FS7CMYLT.js +4 -0
- package/dist/chunk-GDS24SZN.js +30 -0
- package/dist/chunk-GIY6NT2X.js +5 -0
- package/dist/chunk-GWM3AKUD.js +18 -0
- package/dist/chunk-HDOXACHP.js +2 -0
- package/dist/chunk-IILEENID.js +1 -0
- package/dist/chunk-L5TYBFDB.js +1 -0
- package/dist/chunk-MNF2K7NN.cjs +30 -0
- package/dist/chunk-O324RB6R.cjs +1 -0
- package/dist/chunk-OKMEMSKB.cjs +1 -0
- package/dist/chunk-QXJKYNYZ.js +1 -0
- package/dist/chunk-RALTVLB6.js +2 -0
- package/dist/chunk-SRVKFUFI.js +3 -0
- package/dist/chunk-TELQ52LG.cjs +1 -0
- package/dist/chunk-TJHE5EET.cjs +1 -0
- package/dist/chunk-UMMRURPE.js +7 -0
- package/dist/chunk-WN7ICTA5.js +1 -0
- package/dist/{chunk-XSTGE3NI.cjs → chunk-XJYZVGQR.cjs} +1 -1
- package/dist/chunk-ZGTIE3QJ.cjs +4 -0
- package/dist/chunk-ZOZI27AW.cjs +18 -0
- package/dist/collaboration/replication.cjs +1 -1
- package/dist/collaboration/replication.d.ts +20 -4
- package/dist/collaboration/replication.js +1 -1
- package/dist/collaboration.cjs +1 -1
- package/dist/collaboration.d.ts +5 -5
- package/dist/collaboration.js +1 -1
- package/dist/contracts/document.d.ts +3 -3
- package/dist/contracts/editor.d.ts +13 -9
- package/dist/contracts/interaction.d.ts +2 -2
- package/dist/contracts/modules.d.ts +15 -12
- package/dist/contracts/types.d.ts +135 -2
- package/dist/{custom-node-writes-TeUvMP13.d.ts → custom-node-writes-CLJKGD9t.d.ts} +7 -2
- package/dist/{diagnostic-context-DJ0P1uZE.d.ts → diagnostic-context-BtDUY3v2.d.ts} +1 -1
- package/dist/{diagnostic-hints-C9JlLz1L.d.ts → diagnostic-hints-DK8-V0fk.d.ts} +2 -2
- package/dist/{document-protection-C8x3P2J6.d.ts → document-protection-NaniLHWF.d.ts} +1 -1
- package/dist/{editor-B2ShlO23.d.ts → editor-DZwOTmlR.d.ts} +104 -239
- package/dist/editor-fonts-D_-vjuJi.d.ts +53 -0
- package/dist/{editor-scope-C7ke1KJG.d.ts → editor-scope-B3L-1ALc.d.ts} +1 -1
- package/dist/editor.cjs +1 -1
- package/dist/editor.css +2 -2
- package/dist/editor.d.ts +74 -30
- package/dist/editor.js +1 -1
- package/dist/export.cjs +2 -2
- package/dist/export.d.ts +9 -15
- package/dist/export.js +1 -1
- package/dist/{failure-NS2lsya4.d.ts → failure-6KGFrDO9.d.ts} +1 -1
- package/dist/{font-resolver-CWh40DYp.d.ts → font-resolver-BlQNGdvR.d.ts} +1 -1
- package/dist/{headless-document-view-qOpaCF82.d.ts → headless-document-view-Bcz9_Qva.d.ts} +115 -4
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +27 -25
- package/dist/index.js +1 -1
- package/dist/{layout-shaping-CWS3j0Xr.d.ts → layout-shaping-E5J4Z1Gf.d.ts} +1 -1
- package/dist/layout.cjs +1 -1
- package/dist/layout.d.ts +24 -17
- package/dist/layout.js +1 -1
- package/dist/{note-properties-QsKh24sM.d.ts → note-properties-Ds5R2_3F.d.ts} +1 -1
- package/dist/output.cjs +1 -1
- package/dist/output.d.ts +11 -7
- package/dist/output.js +1 -1
- package/dist/{protocol-COZJUKUY.d.ts → protocol-DKa4qt7F.d.ts} +75 -5
- package/dist/{review-paragraph-order-C_QbCKcH.d.ts → review-paragraph-order-Dc17w_6v.d.ts} +1 -1
- package/dist/revision-projection-Cn6rZJ7H.d.ts +258 -0
- package/dist/{semantic-cell-selection-Cub9FDa8.d.ts → semantic-cell-selection-BaUR0iJ4.d.ts} +2 -2
- package/dist/{semantic-interaction-dApRIYpt.d.ts → semantic-interaction-CJoHLoOl.d.ts} +1 -1
- package/dist/{semantic-paint-DLzA8sjP.d.ts → semantic-paint-BPw_n0li.d.ts} +7 -4
- package/dist/{semantic-record-queries-3yp9o11g.d.ts → semantic-record-queries-C0rJ3sB4.d.ts} +1 -1
- package/dist/{semantic-records-B-akgRch.d.ts → semantic-records-BvN-WWst.d.ts} +216 -406
- package/dist/store.cjs +1 -1
- package/dist/store.d.ts +13 -14
- package/dist/store.js +1 -1
- package/dist/{types-barrel-CkF2JbU4.d.ts → tree-op-types-C_S2niXW.d.ts} +117 -26
- package/dist/{tree-package-store-B8l8DX3Z.d.ts → tree-package-store-CRHvMyNj.d.ts} +2 -2
- package/dist/{tree-session-contract-DeLRqohz.d.ts → tree-session-contract-D1awo_dA.d.ts} +5 -5
- package/dist/unsupported-elements-CVos5cqe.d.ts +23 -0
- package/docs/accept-reject-without-scrolling.md +95 -0
- package/docs/comment-on-found-text.md +72 -0
- package/docs/custom-review-cards.md +178 -0
- package/docs/highlight-ranges.md +48 -0
- package/docs/index.md +36 -0
- package/docs/propose-rewrite.md +247 -0
- package/docs/tracked-replacement.md +68 -0
- package/package.json +3 -2
- package/dist/chunk-243W4WW2.cjs +0 -2
- package/dist/chunk-4S24UOPG.js +0 -30
- package/dist/chunk-5SO5QDMV.cjs +0 -2
- package/dist/chunk-6IDOVU6L.cjs +0 -1
- package/dist/chunk-6JIJOZDW.js +0 -1
- package/dist/chunk-BTQKU64Q.cjs +0 -1
- package/dist/chunk-DBOOTED4.cjs +0 -30
- package/dist/chunk-EOTAXOJY.cjs +0 -5
- package/dist/chunk-FDAKJ2SJ.cjs +0 -30
- package/dist/chunk-FNNOJNGY.js +0 -3
- package/dist/chunk-FT33HRZP.js +0 -5
- package/dist/chunk-HC6YNKUI.cjs +0 -1
- package/dist/chunk-HZ66UCIS.js +0 -2
- package/dist/chunk-IBRBNT37.cjs +0 -1
- package/dist/chunk-IVIN7X43.js +0 -30
- package/dist/chunk-LZY6B6IV.js +0 -4
- package/dist/chunk-N6B3BXCL.js +0 -1
- package/dist/chunk-Q5K2GGNG.js +0 -2
- package/dist/chunk-R2XINWVE.js +0 -7
- package/dist/chunk-SUEXVBPR.js +0 -1
- package/dist/chunk-T2QQHG5C.js +0 -18
- package/dist/chunk-VWIJKH4A.js +0 -1
- package/dist/chunk-WO4V6PNS.cjs +0 -18
- package/dist/chunk-XMJKFURD.cjs +0 -4
- package/dist/chunk-YQWMI6J5.cjs +0 -7
- package/dist/chunk-ZCJS7D7S.js +0 -2
- package/dist/omml-equation-BsLAa2lX.d.ts +0 -115
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { H as HistoryGroupOutcome } from './editor-scope-B3L-1ALc.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Why a zip was refused at the trust boundary.
|
|
@@ -2001,6 +2001,18 @@ type AutomationTableMutation = {
|
|
|
2001
2001
|
readonly kind: 'deleteRows' | 'deleteColumns';
|
|
2002
2002
|
readonly index: number;
|
|
2003
2003
|
readonly count: number;
|
|
2004
|
+
} | {
|
|
2005
|
+
/** Merge the rectangle from one cell to another, by row and in-row cell index. */
|
|
2006
|
+
readonly kind: 'mergeCells';
|
|
2007
|
+
readonly topRow: number;
|
|
2008
|
+
readonly firstCell: number;
|
|
2009
|
+
readonly bottomRow: number;
|
|
2010
|
+
readonly lastCell: number;
|
|
2011
|
+
} | {
|
|
2012
|
+
readonly kind: 'splitCell';
|
|
2013
|
+
readonly cellId: string;
|
|
2014
|
+
readonly rowCount: number;
|
|
2015
|
+
readonly columnCount: number;
|
|
2004
2016
|
} | {
|
|
2005
2017
|
readonly kind: 'delete';
|
|
2006
2018
|
} | {
|
|
@@ -2031,6 +2043,70 @@ interface SetFieldCodeOp {
|
|
|
2031
2043
|
readonly code: string;
|
|
2032
2044
|
}
|
|
2033
2045
|
|
|
2046
|
+
/**
|
|
2047
|
+
* Insert an allowlisted page-number complex field at a UTF-16 offset.
|
|
2048
|
+
*
|
|
2049
|
+
* `PAGE_X_OF_Y` is PAGE + literal " of " + NUMPAGES in one undoable op. Non-page
|
|
2050
|
+
* instructions are refused — never authored through this path.
|
|
2051
|
+
*/
|
|
2052
|
+
interface InsertPageFieldOp {
|
|
2053
|
+
readonly op: 'insertPageField';
|
|
2054
|
+
readonly paragraphId: string;
|
|
2055
|
+
readonly offset: number;
|
|
2056
|
+
readonly field: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES' | 'PAGE_X_OF_Y';
|
|
2057
|
+
/**
|
|
2058
|
+
* Write this as a TRACKED insertion, on the same terms as `insertText`.
|
|
2059
|
+
*
|
|
2060
|
+
* The whole field — every `w:fldChar`, the instruction, the `PAGE_X_OF_Y` literal —
|
|
2061
|
+
* goes into ONE `w:ins`, because the field is one proposal: rejecting it must take
|
|
2062
|
+
* the complete atom back, never leave a `begin` standing without its `end`.
|
|
2063
|
+
*/
|
|
2064
|
+
readonly revision?: RevisionAttributionInput;
|
|
2065
|
+
}
|
|
2066
|
+
/**
|
|
2067
|
+
* Insert one complex field with an empty cached result at a UTF-16 offset.
|
|
2068
|
+
*
|
|
2069
|
+
* The instruction must be one that `inertFieldInstruction` admits: a page number, a reference
|
|
2070
|
+
* to a bookmark, note, or style, a sequence number, or a date. It is written as text and never
|
|
2071
|
+
* evaluated. Every other instruction refuses with `invalidArgs`.
|
|
2072
|
+
*/
|
|
2073
|
+
interface InsertComplexFieldOp {
|
|
2074
|
+
readonly op: 'insertComplexField';
|
|
2075
|
+
readonly paragraphId: string;
|
|
2076
|
+
readonly offset: number;
|
|
2077
|
+
readonly instruction: string;
|
|
2078
|
+
/** Write the whole field as ONE tracked insertion, on the same terms as `insertText`. */
|
|
2079
|
+
readonly revision?: RevisionAttributionInput;
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
/** Set one field's cached result text. See the module comment for the placements. */
|
|
2083
|
+
interface SetFieldResultOp {
|
|
2084
|
+
readonly op: 'setFieldResult';
|
|
2085
|
+
readonly paragraphId: string;
|
|
2086
|
+
/** The begin `w:fldChar`, or the `w:fldSimple` element. */
|
|
2087
|
+
readonly fieldNodeId: string;
|
|
2088
|
+
/** Plain text. A tab becomes `w:tab`; other control characters refuse. */
|
|
2089
|
+
readonly text: string;
|
|
2090
|
+
/**
|
|
2091
|
+
* The author whose pending insertion holds the field. The result joins that insertion. The
|
|
2092
|
+
* op mints no revision of its own.
|
|
2093
|
+
*/
|
|
2094
|
+
readonly revision?: RevisionAttributionInput;
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
/** Insert one inline `m:oMath` and the plain runs beside it. */
|
|
2098
|
+
interface InsertEquationOp {
|
|
2099
|
+
readonly op: 'insertEquation';
|
|
2100
|
+
readonly paragraphId: string;
|
|
2101
|
+
readonly offset: number;
|
|
2102
|
+
/** Plain runs and exactly one inline `m:oMath`, in order. Receive fresh ids at apply. */
|
|
2103
|
+
readonly nodes: readonly OoxmlNode[];
|
|
2104
|
+
/** Model length of `nodes`: their text, plus one for the equation. */
|
|
2105
|
+
readonly length: number;
|
|
2106
|
+
/** Write the nodes as ONE tracked insertion, on the same terms as `insertText`. */
|
|
2107
|
+
readonly revision?: RevisionAttributionInput;
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2034
2110
|
type InsertTextOp = {
|
|
2035
2111
|
readonly op: 'insertText';
|
|
2036
2112
|
readonly paragraphId: string;
|
|
@@ -2877,8 +2953,18 @@ interface RevisionBatchResult {
|
|
|
2877
2953
|
/** All pending decisions in the addressed scope, including excluded and unsupported changes. */
|
|
2878
2954
|
readonly remaining: number;
|
|
2879
2955
|
}
|
|
2880
|
-
/**
|
|
2881
|
-
|
|
2956
|
+
/**
|
|
2957
|
+
* @internal Pure preflight; callers commit its operations through their normal write guards.
|
|
2958
|
+
*
|
|
2959
|
+
* `countRemaining: false` skips the exact count of the decisions left after the batch, and
|
|
2960
|
+
* reports `remaining` as the decisions not resolved here. The exact count resolves the whole
|
|
2961
|
+
* batch once more on a copy and lists what is left, which on a long reviewed document cost more
|
|
2962
|
+
* than the plan itself, and a caller that reads only the operations or the skipped changes
|
|
2963
|
+
* (a check, one decision, an editor that recounts its queue) paid it on every call.
|
|
2964
|
+
*/
|
|
2965
|
+
declare function planRevisionBatch(part: OoxmlPart, action: 'accept' | 'reject', keys?: readonly string[], scopeRoot?: OoxmlNode, options?: {
|
|
2966
|
+
readonly countRemaining?: boolean;
|
|
2967
|
+
}): {
|
|
2882
2968
|
ops: readonly TreeDocOp[];
|
|
2883
2969
|
result: RevisionBatchResult;
|
|
2884
2970
|
};
|
|
@@ -3787,26 +3873,7 @@ type TreeDocOp = SetFieldCodeOp | {
|
|
|
3787
3873
|
readonly offset: number;
|
|
3788
3874
|
/** Write this as a TRACKED insertion, on the same terms as `insertText`. */
|
|
3789
3875
|
readonly revision?: RevisionAttributionInput;
|
|
3790
|
-
} | {
|
|
3791
|
-
/**
|
|
3792
|
-
* Insert an allowlisted page-number complex field at a UTF-16 offset.
|
|
3793
|
-
*
|
|
3794
|
-
* `PAGE_X_OF_Y` is PAGE + literal " of " + NUMPAGES in one undoable op. Non-page
|
|
3795
|
-
* instructions are refused — never authored through this path.
|
|
3796
|
-
*/
|
|
3797
|
-
readonly op: 'insertPageField';
|
|
3798
|
-
readonly paragraphId: string;
|
|
3799
|
-
readonly offset: number;
|
|
3800
|
-
readonly field: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES' | 'PAGE_X_OF_Y';
|
|
3801
|
-
/**
|
|
3802
|
-
* Write this as a TRACKED insertion, on the same terms as `insertText`.
|
|
3803
|
-
*
|
|
3804
|
-
* The whole field — every `w:fldChar`, the instruction, the `PAGE_X_OF_Y` literal —
|
|
3805
|
-
* goes into ONE `w:ins`, because the field is one proposal: rejecting it must take
|
|
3806
|
-
* the complete atom back, never leave a `begin` standing without its `end`.
|
|
3807
|
-
*/
|
|
3808
|
-
readonly revision?: RevisionAttributionInput;
|
|
3809
|
-
} | {
|
|
3876
|
+
} | InsertPageFieldOp | InsertComplexFieldOp | SetFieldResultOp | InsertEquationOp | {
|
|
3810
3877
|
/**
|
|
3811
3878
|
* Move a numbered paragraph to another `w:numPr/w:ilvl`.
|
|
3812
3879
|
*
|
|
@@ -4095,6 +4162,8 @@ type TreeDocOp = SetFieldCodeOp | {
|
|
|
4095
4162
|
readonly xpath: string;
|
|
4096
4163
|
readonly storeItemId: string;
|
|
4097
4164
|
};
|
|
4165
|
+
/** Propose the control as a tracked `w:ins`; rejecting removes it with its text. */
|
|
4166
|
+
readonly revision?: RevisionAttributionInput;
|
|
4098
4167
|
} | {
|
|
4099
4168
|
/** Repeating-section item insert — unsupported at this layer (out of scope). */
|
|
4100
4169
|
readonly op: 'addRepeatingSectionItem';
|
|
@@ -4169,6 +4238,18 @@ type TreeDocOp = SetFieldCodeOp | {
|
|
|
4169
4238
|
readonly op: 'deleteTableColumn';
|
|
4170
4239
|
readonly tableId: string;
|
|
4171
4240
|
readonly gridColumnId: string;
|
|
4241
|
+
} | {
|
|
4242
|
+
/** Merge cells covering one rectangle into its top-left cell, content in reading order. */
|
|
4243
|
+
readonly op: 'mergeTableCells';
|
|
4244
|
+
readonly tableId: string;
|
|
4245
|
+
readonly cellIds: readonly string[];
|
|
4246
|
+
} | {
|
|
4247
|
+
/** Split one cell into `rows` by `columns` equal cells; a one-row cell adds rows. */
|
|
4248
|
+
readonly op: 'splitTableCell';
|
|
4249
|
+
readonly tableId: string;
|
|
4250
|
+
readonly cellId: string;
|
|
4251
|
+
readonly rows: number;
|
|
4252
|
+
readonly columns: number;
|
|
4172
4253
|
} | {
|
|
4173
4254
|
/**
|
|
4174
4255
|
* Resize one internal divider between two adjacent canonical grid columns.
|
|
@@ -4648,8 +4729,18 @@ type TreeOpRejection = 'unknown-op' | 'unknown-paragraph' | 'not-a-paragraph' |
|
|
|
4648
4729
|
* mapping cannot be trusted and the inserted row would not match it.
|
|
4649
4730
|
*/
|
|
4650
4731
|
| 'row-hides-cell'
|
|
4651
|
-
/**
|
|
4732
|
+
/** The table carries a legacy `w:hMerge`, which grid edits cannot place. */
|
|
4652
4733
|
| 'table-has-merge'
|
|
4734
|
+
/** The cells to merge do not cover one rectangle, or cover only one cell. */
|
|
4735
|
+
| 'cells-not-rectangle'
|
|
4736
|
+
/** A cell merged over several rows splits only into a divisor of them. */
|
|
4737
|
+
| 'split-rows-not-divisor'
|
|
4738
|
+
/** The cells hold a tracked cell insertion, deletion, or merge. */
|
|
4739
|
+
| 'cell-has-revision'
|
|
4740
|
+
/** The split cells would be narrower than the minimum column width. */
|
|
4741
|
+
| 'cell-too-narrow'
|
|
4742
|
+
/** Without `w:tblGrid`, a cell splits only into a divisor of the columns it spans. */
|
|
4743
|
+
| 'split-needs-grid'
|
|
4653
4744
|
/** The addressed grid column id is missing or ambiguous without `w:tblGrid`. */
|
|
4654
4745
|
| 'unknown-grid-column'
|
|
4655
4746
|
/** The operation would exceed bounded table topology limits. */
|
|
@@ -4687,5 +4778,5 @@ type TreeOpResult = {
|
|
|
4687
4778
|
readonly detail?: string;
|
|
4688
4779
|
};
|
|
4689
4780
|
|
|
4690
|
-
export { validateRasterHeader as a$, DEFAULT_IMAGE_RESOURCE_LIMITS as aV, IMAGE_WRAP_TARGETS as aW, TEXT_FORM_FORMATS as aX, resolveImageResourceLimits as aY, resolveSvgIntrinsicSize as aZ, sniffImageMime as a_, DEFAULT_LIMITS as bF, DEFAULT_OOXML_PACKAGE_LIMITS as bG, DEFAULT_ZIP_LIMITS as bH, HARD_CEILINGS as bL, HYPERLINK_RELATIONSHIP_TYPE as bM, IMAGE_RELATIONSHIP_TYPE as bP, IMAGE_RESOURCE_HARD_CEILINGS as bQ,
|
|
4691
|
-
export type {
|
|
4781
|
+
export { validateRasterHeader as a$, DEFAULT_IMAGE_RESOURCE_LIMITS as aV, IMAGE_WRAP_TARGETS as aW, TEXT_FORM_FORMATS as aX, resolveImageResourceLimits as aY, resolveSvgIntrinsicSize as aZ, sniffImageMime as a_, MAX_CONTENT_CONTROLS_PER_PART as b$, DEFAULT_LIMITS as bF, DEFAULT_OOXML_PACKAGE_LIMITS as bG, DEFAULT_ZIP_LIMITS as bH, HARD_CEILINGS as bL, HYPERLINK_RELATIONSHIP_TYPE as bM, IMAGE_RELATIONSHIP_TYPE as bP, IMAGE_RESOURCE_HARD_CEILINGS as bQ, ACCEPTED_PARAGRAPH_PROPERTIES as bj, ACCEPTED_RUN_PROPERTIES as bk, CONTENT_CONTROL_ID_MAX as bm, CONTENT_CONTROL_PROPERTY_ORDER as bn, XMLNS_NAMESPACE_URI as c$, MAX_CONTENT_CONTROL_NESTING as c0, MAX_SVG_SNIFF_BYTES as c1, OFFICE_RELATIONSHIP_NAMESPACE_URI as c4, OOXML_NODE_IDENTITY_RULES as c5, TABLE_BORDER_STYLES as cS, W15_NAMESPACE_URI as cZ, WML_NAMESPACE_URI as c_, resolveImageRelationship as d$, XML_NAMESPACE_URI as d0, allocateContentControlId as d8, asciiFold as d9, hyperlinkTargetOf as dA, imageResourceLookupFor as dB, isContentControlContentNode as dC, isContentControlNode as dD, isContentControlWrapper as dE, isContentRevisionKind as dF, isHyperlinkNode as dG, isRangeMarkerKind as dH, isValidMime as dI, legacyCheckboxFieldsOf as dJ, liveDrawingReferenceCount as dK, lockForbidsEdit as dL, lockForbidsRemoval as dM, normalizePartName as dN, orderedContentControlProperties as dO, parseContentControlId as dP, partNameKey as dQ, planRevisionAuthorChange as dR, planRevisionBatch as dS, projectDrawing as dT, readOnOffChild as dU, readOoxmlPackage as dV, readOoxmlPart as dW, readXml as dX, readZip as dY, resolveContentControlLock as dZ, resolveContentType as d_, buildContentTypeIndex as da, buildRelationshipSet as db, childElements as dc, commentAnchorsOfStory as dd, commentsOfPart as de, contentControlContentChildren as df, contentControlContentNodeOf as dg, contentControlEndPropertiesNodeOf as dh, contentControlLevelOf as di, contentControlPropertiesNodeOf as dj, contentControlPropertiesOf as dk, contentControlTextOf as dl, contentControlsIn as dm, createImageResourceCache as dn, detectDuplicateNames as dp, enclosedBookmarkDeletions as dq, extensionKey as dr, findContentControl as ds, findElement as dt, firstReviewRange as du, flattenContentControls as dv, hasAnyComment as dw, hasBoundedSvgRoot as dx, hyperlinkAnchorOf as dy, hyperlinkRelationshipIdOf as dz, resolveInternalTarget as e0, resolveLimits as e1, resolveRelationship as e2, reviewItemKey as e3, reviewItemRanges as e4, textContent as e5, textFormFieldsOf as e6, threadStateOfPart as e7, validateExternalTarget as e8, validateGifHeader as e9, validateJpegHeader as ea, validatePngHeader as eb, withPart as ec, withoutBookmarkInPart as ed, writeOoxmlPackage as ee, writeZip as ef, activeReviewItem as eh, reviewItemPositionRank as ei, reviewItemsAt as ej, reviewThreadRootOf as ek };
|
|
4782
|
+
export type { Table as $, ParagraphDisagreements as A, Block as B, CommentRecord as C, DocxDocument as D, ExecResult as E, ParagraphFlags as F, ParagraphTabStop as G, HeaderFooterSet as H, InsertableContentControlType as I, RevisionAuthorEntry as J, RevisionAuthorResult as K, RevisionAuthorSkipReason as L, RevisionBatchEntry as M, NumberingRef as N, OoxmlPart as O, PageMargins as P, RevisionBatchResult as Q, ReviewModelInput as R, StyleDefinitions as S, RevisionBatchSkipDetail as T, RevisionBatchSkipReason as U, RevisionSiteRefusal as V, RevisionType as W, Run as X, Section as Y, SectionProperties as Z, StyleDefinition as _, ReviewItem as a, TableCell as a0, TableRow as a1, Theme as a2, ThemeColorScheme as a3, OoxmlNode as a4, OoxmlPackage as a5, DocxDocumentJSON as a6, DrawingHorizontalReferenceFrame as a7, DrawingKind as a8, DrawingLocks as a9, OoxmlPackageResult as aA, OoxmlPackageRejection as aB, OoxmlNodeId as aC, OoxmlPackageLimits as aD, AutomationTableMutation as aE, RevisionAttributionInput as aF, TreeOpRejection as aG, PackageWatermarkWrite as aH, OoxmlInvariantIssue as aI, DrawingTreeDocOp as aJ, ImpactClass as aK, OoxmlParagraphNode as aL, OoxmlNoteNode as aM, OoxmlContinuationSeparatorNode as aN, OoxmlEndnotesNode as aO, OoxmlFootnotesNode as aP, OoxmlNoteRefNode as aQ, OoxmlNoteReferenceNode as aR, OoxmlSeparatorNode as aS, SourceCrop as aT, TreeDocColorValue as aU, DrawingPositionInput as aa, DrawingVerticalReferenceFrame as ab, FontDefinition as ac, ImageDecodePort as ad, ImageResourceLimits as ae, ImageResourceState as af, ImageWrapTarget as ag, ParagraphFormatCommand as ah, Point as ai, PreservedImageMime as aj, Rect as ak, RenderableImageMime as al, SelectionPin as am, SupportedImageMime as an, Unsubscribe as ao, ValidatedImageBytesHandle as ap, VectorImageMime as aq, Watermark as ar, WatermarkLayout as as, WatermarkState as at, TreeDocOp as au, OoxmlElement as av, OoxmlContentControlNode as aw, OoxmlGenericElementNode as ax, OoxmlContentControlContentNode as ay, OoxmlProperty as az, ReviewRevisionItem as b, TextFormFieldRange as b0, TextFormFieldOptions as b1, DrawingTransform as b2, TableBorderStyle as b3, DrawingAccessibility as b4, DrawingImageEffects as b5, VectorShapeProjection as b6, DrawingProjection as b7, OoxmlDrawingNode as b8, OoxmlInvariantResult as b9, ContentControlProperties as bA, ContentTypeError as bB, ContentTypeIndex as bC, ContentTypeRecords as bD, CreateImageResourceCacheOptions as bE, DefaultRecord as bI, DeleteBookmarkOp as bJ, DeleteTextOp as bK, HyperlinkKind as bN, HyperlinkTarget as bO, ImageRelationshipResolution as bR, ImageResourceLookup as bS, IndexResult as bT, InsertBookmarkOp as bU, InsertBuildingBlockOp as bV, InsertComplexFieldOp as bW, InsertEquationOp as bX, InsertPageFieldOp as bY, InsertTextOp as bZ, LegacyCheckboxFieldRange as b_, OoxmlFldCharNode as ba, OoxmlFldSimpleNode as bb, OoxmlInstrTextNode as bc, TreeOpResult as bd, RelationshipRecord as be, OoxmlHardBreakNode as bf, OoxmlAttribute as bg, ResourceLimits as bh, CommentThreadState as bi, BookmarkOpPosition as bl, CommentAnchor as bo, CommentPosition as bp, CommitTextFormFieldOp as bq, ContentControlCheckbox as br, ContentControlCheckboxState as bs, ContentControlDataBinding as bt, ContentControlDateFormat as bu, ContentControlEntry as bv, ContentControlKind as bw, ContentControlLevel as bx, ContentControlListItem as by, ContentControlLock as bz, ReviewCommentItem as c, NameRejection as c2, NameResult as c3, OoxmlBodyNode as c6, OoxmlBookmarkEndNode as c7, OoxmlBookmarkStartNode as c8, OoxmlContentControlCalendarNode as c9, OoxmlReadResult as cA, OoxmlRunNode as cB, OoxmlRunPropertiesNode as cC, OoxmlTabNode as cD, OoxmlTextElementNode as cE, OoxmlTextNode as cF, OoxmlWmlValAttribute as cG, OoxmlXmlSpaceAttribute as cH, OverrideRecord as cI, RelationshipError as cJ, RelationshipSetResult as cK, RelationshipTargetResolver as cL, ResolveResult as cM, ResolvedRelationship as cN, SetFieldResultOp as cO, SetLegacyCheckboxOp as cP, SetLegacyDropdownOp as cQ, SetTextFormFieldDefaultOp as cR, TabStopWrite as cT, TargetMode as cU, TextFormFieldType as cV, TreeDocOpKind as cW, TreeOpEffect as cX, ValidatedRasterHeader as cY, OoxmlContentControlCheckboxNode as ca, OoxmlContentControlCheckedNode as cb, OoxmlContentControlCheckedStateNode as cc, OoxmlContentControlComboBoxNode as cd, OoxmlContentControlDataBindingNode as ce, OoxmlContentControlDateFormatNode as cf, OoxmlContentControlDateNode as cg, OoxmlContentControlDropDownListNode as ch, OoxmlContentControlEndPropertiesNode as ci, OoxmlContentControlLidNode as cj, OoxmlContentControlListItemNode as ck, OoxmlContentControlPropertiesNode as cl, OoxmlContentControlStoreMappedDataAsNode as cm, OoxmlContentControlTextNode as cn, OoxmlContentControlUncheckedStateNode as co, OoxmlDocumentNode as cp, OoxmlExternalTarget as cq, OoxmlGenericExtensionAttribute as cr, OoxmlHyperlinkNode as cs, OoxmlInvariantIssueCode as ct, OoxmlKnownNodeAttribute as cu, OoxmlNamespaceBinding as cv, OoxmlNodeIdentityRules as cw, OoxmlParagraphPropertiesNode as cx, OoxmlPartMetadata as cy, OoxmlReadRejection as cz, ReviewCustomItem as d, XmlLimits as d1, XmlNode as d2, XmlRejection as d3, XmlResult as d4, ZipLimits as d5, ZipReadResult as d6, ZipRejection as d7, ReviewPosition as e, VectorShapeComponent as eg, ReviewRange as f, ReviewRevisionKind as g, RevisionAddress as h, ContentControlType as i, DocTarget as j, RunFormatting as k, Extent as l, ContainerRef as m, ContentControlFilter as n, DocRange as o, Revision as p, DocComment as q, ColorValue as r, ContentControl as s, DocAnchor as t, DocAnchorRange as u, DocLocation as v, DocumentBody as w, ExecErrorCode as x, IndentFormatting as y, Paragraph as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a5 as OoxmlPackage, an as SupportedImageMime, O as OoxmlPart, a4 as OoxmlNode, av as OoxmlElement, aH as PackageWatermarkWrite, aI as OoxmlInvariantIssue, ad as ImageDecodePort, aF as RevisionAttributionInput, aJ as DrawingTreeDocOp, aK as ImpactClass, au as TreeDocOp, aG as TreeOpRejection, aL as OoxmlParagraphNode, aM as OoxmlNoteNode, aN as OoxmlContinuationSeparatorNode, aO as OoxmlEndnotesNode, aP as OoxmlFootnotesNode, aQ as OoxmlNoteRefNode, aR as OoxmlNoteReferenceNode, aS as OoxmlSeparatorNode } from './tree-op-types-C_S2niXW.js';
|
|
2
2
|
|
|
3
3
|
/** A freshly allocated drawing property id, or the reason one could not be minted. */
|
|
4
4
|
type DrawingPropertyIdResult = {
|
|
@@ -1382,4 +1382,4 @@ declare class TreePackageStore {
|
|
|
1382
1382
|
}
|
|
1383
1383
|
|
|
1384
1384
|
export { NOTE_CONTINUATION_SEPARATOR_ID as B, DEFAULT_MAX_EDITABLE_STORY_PARTS as D, NOTE_ID_MAX as G, NOTE_ID_MIN as J, NOTE_SEPARATOR_ID as K, MAX_FRAGMENT_DECODED_BYTES as M, TreePackageStore as T, allocateDrawingPropertyId as a8, allocateNoteId as a9, isNoteNode as aA, isNoteRefNode as aB, isNoteReferenceNode as aC, isSeparatorNode as aD, normalNoteIds as aE, noteAtomText as aF, noteIdOf as aG, noteKindOf as aH, noteRefKindOf as aI, noteReferenceKindOf as aJ, noteTypeOf as aK, notesOf as aL, notesPartHasId as aM, observeHistoryGroup as aN, parentNodeOf as aO, parseNoteId as aP, parseNoteScopeId as aQ, removeNode as aR, replaceChildren as aS, replaceNode as aT, resolveHeaderFooterParts as aU, resolveHeaderFooterPartsBySection as aV, resolveHeaderFooterResolutionBySection as aW, resolveNotesPart as aX, withBinaryPart as aY, withEmbeddedImage as aZ, withoutUnreferencedImagePart as a_, applyEdits as aa, applyFragmentPaste as ab, applyHeaderFooterLifecycleOp as ac, applyNoteLifecycleOp as ad, atomicNoteSpansOf as ae, cascadeDeletedNoteReferences as af, collectNodeIds as ag, collectNoteReferences as ah, collectPackageNoteReferences as ai, collectSectionPropertyNodes as aj, createNodeIdAllocator as ak, createNoteReferenceScanBudget as al, customMarkFollows as am, diagnoseNoteReferences as an, findNode as ao, findNoteById as ap, formatNoteScopeId as aq, hasNode as ar, insertChildren as as, isContinuationSeparatorNode as at, isEndnotesNode as au, isFootnotesNode as av, isHeaderFooterLifecycleOp as aw, isNormalNote as ax, isNoteAtomNode as ay, isNoteLifecycleOp as az, TreeDocumentStore as f, reportHistoryGroup as r, MAX_NOTES_PER_PART as w, MAX_NOTE_REFERENCE_PARTS as x, MAX_NOTE_REFERENCE_SCAN as y, NOTE_ATOM_CHAR as z };
|
|
1385
|
-
export type { PackageTransactResult as $, ApplyImagePropertiesInput as A, ContentLockPolicy as C, EditOptions as E, FieldResultsMode as F, HeaderFooterParts as H, InsertImageInput as I, NoteDiagnostic as L, NoteKind as N, NoteDiagnosticCode as O, NoteLifecycleImpact as P, NoteLifecycleOp as Q, ReplaceImageOptions as R, StoryScope as S, NoteLifecycleOptions as U, NoteLifecycleRejection as V, NoteLifecycleResult as W, NoteReferenceHit as X, NoteReferenceScanBudget as Y, NoteType as Z, OoxmlEditResult as _,
|
|
1385
|
+
export type { PackageTransactResult as $, ApplyImagePropertiesInput as A, ContentLockPolicy as C, EditOptions as E, FieldResultsMode as F, HeaderFooterParts as H, InsertImageInput as I, NoteDiagnostic as L, NoteKind as N, NoteDiagnosticCode as O, NoteLifecycleImpact as P, NoteLifecycleOp as Q, ReplaceImageOptions as R, StoryScope as S, NoteLifecycleOptions as U, NoteLifecycleRejection as V, NoteLifecycleResult as W, NoteReferenceHit as X, NoteReferenceScanBudget as Y, NoteType as Z, OoxmlEditResult as _, StoryTargetRejection as a, RemotePackageAttribution as a0, StoryResolveResult as a1, TransactionRevisionIds as a2, TreeDocumentStoreOptions as a3, TreePackageStoreOptions as a4, TreeStoryRef as a5, TransactResult as a6, TransactionContext as a7, HeaderFooterSectionResolution as b, HeaderFooterVariant as c, HistoryGroup as d, TreeModelChange as e, SelectionMark as g, TransactOptions as h, ImageIntentResult as i, FragmentPasteInput as j, FragmentPasteResult as k, AtomicNoteSpan as l, CascadeDeletedNoteReferencesOptions as m, DrawingPropertyIdResult as n, HeaderFooterKind as o, HeaderFooterLifecycleImpact as p, HeaderFooterLifecycleOp as q, HeaderFooterLifecycleRejection as s, HeaderFooterLifecycleResult as t, HeaderFooterSlotMeta as u, HistoryCaptureKind as v };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { S as StoryScope, g as SelectionMark, h as TransactOptions, d as HistoryGroup,
|
|
2
|
-
import {
|
|
3
|
-
import { D as DocumentTrackingSettings, I as InsertCustomNodeWrite, C as CustomNodeWriteResult, a as CustomNodeSweepOutcome, E as EmbeddedFont, B as BookmarkIndex, L as ListKind } from './custom-node-writes-
|
|
4
|
-
import { H as HeadlessDocumentView, D as DocumentProperties } from './headless-document-view-
|
|
1
|
+
import { S as StoryScope, g as SelectionMark, h as TransactOptions, d as HistoryGroup, a as StoryTargetRejection, e as TreeModelChange, H as HeaderFooterParts, b as HeaderFooterSectionResolution, I as InsertImageInput, i as ImageIntentResult, R as ReplaceImageOptions, A as ApplyImagePropertiesInput, j as FragmentPasteInput, k as FragmentPasteResult } from './tree-package-store-CRHvMyNj.js';
|
|
2
|
+
import { au as TreeDocOp, O as OoxmlPart, a4 as OoxmlNode, a5 as OoxmlPackage, av as OoxmlElement, a as ReviewItem, an as SupportedImageMime, ad as ImageDecodePort, aF as RevisionAttributionInput } from './tree-op-types-C_S2niXW.js';
|
|
3
|
+
import { D as DocumentTrackingSettings, I as InsertCustomNodeWrite, C as CustomNodeWriteResult, a as CustomNodeSweepOutcome, E as EmbeddedFont, B as BookmarkIndex, L as ListKind } from './custom-node-writes-CLJKGD9t.js';
|
|
4
|
+
import { H as HeadlessDocumentView, D as DocumentProperties } from './headless-document-view-Bcz9_Qva.js';
|
|
5
5
|
import { Node } from 'prosemirror-model';
|
|
6
6
|
import { CollaborationDocumentPort } from './collaboration/replication.js';
|
|
7
|
-
import { V as ViewScope } from './editor-scope-
|
|
7
|
+
import { V as ViewScope } from './editor-scope-B3L-1ALc.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Why an edited projection could not be mapped back into tree ops.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { U as UnsupportedElement } from './semantic-records-BvN-WWst.js';
|
|
2
|
+
|
|
3
|
+
/** A component mount point and its built-in fallback. @public */
|
|
4
|
+
interface UnsupportedElementHost {
|
|
5
|
+
/** Stable identity for one painted occurrence. */
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly element: HTMLElement;
|
|
8
|
+
readonly fallback: HTMLElement;
|
|
9
|
+
readonly slot: HTMLElement;
|
|
10
|
+
readonly unsupported: UnsupportedElement;
|
|
11
|
+
/** Hide the default and expose custom controls to assistive technology. Restore with false. */
|
|
12
|
+
setCustomized(custom: boolean): void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Observe placeholder mounts across repaint, pagination, and document replacement.
|
|
16
|
+
* The returned function disconnects the observer. Component mutations do not publish
|
|
17
|
+
* another list unless the engine's mount points change.
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
declare function observeUnsupportedElements(container: HTMLElement, listener: (hosts: readonly UnsupportedElementHost[]) => void): () => void;
|
|
21
|
+
|
|
22
|
+
export { observeUnsupportedElements as o };
|
|
23
|
+
export type { UnsupportedElementHost as U };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<!-- Generated from docs/site/content/recipes by scripts/sync-agent-docs.mjs. Edit the source and run `bun run docs:agent`. -->
|
|
2
|
+
|
|
3
|
+
# Accept or reject without scrolling
|
|
4
|
+
|
|
5
|
+
When your own list drives the scroll, open an item with `useReview().setActive(key, { reveal: false })`. The caret moves to the item, and the page stays where it is. Then resolve the item with `accept(item)` or `reject(item)`. Review writes such as accept, reject, and comment never scroll the page.
|
|
6
|
+
|
|
7
|
+
**React**
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { useReview, type ReviewItemView } from '@docx-editor.dev/pro/react';
|
|
11
|
+
|
|
12
|
+
export function ChangeRow({ item }: { item: ReviewItemView }) {
|
|
13
|
+
const { setActive, accept, reject } = useReview();
|
|
14
|
+
return (
|
|
15
|
+
<li onClick={() => setActive(item.key, { reveal: false })}>
|
|
16
|
+
{item.text}
|
|
17
|
+
<button
|
|
18
|
+
disabled={item.readOnly}
|
|
19
|
+
onClick={(event) => {
|
|
20
|
+
event.stopPropagation();
|
|
21
|
+
accept(item);
|
|
22
|
+
}}
|
|
23
|
+
>
|
|
24
|
+
Accept
|
|
25
|
+
</button>
|
|
26
|
+
<button
|
|
27
|
+
disabled={item.readOnly}
|
|
28
|
+
onClick={(event) => {
|
|
29
|
+
event.stopPropagation();
|
|
30
|
+
reject(item);
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
33
|
+
Reject
|
|
34
|
+
</button>
|
|
35
|
+
</li>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`accept` and `reject` return `false` when the editor refuses the decision, for example in viewing mode. Read `useReview().lastRefusal` for the diagnostic code.
|
|
41
|
+
|
|
42
|
+
**Vue**
|
|
43
|
+
|
|
44
|
+
```vue
|
|
45
|
+
<script setup lang="ts">
|
|
46
|
+
import { useReview, type ReviewItemView } from '@docx-editor.dev/pro/vue';
|
|
47
|
+
|
|
48
|
+
defineProps<{ item: ReviewItemView }>();
|
|
49
|
+
const { setActive, accept, reject } = useReview();
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<template>
|
|
53
|
+
<li @click="setActive(item.key, { reveal: false })">
|
|
54
|
+
{{ item.text }}
|
|
55
|
+
<button :disabled="item.readOnly" @click.stop="accept(item)">Accept</button>
|
|
56
|
+
<button :disabled="item.readOnly" @click.stop="reject(item)">Reject</button>
|
|
57
|
+
</li>
|
|
58
|
+
</template>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`accept` and `reject` return `false` when the editor refuses the decision, for example in viewing mode. `useReview()` returns `lastRefusal` as a ref, so read `lastRefusal.value?.code` in script, or `lastRefusal?.code` in the template.
|
|
62
|
+
|
|
63
|
+
The buttons stop the click from reaching the row, so a decision does not also activate the item.
|
|
64
|
+
|
|
65
|
+
`reveal` takes `false` or one of four placements:
|
|
66
|
+
|
|
67
|
+
| Value | Where the item lands |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| `'centerIfNeeded'` (default) | Stays still when the item is on screen; centered when it has to travel. |
|
|
70
|
+
| `'center'` | Always centered. |
|
|
71
|
+
| `'nearest'` | The smallest scroll that brings it into view. |
|
|
72
|
+
| `'start'` | Near the top of the viewport. |
|
|
73
|
+
|
|
74
|
+
Add `announce: true` to open the packaged balloon or card for the item.
|
|
75
|
+
|
|
76
|
+
## Decide in a headless pipeline
|
|
77
|
+
|
|
78
|
+
The editing API has no viewport. Load the revisions and call `Revision.accept()` or `Revision.reject()`.
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { DocxEditor } from '@docx-editor.dev/editor-api';
|
|
82
|
+
|
|
83
|
+
const runtime = await DocxEditor.createServer(bytes, { author: 'Review bot' });
|
|
84
|
+
await runtime.run(async (context) => {
|
|
85
|
+
const revisions = context.document.body.revisions;
|
|
86
|
+
revisions.load('items/author');
|
|
87
|
+
await context.sync();
|
|
88
|
+
for (const revision of revisions.items) {
|
|
89
|
+
if (revision.author === 'Review bot') revision.accept();
|
|
90
|
+
}
|
|
91
|
+
await context.sync();
|
|
92
|
+
});
|
|
93
|
+
const saved = await runtime.save();
|
|
94
|
+
runtime.dispose();
|
|
95
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<!-- Generated from docs/site/content/recipes by scripts/sync-agent-docs.mjs. Edit the source and run `bun run docs:agent`. -->
|
|
2
|
+
|
|
3
|
+
# Comment on found text
|
|
4
|
+
|
|
5
|
+
In a browser host, find the text with `editor.findMatches`, select the first match with `editor.selectMatch`, and then call `useReview().comment`. The comment is written as the editor's `author`, so set `author` on the editor and add `reviewModule()` to its modules. `selectMatch` opens the header, footer, or note that holds the match, so a match in any story works.
|
|
6
|
+
|
|
7
|
+
**React**
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { useDocxEditor } from '@docx-editor.dev/react';
|
|
11
|
+
import { useReview } from '@docx-editor.dev/pro/react';
|
|
12
|
+
|
|
13
|
+
export function CommentOnTerm({ term }: { term: string }) {
|
|
14
|
+
const editor = useDocxEditor();
|
|
15
|
+
const { comment } = useReview();
|
|
16
|
+
const run = () => {
|
|
17
|
+
const [match] = editor?.findMatches(term, { wholeWord: true }) ?? [];
|
|
18
|
+
if (match && editor?.selectMatch(match).ok) comment(`Define "${term}".`);
|
|
19
|
+
};
|
|
20
|
+
return <button onClick={run}>Comment on {term}</button>;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`comment` returns `false` when the editor refuses the write. Read `useReview().lastRefusal` for the diagnostic code.
|
|
25
|
+
|
|
26
|
+
**Vue**
|
|
27
|
+
|
|
28
|
+
```vue
|
|
29
|
+
<script setup lang="ts">
|
|
30
|
+
import { useDocxEditor } from '@docx-editor.dev/vue';
|
|
31
|
+
import { useReview } from '@docx-editor.dev/pro/vue';
|
|
32
|
+
|
|
33
|
+
const props = defineProps<{ term: string }>();
|
|
34
|
+
const editor = useDocxEditor();
|
|
35
|
+
const { comment } = useReview();
|
|
36
|
+
function run() {
|
|
37
|
+
const [match] = editor.value?.findMatches(props.term, { wholeWord: true }) ?? [];
|
|
38
|
+
if (match && editor.value?.selectMatch(match).ok) comment(`Define "${props.term}".`);
|
|
39
|
+
}
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<button @click="run">Comment on {{ term }}</button>
|
|
44
|
+
</template>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`comment` returns `false` when the editor refuses the write. `useReview()` returns `lastRefusal` as a ref, so read `lastRefusal.value?.code` in script, or `lastRefusal?.code` in the template.
|
|
48
|
+
|
|
49
|
+
## Comment in a headless pipeline
|
|
50
|
+
|
|
51
|
+
On a server or in an agent pipeline, search the body and call `Range.insertComment`. The runtime writes the comment as its `author` option.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { DocxEditor } from '@docx-editor.dev/editor-api';
|
|
55
|
+
|
|
56
|
+
const runtime = await DocxEditor.createServer(bytes, { author: 'Review bot' });
|
|
57
|
+
await runtime.run(async (context) => {
|
|
58
|
+
const found = context.document.body.search(term, { matchWholeWord: true });
|
|
59
|
+
found.load('items');
|
|
60
|
+
await context.sync();
|
|
61
|
+
found.items[0]?.insertComment(`Define "${term}".`);
|
|
62
|
+
await context.sync();
|
|
63
|
+
});
|
|
64
|
+
const saved = await runtime.save();
|
|
65
|
+
runtime.dispose();
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Both paths save the same comment markup: the same `w:comment` attributes, the same date format, and the same range markers.
|
|
69
|
+
|
|
70
|
+
## Reply to a thread
|
|
71
|
+
|
|
72
|
+
To answer an existing comment, call `useReview().reply(item, text)` in a browser host, or `Comment.reply(text)` in the editing API.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<!-- Generated from docs/site/content/recipes by scripts/sync-agent-docs.mjs. Edit the source and run `bun run docs:agent`. -->
|
|
2
|
+
|
|
3
|
+
# Custom cards in the review rail
|
|
4
|
+
|
|
5
|
+
To draw your own cards, render `DocxEditorReview` with `preset` set to `false` and put your card component inside it. Your component reads the items from `useReview()`, measures each card, stacks the cards with `useStackedReviewPositions`, and converts positions to pixels with `useReviewRailMetrics()`.
|
|
6
|
+
|
|
7
|
+
Measure every card with a `ResizeObserver` and pass the heights in CSS pixels. Without measured heights, each card reserves only `defaultHeight`, and a taller card overlaps the next one.
|
|
8
|
+
|
|
9
|
+
**React**
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import { useCallback, useEffect, useRef, useState, type ReactNode } from 'react';
|
|
13
|
+
import {
|
|
14
|
+
DocxEditorReview,
|
|
15
|
+
useReview,
|
|
16
|
+
useReviewRailMetrics,
|
|
17
|
+
useStackedReviewPositions,
|
|
18
|
+
} from '@docx-editor.dev/pro/react';
|
|
19
|
+
|
|
20
|
+
type OnHeight = (key: string, height: number) => void;
|
|
21
|
+
|
|
22
|
+
function MeasuredCard({
|
|
23
|
+
id,
|
|
24
|
+
top,
|
|
25
|
+
onHeight,
|
|
26
|
+
children,
|
|
27
|
+
}: {
|
|
28
|
+
id: string;
|
|
29
|
+
top: number;
|
|
30
|
+
onHeight: OnHeight;
|
|
31
|
+
children: ReactNode;
|
|
32
|
+
}) {
|
|
33
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const node = ref.current!;
|
|
36
|
+
const observer = new ResizeObserver(() => onHeight(id, node.offsetHeight));
|
|
37
|
+
observer.observe(node);
|
|
38
|
+
return () => observer.disconnect();
|
|
39
|
+
}, [id, onHeight]);
|
|
40
|
+
return (
|
|
41
|
+
<div ref={ref} style={{ position: 'absolute', top }}>
|
|
42
|
+
{children}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function MyCards() {
|
|
48
|
+
const { items, selectionAnchorY, accept } = useReview();
|
|
49
|
+
const metrics = useReviewRailMetrics();
|
|
50
|
+
const [heights, setHeights] = useState<ReadonlyMap<string, number>>(() => new Map());
|
|
51
|
+
const onHeight = useCallback<OnHeight>(
|
|
52
|
+
(key, height) =>
|
|
53
|
+
setHeights((prev) => (prev.get(key) === height ? prev : new Map(prev).set(key, height))),
|
|
54
|
+
[]
|
|
55
|
+
);
|
|
56
|
+
const positions = useStackedReviewPositions(items, heights, {
|
|
57
|
+
scale: metrics.scale,
|
|
58
|
+
defaultHeight: 96,
|
|
59
|
+
});
|
|
60
|
+
const top = (y: number) => metrics.top + y * metrics.scale;
|
|
61
|
+
return (
|
|
62
|
+
<>
|
|
63
|
+
{items.map((item) => (
|
|
64
|
+
<MeasuredCard
|
|
65
|
+
key={item.key}
|
|
66
|
+
id={item.key}
|
|
67
|
+
top={top(positions.get(item.key) ?? 0)}
|
|
68
|
+
onHeight={onHeight}
|
|
69
|
+
>
|
|
70
|
+
{item.text}
|
|
71
|
+
{item.kind === 'revision' && <button onClick={() => accept(item)}>Accept</button>}
|
|
72
|
+
</MeasuredCard>
|
|
73
|
+
))}
|
|
74
|
+
<DocxEditorReview.Draft top={top(selectionAnchorY ?? 0)} />
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function MyRail() {
|
|
80
|
+
return (
|
|
81
|
+
<DocxEditorReview preset={false}>
|
|
82
|
+
<MyCards />
|
|
83
|
+
<DocxEditorReview.AddComment />
|
|
84
|
+
</DocxEditorReview>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The heights map gets a new reference only when a height changes, so the stack recomputes only then. Keep that rule if you store heights another way.
|
|
90
|
+
|
|
91
|
+
**Vue**
|
|
92
|
+
|
|
93
|
+
```vue
|
|
94
|
+
<!-- MyCards.vue -->
|
|
95
|
+
<script setup lang="ts">
|
|
96
|
+
import { onBeforeUnmount, shallowReactive } from 'vue';
|
|
97
|
+
import {
|
|
98
|
+
DocxEditorReview,
|
|
99
|
+
useReview,
|
|
100
|
+
useReviewRailMetrics,
|
|
101
|
+
useStackedReviewPositions,
|
|
102
|
+
} from '@docx-editor.dev/pro/vue';
|
|
103
|
+
|
|
104
|
+
const { items, selectionAnchorY, accept } = useReview();
|
|
105
|
+
const { metrics } = useReviewRailMetrics();
|
|
106
|
+
// Reactive, so a new measurement restacks the cards.
|
|
107
|
+
const heights = shallowReactive(new Map<string, number>());
|
|
108
|
+
const positions = useStackedReviewPositions(items, heights, () => ({
|
|
109
|
+
scale: metrics.value.scale,
|
|
110
|
+
defaultHeight: 96,
|
|
111
|
+
}));
|
|
112
|
+
const top = (y: number) => `${metrics.value.top + y * metrics.value.scale}px`;
|
|
113
|
+
|
|
114
|
+
const observed = new Map<string, { el: Element; observer: ResizeObserver }>();
|
|
115
|
+
function measure(key: string, el: unknown) {
|
|
116
|
+
const current = observed.get(key);
|
|
117
|
+
if (current?.el === el) return;
|
|
118
|
+
current?.observer.disconnect();
|
|
119
|
+
observed.delete(key);
|
|
120
|
+
if (!(el instanceof HTMLElement)) {
|
|
121
|
+
heights.delete(key);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const observer = new ResizeObserver(() => heights.set(key, el.offsetHeight));
|
|
125
|
+
observer.observe(el);
|
|
126
|
+
observed.set(key, { el, observer });
|
|
127
|
+
}
|
|
128
|
+
onBeforeUnmount(() => observed.forEach(({ observer }) => observer.disconnect()));
|
|
129
|
+
</script>
|
|
130
|
+
|
|
131
|
+
<template>
|
|
132
|
+
<div
|
|
133
|
+
v-for="item in items"
|
|
134
|
+
:key="item.key"
|
|
135
|
+
:ref="(el) => measure(item.key, el)"
|
|
136
|
+
:style="{ position: 'absolute', top: top(positions.get(item.key) ?? 0) }"
|
|
137
|
+
>
|
|
138
|
+
{{ item.text }}
|
|
139
|
+
<button v-if="item.kind === 'revision'" @click="accept(item)">Accept</button>
|
|
140
|
+
</div>
|
|
141
|
+
<DocxEditorReview.Draft :top="metrics.top + (selectionAnchorY ?? 0) * metrics.scale" />
|
|
142
|
+
</template>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
```vue
|
|
146
|
+
<!-- MyRail.vue -->
|
|
147
|
+
<script setup lang="ts">
|
|
148
|
+
import { DocxEditorReview } from '@docx-editor.dev/pro/vue';
|
|
149
|
+
import MyCards from './MyCards.vue';
|
|
150
|
+
</script>
|
|
151
|
+
|
|
152
|
+
<template>
|
|
153
|
+
<DocxEditorReview :preset="false">
|
|
154
|
+
<MyCards />
|
|
155
|
+
<DocxEditorReview.AddComment />
|
|
156
|
+
</DocxEditorReview>
|
|
157
|
+
</template>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
A plain `Map` is not reactive, so writes to it would not restack the cards. Use `shallowReactive(new Map())`, or a ref that you replace on each change.
|
|
161
|
+
|
|
162
|
+
## Root parts and card parts
|
|
163
|
+
|
|
164
|
+
`DocxEditorReview` finds its parts among its own children by element type.
|
|
165
|
+
|
|
166
|
+
- **Root parts** are `List`, `Markers`, `AddComment`, `Draft`, and `Balloon`. Put them as direct children of `DocxEditorReview`. Fragments are transparent in React and in Vue. The rail gives these parts geometry that only it can compute, such as the comment button's `top`. A root part inside your own wrapper component is not a part. It renders as ordinary content, without that wiring.
|
|
167
|
+
- **Card parts** are `Card`, `Empty`, and the parts inside a card, such as `Author`, `Summary`, `Accept`, and `Reply`. Put them inside `DocxEditorReview.List`.
|
|
168
|
+
|
|
169
|
+
With `preset` set to `false`, the rail adds no defaults. Root parts that you pass keep their wiring. Every other child renders as is inside the rail element, where `useReviewRailMetrics()` reads the rail's own measurement.
|
|
170
|
+
|
|
171
|
+
## Position the compose box
|
|
172
|
+
|
|
173
|
+
`DocxEditorReview.Draft` renders only while a comment draft is open. A draft opens from `DocxEditorReview.AddComment` or from the `review.addComment` toolbar control. You can place `Draft` in either of these places:
|
|
174
|
+
|
|
175
|
+
- As a direct child of `DocxEditorReview`.
|
|
176
|
+
- Inside your own card component, as in the example. It still renders only while the draft is open.
|
|
177
|
+
|
|
178
|
+
Without `top`, the box sits where the packaged card stack puts it. That position comes from the packaged cards, not yours, so when you render your own cards, pass `top` from your own stack. In the narrow compact rail, the box takes the compact card's `left` in both cases, so it does not overflow the marker strip. The example places the box at the selection's anchor. To keep it clear of your cards, add an entry with the key of your choice and the anchor `selectionAnchorY` to the list that you pass to `useStackedReviewPositions`, in document order.
|