edytor 4.0.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/README.md +2 -2
  2. package/dist/block/block.svelte.js +6 -21
  3. package/dist/block/inlineBlock.svelte.js +4 -6
  4. package/dist/clipboard/moveText.js +6 -8
  5. package/dist/cloudflare/DocumentRoom.d.ts +10 -3
  6. package/dist/cloudflare/index.d.ts +1 -1
  7. package/dist/cloudflare/room/access.d.ts +8 -3
  8. package/dist/cloudflare/room/access.js +44 -20
  9. package/dist/cloudflare/room/admission.js +28 -5
  10. package/dist/cloudflare/room/comments.js +28 -1
  11. package/dist/cloudflare/room/context.d.ts +106 -109
  12. package/dist/cloudflare/room/context.js +10 -3
  13. package/dist/cloudflare/room/forged.d.ts +14 -0
  14. package/dist/cloudflare/room/forged.js +30 -2
  15. package/dist/cloudflare/room/frames.d.ts +4 -0
  16. package/dist/cloudflare/room/frames.js +5 -1
  17. package/dist/cloudflare/room/purge.js +2 -1
  18. package/dist/cloudflare/room/replicas.d.ts +4 -2
  19. package/dist/cloudflare/room/replicas.js +8 -3
  20. package/dist/cloudflare/room/suggest.d.ts +7 -0
  21. package/dist/cloudflare/room/suggest.js +143 -0
  22. package/dist/cloudflare/routeDocumentSocket.d.ts +10 -1
  23. package/dist/cloudflare/routeDocumentSocket.js +5 -3
  24. package/dist/components/Content.svelte +9 -1
  25. package/dist/crdt/anchors.js +3 -2
  26. package/dist/crdt/attribution/attribution.d.ts +3 -0
  27. package/dist/crdt/attribution/attribution.js +3 -3
  28. package/dist/crdt/doc/funnel.d.ts +1 -1
  29. package/dist/crdt/doc/funnel.js +5 -2
  30. package/dist/crdt/doc/gate.d.ts +1 -1
  31. package/dist/crdt/doc/history.d.ts +6 -0
  32. package/dist/crdt/doc/history.js +79 -59
  33. package/dist/crdt/doc/ops.d.ts +81 -0
  34. package/dist/crdt/doc/ops.js +1898 -0
  35. package/dist/crdt/doc/reads.d.ts +2 -2
  36. package/dist/crdt/doc/reads.js +18 -28
  37. package/dist/crdt/doc/suggest.d.ts +167 -0
  38. package/dist/crdt/doc/suggest.js +579 -0
  39. package/dist/crdt/document.d.ts +10 -1
  40. package/dist/crdt/document.js +19 -11
  41. package/dist/crdt/edytor-doc.d.ts +294 -272
  42. package/dist/crdt/edytor-doc.js +123 -108
  43. package/dist/crdt/engine-api.d.ts +8 -2
  44. package/dist/crdt/engine.d.ts +2 -1
  45. package/dist/crdt/engine.js +3 -1
  46. package/dist/crdt/flow.d.ts +5 -47
  47. package/dist/crdt/flow.js +3 -269
  48. package/dist/crdt/index.d.ts +102 -108
  49. package/dist/crdt/index.js +3 -0
  50. package/dist/crdt/operations.d.ts +13 -4
  51. package/dist/crdt/parts.d.ts +43 -0
  52. package/dist/crdt/parts.js +44 -0
  53. package/dist/crdt/placement/display.d.ts +1 -1
  54. package/dist/crdt/placement/display.js +3 -3
  55. package/dist/crdt/placement/keys.d.ts +5 -0
  56. package/dist/crdt/placement/keys.js +5 -0
  57. package/dist/crdt/placement/resolve.d.ts +1 -1
  58. package/dist/crdt/placement/resolve.js +2 -1
  59. package/dist/crdt/protocol.d.ts +1 -1
  60. package/dist/crdt/protocol.js +1 -1
  61. package/dist/crdt/protocols/auth.d.ts +11 -1
  62. package/dist/crdt/protocols/auth.js +17 -1
  63. package/dist/crdt/protocols/awareness.js +46 -81
  64. package/dist/crdt/protocols/comments.d.ts +16 -1
  65. package/dist/crdt/protocols/comments.js +9 -1
  66. package/dist/crdt/providers/index.d.ts +12 -22
  67. package/dist/crdt/providers/index.js +3 -1
  68. package/dist/crdt/providers/indexeddb.d.ts +6 -10
  69. package/dist/crdt/providers/indexeddb.js +10 -16
  70. package/dist/crdt/providers/room.d.ts +11 -0
  71. package/dist/crdt/providers/room.js +26 -12
  72. package/dist/crdt/providers/websocket.d.ts +8 -12
  73. package/dist/crdt/providers/websocket.js +17 -19
  74. package/dist/crdt/purge.d.ts +7 -1
  75. package/dist/crdt/purge.js +32 -2
  76. package/dist/crdt/rangeDelete.d.ts +2 -47
  77. package/dist/crdt/rangeDelete.js +1 -169
  78. package/dist/crdt/restore.d.ts +2 -1
  79. package/dist/crdt/restore.js +9 -0
  80. package/dist/crdt/schema.d.ts +9 -1
  81. package/dist/crdt/schema.js +13 -3
  82. package/dist/crdt/structs.d.ts +2 -0
  83. package/dist/crdt/structs.js +2 -0
  84. package/dist/crdt/text/index/build.d.ts +125 -0
  85. package/dist/crdt/text/index/build.js +2895 -0
  86. package/dist/crdt/text/index/shared.d.ts +2 -6
  87. package/dist/crdt/text/index/shared.js +19 -19
  88. package/dist/crdt/text/model.d.ts +10 -0
  89. package/dist/crdt/text/model.js +10 -4
  90. package/dist/crdt/text/runs.d.ts +43 -42
  91. package/dist/crdt/text/runs.js +2 -165
  92. package/dist/crdt/vendor/yjs/UPSTREAM.md +83 -0
  93. package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
  94. package/dist/crdt/vendor/yjs/dts/structs/Item.d.ts +6 -3
  95. package/dist/crdt/vendor/yjs/dts/ynode.d.ts +13 -2
  96. package/dist/crdt/vendor/yjs/src/index.js +1 -1
  97. package/dist/crdt/vendor/yjs/src/structs/Item.js +44 -5
  98. package/dist/crdt/vendor/yjs/src/ynode.js +29 -7
  99. package/dist/edytor.svelte.d.ts +1 -1
  100. package/dist/edytor.svelte.js +100 -75
  101. package/dist/events/beforeInputCommands.d.ts +2 -2
  102. package/dist/events/domTextOffset.d.ts +2 -0
  103. package/dist/events/domTextOffset.js +8 -0
  104. package/dist/events/nativeInteractiveControl.d.ts +11 -1
  105. package/dist/events/nativeInteractiveControl.js +41 -1
  106. package/dist/events/onBeforeInput.js +3 -3
  107. package/dist/events/onFocus.js +9 -11
  108. package/dist/export/forms.d.ts +75 -75
  109. package/dist/index.d.ts +4 -2
  110. package/dist/index.js +1 -1
  111. package/dist/labels.d.ts +8 -0
  112. package/dist/labels.js +6 -1
  113. package/dist/plugins/comments/CommentsController.svelte.d.ts +5 -1
  114. package/dist/plugins/comments/CommentsController.svelte.js +14 -4
  115. package/dist/plugins/find/search.js +2 -2
  116. package/dist/plugins/index.d.ts +1 -0
  117. package/dist/plugins/index.js +1 -0
  118. package/dist/plugins/richtext/RichTextPlugin.svelte +63 -61
  119. package/dist/plugins/richtext/richTextOperations.js +26 -32
  120. package/dist/plugins/suggestions/SuggestionBars.svelte +40 -23
  121. package/dist/plugins/suggestions/SuggestionBars.svelte.d.ts +3 -1
  122. package/dist/plugins/suggestions/SuggestionRuns.svelte +77 -0
  123. package/dist/plugins/suggestions/SuggestionRuns.svelte.d.ts +9 -0
  124. package/dist/plugins/suggestions/shared.svelte.d.ts +58 -0
  125. package/dist/plugins/suggestions/shared.svelte.js +421 -0
  126. package/dist/plugins/suggestions/suggestionsPlugin.d.ts +15 -4
  127. package/dist/selection/domSelection.d.ts +2 -0
  128. package/dist/selection/domSelection.js +6 -2
  129. package/dist/selection/pointer.svelte.js +75 -48
  130. package/dist/selection/replaceSelection.js +2 -6
  131. package/dist/selection/selection.svelte.d.ts +3 -3
  132. package/dist/selection/selection.svelte.js +39 -32
  133. package/dist/selection/selection.utils.d.ts +14 -0
  134. package/dist/selection/selection.utils.js +33 -11
  135. package/dist/session/commands.js +21 -11
  136. package/dist/session/composition.svelte.d.ts +5 -3
  137. package/dist/session/composition.svelte.js +21 -17
  138. package/dist/session/handles.d.ts +4 -17
  139. package/dist/session/handles.js +14 -44
  140. package/dist/session/navigation.js +6 -9
  141. package/dist/session/selection.d.ts +11 -5
  142. package/dist/session/selection.js +14 -48
  143. package/dist/session/suggestions.svelte.d.ts +38 -9
  144. package/dist/session/suggestions.svelte.js +37 -18
  145. package/dist/session/virtual.d.ts +1 -1
  146. package/dist/surface/attributes.d.ts +5 -0
  147. package/dist/surface/attributes.js +2 -2
  148. package/dist/surface/cells.d.ts +2 -26
  149. package/dist/surface/cells.js +2 -33
  150. package/dist/surface/observer.svelte.d.ts +6 -1
  151. package/dist/surface/observer.svelte.js +143 -111
  152. package/dist/surface/pin.svelte.d.ts +9 -9
  153. package/dist/surface/pin.svelte.js +15 -22
  154. package/dist/surface/projector.svelte.js +10 -16
  155. package/dist/text/text.svelte.js +14 -19
  156. package/dist/themes/notion.css +29 -0
  157. package/dist/utils.d.ts +5 -0
  158. package/dist/utils.js +7 -0
  159. package/package.json +3 -1
  160. package/dist/crdt/doc/capability.d.ts +0 -56
  161. package/dist/crdt/doc/capability.js +0 -211
  162. package/dist/crdt/doc/content.d.ts +0 -16
  163. package/dist/crdt/doc/content.js +0 -77
  164. package/dist/crdt/doc/delete.d.ts +0 -15
  165. package/dist/crdt/doc/delete.js +0 -84
  166. package/dist/crdt/doc/layout.d.ts +0 -9
  167. package/dist/crdt/doc/layout.js +0 -178
  168. package/dist/crdt/doc/meta.d.ts +0 -19
  169. package/dist/crdt/doc/meta.js +0 -199
  170. package/dist/crdt/doc/moves.d.ts +0 -21
  171. package/dist/crdt/doc/moves.js +0 -274
  172. package/dist/crdt/doc/split-merge.d.ts +0 -10
  173. package/dist/crdt/doc/split-merge.js +0 -179
  174. package/dist/crdt/doc/steps.d.ts +0 -65
  175. package/dist/crdt/doc/steps.js +0 -311
  176. package/dist/crdt/text/index/cache.d.ts +0 -16
  177. package/dist/crdt/text/index/cache.js +0 -175
  178. package/dist/crdt/text/index/claims.d.ts +0 -18
  179. package/dist/crdt/text/index/claims.js +0 -225
  180. package/dist/crdt/text/index/fold.d.ts +0 -21
  181. package/dist/crdt/text/index/fold.js +0 -656
  182. package/dist/crdt/text/index/layout.d.ts +0 -24
  183. package/dist/crdt/text/index/layout.js +0 -271
  184. package/dist/crdt/text/index/placement.d.ts +0 -47
  185. package/dist/crdt/text/index/placement.js +0 -741
  186. package/dist/crdt/text/index/records.d.ts +0 -13
  187. package/dist/crdt/text/index/records.js +0 -139
  188. package/dist/crdt/text/index/report.d.ts +0 -18
  189. package/dist/crdt/text/index/report.js +0 -337
  190. package/dist/crdt/text/index/state.d.ts +0 -197
  191. package/dist/crdt/text/index/state.js +0 -116
  192. package/dist/crdt/text/index/streams.d.ts +0 -25
  193. package/dist/crdt/text/index/streams.js +0 -248
