@coze-editor/react-components 0.1.0-alpha.0fd19e

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.
package/dist/index.js ADDED
@@ -0,0 +1,1474 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/index.ts
30
+ var index_exports = {};
31
+ __export(index_exports, {
32
+ ActiveLinePlaceholder: () => ActiveLinePlaceholder,
33
+ CursorInlayHint: () => CursorInlayHint,
34
+ CursorMirror: () => CursorMirror,
35
+ DiagnosticMarkers: () => DiagnosticMarkers,
36
+ DiffView: () => DiffView,
37
+ EmbededLineView: () => EmbededLineView,
38
+ EmbededLineViewSide: () => EmbededLineViewSide,
39
+ FoldGutter: () => FoldGutter,
40
+ Gutter: () => Gutter,
41
+ GutterLineMarker: () => GutterLineMarker,
42
+ GutterPlacement: () => GutterPlacement,
43
+ LineWidget: () => LineWidget,
44
+ Markers: () => Markers,
45
+ Mention: () => Mention,
46
+ Placeholder: () => Placeholder,
47
+ PositionMirror: () => PositionMirror,
48
+ RefElement: () => RefElement,
49
+ SelectionSide: () => import_extensions.SelectionSide,
50
+ getCurrentMentionReplaceRange: () => getCurrentMentionReplaceRange
51
+ });
52
+ module.exports = __toCommonJS(index_exports);
53
+
54
+ // src/cursor-mirror/index.tsx
55
+ var import_react = require("react");
56
+ var import_dom = require("@floating-ui/dom");
57
+ var import_react2 = require("@coze-editor/react");
58
+ var import_extensions = require("@coze-editor/extensions");
59
+ var CursorMirror = (0, import_react.forwardRef)(function CursorMirror2({ side, onChange, onVisibleChange }, ref) {
60
+ const injector = (0, import_react2.useInjector)();
61
+ const editor = (0, import_react2.useEditor)();
62
+ const [dom] = (0, import_react.useState)(() => document.createElement("div"));
63
+ const domRef = (0, import_react.useRef)(dom);
64
+ domRef.current = dom;
65
+ const onChangeRef = (0, import_react.useRef)(onChange);
66
+ onChangeRef.current = onChange;
67
+ const onVisibleChangeRef = (0, import_react.useRef)(onVisibleChange);
68
+ onVisibleChangeRef.current = onVisibleChange;
69
+ (0, import_react.useImperativeHandle)(ref, () => domRef.current);
70
+ (0, import_react.useLayoutEffect)(
71
+ () => injector.inject([
72
+ import_extensions.elementAtPosition.of({
73
+ dom: domRef.current,
74
+ pos: side
75
+ }),
76
+ import_extensions.positionElementLayer
77
+ ]),
78
+ [injector, side]
79
+ );
80
+ (0, import_react.useEffect)(() => {
81
+ const floating = document.createElement("div");
82
+ document.body.appendChild(floating);
83
+ const dispose = (0, import_dom.autoUpdate)(
84
+ domRef.current,
85
+ floating,
86
+ () => {
87
+ if (typeof onChangeRef.current === "function") {
88
+ onChangeRef.current();
89
+ }
90
+ },
91
+ { animationFrame: true }
92
+ );
93
+ return () => {
94
+ document.body.removeChild(floating);
95
+ dispose();
96
+ };
97
+ }, []);
98
+ (0, import_react.useEffect)(() => {
99
+ if (!editor) {
100
+ return;
101
+ }
102
+ const view = editor.$view;
103
+ const observer = new IntersectionObserver(
104
+ (entries) => {
105
+ entries.forEach((entry) => {
106
+ if (typeof onVisibleChangeRef.current === "function") {
107
+ onVisibleChangeRef.current(entry.isIntersecting);
108
+ }
109
+ });
110
+ },
111
+ {
112
+ root: view.scrollDOM,
113
+ threshold: 0
114
+ }
115
+ );
116
+ observer.observe(domRef.current);
117
+ return () => {
118
+ observer.disconnect();
119
+ };
120
+ }, [editor]);
121
+ return null;
122
+ });
123
+
124
+ // src/position-mirror/index.tsx
125
+ var import_react3 = require("react");
126
+ var import_dom2 = require("@floating-ui/dom");
127
+ var import_react4 = require("@coze-editor/react");
128
+ var import_extensions2 = require("@coze-editor/extensions");
129
+ var PositionMirror = (0, import_react3.forwardRef)(function CursorMirror3({ position, onChange, onVisibleChange }, ref) {
130
+ const injector = (0, import_react4.useInjector)();
131
+ const editor = (0, import_react4.useEditor)();
132
+ const [dom] = (0, import_react3.useState)(() => {
133
+ const el = document.createElement("div");
134
+ el.classList.add("cm-position-mirror");
135
+ return el;
136
+ });
137
+ const domRef = (0, import_react3.useRef)(dom);
138
+ domRef.current = dom;
139
+ const onChangeRef = (0, import_react3.useRef)(onChange);
140
+ onChangeRef.current = onChange;
141
+ const onVisibleChangeRef = (0, import_react3.useRef)(onVisibleChange);
142
+ onVisibleChangeRef.current = onVisibleChange;
143
+ (0, import_react3.useImperativeHandle)(ref, () => domRef.current);
144
+ (0, import_react3.useLayoutEffect)(
145
+ () => injector.inject([
146
+ import_extensions2.elementAtPosition.of({
147
+ dom: domRef.current,
148
+ pos: position
149
+ }),
150
+ import_extensions2.positionElementLayer
151
+ ]),
152
+ [injector, position]
153
+ );
154
+ (0, import_react3.useEffect)(() => {
155
+ const floating = document.createElement("div");
156
+ document.body.appendChild(floating);
157
+ const dispose = (0, import_dom2.autoUpdate)(
158
+ domRef.current,
159
+ floating,
160
+ () => {
161
+ if (typeof onChangeRef.current === "function") {
162
+ onChangeRef.current();
163
+ }
164
+ },
165
+ { animationFrame: true }
166
+ );
167
+ return () => {
168
+ document.body.removeChild(floating);
169
+ dispose();
170
+ };
171
+ }, []);
172
+ (0, import_react3.useEffect)(() => {
173
+ if (!editor) {
174
+ return;
175
+ }
176
+ const view = editor.$view;
177
+ const observer = new IntersectionObserver(
178
+ (entries) => {
179
+ entries.forEach((entry) => {
180
+ if (typeof onVisibleChangeRef.current === "function") {
181
+ onVisibleChangeRef.current(entry.isIntersecting);
182
+ }
183
+ });
184
+ },
185
+ {
186
+ root: view.scrollDOM,
187
+ threshold: 0
188
+ }
189
+ );
190
+ observer.observe(domRef.current);
191
+ return () => {
192
+ observer.disconnect();
193
+ };
194
+ }, [editor]);
195
+ return null;
196
+ });
197
+
198
+ // src/cursor-inlay-hint/index.tsx
199
+ var import_react_dom = require("react-dom");
200
+ var import_react5 = require("react");
201
+ var import_react_hooks = require("@coze-editor/react-hooks");
202
+ var import_react6 = require("@coze-editor/react");
203
+ var import_view = require("@codemirror/view");
204
+ var InlayHintWidget = class extends import_view.WidgetType {
205
+ constructor(element) {
206
+ super();
207
+ this.element = element;
208
+ }
209
+ eq(other) {
210
+ return this.element === other.element;
211
+ }
212
+ toDOM() {
213
+ return this.element;
214
+ }
215
+ };
216
+ function CursorInlayHint({ children }) {
217
+ const injector = (0, import_react6.useInjector)();
218
+ const element = (0, import_react_hooks.useHTMLElement)("span");
219
+ (0, import_react5.useLayoutEffect)(
220
+ () => injector.inject([
221
+ import_view.EditorView.decorations.compute(
222
+ ["selection"],
223
+ (state) => import_view.Decoration.set([
224
+ import_view.Decoration.widget({
225
+ widget: new InlayHintWidget(element),
226
+ side: 1
227
+ }).range(state.selection.main.head)
228
+ ])
229
+ )
230
+ ]),
231
+ [injector]
232
+ );
233
+ return (0, import_react_dom.createPortal)(children, element);
234
+ }
235
+
236
+ // src/markers/markers.tsx
237
+ var import_react7 = require("react");
238
+ var import_react_hooks2 = require("@coze-editor/react-hooks");
239
+ var import_react8 = require("@coze-editor/react");
240
+ var import_extensions3 = require("@coze-editor/extensions");
241
+ function Markers({ markers }) {
242
+ const injector = (0, import_react8.useInjector)();
243
+ const field = (0, import_react_hooks2.useStateField)((0, import_react7.useCallback)(() => markers, [markers]));
244
+ (0, import_react7.useLayoutEffect)(
245
+ () => injector.inject([field, import_extensions3.mergeableMarkers.from(field)]),
246
+ [injector, field]
247
+ );
248
+ return null;
249
+ }
250
+
251
+ // src/markers/diagnostic-markers.tsx
252
+ var import_react9 = __toESM(require("react"));
253
+ var import_hash_sum = __toESM(require("hash-sum"));
254
+ var import_react10 = require("@coze-editor/react");
255
+ var import_view2 = require("@codemirror/view");
256
+ function DiagnosticMarkers({ markers }) {
257
+ const theme = (0, import_react9.useMemo)(() => {
258
+ const colors = getColors(markers);
259
+ return colors.reduce((memo, color) => {
260
+ const className = getClassNameFromColor(color);
261
+ memo[`& .${className}`] = {
262
+ backgroundPosition: "left bottom",
263
+ backgroundRepeat: "repeat-x",
264
+ paddingBottom: "0.7px",
265
+ backgroundImage: underline(color)
266
+ };
267
+ return memo;
268
+ }, {});
269
+ }, [markers]);
270
+ const injector = (0, import_react10.useInjector)();
271
+ (0, import_react9.useLayoutEffect)(
272
+ () => injector.inject([import_view2.EditorView.theme(theme)]),
273
+ [injector, theme]
274
+ );
275
+ const finalMarkers = (0, import_react9.useMemo)(
276
+ () => markers.map((marker) => {
277
+ const className = getClassNameFromColor(marker.color ?? "red");
278
+ return {
279
+ from: marker.from,
280
+ to: marker.to,
281
+ className
282
+ };
283
+ }),
284
+ [markers]
285
+ );
286
+ return /* @__PURE__ */ import_react9.default.createElement(Markers, { markers: finalMarkers });
287
+ }
288
+ var isString = (v) => Boolean(v);
289
+ function getColors(markers) {
290
+ return [
291
+ .../* @__PURE__ */ new Set([
292
+ ...markers.map((marker) => marker.color).filter((v) => isString(v)),
293
+ "red"
294
+ ])
295
+ ];
296
+ }
297
+ function getClassNameFromColor(color) {
298
+ return `cm-sdk-diagnostic-marker-${(0, import_hash_sum.default)(color)}`;
299
+ }
300
+ function svg(content, attrs) {
301
+ return `url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" ${attrs}>${encodeURIComponent(content)}</svg>')`;
302
+ }
303
+ function underline(color) {
304
+ return svg(
305
+ `<path d="m0 2.5 l2 -1.5 l1 0 l2 1.5 l1 0" stroke="${color}" fill="none" stroke-width=".7"/>`,
306
+ 'width="6" height="3"'
307
+ );
308
+ }
309
+
310
+ // src/gutter/gutter.tsx
311
+ var import_react_dom2 = require("react-dom");
312
+ var import_react11 = __toESM(require("react"));
313
+ var import_utils = require("jotai/utils");
314
+ var import_jotai2 = require("jotai");
315
+ var import_react_hooks3 = require("@coze-editor/react-hooks");
316
+ var import_react12 = require("@coze-editor/react");
317
+ var import_view4 = require("@codemirror/view");
318
+ var import_state3 = require("@codemirror/state");
319
+
320
+ // src/gutter/right-gutter.ts
321
+ var import_state = require("@codemirror/state");
322
+ var import_view3 = require("@codemirror/view");
323
+ var GutterMarker = class extends import_state.RangeValue {
324
+ /// @internal
325
+ compare(other) {
326
+ return this == other || this.constructor == other.constructor && this.eq(other);
327
+ }
328
+ /// Compare this marker to another marker of the same type.
329
+ eq(other) {
330
+ return false;
331
+ }
332
+ /// This property can be used to add CSS classes to the gutter
333
+ /// element that contains this marker.
334
+ elementClass;
335
+ /// Called if the marker has a `toDOM` method and its representation
336
+ /// was removed from a gutter.
337
+ destroy(dom) {
338
+ }
339
+ };
340
+ GutterMarker.prototype.elementClass = "";
341
+ GutterMarker.prototype.toDOM = void 0;
342
+ GutterMarker.prototype.mapMode = import_state.MapMode.TrackBefore;
343
+ GutterMarker.prototype.startSide = GutterMarker.prototype.endSide = -1;
344
+ GutterMarker.prototype.point = true;
345
+ var gutterLineClass = import_state.Facet.define();
346
+ var gutterWidgetClass = import_state.Facet.define();
347
+ var defaults = {
348
+ class: "",
349
+ renderEmptyElements: false,
350
+ elementStyle: "",
351
+ markers: () => import_state.RangeSet.empty,
352
+ lineMarker: () => null,
353
+ widgetMarker: () => null,
354
+ lineMarkerChange: null,
355
+ initialSpacer: null,
356
+ updateSpacer: null,
357
+ domEventHandlers: {}
358
+ };
359
+ var activeGutters = import_state.Facet.define();
360
+ function gutter(config) {
361
+ return [gutters(), activeGutters.of({ ...defaults, ...config })];
362
+ }
363
+ var unfixGutters = import_state.Facet.define({
364
+ combine: (values) => values.some((x) => x)
365
+ });
366
+ function gutters(config) {
367
+ const result = [
368
+ gutterView,
369
+ // right gutter theme
370
+ import_view3.EditorView.baseTheme({
371
+ ".cm-right-gutters": {
372
+ flexShrink: 0,
373
+ display: "flex",
374
+ height: "100%",
375
+ boxSizing: "border-box",
376
+ insetInlineStart: 0,
377
+ zIndex: 200
378
+ },
379
+ ".cm-right-gutter": {
380
+ display: "flex !important",
381
+ // Necessary -- prevents margin collapsing
382
+ flexDirection: "column",
383
+ flexShrink: 0,
384
+ boxSizing: "border-box",
385
+ minHeight: "100%",
386
+ overflow: "hidden"
387
+ },
388
+ ".cm-rightGutterElement": {
389
+ boxSizing: "border-box"
390
+ }
391
+ })
392
+ ];
393
+ if (config && config.fixed === false) result.push(unfixGutters.of(true));
394
+ return result;
395
+ }
396
+ var gutterView = import_view3.ViewPlugin.fromClass(class {
397
+ constructor(view) {
398
+ this.view = view;
399
+ this.prevViewport = view.viewport;
400
+ this.dom = document.createElement("div");
401
+ this.dom.className = "cm-right-gutters";
402
+ this.dom.setAttribute("aria-hidden", "true");
403
+ this.dom.style.minHeight = this.view.contentHeight / this.view.scaleY + "px";
404
+ this.gutters = view.state.facet(activeGutters).map((conf) => new SingleGutterView(view, conf));
405
+ for (const gutter2 of this.gutters) this.dom.appendChild(gutter2.dom);
406
+ this.fixed = !view.state.facet(unfixGutters);
407
+ if (this.fixed) {
408
+ this.dom.style.position = "sticky";
409
+ }
410
+ this.syncGutters(false);
411
+ view.scrollDOM.appendChild(this.dom);
412
+ }
413
+ gutters;
414
+ dom;
415
+ fixed;
416
+ prevViewport;
417
+ update(update) {
418
+ if (this.updateGutters(update)) {
419
+ const vpA = this.prevViewport, vpB = update.view.viewport;
420
+ const vpOverlap = Math.min(vpA.to, vpB.to) - Math.max(vpA.from, vpB.from);
421
+ this.syncGutters(vpOverlap < (vpB.to - vpB.from) * 0.8);
422
+ }
423
+ if (update.geometryChanged) {
424
+ this.dom.style.minHeight = this.view.contentHeight / this.view.scaleY + "px";
425
+ }
426
+ if (this.view.state.facet(unfixGutters) != !this.fixed) {
427
+ this.fixed = !this.fixed;
428
+ this.dom.style.position = this.fixed ? "sticky" : "";
429
+ }
430
+ this.prevViewport = update.view.viewport;
431
+ }
432
+ syncGutters(detach) {
433
+ const before = this.dom.previousSibling;
434
+ if (detach) this.dom.remove();
435
+ const lineClasses = import_state.RangeSet.iter(this.view.state.facet(gutterLineClass), this.view.viewport.from);
436
+ let classSet = [];
437
+ const contexts = this.gutters.map((gutter2) => new UpdateContext(gutter2, this.view.viewport, -this.view.documentPadding.top));
438
+ for (const line of this.view.viewportLineBlocks) {
439
+ if (classSet.length) classSet = [];
440
+ if (Array.isArray(line.type)) {
441
+ let first = true;
442
+ for (const b of line.type) {
443
+ if (b.type == import_view3.BlockType.Text && first) {
444
+ advanceCursor(lineClasses, classSet, b.from);
445
+ for (const cx of contexts) cx.line(this.view, b, classSet);
446
+ first = false;
447
+ } else if (b.widget) {
448
+ for (const cx of contexts) cx.widget(this.view, b);
449
+ }
450
+ }
451
+ } else if (line.type == import_view3.BlockType.Text) {
452
+ advanceCursor(lineClasses, classSet, line.from);
453
+ for (const cx of contexts) cx.line(this.view, line, classSet);
454
+ } else if (line.widget) {
455
+ for (const cx of contexts) cx.widget(this.view, line);
456
+ }
457
+ }
458
+ for (const cx of contexts) cx.finish();
459
+ if (detach) {
460
+ this.view.scrollDOM.insertBefore(this.dom, (before == null ? void 0 : before.nextSibling) ?? null);
461
+ }
462
+ }
463
+ updateGutters(update) {
464
+ const prev = update.startState.facet(activeGutters), cur = update.state.facet(activeGutters);
465
+ let change = update.docChanged || update.heightChanged || update.viewportChanged || !import_state.RangeSet.eq(
466
+ update.startState.facet(gutterLineClass),
467
+ update.state.facet(gutterLineClass),
468
+ update.view.viewport.from,
469
+ update.view.viewport.to
470
+ );
471
+ if (prev == cur) {
472
+ for (const gutter2 of this.gutters) if (gutter2.update(update)) change = true;
473
+ } else {
474
+ change = true;
475
+ const gutters2 = [];
476
+ for (const conf of cur) {
477
+ const known = prev.indexOf(conf);
478
+ if (known < 0) {
479
+ gutters2.push(new SingleGutterView(this.view, conf));
480
+ } else {
481
+ this.gutters[known].update(update);
482
+ gutters2.push(this.gutters[known]);
483
+ }
484
+ }
485
+ for (const g of this.gutters) {
486
+ g.dom.remove();
487
+ if (gutters2.indexOf(g) < 0) g.destroy();
488
+ }
489
+ for (const g of gutters2) this.dom.appendChild(g.dom);
490
+ this.gutters = gutters2;
491
+ }
492
+ return change;
493
+ }
494
+ destroy() {
495
+ for (const view of this.gutters) view.destroy();
496
+ this.dom.remove();
497
+ }
498
+ }, {
499
+ provide: (plugin) => import_view3.EditorView.scrollMargins.of((view) => {
500
+ const value = view.plugin(plugin);
501
+ if (!value || value.gutters.length == 0 || !value.fixed) return null;
502
+ return view.textDirection == import_view3.Direction.LTR ? { left: value.dom.offsetWidth * view.scaleX } : { right: value.dom.offsetWidth * view.scaleX };
503
+ })
504
+ });
505
+ function asArray(val) {
506
+ return Array.isArray(val) ? val : [val];
507
+ }
508
+ function advanceCursor(cursor, collect, pos) {
509
+ while (cursor.value && cursor.from <= pos) {
510
+ if (cursor.from == pos) collect.push(cursor.value);
511
+ cursor.next();
512
+ }
513
+ }
514
+ var UpdateContext = class {
515
+ constructor(gutter2, viewport, height) {
516
+ this.gutter = gutter2;
517
+ this.height = height;
518
+ this.cursor = import_state.RangeSet.iter(gutter2.markers, viewport.from);
519
+ }
520
+ cursor;
521
+ i = 0;
522
+ addElement(view, block, markers) {
523
+ const { gutter: gutter2 } = this, above = (block.top - this.height) / view.scaleY, height = block.height / view.scaleY;
524
+ if (this.i == gutter2.elements.length) {
525
+ const newElt = new GutterElement(view, height, above, markers);
526
+ gutter2.elements.push(newElt);
527
+ gutter2.dom.appendChild(newElt.dom);
528
+ } else {
529
+ gutter2.elements[this.i].update(view, height, above, markers);
530
+ }
531
+ this.height = block.bottom;
532
+ this.i++;
533
+ }
534
+ line(view, line, extraMarkers) {
535
+ let localMarkers = [];
536
+ advanceCursor(this.cursor, localMarkers, line.from);
537
+ if (extraMarkers.length) localMarkers = localMarkers.concat(extraMarkers);
538
+ const forLine = this.gutter.config.lineMarker(view, line, localMarkers);
539
+ if (forLine) localMarkers.unshift(forLine);
540
+ const gutter2 = this.gutter;
541
+ if (localMarkers.length == 0 && !gutter2.config.renderEmptyElements) return;
542
+ this.addElement(view, line, localMarkers);
543
+ }
544
+ widget(view, block) {
545
+ const marker = this.gutter.config.widgetMarker(view, block.widget, block);
546
+ let markers = marker ? [marker] : null;
547
+ for (const cls of view.state.facet(gutterWidgetClass)) {
548
+ const marker2 = cls(view, block.widget, block);
549
+ if (marker2) (markers || (markers = [])).push(marker2);
550
+ }
551
+ if (markers) this.addElement(view, block, markers);
552
+ }
553
+ finish() {
554
+ const gutter2 = this.gutter;
555
+ while (gutter2.elements.length > this.i) {
556
+ const last = gutter2.elements.pop();
557
+ gutter2.dom.removeChild(last.dom);
558
+ last.destroy();
559
+ }
560
+ }
561
+ };
562
+ var SingleGutterView = class {
563
+ constructor(view, config) {
564
+ this.view = view;
565
+ this.config = config;
566
+ this.dom = document.createElement("div");
567
+ this.dom.className = "cm-right-gutter" + (this.config.class ? " " + this.config.class : "");
568
+ for (const prop in config.domEventHandlers) {
569
+ this.dom.addEventListener(prop, (event) => {
570
+ let target = event.target, y;
571
+ if (target != this.dom && this.dom.contains(target)) {
572
+ while (target.parentNode != this.dom) target = target.parentNode;
573
+ const rect = target.getBoundingClientRect();
574
+ y = (rect.top + rect.bottom) / 2;
575
+ } else {
576
+ y = event.clientY;
577
+ }
578
+ const line = view.lineBlockAtHeight(y - view.documentTop);
579
+ if (config.domEventHandlers[prop](view, line, event)) event.preventDefault();
580
+ });
581
+ }
582
+ this.markers = asArray(config.markers(view));
583
+ if (config.initialSpacer) {
584
+ this.spacer = new GutterElement(view, 0, 0, [config.initialSpacer(view)]);
585
+ this.dom.appendChild(this.spacer.dom);
586
+ this.spacer.dom.style.cssText += "visibility: hidden; pointer-events: none";
587
+ }
588
+ }
589
+ dom;
590
+ elements = [];
591
+ markers;
592
+ spacer = null;
593
+ update(update) {
594
+ const prevMarkers = this.markers;
595
+ this.markers = asArray(this.config.markers(update.view));
596
+ if (this.spacer && this.config.updateSpacer) {
597
+ const updated = this.config.updateSpacer(this.spacer.markers[0], update);
598
+ if (updated != this.spacer.markers[0]) this.spacer.update(update.view, 0, 0, [updated]);
599
+ }
600
+ const vp = update.view.viewport;
601
+ return !import_state.RangeSet.eq(this.markers, prevMarkers, vp.from, vp.to) || (this.config.lineMarkerChange ? this.config.lineMarkerChange(update) : false);
602
+ }
603
+ destroy() {
604
+ for (const elt of this.elements) elt.destroy();
605
+ }
606
+ };
607
+ var GutterElement = class {
608
+ dom;
609
+ height = -1;
610
+ above = 0;
611
+ markers = [];
612
+ constructor(view, height, above, markers) {
613
+ this.dom = document.createElement("div");
614
+ this.dom.className = "cm-rightGutterElement";
615
+ this.update(view, height, above, markers);
616
+ }
617
+ update(view, height, above, markers) {
618
+ if (this.height != height) {
619
+ this.height = height;
620
+ this.dom.style.height = height + "px";
621
+ }
622
+ if (this.above != above)
623
+ this.dom.style.marginTop = (this.above = above) ? above + "px" : "";
624
+ if (!sameMarkers(this.markers, markers)) this.setMarkers(view, markers);
625
+ }
626
+ setMarkers(view, markers) {
627
+ let cls = "cm-rightGutterElement", domPos = this.dom.firstChild;
628
+ for (let iNew = 0, iOld = 0; ; ) {
629
+ let skipTo = iOld, marker = iNew < markers.length ? markers[iNew++] : null, matched = false;
630
+ if (marker) {
631
+ const c = marker.elementClass;
632
+ if (c) cls += " " + c;
633
+ for (let i = iOld; i < this.markers.length; i++)
634
+ if (this.markers[i].compare(marker)) {
635
+ skipTo = i;
636
+ matched = true;
637
+ break;
638
+ }
639
+ } else {
640
+ skipTo = this.markers.length;
641
+ }
642
+ while (iOld < skipTo) {
643
+ const next = this.markers[iOld++];
644
+ if (next.toDOM) {
645
+ next.destroy(domPos);
646
+ const after = domPos.nextSibling;
647
+ domPos.remove();
648
+ domPos = after;
649
+ }
650
+ }
651
+ if (!marker) break;
652
+ if (marker.toDOM) {
653
+ if (matched) domPos = domPos.nextSibling;
654
+ else this.dom.insertBefore(marker.toDOM(view), domPos);
655
+ }
656
+ if (matched) iOld++;
657
+ }
658
+ this.dom.className = cls;
659
+ this.markers = markers;
660
+ }
661
+ destroy() {
662
+ this.setMarkers(null, []);
663
+ }
664
+ };
665
+ function sameMarkers(a, b) {
666
+ if (a.length != b.length) return false;
667
+ for (let i = 0; i < a.length; i++) if (!a[i].compare(b[i])) return false;
668
+ return true;
669
+ }
670
+ var activeLineGutterMarker = new class extends GutterMarker {
671
+ elementClass = "cm-activeLineRightGutter";
672
+ }();
673
+ var activeLineGutterHighlighter = gutterLineClass.compute(["selection"], (state) => {
674
+ const marks = [];
675
+ let last = -1;
676
+ for (const range of state.selection.ranges) {
677
+ const linePos = state.doc.lineAt(range.head).from;
678
+ if (linePos > last) {
679
+ last = linePos;
680
+ marks.push(activeLineGutterMarker.range(linePos));
681
+ }
682
+ }
683
+ return import_state.RangeSet.of(marks);
684
+ });
685
+
686
+ // src/gutter/atoms.ts
687
+ var import_jotai = require("jotai");
688
+ var import_state2 = require("@codemirror/state");
689
+ var facetAtom = (0, import_jotai.atom)(import_state2.Facet.define());
690
+
691
+ // src/gutter/gutter.tsx
692
+ var DOMGutterLineMarker = class extends GutterMarker {
693
+ constructor(dom) {
694
+ super();
695
+ this.dom = dom;
696
+ }
697
+ eq(other) {
698
+ return this.dom === other.dom;
699
+ }
700
+ toDOM() {
701
+ return this.dom;
702
+ }
703
+ };
704
+ function HydrateAtoms({ markers, children }) {
705
+ (0, import_utils.useHydrateAtoms)([[facetAtom, markers]]);
706
+ return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, children);
707
+ }
708
+ var GutterPlacement = /* @__PURE__ */ ((GutterPlacement2) => {
709
+ GutterPlacement2["Left"] = "left";
710
+ GutterPlacement2["Right"] = "right";
711
+ return GutterPlacement2;
712
+ })(GutterPlacement || {});
713
+ function Gutter({
714
+ defaultClassName,
715
+ placement = "left" /* Left */,
716
+ children
717
+ }) {
718
+ const [markersFacet] = (0, import_react11.useState)(
719
+ () => import_state3.Facet.define()
720
+ );
721
+ (0, import_react_hooks3.useInjectorEffect)(
722
+ (injector) => {
723
+ const gutter2 = placement === "right" /* Right */ ? gutter : import_view4.gutter;
724
+ return injector.inject([
725
+ gutter2({
726
+ class: defaultClassName ?? "",
727
+ markers(view) {
728
+ const specs = view.state.facet(markersFacet);
729
+ const { lines } = view.state.doc;
730
+ let markers = import_state3.RangeSet.empty;
731
+ for (const spec of specs) {
732
+ const { lineNumber } = spec;
733
+ if (lineNumber < 1 || lineNumber > lines) {
734
+ continue;
735
+ }
736
+ const line = view.state.doc.line(spec.lineNumber);
737
+ markers = markers.update({
738
+ add: [new DOMGutterLineMarker(spec.dom).range(line.from)],
739
+ sort: true
740
+ });
741
+ }
742
+ return markers;
743
+ }
744
+ })
745
+ ]);
746
+ },
747
+ [placement]
748
+ );
749
+ return /* @__PURE__ */ import_react11.default.createElement(import_jotai2.Provider, null, /* @__PURE__ */ import_react11.default.createElement(HydrateAtoms, { markers: markersFacet }, children));
750
+ }
751
+ function GutterLineMarker({
752
+ lineNumber,
753
+ children
754
+ }) {
755
+ const facet = (0, import_jotai2.useAtomValue)(facetAtom);
756
+ const editor = (0, import_react12.useEditor)();
757
+ const compartment = (0, import_react_hooks3.useCompartment)();
758
+ const elementRef = (0, import_react_hooks3.useLatest)((0, import_react_hooks3.useHTMLElement)());
759
+ (0, import_react_hooks3.useInjectorEffect)((injector) => injector.inject([compartment.of([])]), []);
760
+ (0, import_react11.useEffect)(() => {
761
+ if (!editor) {
762
+ return;
763
+ }
764
+ editor.$view.dispatch({
765
+ effects: compartment.reconfigure(
766
+ facet.of({
767
+ lineNumber,
768
+ dom: elementRef.current
769
+ })
770
+ )
771
+ });
772
+ }, [editor, compartment, lineNumber]);
773
+ return (0, import_react_dom2.createPortal)(children, elementRef.current);
774
+ }
775
+
776
+ // src/fold-gutter/index.tsx
777
+ var import_react_dom3 = require("react-dom");
778
+ var import_react13 = __toESM(require("react"));
779
+ var import_uuid = require("@lukeed/uuid");
780
+ var import_utils2 = require("@coze-editor/utils");
781
+ var import_react_hooks4 = require("@coze-editor/react-hooks");
782
+ var import_react14 = require("@coze-editor/react");
783
+ var import_view5 = require("@codemirror/view");
784
+ var import_state4 = require("@codemirror/state");
785
+ var import_language = require("@codemirror/language");
786
+ function FluentTriangleDown12Filled(props) {
787
+ return /* @__PURE__ */ import_react13.default.createElement(
788
+ "svg",
789
+ {
790
+ xmlns: "http://www.w3.org/2000/svg",
791
+ width: "8px",
792
+ height: "8px",
793
+ viewBox: "0 0 12 12",
794
+ ...props
795
+ },
796
+ /* @__PURE__ */ import_react13.default.createElement(
797
+ "path",
798
+ {
799
+ fill: "currentColor",
800
+ d: "M5.214 10.541a.903.903 0 0 0 1.572 0l4.092-7.169C11.226 2.762 10.789 2 10.09 2H1.91c-.698 0-1.135.762-.787 1.372z"
801
+ }
802
+ )
803
+ );
804
+ }
805
+ function FluentTriangleRight12Filled(props) {
806
+ return /* @__PURE__ */ import_react13.default.createElement(
807
+ "svg",
808
+ {
809
+ xmlns: "http://www.w3.org/2000/svg",
810
+ width: "8px",
811
+ height: "8px",
812
+ viewBox: "0 0 12 12",
813
+ ...props
814
+ },
815
+ /* @__PURE__ */ import_react13.default.createElement(
816
+ "path",
817
+ {
818
+ fill: "currentColor",
819
+ d: "M10.541 6.786a.903.903 0 0 0 0-1.572L3.372 1.122C2.762.774 2 1.211 2 1.91v8.182c0 .698.762 1.135 1.372.787z"
820
+ }
821
+ )
822
+ );
823
+ }
824
+ function defaultRenderMarker(open) {
825
+ return open ? /* @__PURE__ */ import_react13.default.createElement(FluentTriangleDown12Filled, null) : /* @__PURE__ */ import_react13.default.createElement(FluentTriangleRight12Filled, null);
826
+ }
827
+ function defaultRenderPlaceholder() {
828
+ return null;
829
+ }
830
+ function FoldGutter({
831
+ renderMarker = defaultRenderMarker,
832
+ renderPlaceholder = defaultRenderPlaceholder,
833
+ opacityTransition = false,
834
+ opacityTransitionDuration = 300
835
+ }) {
836
+ const connector = (0, import_react_hooks4.usePortalConnector)({ sync: true });
837
+ const connectorRef = (0, import_react_hooks4.useLatest)(connector);
838
+ const renderMarkerRef = (0, import_react_hooks4.useLatest)(renderMarker);
839
+ const renderPlaceholderRef = (0, import_react_hooks4.useLatest)(renderPlaceholder);
840
+ const [opacity, setOpacity] = (0, import_react13.useState)(0);
841
+ const setOpacityRef = (0, import_react_hooks4.useLatest)(setOpacity);
842
+ const injector = (0, import_react14.useInjector)();
843
+ const { Portal } = connector;
844
+ (0, import_react13.useEffect)(() => {
845
+ if (!opacityTransition || !opacityTransitionDuration) {
846
+ return;
847
+ }
848
+ return injector.inject([
849
+ import_view5.EditorView.theme({
850
+ ".cm-foldGutter": {
851
+ transition: `opacity ${opacityTransitionDuration / 1e3}s ease`
852
+ }
853
+ })
854
+ ]);
855
+ }, [injector, opacityTransition, opacityTransitionDuration]);
856
+ (0, import_react_hooks4.useInjectorEffect)(
857
+ (injector2) => {
858
+ if (!opacityTransition) {
859
+ return;
860
+ }
861
+ return injector2.inject([
862
+ import_state4.Prec.lowest(
863
+ import_view5.EditorView.theme({
864
+ ".cm-foldGutter": {
865
+ opacity
866
+ }
867
+ })
868
+ )
869
+ ]);
870
+ },
871
+ [opacityTransition, opacity]
872
+ );
873
+ (0, import_react_hooks4.useInjectorEffect)((injector2) => {
874
+ const disposes = [];
875
+ return (0, import_utils2.disposeAll)([
876
+ injector2.inject([
877
+ import_state4.Prec.low(
878
+ import_view5.EditorView.theme({
879
+ ".cm-foldGutter .cm-gutterElement": {
880
+ display: "flex",
881
+ alignItems: "center",
882
+ cursor: "pointer"
883
+ }
884
+ })
885
+ ),
886
+ (0, import_language.foldGutter)({
887
+ markerDOM(open) {
888
+ const dom = document.createElement("span");
889
+ dom.setAttribute("aria-expanded", open ? "true" : "false");
890
+ const id = (0, import_uuid.v4)();
891
+ connectorRef.current.connect(
892
+ id,
893
+ (0, import_react_dom3.createPortal)(renderMarkerRef.current(open), dom)
894
+ );
895
+ disposes.push(() => {
896
+ connectorRef.current.disconnect(id);
897
+ });
898
+ return dom;
899
+ },
900
+ domEventHandlers: {
901
+ mouseenter() {
902
+ setOpacityRef.current(1);
903
+ return true;
904
+ },
905
+ mouseleave() {
906
+ setOpacityRef.current(0);
907
+ return true;
908
+ }
909
+ }
910
+ }),
911
+ (0, import_language.codeFolding)({
912
+ placeholderDOM(view, onclick) {
913
+ const dom = document.createElement("span");
914
+ const id = (0, import_uuid.v4)();
915
+ connectorRef.current.connect(
916
+ id,
917
+ (0, import_react_dom3.createPortal)(renderPlaceholderRef.current(), dom)
918
+ );
919
+ disposes.push(() => {
920
+ connectorRef.current.disconnect(id);
921
+ });
922
+ dom.addEventListener("click", onclick, false);
923
+ disposes.push(() => {
924
+ dom.removeEventListener("click", onclick, false);
925
+ });
926
+ return dom;
927
+ }
928
+ })
929
+ ]),
930
+ ...disposes
931
+ ]);
932
+ }, []);
933
+ return /* @__PURE__ */ import_react13.default.createElement(Portal, null);
934
+ }
935
+
936
+ // src/placeholder/index.tsx
937
+ var import_react_dom4 = require("react-dom");
938
+ var import_react_hooks5 = require("@coze-editor/react-hooks");
939
+ var import_extension_placeholder = require("@coze-editor/extension-placeholder");
940
+ function Placeholder({ children }) {
941
+ const element = (0, import_react_hooks5.useHTMLElement)("span");
942
+ (0, import_react_hooks5.useInjectorEffect)(
943
+ (injector) => injector.inject([(0, import_extension_placeholder.placeholder)(() => element)]),
944
+ []
945
+ );
946
+ return (0, import_react_dom4.createPortal)(children, element);
947
+ }
948
+ function ActiveLinePlaceholder({
949
+ children
950
+ }) {
951
+ const element = (0, import_react_hooks5.useHTMLElement)("span");
952
+ (0, import_react_hooks5.useInjectorEffect)(
953
+ (injector) => injector.inject([(0, import_extension_placeholder.activeLinePlaceholder)(() => element)]),
954
+ []
955
+ );
956
+ return (0, import_react_dom4.createPortal)(children, element);
957
+ }
958
+
959
+ // src/ref-element/index.tsx
960
+ var import_react15 = require("react");
961
+ var import_react_hooks6 = require("@coze-editor/react-hooks");
962
+ var RefElement = (0, import_react15.forwardRef)(({ element }, ref) => {
963
+ const domRef = (0, import_react_hooks6.useLatest)(element);
964
+ (0, import_react15.useImperativeHandle)(ref, () => domRef.current);
965
+ return null;
966
+ });
967
+ RefElement.displayName = "RefElement";
968
+
969
+ // src/line-widget/index.tsx
970
+ var import_react_dom5 = require("react-dom");
971
+ var import_react16 = require("react");
972
+ var import_react_hooks7 = require("@coze-editor/react-hooks");
973
+ var import_react17 = require("@coze-editor/react");
974
+
975
+ // src/line-widget/cursor-widget/state.ts
976
+ var import_view7 = require("@codemirror/view");
977
+ var import_state5 = require("@codemirror/state");
978
+
979
+ // src/line-widget/cursor-widget/widget-decoration.ts
980
+ var import_view6 = require("@codemirror/view");
981
+ var CustomDivWidget = class extends import_view6.WidgetType {
982
+ customDOM;
983
+ constructor(customDOM) {
984
+ super();
985
+ this.customDOM = customDOM;
986
+ }
987
+ toDOM() {
988
+ const div = document.createElement("div");
989
+ div.className = "cursor-widget-wrapper";
990
+ div.setAttribute("style", "caret-color: initial;");
991
+ if (this.customDOM) {
992
+ div.appendChild(this.customDOM);
993
+ }
994
+ return div;
995
+ }
996
+ eq(widget) {
997
+ return widget.customDOM === this.customDOM;
998
+ }
999
+ };
1000
+ var createBlockWidget = (config, pos) => {
1001
+ if (typeof pos !== "number") {
1002
+ return import_view6.Decoration.none;
1003
+ }
1004
+ return import_view6.Decoration.set(
1005
+ import_view6.Decoration.widget({
1006
+ widget: new CustomDivWidget(config.createDOM()),
1007
+ side: config.side,
1008
+ block: true,
1009
+ config
1010
+ }).range(pos)
1011
+ );
1012
+ };
1013
+
1014
+ // src/line-widget/cursor-widget/state.ts
1015
+ var setWidgetEffect = import_state5.StateEffect.define();
1016
+ var getPos = (state, num) => state.doc.line(num).from;
1017
+ var cursorWidgetState = (facet) => import_state5.StateField.define({
1018
+ create(state) {
1019
+ return createBlockWidget(
1020
+ facet.config,
1021
+ typeof facet.config.lineNumber === "number" ? getPos(state, facet.config.lineNumber) : void 0
1022
+ );
1023
+ },
1024
+ update(widget, tr) {
1025
+ tr.effects.forEach((effect) => {
1026
+ if (effect.is(setWidgetEffect) && effect.value.id === facet.id) {
1027
+ widget = createBlockWidget(
1028
+ {
1029
+ ...facet.config,
1030
+ side: effect.value.side,
1031
+ lineNumber: effect.value.lineNumber
1032
+ },
1033
+ typeof effect.value.lineNumber === "number" ? getPos(tr.state, effect.value.lineNumber) : void 0
1034
+ );
1035
+ }
1036
+ });
1037
+ return widget.update({
1038
+ filter: (from, to) => 0 <= from && to <= tr.state.doc.length
1039
+ });
1040
+ },
1041
+ provide: (f) => import_view7.EditorView.decorations.from(f)
1042
+ });
1043
+ var setWidgetLineNumber = (id, lineNumber, side) => ({
1044
+ effects: [setWidgetEffect.of({ lineNumber, id, side })]
1045
+ });
1046
+
1047
+ // src/line-widget/cursor-widget/common.ts
1048
+ var nextID = 1;
1049
+ var ConfigFacet = class {
1050
+ constructor(config) {
1051
+ this.config = config;
1052
+ }
1053
+ id = nextID++;
1054
+ };
1055
+
1056
+ // src/line-widget/cursor-widget/index.ts
1057
+ var cursorBlockWidget = (config) => {
1058
+ const facet = new ConfigFacet(config);
1059
+ return {
1060
+ setWidgetLineNumber: (lineNumber, side) => setWidgetLineNumber(facet.id, lineNumber, side),
1061
+ extension: [cursorWidgetState(facet)]
1062
+ };
1063
+ };
1064
+
1065
+ // src/line-widget/index.tsx
1066
+ function LineWidget({ children, lineNumber, side }) {
1067
+ const setWidgetLineNumberRef = (0, import_react16.useRef)(null);
1068
+ const injector = (0, import_react17.useInjector)();
1069
+ const editor = (0, import_react17.useEditor)();
1070
+ (0, import_react16.useEffect)(() => {
1071
+ var _a;
1072
+ if (setWidgetLineNumberRef.current && (editor == null ? void 0 : editor.$view)) {
1073
+ (_a = editor.$view) == null ? void 0 : _a.dispatch(setWidgetLineNumberRef.current(lineNumber, side));
1074
+ }
1075
+ }, [lineNumber, side]);
1076
+ const element = (0, import_react_hooks7.useHTMLElement)("span");
1077
+ (0, import_react16.useLayoutEffect)(() => {
1078
+ const { extension, setWidgetLineNumber: setWidgetLineNumber2 } = cursorBlockWidget({
1079
+ side,
1080
+ lineNumber,
1081
+ createDOM: () => element
1082
+ });
1083
+ setWidgetLineNumberRef.current = setWidgetLineNumber2;
1084
+ return injector.inject(extension);
1085
+ }, [injector]);
1086
+ return (0, import_react_dom5.createPortal)(children, element);
1087
+ }
1088
+
1089
+ // src/diff-view/index.tsx
1090
+ var import_react18 = require("react");
1091
+ var import_react19 = require("@coze-editor/react");
1092
+
1093
+ // src/diff-view/extension.ts
1094
+ var import_view8 = require("@codemirror/view");
1095
+ var import_state7 = require("@codemirror/state");
1096
+ var import_merge = require("@codemirror/merge");
1097
+ var diffView = (props) => {
1098
+ const { original = "" } = props;
1099
+ return [
1100
+ (0, import_merge.unifiedMergeView)({
1101
+ original,
1102
+ gutter: false
1103
+ }),
1104
+ import_state7.EditorState.phrases.of({
1105
+ Accept: "^Y",
1106
+ Reject: "^N"
1107
+ }),
1108
+ import_view8.EditorView.theme({
1109
+ ".cm-deletedChunk": {
1110
+ paddingLeft: "2px",
1111
+ backgroundColor: "rgba(220, 68, 50, 0.2)"
1112
+ },
1113
+ ".cm-deletedChunk .cm-chunkButtons": {
1114
+ position: "static",
1115
+ display: "flex"
1116
+ },
1117
+ ".cm-deletedChunk .cm-chunkButtons button": {
1118
+ flex: "1",
1119
+ margin: "0px"
1120
+ },
1121
+ ".cm-deletedChunk .cm-chunkButtons button:first-child": {
1122
+ marginRight: "2px"
1123
+ },
1124
+ ".cm-deletedChunk del": {
1125
+ textDecoration: "none",
1126
+ backgroundColor: "rgba(220, 68, 50, 0.4)"
1127
+ },
1128
+ "&.cm-merge-b .cm-changedLine": {
1129
+ backgroundColor: "rgba(33, 170, 33, 0.2)"
1130
+ },
1131
+ ".cm-insertedLine .cm-changedText": {
1132
+ background: "none",
1133
+ backgroundColor: "rgba(33, 170, 33, 0.4)"
1134
+ }
1135
+ })
1136
+ ];
1137
+ };
1138
+
1139
+ // src/diff-view/index.tsx
1140
+ function DiffView({ original }) {
1141
+ const injector = (0, import_react19.useInjector)();
1142
+ (0, import_react18.useLayoutEffect)(() => injector.inject(diffView({ original })), []);
1143
+ return null;
1144
+ }
1145
+
1146
+ // src/mention/extension.ts
1147
+ var import_utils3 = require("@coze-editor/utils");
1148
+ var import_state8 = require("@codemirror/state");
1149
+
1150
+ // src/mention/is.ts
1151
+ function hasTriggerCharacters(options) {
1152
+ return Array.isArray(options.triggerCharacters);
1153
+ }
1154
+ function hasTrigger(options) {
1155
+ return typeof options.trigger === "function";
1156
+ }
1157
+
1158
+ // src/mention/extension.ts
1159
+ var validForReg = /^[\u4e00-\u9fa5a-zA-Z0-9_']*$/;
1160
+ function defaultValidFor(text) {
1161
+ return validForReg.test(text);
1162
+ }
1163
+ var fields = import_state8.Facet.define();
1164
+ function mention(options) {
1165
+ const mentionConfig = import_state8.Facet.define({
1166
+ combine: import_utils3.FacetCombineStrategy.Last
1167
+ });
1168
+ const field = import_state8.StateField.define({
1169
+ create() {
1170
+ return {
1171
+ show: false,
1172
+ triggerContext: void 0
1173
+ };
1174
+ },
1175
+ update(value, tr) {
1176
+ const options2 = tr.startState.facet(mentionConfig);
1177
+ const { search = true, onOpenChange, onSearch } = options2;
1178
+ let { show } = value;
1179
+ let triggerContext = void 0;
1180
+ if (tr.docChanged) {
1181
+ if (hasTriggerCharacters(options2)) {
1182
+ tr.changes.iterChanges((fromA, toA, fromB, toB, inserted) => {
1183
+ const insertString = inserted.toString();
1184
+ if (fromA === toA && options2.triggerCharacters.includes(insertString)) {
1185
+ triggerContext = {
1186
+ from: fromB,
1187
+ to: toB,
1188
+ triggerCharacter: insertString,
1189
+ cursorPosition: tr.state.selection.main.head
1190
+ };
1191
+ }
1192
+ });
1193
+ } else if (hasTrigger(options2)) {
1194
+ triggerContext = options2.trigger(tr);
1195
+ }
1196
+ }
1197
+ const isSelectUserEvent = tr.isUserEvent("select");
1198
+ const newValue = {
1199
+ show: value.show,
1200
+ triggerContext: value.triggerContext ? { ...value.triggerContext } : void 0
1201
+ };
1202
+ if (triggerContext) {
1203
+ newValue.triggerContext = triggerContext;
1204
+ show = true;
1205
+ if (typeof onSearch === "function") {
1206
+ onSearch({
1207
+ value: ""
1208
+ });
1209
+ }
1210
+ } else if (tr.docChanged && value.triggerContext && search) {
1211
+ if (newValue.triggerContext) {
1212
+ const newFrom = tr.changes.mapPos(
1213
+ value.triggerContext.from,
1214
+ 1,
1215
+ import_state8.MapMode.TrackAfter
1216
+ );
1217
+ const newTo = tr.changes.mapPos(
1218
+ value.triggerContext.to,
1219
+ 1,
1220
+ import_state8.MapMode.Simple
1221
+ );
1222
+ if (typeof newFrom === "number" && typeof newTo === "number") {
1223
+ newValue.triggerContext.from = newFrom;
1224
+ newValue.triggerContext.to = newTo;
1225
+ } else {
1226
+ show = false;
1227
+ }
1228
+ }
1229
+ if (show === true) {
1230
+ const validFor = typeof search === "object" ? search.validFor : defaultValidFor;
1231
+ const from = value.triggerContext.cursorPosition;
1232
+ const to = tr.state.selection.main.head;
1233
+ if (to >= from) {
1234
+ const text = tr.state.sliceDoc(from, to);
1235
+ if (validFor(text, from, to, tr.state)) {
1236
+ show = true;
1237
+ if (typeof onSearch === "function") {
1238
+ onSearch({
1239
+ value: text
1240
+ });
1241
+ }
1242
+ } else {
1243
+ show = false;
1244
+ }
1245
+ } else {
1246
+ show = false;
1247
+ }
1248
+ }
1249
+ } else if (isSelectUserEvent) {
1250
+ show = false;
1251
+ }
1252
+ if (show === false) {
1253
+ newValue.triggerContext = void 0;
1254
+ }
1255
+ if (show !== value.show) {
1256
+ newValue.show = show;
1257
+ if (typeof onOpenChange === "function") {
1258
+ onOpenChange({
1259
+ value: show,
1260
+ state: tr.state,
1261
+ triggerContext: newValue.triggerContext ? {
1262
+ from: newValue.triggerContext.from,
1263
+ to: newValue.triggerContext.to,
1264
+ triggerCharacter: newValue.triggerContext.triggerCharacter
1265
+ } : void 0
1266
+ });
1267
+ }
1268
+ }
1269
+ return newValue;
1270
+ }
1271
+ });
1272
+ return [mentionConfig.of(options), field, fields.of(field)];
1273
+ }
1274
+ function getCurrentMentionReplaceRange(state) {
1275
+ const allFields = state.facet(fields);
1276
+ for (const field of allFields) {
1277
+ const fieldState = state.field(field, false);
1278
+ if (fieldState && fieldState.triggerContext && typeof fieldState.triggerContext.from === "number" && typeof fieldState.triggerContext.to === "number") {
1279
+ return {
1280
+ from: fieldState.triggerContext.from,
1281
+ to: fieldState.triggerContext.to
1282
+ };
1283
+ }
1284
+ }
1285
+ }
1286
+
1287
+ // src/mention/react.tsx
1288
+ var import_react_hooks8 = require("@coze-editor/react-hooks");
1289
+ function Mention(props) {
1290
+ const propsRef = (0, import_react_hooks8.useLatest)(props);
1291
+ (0, import_react_hooks8.useInjectorEffect)((injector) => {
1292
+ const sharedOptions = {
1293
+ search: props.search,
1294
+ onOpenChange(...args) {
1295
+ if (typeof propsRef.current.onOpenChange === "function") {
1296
+ return propsRef.current.onOpenChange(...args);
1297
+ }
1298
+ },
1299
+ onSearch(...args) {
1300
+ if (typeof propsRef.current.onSearch === "function") {
1301
+ return propsRef.current.onSearch(...args);
1302
+ }
1303
+ }
1304
+ };
1305
+ return injector.inject([
1306
+ mention(
1307
+ hasTrigger(props) ? {
1308
+ ...sharedOptions,
1309
+ trigger(tr) {
1310
+ if (hasTrigger(propsRef.current)) {
1311
+ return propsRef.current.trigger(tr);
1312
+ }
1313
+ }
1314
+ } : {
1315
+ ...sharedOptions,
1316
+ triggerCharacters: props.triggerCharacters ?? []
1317
+ }
1318
+ )
1319
+ ]);
1320
+ });
1321
+ return null;
1322
+ }
1323
+
1324
+ // src/embeded-line-view/react.tsx
1325
+ var import_react_dom6 = require("react-dom");
1326
+ var import_react21 = require("react");
1327
+ var import_react_hooks9 = require("@coze-editor/react-hooks");
1328
+ var import_react22 = require("@coze-editor/react");
1329
+ var import_view9 = require("@codemirror/view");
1330
+ var import_state9 = require("@codemirror/state");
1331
+ var DOMWidget = class extends import_view9.WidgetType {
1332
+ constructor(options) {
1333
+ super();
1334
+ this.options = options;
1335
+ }
1336
+ toDOM() {
1337
+ return this.options.dom;
1338
+ }
1339
+ eq(other) {
1340
+ return this.options.dom === other.options.dom;
1341
+ }
1342
+ };
1343
+ var EmbededLineViewSide = /* @__PURE__ */ ((EmbededLineViewSide2) => {
1344
+ EmbededLineViewSide2["Before"] = "before";
1345
+ EmbededLineViewSide2["After"] = "after";
1346
+ return EmbededLineViewSide2;
1347
+ })(EmbededLineViewSide || {});
1348
+ var updateEffect = import_state9.StateEffect.define();
1349
+ var EmbededLineView = (0, import_react21.forwardRef)(function EmbededLineView2({ children }, ref) {
1350
+ const dom = (0, import_react_hooks9.useHTMLElement)("div");
1351
+ const domRef = (0, import_react_hooks9.useLatest)(dom);
1352
+ const editor = (0, import_react22.useEditor)();
1353
+ const editorRef = (0, import_react_hooks9.useLatest)(editor);
1354
+ (0, import_react21.useImperativeHandle)(ref, () => ({
1355
+ update({ visible, line, side }) {
1356
+ var _a;
1357
+ (_a = editorRef.current) == null ? void 0 : _a.$view.dispatch({
1358
+ effects: updateEffect.of({
1359
+ visible,
1360
+ line: line ?? 1,
1361
+ side: side ?? "before" /* Before */
1362
+ })
1363
+ });
1364
+ }
1365
+ }));
1366
+ (0, import_react_hooks9.useInjectorEffect)((injector) => {
1367
+ const field = import_state9.StateField.define({
1368
+ create() {
1369
+ return {
1370
+ position: 0,
1371
+ side: "before" /* Before */,
1372
+ decorations: import_view9.Decoration.none
1373
+ };
1374
+ },
1375
+ update(value, tr) {
1376
+ const newPosition = tr.changes.mapPos(
1377
+ value.position,
1378
+ -1,
1379
+ import_state9.MapMode.Simple
1380
+ );
1381
+ let newValue = value;
1382
+ if (typeof newPosition === "number" && newPosition !== value.position) {
1383
+ const docLine = tr.state.doc.lineAt(newPosition);
1384
+ let decoPos = 0;
1385
+ if (value.side === "after" /* After */) {
1386
+ decoPos = docLine.to;
1387
+ } else {
1388
+ decoPos = docLine.from;
1389
+ }
1390
+ newValue = {
1391
+ ...value,
1392
+ position: newPosition,
1393
+ decorations: import_view9.Decoration.set([
1394
+ import_view9.Decoration.widget({
1395
+ widget: new DOMWidget({
1396
+ dom: domRef.current
1397
+ }),
1398
+ block: true,
1399
+ side: value.side === "after" /* After */ ? 1 : -1
1400
+ }).range(decoPos)
1401
+ ])
1402
+ };
1403
+ }
1404
+ for (const effect of tr.effects) {
1405
+ if (effect.is(updateEffect)) {
1406
+ const { visible, line, side } = effect.value;
1407
+ if (!visible) {
1408
+ return {
1409
+ position: newValue.position,
1410
+ side,
1411
+ decorations: import_view9.Decoration.none
1412
+ };
1413
+ }
1414
+ if (line < 1 || line > tr.startState.doc.lines) {
1415
+ continue;
1416
+ }
1417
+ const docLine = tr.startState.doc.line(line);
1418
+ let decoPos = 0;
1419
+ if (side === "after" /* After */) {
1420
+ decoPos = docLine.to;
1421
+ } else {
1422
+ decoPos = docLine.from;
1423
+ }
1424
+ return {
1425
+ position: decoPos,
1426
+ side,
1427
+ decorations: import_view9.Decoration.set([
1428
+ import_view9.Decoration.widget({
1429
+ widget: new DOMWidget({
1430
+ dom: domRef.current
1431
+ }),
1432
+ block: true,
1433
+ side: newValue.side === "after" /* After */ ? 1 : -1
1434
+ }).range(decoPos)
1435
+ ])
1436
+ };
1437
+ }
1438
+ }
1439
+ return newValue;
1440
+ },
1441
+ provide(f) {
1442
+ return import_view9.EditorView.decorations.compute(
1443
+ [f],
1444
+ (state) => state.field(f).decorations
1445
+ );
1446
+ }
1447
+ });
1448
+ return injector.inject([field]);
1449
+ }, []);
1450
+ return (0, import_react_dom6.createPortal)(children, dom);
1451
+ });
1452
+ // Annotate the CommonJS export names for ESM import in node:
1453
+ 0 && (module.exports = {
1454
+ ActiveLinePlaceholder,
1455
+ CursorInlayHint,
1456
+ CursorMirror,
1457
+ DiagnosticMarkers,
1458
+ DiffView,
1459
+ EmbededLineView,
1460
+ EmbededLineViewSide,
1461
+ FoldGutter,
1462
+ Gutter,
1463
+ GutterLineMarker,
1464
+ GutterPlacement,
1465
+ LineWidget,
1466
+ Markers,
1467
+ Mention,
1468
+ Placeholder,
1469
+ PositionMirror,
1470
+ RefElement,
1471
+ SelectionSide,
1472
+ getCurrentMentionReplaceRange
1473
+ });
1474
+ //# sourceMappingURL=index.js.map