quoin-editor 2.0.4 → 2.1.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 (215) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/MIGRATION.md +1 -1
  3. package/README.md +14 -13
  4. package/dist/ai.cjs +124 -94
  5. package/dist/ai.d.cts +7 -0
  6. package/dist/ai.d.ts +7 -0
  7. package/dist/ai.js +50 -20
  8. package/dist/ai.js.map +1 -1
  9. package/dist/catalogue.cjs +28 -26
  10. package/dist/catalogue.js +19 -17
  11. package/dist/catalogue.js.map +1 -1
  12. package/dist/{chunk-JGEDJYIV.cjs → chunk-2FUWXPPC.cjs} +92 -98
  13. package/dist/{chunk-NHNW5DK3.js → chunk-3F76QQ65.js} +6 -6
  14. package/dist/{chunk-NHNW5DK3.js.map → chunk-3F76QQ65.js.map} +1 -1
  15. package/dist/{chunk-DBOZFNWU.js → chunk-3QYFAAQR.js} +3 -3
  16. package/dist/{chunk-DBOZFNWU.js.map → chunk-3QYFAAQR.js.map} +1 -1
  17. package/dist/{chunk-I7X7B3WD.cjs → chunk-4JDRDPLC.cjs} +17 -8
  18. package/dist/{chunk-EBSDPHPS.cjs → chunk-4UFWFV43.cjs} +1060 -719
  19. package/dist/{chunk-LM3DHROX.cjs → chunk-5AUIA4B3.cjs} +2 -2
  20. package/dist/{chunk-3INFNIGN.cjs → chunk-5H3BB5VJ.cjs} +131 -78
  21. package/dist/{chunk-DJU25PFC.cjs → chunk-5L2NSIHZ.cjs} +11 -11
  22. package/dist/{chunk-W376L2GM.js → chunk-6Y7JAWYY.js} +8 -8
  23. package/dist/chunk-6Y7JAWYY.js.map +1 -0
  24. package/dist/{chunk-UDBLZILE.js → chunk-ATKDXQEY.js} +12 -7
  25. package/dist/{chunk-UDBLZILE.js.map → chunk-ATKDXQEY.js.map} +1 -1
  26. package/dist/{chunk-A2IQHMIH.js → chunk-BE2SYPK5.js} +49 -54
  27. package/dist/chunk-BE2SYPK5.js.map +1 -0
  28. package/dist/{chunk-PURYVDC3.cjs → chunk-CFICD2JP.cjs} +21 -16
  29. package/dist/{chunk-3HW3WRYC.cjs → chunk-CSIUXYRU.cjs} +2 -2
  30. package/dist/{chunk-N7BSFDDM.cjs → chunk-DBKL524I.cjs} +23 -23
  31. package/dist/{chunk-XE3IYW5B.js → chunk-DEFYFIWW.js} +90 -37
  32. package/dist/chunk-DEFYFIWW.js.map +1 -0
  33. package/dist/{chunk-7E43TURF.cjs → chunk-ECI3PSMS.cjs} +7 -7
  34. package/dist/{chunk-4G645EYO.js → chunk-F73QEF7E.js} +5 -5
  35. package/dist/{chunk-4G645EYO.js.map → chunk-F73QEF7E.js.map} +1 -1
  36. package/dist/{chunk-KHRVCTQQ.cjs → chunk-FUT7XLMP.cjs} +61 -74
  37. package/dist/{chunk-7J63427U.cjs → chunk-GQSBOBOM.cjs} +375 -320
  38. package/dist/{chunk-LU3T3JB4.js → chunk-HPNSQWRD.js} +15 -28
  39. package/dist/chunk-HPNSQWRD.js.map +1 -0
  40. package/dist/{chunk-7Y4B7NHO.js → chunk-I34BFOLL.js} +18 -11
  41. package/dist/chunk-I34BFOLL.js.map +1 -0
  42. package/dist/{chunk-AJT54OMZ.js → chunk-IFRXEFQH.js} +9 -15
  43. package/dist/chunk-IFRXEFQH.js.map +1 -0
  44. package/dist/{chunk-YYW33WUL.cjs → chunk-K3XWVRL4.cjs} +8 -8
  45. package/dist/{chunk-LSI4RMTY.js → chunk-L5L6YNLT.js} +3 -3
  46. package/dist/{chunk-LSI4RMTY.js.map → chunk-L5L6YNLT.js.map} +1 -1
  47. package/dist/{chunk-2BPXVQBP.js → chunk-MO4UMXMT.js} +238 -86
  48. package/dist/chunk-MO4UMXMT.js.map +1 -0
  49. package/dist/{chunk-2QKFRKOP.cjs → chunk-N25EH2GZ.cjs} +351 -205
  50. package/dist/{chunk-CSPCDVCT.js → chunk-NCV2ML25.js} +3 -3
  51. package/dist/{chunk-CSPCDVCT.js.map → chunk-NCV2ML25.js.map} +1 -1
  52. package/dist/{chunk-NUQ64S5B.cjs → chunk-OJSKSQTL.cjs} +26 -26
  53. package/dist/chunk-PIWMU4BV.js +9 -0
  54. package/dist/chunk-PIWMU4BV.js.map +1 -0
  55. package/dist/chunk-QFGWSFOI.cjs +10 -0
  56. package/dist/{chunk-GPTJYWGS.js → chunk-RNBLVGWY.js} +3 -3
  57. package/dist/{chunk-GPTJYWGS.js.map → chunk-RNBLVGWY.js.map} +1 -1
  58. package/dist/{chunk-5RBMZGKV.js → chunk-TL2MJOWM.js} +325 -57
  59. package/dist/chunk-TL2MJOWM.js.map +1 -0
  60. package/dist/{chunk-YEDPBYO5.cjs → chunk-UDQ52EEC.cjs} +4 -4
  61. package/dist/{chunk-EIWPJWY3.js → chunk-UE2NQPNG.js} +5 -5
  62. package/dist/{chunk-EIWPJWY3.js.map → chunk-UE2NQPNG.js.map} +1 -1
  63. package/dist/{chunk-BE2YHZXA.cjs → chunk-ULV3SCYP.cjs} +26 -15
  64. package/dist/{chunk-WDBFGX3U.cjs → chunk-VTTMJGWP.cjs} +72 -77
  65. package/dist/{chunk-556PFYES.js → chunk-WK4UGDZN.js} +290 -235
  66. package/dist/chunk-WK4UGDZN.js.map +1 -0
  67. package/dist/{chunk-JZF6UQH5.cjs → chunk-WMKA37NJ.cjs} +12 -12
  68. package/dist/{chunk-F2ZK6Z52.js → chunk-Y26F2X4E.js} +3 -3
  69. package/dist/{chunk-F2ZK6Z52.js.map → chunk-Y26F2X4E.js.map} +1 -1
  70. package/dist/{chunk-FK7EBZPX.cjs → chunk-Z5EEDCRI.cjs} +549 -276
  71. package/dist/{chunk-G6NBQYMM.js → chunk-ZGFZRVQA.js} +817 -478
  72. package/dist/chunk-ZGFZRVQA.js.map +1 -0
  73. package/dist/{chunk-QLVX7MPS.js → chunk-ZQF45LA4.js} +19 -8
  74. package/dist/chunk-ZQF45LA4.js.map +1 -0
  75. package/dist/comments.cjs +127 -65
  76. package/dist/comments.d.cts +35 -2
  77. package/dist/comments.d.ts +35 -2
  78. package/dist/comments.js +73 -12
  79. package/dist/comments.js.map +1 -1
  80. package/dist/{diagram-extension-22x_njXB.d.ts → diagram-extension-BMlh8GCw.d.ts} +1 -1
  81. package/dist/{diagram-extension-C_FSkoj9.d.cts → diagram-extension-gmndUpti.d.cts} +1 -1
  82. package/dist/diagram.cjs +10 -9
  83. package/dist/diagram.d.cts +2 -2
  84. package/dist/diagram.d.ts +2 -2
  85. package/dist/diagram.js +7 -6
  86. package/dist/diff.cjs +25 -25
  87. package/dist/diff.js +3 -3
  88. package/dist/docx.cjs +31 -30
  89. package/dist/docx.js +5 -4
  90. package/dist/docx.js.map +1 -1
  91. package/dist/embed.cjs +10 -9
  92. package/dist/embed.js +8 -7
  93. package/dist/{emoji-extension-Dk5IQLZf.d.cts → emoji-extension-DD9CQTQj.d.cts} +1 -1
  94. package/dist/{emoji-extension-C832oGeT.d.ts → emoji-extension-U_PWZ2fX.d.ts} +1 -1
  95. package/dist/emoji.cjs +10 -9
  96. package/dist/emoji.d.cts +2 -2
  97. package/dist/emoji.d.ts +2 -2
  98. package/dist/emoji.js +7 -6
  99. package/dist/engine.cjs +58 -58
  100. package/dist/engine.d.cts +3 -3
  101. package/dist/engine.d.ts +3 -3
  102. package/dist/engine.js +3 -3
  103. package/dist/{find-extension-DmK9_N81.d.ts → find-extension-BGlqooZi.d.ts} +1 -1
  104. package/dist/{find-extension-BfruAPLi.d.cts → find-extension-BPnAJ8bY.d.cts} +1 -1
  105. package/dist/find.cjs +11 -10
  106. package/dist/find.d.cts +1 -1
  107. package/dist/find.d.ts +1 -1
  108. package/dist/find.js +7 -6
  109. package/dist/headless.cjs +70 -69
  110. package/dist/headless.d.cts +33 -10
  111. package/dist/headless.d.ts +33 -10
  112. package/dist/headless.js +5 -4
  113. package/dist/highlight.cjs +7 -6
  114. package/dist/highlight.js +6 -5
  115. package/dist/highlight.js.map +1 -1
  116. package/dist/{index-3fYvwqUZ.d.cts → index-DN7vRKFw.d.cts} +1 -1
  117. package/dist/{index-CgxnzCO5.d.ts → index-DyIYI3PM.d.ts} +1 -1
  118. package/dist/index.cjs +82 -81
  119. package/dist/index.d.cts +19 -12
  120. package/dist/index.d.ts +19 -12
  121. package/dist/index.js +6 -5
  122. package/dist/{labels-CiCxj2jP.d.cts → labels-BJORhN93.d.ts} +10 -5
  123. package/dist/{labels-BhRJYo46.d.ts → labels-CVYJ2-1X.d.cts} +10 -5
  124. package/dist/locale-ar.cjs +10 -0
  125. package/dist/locale-ar.d.cts +1 -1
  126. package/dist/locale-ar.d.ts +1 -1
  127. package/dist/locale-ar.js +10 -0
  128. package/dist/locale-ar.js.map +1 -1
  129. package/dist/locale-de.cjs +4 -0
  130. package/dist/locale-de.d.cts +1 -1
  131. package/dist/locale-de.d.ts +1 -1
  132. package/dist/locale-de.js +4 -0
  133. package/dist/locale-de.js.map +1 -1
  134. package/dist/locale-es.cjs +4 -0
  135. package/dist/locale-es.d.cts +1 -1
  136. package/dist/locale-es.d.ts +1 -1
  137. package/dist/locale-es.js +4 -0
  138. package/dist/locale-es.js.map +1 -1
  139. package/dist/locale-fr.cjs +4 -0
  140. package/dist/locale-fr.d.cts +1 -1
  141. package/dist/locale-fr.d.ts +1 -1
  142. package/dist/locale-fr.js +4 -0
  143. package/dist/locale-fr.js.map +1 -1
  144. package/dist/locale-ja.cjs +4 -0
  145. package/dist/locale-ja.d.cts +1 -1
  146. package/dist/locale-ja.d.ts +1 -1
  147. package/dist/locale-ja.js +4 -0
  148. package/dist/locale-ja.js.map +1 -1
  149. package/dist/locale-pt.cjs +4 -0
  150. package/dist/locale-pt.d.cts +1 -1
  151. package/dist/locale-pt.d.ts +1 -1
  152. package/dist/locale-pt.js +4 -0
  153. package/dist/locale-pt.js.map +1 -1
  154. package/dist/locale-zh.cjs +4 -0
  155. package/dist/locale-zh.d.cts +1 -1
  156. package/dist/locale-zh.d.ts +1 -1
  157. package/dist/locale-zh.js +4 -0
  158. package/dist/locale-zh.js.map +1 -1
  159. package/dist/math.cjs +11 -10
  160. package/dist/math.js +9 -8
  161. package/dist/mention.cjs +11 -10
  162. package/dist/mention.js +9 -8
  163. package/dist/{node-reveal-DY6bimv3.d.cts → node-reveal-Be7Xa0BL.d.cts} +1 -1
  164. package/dist/{node-reveal-BnFcnHhz.d.ts → node-reveal-CftIEqF_.d.ts} +1 -1
  165. package/dist/palette-DuIFHYHc.d.cts +10 -0
  166. package/dist/palette-DuIFHYHc.d.ts +10 -0
  167. package/dist/presence.cjs +39 -38
  168. package/dist/presence.js +8 -7
  169. package/dist/presence.js.map +1 -1
  170. package/dist/source.cjs +10 -9
  171. package/dist/source.d.cts +1 -1
  172. package/dist/source.d.ts +1 -1
  173. package/dist/source.js +6 -5
  174. package/dist/source.js.map +1 -1
  175. package/dist/{stats-extension-Dmw0Ujxe.d.ts → stats-extension-Bbpr593p.d.ts} +1 -1
  176. package/dist/{stats-extension-D5HySF0a.d.cts → stats-extension-D7FaeydW.d.cts} +1 -1
  177. package/dist/stats.cjs +12 -10
  178. package/dist/stats.d.cts +2 -2
  179. package/dist/stats.d.ts +2 -2
  180. package/dist/stats.js +9 -7
  181. package/dist/styles.css +1 -1
  182. package/dist/{table-extension-7LkLNK6Q.d.cts → table-extension-DNijjmxV.d.cts} +1 -1
  183. package/dist/{table-extension-DEpV0DnP.d.ts → table-extension-Dp6FYGPh.d.ts} +1 -1
  184. package/dist/table.cjs +26 -25
  185. package/dist/table.d.cts +4 -3
  186. package/dist/table.d.ts +4 -3
  187. package/dist/table.js +7 -6
  188. package/dist/{toc-extension-Dvh37bWQ.d.cts → toc-extension-BGEVAmSY.d.cts} +1 -1
  189. package/dist/{toc-extension-SVckrFmb.d.ts → toc-extension-DZIe40eV.d.ts} +1 -1
  190. package/dist/toc.cjs +10 -9
  191. package/dist/toc.d.cts +2 -2
  192. package/dist/toc.d.ts +2 -2
  193. package/dist/toc.js +7 -6
  194. package/dist/{types-DMuuDBVh.d.ts → types-Byu2a9qk.d.ts} +6 -1
  195. package/dist/{types-Bzhq5AXj.d.cts → types-DdDlCyyZ.d.cts} +6 -1
  196. package/dist/view.cjs +4 -4
  197. package/dist/view.js +2 -2
  198. package/dist/yjs.cjs +121 -121
  199. package/dist/yjs.d.cts +2 -2
  200. package/dist/yjs.d.ts +2 -2
  201. package/dist/yjs.js +5 -5
  202. package/package.json +4 -3
  203. package/dist/chunk-2BPXVQBP.js.map +0 -1
  204. package/dist/chunk-556PFYES.js.map +0 -1
  205. package/dist/chunk-5RBMZGKV.js.map +0 -1
  206. package/dist/chunk-7Y4B7NHO.js.map +0 -1
  207. package/dist/chunk-A2IQHMIH.js.map +0 -1
  208. package/dist/chunk-AJT54OMZ.js.map +0 -1
  209. package/dist/chunk-G6NBQYMM.js.map +0 -1
  210. package/dist/chunk-LU3T3JB4.js.map +0 -1
  211. package/dist/chunk-QLVX7MPS.js.map +0 -1
  212. package/dist/chunk-W376L2GM.js.map +0 -1
  213. package/dist/chunk-XE3IYW5B.js.map +0 -1
  214. package/dist/palette-BrX-hEd-.d.cts +0 -4
  215. package/dist/palette-BrX-hEd-.d.ts +0 -4
