edytor 1.0.0 → 3.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 (287) hide show
  1. package/README.md +26 -69
  2. package/dist/block/block.svelte.d.ts +6 -4
  3. package/dist/block/block.svelte.js +12 -8
  4. package/dist/block/inlineBlock.svelte.d.ts +6 -2
  5. package/dist/block/inlineBlock.svelte.js +7 -2
  6. package/dist/clipboard/htmlFlow.d.ts +20 -7
  7. package/dist/clipboard/htmlFlow.js +23 -15
  8. package/dist/clipboard/serializeClipboardFragment.d.ts +37 -4
  9. package/dist/clipboard/serializeClipboardFragment.js +6 -4
  10. package/dist/clipboard/textBlocks.d.ts +8 -0
  11. package/dist/clipboard/textBlocks.js +6 -2
  12. package/dist/cloudflare/room/admission.js +3 -3
  13. package/dist/cloudflare/room/context.d.ts +7 -1
  14. package/dist/cloudflare/routeDocumentSocket.d.ts +17 -0
  15. package/dist/cloudflare/routeDocumentSocket.js +53 -0
  16. package/dist/collaboration/awarenessSelection.d.ts +22 -1
  17. package/dist/collaboration/awarenessSelection.js +42 -0
  18. package/dist/collaboration/comments/client.d.ts +1 -1
  19. package/dist/collaboration/comments/client.js +1 -1
  20. package/dist/collaboration/remoteSelection.js +3 -3
  21. package/dist/components/Block.svelte +3 -1
  22. package/dist/components/Edytor.svelte +38 -20
  23. package/dist/components/Edytor.svelte.d.ts +9 -4
  24. package/dist/components/InlineBlock.svelte +1 -1
  25. package/dist/crdt/admission.d.ts +5 -10
  26. package/dist/crdt/admission.js +5 -11
  27. package/dist/crdt/data.d.ts +10 -0
  28. package/dist/crdt/data.js +20 -2
  29. package/dist/crdt/doc/funnel.d.ts +7 -6
  30. package/dist/crdt/doc/funnel.js +10 -9
  31. package/dist/crdt/doc/gate.d.ts +0 -17
  32. package/dist/crdt/doc/gate.js +2 -41
  33. package/dist/crdt/doc/history.js +2 -2
  34. package/dist/crdt/doc/reads.d.ts +7 -0
  35. package/dist/crdt/doc/reads.js +11 -1
  36. package/dist/crdt/document.d.ts +13 -14
  37. package/dist/crdt/document.js +17 -19
  38. package/dist/crdt/edytor-doc.d.ts +22 -4
  39. package/dist/crdt/edytor-doc.js +5 -8
  40. package/dist/crdt/index.d.ts +9 -3
  41. package/dist/crdt/index.js +2 -2
  42. package/dist/crdt/operations.d.ts +1 -1
  43. package/dist/crdt/operations.js +1 -0
  44. package/dist/crdt/props.d.ts +32 -0
  45. package/dist/crdt/props.js +172 -0
  46. package/dist/crdt/protocol.d.ts +2 -2
  47. package/dist/crdt/protocol.js +2 -2
  48. package/dist/crdt/providers/index.d.ts +1 -1
  49. package/dist/crdt/providers/room.d.ts +10 -9
  50. package/dist/crdt/providers/room.js +13 -10
  51. package/dist/crdt/providers/websocket.d.ts +1 -1
  52. package/dist/crdt/providers/websocket.js +28 -29
  53. package/dist/crdt/semantics.js +3 -1
  54. package/dist/dnd/autoScroll.d.ts +15 -7
  55. package/dist/dnd/autoScroll.js +10 -15
  56. package/dist/{plugins/blockHandles → dnd}/dropIndicator.d.ts +2 -2
  57. package/dist/{plugins/blockHandles → dnd}/dropIndicator.js +2 -5
  58. package/dist/dnd/external.d.ts +6 -0
  59. package/dist/dnd/external.js +17 -0
  60. package/dist/{plugins/blockHandles → dnd}/geometry.d.ts +4 -2
  61. package/dist/{plugins/blockHandles → dnd}/geometry.js +3 -4
  62. package/dist/dnd/placement.d.ts +200 -0
  63. package/dist/dnd/placement.js +426 -0
  64. package/dist/dnd/pragmatic.d.ts +3 -1
  65. package/dist/dnd/pragmatic.js +12 -2
  66. package/dist/dnd/vendor/pragmatic/UPSTREAM.md +51 -18
  67. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.d.ts +4 -0
  68. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js +6 -0
  69. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.d.ts +0 -2
  70. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/element-adapter.js +4 -22
  71. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter-types.d.ts +26 -0
  72. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.d.ts +30 -0
  73. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/external-adapter.js +203 -0
  74. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-items.js +13 -0
  75. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/get-available-types.js +9 -0
  76. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/is-an-available-type.js +19 -0
  77. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.d.ts +4 -0
  78. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/adapter/monitor-for-external.js +6 -0
  79. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/honey-pot-fix/make-honey-pot-fix.js +4 -16
  80. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/internal-types.d.ts +1 -8
  81. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-drop-target.js +5 -6
  82. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/make-adapter/make-monitor.js +2 -3
  83. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.d.ts +1 -1
  84. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/element/custom-native-drag-preview/set-custom-native-drag-preview.js +6 -24
  85. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.d.ts +2 -0
  86. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js +5 -0
  87. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.d.ts +3 -0
  88. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js +12 -0
  89. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/native-types.d.ts +12 -0
  90. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window-in-safari.js +10 -0
  91. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/changing-window/is-entering-window.js +55 -0
  92. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.d.ts +4 -0
  93. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.js +8 -0
  94. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/internal-types.d.ts +0 -4
  95. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/get-scroll-by.js +16 -72
  96. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/over-element/try-scroll.js +1 -9
  97. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/configuration.js +4 -29
  98. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/get-scroll-change.js +2 -3
  99. package/dist/edytor.svelte.d.ts +19 -9
  100. package/dist/edytor.svelte.js +28 -33
  101. package/dist/events/beforeInputCommands.d.ts +2 -2
  102. package/dist/events/beforeInputCommands.js +8 -4
  103. package/dist/events/onBeforeInput.js +1 -1
  104. package/dist/events/onDrop.js +25 -10
  105. package/dist/events/onInput.d.ts +0 -12
  106. package/dist/events/onInput.js +1 -67
  107. package/dist/events/onPaste.d.ts +2 -1
  108. package/dist/events/onPaste.js +8 -3
  109. package/dist/export/forms.d.ts +627 -0
  110. package/dist/export/forms.js +749 -0
  111. package/dist/export/index.d.ts +170 -0
  112. package/dist/export/index.js +161 -0
  113. package/dist/export/markdown.d.ts +41 -0
  114. package/dist/export/markdown.js +585 -0
  115. package/dist/export/markdownWriter.d.ts +9 -0
  116. package/dist/export/markdownWriter.js +133 -0
  117. package/dist/export/mdx.d.ts +15 -0
  118. package/dist/export/mdx.js +33 -0
  119. package/dist/index.d.ts +4 -4
  120. package/dist/index.js +2 -2
  121. package/dist/kinds.js +1 -1
  122. package/dist/labels.d.ts +2 -0
  123. package/dist/labels.js +2 -1
  124. package/dist/plugins/anchored.svelte.d.ts +21 -25
  125. package/dist/plugins/anchored.svelte.js +23 -39
  126. package/dist/plugins/arrowMove/arrowMove.d.ts +1 -1
  127. package/dist/plugins/arrowMove/arrowMove.js +1 -1
  128. package/dist/plugins/blockHandles/BlockHandleController.svelte.d.ts +2 -122
  129. package/dist/plugins/blockHandles/BlockHandleController.svelte.js +48 -414
  130. package/dist/plugins/blockHandles/BlockHandles.svelte +14 -32
  131. package/dist/plugins/blockHandles/blockHandlesPlugin.js +2 -1
  132. package/dist/plugins/blockHandles/dragPreview.d.ts +26 -7
  133. package/dist/plugins/blockHandles/dragPreview.js +33 -0
  134. package/dist/plugins/blockMenu/BlockMenuController.svelte.d.ts +5 -0
  135. package/dist/plugins/blockMenu/BlockMenuController.svelte.js +7 -2
  136. package/dist/plugins/blockMenu/blockMenuPlugin.js +5 -50
  137. package/dist/plugins/chrome.d.ts +27 -5
  138. package/dist/plugins/chrome.js +24 -9
  139. package/dist/plugins/code/CodeHeader.svelte +5 -3
  140. package/dist/plugins/code/CodePlugin.svelte +15 -12
  141. package/dist/plugins/code/header.svelte.js +7 -11
  142. package/dist/plugins/code/languageMenu.svelte.d.ts +5 -2
  143. package/dist/plugins/code/languageMenu.svelte.js +13 -20
  144. package/dist/plugins/code/languages.d.ts +0 -3
  145. package/dist/plugins/code/languages.js +0 -2
  146. package/dist/plugins/columns/ColumnResize.svelte +3 -2
  147. package/dist/plugins/columns/ColumnsPlugin.svelte +8 -21
  148. package/dist/plugins/columns/gaps.d.ts +7 -5
  149. package/dist/plugins/columns/gaps.js +11 -6
  150. package/dist/plugins/columns/resize.svelte.d.ts +5 -6
  151. package/dist/plugins/columns/resize.svelte.js +12 -14
  152. package/dist/plugins/comments/CommentsController.svelte.d.ts +6 -0
  153. package/dist/plugins/comments/CommentsController.svelte.js +20 -0
  154. package/dist/plugins/equation/EquationPlugin.svelte +13 -30
  155. package/dist/plugins/equation/EquationPlugin.svelte.d.ts +1 -0
  156. package/dist/plugins/equation/equation.css +7 -0
  157. package/dist/plugins/equation/equation.svelte.d.ts +7 -15
  158. package/dist/plugins/equation/equation.svelte.js +13 -50
  159. package/dist/plugins/equation/tex.d.ts +17 -0
  160. package/dist/plugins/equation/tex.js +42 -0
  161. package/dist/plugins/fileDrop.d.ts +43 -0
  162. package/dist/plugins/fileDrop.js +122 -0
  163. package/dist/plugins/find/FindController.svelte.d.ts +5 -0
  164. package/dist/plugins/find/FindController.svelte.js +14 -14
  165. package/dist/plugins/find/findPlugin.js +1 -15
  166. package/dist/plugins/image/ImageChrome.svelte +8 -2
  167. package/dist/plugins/image/ImagePlugin.svelte +56 -84
  168. package/dist/plugins/image/ImagePlugin.svelte.d.ts +13 -1
  169. package/dist/plugins/image/controls.svelte.js +16 -2
  170. package/dist/plugins/image/image.css +17 -0
  171. package/dist/plugins/image/toolbar.svelte.d.ts +5 -4
  172. package/dist/plugins/image/toolbar.svelte.js +21 -31
  173. package/dist/plugins/index.d.ts +4 -5
  174. package/dist/plugins/index.js +0 -1
  175. package/dist/plugins/list.svelte.d.ts +9 -0
  176. package/dist/plugins/list.svelte.js +18 -0
  177. package/dist/plugins/markdownShortcuts.js +5 -5
  178. package/dist/plugins/marquee/marqueePlugin.js +0 -4
  179. package/dist/plugins/media/AudioPlugin.svelte +13 -1
  180. package/dist/plugins/media/AudioPlugin.svelte.d.ts +11 -1
  181. package/dist/plugins/media/BookmarkPlugin.svelte +6 -97
  182. package/dist/plugins/media/EmbedPlugin.svelte +5 -90
  183. package/dist/plugins/media/EmptySlot.svelte +36 -20
  184. package/dist/plugins/media/EmptySlot.svelte.d.ts +6 -15
  185. package/dist/plugins/media/FilePlugin.svelte +12 -20
  186. package/dist/plugins/media/FilePlugin.svelte.d.ts +9 -0
  187. package/dist/plugins/media/MediaEmpty.svelte +2 -55
  188. package/dist/plugins/media/MediaEmpty.svelte.d.ts +18 -14
  189. package/dist/plugins/media/SourceBlock.svelte +178 -52
  190. package/dist/plugins/media/SourceBlock.svelte.d.ts +13 -6
  191. package/dist/plugins/media/UploadPreview.svelte +32 -0
  192. package/dist/plugins/media/UploadPreview.svelte.d.ts +11 -0
  193. package/dist/plugins/media/VideoPlugin.svelte +13 -1
  194. package/dist/plugins/media/VideoPlugin.svelte.d.ts +11 -1
  195. package/dist/plugins/media/empty.svelte.d.ts +13 -4
  196. package/dist/plugins/media/empty.svelte.js +32 -26
  197. package/dist/plugins/media/media.d.ts +9 -63
  198. package/dist/plugins/media/media.js +1 -194
  199. package/dist/plugins/media/sources.d.ts +60 -0
  200. package/dist/plugins/media/sources.js +165 -0
  201. package/dist/plugins/media/upload.css +23 -0
  202. package/dist/plugins/media/urlPaste.svelte.d.ts +2 -1
  203. package/dist/plugins/media/urlPaste.svelte.js +12 -21
  204. package/dist/plugins/mention/MentionPlugin.svelte +50 -38
  205. package/dist/plugins/mention/MentionPlugin.svelte.d.ts +11 -2
  206. package/dist/plugins/mention/mention.css +6 -0
  207. package/dist/plugins/page/PagePlugin.svelte +2 -9
  208. package/dist/plugins/page/page.js +1 -1
  209. package/dist/plugins/pageLink/PageLinkPlugin.svelte +126 -28
  210. package/dist/plugins/pageLink/PageLinkPlugin.svelte.d.ts +13 -1
  211. package/dist/plugins/pageLink/pageLink.css +6 -0
  212. package/dist/plugins/richtext/RichTextPlugin.svelte +99 -204
  213. package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +1 -0
  214. package/dist/plugins/richtext/body.js +1 -1
  215. package/dist/plugins/richtext/calloutIcons.svelte.d.ts +2 -2
  216. package/dist/plugins/richtext/calloutIcons.svelte.js +5 -7
  217. package/dist/plugins/richtext/richTextOperations.d.ts +1 -19
  218. package/dist/plugins/richtext/richTextOperations.js +3 -49
  219. package/dist/plugins/richtext/richtext.css +6 -0
  220. package/dist/plugins/slashMenu/SlashMenuController.svelte.d.ts +2 -0
  221. package/dist/plugins/slashMenu/SlashMenuController.svelte.js +7 -0
  222. package/dist/plugins/slashMenu/slashMenuPlugin.js +5 -14
  223. package/dist/plugins/table/TableChrome.svelte +2 -3
  224. package/dist/plugins/table/TablePlugin.svelte +20 -54
  225. package/dist/plugins/table/chrome.svelte.d.ts +5 -2
  226. package/dist/plugins/table/chrome.svelte.js +33 -56
  227. package/dist/plugins/table/table.js +3 -3
  228. package/dist/plugins/toc/TocPlugin.svelte +2 -4
  229. package/dist/plugins/toolbar/ToolbarController.svelte.d.ts +7 -0
  230. package/dist/plugins/toolbar/ToolbarController.svelte.js +20 -13
  231. package/dist/plugins/toolbar/toolbarPlugin.js +19 -53
  232. package/dist/plugins/triggers/TriggerController.svelte.d.ts +7 -2
  233. package/dist/plugins/triggers/TriggerController.svelte.js +11 -4
  234. package/dist/plugins/triggers/place.js +1 -2
  235. package/dist/plugins/triggers/triggers.d.ts +6 -1
  236. package/dist/plugins/triggers/triggers.js +12 -13
  237. package/dist/plugins/uploads.svelte.d.ts +48 -32
  238. package/dist/plugins/uploads.svelte.js +119 -43
  239. package/dist/plugins.d.ts +66 -14
  240. package/dist/plugins.js +0 -24
  241. package/dist/selection/replaceSelection.js +2 -2
  242. package/dist/selection/selection.svelte.d.ts +4 -10
  243. package/dist/selection/selection.svelte.js +7 -11
  244. package/dist/session/attempt.d.ts +16 -6
  245. package/dist/session/attempt.js +1 -0
  246. package/dist/session/bindings.js +35 -32
  247. package/dist/session/commands.d.ts +7 -11
  248. package/dist/session/commands.js +15 -19
  249. package/dist/session/history.js +1 -0
  250. package/dist/session/inputRules.d.ts +6 -3
  251. package/dist/session/inputRules.js +10 -6
  252. package/dist/session/moves.d.ts +33 -0
  253. package/dist/session/moves.js +71 -1
  254. package/dist/session/navigation.d.ts +7 -0
  255. package/dist/session/navigation.js +20 -11
  256. package/dist/session/props.d.ts +28 -0
  257. package/dist/session/props.js +65 -0
  258. package/dist/session/suggestions.svelte.d.ts +0 -11
  259. package/dist/session/suggestions.svelte.js +15 -3
  260. package/dist/session/uploads.d.ts +29 -0
  261. package/dist/session/uploads.js +10 -0
  262. package/dist/surface/lines.js +1 -3
  263. package/dist/surface/observer.svelte.d.ts +17 -1
  264. package/dist/surface/observer.svelte.js +72 -17
  265. package/dist/surface/overlay.d.ts +0 -14
  266. package/dist/surface/overlay.js +0 -25
  267. package/dist/surface/projector.svelte.js +1 -1
  268. package/dist/text/text.svelte.js +3 -13
  269. package/dist/themes/notion.css +9 -0
  270. package/dist/utils/sanitize.d.ts +38 -0
  271. package/dist/utils/sanitize.js +82 -0
  272. package/dist/utils.d.ts +2 -0
  273. package/dist/utils.js +5 -0
  274. package/package.json +18 -1
  275. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/max-z-index.js +0 -3
  276. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop/util/supports-popover.js +0 -16
  277. package/dist/dnd/vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/shared/is-axis-allowed.js +0 -3
  278. package/dist/plugins/code/LanguageMenu.svelte +0 -25
  279. package/dist/plugins/code/LanguageMenu.svelte.d.ts +0 -9
  280. package/dist/plugins/equation/EquationEditor.svelte +0 -27
  281. package/dist/plugins/equation/EquationEditor.svelte.d.ts +0 -9
  282. package/dist/plugins/image/ImageToolbarHost.svelte +0 -37
  283. package/dist/plugins/image/ImageToolbarHost.svelte.d.ts +0 -9
  284. package/dist/plugins/richtext/CalloutIconPicker.svelte +0 -26
  285. package/dist/plugins/richtext/CalloutIconPicker.svelte.d.ts +0 -9
  286. /package/dist/{plugins/columns → dnd}/stacking.d.ts +0 -0
  287. /package/dist/{plugins/columns → dnd}/stacking.js +0 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Properties: the deep proxy behind `block.data`, `atom.data`,
