@coze-editor/react-components 0.1.0-alpha.09ffeb

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