quoin-editor 0.4.2 → 1.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 (231) hide show
  1. package/CHANGELOG.md +205 -0
  2. package/MIGRATION.md +233 -0
  3. package/README.md +78 -716
  4. package/dist/ai.cjs +1107 -0
  5. package/dist/ai.cjs.map +1 -0
  6. package/dist/ai.d.cts +68 -0
  7. package/dist/ai.d.ts +68 -0
  8. package/dist/ai.js +1107 -0
  9. package/dist/ai.js.map +1 -0
  10. package/dist/catalogue.cjs +59 -0
  11. package/dist/catalogue.cjs.map +1 -0
  12. package/dist/catalogue.d.cts +39 -0
  13. package/dist/catalogue.d.ts +39 -0
  14. package/dist/catalogue.js +59 -0
  15. package/dist/catalogue.js.map +1 -0
  16. package/dist/chunk-2QCRZ7OL.cjs +319 -0
  17. package/dist/chunk-2QCRZ7OL.cjs.map +1 -0
  18. package/dist/chunk-2VDK27IF.cjs +6666 -0
  19. package/dist/chunk-2VDK27IF.cjs.map +1 -0
  20. package/dist/chunk-47MLKSI2.js +326 -0
  21. package/dist/chunk-47MLKSI2.js.map +1 -0
  22. package/dist/chunk-5DNCCN6X.cjs +326 -0
  23. package/dist/chunk-5DNCCN6X.cjs.map +1 -0
  24. package/dist/chunk-AEJXZBVR.cjs +1378 -0
  25. package/dist/chunk-AEJXZBVR.cjs.map +1 -0
  26. package/dist/chunk-CDELOHDY.cjs +239 -0
  27. package/dist/chunk-CDELOHDY.cjs.map +1 -0
  28. package/dist/chunk-E75EHRPA.cjs +175 -0
  29. package/dist/chunk-E75EHRPA.cjs.map +1 -0
  30. package/dist/chunk-EL2OEJQC.cjs +562 -0
  31. package/dist/chunk-EL2OEJQC.cjs.map +1 -0
  32. package/dist/chunk-GLLXHMH2.cjs +25 -0
  33. package/dist/chunk-GLLXHMH2.cjs.map +1 -0
  34. package/dist/chunk-GTTPVJSD.cjs +3286 -0
  35. package/dist/chunk-GTTPVJSD.cjs.map +1 -0
  36. package/dist/chunk-HELJTLNC.cjs +100 -0
  37. package/dist/chunk-HELJTLNC.cjs.map +1 -0
  38. package/dist/chunk-HJIQT3S5.js +4047 -0
  39. package/dist/chunk-HJIQT3S5.js.map +1 -0
  40. package/dist/chunk-HZSSEYJS.cjs +504 -0
  41. package/dist/chunk-HZSSEYJS.cjs.map +1 -0
  42. package/dist/chunk-JDPTZUBW.js +184 -0
  43. package/dist/chunk-JDPTZUBW.js.map +1 -0
  44. package/dist/chunk-JEIFJHEI.js +14 -0
  45. package/dist/chunk-JEIFJHEI.js.map +1 -0
  46. package/dist/chunk-K574XHMM.js +25 -0
  47. package/dist/chunk-K574XHMM.js.map +1 -0
  48. package/dist/chunk-KAVU6T6J.js +249 -0
  49. package/dist/chunk-KAVU6T6J.js.map +1 -0
  50. package/dist/chunk-KXOBZGQO.js +1378 -0
  51. package/dist/chunk-KXOBZGQO.js.map +1 -0
  52. package/dist/chunk-LCQSG4M6.js +3335 -0
  53. package/dist/chunk-LCQSG4M6.js.map +1 -0
  54. package/dist/chunk-MQ2XQ4MX.js +100 -0
  55. package/dist/chunk-MQ2XQ4MX.js.map +1 -0
  56. package/dist/chunk-ND5XJVK2.cjs +3335 -0
  57. package/dist/chunk-ND5XJVK2.cjs.map +1 -0
  58. package/dist/chunk-NNDYYEW5.js +504 -0
  59. package/dist/chunk-NNDYYEW5.js.map +1 -0
  60. package/dist/chunk-NOKWNK2O.js +319 -0
  61. package/dist/chunk-NOKWNK2O.js.map +1 -0
  62. package/dist/chunk-OMOBMXD5.cjs +57 -0
  63. package/dist/chunk-OMOBMXD5.cjs.map +1 -0
  64. package/dist/chunk-PMWCQSQX.js +239 -0
  65. package/dist/chunk-PMWCQSQX.js.map +1 -0
  66. package/dist/chunk-POBM7MGR.js +30 -0
  67. package/dist/chunk-POBM7MGR.js.map +1 -0
  68. package/dist/chunk-PWUEPDA3.cjs +598 -0
  69. package/dist/chunk-PWUEPDA3.cjs.map +1 -0
  70. package/dist/chunk-PZ4GT5JO.cjs +4047 -0
  71. package/dist/chunk-PZ4GT5JO.cjs.map +1 -0
  72. package/dist/chunk-QAW5NH6S.cjs +14 -0
  73. package/dist/chunk-QAW5NH6S.cjs.map +1 -0
  74. package/dist/chunk-RDG4VI6E.cjs +706 -0
  75. package/dist/chunk-RDG4VI6E.cjs.map +1 -0
  76. package/dist/chunk-RUDWMKYX.js +562 -0
  77. package/dist/chunk-RUDWMKYX.js.map +1 -0
  78. package/dist/chunk-SG37UBDO.js +706 -0
  79. package/dist/chunk-SG37UBDO.js.map +1 -0
  80. package/dist/chunk-SLVDAHHK.cjs +30 -0
  81. package/dist/chunk-SLVDAHHK.cjs.map +1 -0
  82. package/dist/chunk-T7SW6OWV.js +598 -0
  83. package/dist/chunk-T7SW6OWV.js.map +1 -0
  84. package/dist/chunk-TC4DARU2.js +175 -0
  85. package/dist/chunk-TC4DARU2.js.map +1 -0
  86. package/dist/chunk-WQHV3MRE.cjs +184 -0
  87. package/dist/chunk-WQHV3MRE.cjs.map +1 -0
  88. package/dist/chunk-WXMYDXPN.cjs +33 -0
  89. package/dist/chunk-WXMYDXPN.cjs.map +1 -0
  90. package/dist/chunk-XEBWC7ZL.js +57 -0
  91. package/dist/chunk-XEBWC7ZL.js.map +1 -0
  92. package/dist/chunk-ZC24WB7Y.cjs +249 -0
  93. package/dist/chunk-ZC24WB7Y.cjs.map +1 -0
  94. package/dist/chunk-ZGZEJCRV.js +6666 -0
  95. package/dist/chunk-ZGZEJCRV.js.map +1 -0
  96. package/dist/chunk-ZHOSSWUM.js +33 -0
  97. package/dist/chunk-ZHOSSWUM.js.map +1 -0
  98. package/dist/chunk-ZS2WA357.js +3286 -0
  99. package/dist/chunk-ZS2WA357.js.map +1 -0
  100. package/dist/comments.cjs +993 -0
  101. package/dist/comments.cjs.map +1 -0
  102. package/dist/comments.d.cts +88 -0
  103. package/dist/comments.d.ts +88 -0
  104. package/dist/comments.js +993 -0
  105. package/dist/comments.js.map +1 -0
  106. package/dist/diff.cjs +343 -0
  107. package/dist/diff.cjs.map +1 -0
  108. package/dist/diff.d.cts +67 -0
  109. package/dist/diff.d.ts +67 -0
  110. package/dist/diff.js +343 -0
  111. package/dist/diff.js.map +1 -0
  112. package/dist/docx.cjs +854 -0
  113. package/dist/docx.cjs.map +1 -0
  114. package/dist/docx.d.cts +27 -0
  115. package/dist/docx.d.ts +27 -0
  116. package/dist/docx.js +854 -0
  117. package/dist/docx.js.map +1 -0
  118. package/dist/embed-provider-jXwlRmnp.d.cts +19 -0
  119. package/dist/embed-provider-jXwlRmnp.d.ts +19 -0
  120. package/dist/embed.cjs +17 -0
  121. package/dist/embed.cjs.map +1 -0
  122. package/dist/embed.d.cts +56 -0
  123. package/dist/embed.d.ts +56 -0
  124. package/dist/embed.js +17 -0
  125. package/dist/embed.js.map +1 -0
  126. package/dist/emoji-data.cjs +1968 -0
  127. package/dist/emoji-data.cjs.map +1 -0
  128. package/dist/emoji-data.js +1968 -0
  129. package/dist/emoji-data.js.map +1 -0
  130. package/dist/emoji-extension-C12gDPm6.d.cts +46 -0
  131. package/dist/emoji-extension-DpQ43HjE.d.ts +46 -0
  132. package/dist/emoji.cjs +18 -0
  133. package/dist/emoji.cjs.map +1 -0
  134. package/dist/emoji.d.cts +31 -0
  135. package/dist/emoji.d.ts +31 -0
  136. package/dist/emoji.js +18 -0
  137. package/dist/emoji.js.map +1 -0
  138. package/dist/engine.cjs +119 -0
  139. package/dist/engine.cjs.map +1 -0
  140. package/dist/engine.d.cts +144 -0
  141. package/dist/engine.d.ts +144 -0
  142. package/dist/engine.js +119 -0
  143. package/dist/engine.js.map +1 -0
  144. package/dist/find-extension-DKqLLSuP.d.ts +41 -0
  145. package/dist/find-extension-_sbZEt3R.d.cts +41 -0
  146. package/dist/find.cjs +20 -0
  147. package/dist/find.cjs.map +1 -0
  148. package/dist/find.d.cts +44 -0
  149. package/dist/find.d.ts +44 -0
  150. package/dist/find.js +20 -0
  151. package/dist/find.js.map +1 -0
  152. package/dist/headless.cjs +151 -518
  153. package/dist/headless.cjs.map +1 -1
  154. package/dist/headless.d.cts +102 -69
  155. package/dist/headless.d.ts +102 -69
  156. package/dist/headless.js +149 -467
  157. package/dist/headless.js.map +1 -1
  158. package/dist/index-CgD72kHB.d.cts +65 -0
  159. package/dist/index-DNYbTK3w.d.ts +65 -0
  160. package/dist/index.cjs +183 -2753
  161. package/dist/index.cjs.map +1 -1
  162. package/dist/index.d.cts +345 -253
  163. package/dist/index.d.ts +345 -253
  164. package/dist/index.js +168 -2696
  165. package/dist/index.js.map +1 -1
  166. package/dist/math.cjs +18 -0
  167. package/dist/math.cjs.map +1 -0
  168. package/dist/math.d.cts +49 -0
  169. package/dist/math.d.ts +49 -0
  170. package/dist/math.js +18 -0
  171. package/dist/math.js.map +1 -0
  172. package/dist/mention.cjs +18 -0
  173. package/dist/mention.cjs.map +1 -0
  174. package/dist/mention.d.cts +50 -0
  175. package/dist/mention.d.ts +50 -0
  176. package/dist/mention.js +18 -0
  177. package/dist/mention.js.map +1 -0
  178. package/dist/presence.cjs +565 -0
  179. package/dist/presence.cjs.map +1 -0
  180. package/dist/presence.d.cts +30 -0
  181. package/dist/presence.d.ts +30 -0
  182. package/dist/presence.js +565 -0
  183. package/dist/presence.js.map +1 -0
  184. package/dist/registry-CWBOSAHm.d.cts +121 -0
  185. package/dist/registry-CWBOSAHm.d.ts +121 -0
  186. package/dist/stats-extension-Bly88uio.d.ts +40 -0
  187. package/dist/stats-extension-CJPijvUb.d.cts +40 -0
  188. package/dist/stats.cjs +19 -0
  189. package/dist/stats.cjs.map +1 -0
  190. package/dist/stats.d.cts +19 -0
  191. package/dist/stats.d.ts +19 -0
  192. package/dist/stats.js +19 -0
  193. package/dist/stats.js.map +1 -0
  194. package/dist/styles.css +1 -1
  195. package/dist/table-extension-BTLxFy2S.d.cts +57 -0
  196. package/dist/table-extension-Dzf4k6hI.d.ts +57 -0
  197. package/dist/table.cjs +50 -0
  198. package/dist/table.cjs.map +1 -0
  199. package/dist/table.d.cts +57 -0
  200. package/dist/table.d.ts +57 -0
  201. package/dist/table.js +50 -0
  202. package/dist/table.js.map +1 -0
  203. package/dist/to-html-C5t7xyaM.d.ts +21 -0
  204. package/dist/to-html-CNCITCln.d.cts +21 -0
  205. package/dist/toc-extension-B3-s6h2x.d.cts +25 -0
  206. package/dist/toc-extension-DWm5alVj.d.ts +25 -0
  207. package/dist/toc.cjs +18 -0
  208. package/dist/toc.cjs.map +1 -0
  209. package/dist/toc.d.cts +24 -0
  210. package/dist/toc.d.ts +24 -0
  211. package/dist/toc.js +18 -0
  212. package/dist/toc.js.map +1 -0
  213. package/dist/types-Cz7XJLaK.d.cts +366 -0
  214. package/dist/types-DULc8wwg.d.cts +120 -0
  215. package/dist/types-DULc8wwg.d.ts +120 -0
  216. package/dist/types-a1CRBlEh.d.ts +366 -0
  217. package/dist/view-controller-DSHw0ltQ.d.cts +118 -0
  218. package/dist/view-controller-UbpzblGl.d.ts +118 -0
  219. package/dist/view.cjs +23 -0
  220. package/dist/view.cjs.map +1 -0
  221. package/dist/view.d.cts +40 -0
  222. package/dist/view.d.ts +40 -0
  223. package/dist/view.js +23 -0
  224. package/dist/view.js.map +1 -0
  225. package/dist/yjs.cjs +1026 -0
  226. package/dist/yjs.cjs.map +1 -0
  227. package/dist/yjs.d.cts +22 -0
  228. package/dist/yjs.d.ts +22 -0
  229. package/dist/yjs.js +1026 -0
  230. package/dist/yjs.js.map +1 -0
  231. package/package.json +217 -18