3
+ * `edytor.data` and `document.data` (SyncedStore's feel, one small module).
4
+ * It is sugar over the one write path: every mutation is a data patch
5
+ * handed to `write`, which is the `patchData` operation (dispatched on a
6
+ * view, raw on a bare document).
7
+ *
8
+ * A read goes to `read()` every time (the live source), so a reactive
9
+ * reader of `block.data.title` re-runs when anyone changes it, and a key a
10
+ * peer deletes is gone. Plain objects read as nested proxies, arrays as
11
+ * array proxies, everything else as the raw value; a proxy is cached per
12
+ * path, so its identity is stable. An object or array held in an array
13
+ * item is that item's (its path names the item by id, from `ids`): it
14
+ * stays on its item wherever peers move it, so `{#each list as item (item)}`
15
+ * keeps a row on its item; once the item is removed, its writes are
16
+ * refused. A key is a path segment as `keySegment` writes it.
17
+ *
18
+ * Writes, each the patch of only what it changes (per-leaf storage, so
19
+ * concurrent edits of other keys and items merge): `obj.key = v`,
20
+ * `arr[i] = v` and `delete obj.key` patch that path; `push`, `pop`,
21
+ * `shift`, `unshift`, `splice` and `length` are one `splice` (the items
22
+ * kept keep their ids), `sort` and `reverse` one `order` (the items move),
23
+ * `fill` and `copyWithin` writes of the items they change. Assigning a
24
+ * value equal to the one there writes nothing. `JSON.stringify` and
25
+ * `$state.snapshot` read plain JSON through it.
26
+ */
27
+ import { isObject, keySegment, segmentKey } from './data.js';
28
+ import { jsonEquals } from '../utils/json.js';
29
+ /** A plain JSON copy (proxies included), or `undefined`. */
30
+ const plain = (v) => (v === undefined ? v : JSON.parse(JSON.stringify(v)));
31
+ /** The items of `now` that differ from `was`, as writes of those items. */
32
+ const changed = (_, __, was, now) => now.flatMap((value, i) => JSON.stringify(value) === JSON.stringify(was[i]) ? [] : [{ at: `${i}`, value }]);
33
+ /**
34
+ * Each array mutator as the patches of the array (or of its items `at`),
35
+ * from its length `n`, the call's `args`, the array `was` and the result `out`.
36
+ */
37
+ const MUTATORS = {
38
+ push: (n, args) => ({ splice: [n, 0, ...args] }),
39
+ pop: (n) => ({ splice: [Math.max(n - 1, 0), n && 1] }),
40
+ shift: () => ({ splice: [0, 1] }),
41
+ unshift: (_, args) => ({ splice: [0, 0, ...args] }),
42
+ // The start and count `splice` resolved (negative, fractional, past the end).
43
+ splice: (n, [start, , ...items], _, out) => {
44
+ const s = Math.trunc(Number(start)) || 0;
45
+ return { splice: [s < 0 ? Math.max(n + s, 0) : Math.min(s, n), out.length, ...items] };
46
+ },
47
+ sort: (n, [compare], was) => ({ order: sorted(n, was, compare) }),
48
+ reverse: (n) => ({ order: Array.from({ length: n }, (_, i) => n - 1 - i) }),
49
+ fill: changed,
50
+ copyWithin: changed
51
+ };
52
+ /** The indexes `Array.prototype.sort` puts `values` in (stable, `undefined` compare: by string). */
53
+ const sorted = (n, values, compare) => {
54
+ const by = typeof compare === 'function'
55
+ ? compare
56
+ : (a, b) => (`${a}` < `${b}` ? -1 : `${a}` > `${b}` ? 1 : 0);
57
+ return Array.from({ length: n }, (_, i) => i).sort((a, b) => by(values[a], values[b]));
58
+ };
59
+ export const propsProxy = (read, write,
60
+ /** The ids of the items of the array at a path (`facade.dataItemIds`). */
61
+ ids = () => []) => {
62
+ const cache = new Map();
63
+ // Item ids per array path, for the value `read()` last gave.
64
+ let seen;
65
+ const known = new Map();
66
+ const idsOf = (path) => {
67
+ const now = read();
68
+ if (now !== seen) {
69
+ seen = now;
70
+ known.clear();
71
+ }
72
+ const key = JSON.stringify(path);
73
+ return known.get(key) ?? known.set(key, ids(path)).get(key);
74
+ };
75
+ const at = (path) => path.reduce((v, k, n) => /^~[a-z]/.test(k)
76
+ ? Array.isArray(v)
77
+ ? v[idsOf(path.slice(0, n)).indexOf(k)]
78
+ : undefined // its array is gone
79
+ : v !== null && typeof v === 'object'
80
+ ? v[segmentKey(k)]
81
+ : undefined, read());
82
+ const put = (path, value) => {
83
+ const next = plain(value);
84
+ if (jsonEquals(at(path), next))
85
+ return;
86
+ write([{ path, ...(next !== undefined && { value: next }) }]);
87
+ };
88
+ const wrap = (path, v) => Array.isArray(v) || isObject(v) ? proxy(path, Array.isArray(v)) : v;
89
+ const proxy = (path, array) => {
90
+ const key = `${array ? '[' : '{'}${JSON.stringify(path)}`;
91
+ const cached = cache.get(key);
92
+ if (cached)
93
+ return cached;
94
+ const current = () => {
95
+ const v = at(path);
96
+ return array ? (Array.isArray(v) ? v : []) : isObject(v) ? v : {};
97
+ };
98
+ /** The path of child `k`: an item by its id, a key as its segment. */
99
+ const child = (k) => [...path, (array && idsOf(path)[Number(k)]) || keySegment(k)];
100
+ const items = () => current().map((v, i) => wrap(child(`${i}`), v));
101
+ const own = (k) => Object.prototype.hasOwnProperty.call(current(), k);
102
+ const made = new Proxy(array ? [] : {}, {
103
+ get(target, k) {
104
+ if (typeof k === 'symbol')
105
+ return array && k === Symbol.iterator
106
+ ? () => items()[Symbol.iterator]()
107
+ : Reflect.get(target, k);
108
+ if (array && k === 'length')
109
+ return current().length;
110
+ if (own(k))
111
+ return wrap(child(k), current()[k]);
112
+ if (array && Object.hasOwn(MUTATORS, k))
113
+ return (...args) => {
114
+ const was = plain(current());
115
+ const next = [...was];
116
+ const fn = Array.prototype[k];
117
+ args = args.map((a) => (a !== null && typeof a === 'object' ? plain(a) : a));
118
+ const out = fn.apply(next, args);
119
+ const ops = [MUTATORS[k](was.length, args, was, out)].flat();
120
+ if (!jsonEquals(was, next))
121
+ write(ops.map(({ at, ...op }) => ({ ...op, path: at ? [...path, at] : path })));
122
+ return out === next ? made : out;
123
+ };
124
+ const method = array ? Array.prototype[k] : undefined;
125
+ if (typeof method === 'function')
126
+ return (...args) => method.apply(items(), args);
127
+ return Reflect.get(target, k);
128
+ },
129
+ set(_, k, value) {
130
+ if (typeof k === 'symbol')
131
+ return false;
132
+ if (array && k === 'length') {
133
+ const n = current().length;
134
+ const nulls = Array.from({ length: Math.max(value - n, 0) }, () => null);
135
+ write([{ path, splice: [Math.min(value, n), Math.max(n - value, 0), ...nulls] }]);
136
+ }
137
+ else
138
+ put([...path, keySegment(k)], value);
139
+ return true;
140
+ },
141
+ deleteProperty(_, k) {
142
+ if (typeof k === 'symbol')
143
+ return false;
144
+ if (own(k))
145
+ put([...path, keySegment(k)], undefined);
146
+ return true;
147
+ },
148
+ has: (target, k) => (typeof k === 'string' && own(k)) || Reflect.has(target, k),
149
+ ownKeys: () => [...Object.keys(current()), ...(array ? ['length'] : [])],
150
+ getOwnPropertyDescriptor(target, k) {
151
+ if (array && k === 'length')
152
+ return (Reflect.getOwnPropertyDescriptor(target, k) && {
153
+ value: current().length,
154
+ writable: true,
155
+ enumerable: false,
156
+ configurable: false
157
+ });
158
+ if (typeof k !== 'string' || !own(k))
159
+ return undefined;
160
+ return {
161
+ value: wrap(child(k), current()[k]),
162
+ writable: true,
163
+ enumerable: true,
164
+ configurable: true
165
+ };
166
+ }
167
+ });
168
+ cache.set(key, made);
169
+ return made;
170
+ };
171
+ return proxy([], false);
172
+ };
@@ -27,14 +27,14 @@
27
27
  export { bindCrdt, type Crdt, type EngineApi, type EngineDoc, type EngineNode, type EngineTransaction, type EngineItemRef, type YNode, type YItem, type YDoc, type YUndoManager, type YTransaction } from './index.js';
28
28
  export { SCHEMA_VERSION, META_KEY } from './edytor-doc.js';
29
29
  export { GENERATION, generationWord, frame, PROTOCOL_VERSION, GENERATION_RECORD, GenerationMismatchError, readProtocolVersion, type GenerationRecord } from './protocols/envelope.js';
30
- export { messageSync, messageAwareness, messageAuth, messageQueryAwareness, messageSaved, messageChunk, messageComments, MAX_FRAME_BYTES, chunkFrame, createChunkReader, ChunkLimitError, type ChunkReader, CLOSE } from './providers/room.js';
30
+ export { messageSync, messageAwareness, messageAuth, messageQueryAwareness, messageSaved, messageChunk, messageComments, MAX_FRAME_BYTES, chunkFrame, createChunkReader, ChunkError, type ChunkReader, CLOSE } from './providers/room.js';
31
31
  export { messageYjsSyncStep1, messageYjsSyncStep2, messageYjsUpdate, type SyncProtocol } from './protocols/sync.js';
32
32
  export { messagePermissionDenied, messageReadOnly, writePermissionDenied, writeReadOnly } from './protocols/auth.js';
33
33
  export { commentsSubscribe, commentsSnapshot, commentsChange, writeCommentsSubscribe, writeCommentsSnapshot, writeCommentsChange, readCommentsMessage, type CommentChange, type CommentMessage, type CommentSnapshot, type CommentThread, type ThreadComment } from './protocols/comments.js';
34
34
  export { applyAwarenessUpdate, encodeAwarenessUpdate, readAwarenessEntries, writeAwarenessEntries, type AwarenessEntry } from './protocols/awareness.js';
35
35
  export { createDecoder, readVarUint, readVarUint8Array, type Decoder } from 'lib0-v14/decoding';
36
36
  export { writeVarUint8Array, type Encoder } from 'lib0-v14/encoding';
37
- export { assertAdmission, assertSchema, assertUsableDoc, checkSchema, inspectAdmission, isInitialized, registryEmpty, schemaVersion, SchemaMismatchError, UndecodableUpdateError, UnsupportedDocError, type AdmissionResult, type AdmissionVerdict, type SchemaProblem } from './admission.js';
37
+ export { assertAdmission, assertSchema, checkSchema, inspectAdmission, isInitialized, registryEmpty, schemaVersion, SchemaMismatchError, UndecodableUpdateError, type AdmissionResult, type AdmissionVerdict, type SchemaProblem } from './admission.js';
38
38
  import type { ProviderStack } from './providers/index.js';
39
39
  export declare const IndexeddbPersistence: ProviderStack['IndexeddbPersistence'];
40
40
  export declare const WebsocketProvider: ProviderStack['WebsocketProvider'];
@@ -30,7 +30,7 @@ export { bindCrdt } from './index.js';
30
30
  export { SCHEMA_VERSION, META_KEY } from './edytor-doc.js';
31
31
  export { GENERATION, generationWord, frame, PROTOCOL_VERSION, GENERATION_RECORD, GenerationMismatchError, readProtocolVersion } from './protocols/envelope.js';
32
32
  // ── Message types, acknowledgements and chunks ─────────────────────────
33
- export { messageSync, messageAwareness, messageAuth, messageQueryAwareness, messageSaved, messageChunk, messageComments, MAX_FRAME_BYTES, chunkFrame, createChunkReader, ChunkLimitError, CLOSE } from './providers/room.js';
33
+ export { messageSync, messageAwareness, messageAuth, messageQueryAwareness, messageSaved, messageChunk, messageComments, MAX_FRAME_BYTES, chunkFrame, createChunkReader, ChunkError, CLOSE } from './providers/room.js';
34
34
  export { messageYjsSyncStep1, messageYjsSyncStep2, messageYjsUpdate } from './protocols/sync.js';
35
35
  export { messagePermissionDenied, messageReadOnly, writePermissionDenied, writeReadOnly } from './protocols/auth.js';
36
36
  export { commentsSubscribe, commentsSnapshot, commentsChange, writeCommentsSubscribe, writeCommentsSnapshot, writeCommentsChange, readCommentsMessage } from './protocols/comments.js';
@@ -46,7 +46,7 @@ export { writeVarUint8Array } from 'lib0-v14/encoding';
46
46
  // the matrix and the refusal-preserves-data contract). The errors they
47
47
  // throw are also exported from `edytor` and `edytor/crdt/edytor`, where a
48
48
  // `loadDocument` caller catches them.
49
- export { assertAdmission, assertSchema, assertUsableDoc, checkSchema, inspectAdmission, isInitialized, registryEmpty, schemaVersion, SchemaMismatchError, UndecodableUpdateError, UnsupportedDocError } from './admission.js';
49
+ export { assertAdmission, assertSchema, checkSchema, inspectAdmission, isInitialized, registryEmpty, schemaVersion, SchemaMismatchError, UndecodableUpdateError } from './admission.js';
50
50
  // ── Raw providers ──────────────────────────────────────────────────────
51
51
  //
52
52
  // The classes `createIndexeddbSync`/`createWebsocketSync` construct, bound
@@ -280,7 +280,7 @@ export declare const bindProviders: (Y: EngineApi) => {
280
280
  off<NAME extends "refused" | "status" | "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: WebsocketProviderEvents[NAME]): void;
281
281
  };
282
282
  };
