quoin-editor 0.4.2 → 1.0.1

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 +251 -0
  2. package/MIGRATION.md +233 -0
  3. package/README.md +78 -716
  4. package/dist/ai.cjs +1148 -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 +1148 -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-26Q4LSIU.js +100 -0
  17. package/dist/chunk-26Q4LSIU.js.map +1 -0
  18. package/dist/chunk-56C7GCKO.cjs +1385 -0
  19. package/dist/chunk-56C7GCKO.cjs.map +1 -0
  20. package/dist/chunk-5M4QG3ZC.cjs +3303 -0
  21. package/dist/chunk-5M4QG3ZC.cjs.map +1 -0
  22. package/dist/chunk-5R3ISX4A.cjs +6643 -0
  23. package/dist/chunk-5R3ISX4A.cjs.map +1 -0
  24. package/dist/chunk-62WKUAQY.js +3335 -0
  25. package/dist/chunk-62WKUAQY.js.map +1 -0
  26. package/dist/chunk-6LMS5J3Y.js +320 -0
  27. package/dist/chunk-6LMS5J3Y.js.map +1 -0
  28. package/dist/chunk-6PKVJZQV.cjs +100 -0
  29. package/dist/chunk-6PKVJZQV.cjs.map +1 -0
  30. package/dist/chunk-6YSGUAVW.js +376 -0
  31. package/dist/chunk-6YSGUAVW.js.map +1 -0
  32. package/dist/chunk-75C6PX2L.cjs +239 -0
  33. package/dist/chunk-75C6PX2L.cjs.map +1 -0
  34. package/dist/chunk-A4IJSJKL.js +598 -0
  35. package/dist/chunk-A4IJSJKL.js.map +1 -0
  36. package/dist/chunk-BTBHHBVR.cjs +3335 -0
  37. package/dist/chunk-BTBHHBVR.cjs.map +1 -0
  38. package/dist/chunk-CLTHD5GO.cjs +34 -0
  39. package/dist/chunk-CLTHD5GO.cjs.map +1 -0
  40. package/dist/chunk-EH5KXQXY.cjs +62 -0
  41. package/dist/chunk-EH5KXQXY.cjs.map +1 -0
  42. package/dist/chunk-ESMAW4NK.cjs +184 -0
  43. package/dist/chunk-ESMAW4NK.cjs.map +1 -0
  44. package/dist/chunk-EYFCOV3T.cjs +30 -0
  45. package/dist/chunk-EYFCOV3T.cjs.map +1 -0
  46. package/dist/chunk-F5V3IEEE.cjs +326 -0
  47. package/dist/chunk-F5V3IEEE.cjs.map +1 -0
  48. package/dist/chunk-GPIDU3GN.js +239 -0
  49. package/dist/chunk-GPIDU3GN.js.map +1 -0
  50. package/dist/chunk-HOIDJEVI.cjs +4063 -0
  51. package/dist/chunk-HOIDJEVI.cjs.map +1 -0
  52. package/dist/chunk-JJ3RASQS.cjs +706 -0
  53. package/dist/chunk-JJ3RASQS.cjs.map +1 -0
  54. package/dist/chunk-LE3F7WIP.js +6643 -0
  55. package/dist/chunk-LE3F7WIP.js.map +1 -0
  56. package/dist/chunk-LE5XMIFJ.cjs +14 -0
  57. package/dist/chunk-LE5XMIFJ.cjs.map +1 -0
  58. package/dist/chunk-LMAEPFTX.js +30 -0
  59. package/dist/chunk-LMAEPFTX.js.map +1 -0
  60. package/dist/chunk-LV6EYPJO.js +34 -0
  61. package/dist/chunk-LV6EYPJO.js.map +1 -0
  62. package/dist/chunk-MLRAVUFG.cjs +376 -0
  63. package/dist/chunk-MLRAVUFG.cjs.map +1 -0
  64. package/dist/chunk-MQUCCSWG.js +14 -0
  65. package/dist/chunk-MQUCCSWG.js.map +1 -0
  66. package/dist/chunk-O4Z2WMFF.js +62 -0
  67. package/dist/chunk-O4Z2WMFF.js.map +1 -0
  68. package/dist/chunk-OCCKQHCY.js +25 -0
  69. package/dist/chunk-OCCKQHCY.js.map +1 -0
  70. package/dist/chunk-PGSS4IOS.js +706 -0
  71. package/dist/chunk-PGSS4IOS.js.map +1 -0
  72. package/dist/chunk-PIWRSX7U.js +562 -0
  73. package/dist/chunk-PIWRSX7U.js.map +1 -0
  74. package/dist/chunk-PX6LZMH4.cjs +598 -0
  75. package/dist/chunk-PX6LZMH4.cjs.map +1 -0
  76. package/dist/chunk-QXG3HWDS.js +184 -0
  77. package/dist/chunk-QXG3HWDS.js.map +1 -0
  78. package/dist/chunk-RQW3P3GH.js +504 -0
  79. package/dist/chunk-RQW3P3GH.js.map +1 -0
  80. package/dist/chunk-SSIRYUCK.js +3303 -0
  81. package/dist/chunk-SSIRYUCK.js.map +1 -0
  82. package/dist/chunk-UBNG5YCG.js +326 -0
  83. package/dist/chunk-UBNG5YCG.js.map +1 -0
  84. package/dist/chunk-UCXLRRWY.js +1385 -0
  85. package/dist/chunk-UCXLRRWY.js.map +1 -0
  86. package/dist/chunk-UDAVVEFC.cjs +562 -0
  87. package/dist/chunk-UDAVVEFC.cjs.map +1 -0
  88. package/dist/chunk-UPSLDTLT.js +4063 -0
  89. package/dist/chunk-UPSLDTLT.js.map +1 -0
  90. package/dist/chunk-UWNZG2SD.cjs +25 -0
  91. package/dist/chunk-UWNZG2SD.cjs.map +1 -0
  92. package/dist/chunk-V3KLMSRO.cjs +504 -0
  93. package/dist/chunk-V3KLMSRO.cjs.map +1 -0
  94. package/dist/chunk-VACTAZWS.cjs +249 -0
  95. package/dist/chunk-VACTAZWS.cjs.map +1 -0
  96. package/dist/chunk-WMN6566P.js +249 -0
  97. package/dist/chunk-WMN6566P.js.map +1 -0
  98. package/dist/chunk-XX5FTPJR.cjs +320 -0
  99. package/dist/chunk-XX5FTPJR.cjs.map +1 -0
  100. package/dist/comments.cjs +1008 -0
  101. package/dist/comments.cjs.map +1 -0
  102. package/dist/comments.d.cts +93 -0
  103. package/dist/comments.d.ts +93 -0
  104. package/dist/comments.js +1008 -0
  105. package/dist/comments.js.map +1 -0
  106. package/dist/diff.cjs +346 -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 +346 -0
  111. package/dist/diff.js.map +1 -0
  112. package/dist/docx.cjs +874 -0
  113. package/dist/docx.cjs.map +1 -0
  114. package/dist/docx.d.cts +33 -0
  115. package/dist/docx.d.ts +33 -0
  116. package/dist/docx.js +874 -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-CmPlRssm.d.ts +46 -0
  131. package/dist/emoji-extension-zJ6F7hW8.d.cts +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-BcRyE9K4.d.cts +41 -0
  145. package/dist/find-extension-CmFehyul.d.ts +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-CFPmCee4.d.cts +68 -0
  159. package/dist/index-DiCGV60d.d.ts +68 -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 +562 -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 +562 -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-DisOEbbI.d.ts +40 -0
  187. package/dist/stats-extension-Dt1lgP3m.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-BTMJnT7J.d.ts +57 -0
  196. package/dist/table-extension-DxZz3jqp.d.cts +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-CR9U-l6j.d.ts +25 -0
  206. package/dist/toc-extension-DGHywOBv.d.cts +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-C6_QkXzy.d.ts +358 -0
  214. package/dist/types-CJ7Gq3GX.d.cts +358 -0
  215. package/dist/types-DULc8wwg.d.cts +120 -0
  216. package/dist/types-DULc8wwg.d.ts +120 -0
  217. package/dist/view-controller-BD1KwYfE.d.cts +105 -0
  218. package/dist/view-controller-y4cb60ue.d.ts +105 -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 +864 -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 +864 -0
  230. package/dist/yjs.js.map +1 -0
  231. package/package.json +217 -18