@@ -23,18 +23,16 @@
23
23
  * `doc/types.ts` — the public types; `doc/plan.ts` — op results, a plan's
24
24
  * effect, ingress normalization.
25
25
  * - `doc/reads.ts` (`DocBase`: the doc, its engine, its index and
26
- * roles) — the reads, roles and document order; `doc/capability.ts` —
27
- * structural capability (`canPlace`, `fits`, `canMerge`, the island and
28
- * void rules).
26
+ * roles) — the reads, roles and document order.
29
27
  * - `doc/funnel.ts` — the write funnel (`write`, `apply`, attribution);
30
28
  * `doc/events.ts` — `onChange`; `doc/history.ts` —
31
29
  * `createUndoManager`; `doc/anchors.ts` — caret anchors.
32
- * - `doc/steps.ts` — the step writers every op composes (ranks, settle,
33
- * emptying, dissolving); the prepared op families over them
34
- * (`OpsContext`): `doc/moves.ts`, `doc/layout.ts`, `doc/split-merge.ts`,
35
- * `doc/delete.ts`, `doc/meta.ts` (type and data), `doc/content.ts`
36
- * (text, atoms, marks); range deletion and flow placement are
37
- * `rangeDelete.ts` and `flow.ts`.
30
+ * - `doc/ops.ts` — one closure over the reads: the structural capability
31
+ * (`canPlace`, `fits`, `canMerge`, the island and void rules), the step
32
+ * writers every op composes (ranks, settle, emptying, dissolving) and the
33
+ * prepared op families (placement, layout, split and merge, delete, type
34
+ * and data, text, atoms and marks), then range deletion and flow placement
35
+ * over them (their types in `rangeDelete.ts` and `flow.ts`).
38
36
  *
