@wordpress/core-data 7.40.2-next.v.202602241322.0 → 7.40.2
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 +0 -27
- package/build/actions.cjs +9 -26
- package/build/actions.cjs.map +2 -2
- package/build/awareness/post-editor-awareness.cjs +45 -6
- package/build/awareness/post-editor-awareness.cjs.map +2 -2
- package/build/awareness/types.cjs.map +1 -1
- package/build/entities.cjs +50 -23
- package/build/entities.cjs.map +2 -2
- package/build/entity-provider.cjs +15 -6
- package/build/entity-provider.cjs.map +2 -2
- package/build/hooks/use-entity-prop.cjs +33 -2
- package/build/hooks/use-entity-prop.cjs.map +2 -2
- package/build/hooks/use-post-editor-awareness-state.cjs +120 -1
- package/build/hooks/use-post-editor-awareness-state.cjs.map +2 -2
- package/build/index.cjs +0 -3
- package/build/index.cjs.map +2 -2
- package/build/private-actions.cjs +27 -3
- package/build/private-actions.cjs.map +2 -2
- package/build/private-apis.cjs +14 -5
- package/build/private-apis.cjs.map +3 -3
- package/build/private-selectors.cjs +22 -2
- package/build/private-selectors.cjs.map +2 -2
- package/build/queried-data/actions.cjs +1 -1
- package/build/queried-data/actions.cjs.map +2 -2
- package/build/queried-data/reducer.cjs +19 -13
- package/build/queried-data/reducer.cjs.map +2 -2
- package/build/reducer.cjs +19 -2
- package/build/reducer.cjs.map +2 -2
- package/build/resolvers.cjs +16 -6
- package/build/resolvers.cjs.map +2 -2
- package/build/selectors.cjs +0 -15
- package/build/selectors.cjs.map +2 -2
- package/build/sync.cjs +11 -5
- package/build/sync.cjs.map +2 -2
- package/build/types.cjs.map +1 -1
- package/build/utils/block-selection-history.cjs +1 -1
- package/build/utils/block-selection-history.cjs.map +2 -2
- package/build/utils/crdt-blocks.cjs +125 -49
- package/build/utils/crdt-blocks.cjs.map +2 -2
- package/build/utils/crdt-selection.cjs +50 -19
- package/build/utils/crdt-selection.cjs.map +2 -2
- package/build/utils/crdt-text.cjs +52 -0
- package/build/utils/crdt-text.cjs.map +7 -0
- package/build/utils/crdt-user-selections.cjs +16 -6
- package/build/utils/crdt-user-selections.cjs.map +3 -3
- package/build/utils/crdt-utils.cjs +54 -2
- package/build/utils/crdt-utils.cjs.map +2 -2
- package/build/utils/crdt.cjs +38 -29
- package/build/utils/crdt.cjs.map +2 -2
- package/build-module/actions.mjs +14 -26
- package/build-module/actions.mjs.map +2 -2
- package/build-module/awareness/post-editor-awareness.mjs +47 -7
- package/build-module/awareness/post-editor-awareness.mjs.map +2 -2
- package/build-module/entities.mjs +53 -24
- package/build-module/entities.mjs.map +2 -2
- package/build-module/entity-provider.mjs +15 -6
- package/build-module/entity-provider.mjs.map +2 -2
- package/build-module/hooks/use-entity-prop.mjs +34 -3
- package/build-module/hooks/use-entity-prop.mjs.map +2 -2
- package/build-module/hooks/use-post-editor-awareness-state.mjs +117 -1
- package/build-module/hooks/use-post-editor-awareness-state.mjs.map +2 -2
- package/build-module/index.mjs +0 -2
- package/build-module/index.mjs.map +2 -2
- package/build-module/private-actions.mjs +24 -2
- package/build-module/private-actions.mjs.map +2 -2
- package/build-module/private-apis.mjs +21 -6
- package/build-module/private-apis.mjs.map +3 -3
- package/build-module/private-selectors.mjs +19 -1
- package/build-module/private-selectors.mjs.map +2 -2
- package/build-module/queried-data/actions.mjs +1 -1
- package/build-module/queried-data/actions.mjs.map +2 -2
- package/build-module/queried-data/reducer.mjs +19 -13
- package/build-module/queried-data/reducer.mjs.map +2 -2
- package/build-module/reducer.mjs +18 -2
- package/build-module/reducer.mjs.map +2 -2
- package/build-module/resolvers.mjs +16 -6
- package/build-module/resolvers.mjs.map +2 -2
- package/build-module/selectors.mjs +0 -14
- package/build-module/selectors.mjs.map +2 -2
- package/build-module/sync.mjs +7 -3
- package/build-module/sync.mjs.map +2 -2
- package/build-module/utils/block-selection-history.mjs +5 -2
- package/build-module/utils/block-selection-history.mjs.map +2 -2
- package/build-module/utils/crdt-blocks.mjs +124 -49
- package/build-module/utils/crdt-blocks.mjs.map +2 -2
- package/build-module/utils/crdt-selection.mjs +53 -20
- package/build-module/utils/crdt-selection.mjs.map +2 -2
- package/build-module/utils/crdt-text.mjs +26 -0
- package/build-module/utils/crdt-text.mjs.map +7 -0
- package/build-module/utils/crdt-user-selections.mjs +16 -7
- package/build-module/utils/crdt-user-selections.mjs.map +3 -3
- package/build-module/utils/crdt-utils.mjs +51 -1
- package/build-module/utils/crdt-utils.mjs.map +2 -2
- package/build-module/utils/crdt.mjs +42 -34
- package/build-module/utils/crdt.mjs.map +2 -2
- package/build-types/actions.d.ts +0 -11
- package/build-types/actions.d.ts.map +1 -1
- package/build-types/awareness/post-editor-awareness.d.ts +2 -2
- package/build-types/awareness/post-editor-awareness.d.ts.map +1 -1
- package/build-types/awareness/types.d.ts +6 -1
- package/build-types/awareness/types.d.ts.map +1 -1
- package/build-types/entities.d.ts +20 -1
- package/build-types/entities.d.ts.map +1 -1
- package/build-types/entity-provider.d.ts +11 -6
- package/build-types/entity-provider.d.ts.map +1 -1
- package/build-types/hooks/use-entity-prop.d.ts.map +1 -1
- package/build-types/hooks/use-post-editor-awareness-state.d.ts +40 -7
- package/build-types/hooks/use-post-editor-awareness-state.d.ts.map +1 -1
- package/build-types/index.d.ts +0 -3
- package/build-types/index.d.ts.map +1 -1
- package/build-types/parsed-blocks-cache.d.ts +10 -0
- package/build-types/parsed-blocks-cache.d.ts.map +1 -0
- package/build-types/private-actions.d.ts +12 -0
- package/build-types/private-actions.d.ts.map +1 -1
- package/build-types/private-apis.d.ts +21 -1
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/private-selectors.d.ts +17 -0
- package/build-types/private-selectors.d.ts.map +1 -1
- package/build-types/queried-data/reducer.d.ts.map +1 -1
- package/build-types/reducer.d.ts +15 -0
- package/build-types/reducer.d.ts.map +1 -1
- package/build-types/resolvers.d.ts.map +1 -1
- package/build-types/selectors.d.ts +1 -9
- package/build-types/selectors.d.ts.map +1 -1
- package/build-types/sync.d.ts +2 -2
- package/build-types/sync.d.ts.map +1 -1
- package/build-types/types.d.ts +11 -2
- package/build-types/types.d.ts.map +1 -1
- package/build-types/utils/block-selection-history.d.ts.map +1 -1
- package/build-types/utils/crdt-blocks.d.ts +12 -1
- package/build-types/utils/crdt-blocks.d.ts.map +1 -1
- package/build-types/utils/crdt-selection.d.ts +10 -0
- package/build-types/utils/crdt-selection.d.ts.map +1 -1
- package/build-types/utils/crdt-text.d.ts +16 -0
- package/build-types/utils/crdt-text.d.ts.map +1 -0
- package/build-types/utils/crdt-user-selections.d.ts +17 -4
- package/build-types/utils/crdt-user-selections.d.ts.map +1 -1
- package/build-types/utils/crdt-utils.d.ts +20 -0
- package/build-types/utils/crdt-utils.d.ts.map +1 -1
- package/build-types/utils/crdt.d.ts +14 -7
- package/build-types/utils/crdt.d.ts.map +1 -1
- package/build-types/utils/normalize-query-for-resolution.d.ts +12 -0
- package/build-types/utils/normalize-query-for-resolution.d.ts.map +1 -0
- package/build-types/utils/save-crdt-doc.d.ts +8 -0
- package/build-types/utils/save-crdt-doc.d.ts.map +1 -0
- package/build-types/utils/test/crdt-utils.d.ts +2 -0
- package/build-types/utils/test/crdt-utils.d.ts.map +1 -0
- package/package.json +18 -18
- package/src/actions.js +26 -41
- package/src/awareness/post-editor-awareness.ts +106 -7
- package/src/awareness/test/post-editor-awareness.ts +50 -10
- package/src/awareness/types.ts +7 -1
- package/src/entities.js +62 -24
- package/src/entity-provider.js +24 -11
- package/src/hooks/test/use-post-editor-awareness-state.ts +446 -3
- package/src/hooks/use-entity-prop.js +43 -3
- package/src/hooks/use-post-editor-awareness-state.ts +229 -7
- package/src/index.js +0 -6
- package/src/private-actions.js +43 -1
- package/src/{private-apis.js → private-apis.ts} +21 -3
- package/src/private-selectors.ts +43 -0
- package/src/queried-data/actions.js +1 -1
- package/src/queried-data/reducer.js +26 -14
- package/src/reducer.js +36 -1
- package/src/resolvers.js +23 -7
- package/src/selectors.ts +1 -32
- package/src/sync.ts +6 -2
- package/src/test/entities.js +231 -14
- package/src/test/private-actions.js +1 -1
- package/src/test/resolvers.js +64 -11
- package/src/test/store.js +116 -0
- package/src/types.ts +21 -2
- package/src/utils/block-selection-history.ts +5 -2
- package/src/utils/crdt-blocks.ts +250 -81
- package/src/utils/crdt-selection.ts +92 -26
- package/src/utils/crdt-text.ts +43 -0
- package/src/utils/crdt-user-selections.ts +29 -8
- package/src/utils/crdt-utils.ts +99 -0
- package/src/utils/crdt.ts +72 -46
- package/src/utils/test/crdt-blocks.ts +1177 -22
- package/src/utils/test/crdt-user-selections.ts +5 -0
- package/src/utils/test/crdt-utils.ts +387 -0
- package/src/utils/test/crdt.ts +423 -60
|
@@ -15,7 +15,7 @@ export interface Block {
|
|
|
15
15
|
originalContent?: string;
|
|
16
16
|
validationIssues?: string[];
|
|
17
17
|
}
|
|
18
|
-
interface YBlockRecord extends YMapRecord {
|
|
18
|
+
export interface YBlockRecord extends YMapRecord {
|
|
19
19
|
attributes: YBlockAttributes;
|
|
20
20
|
clientId: string;
|
|
21
21
|
innerBlocks: YBlocks;
|
|
@@ -26,6 +26,17 @@ interface YBlockRecord extends YMapRecord {
|
|
|
26
26
|
export type YBlock = YMapWrap<YBlockRecord>;
|
|
27
27
|
export type YBlocks = Y.Array<YBlock>;
|
|
28
28
|
export type YBlockAttributes = Y.Map<Y.Text | unknown>;
|
|
29
|
+
/**
|
|
30
|
+
* Convert blocks from their CRDT-serialized form back to the runtime form
|
|
31
|
+
* expected by the block editor. Rich-text attributes are stored as Y.Text in
|
|
32
|
+
* the CRDT document, which serializes to plain strings via toJSON(). This
|
|
33
|
+
* function restores them to RichTextData instances so that block edit
|
|
34
|
+
* components that rely on RichTextData methods (e.g. `.text`) work correctly.
|
|
35
|
+
*
|
|
36
|
+
* @param blocks Blocks as extracted from the CRDT document via toJSON().
|
|
37
|
+
* @return Blocks with rich-text attributes restored to RichTextData.
|
|
38
|
+
*/
|
|
39
|
+
export declare function deserializeBlockAttributes(blocks: Block[]): Block[];
|
|
29
40
|
/**
|
|
30
41
|
* Merge incoming block data into the local Y.Doc.
|
|
31
42
|
* This function is called to sync local block changes to a shared Y.Doc.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt-blocks.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-blocks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAEpC;;GAEG;AACH,OAAO,EAAc,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"crdt-blocks.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-blocks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAEpC;;GAEG;AACH,OAAO,EAAc,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI1E,UAAU,eAAe;IACxB,CAAE,GAAG,EAAE,MAAM,GAAI,OAAO,CAAC;CACzB;AAcD,MAAM,WAAW,KAAK;IACrB,UAAU,EAAE,eAAe,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,KAAK,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAGD,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC/C,UAAU,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAE,YAAY,CAAE,CAAC;AAC9C,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAE,MAAM,CAAE,CAAC;AAIxC,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,GAAG,CAAE,CAAC,CAAC,IAAI,GAAG,OAAO,CAAE,CAAC;AA2GzD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAE,MAAM,EAAE,KAAK,EAAE,GAAI,KAAK,EAAE,CAwBrE;AAsGD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,KAAK,EAAE,EACvB,cAAc,EAAE,MAAM,GAAG,IAAI,GAC3B,IAAI,CAqLN;AA0ID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,UAAU,EAAE,CAAC,CAAC,IAAI,EAClB,YAAY,EAAE,MAAM,EACpB,cAAc,GAAE,MAAM,GAAG,IAAW,GAClC,IAAI,CA4BN"}
|
|
@@ -13,4 +13,14 @@ export declare function updateSelectionHistory(ydoc: CRDTDoc, wpSelection: WPSel
|
|
|
13
13
|
* @param ydoc The Y.Doc where blocks are stored
|
|
14
14
|
*/
|
|
15
15
|
export declare function restoreSelection(selectionHistory: YFullSelection[], ydoc: Y.Doc): void;
|
|
16
|
+
/**
|
|
17
|
+
* If the latest selection has been shifted by remote edits, resolve and return
|
|
18
|
+
* it as a WPSelection. Returns null when the history is empty or neither
|
|
19
|
+
* endpoint has moved.
|
|
20
|
+
*
|
|
21
|
+
* @param ydoc The Y.Doc to resolve positions against
|
|
22
|
+
* @param selectionHistory The selection history to check
|
|
23
|
+
* @return The shifted WPSelection, or null if nothing moved.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getShiftedSelection(ydoc: Y.Doc, selectionHistory: YFullSelection[]): WPSelection | null;
|
|
16
26
|
//# sourceMappingURL=crdt-selection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt-selection.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-selection.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAElD;;GAEG;AACH,OAAO,EAIN,KAAK,cAAc,EAEnB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"crdt-selection.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-selection.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAElD;;GAEG;AACH,OAAO,EAIN,KAAK,cAAc,EAEnB,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EAAoB,WAAW,EAAE,MAAM,UAAU,CAAC;AAsB9D,wBAAgB,mBAAmB,CAAE,IAAI,EAAE,OAAO,GAAI,cAAc,EAAE,CAErE;AAED,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,GACtB,IAAI,CAEN;AAoGD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC/B,gBAAgB,EAAE,cAAc,EAAE,EAClC,IAAI,EAAE,CAAC,CAAC,GAAG,GACT,IAAI,CA+DN;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,CAAC,CAAC,GAAG,EACX,gBAAgB,EAAE,cAAc,EAAE,GAChC,WAAW,GAAG,IAAI,CA+BpB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { RichTextData } from '@wordpress/rich-text';
|
|
5
|
+
/**
|
|
6
|
+
* Returns a function that converts HTML strings to RichTextData instances,
|
|
7
|
+
* using a FIFO cache bounded by `maxSize` to avoid re-parsing identical
|
|
8
|
+
* strings. Repeated calls with the same string return the cached instance
|
|
9
|
+
* without re-running the HTML parser and DOM traversal.
|
|
10
|
+
*
|
|
11
|
+
* @param maxSize Maximum number of entries to hold in the cache.
|
|
12
|
+
* @return A cached version of RichTextData.fromHTMLString.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createRichTextDataCache(maxSize: number): (value: string) => RichTextData;
|
|
15
|
+
export declare const getCachedRichTextData: (value: string) => RichTextData;
|
|
16
|
+
//# sourceMappingURL=crdt-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crdt-text.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-text.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIpD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,MAAM,GACb,CAAE,KAAK,EAAE,MAAM,KAAM,YAAY,CAoBnC;AAED,eAAO,MAAM,qBAAqB,UAtBtB,MAAM,KAAM,YAwBvB,CAAC"}
|
|
@@ -10,6 +10,15 @@ export declare enum SelectionType {
|
|
|
10
10
|
SelectionInMultipleBlocks = "selection-in-multiple-blocks",
|
|
11
11
|
WholeBlock = "whole-block"
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The direction of a text selection, indicating where the caret sits.
|
|
15
|
+
*/
|
|
16
|
+
export declare enum SelectionDirection {
|
|
17
|
+
/** The caret is at the end of the selection (default / left-to-right). */
|
|
18
|
+
Forward = "f",
|
|
19
|
+
/** The caret is at the start of the selection (right-to-left). */
|
|
20
|
+
Backward = "b"
|
|
21
|
+
}
|
|
13
22
|
/**
|
|
14
23
|
* Converts WordPress block editor selection to a SelectionState.
|
|
15
24
|
*
|
|
@@ -18,12 +27,16 @@ export declare enum SelectionType {
|
|
|
18
27
|
* differ between the block-editor store and the Yjs document (e.g. in "Show
|
|
19
28
|
* Template" mode).
|
|
20
29
|
*
|
|
21
|
-
* @param selectionStart
|
|
22
|
-
* @param selectionEnd
|
|
23
|
-
* @param yDoc
|
|
30
|
+
* @param selectionStart - The start position of the selection
|
|
31
|
+
* @param selectionEnd - The end position of the selection
|
|
32
|
+
* @param yDoc - The Yjs document
|
|
33
|
+
* @param options - Optional parameters
|
|
34
|
+
* @param options.selectionDirection - The direction of the selection (forward or backward)
|
|
24
35
|
* @return The SelectionState
|
|
25
36
|
*/
|
|
26
|
-
export declare function getSelectionState(selectionStart: WPBlockSelection, selectionEnd: WPBlockSelection, yDoc: Y.Doc
|
|
37
|
+
export declare function getSelectionState(selectionStart: WPBlockSelection, selectionEnd: WPBlockSelection, yDoc: Y.Doc, options?: {
|
|
38
|
+
selectionDirection?: SelectionDirection;
|
|
39
|
+
}): SelectionState;
|
|
27
40
|
/**
|
|
28
41
|
* Resolves a local block-editor clientId to its index path relative to the
|
|
29
42
|
* post content blocks. This allows finding the corresponding block in the Yjs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt-user-selections.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-user-selections.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAWpC,OAAO,KAAK,EACX,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EAOd,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,oBAAY,aAAa;IACxB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,mBAAmB,2BAA2B;IAC9C,yBAAyB,iCAAiC;IAC1D,UAAU,gBAAgB;CAC1B;AAED
|
|
1
|
+
{"version":3,"file":"crdt-user-selections.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-user-selections.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAWpC,OAAO,KAAK,EACX,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EAOd,MAAM,UAAU,CAAC;AAElB;;GAEG;AACH,oBAAY,aAAa;IACxB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,mBAAmB,2BAA2B;IAC9C,yBAAyB,iCAAiC;IAC1D,UAAU,gBAAgB;CAC1B;AAED;;GAEG;AACH,oBAAY,kBAAkB;IAC7B,0EAA0E;IAC1E,OAAO,MAAM;IACb,kEAAkE;IAClE,QAAQ,MAAM;CACd;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAChC,cAAc,EAAE,gBAAgB,EAChC,YAAY,EAAE,gBAAgB,EAC9B,IAAI,EAAE,CAAC,CAAC,GAAG,EACX,OAAO,CAAC,EAAE;IAAE,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;CAAE,GACnD,cAAc,CAwFhB;AA0CD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAC3C,QAAQ,EAAE,MAAM,GACd,sBAAsB,GAAG,IAAI,CAyB/B;AA4DD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,UAAU,EAAE,cAAc,EAC1B,UAAU,EAAE,cAAc,GACxB,OAAO,CAsDT"}
|
|
@@ -62,4 +62,24 @@ export declare function isYMap<T extends YMapRecord>(value: YMapWrap<T> | undefi
|
|
|
62
62
|
* @return The block, or null if the block is not found
|
|
63
63
|
*/
|
|
64
64
|
export declare function findBlockByClientIdInDoc(blockId: string, ydoc: Y.Doc): YBlock | null;
|
|
65
|
+
/**
|
|
66
|
+
* Convert an HTML character index (counting tag characters) to a rich-text
|
|
67
|
+
* offset (counting only text characters). Used on read paths where Y.Text
|
|
68
|
+
* resolves to an HTML index but the block editor expects a text offset.
|
|
69
|
+
*
|
|
70
|
+
* @param html The full HTML string from Y.Text.
|
|
71
|
+
* @param htmlIndex The HTML character index.
|
|
72
|
+
* @return The corresponding rich-text offset.
|
|
73
|
+
*/
|
|
74
|
+
export declare function htmlIndexToRichTextOffset(html: string, htmlIndex: number): number;
|
|
75
|
+
/**
|
|
76
|
+
* Convert a rich-text offset (counting only text characters) to an HTML
|
|
77
|
+
* character index (counting tag characters). Used on write paths where the
|
|
78
|
+
* block editor provides a text offset but Y.Text expects an HTML index.
|
|
79
|
+
*
|
|
80
|
+
* @param html The full HTML string from Y.Text.
|
|
81
|
+
* @param richTextOffset The rich-text text offset.
|
|
82
|
+
* @return The corresponding HTML character index.
|
|
83
|
+
*/
|
|
84
|
+
export declare function richTextOffsetToHtmlIndex(html: string, richTextOffset: number): number;
|
|
65
85
|
//# sourceMappingURL=crdt-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt-utils.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"crdt-utils.d.ts","sourceRoot":"","sources":["../../src/utils/crdt-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAC;AAGpC;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,eAAe,CAAC;AAIrD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAE,MAAM,EAAE,OAAO,CAAE,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,QAAQ,CAAE,CAAC,SAAS,UAAU,CAAG,SAAQ,CAAC,CAAC,YAAY,CAAE,CAAC,CAAE;IAC5E,MAAM,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,IAAI,CAAC;IAChD,OAAO,EAAE,CACR,QAAQ,EAAE,CACT,KAAK,EAAE,CAAC,CAAE,MAAM,CAAC,CAAE,EACnB,GAAG,EAAE,MAAM,CAAC,EACZ,GAAG,EAAE,QAAQ,CAAE,CAAC,CAAE,KACd,IAAI,KACL,IAAI,CAAC;IACV,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,OAAO,CAAC;IAChD,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,KAAM,CAAC,CAAE,CAAC,CAAE,GAAG,SAAS,CAAC;IAC3D,GAAG,EAAE,CAAE,CAAC,SAAS,MAAM,CAAC,EAAI,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAE,CAAC,CAAE,KAAM,IAAI,CAAC;IAC5D,MAAM,EAAE,MAAM,CAAC,CAAC;CAEhB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAE,CAAC,SAAS,UAAU,EAC/C,GAAG,EAAE,CAAC,CAAC,GAAG,EACV,GAAG,EAAE,MAAM,GACT,QAAQ,CAAE,CAAC,CAAE,CAEf;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAE,CAAC,SAAS,UAAU,EAC/C,OAAO,GAAE,OAAO,CAAE,CAAC,CAAO,GACxB,QAAQ,CAAE,CAAC,CAAE,CAEf;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAE,CAAC,SAAS,UAAU,EAC3C,KAAK,EAAE,QAAQ,CAAE,CAAC,CAAE,GAAG,SAAS,GAC9B,KAAK,IAAI,QAAQ,CAAE,CAAC,CAAE,CAExB;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,CAAC,CAAC,GAAG,GACT,MAAM,GAAG,IAAI,CASf;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GACf,MAAM,CAiBR;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GACpB,MAAM,CA4BR"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type CRDTDoc, type SyncConfig, Y } from '@wordpress/sync';
|
|
2
2
|
import { type Block, type YBlocks } from './crdt-blocks';
|
|
3
3
|
import { type Post } from '../entity-types/post';
|
|
4
|
-
import { type Type } from '../entity-types';
|
|
5
4
|
import type { WPSelection } from '../types';
|
|
6
5
|
import { type YMapRecord, type YMapWrap } from './crdt-utils';
|
|
7
6
|
export type PostChanges = Partial<Post> & {
|
|
@@ -30,30 +29,38 @@ export interface YPostRecord extends YMapRecord {
|
|
|
30
29
|
template: string;
|
|
31
30
|
title: Y.Text;
|
|
32
31
|
}
|
|
32
|
+
export declare const POST_META_KEY_FOR_CRDT_DOC_PERSISTENCE = "_crdt_document";
|
|
33
33
|
/**
|
|
34
34
|
* Given a set of local changes to a post record, apply those changes to the
|
|
35
35
|
* local Y.Doc.
|
|
36
36
|
*
|
|
37
37
|
* @param {CRDTDoc} ydoc
|
|
38
38
|
* @param {PostChanges} changes
|
|
39
|
-
* @param {
|
|
39
|
+
* @param {Set<string>} syncedProperties
|
|
40
40
|
* @return {void}
|
|
41
41
|
*/
|
|
42
|
-
export declare function applyPostChangesToCRDTDoc(ydoc: CRDTDoc, changes: PostChanges,
|
|
42
|
+
export declare function applyPostChangesToCRDTDoc(ydoc: CRDTDoc, changes: PostChanges, syncedProperties: Set<string>): void;
|
|
43
43
|
/**
|
|
44
44
|
* Given a local Y.Doc that *may* contain changes from remote peers, compare
|
|
45
45
|
* against the local record and determine if there are changes (edits) we want
|
|
46
46
|
* to dispatch.
|
|
47
47
|
*
|
|
48
|
-
* @param {CRDTDoc}
|
|
49
|
-
* @param {Post}
|
|
50
|
-
* @param {
|
|
48
|
+
* @param {CRDTDoc} ydoc
|
|
49
|
+
* @param {Post} editedRecord
|
|
50
|
+
* @param {Set<string>} syncedProperties
|
|
51
51
|
* @return {Partial<PostChanges>} The changes that should be applied to the local record.
|
|
52
52
|
*/
|
|
53
|
-
export declare function getPostChangesFromCRDTDoc(ydoc: CRDTDoc, editedRecord: Post,
|
|
53
|
+
export declare function getPostChangesFromCRDTDoc(ydoc: CRDTDoc, editedRecord: Post, syncedProperties: Set<string>): PostChanges;
|
|
54
54
|
/**
|
|
55
55
|
* This default sync config can be used for entities that are flat maps of
|
|
56
56
|
* primitive values and do not require custom logic to merge changes.
|
|
57
57
|
*/
|
|
58
58
|
export declare const defaultSyncConfig: SyncConfig;
|
|
59
|
+
/**
|
|
60
|
+
* This default collection sync config can be used to sync entity collections
|
|
61
|
+
* (e.g., block comments) where we are not interested in merging changes at the
|
|
62
|
+
* individual record level, but instead want to replace the entire collection
|
|
63
|
+
* when changes are detected.
|
|
64
|
+
*/
|
|
65
|
+
export declare const defaultCollectionSyncConfig: SyncConfig;
|
|
59
66
|
//# sourceMappingURL=crdt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../../src/utils/crdt.ts"],"names":[],"mappings":"AAUA,OAAO,EACN,KAAK,OAAO,
|
|
1
|
+
{"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../../src/utils/crdt.ts"],"names":[],"mappings":"AAUA,OAAO,EACN,KAAK,OAAO,EAIZ,KAAK,UAAU,EACf,CAAC,EACD,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EAIN,KAAK,KAAK,EAEV,KAAK,OAAO,EACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAM5C,OAAO,EAIN,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,MAAM,cAAc,CAAC;AAGtB,MAAM,MAAM,WAAW,GAAG,OAAO,CAAE,IAAI,CAAE,GAAG;IAC3C,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,CAAE,SAAS,CAAE,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,IAAI,CAAE,SAAS,CAAE,GAAG,MAAM,CAAC;IACrC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,KAAK,CAAC,EAAE,IAAI,CAAE,OAAO,CAAE,GAAG,MAAM,CAAC;CACjC,CAAC;AAGF,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC9C,MAAM,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,CAAE,UAAU,CAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC;CACd;AAED,eAAO,MAAM,sCAAsC,mBAAmB,CAAC;AAsCvE;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,GAAG,CAAE,MAAM,CAAE,GAC7B,IAAI,CAoIN;AAMD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACxC,IAAI,EAAE,OAAO,EACb,YAAY,EAAE,IAAI,EAClB,gBAAgB,EAAE,GAAG,CAAE,MAAM,CAAE,GAC7B,WAAW,CAuJb;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAI/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,EAAE,UAKzC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a copy of `query` filtered to only the keys that affect resolution
|
|
3
|
+
* identity (`context` and `_fields`), or `undefined` when none are present.
|
|
4
|
+
* This mirrors the normalisation that the data store applies when keying
|
|
5
|
+
* resolved records, so that `finishResolutions` receives args that match the
|
|
6
|
+
* keys used by callers who omit pagination params.
|
|
7
|
+
*
|
|
8
|
+
* @param {Object} query The raw query object.
|
|
9
|
+
* @return {Object|undefined} Normalised query or undefined.
|
|
10
|
+
*/
|
|
11
|
+
export default function normalizeQueryForResolution(query: any): any | undefined;
|
|
12
|
+
//# sourceMappingURL=normalize-query-for-resolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-query-for-resolution.d.ts","sourceRoot":"","sources":["../../src/utils/normalize-query-for-resolution.js"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,2BAA2B,CAAE,KAAK,KAAA,GAF9C,MAAO,SAAS,CAc3B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persist the current CRDT document through the sync /save endpoint.
|
|
3
|
+
*
|
|
4
|
+
* @param {import('@wordpress/sync').ObjectType} objectType Object type.
|
|
5
|
+
* @param {import('@wordpress/sync').ObjectID} objectId Object ID.
|
|
6
|
+
*/
|
|
7
|
+
export declare function saveCRDTDoc(objectType: import('@wordpress/sync').ObjectType, objectId: import('@wordpress/sync').ObjectID): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=save-crdt-doc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save-crdt-doc.d.ts","sourceRoot":"","sources":["../../src/utils/save-crdt-doc.js"],"names":[],"mappings":"AAiCA;;;;;GAKG;AACH,wBAAsB,WAAW,CAAE,UAAU,EAHlC,OAAO,iBAAiB,EAAE,UAGQ,EAAE,QAAQ,EAF5C,OAAO,iBAAiB,EAAE,QAEkB,iBAwBtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crdt-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/test/crdt-utils.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/core-data",
|
|
3
|
-
"version": "7.40.2
|
|
3
|
+
"version": "7.40.2",
|
|
4
4
|
"description": "Access to and manipulation of core WordPress entities.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -49,22 +49,22 @@
|
|
|
49
49
|
"build-module/index.mjs"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@wordpress/api-fetch": "^7.40.1
|
|
53
|
-
"@wordpress/block-editor": "^15.13.2
|
|
54
|
-
"@wordpress/blocks": "^15.13.1
|
|
55
|
-
"@wordpress/compose": "^7.40.1
|
|
56
|
-
"@wordpress/data": "^10.40.1
|
|
57
|
-
"@wordpress/deprecated": "^4.40.1
|
|
58
|
-
"@wordpress/element": "^6.40.1
|
|
59
|
-
"@wordpress/html-entities": "^4.40.1
|
|
60
|
-
"@wordpress/i18n": "^6.13.1
|
|
61
|
-
"@wordpress/is-shallow-equal": "^5.40.1
|
|
62
|
-
"@wordpress/private-apis": "^1.40.1
|
|
63
|
-
"@wordpress/rich-text": "^7.40.1
|
|
64
|
-
"@wordpress/sync": "^1.40.1
|
|
65
|
-
"@wordpress/undo-manager": "^1.40.1
|
|
66
|
-
"@wordpress/url": "^4.40.1
|
|
67
|
-
"@wordpress/warning": "^3.40.1
|
|
52
|
+
"@wordpress/api-fetch": "^7.40.1",
|
|
53
|
+
"@wordpress/block-editor": "^15.13.2",
|
|
54
|
+
"@wordpress/blocks": "^15.13.1",
|
|
55
|
+
"@wordpress/compose": "^7.40.1",
|
|
56
|
+
"@wordpress/data": "^10.40.1",
|
|
57
|
+
"@wordpress/deprecated": "^4.40.1",
|
|
58
|
+
"@wordpress/element": "^6.40.1",
|
|
59
|
+
"@wordpress/html-entities": "^4.40.1",
|
|
60
|
+
"@wordpress/i18n": "^6.13.1",
|
|
61
|
+
"@wordpress/is-shallow-equal": "^5.40.1",
|
|
62
|
+
"@wordpress/private-apis": "^1.40.1",
|
|
63
|
+
"@wordpress/rich-text": "^7.40.1",
|
|
64
|
+
"@wordpress/sync": "^1.40.1",
|
|
65
|
+
"@wordpress/undo-manager": "^1.40.1",
|
|
66
|
+
"@wordpress/url": "^4.40.1",
|
|
67
|
+
"@wordpress/warning": "^3.40.1",
|
|
68
68
|
"change-case": "^4.1.2",
|
|
69
69
|
"equivalent-key-map": "^0.2.2",
|
|
70
70
|
"fast-deep-equal": "^3.1.3",
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"publishConfig": {
|
|
85
85
|
"access": "public"
|
|
86
86
|
},
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "adb6623c9f32490cfc73c7ac7f122578c1f10c65"
|
|
88
88
|
}
|
package/src/actions.js
CHANGED
|
@@ -19,9 +19,17 @@ import { receiveItems, removeItems, receiveQueriedItems } from './queried-data';
|
|
|
19
19
|
import { DEFAULT_ENTITY_KEY } from './entities';
|
|
20
20
|
import { createBatch } from './batch';
|
|
21
21
|
import { STORE_NAME } from './name';
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
LOCAL_EDITOR_ORIGIN,
|
|
24
|
+
LOCAL_UNDO_IGNORED_ORIGIN,
|
|
25
|
+
getSyncManager,
|
|
26
|
+
} from './sync';
|
|
23
27
|
import logEntityDeprecation from './utils/log-entity-deprecation';
|
|
24
28
|
|
|
29
|
+
function addTitleToAutoDraft( record ) {
|
|
30
|
+
return record.status === 'auto-draft' ? { ...record, title: '' } : record;
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
/**
|
|
26
34
|
* Returns an action object used in signalling that authors have been received.
|
|
27
35
|
* Ignored from documentation as it's internal to the data store.
|
|
@@ -96,12 +104,9 @@ export function receiveEntityRecords(
|
|
|
96
104
|
// Auto drafts should not have titles, but some plugins rely on them so we can't filter this
|
|
97
105
|
// on the server.
|
|
98
106
|
if ( kind === 'postType' ) {
|
|
99
|
-
records =
|
|
100
|
-
(
|
|
101
|
-
|
|
102
|
-
? { ...record, title: '' }
|
|
103
|
-
: record
|
|
104
|
-
);
|
|
107
|
+
records = Array.isArray( records )
|
|
108
|
+
? records.map( addTitleToAutoDraft )
|
|
109
|
+
: addTitleToAutoDraft( records );
|
|
105
110
|
}
|
|
106
111
|
let action;
|
|
107
112
|
if ( query ) {
|
|
@@ -445,11 +450,18 @@ export const editEntityRecord =
|
|
|
445
450
|
? false
|
|
446
451
|
: ! options.isCached;
|
|
447
452
|
|
|
453
|
+
// Use an untracked origin for undoIgnore changes so the Yjs
|
|
454
|
+
// UndoManager does not capture them as undo levels, while
|
|
455
|
+
// still syncing them to the CRDT document and other peers.
|
|
456
|
+
const origin = options.undoIgnore
|
|
457
|
+
? LOCAL_UNDO_IGNORED_ORIGIN
|
|
458
|
+
: LOCAL_EDITOR_ORIGIN;
|
|
459
|
+
|
|
448
460
|
getSyncManager()?.update(
|
|
449
461
|
objectType,
|
|
450
462
|
objectId,
|
|
451
463
|
editsWithMerges,
|
|
452
|
-
|
|
464
|
+
origin,
|
|
453
465
|
{ isNewUndoLevel }
|
|
454
466
|
);
|
|
455
467
|
}
|
|
@@ -773,10 +785,10 @@ export const saveEntityRecord =
|
|
|
773
785
|
if ( entityConfig.__unstablePrePersist ) {
|
|
774
786
|
edits = {
|
|
775
787
|
...edits,
|
|
776
|
-
...entityConfig.__unstablePrePersist(
|
|
788
|
+
...( await entityConfig.__unstablePrePersist(
|
|
777
789
|
persistedRecord,
|
|
778
790
|
edits
|
|
779
|
-
),
|
|
791
|
+
) ),
|
|
780
792
|
};
|
|
781
793
|
}
|
|
782
794
|
updatedRecord = await __unstableFetch( {
|
|
@@ -793,11 +805,13 @@ export const saveEntityRecord =
|
|
|
793
805
|
edits
|
|
794
806
|
);
|
|
795
807
|
if ( entityConfig.syncConfig ) {
|
|
808
|
+
// Use an untracked origin so that the save
|
|
809
|
+
// response does not create undo levels.
|
|
796
810
|
getSyncManager()?.update(
|
|
797
811
|
`${ kind }/${ name }`,
|
|
798
812
|
recordId,
|
|
799
813
|
updatedRecord,
|
|
800
|
-
|
|
814
|
+
LOCAL_UNDO_IGNORED_ORIGIN,
|
|
801
815
|
{ isSave: true }
|
|
802
816
|
);
|
|
803
817
|
}
|
|
@@ -1108,7 +1122,7 @@ export const receiveRevisions =
|
|
|
1108
1122
|
dispatch( {
|
|
1109
1123
|
type: 'RECEIVE_ITEM_REVISIONS',
|
|
1110
1124
|
key,
|
|
1111
|
-
items:
|
|
1125
|
+
items: records,
|
|
1112
1126
|
recordKey,
|
|
1113
1127
|
meta,
|
|
1114
1128
|
query,
|
|
@@ -1117,32 +1131,3 @@ export const receiveRevisions =
|
|
|
1117
1131
|
invalidateCache,
|
|
1118
1132
|
} );
|
|
1119
1133
|
};
|
|
1120
|
-
|
|
1121
|
-
/**
|
|
1122
|
-
* Returns an action object used to set the sync connection status for an entity or collection.
|
|
1123
|
-
*
|
|
1124
|
-
* @param {string} kind Kind of the entity.
|
|
1125
|
-
* @param {string} name Name of the entity.
|
|
1126
|
-
* @param {number|string|null} key The entity key, or null for collections.
|
|
1127
|
-
* @param {Object|null} status The connection state object or null on unload.
|
|
1128
|
-
*
|
|
1129
|
-
* @return {Object} Action object.
|
|
1130
|
-
*/
|
|
1131
|
-
export function setSyncConnectionStatus( kind, name, key, status ) {
|
|
1132
|
-
if ( ! status ) {
|
|
1133
|
-
return {
|
|
1134
|
-
type: 'CLEAR_SYNC_CONNECTION_STATUS',
|
|
1135
|
-
kind,
|
|
1136
|
-
name,
|
|
1137
|
-
key,
|
|
1138
|
-
};
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
return {
|
|
1142
|
-
type: 'SET_SYNC_CONNECTION_STATUS',
|
|
1143
|
-
kind,
|
|
1144
|
-
name,
|
|
1145
|
-
key,
|
|
1146
|
-
status,
|
|
1147
|
-
};
|
|
1148
|
-
}
|
|
@@ -16,10 +16,12 @@ import {
|
|
|
16
16
|
LOCAL_CURSOR_UPDATE_DEBOUNCE_IN_MS,
|
|
17
17
|
} from './config';
|
|
18
18
|
import { STORE_NAME as coreStore } from '../name';
|
|
19
|
+
import { htmlIndexToRichTextOffset } from '../utils/crdt-utils';
|
|
19
20
|
import {
|
|
20
21
|
areSelectionsStatesEqual,
|
|
21
22
|
getSelectionState,
|
|
22
23
|
SelectionType,
|
|
24
|
+
SelectionDirection,
|
|
23
25
|
} from '../utils/crdt-user-selections';
|
|
24
26
|
|
|
25
27
|
import type { SelectionState, WPBlockSelection } from '../types';
|
|
@@ -69,6 +71,18 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
69
71
|
let selectionEnd = getSelectionEnd();
|
|
70
72
|
let localCursorTimeout: NodeJS.Timeout | null = null;
|
|
71
73
|
|
|
74
|
+
// During rapid selection changes (e.g. undo restoring content and
|
|
75
|
+
// selection), the debounce discards intermediate events. If we use the
|
|
76
|
+
// last intermediate state instead of the overall change it can produce
|
|
77
|
+
// the wrong direction.
|
|
78
|
+
// Use selectionBeforeDebounce to capture the selection state from
|
|
79
|
+
// before the debounce window so that direction is computed across the
|
|
80
|
+
// full window when it fires.
|
|
81
|
+
let selectionBeforeDebounce: {
|
|
82
|
+
start: WPBlockSelection;
|
|
83
|
+
end: WPBlockSelection;
|
|
84
|
+
} | null = null;
|
|
85
|
+
|
|
72
86
|
subscribe( () => {
|
|
73
87
|
const newSelectionStart = getSelectionStart();
|
|
74
88
|
const newSelectionEnd = getSelectionEnd();
|
|
@@ -80,6 +94,15 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
80
94
|
return;
|
|
81
95
|
}
|
|
82
96
|
|
|
97
|
+
// On the first change of a debounce window, snapshot the state
|
|
98
|
+
// we're moving away from.
|
|
99
|
+
if ( ! selectionBeforeDebounce ) {
|
|
100
|
+
selectionBeforeDebounce = {
|
|
101
|
+
start: selectionStart,
|
|
102
|
+
end: selectionEnd,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
83
106
|
selectionStart = newSelectionStart;
|
|
84
107
|
selectionEnd = newSelectionEnd;
|
|
85
108
|
|
|
@@ -103,10 +126,29 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
103
126
|
}
|
|
104
127
|
|
|
105
128
|
localCursorTimeout = setTimeout( () => {
|
|
129
|
+
// Compute direction across the full debounce window.
|
|
130
|
+
const selectionStateOptions: {
|
|
131
|
+
selectionDirection?: SelectionDirection;
|
|
132
|
+
} = {};
|
|
133
|
+
|
|
134
|
+
if ( selectionBeforeDebounce ) {
|
|
135
|
+
selectionStateOptions.selectionDirection =
|
|
136
|
+
detectSelectionDirection(
|
|
137
|
+
selectionBeforeDebounce.start,
|
|
138
|
+
selectionBeforeDebounce.end,
|
|
139
|
+
selectionStart,
|
|
140
|
+
selectionEnd
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Reset debounced selection state.
|
|
144
|
+
selectionBeforeDebounce = null;
|
|
145
|
+
}
|
|
146
|
+
|
|
106
147
|
const selectionState = getSelectionState(
|
|
107
148
|
selectionStart,
|
|
108
149
|
selectionEnd,
|
|
109
|
-
this.doc
|
|
150
|
+
this.doc,
|
|
151
|
+
selectionStateOptions
|
|
110
152
|
);
|
|
111
153
|
|
|
112
154
|
this.setThrottledLocalStateField(
|
|
@@ -171,6 +213,10 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
171
213
|
return state1 === state2;
|
|
172
214
|
}
|
|
173
215
|
|
|
216
|
+
if ( ! state1.selection || ! state2.selection ) {
|
|
217
|
+
return state1.selection === state2.selection;
|
|
218
|
+
}
|
|
219
|
+
|
|
174
220
|
return areSelectionsStatesEqual( state1.selection, state2.selection );
|
|
175
221
|
}
|
|
176
222
|
|
|
@@ -188,14 +234,14 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
188
234
|
* clientIds (e.g. in "Show Template" mode where blocks are cloned).
|
|
189
235
|
*
|
|
190
236
|
* @param selection - The selection state.
|
|
191
|
-
* @return The text
|
|
237
|
+
* @return The rich-text offset and block client ID, or nulls if not resolvable.
|
|
192
238
|
*/
|
|
193
239
|
public convertSelectionStateToAbsolute( selection: SelectionState ): {
|
|
194
|
-
|
|
240
|
+
richTextOffset: number | null;
|
|
195
241
|
localClientId: string | null;
|
|
196
242
|
} {
|
|
197
243
|
if ( selection.type === SelectionType.None ) {
|
|
198
|
-
return {
|
|
244
|
+
return { richTextOffset: null, localClientId: null };
|
|
199
245
|
}
|
|
200
246
|
|
|
201
247
|
if ( selection.type === SelectionType.WholeBlock ) {
|
|
@@ -218,7 +264,7 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
218
264
|
}
|
|
219
265
|
}
|
|
220
266
|
|
|
221
|
-
return {
|
|
267
|
+
return { richTextOffset: null, localClientId };
|
|
222
268
|
}
|
|
223
269
|
|
|
224
270
|
// Text-based selections: resolve cursor position and navigate up.
|
|
@@ -233,7 +279,7 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
233
279
|
);
|
|
234
280
|
|
|
235
281
|
if ( ! absolutePosition ) {
|
|
236
|
-
return {
|
|
282
|
+
return { richTextOffset: null, localClientId: null };
|
|
237
283
|
}
|
|
238
284
|
|
|
239
285
|
// Navigate up: Y.Text -> attributes Y.Map -> block Y.Map
|
|
@@ -242,7 +288,13 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
242
288
|
yType instanceof Y.Map ? getBlockPathInYdoc( yType ) : null;
|
|
243
289
|
const localClientId = path ? resolveBlockClientIdByPath( path ) : null;
|
|
244
290
|
|
|
245
|
-
return {
|
|
291
|
+
return {
|
|
292
|
+
richTextOffset: htmlIndexToRichTextOffset(
|
|
293
|
+
absolutePosition.type.toString(),
|
|
294
|
+
absolutePosition.index
|
|
295
|
+
),
|
|
296
|
+
localClientId,
|
|
297
|
+
};
|
|
246
298
|
}
|
|
247
299
|
|
|
248
300
|
/**
|
|
@@ -325,3 +377,50 @@ export class PostEditorAwareness extends BaseAwarenessState< PostEditorState > {
|
|
|
325
377
|
};
|
|
326
378
|
}
|
|
327
379
|
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Detect the direction of a selection change by comparing old and new edges.
|
|
383
|
+
*
|
|
384
|
+
* When the user extends a selection backward (e.g. Shift+Left), the
|
|
385
|
+
* selectionStart edge moves while selectionEnd stays fixed, so the caret
|
|
386
|
+
* is at the start. The reverse is true for forward extension.
|
|
387
|
+
*
|
|
388
|
+
* @param prevStart - The previous selectionStart.
|
|
389
|
+
* @param prevEnd - The previous selectionEnd.
|
|
390
|
+
* @param newStart - The new selectionStart.
|
|
391
|
+
* @param newEnd - The new selectionEnd.
|
|
392
|
+
* @return The detected direction, defaulting to Forward when indeterminate.
|
|
393
|
+
*/
|
|
394
|
+
function detectSelectionDirection(
|
|
395
|
+
prevStart: WPBlockSelection,
|
|
396
|
+
prevEnd: WPBlockSelection,
|
|
397
|
+
newStart: WPBlockSelection,
|
|
398
|
+
newEnd: WPBlockSelection
|
|
399
|
+
): SelectionDirection {
|
|
400
|
+
const startMoved = ! areBlockSelectionsEqual( prevStart, newStart );
|
|
401
|
+
const endMoved = ! areBlockSelectionsEqual( prevEnd, newEnd );
|
|
402
|
+
|
|
403
|
+
if ( startMoved && ! endMoved ) {
|
|
404
|
+
return SelectionDirection.Backward;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return SelectionDirection.Forward;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Compare two WPBlockSelection objects by value.
|
|
412
|
+
*
|
|
413
|
+
* @param a - First selection.
|
|
414
|
+
* @param b - Second selection.
|
|
415
|
+
* @return True if all fields are equal.
|
|
416
|
+
*/
|
|
417
|
+
function areBlockSelectionsEqual(
|
|
418
|
+
a: WPBlockSelection,
|
|
419
|
+
b: WPBlockSelection
|
|
420
|
+
): boolean {
|
|
421
|
+
return (
|
|
422
|
+
a.clientId === b.clientId &&
|
|
423
|
+
a.attributeKey === b.attributeKey &&
|
|
424
|
+
a.offset === b.offset
|
|
425
|
+
);
|
|
426
|
+
}
|