package/dist/ai.cjs ADDED
@@ -0,0 +1,1107 @@
1
+ 'use client';"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
+
3
+
4
+ var _chunkQAW5NH6Scjs = require('./chunk-QAW5NH6S.cjs');
5
+
6
+
7
+ var _chunkWXMYDXPNcjs = require('./chunk-WXMYDXPN.cjs');
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+ var _chunk2VDK27IFcjs = require('./chunk-2VDK27IF.cjs');
21
+
22
+
23
+
24
+
25
+
26
+ var _chunkGTTPVJSDcjs = require('./chunk-GTTPVJSD.cjs');
27
+ require('./chunk-OMOBMXD5.cjs');
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+ var _chunkPZ4GT5JOcjs = require('./chunk-PZ4GT5JO.cjs');
51
+ require('./chunk-2QCRZ7OL.cjs');
52
+
53
+
54
+
55
+
56
+
57
+ var _chunkND5XJVK2cjs = require('./chunk-ND5XJVK2.cjs');
58
+
59
+ // src/extensions/ai/streaming-markdown.ts
60
+ var FENCE = /^ {0,3}(`{3,}|~{3,})/;
61
+ var MARKER_ONLY = /^\s*(?:[-*+]|\d+[.)]|#{1,6}|>)\s*$/;
62
+ var LINE_PREFIX = /^\s*(?:>\s?)*(?:(?:[-*+]|\d+[.)])\s+(?:\[[ xX]\]\s+)?|#{1,6}\s+)?/;
63
+ var BLOCK_START = /^\s*(?:[-*+]\s|\d+[.)]\s|#{1,6}\s|>)/;
64
+ var OPEN_ADDRESS = /\[([^\]]*)\]\(([^)\s]*)$/;
65
+ var OPEN_TEXT = /\[([^\]]*)$/;
66
+ var DOUBLE = ["**", "__", "~~"];
67
+ var WORD = /[\p{L}\p{N}]/u;
68
+ var isSpace = (char) => char === void 0 || /\s/.test(char);
69
+ function openFence(lines) {
70
+ let open = null;
71
+ for (const line of lines) {
72
+ const fence = _optionalChain([FENCE, 'access', _2 => _2.exec, 'call', _3 => _3(line), 'optionalAccess', _4 => _4[1]]);
73
+ if (open === null) open = _nullishCoalesce(fence, () => ( null));
74
+ else if (fence !== void 0 && fence[0] === open[0] && fence.length >= open.length && line.trim() === fence) {
75
+ open = null;
76
+ }
77
+ }
78
+ return open;
79
+ }
80
+ function closeLink(body) {
81
+ const address = OPEN_ADDRESS.exec(body);
82
+ if (address !== null) {
83
+ return address[2] === "" ? body.slice(0, address.index) + address[1] : `${body})`;
84
+ }
85
+ const text = OPEN_TEXT.exec(body);
86
+ return text === null ? body : body.slice(0, text.index) + text[1];
87
+ }
88
+ function tokenAt(body, at) {
89
+ const two = body.slice(at, at + 2);
90
+ if (DOUBLE.includes(two)) return two;
91
+ const one = body[at];
92
+ if (one === "*") return one;
93
+ if (one === "_" && !(WORD.test(_nullishCoalesce(body[at - 1], () => ( ""))) && WORD.test(_nullishCoalesce(body[at + 1], () => ( ""))))) return one;
94
+ return null;
95
+ }
96
+ function codeEnd(body, at) {
97
+ let end = at;
98
+ while (body[end] === "`") end++;
99
+ const run = body.slice(at, end);
100
+ const close = body.indexOf(run, end);
101
+ return { end: close === -1 ? -1 : close + run.length, run };
102
+ }
103
+ function closeInline(source) {
104
+ const body = closeLink(source);
105
+ const opened = [];
106
+ let code = null;
107
+ for (let at = 0; at < body.length && code === null; ) {
108
+ if (body[at] === "`") {
109
+ const { end, run } = codeEnd(body, at);
110
+ if (end === -1) code = { token: run, at };
111
+ at = end === -1 ? body.length : end;
112
+ continue;
113
+ }
114
+ if (body.startsWith("](", at)) {
115
+ const close = body.indexOf(")", at);
116
+ at = close === -1 ? body.length : close + 1;
117
+ continue;
118
+ }
119
+ const token = tokenAt(body, at);
120
+ if (token === null) {
121
+ at++;
122
+ continue;
123
+ }
124
+ const before = body[at - 1];
125
+ const after = body[at + token.length];
126
+ if (_optionalChain([opened, 'access', _5 => _5.at, 'call', _6 => _6(-1), 'optionalAccess', _7 => _7.token]) === token && !isSpace(before)) opened.pop();
127
+ else if (after === void 0 || !isSpace(after)) opened.push({ token, at });
128
+ at += token.length;
129
+ }
130
+ if (code !== null) opened.push(code);
131
+ let text = body;
132
+ while (opened.length > 0 && opened[opened.length - 1].at + opened[opened.length - 1].token.length === text.length) {
133
+ text = text.slice(0, opened.pop().at);
134
+ }
135
+ return text + opened.reverse().map(({ token }) => token).join("");
136
+ }
137
+ function closeStreaming(markdown) {
138
+ const lines = markdown.split("\n");
139
+ const fence = openFence(lines);
140
+ if (fence !== null) return `${markdown}${markdown.endsWith("\n") ? "" : "\n"}${fence[0].repeat(fence.length)}`;
141
+ const last = lines[lines.length - 1];
142
+ if (last.trim() !== "" && MARKER_ONLY.test(last)) return markdown.slice(0, markdown.length - last.length);
143
+ let first = lines.length - 1;
144
+ while (first > 0 && lines[first - 1].trim() !== "" && !FENCE.test(lines[first - 1]) && !BLOCK_START.test(lines[first])) {
145
+ first--;
146
+ }
147
+ const block = lines.slice(first).join("\n");
148
+ const head = markdown.slice(0, markdown.length - block.length);
149
+ const prefix = _nullishCoalesce(_optionalChain([LINE_PREFIX, 'access', _8 => _8.exec, 'call', _9 => _9(block), 'optionalAccess', _10 => _10[0]]), () => ( ""));
150
+ return head + prefix + closeInline(block.slice(prefix.length));
151
+ }
152
+
153
+ // src/extensions/ai/ai-target.ts
154
+ function targetOfBlocks(state, ids) {
155
+ const { doc, schema } = state;
156
+ const first = doc.blocks[_nullishCoalesce(doc.index.get(ids[0]), () => ( -1))];
157
+ const last = doc.blocks[_nullishCoalesce(doc.index.get(ids[ids.length - 1]), () => ( -1))];
158
+ if (first === void 0 || last === void 0) return null;
159
+ const start = _chunkPZ4GT5JOcjs.primaryRegion.call(void 0, schema, first);
160
+ const end = _chunkPZ4GT5JOcjs.primaryRegion.call(void 0, schema, last);
161
+ if (start === null || end === null) return null;
162
+ const from = { block: first.id, region: start, offset: 0 };
163
+ return { from, to: { block: last.id, region: end, offset: _chunkPZ4GT5JOcjs.regionLength.call(void 0, last, end) }, selected: ids.length > 1 };
164
+ }
165
+ function targetOfSelection(state) {
166
+ const { doc, selection } = state;
167
+ if (selection === null) return null;
168
+ if (selection.kind !== "text") return targetOfBlocks(state, _chunkPZ4GT5JOcjs.selectedBlockIds.call(void 0, doc, selection));
169
+ const { from, to } = _chunkPZ4GT5JOcjs.orderedRange.call(void 0, doc, selection.anchor, selection.head);
170
+ if (_chunkPZ4GT5JOcjs.comparePos.call(void 0, doc, from, to) !== 0) return { from, to, selected: true };
171
+ const block = doc.blocks[doc.index.get(from.block)];
172
+ const whole = { block: from.block, region: from.region };
173
+ return { from: { ...whole, offset: 0 }, to: { ...whole, offset: _chunkPZ4GT5JOcjs.regionLength.call(void 0, block, from.region) }, selected: false };
174
+ }
175
+ function nearestKept(tr, target) {
176
+ const { doc } = tr.before;
177
+ const first = _nullishCoalesce(doc.index.get(target.from.block), () => ( 0));
178
+ const last = _nullishCoalesce(doc.index.get(target.to.block), () => ( first));
179
+ const kept = (block) => block && tr.doc.blocks[_nullishCoalesce(tr.doc.index.get(block.id), () => ( -1))];
180
+ for (let step = 1; first - step >= 0 || last + step < doc.blocks.length; step++) {
181
+ const found = _nullishCoalesce(kept(doc.blocks[first - step]), () => ( kept(doc.blocks[last + step])));
182
+ if (found) return found;
183
+ }
184
+ return tr.doc.blocks[0];
185
+ }
186
+ function edgeOf(tr, target) {
187
+ const point = tr.mapPos(target.from, -1);
188
+ const block = _nullishCoalesce(tr.doc.blocks[_nullishCoalesce(tr.doc.index.get(point.block), () => ( -1))], () => ( nearestKept(tr, target)));
189
+ if (block === void 0) return null;
190
+ const region = _nullishCoalesce(_chunkPZ4GT5JOcjs.primaryRegion.call(void 0, tr.before.schema, block), () => ( ""));
191
+ const length = region === "" ? 0 : _chunkPZ4GT5JOcjs.regionLength.call(void 0, block, region);
192
+ const offset = block.id === point.block ? Math.min(point.offset, length) : length;
193
+ const after = offset > 0 || length === 0;
194
+ const at = { block: block.id, region, offset: after ? length : 0 };
195
+ return { from: at, to: at, selected: true, lost: { after } };
196
+ }
197
+ function mapTarget(tr, target) {
198
+ if (!tr.doc.index.has(target.from.block) || !tr.doc.index.has(target.to.block)) return edgeOf(tr, target);
199
+ const inside = target.selected ? 1 : -1;
200
+ const from = tr.mapPos(target.from, inside);
201
+ const mapped2 = tr.mapPos(target.to, -inside);
202
+ if (!tr.doc.index.has(from.block) || !tr.doc.index.has(mapped2.block)) return edgeOf(tr, target);
203
+ const to = _chunkPZ4GT5JOcjs.comparePos.call(void 0, tr.doc, from, mapped2) > 0 ? from : mapped2;
204
+ return from === target.from && to === target.to ? target : { ...target, from, to };
205
+ }
206
+ var targetGone = (doc, target) => target.lost !== void 0 || target.selected && _chunkPZ4GT5JOcjs.comparePos.call(void 0, doc, target.from, target.to) === 0;
207
+ function targetRanges(state, { from, to }) {
208
+ const { doc, schema } = state;
209
+ const start = doc.index.get(from.block);
210
+ const end = doc.index.get(to.block);
211
+ return doc.blocks.slice(start, end + 1).flatMap((block, i) => {
212
+ const region = i === 0 ? from.region : block.id === to.block ? to.region : _chunkPZ4GT5JOcjs.primaryRegion.call(void 0, schema, block);
213
+ if (region === null || !Object.hasOwn(block.regions, region)) return [];
214
+ const left = i === 0 ? from.offset : 0;
215
+ const right = block.id === to.block ? to.offset : _chunkPZ4GT5JOcjs.regionLength.call(void 0, block, region);
216
+ return right > left ? [{ block: block.id, region, from: left, to: right }] : [];
217
+ });
218
+ }
219
+
220
+ // src/extensions/ai/ai-plugin.ts
221
+ var aiKey = _chunkPZ4GT5JOcjs.createPluginKey.call(void 0, "ai");
222
+ var AI = "ai";
223
+ var IDLE = { target: null, menu: null, ghost: null, held: [] };
224
+ var aiState = (state) => _chunkPZ4GT5JOcjs.getPluginState.call(void 0, state, aiKey);
225
+ var aiTransaction = (state, act2) => new (0, _chunkPZ4GT5JOcjs.Transaction)(state).setMeta(AI, act2).setMeta("addToHistory", false);
226
+ function written(ghost, key, phase, output) {
227
+ return ghost.key !== key ? ghost : { ...ghost, phase, output, shown: closeStreaming(output) };
228
+ }
229
+ function act(value, action) {
230
+ switch (action.type) {
231
+ case "open":
232
+ return { ...value, target: action.target, menu: { fromSpace: action.fromSpace }, ghost: null };
233
+ case "close":
234
+ return value.ghost === null ? { ...value, target: null, menu: null } : { ...value, menu: null };
235
+ case "start": {
236
+ const ghost = { key: action.key, replace: action.replace, phase: "streaming", output: "", shown: "" };
237
+ return value.target === null ? value : { ...value, menu: null, ghost };
238
+ }
239
+ case "stream":
240
+ case "end": {
241
+ const { ghost } = value;
242
+ if (ghost === null || ghost.phase !== "streaming") return value;
243
+ const phase = action.type === "end" ? action.phase : "streaming";
244
+ return { ...value, ghost: written(ghost, action.key, phase, action.output) };
245
+ }
246
+ case "discard":
247
+ return { ...value, target: null, menu: null, ghost: null };
248
+ case "focus":
249
+ return value.held.length === 0 ? value : { ...value, held: [] };
250
+ }
251
+ }
252
+ function caretBlock(state) {
253
+ const { selection } = state;
254
+ return _optionalChain([selection, 'optionalAccess', _11 => _11.kind]) === "text" ? selection.head.block : null;
255
+ }
256
+ function hasText(state, id) {
257
+ const block = state.doc.blocks[_nullishCoalesce(state.doc.index.get(id), () => ( -1))];
258
+ return block !== void 0 && Object.keys(block.regions).some((region) => _chunkPZ4GT5JOcjs.regionLength.call(void 0, block, region) > 0);
259
+ }
260
+ function heldText(tr, value, before, after) {
261
+ if (!tr.docChanged) return value.held;
262
+ const touched = [caretBlock(before), caretBlock(after)].filter(
263
+ (id) => id !== null && !value.held.includes(id) && (hasText(before, id) || hasText(after, id))
264
+ );
265
+ return touched.length === 0 ? value.held : [...value.held, ...new Set(touched)];
266
+ }
267
+ function mapped(tr, value) {
268
+ const { target, ghost } = value;
269
+ if (!tr.docChanged || target === null) return value;
270
+ const moved = mapTarget(tr, target);
271
+ if (moved === null || moved.lost && ghost === null) return { ...value, target: null, menu: null, ghost: null };
272
+ return moved === target ? value : { ...value, target: moved };
273
+ }
274
+ var aiPlugin = {
275
+ key: aiKey,
276
+ init: () => IDLE,
277
+ apply(tr, value, before, after) {
278
+ const held = heldText(tr, value, before, after);
279
+ const next = mapped(tr, held === value.held ? value : { ...value, held });
280
+ const action = tr.getMeta(AI);
281
+ return action === void 0 ? next : act(next, action);
282
+ }
283
+ };
284
+
285
+ // src/extensions/ai/ai-decorations.ts
286
+ var REPLACED = { class: "quoin-ai-replaced" };
287
+ var ROOM = "data-quoin-ai-room";
288
+ var drawn = /* @__PURE__ */ new WeakMap();
289
+ function decorate(state, { target, ghost }) {
290
+ if (target === null || ghost === null) return [];
291
+ const replaced = ghost.replace && !targetGone(state.doc, target) ? targetRanges(state, target).map((range) => ({ kind: "inline", ...range, attrs: REPLACED })) : [];
292
+ return [...replaced, { kind: "block", block: target.to.block, attrs: { [ROOM]: "" } }];
293
+ }
294
+ function aiDecorations(state) {
295
+ const value = aiState(state);
296
+ const last = drawn.get(value);
297
+ if (_optionalChain([last, 'optionalAccess', _12 => _12.doc]) === state.doc) return last.decorations;
298
+ const decorations = decorate(state, value);
299
+ drawn.set(value, { doc: state.doc, decorations });
300
+ return decorations;
301
+ }
302
+
303
+ // src/extensions/ai/ai-items.ts
304
+ var _lucidereact = require('lucide-react');
305
+
306
+ // src/extensions/ai/ai-actions.ts
307
+ var MENU_ACTIONS = [
308
+ "continue",
309
+ "improve",
310
+ "fix",
311
+ "shorten",
312
+ "lengthen",
313
+ "simplify",
314
+ "tone",
315
+ "translate",
316
+ "summarize",
317
+ "explain"
318
+ ];
319
+ var EMPTY_LINE_ACTIONS = ["continue", "summarize"];
320
+ var TRANSFORMS = /* @__PURE__ */ new Set(["improve", "fix", "shorten", "lengthen", "simplify", "tone", "translate"]);
321
+ var ASKS_FOR_PROMPT = /* @__PURE__ */ new Set(["tone", "translate"]);
322
+ var replacesTarget = (action, selected) => TRANSFORMS.has(action) || action === "custom" && selected;
323
+
324
+ // src/extensions/ai/ai-link.ts
325
+ var links = /* @__PURE__ */ new WeakMap();
326
+ function linkOf(editor) {
327
+ let link = links.get(editor);
328
+ if (link === void 0) {
329
+ link = { mounts: 0, run: null, last: null, report: (error) => console.error(error), ended: () => {
330
+ }, stopWatching: null };
331
+ links.set(editor, link);
332
+ }
333
+ return link;
334
+ }
335
+
336
+ // src/extensions/ai/ai-request.ts
337
+ var CONTEXT_LIMIT = 8e3;
338
+ var BOUNDARY = "\n\n";
339
+ var isHigh = (code) => code >= 55296 && code <= 56319;
340
+ var isLow = (code) => code >= 56320 && code <= 57343;
341
+ function aroundSelection(text, start, end, limit = CONTEXT_LIMIT) {
342
+ if (text.length <= limit) return text;
343
+ let from = Math.max(0, Math.min(Math.round((start + end - limit) / 2), text.length - limit));
344
+ let to = from + limit;
345
+ if (from > 0) {
346
+ const boundary = text.indexOf(BOUNDARY, from);
347
+ if (boundary !== -1 && boundary + BOUNDARY.length <= Math.min(start, to)) from = boundary + BOUNDARY.length;
348
+ }
349
+ if (to < text.length) {
350
+ const boundary = text.lastIndexOf(BOUNDARY, to - BOUNDARY.length);
351
+ if (boundary >= Math.max(end, from)) to = boundary + 1;
352
+ }
353
+ if (isLow(text.charCodeAt(from))) from++;
354
+ if (to > from && isHigh(text.charCodeAt(to - 1))) to--;
355
+ return text.slice(from, to);
356
+ }
357
+ var WHITESPACE_ENTITY = /(?<!\\)&#(32|9);/g;
358
+ var plain = (markdown) => markdown.replace(WHITESPACE_ENTITY, (_, code) => code === "32" ? " " : " ");
359
+ var markdownOf = (state, blocks) => _chunkPZ4GT5JOcjs.toMarkdown.call(void 0, blocks, { schema: state.schema, comments: false });
360
+ function rangeMarkdown(state, from, to) {
361
+ const slice = _chunkPZ4GT5JOcjs.sliceFromSelection.call(void 0, { ...state, selection: _chunkPZ4GT5JOcjs.textSelection.call(void 0, from, to) }, _chunkND5XJVK2cjs.createBlockCodec.call(void 0, state.schema));
362
+ return slice === null ? "" : markdownOf(state, slice.blocks).replace(/\n$/, "");
363
+ }
364
+ function documentContext(state, target, selection) {
365
+ const blocks = _chunkND5XJVK2cjs.createBlockCodec.call(void 0, state.schema).blocksFromDoc(state.doc);
366
+ const full = plain(markdownOf(state, blocks));
367
+ if (full.length <= CONTEXT_LIMIT) return full;
368
+ const index = _nullishCoalesce(state.doc.index.get(target.from.block), () => ( 0));
369
+ const blockStart = index === 0 ? 0 : plain(markdownOf(state, blocks.slice(0, index))).length + 1;
370
+ const lead = { ...target.from, offset: 0 };
371
+ const start = blockStart + plain(rangeMarkdown(state, lead, target.from)).length;
372
+ return aroundSelection(full, start, start + selection.length);
373
+ }
374
+ function buildRequest(state, target, input) {
375
+ const selection = plain(rangeMarkdown(state, target.from, target.to));
376
+ const request = { action: input.action, selection, context: documentContext(state, target, selection) };
377
+ if (input.prompt !== void 0) request.prompt = input.prompt;
378
+ if (input.language !== void 0) request.language = input.language;
379
+ return request;
380
+ }
381
+
382
+ // src/extensions/ai/ai-session.ts
383
+ var nextKey = 0;
384
+ function onNextFrame(draw) {
385
+ if (typeof requestAnimationFrame === "function") {
386
+ const frame = requestAnimationFrame(draw);
387
+ return () => cancelAnimationFrame(frame);
388
+ }
389
+ const timer = setTimeout(draw, 16);
390
+ return () => clearTimeout(timer);
391
+ }
392
+ function endRun(link, ended = false) {
393
+ const { run } = link;
394
+ if (run === null) return null;
395
+ link.run = null;
396
+ _optionalChain([run, 'access', _13 => _13.cancelFrame, 'optionalCall', _14 => _14()]);
397
+ run.cancelFrame = null;
398
+ if (!ended) run.abort.abort();
399
+ return run;
400
+ }
401
+ var send = (editor, act2) => editor.dispatch(aiTransaction(editor.state, act2));
402
+ async function read(editor, link, run, stream, request) {
403
+ const live = () => link.run === run && link.mounts > 0;
404
+ const end = (phase) => {
405
+ endRun(link, true);
406
+ send(editor, { type: "end", key: run.key, phase, output: run.output });
407
+ };
408
+ const draw = () => {
409
+ run.cancelFrame = null;
410
+ if (live()) send(editor, { type: "stream", key: run.key, output: run.output });
411
+ };
412
+ try {
413
+ const chunks = await stream(request, run.abort.signal);
414
+ for await (const chunk of chunks) {
415
+ if (!live()) return;
416
+ if (typeof chunk !== "string") throw new TypeError(`The AI stream gave a chunk that is not text: ${typeof chunk}`);
417
+ run.output += chunk;
418
+ run.cancelFrame ??= onNextFrame(draw);
419
+ }
420
+ if (!live()) return;
421
+ end("done");
422
+ link.ended("done", run.output);
423
+ } catch (error) {
424
+ if (!live()) return;
425
+ end("error");
426
+ link.report(_chunk2VDK27IFcjs.toError.call(void 0, error));
427
+ }
428
+ }
429
+ function startStream(editor, link, stream, request, replace) {
430
+ endRun(link);
431
+ if (aiState(editor.state).target === null || link.mounts === 0) return;
432
+ const run = { key: ++nextKey, abort: new AbortController(), output: "", cancelFrame: null };
433
+ link.run = run;
434
+ link.last = request;
435
+ send(editor, { type: "start", key: run.key, replace });
436
+ void read(editor, link, run, stream, request);
437
+ }
438
+ function stopped(editor, link, key, output) {
439
+ const { ghost } = aiState(editor.state);
440
+ if (link.mounts === 0 || _optionalChain([ghost, 'optionalAccess', _15 => _15.key]) !== key || ghost.phase !== "streaming") return;
441
+ send(editor, { type: "end", key, phase: "stopped", output });
442
+ link.ended("stopped", output);
443
+ }
444
+ function stopStream(editor, link) {
445
+ const run = endRun(link);
446
+ const { ghost } = aiState(editor.state);
447
+ if (run !== null) stopped(editor, link, run.key, run.output);
448
+ else if (ghost !== null) stopped(editor, link, ghost.key, ghost.output);
449
+ }
450
+ function watchGhost(editor, link) {
451
+ return editor.subscribe((state, tr) => {
452
+ const { run } = link;
453
+ const { ghost, target } = aiState(state);
454
+ if (run === null) return;
455
+ if (_optionalChain([ghost, 'optionalAccess', _16 => _16.key]) !== run.key || ghost.phase !== "streaming") endRun(link);
456
+ else if (_optionalChain([target, 'optionalAccess', _17 => _17.lost]) !== void 0 && tr !== null && _optionalChain([aiState, 'call', _18 => _18(tr.before), 'access', _19 => _19.target, 'optionalAccess', _20 => _20.lost]) === void 0) {
457
+ endRun(link);
458
+ queueMicrotask(() => stopped(editor, link, run.key, run.output));
459
+ }
460
+ });
461
+ }
462
+
463
+ // src/extensions/ai/ai-flow.ts
464
+ function openMenu(editor, target, fromSpace) {
465
+ editor.dispatch(aiTransaction(editor.state, { type: "open", target, fromSpace }));
466
+ }
467
+ function closeMenu(editor) {
468
+ editor.dispatch(aiTransaction(editor.state, { type: "close" }));
469
+ }
470
+ function ask(editor, stream, input) {
471
+ const { target } = aiState(editor.state);
472
+ if (target === null) return;
473
+ const request = buildRequest(editor.state, target, input);
474
+ startStream(editor, linkOf(editor), stream, request, replacesTarget(input.action, target.selected));
475
+ }
476
+ function retry(editor, stream) {
477
+ const link = linkOf(editor);
478
+ const { ghost } = aiState(editor.state);
479
+ if (ghost !== null && link.last !== null) startStream(editor, link, stream, link.last, ghost.replace);
480
+ }
481
+ function followUp(editor, stream, prompt) {
482
+ const link = linkOf(editor);
483
+ const { ghost } = aiState(editor.state);
484
+ if (ghost === null || link.last === null) return;
485
+ const { context, language } = link.last;
486
+ const request = { action: "custom", prompt, selection: ghost.output, context };
487
+ startStream(editor, link, stream, language === void 0 ? request : { ...request, language }, ghost.replace);
488
+ }
489
+ function stop(editor) {
490
+ stopStream(editor, linkOf(editor));
491
+ }
492
+ function noteFocus(editor) {
493
+ if (aiState(editor.state).held.length > 0) editor.dispatch(aiTransaction(editor.state, { type: "focus" }));
494
+ }
495
+ function discard(editor) {
496
+ editor.dispatch(aiTransaction(editor.state, { type: "discard" }));
497
+ }
498
+
499
+ // src/extensions/ai/ai-env.ts
500
+ function languageOf(controller) {
501
+ return _optionalChain([controller, 'access', _21 => _21.root, 'optionalAccess', _22 => _22.closest, 'call', _23 => _23("[lang]"), 'optionalAccess', _24 => _24.getAttribute, 'call', _25 => _25("lang")]) || void 0;
502
+ }
503
+ function askFrom(env, action, prompt) {
504
+ const { controller, stream } = env;
505
+ const language = languageOf(controller);
506
+ ask(controller.editor, stream, { action, ...prompt === void 0 ? {} : { prompt }, ...language ? { language } : {} });
507
+ }
508
+
509
+ // src/extensions/ai/ai-items.ts
510
+ function openFor(controller) {
511
+ const target = targetOfSelection(controller.editor.state);
512
+ if (target !== null) openMenu(controller.editor, target, false);
513
+ return target !== null;
514
+ }
515
+ var KEYWORDS = ["ai", "assistant", "write", "generate"];
516
+ function aiSlashItems(labels, stream) {
517
+ return [
518
+ {
519
+ id: "ai",
520
+ title: labels.askAi,
521
+ description: labels.askAiDescription,
522
+ group: "ai",
523
+ icon: _lucidereact.Sparkles,
524
+ keywords: KEYWORDS,
525
+ run: ({ controller }) => void openFor(controller)
526
+ },
527
+ {
528
+ id: "ai-continue",
529
+ title: labels.actions.continue,
530
+ group: "ai",
531
+ icon: _lucidereact.PenLine,
532
+ keywords: [...KEYWORDS, "continue"],
533
+ run: ({ controller }) => {
534
+ if (openFor(controller)) askFrom({ controller, stream, labels }, "continue");
535
+ }
536
+ }
537
+ ];
538
+ }
539
+ var aiBubbleItem = (labels) => ({
540
+ id: "ai",
541
+ title: labels.askAi,
542
+ icon: _lucidereact.Sparkles,
543
+ available: (state) => aiState(state).ghost === null,
544
+ run: (controller) => void openFor(controller)
545
+ });
546
+ var aiBlockMenuItem = (labels) => ({
547
+ id: "ai",
548
+ label: labels.askAi,
549
+ icon: _lucidereact.Sparkles,
550
+ available: (state, blockIds) => targetOfBlocks(state, blockIds) !== null,
551
+ run: (controller, blockIds) => {
552
+ const target = targetOfBlocks(controller.editor.state, blockIds);
553
+ if (target !== null) openMenu(controller.editor, target, false);
554
+ }
555
+ });
556
+
557
+ // src/extensions/ai/ai-labels.ts
558
+ var englishAiLabels = {
559
+ askAi: "Ask AI",
560
+ askAiDescription: "Write or edit with AI",
561
+ actions: {
562
+ continue: "Continue writing",
563
+ improve: "Improve writing",
564
+ fix: "Fix spelling and grammar",
565
+ shorten: "Make shorter",
566
+ lengthen: "Make longer",
567
+ simplify: "Simplify language",
568
+ tone: "Change tone",
569
+ translate: "Translate",
570
+ summarize: "Summarize",
571
+ explain: "Explain",
572
+ custom: "Ask AI"
573
+ },
574
+ menu: "AI actions",
575
+ prompt: "Ask AI to write or edit",
576
+ tonePrompt: "Tone to take, such as friendly",
577
+ translatePrompt: "Language to translate to",
578
+ ask: (prompt) => `Ask AI: ${prompt}`,
579
+ response: "AI response",
580
+ writing: "Writing",
581
+ stopped: "Stopped",
582
+ stop: "Stop",
583
+ accept: "Accept",
584
+ discard: "Discard",
585
+ retry: "Retry",
586
+ followUp: "Tell AI what to do next",
587
+ failed: "AI could not answer",
588
+ written: (text) => `AI response ready: ${text}`,
589
+ halted: (text) => `Stopped. AI response so far: ${text}`,
590
+ targetGone: "The text this was for was removed, so Accept inserts it where that text was"
591
+ };
592
+ function resolveAiLabels(overrides) {
593
+ const given = Object.entries(_nullishCoalesce(overrides, () => ( {}))).filter(([, value]) => value !== void 0);
594
+ return given.length === 0 ? englishAiLabels : { ...englishAiLabels, ...Object.fromEntries(given) };
595
+ }
596
+
597
+ // src/extensions/ai/ai-space.ts
598
+ var openOnSpace = (state, dispatch) => {
599
+ const { selection, doc } = state;
600
+ const ai = aiState(state);
601
+ if (_optionalChain([selection, 'optionalAccess', _26 => _26.kind]) !== "text" || !_chunkPZ4GT5JOcjs.isCollapsed.call(void 0, selection) || ai.menu !== null || ai.ghost !== null) return false;
602
+ const { head } = selection;
603
+ const block = doc.blocks[doc.index.get(head.block)];
604
+ const paragraph = block.type === "MARKDOWN" && block.attrs.kind === "paragraph";
605
+ if (!paragraph || _chunkPZ4GT5JOcjs.regionLength.call(void 0, block, head.region) > 0 || ai.held.includes(block.id)) return false;
606
+ _optionalChain([dispatch, 'optionalCall', _27 => _27(aiTransaction(state, { type: "open", target: { from: head, to: head, selected: false }, fromSpace: true }))]);
607
+ return true;
608
+ };
609
+
610
+ // src/extensions/ai/AiOverlay.tsx
611
+ var _react = require('react');
612
+
613
+ // src/extensions/ai/AiBar.tsx
614
+
615
+
616
+ // src/extensions/ai/ai-accept.ts
617
+ var isParagraph = (block) => _optionalChain([block, 'optionalAccess', _28 => _28.type]) === "MARKDOWN" && _chunkND5XJVK2cjs.parseLine.call(void 0, String(_nullishCoalesce(block.data.markdown, () => ( "")))).kind === "paragraph";
618
+ var DISCARD = { type: "discard" };
619
+ function insertBeside(tr, schema, target, pieces, makeId) {
620
+ const index = tr.doc.index.get(target.to.block);
621
+ const at = _optionalChain([target, 'access', _29 => _29.lost, 'optionalAccess', _30 => _30.after]) ? _chunkPZ4GT5JOcjs.descendantsEnd.call(void 0, tr.doc, index) : index;
622
+ const fresh = _chunkPZ4GT5JOcjs.freshBlocks.call(void 0, pieces, tr.doc.blocks[index].indent, makeId);
623
+ tr.step(_chunkPZ4GT5JOcjs.insertBlocksStep.call(void 0, at, fresh));
624
+ _chunkPZ4GT5JOcjs.capIndents.call(void 0, tr, at, at + fresh.length);
625
+ tr.setSelection(_chunkPZ4GT5JOcjs.endOf.call(void 0, tr.doc, schema, fresh[fresh.length - 1].id));
626
+ }
627
+ function acceptAnswer(editor) {
628
+ const { state } = editor;
629
+ const { target, ghost } = aiState(state);
630
+ if (target === null || ghost === null || ghost.phase === "streaming" || ghost.phase === "error") return null;
631
+ const { codec } = editor;
632
+ const makeId = codec.context.newId;
633
+ const blocks = _chunkND5XJVK2cjs.fromMarkdown.call(void 0, ghost.output, { newId: makeId });
634
+ const pieces = blocks.flatMap((block) => codec.toEngineBlocks(block));
635
+ const tr = editor.createTransaction().setOrigin("ai").setMeta(AI, DISCARD);
636
+ const gone = targetGone(state.doc, target);
637
+ if (pieces.length > 0 && target.lost !== void 0) {
638
+ insertBeside(tr, state.schema, target, pieces, makeId);
639
+ } else if (pieces.length > 0) {
640
+ const { schema } = state;
641
+ const open = { openStart: isParagraph(blocks[0]), openEnd: isParagraph(blocks[blocks.length - 1]) };
642
+ if (ghost.replace || gone) {
643
+ const caret = ghost.replace && !gone ? _chunkPZ4GT5JOcjs.deleteRange.call(void 0, tr, schema, target.from, target.to, makeId) : target.to;
644
+ _chunkPZ4GT5JOcjs.pasteAtCaret.call(void 0, tr, schema, caret, open, pieces, makeId);
645
+ } else {
646
+ const block = tr.doc.blocks[tr.doc.index.get(target.to.block)];
647
+ const end = { ...target.to, offset: _chunkPZ4GT5JOcjs.regionLength.call(void 0, block, target.to.region) };
648
+ _chunkPZ4GT5JOcjs.pasteAtCaret.call(void 0, tr, schema, end, { openStart: false, openEnd: false }, pieces, makeId);
649
+ }
650
+ }
651
+ editor.dispatch(tr);
652
+ return { gone };
653
+ }
654
+
655
+ // src/extensions/ai/AiBar.tsx
656
+ var _jsxruntime = require('react/jsx-runtime');
657
+ var PRIMARY = "data-ai-primary";
658
+ function AiBar({ env, ghost, gone, barId }) {
659
+ const { controller, stream, labels } = env;
660
+ const { editor } = controller;
661
+ const content = _react.useRef.call(void 0, null);
662
+ const inside = _react.useRef.call(void 0, false);
663
+ const [next, setNext] = _react.useState.call(void 0, "");
664
+ const { phase } = ghost;
665
+ const focusPrimary = () => _optionalChain([content, 'access', _31 => _31.current, 'optionalAccess', _32 => _32.querySelector, 'call', _33 => _33(`[${PRIMARY}]`), 'optionalAccess', _34 => _34.focus, 'call', _35 => _35()]);
666
+ _chunkGTTPVJSDcjs.useIsomorphicLayoutEffect.call(void 0, () => {
667
+ const active = _optionalChain([content, 'access', _36 => _36.current, 'optionalAccess', _37 => _37.ownerDocument, 'access', _38 => _38.activeElement]);
668
+ inside.current = active == null || active === active.ownerDocument.body;
669
+ if (inside.current) focusPrimary();
670
+ }, []);
671
+ _chunkGTTPVJSDcjs.useIsomorphicLayoutEffect.call(void 0, () => {
672
+ const active = _optionalChain([content, 'access', _39 => _39.current, 'optionalAccess', _40 => _40.ownerDocument, 'access', _41 => _41.activeElement]);
673
+ if (inside.current && !_optionalChain([content, 'access', _42 => _42.current, 'optionalAccess', _43 => _43.contains, 'call', _44 => _44(_nullishCoalesce(active, () => ( null)))])) focusPrimary();
674
+ }, [phase, ghost.key]);
675
+ const backToText = () => {
676
+ if (inside.current) controller.focus();
677
+ inside.current = false;
678
+ };
679
+ const onAccept = () => {
680
+ let gone2 = false;
681
+ controller.edit(() => {
682
+ const result = acceptAnswer(editor);
683
+ gone2 = _nullishCoalesce(_optionalChain([result, 'optionalAccess', _45 => _45.gone]), () => ( false));
684
+ return result !== null;
685
+ });
686
+ controller.focus();
687
+ if (gone2) controller.announce(labels.targetGone);
688
+ };
689
+ const onDiscard = () => {
690
+ discard(editor);
691
+ backToText();
692
+ };
693
+ const onFollowUp = (event) => {
694
+ event.preventDefault();
695
+ if (next.trim() === "") return;
696
+ followUp(editor, stream, next.trim());
697
+ setNext("");
698
+ };
699
+ const primary = { [PRIMARY]: "" };
700
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
701
+ "div",
702
+ {
703
+ ref: content,
704
+ id: barId,
705
+ role: "group",
706
+ "aria-label": labels.response,
707
+ className: "quoin-ai-bar flex flex-wrap items-center gap-2 rounded-md border bg-popover p-2 text-popover-foreground shadow-md",
708
+ onFocus: () => inside.current = true,
709
+ onBlur: (event) => inside.current = _nullishCoalesce(_optionalChain([content, 'access', _46 => _46.current, 'optionalAccess', _47 => _47.contains, 'call', _48 => _48(event.relatedTarget)]), () => ( false)),
710
+ onKeyDown: (event) => {
711
+ if (event.key !== "Escape" || event.nativeEvent.isComposing) return;
712
+ event.preventDefault();
713
+ if (phase === "streaming") stop(editor);
714
+ else onDiscard();
715
+ },
716
+ children: [
717
+ phase === "streaming" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
718
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm text-muted-foreground", children: labels.writing }),
719
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2VDK27IFcjs.Button, { ...primary, size: "sm", variant: "outline", onClick: () => stop(editor), children: labels.stop })
720
+ ] }),
721
+ phase === "error" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
722
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { role: "alert", className: "text-sm text-destructive", children: labels.failed }),
723
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2VDK27IFcjs.Button, { ...primary, size: "sm", onClick: () => retry(editor, stream), children: labels.retry }),
724
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2VDK27IFcjs.Button, { size: "sm", variant: "ghost", onClick: onDiscard, children: labels.discard })
725
+ ] }),
726
+ (phase === "done" || phase === "stopped") && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
727
+ phase === "stopped" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm text-muted-foreground", children: labels.stopped }),
728
+ gone && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "w-full text-xs text-muted-foreground", children: labels.targetGone }),
729
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2VDK27IFcjs.Button, { ...primary, size: "sm", onClick: onAccept, children: labels.accept }),
730
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2VDK27IFcjs.Button, { size: "sm", variant: "ghost", onClick: onDiscard, children: labels.discard }),
731
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2VDK27IFcjs.Button, { size: "sm", variant: "ghost", onClick: () => retry(editor, stream), children: labels.retry }),
732
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "form", { className: "w-full", onSubmit: onFollowUp, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
733
+ _chunk2VDK27IFcjs.Input,
734
+ {
735
+ "aria-label": labels.followUp,
736
+ placeholder: labels.followUp,
737
+ value: next,
738
+ onChange: (event) => setNext(event.target.value),
739
+ onKeyDown: (event) => {
740
+ if (event.key === "Enter" && event.nativeEvent.isComposing) event.preventDefault();
741
+ }
742
+ }
743
+ ) })
744
+ ] })
745
+ ]
746
+ }
747
+ );
748
+ }
749
+
750
+ // src/extensions/ai/AiGhost.tsx
751
+
752
+
753
+ // src/extensions/ai/ai-ghost-render.ts
754
+ var reader = null;
755
+ function readerOf() {
756
+ if (reader === null) {
757
+ const schema = _chunkND5XJVK2cjs.createSchema.call(void 0, );
758
+ reader = { schema, codec: _chunkND5XJVK2cjs.createBlockCodec.call(void 0, schema) };
759
+ }
760
+ return reader;
761
+ }
762
+ function fillGhost(ghost, markdown) {
763
+ const doc = ghost.ownerDocument;
764
+ const { schema, codec } = readerOf();
765
+ const drawn2 = [];
766
+ for (const block of _chunkND5XJVK2cjs.fromMarkdown.call(void 0, markdown)) {
767
+ for (const piece of codec.toEngineBlocks(block)) {
768
+ const element = doc.createElement("div");
769
+ element.className = "quoin-ai-ghost-block";
770
+ element.dataset.kind = String(_nullishCoalesce(piece.attrs.kind, () => ( piece.type.toLowerCase())));
771
+ if (piece.attrs.level !== void 0) element.dataset.level = String(piece.attrs.level);
772
+ if (piece.indent > 0) element.style.setProperty("--quoin-ai-indent", String(piece.indent));
773
+ const region = _chunkPZ4GT5JOcjs.primaryRegion.call(void 0, schema, piece);
774
+ if (region === null) element.textContent = _chunkPZ4GT5JOcjs.toPlainText.call(void 0, [codec.toQuoin(piece)], { schema });
775
+ else _chunkGTTPVJSDcjs.renderInline.call(void 0, element, piece.regions[region], []);
776
+ drawn2.push(element);
777
+ }
778
+ }
779
+ ghost.replaceChildren(...drawn2);
780
+ }
781
+
782
+ // src/extensions/ai/use-ghost-place.ts
783
+
784
+ var ROOM2 = "--quoin-ai-room";
785
+ var GAP = 4;
786
+ function place(controller, root, layer, block, region) {
787
+ const shell = controller.blockElement(block);
788
+ if (shell === void 0 || !shell.isConnected) {
789
+ layer.style.visibility = "hidden";
790
+ return;
791
+ }
792
+ layer.style.visibility = "";
793
+ const host = _nullishCoalesce(controller.registry.get(block, region), () => ( shell));
794
+ const origin = root.getBoundingClientRect();
795
+ const scale = origin.width / root.offsetWidth || 1;
796
+ const below = shell.getBoundingClientRect();
797
+ const text = host.getBoundingClientRect();
798
+ const left = (text.left - origin.left) / scale - root.clientLeft + root.scrollLeft;
799
+ const top = (below.bottom - origin.top) / scale - root.clientTop + root.scrollTop + GAP;
800
+ layer.style.transform = `translate(${left}px, ${top}px)`;
801
+ layer.style.width = `${text.width / scale}px`;
802
+ clipAside(layer, text, _chunkQAW5NH6Scjs.clipOf.call(void 0, host, root), scale);
803
+ root.style.setProperty(ROOM2, `${layer.offsetHeight + 2 * GAP}px`);
804
+ }
805
+ function clipAside(layer, text, clip, scale) {
806
+ const area = _optionalChain([clip, 'optionalAccess', _49 => _49.getBoundingClientRect, 'call', _50 => _50()]);
807
+ const start = area === void 0 ? 0 : Math.max(0, area.left - text.left) / scale;
808
+ const end = area === void 0 ? 0 : Math.max(0, text.right - area.right) / scale;
809
+ layer.style.clipPath = start > 0 || end > 0 ? `inset(0 ${end}px 0 ${start}px)` : "";
810
+ if (start + end >= text.width / scale && text.width > 0) layer.style.visibility = "hidden";
811
+ }
812
+ function useGhostPlace(controller, layer, block, region) {
813
+ const placeNow = _react.useRef.call(void 0, () => {
814
+ });
815
+ _chunkGTTPVJSDcjs.useIsomorphicLayoutEffect.call(void 0, () => {
816
+ const root = controller.root;
817
+ const element = layer.current;
818
+ const view = _optionalChain([root, 'optionalAccess', _51 => _51.ownerDocument, 'access', _52 => _52.defaultView]);
819
+ if (!root || !element || !view) return void 0;
820
+ const update = () => place(controller, root, element, block, region);
821
+ let frame = 0;
822
+ const later = () => {
823
+ view.cancelAnimationFrame(frame);
824
+ frame = view.requestAnimationFrame(update);
825
+ };
826
+ update();
827
+ placeNow.current = update;
828
+ const observer = new ResizeObserver(later);
829
+ observer.observe(root);
830
+ observer.observe(element);
831
+ const host = controller.registry.get(block, region);
832
+ if (host) observer.observe(host);
833
+ const unsubscribe = controller.editor.subscribe(later);
834
+ const fonts = root.ownerDocument.fonts;
835
+ root.addEventListener("scroll", later, { capture: true, passive: true });
836
+ _optionalChain([fonts, 'optionalAccess', _53 => _53.addEventListener, 'call', _54 => _54("loadingdone", later)]);
837
+ return () => {
838
+ placeNow.current = () => {
839
+ };
840
+ view.cancelAnimationFrame(frame);
841
+ observer.disconnect();
842
+ unsubscribe();
843
+ root.removeEventListener("scroll", later, { capture: true });
844
+ _optionalChain([fonts, 'optionalAccess', _55 => _55.removeEventListener, 'call', _56 => _56("loadingdone", later)]);
845
+ root.style.removeProperty(ROOM2);
846
+ };
847
+ }, [controller, layer, block, region]);
848
+ return _react.useCallback.call(void 0, () => placeNow.current(), []);
849
+ }
850
+
851
+ // src/extensions/ai/AiGhost.tsx
852
+
853
+ function AiGhost({ env, ghost, target, gone, barId }) {
854
+ const layer = _react.useRef.call(void 0, null);
855
+ const drawn2 = _react.useRef.call(void 0, null);
856
+ const place2 = useGhostPlace(env.controller, layer, target.to.block, target.to.region);
857
+ _chunkGTTPVJSDcjs.useIsomorphicLayoutEffect.call(void 0, () => {
858
+ const element = drawn2.current;
859
+ if (element === null) return;
860
+ element.setAttribute("inert", "");
861
+ fillGhost(element, ghost.shown);
862
+ place2();
863
+ }, [ghost.shown, ghost.phase, gone, place2]);
864
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { ref: layer, className: "quoin-ai-layer", children: [
865
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: drawn2, className: "quoin-ai-ghost", "aria-hidden": "true", "data-phase": ghost.phase }),
866
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AiBar, { env, ghost, gone, barId })
867
+ ] });
868
+ }
869
+
870
+ // src/extensions/ai/AiMenu.tsx
871
+
872
+
873
+ // src/extensions/ai/use-target-anchor.ts
874
+
875
+ function useTargetAnchor(controller, target) {
876
+ const latest = _react.useRef.call(void 0, target);
877
+ _chunkGTTPVJSDcjs.useIsomorphicLayoutEffect.call(void 0, () => {
878
+ latest.current = target;
879
+ });
880
+ return _react.useMemo.call(void 0, () => {
881
+ const end = () => {
882
+ const { to } = latest.current;
883
+ return { block: to.block, region: to.region, from: to.offset, to: to.offset };
884
+ };
885
+ return {
886
+ current: _chunk2VDK27IFcjs.virtualAnchor.call(void 0,
887
+ () => _chunk2VDK27IFcjs.rangeRect.call(void 0, controller, end()),
888
+ () => controller.registry.get(end().block, end().region)
889
+ )
890
+ };
891
+ }, [controller]);
892
+ }
893
+
894
+ // src/extensions/ai/AiMenu.tsx
895
+
896
+ function choicesFor(env, target, query) {
897
+ const { labels } = env;
898
+ const emptyLine = !target.selected && target.to.offset === 0;
899
+ const wanted = query.trim().toLowerCase();
900
+ const actions = (emptyLine ? EMPTY_LINE_ACTIONS : MENU_ACTIONS).filter(
901
+ (action) => labels.actions[action].toLowerCase().includes(wanted)
902
+ );
903
+ const listed = actions.map((action) => ({ action, label: labels.actions[action] }));
904
+ return wanted === "" ? listed : [...listed, { action: "custom", label: labels.ask(query.trim()) }];
905
+ }
906
+ function AiMenu({ env, target, fromSpace }) {
907
+ const { controller, labels } = env;
908
+ const [query, setQuery] = _react.useState.call(void 0, "");
909
+ const [asking, setAsking] = _react.useState.call(void 0, null);
910
+ const [active, setActive] = _react.useState.call(void 0, 0);
911
+ const field = _react.useRef.call(void 0, null);
912
+ const anchor = useTargetAnchor(controller, target);
913
+ const id = _react.useId.call(void 0, );
914
+ const choices = asking === null ? choicesFor(env, target, query) : [];
915
+ const current = Math.min(active, choices.length - 1);
916
+ const optionId = (index) => `${id}-${index}`;
917
+ const close = (typeSpace) => {
918
+ closeMenu(controller.editor);
919
+ controller.focus();
920
+ if (typeSpace) controller.edit(() => controller.editor.insertText(" "));
921
+ };
922
+ const choose = ({ action }) => {
923
+ if (!ASKS_FOR_PROMPT.has(action)) return askFrom(env, action, action === "custom" ? query.trim() : void 0);
924
+ setAsking(action);
925
+ setQuery("");
926
+ };
927
+ const onKeyDown = (event) => {
928
+ if (event.nativeEvent.isComposing) return;
929
+ const step = event.key === "ArrowDown" ? 1 : event.key === "ArrowUp" ? -1 : 0;
930
+ if (step !== 0 && choices.length > 0) {
931
+ event.preventDefault();
932
+ setActive((current + step + choices.length) % choices.length);
933
+ } else if (event.key === "Enter") {
934
+ event.preventDefault();
935
+ if (asking !== null && query.trim() !== "") askFrom(env, asking, query.trim());
936
+ else if (choices[current] !== void 0) choose(choices[current]);
937
+ } else if (event.key === " " && fromSpace && query === "" && asking === null) {
938
+ event.preventDefault();
939
+ close(true);
940
+ }
941
+ };
942
+ const fieldLabel = asking === "tone" ? labels.tonePrompt : asking === "translate" ? labels.translatePrompt : labels.prompt;
943
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
944
+ _chunk2VDK27IFcjs.Popover,
945
+ {
946
+ open: true,
947
+ modal: false,
948
+ onOpenChange: (next) => {
949
+ if (!next) closeMenu(controller.editor);
950
+ },
951
+ children: [
952
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2VDK27IFcjs.PopoverAnchor, { virtualRef: anchor }),
953
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
954
+ _chunk2VDK27IFcjs.PopoverContent,
955
+ {
956
+ "aria-label": labels.askAi,
957
+ side: "bottom",
958
+ align: "start",
959
+ className: "w-80 p-1",
960
+ onOpenAutoFocus: (event) => {
961
+ event.preventDefault();
962
+ _optionalChain([field, 'access', _57 => _57.current, 'optionalAccess', _58 => _58.focus, 'call', _59 => _59()]);
963
+ },
964
+ onCloseAutoFocus: (event) => event.preventDefault(),
965
+ onEscapeKeyDown: (event) => {
966
+ event.preventDefault();
967
+ close(fromSpace);
968
+ },
969
+ children: [
970
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
971
+ _chunk2VDK27IFcjs.Input,
972
+ {
973
+ ref: field,
974
+ role: "combobox",
975
+ "aria-label": fieldLabel,
976
+ placeholder: fieldLabel,
977
+ "aria-expanded": choices.length > 0,
978
+ "aria-controls": choices.length > 0 ? `${id}-list` : void 0,
979
+ "aria-autocomplete": "list",
980
+ "aria-activedescendant": choices.length > 0 ? optionId(current) : void 0,
981
+ value: query,
982
+ onChange: (event) => {
983
+ setQuery(event.target.value);
984
+ setActive(0);
985
+ },
986
+ onKeyDown
987
+ }
988
+ ),
989
+ choices.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { id: `${id}-list`, role: "listbox", "aria-label": labels.menu, className: "mt-1 max-h-72 overflow-y-auto", children: choices.map((choice, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
990
+ "li",
991
+ {
992
+ id: optionId(index),
993
+ role: "option",
994
+ "aria-selected": index === current,
995
+ className: _chunk2VDK27IFcjs.cn.call(void 0, _chunk2VDK27IFcjs.MENU_ITEM, index === current && "bg-accent text-accent-foreground"),
996
+ onMouseDown: (event) => event.preventDefault(),
997
+ onClick: () => choose(choice),
998
+ children: choice.label
999
+ },
1000
+ choice.action
1001
+ )) })
1002
+ ]
1003
+ }
1004
+ )
1005
+ ]
1006
+ }
1007
+ );
1008
+ }
1009
+
1010
+ // src/extensions/ai/AiOverlay.tsx
1011
+
1012
+ var goneOf = (state) => {
1013
+ const { target, ghost } = aiState(state);
1014
+ return target !== null && ghost !== null && targetGone(state.doc, target);
1015
+ };
1016
+ var plainText = (markdown) => _chunkPZ4GT5JOcjs.toPlainText.call(void 0, _chunkND5XJVK2cjs.fromMarkdown.call(void 0, markdown));
1017
+ function AiOverlay({ controller, stream, labels }) {
1018
+ const { onError } = _chunk2VDK27IFcjs.useQuoin.call(void 0, );
1019
+ const link = linkOf(controller.editor);
1020
+ _chunkGTTPVJSDcjs.useIsomorphicLayoutEffect.call(void 0, () => {
1021
+ link.report = onError;
1022
+ link.ended = (phase, output) => controller.announce((phase === "done" ? labels.written : labels.halted)(plainText(output)));
1023
+ }, [link, onError, controller, labels]);
1024
+ const value = _chunkGTTPVJSDcjs.useEditorState.call(void 0, controller, aiState);
1025
+ const gone = _chunkGTTPVJSDcjs.useEditorState.call(void 0, controller, goneOf);
1026
+ const readOnly = _chunkGTTPVJSDcjs.useReadOnly.call(void 0, controller);
1027
+ const env = _react.useMemo.call(void 0, () => ({ controller, stream, labels }), [controller, stream, labels]);
1028
+ const barId = _react.useId.call(void 0, );
1029
+ const showing = value.ghost !== null;
1030
+ _react.useEffect.call(void 0, () => {
1031
+ if (!showing) return;
1032
+ const toBar = (event) => {
1033
+ if (event.key !== "Escape" || event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return false;
1034
+ const bar = _optionalChain([controller, 'access', _60 => _60.root, 'optionalAccess', _61 => _61.ownerDocument, 'access', _62 => _62.getElementById, 'call', _63 => _63(barId)]);
1035
+ _optionalChain([bar, 'optionalAccess', _64 => _64.querySelector, 'call', _65 => _65(`[${PRIMARY}]`), 'optionalAccess', _66 => _66.focus, 'call', _67 => _67()]);
1036
+ return bar != null;
1037
+ };
1038
+ controller.keyInterceptors.add(toBar);
1039
+ return () => void controller.keyInterceptors.delete(toBar);
1040
+ }, [controller, showing, barId]);
1041
+ _react.useEffect.call(void 0, () => {
1042
+ const root = controller.root;
1043
+ if (!root) return;
1044
+ let away = true;
1045
+ return _chunkWXMYDXPNcjs.watchCanvasFocus.call(void 0, controller, root.ownerDocument, (inside, node) => {
1046
+ if (!inside) away = true;
1047
+ else if (root.contains(node)) {
1048
+ if (away) noteFocus(controller.editor);
1049
+ away = false;
1050
+ }
1051
+ });
1052
+ }, [controller]);
1053
+ _react.useEffect.call(void 0,
1054
+ () => controller.subscribeReadOnly(() => {
1055
+ if (!controller.readOnly) return;
1056
+ endRun(link);
1057
+ queueMicrotask(() => {
1058
+ if (link.mounts > 0 && aiState(controller.editor.state).target !== null) discard(controller.editor);
1059
+ });
1060
+ }),
1061
+ [controller, link]
1062
+ );
1063
+ if (readOnly || value.target === null) return null;
1064
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1065
+ value.menu !== null && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AiMenu, { env, target: value.target, fromSpace: value.menu.fromSpace }),
1066
+ value.ghost !== null && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AiGhost, { env, ghost: value.ghost, target: value.target, gone, barId })
1067
+ ] });
1068
+ }
1069
+
1070
+ // src/extensions/ai/ai-extension.tsx
1071
+
1072
+ function aiExtension(options) {
1073
+ const { stream } = options;
1074
+ const labels = resolveAiLabels(options.labels);
1075
+ function Overlay({ controller }) {
1076
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AiOverlay, { controller, stream, labels });
1077
+ }
1078
+ const ui = {
1079
+ slashItems: aiSlashItems(labels, stream),
1080
+ bubbleItems: [aiBubbleItem(labels)],
1081
+ blockMenuItems: [aiBlockMenuItem(labels)],
1082
+ overlays: [Overlay]
1083
+ };
1084
+ return _chunkPZ4GT5JOcjs.defineExtension.call(void 0, {
1085
+ name: "ai",
1086
+ plugins: [aiPlugin],
1087
+ decorations: aiDecorations,
1088
+ keymap: { " ": openOnSpace },
1089
+ // One watcher per editor however many views mount it, and the stream ends with the last of them.
1090
+ onMount(editor) {
1091
+ const link = linkOf(editor);
1092
+ if (link.mounts++ === 0) link.stopWatching = watchGhost(editor, link);
1093
+ return () => {
1094
+ if (--link.mounts > 0) return;
1095
+ _optionalChain([link, 'access', _68 => _68.stopWatching, 'optionalCall', _69 => _69()]);
1096
+ link.stopWatching = null;
1097
+ endRun(link);
1098
+ };
1099
+ },
1100
+ ui
1101
+ });
1102
+ }
1103
+
1104
+
1105
+
1106
+ exports.aiExtension = aiExtension; exports.englishAiLabels = englishAiLabels;
1107
+ //# sourceMappingURL=ai.cjs.map