39
37
  * ── Identity discipline ────────────────────────────────────────────────
40
38
  *
@@ -56,24 +54,15 @@ import { bindPurge, readHorizon } from './purge.js';
56
54
  import { restoreDocument } from './restore.js';
57
55
  import { bindRuns, indexOf } from './text/runs.js';
58
56
  import { bindBlockAttribution, blockAttributionOf } from './attribution/block.js';
59
- import { rangeDeleteOps } from './rangeDelete.js';
60
- import { flowOps } from './flow.js';
61
57
  import { assertSchema, checkSchema, isInitialized, META_KEY, registryEmpty, SCHEMA_NAME, SCHEMA_VERSION, SchemaMismatchError, schemaVersion } from './doc/gate.js';
62
58
  import { bindSeed, restore } from './doc/seed.js';
63
59
  import { applied, ref } from './doc/plan.js';
64
60
  import { docReads } from './doc/reads.js';
65
- import { docCapability } from './doc/capability.js';
66
61
  import { writeFunnel } from './doc/funnel.js';
67
62
  import { docEvents } from './doc/events.js';
68
63
  import { docHistory } from './doc/history.js';
69
64
  import { docAnchors } from './doc/anchors.js';
70
- import { planSteps } from './doc/steps.js';
71
- import { moveOps } from './doc/moves.js';
72
- import { layoutOps } from './doc/layout.js';
73
- import { splitMergeOps } from './doc/split-merge.js';
74
- import { deleteOps } from './doc/delete.js';
75
- import { metaOps } from './doc/meta.js';
76
- import { contentOps } from './doc/content.js';
65
+ import { docOps } from './doc/ops.js';
77
66
  // ── schema manifest and gate (`doc/gate.ts`) ────────────────────────────