@@ -0,0 +1,184 @@
1
+ import {
2
+ domMapOf
3
+ } from "./chunk-SSIRYUCK.js";
4
+ import {
5
+ Transaction,
6
+ textSelection,
7
+ undoInputRule
8
+ } from "./chunk-UPSLDTLT.js";
9
+ import {
10
+ blockById,
11
+ sliceInline
12
+ } from "./chunk-62WKUAQY.js";
13
+
14
+ // src/extensions/atoms/atom-place.ts
15
+ function atomAt({ doc }, pos, types) {
16
+ const inline = blockById(doc, pos.block)?.regions[pos.region];
17
+ const [node] = inline === void 0 || pos.offset < 0 ? [] : sliceInline(inline, pos.offset, pos.offset + 1);
18
+ return node?.kind === "atom" && types.includes(node.type) ? node : null;
19
+ }
20
+ function atomPlaceAt(state, pos, types) {
21
+ const node = atomAt(state, pos, types);
22
+ return node === null ? null : { ...pos, node };
23
+ }
24
+ function atomBeforeCaret(state, types) {
25
+ const { selection } = state;
26
+ if (selection?.kind !== "text") return null;
27
+ const { anchor, head } = selection;
28
+ if (anchor.block !== head.block || anchor.region !== head.region || anchor.offset !== head.offset) return null;
29
+ return head.offset === 0 ? null : atomPlaceAt(state, { ...head, offset: head.offset - 1 }, types);
30
+ }
31
+ function selectedAtom(state, types) {
32
+ const { selection } = state;
33
+ if (selection?.kind !== "text") return null;
34
+ const { anchor, head } = selection;
35
+ if (anchor.block !== head.block || anchor.region !== head.region || Math.abs(anchor.offset - head.offset) !== 1) {
36
+ return null;
37
+ }
38
+ return atomPlaceAt(state, { ...head, offset: Math.min(anchor.offset, head.offset) }, types);
39
+ }
40
+
41
+ // src/extensions/atoms/extend-over-atom.ts
42
+ function extendOverAtom(types, direction) {
43
+ return (state, dispatch) => {
44
+ const { selection } = state;
45
+ if (selection?.kind !== "text") return false;
46
+ const { anchor, head } = selection;
47
+ if (atomAt(state, { ...head, offset: direction < 0 ? head.offset - 1 : head.offset }, types) === null) return false;
48
+ dispatch?.(new Transaction(state).setSelection(textSelection(anchor, { ...head, offset: head.offset + direction })));
49
+ return true;
50
+ };
51
+ }
52
+
53
+ // src/extensions/atoms/select-atom-backward.ts
54
+ function selectAtomBackward(types) {
55
+ return (state, dispatch) => {
56
+ if (undoInputRule(state, dispatch)) return true;
57
+ const place = atomBeforeCaret(state, types);
58
+ if (place === null) return false;
59
+ const { block, region, offset } = place;
60
+ const atom = textSelection({ block, region, offset }, { block, region, offset: offset + 1 });
61
+ dispatch?.(new Transaction(state).setSelection(atom));
62
+ return true;
63
+ };
64
+ }
65
+
66
+ // src/extensions/atoms/atom-keymap.ts
67
+ function atomKeymap(types) {
68
+ return {
69
+ Backspace: selectAtomBackward(types),
70
+ "Shift-ArrowLeft": extendOverAtom(types, -1),
71
+ "Shift-ArrowRight": extendOverAtom(types, 1)
72
+ };
73
+ }
74
+
75
+ // src/extensions/atoms/selected-atom-decorations.ts
76
+ var SELECTED_ATOM = "data-quoin-selected-atom";
77
+ function selectedAtomDecorations(types) {
78
+ return (state) => {
79
+ const place = selectedAtom(state, types);
80
+ if (place === null) return [];
81
+ const { block, region, offset } = place;
82
+ return [{ kind: "inline", block, region, from: offset, to: offset + 1, attrs: { [SELECTED_ATOM]: "" } }];
83
+ };
84
+ }
85
+
86
+ // src/extensions/atoms/use-selection-out-of-atoms.ts
87
+ import { useEffect } from "react";
88
+
89
+ // src/extensions/atoms/selection-out-of-atoms.ts
90
+ var ELEMENT_NODE = 1;
91
+ function atomAround(node, types) {
92
+ const element = node.nodeType === ELEMENT_NODE ? node : node.parentElement;
93
+ const atom = element?.closest("[data-quoin-atom]") ?? null;
94
+ return atom !== null && types.includes(atom.getAttribute("data-quoin-atom") ?? "") ? atom : null;
95
+ }
96
+ function follows(atom, { node, offset }) {
97
+ const range = atom.ownerDocument.createRange();
98
+ range.selectNode(atom);
99
+ return range.comparePoint(node, offset) > 0;
100
+ }
101
+ function mapOf(atom, hostOf) {
102
+ const host = hostOf(atom);
103
+ return host === null ? void 0 : domMapOf(host);
104
+ }
105
+ function beside(atom, after, hostOf) {
106
+ const map = mapOf(atom, hostOf);
107
+ const from = map?.fromDom(atom, 0);
108
+ if (map === void 0 || from === null || from === void 0) return null;
109
+ return after ? map.toDom(from + 1, -1) : map.toDom(from, 1);
110
+ }
111
+ function caretOutside(atom, { node, offset }, hostOf) {
112
+ const map = mapOf(atom, hostOf);
113
+ const at = map?.fromDom(node, offset);
114
+ return map === void 0 || at === null || at === void 0 ? null : map.toDom(at, -1);
115
+ }
116
+ function moveSelectionOutOfAtoms(selection, hostOf, types) {
117
+ const { anchorNode, anchorOffset, focusNode, focusOffset } = selection;
118
+ if (anchorNode === null || focusNode === null) return false;
119
+ const anchor = { node: anchorNode, offset: anchorOffset };
120
+ const focus = { node: focusNode, offset: focusOffset };
121
+ const anchorAtom = atomAround(anchorNode, types);
122
+ const focusAtom = atomAround(focusNode, types);
123
+ let ends;
124
+ if (focusAtom !== null && selection.isCollapsed) {
125
+ const caret = caretOutside(focusAtom, focus, hostOf);
126
+ ends = [caret, caret];
127
+ } else if (focusAtom !== null && anchorAtom === focusAtom) {
128
+ ends = [beside(focusAtom, false, hostOf), beside(focusAtom, true, hostOf)];
129
+ } else {
130
+ ends = [
131
+ anchorAtom === null ? anchor : beside(anchorAtom, !follows(anchorAtom, focus), hostOf),
132
+ focusAtom === null ? focus : beside(focusAtom, !follows(focusAtom, anchor), hostOf)
133
+ ];
134
+ }
135
+ const [base, extent] = ends;
136
+ if (anchorAtom === null && focusAtom === null || base === null || extent === null) return false;
137
+ selection.setBaseAndExtent(base.node, base.offset, extent.node, extent.offset);
138
+ return true;
139
+ }
140
+
141
+ // src/extensions/atoms/use-selection-out-of-atoms.ts
142
+ function useSelectionOutOfAtoms(controller, types, editable) {
143
+ useEffect(() => {
144
+ const root = controller.root;
145
+ const view = root?.ownerDocument.defaultView;
146
+ if (!editable || root === null || !view) return;
147
+ const hostOf = (node) => controller.registry.locate(node)?.element ?? null;
148
+ const moveOut = () => {
149
+ const selection = view.getSelection();
150
+ if (selection === null || controller.composingKey !== null) return;
151
+ if (root.contains(root.ownerDocument.activeElement)) moveSelectionOutOfAtoms(selection, hostOf, types);
152
+ };
153
+ view.addEventListener("selectionchange", moveOut, true);
154
+ root.addEventListener("keydown", moveOut, true);
155
+ return () => {
156
+ view.removeEventListener("selectionchange", moveOut, true);
157
+ root.removeEventListener("keydown", moveOut, true);
158
+ };
159
+ }, [controller, types, editable]);
160
+ }
161
+
162
+ // src/extensions/atoms/atom-at-target.ts
163
+ function atomAtTarget(controller, target, types) {
164
+ const element = target?.closest?.("[data-quoin-atom]");
165
+ if (!element) return null;
166
+ const host = controller.registry.locate(element);
167
+ const offset = host === null ? null : domMapOf(host.element)?.fromDom(element, 0);
168
+ if (host === null || offset === null || offset === void 0) return null;
169
+ return atomPlaceAt(controller.editor.state, { block: host.block, region: host.region, offset }, types);
170
+ }
171
+
172
+ // src/extensions/atoms/plain-enter.ts
173
+ var plainEnter = (event) => event.key === "Enter" && !event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey;
174
+
175
+ export {
176
+ atomAt,
177
+ selectedAtom,
178
+ atomKeymap,
179
+ selectedAtomDecorations,
180
+ useSelectionOutOfAtoms,
181
+ atomAtTarget,
182
+ plainEnter
183
+ };
184
+ //# sourceMappingURL=chunk-QXG3HWDS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/extensions/atoms/atom-place.ts","../src/extensions/atoms/extend-over-atom.ts","../src/extensions/atoms/select-atom-backward.ts","../src/extensions/atoms/atom-keymap.ts","../src/extensions/atoms/selected-atom-decorations.ts","../src/extensions/atoms/use-selection-out-of-atoms.ts","../src/extensions/atoms/selection-out-of-atoms.ts","../src/extensions/atoms/atom-at-target.ts","../src/extensions/atoms/plain-enter.ts"],"mappings":"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","names":[]}
@@ -0,0 +1,504 @@
1
+ import {
2
+ FOCUS_RING,
3
+ Input,
4
+ Popover,
5
+ PopoverAnchor,
6
+ PopoverContent,
7
+ SuggestionMenu,
8
+ bubblePart,
9
+ cn,
10
+ noChange,
11
+ preventDefault,
12
+ replaceTrigger,
13
+ runOnBlocks,
14
+ styleTargets,
15
+ suggestionPlugin,
16
+ toError,
17
+ useOutsidePress,
18
+ usePartAnchor,
19
+ useQuoin
20
+ } from "./chunk-LE3F7WIP.js";
21
+ import {
22
+ useEditorState,
23
+ useIsomorphicLayoutEffect,
24
+ useReadOnly
25
+ } from "./chunk-SSIRYUCK.js";
26
+ import {
27
+ createPluginKey,
28
+ defineExtension,
29
+ getPluginState,
30
+ insertText,
31
+ setAttrs
32
+ } from "./chunk-UPSLDTLT.js";
33
+ import {
34
+ blockById
35
+ } from "./chunk-62WKUAQY.js";
36
+
37
+ // src/extensions/emoji/CalloutIconPicker.tsx
38
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef3 } from "react";
39
+
40
+ // src/extensions/emoji/all-callouts.ts
41
+ var allCallouts = (state, blockIds) => blockIds.length > 0 && blockIds.every((id) => blockById(state.doc, id)?.type === "CALLOUT");
42
+
43
+ // src/extensions/emoji/composing-key.ts
44
+ var isComposing = (event) => event.isComposing || event.keyCode === 229;
45
+
46
+ // src/extensions/emoji/EmojiPicker.tsx
47
+ import { useMemo, useRef as useRef2, useState as useState3 } from "react";
48
+
49
+ // src/extensions/emoji/EmojiGrids.tsx
50
+ import { forwardRef, memo, useId, useState } from "react";
51
+
52
+ // src/extensions/emoji/emoji-name.ts
53
+ var emojiName = ({ shortcodes, tags }) => shortcodes[0] ?? tags[0] ?? "";
54
+
55
+ // src/extensions/emoji/grid-moves.ts
56
+ var inRow = (rows, row, col) => ({ row, col: Math.min(col, rows[row] - 1) });
57
+ var MOVES = {
58
+ ArrowRight: (rows, { row, col }) => {
59
+ if (col + 1 < rows[row]) return { row, col: col + 1 };
60
+ return row + 1 < rows.length ? { row: row + 1, col: 0 } : { row, col };
61
+ },
62
+ ArrowLeft: (rows, { row, col }) => {
63
+ if (col > 0) return { row, col: col - 1 };
64
+ return row > 0 ? { row: row - 1, col: rows[row - 1] - 1 } : { row, col };
65
+ },
66
+ ArrowDown: (rows, { row, col }) => inRow(rows, Math.min(row + 1, rows.length - 1), col),
67
+ ArrowUp: (rows, { row, col }) => inRow(rows, Math.max(row - 1, 0), col),
68
+ Home: (_, { row }, ctrl) => ctrl ? { row: 0, col: 0 } : { row, col: 0 },
69
+ End: (rows, { row }, ctrl) => {
70
+ const to = ctrl ? rows.length - 1 : row;
71
+ return { row: to, col: rows[to] - 1 };
72
+ }
73
+ };
74
+ function gridMove(rows, cell, key, ctrl = false) {
75
+ return Object.hasOwn(MOVES, key) ? MOVES[key](rows, cell, ctrl) : null;
76
+ }
77
+
78
+ // src/extensions/emoji/EmojiGrids.tsx
79
+ import { jsx, jsxs } from "react/jsx-runtime";
80
+ var CELL = cn(
81
+ "flex size-8 shrink-0 cursor-default items-center justify-center rounded-sm text-xl hover:bg-accent",
82
+ FOCUS_RING
83
+ );
84
+ var HEADING = "px-1 pt-2 pb-1 text-xs font-medium text-muted-foreground";
85
+ var FIRST = { row: 0, col: 0 };
86
+ var cellId = (baseId, row, col) => `${baseId}-cell-${row}-${col}`;
87
+ var emojiAt = (target) => target instanceof Element ? target.closest("[data-emoji]")?.getAttribute("data-emoji") ?? null : null;
88
+ var EmojiRow = memo(function EmojiRow2({ baseId, row, emoji, activeCol }) {
89
+ return /* @__PURE__ */ jsx("div", { role: "row", className: "flex", children: emoji.map((cell, col) => /* @__PURE__ */ jsx(
90
+ "div",
91
+ {
92
+ role: "gridcell",
93
+ id: cellId(baseId, row, col),
94
+ tabIndex: col === activeCol ? 0 : -1,
95
+ "aria-label": emojiName(cell),
96
+ "data-emoji": cell.emoji,
97
+ className: CELL,
98
+ children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: cell.emoji })
99
+ },
100
+ cell.emoji
101
+ )) });
102
+ });
103
+ var EmojiGrids = forwardRef(function EmojiGrids2({ layout, onPick }, ref) {
104
+ const baseId = useId();
105
+ const [active, setActive] = useState(null);
106
+ const current = (active === null ? void 0 : layout.places.get(active)) ?? FIRST;
107
+ const onKeyDown = (event) => {
108
+ if (isComposing(event.nativeEvent) || event.altKey || event.shiftKey || event.metaKey) return;
109
+ if (event.key === "Enter") {
110
+ const emoji = emojiAt(event.target);
111
+ if (emoji === null) return;
112
+ event.preventDefault();
113
+ onPick(emoji);
114
+ return;
115
+ }
116
+ const next = gridMove(layout.rowLengths, current, event.key, event.ctrlKey);
117
+ if (next === null) return;
118
+ event.preventDefault();
119
+ setActive(layout.rows[next.row][next.col].emoji);
120
+ event.currentTarget.ownerDocument.getElementById(cellId(baseId, next.row, next.col))?.focus();
121
+ };
122
+ const onClick = (event) => {
123
+ const emoji = emojiAt(event.target);
124
+ if (emoji !== null) onPick(emoji);
125
+ };
126
+ const onFocus = (event) => {
127
+ const emoji = emojiAt(event.target);
128
+ if (emoji !== null) setActive(emoji);
129
+ };
130
+ return /* @__PURE__ */ jsx("div", { ref, className: "max-h-72 overflow-y-auto", onKeyDown, onClick, onFocus, children: layout.sections.map((section) => /* @__PURE__ */ jsxs("div", { children: [
131
+ /* @__PURE__ */ jsx("div", { id: `${baseId}-${section.key}`, className: HEADING, children: section.label }),
132
+ /* @__PURE__ */ jsx("div", { role: "grid", "aria-labelledby": `${baseId}-${section.key}`, children: section.rows.map((emoji, index) => {
133
+ const row = section.firstRow + index;
134
+ return /* @__PURE__ */ jsx(
135
+ EmojiRow,
136
+ {
137
+ baseId,
138
+ row,
139
+ emoji,
140
+ activeCol: row === current.row ? current.col : null
141
+ },
142
+ row
143
+ );
144
+ }) })
145
+ ] }, section.key)) });
146
+ });
147
+
148
+ // src/extensions/emoji/picker-layout.ts
149
+ var COLUMNS = 8;
150
+ function inRows(emoji) {
151
+ const rows = [];
152
+ for (let start = 0; start < emoji.length; start += COLUMNS) rows.push(emoji.slice(start, start + COLUMNS));
153
+ return rows;
154
+ }
155
+ function grouped(found, labels) {
156
+ const byGroup = /* @__PURE__ */ new Map();
157
+ for (const emoji of found) {
158
+ const group = byGroup.get(emoji.group);
159
+ if (group === void 0) byGroup.set(emoji.group, [emoji]);
160
+ else group.push(emoji);
161
+ }
162
+ return [...byGroup].map(([group, emoji]) => ({ key: group, label: labels.groups[group], rows: inRows(emoji) }));
163
+ }
164
+ function pickerLayout(found, searching, labels) {
165
+ const unplaced = found.length === 0 ? [] : searching ? [{ key: "results", label: labels.searchResults, rows: inRows(found) }] : grouped(found, labels);
166
+ let firstRow = 0;
167
+ const sections = unplaced.map((section) => {
168
+ const placed = { ...section, firstRow };
169
+ firstRow += section.rows.length;
170
+ return placed;
171
+ });
172
+ const rows = sections.flatMap((section) => section.rows);
173
+ const places = /* @__PURE__ */ new Map();
174
+ rows.forEach((cells, row) => cells.forEach(({ emoji }, col) => places.set(emoji, { row, col })));
175
+ return { sections, rows, rowLengths: rows.map((cells) => cells.length), places };
176
+ }
177
+
178
+ // src/extensions/emoji/use-emoji-data.ts
179
+ import { useEffect, useRef, useState as useState2 } from "react";
180
+
181
+ // src/extensions/emoji/lazy-load.ts
182
+ function lazyLoad(load) {
183
+ let pending = null;
184
+ let value = null;
185
+ return {
186
+ load() {
187
+ pending ??= new Promise((resolve) => resolve(load())).then(
188
+ (current) => {
189
+ value = { current };
190
+ return current;
191
+ },
192
+ (reason) => {
193
+ pending = null;
194
+ throw reason;
195
+ }
196
+ );
197
+ return pending;
198
+ },
199
+ loaded: () => value?.current
200
+ };
201
+ }
202
+
203
+ // src/extensions/emoji/emoji-data.ts
204
+ var importEmojiData = () => import("./emoji-data.js").then(({ searchEmoji, emojiByShortcode, skinTones }) => ({
205
+ searchEmoji,
206
+ emojiByShortcode,
207
+ skinTones
208
+ }));
209
+ var emojiData = lazyLoad(importEmojiData);
210
+ var loadEmojiData = () => emojiData.load();
211
+
212
+ // src/extensions/emoji/use-emoji-data.ts
213
+ function useEmojiData() {
214
+ const { onError } = useQuoin();
215
+ const report = useRef(onError);
216
+ useIsomorphicLayoutEffect(() => {
217
+ report.current = onError;
218
+ });
219
+ const [state, setState] = useState2(() => emojiData.loaded() ?? "loading");
220
+ useEffect(() => {
221
+ let current = true;
222
+ emojiData.load().then(
223
+ (data) => {
224
+ if (current) setState(data);
225
+ },
226
+ (reason) => {
227
+ if (!current) return;
228
+ setState("failed");
229
+ report.current(toError(reason));
230
+ }
231
+ );
232
+ return () => {
233
+ current = false;
234
+ };
235
+ }, []);
236
+ return state;
237
+ }
238
+
239
+ // src/extensions/emoji/EmojiPicker.tsx
240
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
241
+ var ACTIVE_CELL = '[role="gridcell"][tabindex="0"]';
242
+ function EmojiPicker({ labels, onPick }) {
243
+ const data = useEmojiData();
244
+ const [query, setQuery] = useState3("");
245
+ const field = useRef2(null);
246
+ const grids = useRef2(null);
247
+ const searching = query.trim() !== "";
248
+ const layout = useMemo(
249
+ () => typeof data === "string" ? null : pickerLayout(data.searchEmoji(query), searching, labels),
250
+ [data, query, searching, labels]
251
+ );
252
+ const shown = layout !== null && layout.sections.length > 0;
253
+ const status = data === "loading" ? labels.loading : data === "failed" ? labels.loadFailed : shown ? "" : labels.noMatches;
254
+ const focusGrids = () => grids.current?.querySelector(ACTIVE_CELL)?.focus();
255
+ const onKeyDown = (event) => {
256
+ if (event.key !== "Tab" || isComposing(event.nativeEvent) || event.altKey || event.ctrlKey || event.metaKey) return;
257
+ event.preventDefault();
258
+ event.stopPropagation();
259
+ if (event.target === field.current) focusGrids();
260
+ else field.current?.focus();
261
+ };
262
+ const onFieldKeyDown = (event) => {
263
+ if (isComposing(event.nativeEvent)) return;
264
+ if (event.key === "ArrowDown") {
265
+ event.preventDefault();
266
+ focusGrids();
267
+ } else if (event.key === "Enter" && searching && shown) {
268
+ event.preventDefault();
269
+ onPick(layout.rows[0][0].emoji);
270
+ }
271
+ };
272
+ return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-1", onKeyDown, children: [
273
+ /* @__PURE__ */ jsx2(
274
+ Input,
275
+ {
276
+ ref: field,
277
+ className: "h-8",
278
+ "aria-label": labels.searchEmoji,
279
+ placeholder: labels.searchEmoji,
280
+ autoComplete: "off",
281
+ spellCheck: false,
282
+ value: query,
283
+ onChange: (event) => setQuery(event.target.value),
284
+ onKeyDown: onFieldKeyDown
285
+ }
286
+ ),
287
+ /* @__PURE__ */ jsx2("p", { role: "status", className: "px-1 text-sm text-muted-foreground empty:hidden", children: status }),
288
+ shown && /* @__PURE__ */ jsx2(EmojiGrids, { ref: grids, layout, onPick })
289
+ ] });
290
+ }
291
+
292
+ // src/extensions/emoji/icon-request.ts
293
+ import { useCallback, useSyncExternalStore } from "react";
294
+ var stores = /* @__PURE__ */ new WeakMap();
295
+ function storeOf(controller) {
296
+ let store = stores.get(controller);
297
+ if (store === void 0) {
298
+ store = { request: null, listeners: /* @__PURE__ */ new Set() };
299
+ stores.set(controller, store);
300
+ }
301
+ return store;
302
+ }
303
+ function requestIcon(controller, request) {
304
+ const store = storeOf(controller);
305
+ if (store.request === request) return;
306
+ store.request = request;
307
+ for (const listener of [...store.listeners]) listener();
308
+ }
309
+ function useIconRequest(controller) {
310
+ const subscribe = useCallback(
311
+ (notify) => {
312
+ const { listeners } = storeOf(controller);
313
+ listeners.add(notify);
314
+ return () => void listeners.delete(notify);
315
+ },
316
+ [controller]
317
+ );
318
+ const read = useCallback(() => storeOf(controller).request, [controller]);
319
+ return useSyncExternalStore(subscribe, read, read);
320
+ }
321
+
322
+ // src/extensions/emoji/CalloutIconPicker.tsx
323
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
324
+ var CALLOUT_ICON = ".quoin-callout > :first-child";
325
+ function CalloutIconPicker({ controller, labels }) {
326
+ const readOnly = useReadOnly(controller);
327
+ const request = useIconRequest(controller);
328
+ const there = useEditorState(
329
+ controller,
330
+ useCallback2((state) => request !== null && allCallouts(state, request.blocks), [request])
331
+ );
332
+ const shown = request !== null && there && !readOnly;
333
+ useEffect2(() => {
334
+ if (request !== null && !shown) requestIcon(controller, null);
335
+ }, [controller, request, shown]);
336
+ if (!shown) return null;
337
+ return /* @__PURE__ */ jsx3(IconPopover, { controller, labels, request }, request.blocks.join(" "));
338
+ }
339
+ function IconPopover({ controller, labels, request: { blocks } }) {
340
+ const anchor = usePartAnchor(controller, blocks[0], CALLOUT_ICON);
341
+ const content = useRef3(null);
342
+ const close = () => requestIcon(controller, null);
343
+ const finish = (icon) => {
344
+ close();
345
+ runOnBlocks(controller, blocks, icon === null ? noChange : setAttrs({ icon }));
346
+ controller.focus();
347
+ };
348
+ const ownerDocument = useCallback2(() => controller.root?.ownerDocument ?? document, [controller]);
349
+ useOutsidePress(content, ownerDocument, close);
350
+ return /* @__PURE__ */ jsxs3(
351
+ Popover,
352
+ {
353
+ open: true,
354
+ modal: false,
355
+ onOpenChange: (open) => {
356
+ if (!open) close();
357
+ },
358
+ children: [
359
+ /* @__PURE__ */ jsx3(PopoverAnchor, { virtualRef: anchor }),
360
+ /* @__PURE__ */ jsx3(
361
+ PopoverContent,
362
+ {
363
+ ref: content,
364
+ "aria-label": labels.chooseIcon,
365
+ side: "bottom",
366
+ align: "start",
367
+ className: "w-80 p-2",
368
+ onCloseAutoFocus: preventDefault,
369
+ onEscapeKeyDown: (event) => {
370
+ event.preventDefault();
371
+ if (!isComposing(event)) finish(null);
372
+ },
373
+ ...bubblePart(controller),
374
+ children: /* @__PURE__ */ jsx3(EmojiPicker, { labels, onPick: finish })
375
+ }
376
+ )
377
+ ]
378
+ }
379
+ );
380
+ }
381
+
382
+ // src/extensions/emoji/choose-icon-action.ts
383
+ import { SmilePlus } from "lucide-react";
384
+ function calloutsFor(state, blockIds) {
385
+ if (blockIds.length === 0 || !state.doc.index.has(blockIds[0])) return null;
386
+ const targets = styleTargets(state, blockIds[0]);
387
+ return allCallouts(state, targets) ? targets : null;
388
+ }
389
+ var chooseIconAction = (labels) => ({
390
+ id: "choose-icon",
391
+ label: labels.chooseIcon,
392
+ icon: SmilePlus,
393
+ available: (state, blockIds) => calloutsFor(state, blockIds) !== null,
394
+ run: (controller, blockIds) => {
395
+ const blocks = calloutsFor(controller.editor.state, blockIds);
396
+ if (blocks !== null) requestIcon(controller, { blocks });
397
+ }
398
+ });
399
+
400
+ // src/extensions/emoji/emoji-key.ts
401
+ var emojiKey = createPluginKey("emoji");
402
+
403
+ // src/extensions/emoji/emoji-labels.ts
404
+ var englishEmojiLabels = {
405
+ emojiMenu: "Emoji",
406
+ loading: "Loading emoji\u2026",
407
+ loadFailed: "Emoji could not be loaded",
408
+ noMatches: "No emoji found",
409
+ chooseIcon: "Choose icon",
410
+ searchEmoji: "Search emoji",
411
+ searchResults: "Search results",
412
+ groups: {
413
+ smileys: "Smileys and emotion",
414
+ people: "People and body",
415
+ animals: "Animals and nature",
416
+ food: "Food and drink",
417
+ travel: "Travel and places",
418
+ activities: "Activities",
419
+ objects: "Objects",
420
+ symbols: "Symbols",
421
+ flags: "Flags"
422
+ }
423
+ };
424
+ function resolveEmojiLabels(overrides) {
425
+ const given = Object.entries(overrides ?? {}).filter(([, value]) => value !== void 0);
426
+ return given.length === 0 ? englishEmojiLabels : { ...englishEmojiLabels, ...Object.fromEntries(given) };
427
+ }
428
+
429
+ // src/extensions/emoji/EmojiMenu.tsx
430
+ import { useCallback as useCallback3, useMemo as useMemo2, useState as useState4 } from "react";
431
+
432
+ // src/extensions/emoji/emoji-source.ts
433
+ function emojiSource(limit, onFailure) {
434
+ let failed = false;
435
+ return (query) => {
436
+ const data = emojiData.loaded();
437
+ if (data !== void 0) return data.searchEmoji(query, limit);
438
+ if (failed) return [];
439
+ return emojiData.load().then(
440
+ (loaded) => loaded.searchEmoji(query, limit),
441
+ (reason) => {
442
+ failed = true;
443
+ onFailure();
444
+ throw reason;
445
+ }
446
+ );
447
+ };
448
+ }
449
+
450
+ // src/extensions/emoji/EmojiMenu.tsx
451
+ import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
452
+ var SHOWN = 8;
453
+ var SHORTEST_QUERY = 2;
454
+ var queryAt = (state) => getPluginState(state, emojiKey).active?.query ?? null;
455
+ var emojiOf = ({ emoji }) => emoji;
456
+ var renderEmoji = (emoji) => /* @__PURE__ */ jsxs4(Fragment, { children: [
457
+ /* @__PURE__ */ jsx4("span", { "aria-hidden": "true", className: "text-base", children: emoji.emoji }),
458
+ /* @__PURE__ */ jsx4("span", { className: "truncate", children: emojiName(emoji) })
459
+ ] });
460
+ function EmojiMenu({ controller, labels }) {
461
+ const readOnly = useReadOnly(controller);
462
+ const query = useEditorState(controller, queryAt);
463
+ if (readOnly || query === null || query.length < SHORTEST_QUERY) return null;
464
+ return /* @__PURE__ */ jsx4(EmojiMatches, { controller, labels });
465
+ }
466
+ function EmojiMatches({ controller, labels }) {
467
+ const [failed, setFailed] = useState4(false);
468
+ const source = useMemo2(() => emojiSource(SHOWN, () => setFailed(true)), []);
469
+ const choose = useCallback3(
470
+ (emoji, range) => void replaceTrigger(controller, range, insertText(emoji.emoji)),
471
+ [controller]
472
+ );
473
+ return /* @__PURE__ */ jsx4(
474
+ SuggestionMenu,
475
+ {
476
+ controller,
477
+ pluginKey: emojiKey,
478
+ items: source,
479
+ itemKey: emojiOf,
480
+ renderItem: renderEmoji,
481
+ onSelect: choose,
482
+ label: labels.emojiMenu,
483
+ emptyLabel: failed ? labels.loadFailed : labels.noMatches,
484
+ pendingLabel: labels.loading
485
+ }
486
+ );
487
+ }
488
+
489
+ // src/extensions/emoji/emoji-extension.tsx
490
+ import { jsx as jsx5 } from "react/jsx-runtime";
491
+ function emojiExtension(options = {}) {
492
+ const labels = resolveEmojiLabels(options.labels);
493
+ const Menu = ({ controller }) => /* @__PURE__ */ jsx5(EmojiMenu, { controller, labels });
494
+ const Picker = ({ controller }) => /* @__PURE__ */ jsx5(CalloutIconPicker, { controller, labels });
495
+ const ui = { blockMenuItems: [chooseIconAction(labels)], overlays: [Menu, Picker] };
496
+ return defineExtension({ name: "emoji", plugins: [suggestionPlugin(emojiKey, { char: ":" })], ui });
497
+ }
498
+
499
+ export {
500
+ loadEmojiData,
501
+ englishEmojiLabels,
502
+ emojiExtension
503
+ };
504
+ //# sourceMappingURL=chunk-RQW3P3GH.js.map