package/dist/comments.cjs CHANGED
@@ -1,18 +1,20 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var chunkLM3DHROX_cjs = require('./chunk-LM3DHROX.cjs');
5
- var chunk3HW3WRYC_cjs = require('./chunk-3HW3WRYC.cjs');
6
- var chunkEBSDPHPS_cjs = require('./chunk-EBSDPHPS.cjs');
7
- var chunk2QKFRKOP_cjs = require('./chunk-2QKFRKOP.cjs');
4
+ var chunk5AUIA4B3_cjs = require('./chunk-5AUIA4B3.cjs');
5
+ var chunkCSIUXYRU_cjs = require('./chunk-CSIUXYRU.cjs');
6
+ var chunk4UFWFV43_cjs = require('./chunk-4UFWFV43.cjs');
7
+ var chunkN25EH2GZ_cjs = require('./chunk-N25EH2GZ.cjs');
8
8
  var chunkZWTIRGY5_cjs = require('./chunk-ZWTIRGY5.cjs');
9
9
  require('./chunk-A6PGQVTR.cjs');
10
- var chunkFK7EBZPX_cjs = require('./chunk-FK7EBZPX.cjs');
11
- require('./chunk-DJU25PFC.cjs');
12
- var chunkI7X7B3WD_cjs = require('./chunk-I7X7B3WD.cjs');
10
+ require('./chunk-QFGWSFOI.cjs');
11
+ var chunkZ5EEDCRI_cjs = require('./chunk-Z5EEDCRI.cjs');
12
+ require('./chunk-5L2NSIHZ.cjs');
13
+ var chunk4JDRDPLC_cjs = require('./chunk-4JDRDPLC.cjs');
13
14
  var react = require('react');