283
- watchComments: (server: string, roomName: string, listener: (message: import("../protocol.js").CommentMessage) => void) => (() => void);
283
+ watchComments: (server: string | null, roomName: string, listener: (message: import("../protocol.js").CommentMessage) => void) => (() => void);
284
284
  storeState: (idbPersistence: {
285
285
  db: IDBDatabase | null;
286
286
  name: string;
@@ -69,14 +69,15 @@ export declare const MAX_FRAME_BYTES: number;
69
69
  * receiver applies the reassembled frame only once `end` arrives.
70
70
  */
71
71
  export declare const chunkFrame: (whole: Uint8Array, maxFrameBytes?: number) => Uint8Array[];
72
- /** A chunk sequence announces a frame larger than its reader takes ({@link createChunkReader}). */
73
- export declare class ChunkLimitError extends Error {
74
- readonly total: number;
75
- readonly limit: number;
76
- constructor(total: number, limit: number);
77
- }
78
- /** A chunk part or end with no sequence started (one lost, or never sent). */
79
- export declare class ChunkSequenceError extends Error {
72
+ /**
73
+ * A chunk sequence its reader refuses ({@link createChunkReader}): one
74
+ * announcing a frame larger than the reader takes (`total` over `limit`),
75
+ * or a part or end with no sequence started (one lost, or never sent).
76
+ */
77
+ export declare class ChunkError extends Error {
78
+ readonly total?: number | undefined;
79
+ readonly limit?: number | undefined;
80
+ constructor(total?: number | undefined, limit?: number | undefined);
80
81
  }
81
82
  /** A chunk reader ({@link createChunkReader}): feed it chunk bodies; `buffered` is what it holds. */
82
83
  export type ChunkReader = {
@@ -89,7 +90,7 @@ export type ChunkReader = {
89
90
  * each chunk frame's body (after the message type); it returns the whole
90
91
  * frame on `end`, `null` before. An out-of-order or oversized sequence
91
92
  * throws and resets; a sequence announcing more than `maxBytes` throws
92
- * {@link ChunkLimitError} at its start, before anything is buffered. A
93
+ * {@link ChunkError} at its start, before anything is buffered. A
93
94
  * sequence is assembled into ONE buffer of its announced size, allocated
94
95
  * at its start (`buffered`), never into parts copied at its end.
95
96
  * `admit(total)` is asked at each start, before that allocation: it may
@@ -92,26 +92,29 @@ export const chunkFrame = (whole, maxFrameBytes = MAX_FRAME_BYTES) => {
92
92
  frames.push(frame(messageChunk, (e) => encoding.writeVarUint(e, chunkEnd)));
93
93
  return frames;
94
94
  };
95
- /** A chunk sequence announces a frame larger than its reader takes ({@link createChunkReader}). */
96
- export class ChunkLimitError extends Error {
95
+ /**
96
+ * A chunk sequence its reader refuses ({@link createChunkReader}): one
97
+ * announcing a frame larger than the reader takes (`total` over `limit`),
98
+ * or a part or end with no sequence started (one lost, or never sent).
99
+ */
100
+ export class ChunkError extends Error {
97
101
  total;
98
102
  limit;
99
103
  constructor(total, limit) {
100
- super(`chunked frame of ${total} bytes exceeds ${limit}`);
104
+ super(limit === undefined
105
+ ? 'chunk without a start'
106
+ : `chunked frame of ${total} bytes exceeds ${limit}`);
101
107
  this.total = total;
102
108
  this.limit = limit;
103
- this.name = 'ChunkLimitError';
109
+ this.name = 'ChunkError';
104
110
  }
105
111
  }
106
- /** A chunk part or end with no sequence started (one lost, or never sent). */
107
- export class ChunkSequenceError extends Error {
108
- }
109
112
  /**
110
113
  * The receiving half of {@link chunkFrame}, one per connection: feed it
111
114
  * each chunk frame's body (after the message type); it returns the whole
112
115
  * frame on `end`, `null` before. An out-of-order or oversized sequence
113
116
  * throws and resets; a sequence announcing more than `maxBytes` throws
114
- * {@link ChunkLimitError} at its start, before anything is buffered. A
117
+ * {@link ChunkError} at its start, before anything is buffered. A
115
118
  * sequence is assembled into ONE buffer of its announced size, allocated
116
119
  * at its start (`buffered`), never into parts copied at its end.
117
120
  * `admit(total)` is asked at each start, before that allocation: it may
@@ -136,14 +139,14 @@ export const createChunkReader = (maxBytes = Infinity, admit = () => true) => {
136
139
  reset();
137
140
  const announced = decoding.readVarUint(decoder);
138
141
  if (announced > maxBytes)
139
- throw new ChunkLimitError(announced, maxBytes);
142
+ throw new ChunkError(announced, maxBytes);
140
143
  whole = admit(announced) ? new Uint8Array(announced) : null;
141
144
  total = announced;
142
145
  open = true;
143
146
  return null;
144
147
  }
145
148
  if (!open)
146
- throw new ChunkSequenceError(`chunk ${kind} without a start`);
149
+ throw new ChunkError();
147
150
  if (kind === chunkPart) {
148
151
  const bytes = decoding.readVarUint8Array(decoder);
149
152
  if (received + bytes.length > total)
@@ -228,5 +228,5 @@ export declare const bindWebsocketProvider: (Y: EngineApi) => {
228
228
  off<NAME extends "refused" | "status" | "failed" | "schema-mismatch" | "message-error" | "protocol-mismatch" | "synced" | "connection-close" | "connection-error" | "saved" | "permission-denied" | "expired" | "unreachable">(name: NAME, f: WebsocketProviderEvents[NAME]): void;
229
229
  };
230
230
  };
231
- watchComments: (server: string, roomName: string, listener: (message: CommentMessage) => void) => (() => void);
231
+ watchComments: (server: string | null, roomName: string, listener: (message: CommentMessage) => void) => (() => void);
232
232
  };
@@ -142,16 +142,16 @@ export const bindWebsocketProvider = (Y) => {
142
142
  provider.synced = true;
143
143
  }
144
144
  });
145
- // A room's comment threads (`watchComments`): the listeners of each room,
146
- // by `<serverUrl>/<room>`, and the providers dialing it. A provider asks
147
- // the room for them (a subscribe) at every open while a room has a
148
- // listener, and hands each message the room sends to every listener.
149
- const commentListeners = new Map();
150
- const providersOf = new Map();
145
+ const watchers = new Set();
146
+ const providers = new Set();
151
147
  const subscribeFrame = (on) => frame(messageComments, (e) => writeCommentsSubscribe(e, on));
148
+ const hears = (watcher, provider) => watcher.room === provider.roomname &&
149
+ (watcher.channel === null || watcher.channel === provider.bcChannel);
150
+ const listenersOf = (provider) => [...watchers].filter((watcher) => hears(watcher, provider)).map((watcher) => watcher.listener);
151
+ const providersFor = (watcher) => [...providers].filter((p) => hears(watcher, p));
152
152
  room.messageHandlers[messageComments] = (_encoder, decoder, provider) => {
153
153
  const message = readCommentsMessage(decoder);
154
- for (const listener of [...(commentListeners.get(provider.bcChannel) ?? [])]) {
154
+ for (const listener of listenersOf(provider)) {
155
155
  try {
156
156
  listener(message);
157
157
  }
@@ -162,26 +162,28 @@ export const bindWebsocketProvider = (Y) => {
162
162
  };
163
163
  /**
164
164
  * Hear the comment threads of `room` on `server` (the URL a provider
165
- * dials, `ws:`/`wss:`): every provider of that room subscribes now and
166
- * at each (re)connect, which the room answers with every thread (a
167
- * `snapshot`), then sends each `change`. Answers the unsubscribe; the
168
- * last one leaving tells the room to stop.
165
+ * dials, `ws:`/`wss:`; `null`: every provider of that room on the page,
166
+ * whatever its server): every such provider subscribes now and at each
167
+ * (re)connect, which the room answers with every thread (a `snapshot`),
168
+ * then sends each `change`. Answers the unsubscribe; the last listener
169
+ * of a provider leaving tells its room to stop.
169
170
  */
170
171
  const watchComments = (server, roomName, listener) => {
171
- const key = `${server.replace(/\/+$/, '')}/${roomName}`;
172
- const listeners = commentListeners.get(key) ?? new Set();
173
- commentListeners.set(key, listeners);
174
- const first = listeners.size === 0;
175
- listeners.add(listener);
176
- if (first)
177
- for (const provider of providersOf.get(key) ?? [])
178
- send(provider, subscribeFrame(true));
172
+ const watcher = {
173
+ room: roomName,
174
+ channel: server === null ? null : `${server.replace(/\/+$/, '')}/${roomName}`,
175
+ listener
176
+ };
177
+ const fresh = providersFor(watcher).filter((p) => listenersOf(p).length === 0);
178
+ watchers.add(watcher);
179
+ for (const provider of fresh)
180
+ send(provider, subscribeFrame(true));
179
181
  return () => {
180
- if (!listeners.delete(listener) || listeners.size > 0)
182
+ if (!watchers.delete(watcher))
181
183
  return;
182
- commentListeners.delete(key);
183
- for (const provider of providersOf.get(key) ?? [])
184
- send(provider, subscribeFrame(false));
184
+ for (const provider of providersFor(watcher))
185
+ if (listenersOf(provider).length === 0)
186
+ send(provider, subscribeFrame(false));
185
187
  };
186
188
  };
187
189
  // The room's acknowledgement and its bounded catch-up (a frame too large
@@ -468,7 +470,7 @@ export const bindWebsocketProvider = (Y) => {
468
470
  for (const buf of room.hello(provider))
469
471
  sendOn(provider, websocket, buf);
470
472
  // The room's comment threads, while someone listens (`watchComments`).
471
- if (commentListeners.get(provider.bcChannel)?.size)
473
+ if (listenersOf(provider).length > 0)
472
474
  sendOn(provider, websocket, subscribeFrame(true));
473
475
  };
474
476
  provider.emit('status', [{ status: 'connecting' }]);
@@ -540,8 +542,7 @@ export const bindWebsocketProvider = (Y) => {
540
542
  this._resync = setInterval(() => send(this, room.step1(this)), resyncInterval);
541
543
  }
542
544
  this._bcSubscriber = room.bcSubscriber(this);
543
- const peers = providersOf.get(this.bcChannel) ?? new Set();
544
- providersOf.set(this.bcChannel, peers.add(this));
545
+ providers.add(this);
545
546
  // Local doc updates go to the room; another tab's go to the server
546
547
  // only (`broadcastUpdate` quarantines a read-only document). A
547
548
  // socket the room made read-only gets this document's own edits
@@ -641,9 +642,7 @@ export const bindWebsocketProvider = (Y) => {
641
642
  return;
642
643
  clearInterval(this._resync);
643
644
  clearInterval(this._checkInterval);
644
- const peers = providersOf.get(this.bcChannel);
645
- if (peers?.delete(this) && peers.size === 0)
646
- providersOf.delete(this.bcChannel);
645
+ providers.delete(this);
647
646
  this.disconnect();
648
647
  this.awareness.off('update', this._awarenessUpdateHandler);
649
648
  this.doc.off('update', this._updateHandler);
@@ -40,6 +40,7 @@ export const normalizeRole = (role) => {
40
40
  };
41
41
  };
42
42
  /** Freeze `value` and everything in it: the tables are shared by every document. */
43
+ /* @__NO_SIDE_EFFECTS__ */
43
44
  const frozen = (value) => {
44
45
  if (value && typeof value === 'object' && !Object.isFrozen(value)) {
45
46
  Object.freeze(value);
@@ -294,7 +295,8 @@ export const equationSemantics = /* @__PURE__ */ semanticsOf(equationKinds);
294
295
  * plugins are not default plugins of `<Edytor>`, but their roles are here so their
295
296
  * blocks read the same on every replica.
296
297
  */
297
- export const defaultSemantics = withMarks(semanticsOf(richTextKinds, codeKinds, imageKinds, mediaKinds, layoutKinds, pageKinds, tocKinds, tableKinds, equationKinds), { ...richTextMarks, ...commentMarks });
298
+ export const defaultSemantics = /* @__PURE__ */ withMarks(semanticsOf(richTextKinds, codeKinds, imageKinds, mediaKinds, layoutKinds, pageKinds, tocKinds, tableKinds, equationKinds),
299
+ /* @__PURE__ */ Object.assign({}, richTextMarks, commentMarks));
298
300
  /**
299
301
  * The facade configuration (`EdytorDocConfig`) a document with no view
300
302
  * reads `semantics` with — the room's: roles, default children, content-less kinds
@@ -1,9 +1,17 @@
1
+ /** One adapter's auto-scroll (Atlassian's auto-scroll package), its drags already chosen. */
2
+ export type Scrollers = {
3
+ /** The window scrolls as the pointer nears its edges. */
4
+ window(): () => void;
5
+ /** `element` scrolls as the pointer nears its edges. */
6
+ element(element: Element): () => void;
7
+ };
1
8
  /**
2
- * Auto-scroll for one drag (a block's, a table row's or column's; Atlassian's
3
- * auto-scroll package): the window
4
- * and every scrolling element from the editor up (the editor included) scroll
5
- * as the pointer nears their edges, faster the closer and the longer it stays,
6
- * innermost first. `ours` keeps it to this editor's drags. Registered at the
7
- * drag's start (the package allows it mid-drag); the answer releases it.
9
+ * Auto-scroll for one drag (a block's, a table row's or column's, files
10
+ * dragged from outside): the window and every scrolling element from the
11
+ * editor up (the editor included) scroll as the pointer nears their edges,
12
+ * faster the closer and the longer it stays, innermost first. `scrollers`
13
+ * is the drag's adapter's (`elementScrollers`, `externalScrollers`), kept to
14
+ * this editor's drags. Registered at the drag's start (the package allows it
15
+ * mid-drag); the answer releases it.
8
16
  */
9
- export declare const autoScrollFor: (root: HTMLElement, ours: (data: Record<string | symbol, unknown>) => boolean) => (() => void);
17
+ export declare const autoScrollFor: (root: HTMLElement, scrollers: Scrollers) => (() => void);
@@ -1,25 +1,20 @@
1
- import { autoScroll, autoScrollWindow } from './pragmatic.js';
2
1
  /**
3
- * Auto-scroll for one drag (a block's, a table row's or column's; Atlassian's
4
- * auto-scroll package): the window
5
- * and every scrolling element from the editor up (the editor included) scroll
6
- * as the pointer nears their edges, faster the closer and the longer it stays,
7
- * innermost first. `ours` keeps it to this editor's drags. Registered at the
8
- * drag's start (the package allows it mid-drag); the answer releases it.
2
+ * Auto-scroll for one drag (a block's, a table row's or column's, files
3
+ * dragged from outside): the window and every scrolling element from the
4
+ * editor up (the editor included) scroll as the pointer nears their edges,
5
+ * faster the closer and the longer it stays, innermost first. `scrollers`
6
+ * is the drag's adapter's (`elementScrollers`, `externalScrollers`), kept to
7
+ * this editor's drags. Registered at the drag's start (the package allows it
8
+ * mid-drag); the answer releases it.
9
9
  */
10
- export const autoScrollFor = (root, ours) => {
11
- // The scroller hit-tests with `elementsFromPoint` every frame (jsdom has none),
12
- // so it is created only where that exists.
13
- if (typeof root.ownerDocument.elementsFromPoint !== 'function')
14
- return () => { };
15
- const canScroll = ({ source }) => ours(source.data);
16
- const releases = [autoScrollWindow({ canScroll })];
10
+ export const autoScrollFor = (root, scrollers) => {
11
+ const releases = [scrollers.window()];
17
12
  const { body, documentElement, defaultView } = root.ownerDocument;
18
13
  // The window is the document's scroller: stop below it.
19
14
  for (let element = root; element && element !== body && element !== documentElement; element = element.parentElement) {
20
15
  const { overflowX, overflowY } = defaultView.getComputedStyle(element);
21
16
  if (/auto|scroll|overlay/.test(`${overflowX} ${overflowY}`))
22
- releases.push(autoScroll({ element, canScroll }));
17
+ releases.push(scrollers.element(element));
23
18
  }
24
19
  return () => releases.forEach((release) => release());
25
20
  };
@@ -5,8 +5,8 @@
5
5
  * future parent's own row. Both live in the overlay layer, measured each
6
6
  * frame. The controller decides the placement; this draws it.
7
7
  */
8
- import type { Block } from '../../block/block.svelte.js';
9
- import type { Edytor } from '../../edytor.svelte.js';
8
+ import type { Block } from '../block/block.svelte.js';
9
+ import type { Edytor } from '../edytor.svelte.js';
10
10
  import { type DropPlacement } from './geometry.js';
11
11
  /** What the indicator reads of the controller: the dragged blocks and the beside resolution. */
12
12
  type IndicatorContext = {
@@ -1,4 +1,4 @@
1
- import { getOwnRowBottom, isBeside, nestIndent, ownRow, ownTextRow } from './geometry.js';
1
+ import { cssVar, getOwnRowBottom, isBeside, nestIndent, ownRow, ownTextRow } from './geometry.js';
2
2
  /** Notion's drop bar: 4px (its height in `BlockHandles.svelte`, its look the app's). */
3
3
  const BAR = 4;
4
4
  /** Place `element` at `box`, relative to the layer (`origin`). */
@@ -14,10 +14,7 @@ const place = (element, box, origin) => Object.assign(element.style, {
14
14
  * unset there without one.
15
15
  */
16
16
  const themed = (from, name) => {
17
- const value = from.ownerDocument.defaultView
18
- ?.getComputedStyle(from)
19
- .getPropertyValue(name)
20
- .trim();
17
+ const value = cssVar(from, name);
21
18
  return (element) => value ? element.style.setProperty(name, value) : element.style.removeProperty(name);
22
19
  };
23
20
  /**
@@ -0,0 +1,6 @@
1
+ import type { Scrollers } from './autoScroll.js';
2
+ export { dropTargetForExternal } from './vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js';
3
+ export { containsFiles } from './vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js';
4
+ export { getFiles } from './vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js';
5
+ /** The external adapter's auto-scroll, while `ours()` (the drag is over this editor). */
6
+ export declare const externalScrollers: (ours: () => boolean) => Scrollers;
@@ -0,0 +1,17 @@
1
+ // Pragmatic drag and drop's external adapter (vendored with the element
2
+ // adapter, on its core, `vendor/pragmatic/UPSTREAM.md`): drags that start
3
+ // outside the window (files from the desktop). Only the media plugins that
4
+ // take an upload import it (`plugins/fileDrop.ts`), so a view without them
5
+ // ships none of it.
6
+ import { autoScrollForExternal, autoScrollWindowForExternal } from './vendor/pragmatic/pragmatic-drag-and-drop-auto-scroll/entry-point/external.js';
7
+ export { dropTargetForExternal } from './vendor/pragmatic/pragmatic-drag-and-drop/adapter/drop-target-for-external.js';
8
+ export { containsFiles } from './vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/contains-files.js';
9
+ export { getFiles } from './vendor/pragmatic/pragmatic-drag-and-drop/public-utils/external/get-files.js';
10
+ /** The external adapter's auto-scroll, while `ours()` (the drag is over this editor). */
11
+ export const externalScrollers = (ours) => {
12
+ const canScroll = () => ours();
13
+ return {
14
+ window: () => autoScrollWindowForExternal({ canScroll }),
15
+ element: (element) => autoScrollForExternal({ element, canScroll })
16
+ };
17
+ };
@@ -4,8 +4,8 @@
4
4
  * placement's shape, a block's own row, its first text line and one
5
5
  * nesting step.
6
6
  */
7
- import type { Block } from '../../block/block.svelte.js';
8
- import type { BlockMovePosition } from '../../session/moves.js';
7
+ import type { Block } from '../block/block.svelte.js';
8
+ import type { BlockMovePosition } from '../session/moves.js';
9
9
  export type DropPlacement = {
10
10
  target: Block;
11
11
  node: HTMLElement;
@@ -27,6 +27,8 @@ export declare const ownTextRow: (node: HTMLElement) => DOMRect;
27
27
  */
28
28
  export declare const NEST_INDENT = 24;
29
29
  export declare const nestIndent: (node: HTMLElement) => number;
30
+ /** The theme variable `name` as `node` inherits it, read now (none outside a window). */
31
+ export declare const cssVar: (node: HTMLElement, name: string) => string | undefined;
30
32
  /**
31
33
  * Whether `y` is over the hint of `node`'s empty body (`body.hint`, a kind's
32
34
  * `data-edytor-empty-body` element: an open toggle's, a callout's): a drop
@@ -31,12 +31,11 @@ export const ownTextRow = (node) => {
31
31
  */
32
32
  export const NEST_INDENT = 24;
33
33
  export const nestIndent = (node) => {
34
- const value = node.ownerDocument.defaultView
35
- ?.getComputedStyle(node)
36
- .getPropertyValue('--edytor-nest-indent')
37
- .trim();
34
+ const value = cssVar(node, '--edytor-nest-indent');
38
35
  return value?.endsWith('px') ? parseFloat(value) : NEST_INDENT;
39
36
  };
37
+ /** The theme variable `name` as `node` inherits it, read now (none outside a window). */
38
+ export const cssVar = (node, name) => node.ownerDocument.defaultView?.getComputedStyle(node).getPropertyValue(name).trim();
40
39
  /**
41
40
  * Whether `y` is over the hint of `node`'s empty body (`body.hint`, a kind's
42
41
  * `data-edytor-empty-body` element: an open toggle's, a callout's): a drop