78
67
  export { SCHEMA };
79
68
  export { assertSchema, checkSchema, isInitialized, META_KEY, registryEmpty, SCHEMA_NAME, SCHEMA_VERSION, SchemaMismatchError, schemaVersion };
@@ -105,7 +94,7 @@ export const docFacade = (Y, layers) => {
105
94
  // per-doc (WeakMap-keyed), so facades on the same doc share it.
106
95
  const BA = bindBlockAttribution(Y);
107
96
  const { init, seed } = bindSeed(Y, BA);
108
- return (doc, config = {}) => {
97
+ const create = (doc, config = {}) => {
109
98
  adoptRules(doc);
110
99
  setMarkEdges(doc, config.markEdge ?? (() => undefined));
111
100
  const roleOf = config.roleOf ?? (() => undefined);
@@ -123,30 +112,52 @@ export const docFacade = (Y, layers) => {
123
112
  // A layout displays only its items — its
124
113
  // `defaultChild` kind — and only two or more (`layout.*`). A table
125
114
  // displays only its rows and a row only its cells (`table.*`).
115
+ let kinds = new Map();
116
+ let declared;
126
117
  const roles = {
127
- childless: (type) => roleOf(type)?.void === true,
128
- island: (type) => roleOf(type)?.island === true,
129
- container: (type) => !rendersContentOf(type) && roleOf(type)?.void !== true && roleOf(type)?.island !== true,
130
- rendersContent: (type) => rendersContentOf(type),
131
- defaultChild: (type) => (type !== null ? defaultChildOf(type) : undefined) ?? defaultType,
132
- line: (type) => {
133
- const role = roleOf(type);
134
- return role?.island === true && role.lines === true ? defaultChildOf(type) : undefined;
118
+ of: (type) => {
119
+ let k = kinds.get(type);
120
+ if (k === undefined) {
121
+ const role = type === null ? undefined : roleOf(type);
122
+ const own = type === null ? undefined : defaultChildOf(type);
123
+ const renders = type === null || rendersContentOf(type);
124
+ kinds.set(type, (k = {
125
+ childless: role?.void === true,
126
+ island: role?.island === true,
127
+ container: !renders && role?.void !== true && role?.island !== true,
128
+ rendersContent: renders,
129
+ child: own ?? defaultType,
130
+ line: role?.island === true && role.lines === true ? own : undefined,
131
+ layout: role?.layout === true ? own : undefined,
132
+ table: role?.table === true ? own : undefined
133
+ }));
134
+ }
135
+ return k;
135
136
  },
136
- lineKinds: () => [...(config.kinds?.() ?? [])].flatMap((type) => roles.line(type) ?? []),
137
- layout: (type) => (roleOf(type)?.layout === true ? defaultChildOf(type) : undefined),
138
- layoutKinds: () => [...(config.kinds?.() ?? [])].filter((type) => roles.layout(type) !== undefined),
139
- table: (type) => (roleOf(type)?.table === true ? defaultChildOf(type) : undefined),
140
- tableKinds: () => [...(config.kinds?.() ?? [])].filter((type) => roles.table(type) !== undefined)
137
+ declared: () => {
138
+ if (declared === undefined) {
139
+ const all = [...(config.kinds?.() ?? [])].map(roles.of);
140
+ const rows = new Map(all.flatMap((k) => (k.table ? [[k.table, roles.of(k.table).child]] : [])));
141
+ declared = {
142
+ lines: new Set(all.flatMap((k) => k.line ?? [])),
143
+ layouts: [...(config.kinds?.() ?? [])].filter((t) => roles.of(t).layout !== undefined),
144
+ items: new Set(all.flatMap((k) => k.layout ?? [])),
145
+ rows,
146
+ cells: new Set(rows.values())
147
+ };
148
+ }
149
+ return declared;
150
+ }
141
151
  };
142
152
  if (config.roleOf)
143
153
  runsView.roles(roles);
144
154
  // The facade's parts, each over the ones before it (`doc/*`).
145
155
  const base = { Y, doc, runsView, roles, roleOf, rendersContentOf };
146
156
  const reads = { ...base, ...docReads(base) };
147
- const shape = { ...reads, ...docCapability(reads) };
157
+ // The capability, the step writers and the prepared op families (`doc/ops.ts`).
158
+ const ops = { ...reads, ...docOps(reads) };
148
159
  const { blockJSON, view, blockTypeOf, blockDataOf, docData, dataItemIds, dataPreview, childrenIds, positionOf, pathOf, ancestorsOf, slotOf, isVoid, isIsland, isLines, islandOf, insideIsland, isLayout, isLayoutItem, order, compare, next, previous, displayLength, contentItems, hasBlock, live } = reads;
149
- const { canPlace, fits, nestParent, canMerge, defaultChild } = shape;
160
+ const { canPlace, fits, nestParent, canMerge, defaultChild, plan, landingOf, besideAt } = ops;
150
161
  const funnel = writeFunnel({ ...reads, BA, config });
151
162
  const { write, apply } = funnel;
152
163
  const events = docEvents({ runsView });
@@ -157,53 +168,34 @@ export const docFacade = (Y, layers) => {
157
168
  };
158
169
  const { createUndoManager } = docHistory({ ...base, ...funnel, init });
159
170
  const { anchorAt, followUndo, resolveAnchor } = docAnchors(reads);
160
- const steps = { ...shape, ...planSteps(shape) };
161
- const { plan } = steps;
162
- // The prepared op families (`OpsContext`: the reads, capability and step writers).
163
- const { insertBlocks, moveBlocks, unNestBlocks, unNestBlock, landingOf, liftOut, duplicateBlock } = moveOps(steps);
164
- const { besideAt, placeBeside, wrapInLayout } = layoutOps(steps);
165
- const { splitBlock, mergeBlocks, mergeBackward, mergeForward } = splitMergeOps(steps);
166
- const { deleteBlocks, deleteBlock } = deleteOps(steps);
167
- const { dataSteps, replaceData, setBlockType, patchData, setBlock } = metaOps(steps);
168
- const { insertText, deleteText, formatRange, clearMarks, insertInline, removeInline } = contentOps(steps);
169
- /** What range deletion and flow placement compose: the step writers and the ops. */
170
- const ops = { ...steps, insertBlocks, deleteBlocks, dataSteps, replaceData };
171
171
  /** Every document op, prepared — `apply(prepare.op(…))` is the op. */
172
172
  const prepare = {
173
- insertBlocks,
174
- moveBlocks,
173
+ ...ops.prepare,
175
174
  /**
176
175
  * Move `id` to the last position under `parent` — under a container
177
176
  * it is no item of, under its last item (`nestParent`: Tab after a list).
178
177
  */
179
178
  nestBlock: (id, parent) => {
180
179
  const at = nestParent([ref(id)], ref(parent));
181
- return moveBlocks([id], { parent: at, index: childrenIds(at).length });
180
+ return ops.prepare.moveBlocks([id], { parent: at, index: childrenIds(at).length });
182
181
  },
183
- unNestBlock,
184
- unNestBlocks,
185
- liftOut,
186
- placeBeside,
187
- wrapInLayout,
188
- splitBlock,
189
- mergeBlocks,
190
- mergeBackward,
191
- mergeForward,
192
- deleteBlock,
193
- setBlock,
194
- setBlockType,
195
- patchData,
196
- duplicateBlock,
197
- insertText,
198
- deleteText,
199
- formatRange,
200
- clearMarks,
201
- insertInline,
202
- removeInline,
203
182
  /** Delete a block selection — one plan; only the members leave (`deleteBlocks` above). */
204
- deleteBlocks: (ids) => deleteBlocks(ids),
205
- ...rangeDeleteOps(ops),
206
- ...flowOps(ops)
183
+ deleteBlocks: (ids) => ops.prepare.deleteBlocks(ids)
184
+ };
185
+ /**
186
+ * What a part built over this document reads beyond the facade (the
187
+ * shared suggestions, `doc/suggest.ts`): the reads, a facade over
188
+ * another doc (`create`, with this `config`);
189
+ * `v` counts its changes no index fact shows (in `version`), and
190
+ * `base`, when set, is the export `toJSON()` gives unless asked for
191
+ * the suggestions.
192
+ */
193
+ const part = {
194
+ ...reads,
195
+ config,
196
+ create: create,
197
+ v: 0,
198
+ base: undefined
207
199
  };
208
200
  /**
209
201
  * Plans prepared at one version, as one plan (refused if any part is;
@@ -226,7 +218,11 @@ export const docFacade = (Y, layers) => {
226
218
  * omitted when empty): the one serializer, {@link blockJSON}, over the
227
219
  * root's visible children.
228
220
  */
229
- const toJSON = () => {
221
+ const toJSON = (options) => {
222
+ // A part's export first (the shared suggestions': without the pending ones, `sugg.json.base`).
223
+ const base = !options?.suggestions && part.base?.();
224
+ if (base)
225
+ return base;
230
226
  const data = docData();
231
227
  const children = childrenIds(null).map(blockJSON);
232
228
  return Object.keys(data).length > 0
@@ -236,32 +232,17 @@ export const docFacade = (Y, layers) => {
236
232
  // ── facade object ─────────────────────────────────────────────────
237
233
  /** A read taking an id first: the id normalizes at ingress. */
238
234
  const byRef = (f) => (id, ...rest) => f(ref(id), ...rest);
239
- const facade = {
240
- // lifecycle
241
- init: (opts) => write(() => init(doc, opts)),
242
- /** Apply the deterministic seed of `value` and the document's `data` — the document's seed decision. */
243
- seed: (value, data) => write(() => seed(doc, value, defaultType, data)),
244
- isInitialized: () => isInitialized(doc),
245
- /** Replicated `meta.v` schema version (the module-level read, bound). */
246
- schemaVersion: () => schemaVersion(doc),
247
- /**
248
- * The schema gate for this doc — throws {@link SchemaMismatchError}
249
- * on unversioned-content or unsupported-version state. Consumers
250
- * (`Edytor.sync()`, packed consumers) call it before trusting
251
- * a synced doc.
252
- */
253
- checkSchema: () => checkSchema(doc),
254
- assertSchema: () => assertSchema(doc),
255
- dispose,
256
- createUndoManager,
235
+ /**
236
+ * The public operations (`DocumentOperations`), each name once: what
237
+ * an `EdytorDocument` forwards. The facade has them and the internal
238
+ * members below.
239
+ */
240
+ const api = {
257
241
  // reads — every id argument normalizes at ingress
258
242
  project: () => project(doc),
259
243
  toJSON,
260
244
  blockJSON: byRef(blockJSON),
261
245
  childrenIds: byRef(childrenIds),
262
- /** Visible children of `parent` with their ranks, in `(rank, id)` order. */
263
- childSlots: (parent) => view().kids.get(parent) ?? [],
264
- slotOf: byRef(slotOf),
265
246
  positionOf: byRef(positionOf),
266
247
  pathOf: byRef(pathOf),
267
248
  parentOf: byRef((id) => positionOf(id)?.parent ?? null),
@@ -279,8 +260,6 @@ export const docFacade = (Y, layers) => {
279
260
  * O(1) per call; live-replicated (remote values read the same).
280
261
  */
281
262
  blockAttribution: byRef((id) => blockAttributionOf(doc, id)),
282
- crdtId: byRef((id) => crdtId(doc, id)),
283
- resolveBlock: byRef((id) => resolveBlock(doc, id)),
284
263
  displayLength: byRef(displayLength),
285
264
  contentItems: byRef(contentItems),
286
265
  hasBlock: byRef(hasBlock),
@@ -292,10 +271,6 @@ export const docFacade = (Y, layers) => {
292
271
  // caret anchors — backing-text-bound selection endpoints
293
272
  anchorAt: byRef(anchorAt),
294
273
  resolveAnchor,
295
- followUndo,
296
- // roles
297
- /** Re-read the roles after `roleOf` answers differently (roles adopted later). */
298
- rolesChanged: () => runsView.roles(roles),
299
274
  isVoid: byRef(isVoid),
300
275
  isIsland: byRef(isIsland),
301
276
  isLines: byRef(isLines),
@@ -331,10 +306,8 @@ export const docFacade = (Y, layers) => {
331
306
  nestParent: (ids, parent) => nestParent(ids.map(ref), ref(parent)),
332
307
  /** Where a block of `kind` at `id`'s place lands, and the containers it leaves (`liftOut`). */
333
308
  landingOf: (id, kind, after) => landingOf(ref(id), ref(kind), after),
334
- defaultChild: byRef(defaultChild),
335
309
  // maintained runs (bound to this doc)
336
310
  runs: byRef(runsView.runs),
337
- contentJSON: byRef(runsView.contentJSON),
338
311
  // events
339
312
  onChange,
340
313
  // every op — each returns an {@link OpResult}; `apply(prepare.op(…))`
@@ -347,10 +320,6 @@ export const docFacade = (Y, layers) => {
347
320
  // transactions (composed ops already run in one; expose for callers
348
321
  // that batch several ops into one undo step / one event)
349
322
  transact: (fn, origin) => write(() => doc.transact(fn, origin)),
350
- // escape hatch for the history and debugging — the bound engine layers.
351
- model: layers.model,
352
- text: layers.text,
353
- runsView,
354
323
  // ── model-state version ─────────────────────────────
355
324
  /**
356
325
  * The index version — bumps on every fold that changed derived
@@ -359,11 +328,57 @@ export const docFacade = (Y, layers) => {
359
328
  * post-write state — this is the read-your-writes contract.
360
329
  */
361
330
  get version() {
362
- return runsView.version();
331
+ // A part's change may show in no index fact (a suggestion's decision).
332
+ return runsView.version() + part.v;
363
333
  }
364
334
  };
365
- return facade;
335
+ const internal = {
336
+ // lifecycle
337
+ init: (opts) => write(() => init(doc, opts)),
338
+ /** Apply the deterministic seed of `value` and the document's `data` — the document's seed decision. */
339
+ seed: (value, data) => write(() => seed(doc, value, defaultType, data)),
340
+ isInitialized: () => isInitialized(doc),
341
+ /** Replicated `meta.v` schema version (the module-level read, bound). */
342
+ schemaVersion: () => schemaVersion(doc),
343
+ /**
344
+ * The schema gate for this doc — throws {@link SchemaMismatchError}
345
+ * on unversioned-content or unsupported-version state. Consumers
346
+ * (`Edytor.sync()`, packed consumers) call it before trusting
347
+ * a synced doc.
348
+ */
349
+ checkSchema: () => checkSchema(doc),
350
+ assertSchema: () => assertSchema(doc),
351
+ dispose,
352
+ createUndoManager,
353
+ /** @internal What a part built over the document reads and writes (`doc/suggest.ts`). */
354
+ part,
355
+ /** Visible children of `parent` with their ranks, in `(rank, id)` order. */
356
+ childSlots: (parent) => view().kids.get(parent) ?? [],
357
+ slotOf: byRef(slotOf),
358
+ crdtId: byRef((id) => crdtId(doc, id)),
359
+ resolveBlock: byRef((id) => resolveBlock(doc, id)),
360
+ followUndo,
361
+ // roles
362
+ /** Re-read the roles after `roleOf` answers differently (roles adopted later). */
363
+ rolesChanged: (place = true) => {
364
+ kinds = new Map();
365
+ declared = undefined;
366
+ if (place)
367
+ runsView.roles(roles);
368
+ },
369
+ defaultChild: byRef(defaultChild),
370
+ contentJSON: byRef(runsView.contentJSON),
371
+ // escape hatch for the history and debugging — the bound engine layers.
372
+ model: layers.model,
373
+ text: layers.text,
374
+ runsView,
375
+ /** The public members' names (`EdytorDocument` forwards them). */
376
+ api: api
377
+ };
378
+ // The public members joined as they are (the `version` getter stays one).
379
+ return Object.defineProperties(internal, Object.getOwnPropertyDescriptors(api));
366
380
  };
381
+ return create;
367
382
  };
368
383
  /**
369
384
  * Bind the assembled model to a concrete engine surface. `Y` must be the
@@ -78,9 +78,15 @@ export interface EngineNode {
78
78
  * Delete `length` live units at `index`. With `into` (the document's
79
79
  * records list), they are held by one record appended there instead (a
80
80
  * delete its writer can take back), except those `fresh` names, which are
81
- * removed.
81
+ * removed. With `propose` (a suggestion's delete), each
82
+ * unit is sorted: `1` held as above (its author's own), `2` proposed (an
83
+ * id list appended to `propose.into`) or `3` stepped over; proposed and
84
+ * stepped-over units read gone until the engine's `unhide`.
82
85
  */
83
- delete(index: number, length?: number, into?: EngineNode | null, fresh?: unknown): void;
86
+ delete(index: number, length?: number, into?: EngineNode | null, fresh?: unknown, propose?: {
87
+ into: EngineNode;
88
+ sort: (client: number, clock: number) => number;
89
+ } | null): void;
84
90
  /** Append one hold record of `ids` (`client, clock, len` triples) to this records list: they read as deleted while it lives. */
85
91
  hold(ids: number[]): void;
86
92
  /**
@@ -30,6 +30,7 @@ export type EngineSymbol =
30
30
  | 'followRedone'
31
31
  | 'isParentOf'
32
32
  | 'mergeIdSets'
33
- | 'createID';
33
+ | 'createID'
34
+ | 'unhide';
34
35
 
35
36
  export declare const Y: Pick<typeof V, EngineSymbol>;
@@ -45,5 +45,7 @@ export const Y = {
45
45
  followRedone: V.followRedone,
46
46
  isParentOf: V.isParentOf,
47
47
  mergeIdSets: V.mergeIdSets,
48
- createID: V.createID
48
+ createID: V.createID,
49
+ // a suggestion's proposed deletion reads gone until its plan ends (fork patch YP32)
50
+ unhide: V.unhide
49
51
  };
@@ -1,47 +1,9 @@
1
1
  /**
2
- * Placement of an admitted flow — one prepared document operation for
3
- * paste, drop and fragment insertion. The rules are the `flow.*` rows of
4
- * `docs/editor-delete-contract.md`:
5
- *
6
- * - a flow is lines with fresh ids: a kinded block, or an inline run (no
7
- * `type`); an empty flow changes nothing (`flow.shape`);
8
- * - one line joins the text at the position; an empty block takes a kinded
9
- * line's kind (`flow.inline`);
10
- * - several lines split the block: the first joins the head, the last is the
11
- * tail's block and takes the text after the position and the block's
12
- * children, the rest go between (`flow.split`) — children the view
13
- * hides (a closed toggle's body) stay with the head, as Enter keeps them;
14
- * - a line that joins no text (a list, a code block, a divider: it renders
15
- * none of its own, or is a void or an island) is placed as a block, never
16
- * joined; the text after the position stays in a shown line of the
17
- * block's kind (`flow.apart`), and the caret ends the last pasted
18
- * shown line;
19
- * - in a code line (a `lines` island) the lines, nested ones included, are
20
- * placed as plain lines (`flow.lines`);
21
- * - a `whole` flow (a block-selection copy) goes after the block, replacing
22
- * it when empty (`flow.whole`); over selected blocks the lines take their
23
- * slot (`flow.slot`), and at a slot they are placed with nothing replaced
24
- * (`flow.place`: an accepted suggestion), as plain inserts (`insertBlocks`: their order
25
- * against a peer's split beside them is not claimed); a void
26
- * takes one run (`flow.void`);
27
- * - a table's cell is never split: it takes the lines a flow shows, nested
28
- * ones and a pasted table's cells included, as one text joined by line
29
- * breaks; a cell outside a row (cells copied out of a table) is a line of
30
- * text, and a row outside a table its cells (`table.paste`);
31
- * - a plain line that lands directly in a container takes its item kind
32
- * (the document's `fitted`: a pasted paragraph in a list is its item),
33
- * and so does a line of the list's flat item kind (the view's
34
- * `itemKind`: a pasted numbered item in an `ordered-list`); any
35
- * other kind keeps its kind and data (a pasted image stays an image, a
36
- * bulleted item in an `ordered-list` a bulleted item).
2
+ * The types flow placement (`insertFlow`: the `flow.*` rows, prepared in
3
+ * `doc/ops.ts`) reads, and where the caret ends a placed block.
37
4
  */
38
5
  import type { BlockId, BlockSpec, Destination } from './placement/model.js';
39
- import type { Prepared } from './edytor-doc.js';
40
6
  import type { DocPosition, RangeView } from './rangeDelete.js';
41
- import type { OpsContext } from './doc/steps.js';
42
- import type { MoveOps } from './doc/moves.js';
43
- import type { DeleteOps } from './doc/delete.js';
44
- import type { MetaOps } from './doc/meta.js';
45
7
  /** One line of a flow: a kinded block, or an inline run when it has no `type`. */
46
8
  export type FlowLine = Omit<BlockSpec, 'type'> & {
47
9
  type?: string;
@@ -72,8 +34,8 @@ export type FlowTarget = DocPosition | {
72
34
  } | {
73
35
  slot: Destination;
74
36
  };
75
- /** What flow placement composes: the step writers and the ops it places and deletes with. */
76
- export type FlowContext = OpsContext & Pick<MoveOps, 'insertBlocks'> & Pick<DeleteOps, 'deleteBlocks'> & Pick<MetaOps, 'dataSteps' | 'replaceData'>;
37
+ /** The units of a line's content (an atom counts 1). */
38
+ export declare const lengthOf: (l: FlowLine) => number;
77
39
  /**
78
40
  * Where the caret ends a placed block: its own content's end when it shows a
79
41
  * line (renders its content, no void; a toggle's header, never its body),
@@ -82,10 +44,6 @@ export type FlowContext = OpsContext & Pick<MoveOps, 'insertBlocks'> & Pick<Dele
82
44
  * paragraph (`doc.empty.virtual`) place the caret by it.
83
45
  */
84
46
  export declare const placedEnd: (roleOf: (kind: string) => {
85
- void: boolean;
47
+ childless: boolean;
86
48
  rendersContent: boolean;
87
49
  }) => (s: BlockSpec) => DocPosition | undefined;
88
- /** `insertFlow`, prepared. */
89
- export declare const flowOps: (c: FlowContext) => {
90
- insertFlow: (target: FlowTarget, flow: Flow, view?: FlowView) => Prepared;
91
- };