14
15
  var jsxRuntime = require('react/jsx-runtime');
15
16
  var DialogPrimitive = require('@radix-ui/react-dialog');
17
+ var reactDirection = require('@radix-ui/react-direction');
16
18
 
17
19
  function _interopNamespace(e) {
18
20
  if (e && e.__esModule) return e;
@@ -40,7 +42,7 @@ function addRegion(anchors, block, region, inline2) {
40
42
  let position = 0;
41
43
  for (const node of inline2) {
42
44
  const from = position;
43
- position += chunkI7X7B3WD_cjs.nodeLength(node);
45
+ position += chunk4JDRDPLC_cjs.nodeLength(node);
44
46
  for (const id of idsOf(node)) {
45
47
  const ranges = anchors.get(id) ?? [];
46
48
  const last = ranges[ranges.length - 1];
@@ -67,25 +69,25 @@ function commentAnchors(doc) {
67
69
  var atomLabel = (node) => node.kind === "atom" ? node.attrs.label ?? "" : "";
68
70
  function anchorText(doc, ranges) {
69
71
  return ranges.map(({ block, region, from, to }) => {
70
- const inline2 = chunkI7X7B3WD_cjs.blockById(doc, block)?.regions[region] ?? [];
71
- return chunkI7X7B3WD_cjs.inlineText(chunkI7X7B3WD_cjs.sliceInline(inline2, from, to), atomLabel);
72
+ const inline2 = chunk4JDRDPLC_cjs.blockById(doc, block)?.regions[region] ?? [];
73
+ return chunk4JDRDPLC_cjs.inlineText(chunk4JDRDPLC_cjs.sliceInline(inline2, from, to), atomLabel);
72
74
  }).join(" ");
73
75
  }
74
76
  function commentIdsAt(doc, { block, region, offset }) {
75
- const inline2 = chunkI7X7B3WD_cjs.blockById(doc, block)?.regions[region] ?? [];
77
+ const inline2 = chunk4JDRDPLC_cjs.blockById(doc, block)?.regions[region] ?? [];
76
78
  const ids = /* @__PURE__ */ new Set();
77
79
  let position = 0;
78
80
  for (const node of inline2) {
79
- const end = position + chunkI7X7B3WD_cjs.nodeLength(node);
81
+ const end = position + chunk4JDRDPLC_cjs.nodeLength(node);
80
82
  if (position <= offset && offset <= end && end > position) idsOf(node).forEach((id) => ids.add(id));
81
83
  position = end;
82
84
  }
83
85
  return [...ids].sort();
84
86
  }
85
87
  function threadRemoval(state, id) {
86
- const tr = new chunkFK7EBZPX_cjs.Transaction(state).setOrigin("command");
88
+ const tr = new chunkZ5EEDCRI_cjs.Transaction(state).setOrigin("command");
87
89
  for (const { block, region, from, to } of commentAnchors(state.doc).get(id) ?? []) {
88
- tr.step(chunkFK7EBZPX_cjs.removeMarkStep(block, region, from, to, { type: "comment", attrs: { id } }));
90
+ tr.step(chunkZ5EEDCRI_cjs.removeMarkStep(block, region, from, to, { type: "comment", attrs: { id } }));
89
91
  }
90
92
  return tr;
91
93
  }
@@ -96,14 +98,14 @@ function mapPendingRanges(tr, ranges, state) {
96
98
  const from = tr.mapPos({ block: range.block, region: range.region, offset: range.from }, 1);
97
99
  const to = tr.mapPos({ block: range.block, region: range.region, offset: range.to }, -1);
98
100
  const { index } = state.doc;
99
- if (!index.has(from.block) || !index.has(to.block) || chunkFK7EBZPX_cjs.comparePos(state.doc, from, to) >= 0) return [];
100
- return chunkFK7EBZPX_cjs.markRanges({ ...state, selection: chunkFK7EBZPX_cjs.textSelection(from, to) });
101
+ if (!index.has(from.block) || !index.has(to.block) || chunkZ5EEDCRI_cjs.comparePos(state.doc, from, to) >= 0) return [];
102
+ return chunkZ5EEDCRI_cjs.markRanges({ ...state, selection: chunkZ5EEDCRI_cjs.textSelection(from, to) });
101
103
  });
102
104
  }
103
105
 
104
106
  // src/extensions/comments/comments-plugin.ts
105
107
  var isEnded = (ended, id, current) => ended.some((thread) => thread.id === id && thread.seen?.resolved === current?.resolved);
106
- var commentsKey = chunkFK7EBZPX_cjs.createPluginKey("comments");
108
+ var commentsKey = chunkZ5EEDCRI_cjs.createPluginKey("comments");
107
109
  var COMMENTS = "comments";
108
110
  var IDLE = { pending: [], active: null, open: null, ended: [] };
109
111
  function act(value, action) {
@@ -156,26 +158,26 @@ var commentsPlugin = {
156
158
 
157
159
  // src/extensions/comments/comment-create.ts
158
160
  var nextKey = 0;
159
- var hasCommentableText = (state) => state.selection?.kind === "text" && chunkFK7EBZPX_cjs.markRanges(state).length > 0;
161
+ var hasCommentableText = (state) => state.selection?.kind === "text" && chunkZ5EEDCRI_cjs.markRanges(state).length > 0;
160
162
  var requestComment = (state, dispatch) => {
161
163
  const { selection } = state;
162
- if (selection?.kind !== "text" || chunkFK7EBZPX_cjs.getPluginState(state, commentsKey).pending.length > 0) return false;
163
- const ranges = chunkFK7EBZPX_cjs.markRanges(state);
164
+ if (selection?.kind !== "text" || chunkZ5EEDCRI_cjs.getPluginState(state, commentsKey).pending.length > 0) return false;
165
+ const ranges = chunkZ5EEDCRI_cjs.markRanges(state);
164
166
  if (ranges.length === 0) return false;
165
167
  if (dispatch === void 0) return true;
166
168
  const pending = { key: ++nextKey, ranges, selection };
167
169
  const action = { type: "pending", pending };
168
- dispatch(new chunkFK7EBZPX_cjs.Transaction(state).setMeta(COMMENTS, action).setMeta("addToHistory", false));
170
+ dispatch(new chunkZ5EEDCRI_cjs.Transaction(state).setMeta(COMMENTS, action).setMeta("addToHistory", false));
169
171
  return true;
170
172
  };
171
173
  function settledTransaction(editor, key, id) {
172
- const pending = chunkFK7EBZPX_cjs.getPluginState(editor.state, commentsKey).pending.find((anchor) => anchor.key === key);
174
+ const pending = chunkZ5EEDCRI_cjs.getPluginState(editor.state, commentsKey).pending.find((anchor) => anchor.key === key);
173
175
  const tr = editor.createTransaction().setOrigin("command");
174
176
  const ranges = id === null ? [] : pending?.ranges ?? [];
175
177
  for (const { block, region, from, to } of ranges) {
176
- tr.step(chunkFK7EBZPX_cjs.addMarkStep(block, region, from, to, { type: "comment", attrs: { id } }));
178
+ tr.step(chunkZ5EEDCRI_cjs.addMarkStep(block, region, from, to, { type: "comment", attrs: { id } }));
177
179
  }
178
- const untouched = pending !== void 0 && chunkFK7EBZPX_cjs.sameSelection(editor.state.selection, pending.selection);
180
+ const untouched = pending !== void 0 && chunkZ5EEDCRI_cjs.sameSelection(editor.state.selection, pending.selection);
179
181
  const open = id !== null && ranges.length > 0 && untouched ? { ids: [id], focus: true } : void 0;
180
182
  const action = { type: "settled", key, open };
181
183
  return tr.setMeta(COMMENTS, action);
@@ -186,7 +188,7 @@ function create(editor, pending, onCreate, link) {
186
188
  if (link.mounts === 0) return;
187
189
  const tr = settledTransaction(editor, pending.key, id);
188
190
  editor.dispatch(tr);
189
- if (id === null) link.report(chunkEBSDPHPS_cjs.toError(error));
191
+ if (id === null) link.report(chunk4UFWFV43_cjs.toError(error));
190
192
  else if (!tr.docChanged) link.report(new Error(`Comment thread ${id} has no text: it was deleted meanwhile`));
191
193
  };
192
194
  new Promise((resolve) => resolve(onCreate(input))).then(
@@ -203,20 +205,20 @@ function watchCreates(editor, onCreate, link) {
203
205
 
204
206
  // src/extensions/comments/comment-open.ts
205
207
  function openIds(state, threads, ids) {
206
- const { ended } = chunkFK7EBZPX_cjs.getPluginState(state, commentsKey);
208
+ const { ended } = chunkZ5EEDCRI_cjs.getPluginState(state, commentsKey);
207
209
  return ids.filter((id) => {
208
210
  const thread = threads.find(id);
209
211
  return thread?.resolved === false && !isEnded(ended, id, thread);
210
212
  });
211
213
  }
212
214
  function commentsTransaction(state, action) {
213
- return new chunkFK7EBZPX_cjs.Transaction(state).setMeta(COMMENTS, action).setMeta("addToHistory", false);
215
+ return new chunkZ5EEDCRI_cjs.Transaction(state).setMeta(COMMENTS, action).setMeta("addToHistory", false);
214
216
  }
215
217
  function commentCommand(threads) {
216
218
  return (state, dispatch) => {
217
219
  if (requestComment(state, dispatch)) return true;
218
220
  const { selection } = state;
219
- if (selection?.kind !== "text" || !chunkFK7EBZPX_cjs.isCollapsed(selection)) return false;
221
+ if (selection?.kind !== "text" || !chunkZ5EEDCRI_cjs.isCollapsed(selection)) return false;
220
222
  const ids = openIds(state, threads, commentIdsAt(state.doc, selection.head));
221
223
  if (ids.length === 0) return false;
222
224
  dispatch?.(commentsTransaction(state, { type: "open", open: { ids, focus: true } }));
@@ -290,7 +292,7 @@ function place(controller, box, gap) {
290
292
  root.style.setProperty(HEIGHT, `${bottom}px`);
291
293
  }
292
294
  function useBlockAligned(controller, box, gap, key) {
293
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
295
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
294
296
  const element = box.current;
295
297
  const view = element?.ownerDocument.defaultView;
296
298
  if (!element || !view) return void 0;
@@ -334,10 +336,10 @@ function CommentMarkers({ env, box, entries, onOpen }) {
334
336
  "data-rail-item": "",
335
337
  "data-block": block,
336
338
  "aria-label": env.labels.showComments(ids.length),
337
- className: chunkEBSDPHPS_cjs.cn("quoin-comments-marker", chunkEBSDPHPS_cjs.FOCUS_RING),
339
+ className: chunk4UFWFV43_cjs.cn("quoin-comments-marker", chunk4UFWFV43_cjs.FOCUS_RING),
338
340
  onClick: (event) => onOpen(ids[0], event.currentTarget),
339
341
  children: [
340
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.MessageSquare, { "aria-hidden": "true" }),
342
+ /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.MessageSquare, { "aria-hidden": "true" }),
341
343
  ids.length
342
344
  ]
343
345
  },
@@ -351,7 +353,7 @@ async function called(link, call) {
351
353
  await call();
352
354
  return true;
353
355
  } catch (error) {
354
- link.report(chunkEBSDPHPS_cjs.toError(error));
356
+ link.report(chunk4UFWFV43_cjs.toError(error));
355
357
  return false;
356
358
  }
357
359
  }
@@ -366,7 +368,7 @@ function sendReply(link, call, id, body) {
366
368
  }
367
369
  var initials = (name) => name.trim().split(/\s+/).slice(0, 2).map((word) => Array.from(word)[0]?.toUpperCase() ?? "").join("");
368
370
  function CommentAvatar({ author }) {
369
- const picture = chunkLM3DHROX_cjs.webAddress(author.avatarUrl);
371
+ const picture = chunk5AUIA4B3_cjs.webAddress(author.avatarUrl);
370
372
  const [failed, setFailed] = react.useState(null);
371
373
  if (picture !== null && picture !== failed) {
372
374
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -444,21 +446,21 @@ function ReplyBox({ env, threadId, first }) {
444
446
  }
445
447
  ),
446
448
  /* @__PURE__ */ jsxRuntime.jsx(
447
- chunkEBSDPHPS_cjs.Button,
449
+ chunk4UFWFV43_cjs.Button,
448
450
  {
449
451
  type: "submit",
450
452
  variant: "ghost",
451
453
  size: "icon-sm",
452
454
  "aria-label": labels.send,
453
455
  "aria-disabled": text === "" || sending || void 0,
454
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.SendHorizontal, {})
456
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.SendHorizontal, {})
455
457
  }
456
458
  )
457
459
  ] });
458
460
  }
459
461
  function ThreadView({ env, id, thread, onEnded }) {
460
462
  const { controller, host, labels, link } = env;
461
- const readOnly = chunk2QKFRKOP_cjs.useReadOnly(controller);
463
+ const readOnly = chunkN25EH2GZ_cjs.useReadOnly(controller);
462
464
  const [busy, setBusy] = react.useState(false);
463
465
  const alive = react.useRef(true);
464
466
  const root = react.useRef(null);
@@ -479,11 +481,11 @@ function ThreadView({ env, id, thread, onEnded }) {
479
481
  if (ended && stayed) onEnded();
480
482
  };
481
483
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: root, className: "flex flex-col gap-3", children: [
482
- comments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex flex-col gap-3", children: comments.map((comment) => /* @__PURE__ */ jsxRuntime.jsx(CommentItem, { comment, labels }, comment.id)) }),
484
+ comments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex list-none flex-col gap-3", children: comments.map((comment) => /* @__PURE__ */ jsxRuntime.jsx(CommentItem, { comment, labels }, comment.id)) }),
483
485
  /* @__PURE__ */ jsxRuntime.jsx(ReplyBox, { env, threadId: id, first: comments.length === 0 }),
484
486
  !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-1", children: [
485
487
  /* @__PURE__ */ jsxRuntime.jsx(
486
- chunkEBSDPHPS_cjs.Button,
488
+ chunk4UFWFV43_cjs.Button,
487
489
  {
488
490
  type: "button",
489
491
  variant: "ghost",
@@ -494,7 +496,7 @@ function ThreadView({ env, id, thread, onEnded }) {
494
496
  }
495
497
  ),
496
498
  /* @__PURE__ */ jsxRuntime.jsx(
497
- chunkEBSDPHPS_cjs.Button,
499
+ chunk4UFWFV43_cjs.Button,
498
500
  {
499
501
  type: "button",
500
502
  variant: "ghost",
@@ -531,7 +533,7 @@ function ThreadCard({ env, entry, active, expanded, onToggle }) {
531
533
  ref: header,
532
534
  type: "button",
533
535
  "aria-expanded": expanded,
534
- className: chunkEBSDPHPS_cjs.cn("flex w-full flex-col items-start gap-1 rounded-sm text-start", chunkEBSDPHPS_cjs.FOCUS_RING),
536
+ className: chunk4UFWFV43_cjs.cn("flex w-full flex-col items-start gap-1 rounded-sm text-start", chunk4UFWFV43_cjs.FOCUS_RING),
535
537
  onClick: () => onToggle(expanded ? null : thread.id),
536
538
  children: [
537
539
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: removed ? "text-xs text-muted-foreground italic" : "quoin-comments-quote", children: removed ? labels.textRemoved : anchorText2 }),
@@ -551,7 +553,7 @@ var GAP2 = 8;
551
553
  var layoutKey = (entries, value) => `${value.active} ${value.open !== null} ${entries.map(({ thread, ranges }) => `${thread.id}:${ranges[0]?.block}`)}`;
552
554
  function CommentsRail({ env, box, entries, value, onToggle }) {
553
555
  useBlockAligned(env.controller, box, GAP2, layoutKey(entries, value));
554
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: box, className: "quoin-comments-rail", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": env.labels.comments, children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsx("li", { "data-rail-item": "", "data-block": entry.ranges[0]?.block ?? "", children: /* @__PURE__ */ jsxRuntime.jsx(
556
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: box, className: "quoin-comments-rail", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": env.labels.comments, className: "list-none", children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsx("li", { "data-rail-item": "", "data-block": entry.ranges[0]?.block ?? "", children: /* @__PURE__ */ jsxRuntime.jsx(
555
557
  ThreadCard,
556
558
  {
557
559
  env,
@@ -565,6 +567,7 @@ function CommentsRail({ env, box, entries, value, onToggle }) {
565
567
  function CommentsSheet({ env, entries, value, onToggle, onClose, returnFocus }) {
566
568
  const { labels } = env;
567
569
  const content = react.useRef(null);
570
+ const dir = reactDirection.useDirection();
568
571
  const outside = react.useRef(false);
569
572
  const focusOpened = (event) => {
570
573
  const opened = content.current?.querySelector('[aria-expanded="true"]');
@@ -584,6 +587,7 @@ function CommentsSheet({ env, entries, value, onToggle, onClose, returnFocus })
584
587
  DialogPrimitive__namespace.Content,
585
588
  {
586
589
  ref: content,
590
+ dir,
587
591
  "aria-describedby": void 0,
588
592
  className: "quoin quoin-comments-sheet",
589
593
  onOpenAutoFocus: focusOpened,
@@ -597,9 +601,9 @@ function CommentsSheet({ env, entries, value, onToggle, onClose, returnFocus })
597
601
  children: [
598
602
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
599
603
  /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Title, { className: "text-sm font-semibold", children: labels.comments }),
600
- /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.close, children: /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.X, {}) }) })
604
+ /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": labels.close, children: /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.X, {}) }) })
601
605
  ] }),
602
- /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": labels.comments, className: "flex flex-col gap-2", children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
606
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": labels.comments, className: "flex list-none flex-col gap-2", children: entries.map((entry) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
603
607
  ThreadCard,
604
608
  {
605
609
  env,
@@ -624,11 +628,11 @@ function railEntries(doc, threads, ended = []) {
624
628
  const ranges = anchors.get(thread.id) ?? NONE;
625
629
  return { thread, ranges, anchorText: anchorText(doc, ranges) };
626
630
  });
627
- const place2 = ({ ranges: [first] }) => first === void 0 ? [Infinity, 0] : [chunkI7X7B3WD_cjs.indexOfBlock(doc, first.block), first.from];
631
+ const place2 = ({ ranges: [first] }) => first === void 0 ? [Infinity, 0] : [chunk4JDRDPLC_cjs.indexOfBlock(doc, first.block), first.from];
628
632
  return entries.map((entry, order) => ({ entry, order, at: place2(entry) })).sort((a, b) => a.at[0] - b.at[0] || a.at[1] - b.at[1] || a.order - b.order).map(({ entry }) => entry);
629
633
  }
630
634
  function ThreadChooser({ env, choices, onChoose }) {
631
- return /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": env.labels.threadsHere, className: "flex flex-col gap-1", children: choices.map(({ id, anchorText: anchorText2, preview }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
635
+ return /* @__PURE__ */ jsxRuntime.jsx("ul", { "aria-label": env.labels.threadsHere, className: "flex list-none flex-col gap-1", children: choices.map(({ id, anchorText: anchorText2, preview }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
632
636
  "button",
633
637
  {
634
638
  type: "button",
@@ -644,22 +648,22 @@ function ThreadChooser({ env, choices, onChoose }) {
644
648
  var docOf = (state) => state.doc;
645
649
  function focusIsOurs(controller, content) {
646
650
  const active = content?.ownerDocument.activeElement ?? null;
647
- return active === null || active === active.ownerDocument.body || chunk3HW3WRYC_cjs.ownsNode(controller, active);
651
+ return active === null || active === active.ownerDocument.body || chunkCSIUXYRU_cjs.ownsNode(controller, active);
648
652
  }
649
653
  function ThreadPopover({ env, open, threads, onChoose, onClose }) {
650
654
  const { controller, labels } = env;
651
- const doc = chunk2QKFRKOP_cjs.useEditorState(controller, docOf);
655
+ const doc = chunkN25EH2GZ_cjs.useEditorState(controller, docOf);
652
656
  const anchors = commentAnchors(doc);
653
657
  const { ids } = open;
654
658
  const first = ids.map((id) => anchors.get(id)?.[0]).find(Boolean);
655
659
  const latest = react.useRef(first);
656
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
660
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
657
661
  if (first) latest.current = first;
658
662
  });
659
663
  const anchor = react.useMemo(
660
664
  () => ({
661
- current: chunkEBSDPHPS_cjs.virtualAnchor(
662
- () => latest.current ? chunkEBSDPHPS_cjs.rangeRect(controller, latest.current) : null,
665
+ current: chunk4UFWFV43_cjs.virtualAnchor(
666
+ () => latest.current ? chunk4UFWFV43_cjs.rangeRect(controller, latest.current) : null,
663
667
  () => latest.current && controller.registry.get(latest.current.block, latest.current.region)
664
668
  )
665
669
  }),
@@ -672,7 +676,7 @@ function ThreadPopover({ env, open, threads, onChoose, onClose }) {
672
676
  target?.focus();
673
677
  }
674
678
  };
675
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
679
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
676
680
  if (open.focus) focusField();
677
681
  }, [open]);
678
682
  if (first === void 0 && latest.current === void 0) return null;
@@ -693,7 +697,7 @@ function ThreadPopover({ env, open, threads, onChoose, onClose }) {
693
697
  };
694
698
  const choices = ids.map((id) => ({ id, anchorText: textOf(id), preview: threads.find(id)?.comments[0]?.body ?? "" }));
695
699
  return /* @__PURE__ */ jsxRuntime.jsxs(
696
- chunkEBSDPHPS_cjs.Popover,
700
+ chunk4UFWFV43_cjs.Popover,
697
701
  {
698
702
  open: true,
699
703
  modal: false,
@@ -701,9 +705,9 @@ function ThreadPopover({ env, open, threads, onChoose, onClose }) {
701
705
  if (!next) onClose();
702
706
  },
703
707
  children: [
704
- /* @__PURE__ */ jsxRuntime.jsx(chunkEBSDPHPS_cjs.PopoverAnchor, { virtualRef: anchor }),
708
+ /* @__PURE__ */ jsxRuntime.jsx(chunk4UFWFV43_cjs.PopoverAnchor, { virtualRef: anchor }),
705
709
  /* @__PURE__ */ jsxRuntime.jsxs(
706
- chunkEBSDPHPS_cjs.PopoverContent,
710
+ chunk4UFWFV43_cjs.PopoverContent,
707
711
  {
708
712
  ref: content,
709
713
  "aria-label": gone ? labels.textRemoved : single ? labels.thread(textOf(ids[0])) : labels.threadsHere,
@@ -751,7 +755,7 @@ function useAnchorClicks(controller, threads) {
751
755
  var WIDE_CANVAS = 800;
752
756
  function useCanvasWide(box, initial) {
753
757
  const [wide, setWide] = react.useState(initial);
754
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
758
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
755
759
  const canvas = box.current?.parentElement;
756
760
  if (!canvas) return void 0;
757
761
  const measure = () => setWide(canvas.offsetWidth >= WIDE_CANVAS);
@@ -765,18 +769,18 @@ function useCanvasWide(box, initial) {
765
769
  function useThreads(threads) {
766
770
  return react.useSyncExternalStore(threads.subscribe, threads.get, threads.get);
767
771
  }
768
- var commentsOf = (state) => chunkFK7EBZPX_cjs.getPluginState(state, commentsKey);
772
+ var commentsOf = (state) => chunkZ5EEDCRI_cjs.getPluginState(state, commentsKey);
769
773
  var docOf2 = (state) => state.doc;
770
774
  function CommentsOverlay({ controller, host, labels }) {
771
- const { onError } = chunkEBSDPHPS_cjs.useQuoin();
775
+ const { onError } = chunk4UFWFV43_cjs.useQuoin();
772
776
  const link = linkOf(controller.editor);
773
- chunk2QKFRKOP_cjs.useIsomorphicLayoutEffect(() => {
777
+ chunkN25EH2GZ_cjs.useIsomorphicLayoutEffect(() => {
774
778
  link.report = onError;
775
779
  }, [link, onError]);
776
780
  useAnchorClicks(controller, host.threads);
777
781
  const threads = useThreads(host.threads);
778
- const value = chunk2QKFRKOP_cjs.useEditorState(controller, commentsOf);
779
- const doc = chunk2QKFRKOP_cjs.useEditorState(controller, docOf2);
782
+ const value = chunkN25EH2GZ_cjs.useEditorState(controller, commentsOf);
783
+ const doc = chunkN25EH2GZ_cjs.useEditorState(controller, docOf2);
780
784
  const entries = react.useMemo(() => railEntries(doc, threads, value.ended), [doc, threads, value.ended]);
781
785
  const box = react.useRef(null);
782
786
  const wide = useCanvasWide(box, host.initialLayout === "wide");
@@ -836,7 +840,7 @@ var ACTIVE = { class: "quoin-comment-active" };
836
840
  var inline = (ranges, attrs) => ranges.map((range) => ({ kind: "inline", ...range, attrs }));
837
841
  var drawn = /* @__PURE__ */ new WeakMap();
838
842
  function commentsDecorations(state) {
839
- const value = chunkFK7EBZPX_cjs.getPluginState(state, commentsKey);
843
+ const value = chunkZ5EEDCRI_cjs.getPluginState(state, commentsKey);
840
844
  const last = drawn.get(value);
841
845
  if (last?.doc === state.doc) return last.decorations;
842
846
  const active = value.active === null ? [] : commentAnchors(state.doc).get(value.active) ?? [];
@@ -848,7 +852,7 @@ function commentsDecorations(state) {
848
852
  // src/extensions/comments/watch-ended.ts
849
853
  function watchEnded(editor, threads) {
850
854
  return threads.subscribe(() => {
851
- const { ended } = chunkFK7EBZPX_cjs.getPluginState(editor.state, commentsKey);
855
+ const { ended } = chunkZ5EEDCRI_cjs.getPluginState(editor.state, commentsKey);
852
856
  const kept = ended.filter(({ id }) => isEnded(ended, id, threads.find(id)));
853
857
  if (kept.length < ended.length) editor.dispatch(commentsTransaction(editor.state, { type: "caught", kept }));
854
858
  });
@@ -856,9 +860,9 @@ function watchEnded(editor, threads) {
856
860
  var commentItem = (labels) => ({
857
861
  id: "comment",
858
862
  title: labels.comment,
859
- icon: chunkEBSDPHPS_cjs.MessageSquarePlus,
863
+ icon: chunk4UFWFV43_cjs.MessageSquarePlus,
860
864
  shortcut: "Mod-Alt-m",
861
- available: (state) => hasCommentableText(state) && chunkFK7EBZPX_cjs.getPluginState(state, commentsKey).pending.length === 0,
865
+ available: (state) => hasCommentableText(state) && chunkZ5EEDCRI_cjs.getPluginState(state, commentsKey).pending.length === 0,
862
866
  // Focus goes back to the text first: the button leaves the toolbar while the thread is being asked for.
863
867
  run: (controller) => {
864
868
  controller.focus();
@@ -872,7 +876,7 @@ function commentsExtension(options) {
872
876
  return /* @__PURE__ */ jsxRuntime.jsx(CommentsOverlay, { controller, host, labels });
873
877
  }
874
878
  const ui = { bubbleItems: [commentItem(labels)], overlays: [Overlay] };
875
- return chunkFK7EBZPX_cjs.defineExtension({
879
+ return chunkZ5EEDCRI_cjs.defineExtension({
876
880
  name: "comments",
877
881
  plugins: [commentsPlugin],
878
882
  decorations: commentsDecorations,
@@ -919,6 +923,64 @@ function createCommentThreads(initial = NO_THREADS) {
919
923
  };
920
924
  }
921
925
 
926
+ // src/extensions/comments/shared-threads.ts
927
+ var byTime = (a, b) => (a.createdAt ?? "").localeCompare(b.createdAt ?? "") || a.id.localeCompare(b.id);
928
+ function readThreads(metas, replies) {
929
+ const comments = /* @__PURE__ */ new Map();
930
+ for (const { threadId, ...comment } of [...replies.values()].sort(byTime)) {
931
+ const list = comments.get(threadId);
932
+ if (list === void 0) comments.set(threadId, [comment]);
933
+ else list.push(comment);
934
+ }
935
+ return [...metas.values()].sort(byTime).map(({ id, resolved }) => ({ id, resolved, comments: comments.get(id) ?? [] }));
936
+ }
937
+
938
+ // src/extensions/comments/yjs-comment-threads.ts
939
+ function yjsCommentThreads(doc, options) {
940
+ const { currentUser, field = "comment" } = options;
941
+ const metas = doc.getMap(`${field}-threads`);
942
+ const replies = doc.getMap(`${field}-replies`);
943
+ const threads = createCommentThreads(readThreads(metas, replies));
944
+ const refresh = () => threads.set(readThreads(metas, replies));
945
+ const held = (threadId) => {
946
+ const meta = metas.get(threadId);
947
+ if (meta === void 0) throw new Error(`No comment thread "${threadId}" in the shared document.`);
948
+ return meta;
949
+ };
950
+ return {
951
+ threads,
952
+ async onCreate() {
953
+ const id = chunk4JDRDPLC_cjs.newId();
954
+ metas.set(id, { id, resolved: false, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
955
+ return id;
956
+ },
957
+ async onReply(threadId, body) {
958
+ held(threadId);
959
+ const id = chunk4JDRDPLC_cjs.newId();
960
+ replies.set(id, { id, threadId, author: currentUser, body, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
961
+ },
962
+ async onResolve(threadId) {
963
+ metas.set(threadId, { ...held(threadId), resolved: true });
964
+ },
965
+ async onDelete(threadId) {
966
+ doc.transact(() => {
967
+ metas.delete(threadId);
968
+ for (const comment of [...replies.values()]) if (comment.threadId === threadId) replies.delete(comment.id);
969
+ });
970
+ },
971
+ listen() {
972
+ refresh();
973
+ metas.observe(refresh);
974
+ replies.observe(refresh);
975
+ return () => {
976
+ metas.unobserve(refresh);
977
+ replies.unobserve(refresh);
978
+ };
979
+ }
980
+ };
981
+ }
982
+
922
983
  exports.commentsExtension = commentsExtension;
923
984
  exports.createCommentThreads = createCommentThreads;
924
985
  exports.englishCommentsLabels = englishCommentsLabels;
986
+ exports.yjsCommentThreads = yjsCommentThreads;
@@ -64,5 +64,38 @@ type CommentsOptions = {
64
64
  */
65
65
  declare function commentsExtension(options: CommentsOptions): Extension;
66
66
 
67
- export { CommentsLabels, commentsExtension, createCommentThreads };
68
- export type { CommentAuthor, CommentThread, CommentThreads, CommentUser, CommentsOptions, ThreadComment };
67
+ /** The part of a `Y.Map` that comment threads read and write. */
68
+ type YjsCommentsMap<T> = {
69
+ get(key: string): T | undefined;
70
+ has(key: string): boolean;
71
+ set(key: string, value: T): unknown;
72
+ delete(key: string): void;
73
+ values(): Iterable<T>;
74
+ observe(listener: () => void): void;
75
+ unobserve(listener: () => void): void;
76
+ };
77
+
78
+ /** The part of a `Y.Doc` that `yjsCommentThreads` reads and writes, so that this entry needs no Yjs types. */
79
+ type YjsCommentsDoc = {
80
+ getMap<T>(name: string): YjsCommentsMap<T>;
81
+ transact(change: () => void): unknown;
82
+ };
83
+ type YjsCommentThreadsOptions = {
84
+ /** Who writes the replies sent from this client, as given to `commentsExtension`. */
85
+ currentUser: CommentUser;
86
+ /** What the names of the two shared maps start with: `comment` gives `comment-threads` and `comment-replies`. */
87
+ field?: string;
88
+ };
89
+ type YjsCommentThreads = Pick<CommentsOptions, 'threads' | 'onCreate' | 'onReply' | 'onResolve' | 'onDelete'> & {
90
+ /** Reads the shared maps into `threads`, then follows them until the function it returns is called. */
91
+ listen(): () => void;
92
+ };
93
+ /**
94
+ * Comment threads kept in a Yjs document, so collaborators see each other's: each thread in one shared map and each
95
+ * comment in another, by its own id, so that replies sent at the same time all stay. Hand the store and the four
96
+ * callbacks to `commentsExtension`, and call `listen` while the canvas is mounted.
97
+ */
98
+ declare function yjsCommentThreads(doc: YjsCommentsDoc, options: YjsCommentThreadsOptions): YjsCommentThreads;
99
+
100
+ export { CommentsLabels, commentsExtension, createCommentThreads, yjsCommentThreads };
101
+ export type { CommentAuthor, CommentThread, CommentThreads, CommentUser, CommentsOptions, ThreadComment, YjsCommentThreads, YjsCommentThreadsOptions, YjsCommentsDoc, YjsCommentsMap };
@@ -64,5 +64,38 @@ type CommentsOptions = {
64
64
  */
65
65
  declare function commentsExtension(options: CommentsOptions): Extension;
66
66
 
67
- export { CommentsLabels, commentsExtension, createCommentThreads };
68
- export type { CommentAuthor, CommentThread, CommentThreads, CommentUser, CommentsOptions, ThreadComment };
67
+ /** The part of a `Y.Map` that comment threads read and write. */
68
+ type YjsCommentsMap<T> = {
69
+ get(key: string): T | undefined;
70
+ has(key: string): boolean;
71
+ set(key: string, value: T): unknown;
72
+ delete(key: string): void;
73
+ values(): Iterable<T>;
74
+ observe(listener: () => void): void;
75
+ unobserve(listener: () => void): void;
76
+ };
77
+
78
+ /** The part of a `Y.Doc` that `yjsCommentThreads` reads and writes, so that this entry needs no Yjs types. */
79
+ type YjsCommentsDoc = {
80
+ getMap<T>(name: string): YjsCommentsMap<T>;
81
+ transact(change: () => void): unknown;
82
+ };
83
+ type YjsCommentThreadsOptions = {
84
+ /** Who writes the replies sent from this client, as given to `commentsExtension`. */
85
+ currentUser: CommentUser;
86
+ /** What the names of the two shared maps start with: `comment` gives `comment-threads` and `comment-replies`. */
87
+ field?: string;
88
+ };
89
+ type YjsCommentThreads = Pick<CommentsOptions, 'threads' | 'onCreate' | 'onReply' | 'onResolve' | 'onDelete'> & {
90
+ /** Reads the shared maps into `threads`, then follows them until the function it returns is called. */
91
+ listen(): () => void;
92
+ };
93
+ /**
94
+ * Comment threads kept in a Yjs document, so collaborators see each other's: each thread in one shared map and each
95
+ * comment in another, by its own id, so that replies sent at the same time all stay. Hand the store and the four
96
+ * callbacks to `commentsExtension`, and call `listen` while the canvas is mounted.
97
+ */
98
+ declare function yjsCommentThreads(doc: YjsCommentsDoc, options: YjsCommentThreadsOptions): YjsCommentThreads;
99
+
100
+ export { CommentsLabels, commentsExtension, createCommentThreads, yjsCommentThreads };
101
+ export type { CommentAuthor, CommentThread, CommentThreads, CommentUser, CommentsOptions, ThreadComment, YjsCommentThreads, YjsCommentThreadsOptions, YjsCommentsDoc, YjsCommentsMap };