@tutti-os/ui-rich-text 0.0.124 → 0.0.126
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/README.md +58 -3
- package/dist/RichTextMentionService-CsZ9CGQf.d.ts +45 -0
- package/dist/chunk-3UTSSMV7.js +113 -0
- package/dist/chunk-3UTSSMV7.js.map +1 -0
- package/dist/{chunk-RUX5KKX3.js → chunk-CLNWVUDR.js} +1 -111
- package/dist/chunk-CLNWVUDR.js.map +1 -0
- package/dist/chunk-XN4EGZGR.js +316 -0
- package/dist/chunk-XN4EGZGR.js.map +1 -0
- package/dist/editor/index.d.ts +25 -5
- package/dist/editor/index.js +247 -149
- package/dist/editor/index.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +19 -0
- package/dist/plugins/index.js +4 -2
- package/dist/service/index.d.ts +14 -0
- package/dist/service/index.js +22 -0
- package/dist/service/index.js.map +1 -0
- package/package.json +11 -3
- package/dist/chunk-RUX5KKX3.js.map +0 -1
package/dist/editor/index.js
CHANGED
|
@@ -14,11 +14,10 @@ import {
|
|
|
14
14
|
} from "../chunk-AB4LAEBH.js";
|
|
15
15
|
import {
|
|
16
16
|
createRichTextMentionAttrs,
|
|
17
|
-
createRichTextTriggerRegistry,
|
|
18
17
|
getRichTextMentionDisplayText,
|
|
19
18
|
renderRichTextTriggerInsertResult,
|
|
20
19
|
resolveRichTextMentionView
|
|
21
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-CLNWVUDR.js";
|
|
22
21
|
import {
|
|
23
22
|
findRichTextMarkdownLinks,
|
|
24
23
|
isRichTextMentionHref,
|
|
@@ -30,13 +29,18 @@ import {
|
|
|
30
29
|
serializeRichTextDocumentToContent,
|
|
31
30
|
workspaceReferenceNodeName
|
|
32
31
|
} from "../chunk-RXT3DN3A.js";
|
|
32
|
+
import {
|
|
33
|
+
createRichTextMentionIdentityKey,
|
|
34
|
+
createRichTextMentionService
|
|
35
|
+
} from "../chunk-XN4EGZGR.js";
|
|
36
|
+
import "../chunk-3UTSSMV7.js";
|
|
33
37
|
|
|
34
38
|
// src/editor/RichTextTriggerEditor.tsx
|
|
35
39
|
import {
|
|
36
|
-
useCallback,
|
|
37
|
-
useEffect as
|
|
40
|
+
useCallback as useCallback2,
|
|
41
|
+
useEffect as useEffect3,
|
|
38
42
|
useLayoutEffect,
|
|
39
|
-
useMemo,
|
|
43
|
+
useMemo as useMemo2,
|
|
40
44
|
useRef,
|
|
41
45
|
useState as useState2
|
|
42
46
|
} from "react";
|
|
@@ -48,6 +52,64 @@ import { EditorContent, useEditor } from "@tiptap/react";
|
|
|
48
52
|
import { ViewportMenuSurface } from "@tutti-os/ui-system/components";
|
|
49
53
|
import { cn } from "@tutti-os/ui-system/utils";
|
|
50
54
|
|
|
55
|
+
// src/editor/RichTextMentionServiceProvider.tsx
|
|
56
|
+
import {
|
|
57
|
+
createContext,
|
|
58
|
+
useCallback,
|
|
59
|
+
useContext,
|
|
60
|
+
useEffect,
|
|
61
|
+
useMemo,
|
|
62
|
+
useSyncExternalStore
|
|
63
|
+
} from "react";
|
|
64
|
+
import { jsx } from "react/jsx-runtime";
|
|
65
|
+
var RichTextMentionServiceContext = createContext(null);
|
|
66
|
+
var idleSnapshot = Object.freeze({ state: "idle" });
|
|
67
|
+
function RichTextMentionServiceProvider({
|
|
68
|
+
service,
|
|
69
|
+
children
|
|
70
|
+
}) {
|
|
71
|
+
return /* @__PURE__ */ jsx(RichTextMentionServiceContext.Provider, { value: service, children });
|
|
72
|
+
}
|
|
73
|
+
function useRichTextMentionService(explicitService) {
|
|
74
|
+
const contextService = useContext(RichTextMentionServiceContext);
|
|
75
|
+
return explicitService ?? contextService;
|
|
76
|
+
}
|
|
77
|
+
function useEffectiveRichTextMentionService(input) {
|
|
78
|
+
const contextService = useRichTextMentionService();
|
|
79
|
+
const legacyService = useMemo(
|
|
80
|
+
() => input.mentionService || contextService ? null : createRichTextMentionService({
|
|
81
|
+
providers: input.triggerProviders ?? []
|
|
82
|
+
}),
|
|
83
|
+
[contextService, input.mentionService, input.triggerProviders]
|
|
84
|
+
);
|
|
85
|
+
useEffect(() => () => legacyService?.dispose(), [legacyService]);
|
|
86
|
+
return input.mentionService ?? contextService ?? legacyService;
|
|
87
|
+
}
|
|
88
|
+
function useResolvedRichTextMention(identity, explicitService) {
|
|
89
|
+
const service = useRichTextMentionService(explicitService);
|
|
90
|
+
const identityKey = createRichTextMentionIdentityKey(identity);
|
|
91
|
+
const stableIdentity = useMemo(
|
|
92
|
+
() => identity,
|
|
93
|
+
// Identity presentation fallback changes must still refresh the hook input.
|
|
94
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
95
|
+
[identityKey, identity.label]
|
|
96
|
+
);
|
|
97
|
+
const subscribe = useCallback(
|
|
98
|
+
(listener) => service?.subscribe(listener, stableIdentity) ?? (() => {
|
|
99
|
+
}),
|
|
100
|
+
[service, stableIdentity]
|
|
101
|
+
);
|
|
102
|
+
const getSnapshot = useCallback(
|
|
103
|
+
() => service?.getSnapshot(stableIdentity) ?? idleSnapshot,
|
|
104
|
+
[service, stableIdentity]
|
|
105
|
+
);
|
|
106
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (service) void service.resolve(stableIdentity);
|
|
109
|
+
}, [service, stableIdentity]);
|
|
110
|
+
return snapshot;
|
|
111
|
+
}
|
|
112
|
+
|
|
51
113
|
// src/editor/richTextTriggerQuery.ts
|
|
52
114
|
function isRichTextTriggerPrefixBoundary(character, boundary) {
|
|
53
115
|
if (boundary === "whitespace") {
|
|
@@ -229,7 +291,7 @@ function resolveTopStartPlacement(cursorRect, menuOffset) {
|
|
|
229
291
|
|
|
230
292
|
// src/editor/RichTextTriggerMenuItem.tsx
|
|
231
293
|
import { FileIcon, FolderFilledIcon } from "@tutti-os/ui-system/icons";
|
|
232
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
294
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
233
295
|
function RichTextTriggerMenuItem({
|
|
234
296
|
iconUrl,
|
|
235
297
|
label,
|
|
@@ -253,7 +315,7 @@ function RichTextTriggerMenuItem({
|
|
|
253
315
|
onSelect();
|
|
254
316
|
},
|
|
255
317
|
children: [
|
|
256
|
-
/* @__PURE__ */
|
|
318
|
+
/* @__PURE__ */ jsx2(
|
|
257
319
|
RichTextTriggerMenuIcon,
|
|
258
320
|
{
|
|
259
321
|
iconUrl,
|
|
@@ -261,8 +323,8 @@ function RichTextTriggerMenuItem({
|
|
|
261
323
|
}
|
|
262
324
|
),
|
|
263
325
|
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-auto flex-col items-start gap-0.5", children: [
|
|
264
|
-
/* @__PURE__ */
|
|
265
|
-
subtitle ? /* @__PURE__ */
|
|
326
|
+
/* @__PURE__ */ jsx2("span", { className: "w-full overflow-hidden text-ellipsis whitespace-nowrap text-[13px] leading-5 font-semibold", children: label }),
|
|
327
|
+
subtitle ? /* @__PURE__ */ jsx2("span", { className: "w-full overflow-hidden text-ellipsis whitespace-nowrap text-[11px] leading-4 text-[var(--text-secondary)]", children: subtitle }) : null
|
|
266
328
|
] })
|
|
267
329
|
]
|
|
268
330
|
}
|
|
@@ -275,23 +337,23 @@ function RichTextTriggerMenuIcon({
|
|
|
275
337
|
const normalizedIconUrl = iconUrl?.trim() ?? "";
|
|
276
338
|
if (workspaceReferenceFileKind) {
|
|
277
339
|
const Icon = workspaceReferenceFileKind === "folder" ? FolderFilledIcon : FileIcon;
|
|
278
|
-
return /* @__PURE__ */
|
|
340
|
+
return /* @__PURE__ */ jsx2(
|
|
279
341
|
"span",
|
|
280
342
|
{
|
|
281
343
|
"aria-hidden": "true",
|
|
282
344
|
className: "inline-grid size-4 flex-none place-items-center text-[var(--folder)]",
|
|
283
345
|
"data-rich-text-trigger-icon": "true",
|
|
284
|
-
children: /* @__PURE__ */
|
|
346
|
+
children: /* @__PURE__ */ jsx2(Icon, { className: "size-4" })
|
|
285
347
|
}
|
|
286
348
|
);
|
|
287
349
|
}
|
|
288
|
-
return /* @__PURE__ */
|
|
350
|
+
return /* @__PURE__ */ jsx2(
|
|
289
351
|
"span",
|
|
290
352
|
{
|
|
291
353
|
"aria-hidden": "true",
|
|
292
354
|
className: "inline-grid size-4 flex-none place-items-center overflow-hidden rounded bg-[var(--bg-block,var(--transparency-block))]",
|
|
293
355
|
"data-rich-text-trigger-icon": "true",
|
|
294
|
-
children: normalizedIconUrl ? /* @__PURE__ */
|
|
356
|
+
children: normalizedIconUrl ? /* @__PURE__ */ jsx2(
|
|
295
357
|
"img",
|
|
296
358
|
{
|
|
297
359
|
alt: "",
|
|
@@ -301,7 +363,7 @@ function RichTextTriggerMenuIcon({
|
|
|
301
363
|
loading: "lazy",
|
|
302
364
|
src: normalizedIconUrl
|
|
303
365
|
}
|
|
304
|
-
) : /* @__PURE__ */
|
|
366
|
+
) : /* @__PURE__ */ jsx2("span", { className: "block size-3 rounded-[3px] bg-[var(--transparency-block)]" })
|
|
305
367
|
}
|
|
306
368
|
);
|
|
307
369
|
}
|
|
@@ -312,30 +374,19 @@ import { ReactNodeViewRenderer } from "@tiptap/react";
|
|
|
312
374
|
|
|
313
375
|
// src/extensions/MentionReferenceNodeView.tsx
|
|
314
376
|
import { NodeViewWrapper } from "@tiptap/react";
|
|
315
|
-
import {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
319
|
-
var richTextMentionReferencePillClassName = "max-w-[16rem]";
|
|
377
|
+
import { MentionPill } from "@tutti-os/ui-system/components";
|
|
378
|
+
|
|
379
|
+
// src/extensions/mentionPillPresentation.ts
|
|
320
380
|
function readStringAttr(value) {
|
|
321
381
|
return typeof value === "string" ? value.trim() : "";
|
|
322
382
|
}
|
|
323
383
|
function readMentionPresentationUrl(presentation) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
const value = presentation.iconUrl ?? presentation.thumbnailUrl;
|
|
328
|
-
if (typeof value !== "string") {
|
|
329
|
-
return null;
|
|
330
|
-
}
|
|
331
|
-
const trimmed = value.trim();
|
|
384
|
+
const value = presentation?.iconUrl ?? presentation?.thumbnailUrl;
|
|
385
|
+
const trimmed = readStringAttr(value);
|
|
332
386
|
return trimmed || null;
|
|
333
387
|
}
|
|
334
388
|
function readMentionScopeValue(scope, key) {
|
|
335
|
-
|
|
336
|
-
return "";
|
|
337
|
-
}
|
|
338
|
-
return readStringAttr(scope[key]);
|
|
389
|
+
return readStringAttr(scope?.[key]);
|
|
339
390
|
}
|
|
340
391
|
function resolveMentionPillKind(providerId, scope) {
|
|
341
392
|
const id = providerId.trim();
|
|
@@ -356,24 +407,37 @@ function resolveMentionPillKind(providerId, scope) {
|
|
|
356
407
|
}
|
|
357
408
|
return "issue";
|
|
358
409
|
}
|
|
410
|
+
function resolveMentionPillIconUrl(input) {
|
|
411
|
+
return readMentionPresentationUrl(input.presentation) || readMentionScopeValue(input.scope, "icon") || null;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// src/extensions/MentionReferenceNodeView.tsx
|
|
415
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
416
|
+
var richTextMentionReferencePillClassName = "max-w-[16rem]";
|
|
417
|
+
function readStringAttr2(value) {
|
|
418
|
+
return typeof value === "string" ? value.trim() : "";
|
|
419
|
+
}
|
|
359
420
|
function MentionReferenceNodeView({
|
|
360
421
|
node,
|
|
361
422
|
selected
|
|
362
423
|
}) {
|
|
363
424
|
const label = typeof node.attrs.label === "string" ? node.attrs.label.trim().replace(/^@+/, "").trim() : "";
|
|
364
|
-
const iconUrl =
|
|
425
|
+
const iconUrl = resolveMentionPillIconUrl({
|
|
426
|
+
presentation: node.attrs.presentation,
|
|
427
|
+
scope: node.attrs.scope
|
|
428
|
+
});
|
|
365
429
|
const kind = resolveMentionPillKind(
|
|
366
|
-
|
|
430
|
+
readStringAttr2(node.attrs.providerId),
|
|
367
431
|
node.attrs.scope
|
|
368
432
|
);
|
|
369
|
-
return /* @__PURE__ */
|
|
433
|
+
return /* @__PURE__ */ jsx3(
|
|
370
434
|
NodeViewWrapper,
|
|
371
435
|
{
|
|
372
436
|
as: "span",
|
|
373
437
|
className: `inline-flex max-w-full align-baseline${selected ? " is-selected" : ""}`,
|
|
374
438
|
contentEditable: false,
|
|
375
439
|
"data-rich-text-mention-reference": "true",
|
|
376
|
-
children: /* @__PURE__ */
|
|
440
|
+
children: /* @__PURE__ */ jsx3(
|
|
377
441
|
MentionPill,
|
|
378
442
|
{
|
|
379
443
|
className: richTextMentionReferencePillClassName,
|
|
@@ -444,7 +508,7 @@ import { mergeAttributes as mergeAttributes2, Node as Node2 } from "@tiptap/core
|
|
|
444
508
|
import { ReactNodeViewRenderer as ReactNodeViewRenderer2 } from "@tiptap/react";
|
|
445
509
|
|
|
446
510
|
// src/extensions/WorkspaceReferenceNodeView.tsx
|
|
447
|
-
import { useEffect, useState } from "react";
|
|
511
|
+
import { useEffect as useEffect2, useState } from "react";
|
|
448
512
|
import { NodeViewWrapper as NodeViewWrapper2 } from "@tiptap/react";
|
|
449
513
|
import {
|
|
450
514
|
MentionPill as MentionPill2,
|
|
@@ -494,7 +558,7 @@ function isPathRoot(path) {
|
|
|
494
558
|
}
|
|
495
559
|
|
|
496
560
|
// src/extensions/WorkspaceReferenceNodeView.tsx
|
|
497
|
-
import { jsx as
|
|
561
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
498
562
|
var richTextWorkspaceReferencePillClassName = "max-w-[18rem]";
|
|
499
563
|
function WorkspaceReferenceNodeView({
|
|
500
564
|
deleteNode,
|
|
@@ -511,7 +575,7 @@ function WorkspaceReferenceNodeView({
|
|
|
511
575
|
const path = typeof attrs.path === "string" ? attrs.path : "";
|
|
512
576
|
const presentation = getWorkspaceReferencePresentation(label, path);
|
|
513
577
|
const removeActionAriaLabel = typeof extensionOptions.removeActionAriaLabel === "string" ? extensionOptions.removeActionAriaLabel : defaultRichTextTriggerText.removeReferenceActionLabel;
|
|
514
|
-
|
|
578
|
+
useEffect2(() => {
|
|
515
579
|
const syncEditable = () => {
|
|
516
580
|
setIsEditable(editor.isEditable);
|
|
517
581
|
};
|
|
@@ -531,7 +595,7 @@ function WorkspaceReferenceNodeView({
|
|
|
531
595
|
}
|
|
532
596
|
deleteNode();
|
|
533
597
|
};
|
|
534
|
-
return /* @__PURE__ */
|
|
598
|
+
return /* @__PURE__ */ jsx4(
|
|
535
599
|
NodeViewWrapper2,
|
|
536
600
|
{
|
|
537
601
|
as: "span",
|
|
@@ -539,7 +603,7 @@ function WorkspaceReferenceNodeView({
|
|
|
539
603
|
contentEditable: false,
|
|
540
604
|
"data-rich-text-workspace-reference": "true",
|
|
541
605
|
children: /* @__PURE__ */ jsxs2(Tooltip, { children: [
|
|
542
|
-
/* @__PURE__ */
|
|
606
|
+
/* @__PURE__ */ jsx4(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx4(
|
|
543
607
|
MentionPill2,
|
|
544
608
|
{
|
|
545
609
|
className: richTextWorkspaceReferencePillClassName,
|
|
@@ -554,7 +618,7 @@ function WorkspaceReferenceNodeView({
|
|
|
554
618
|
} : void 0
|
|
555
619
|
}
|
|
556
620
|
) }),
|
|
557
|
-
/* @__PURE__ */
|
|
621
|
+
/* @__PURE__ */ jsx4(
|
|
558
622
|
TooltipContent,
|
|
559
623
|
{
|
|
560
624
|
className: "max-w-md whitespace-normal break-all",
|
|
@@ -638,7 +702,7 @@ var WorkspaceReference = Node2.create({
|
|
|
638
702
|
});
|
|
639
703
|
|
|
640
704
|
// src/editor/RichTextTriggerEditor.tsx
|
|
641
|
-
import { jsx as
|
|
705
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
642
706
|
var RICH_TEXT_MENTION_PRESENTATION_KEYS = [
|
|
643
707
|
"agentProviderId",
|
|
644
708
|
"agentIconUrl",
|
|
@@ -656,7 +720,8 @@ var RICH_TEXT_MENTION_PRESENTATION_KEYS = [
|
|
|
656
720
|
function RichTextTriggerEditor({
|
|
657
721
|
value,
|
|
658
722
|
onChange,
|
|
659
|
-
triggerProviders
|
|
723
|
+
triggerProviders,
|
|
724
|
+
mentionService,
|
|
660
725
|
placeholder,
|
|
661
726
|
disabled = false,
|
|
662
727
|
className,
|
|
@@ -687,11 +752,11 @@ function RichTextTriggerEditor({
|
|
|
687
752
|
const mentionHydrationRequestRef = useRef(0);
|
|
688
753
|
const suppressPastedAtQueryRef = useRef(false);
|
|
689
754
|
const containerRef = useRef(null);
|
|
690
|
-
const registry =
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
);
|
|
694
|
-
const activeTriggerConfigs =
|
|
755
|
+
const registry = useEffectiveRichTextMentionService({
|
|
756
|
+
mentionService,
|
|
757
|
+
triggerProviders
|
|
758
|
+
});
|
|
759
|
+
const activeTriggerConfigs = useMemo2(
|
|
695
760
|
() => registry.listTriggerConfigs(),
|
|
696
761
|
[registry]
|
|
697
762
|
);
|
|
@@ -710,7 +775,7 @@ function RichTextTriggerEditor({
|
|
|
710
775
|
const [isLoading, setIsLoading] = useState2(false);
|
|
711
776
|
const [resolvedMenuAnchor, setResolvedMenuAnchor] = useState2(null);
|
|
712
777
|
latestOnChangeRef.current = onChange;
|
|
713
|
-
const resetMenuPlacement =
|
|
778
|
+
const resetMenuPlacement = useCallback2(() => {
|
|
714
779
|
setResolvedMenuAnchor(null);
|
|
715
780
|
}, []);
|
|
716
781
|
const editor = useEditor({
|
|
@@ -755,7 +820,7 @@ function RichTextTriggerEditor({
|
|
|
755
820
|
latestOnChangeRef.current(serialized);
|
|
756
821
|
}
|
|
757
822
|
});
|
|
758
|
-
|
|
823
|
+
useEffect3(() => {
|
|
759
824
|
if (!editor) {
|
|
760
825
|
return;
|
|
761
826
|
}
|
|
@@ -777,34 +842,32 @@ function RichTextTriggerEditor({
|
|
|
777
842
|
);
|
|
778
843
|
lastSerializedValueRef.current = normalizedValue;
|
|
779
844
|
}, [editor, normalizedValue]);
|
|
780
|
-
|
|
845
|
+
useEffect3(() => {
|
|
781
846
|
if (!editor) {
|
|
782
847
|
return;
|
|
783
848
|
}
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
}
|
|
799
|
-
applyResolvedMentionAttrs(editor, mention.pos, mention.attrs, {
|
|
800
|
-
label: resolved.label,
|
|
801
|
-
presentation: resolved.presentation
|
|
849
|
+
const hydrateMentions = () => {
|
|
850
|
+
const requestId = mentionHydrationRequestRef.current + 1;
|
|
851
|
+
mentionHydrationRequestRef.current = requestId;
|
|
852
|
+
const mentions = collectHydratableMentionNodes(editor);
|
|
853
|
+
for (const mention of mentions) {
|
|
854
|
+
void registry.resolve(mention.attrs).then((snapshot) => {
|
|
855
|
+
const resolved = snapshot.state === "ready" ? snapshot.resolved : void 0;
|
|
856
|
+
if (!resolved || mentionHydrationRequestRef.current !== requestId || editor.isDestroyed) {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
applyResolvedMentionAttrs(editor, mention.pos, mention.attrs, {
|
|
860
|
+
label: resolved.label,
|
|
861
|
+
presentation: resolved.presentation
|
|
862
|
+
});
|
|
863
|
+
}).catch(() => {
|
|
802
864
|
});
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
hydrateMentions();
|
|
868
|
+
return registry.subscribe(hydrateMentions);
|
|
806
869
|
}, [editor, registry, normalizedValue]);
|
|
807
|
-
|
|
870
|
+
useEffect3(() => {
|
|
808
871
|
if (!editor) {
|
|
809
872
|
return;
|
|
810
873
|
}
|
|
@@ -814,7 +877,7 @@ function RichTextTriggerEditor({
|
|
|
814
877
|
lastFocusSignalRef.current = focusSignal;
|
|
815
878
|
editor.commands.focus("end");
|
|
816
879
|
}, [editor, focusSignal]);
|
|
817
|
-
|
|
880
|
+
useEffect3(() => {
|
|
818
881
|
if (!editor) {
|
|
819
882
|
return;
|
|
820
883
|
}
|
|
@@ -823,7 +886,7 @@ function RichTextTriggerEditor({
|
|
|
823
886
|
editor.state.tr.setMeta("richTextEditable", !disabled)
|
|
824
887
|
);
|
|
825
888
|
}, [disabled, editor]);
|
|
826
|
-
|
|
889
|
+
useEffect3(() => {
|
|
827
890
|
if (!editor) {
|
|
828
891
|
return;
|
|
829
892
|
}
|
|
@@ -852,7 +915,7 @@ function RichTextTriggerEditor({
|
|
|
852
915
|
editor.off("blur", updateFocus);
|
|
853
916
|
};
|
|
854
917
|
}, [activeTriggerConfigs, editor]);
|
|
855
|
-
|
|
918
|
+
useEffect3(() => {
|
|
856
919
|
if (!editor || !query || activeTriggerConfigs.length === 0) {
|
|
857
920
|
setMatches([]);
|
|
858
921
|
setActiveIndex(0);
|
|
@@ -909,7 +972,7 @@ function RichTextTriggerEditor({
|
|
|
909
972
|
palette,
|
|
910
973
|
activePaletteCategoryId
|
|
911
974
|
);
|
|
912
|
-
const paletteState =
|
|
975
|
+
const paletteState = useMemo2(
|
|
913
976
|
() => palette ? buildMentionPaletteModelFromTriggerMatches({
|
|
914
977
|
activeCategoryId: resolvedPaletteCategoryId,
|
|
915
978
|
categories: palette.categories,
|
|
@@ -920,7 +983,7 @@ function RichTextTriggerEditor({
|
|
|
920
983
|
}) : null,
|
|
921
984
|
[isLoading, matches, palette, query?.keyword, resolvedPaletteCategoryId]
|
|
922
985
|
);
|
|
923
|
-
|
|
986
|
+
useEffect3(() => {
|
|
924
987
|
const defaultCategoryId = resolveDefaultPaletteCategoryId(palette);
|
|
925
988
|
if (!defaultCategoryId) {
|
|
926
989
|
setActivePaletteCategoryId("");
|
|
@@ -933,7 +996,7 @@ function RichTextTriggerEditor({
|
|
|
933
996
|
}
|
|
934
997
|
setActivePaletteCategoryId(defaultCategoryId);
|
|
935
998
|
}, [activePaletteCategoryId, palette]);
|
|
936
|
-
|
|
999
|
+
useEffect3(() => {
|
|
937
1000
|
if (!paletteState) {
|
|
938
1001
|
setHighlightedPaletteKey(null);
|
|
939
1002
|
return;
|
|
@@ -1116,8 +1179,8 @@ function RichTextTriggerEditor({
|
|
|
1116
1179
|
},
|
|
1117
1180
|
ref: containerRef,
|
|
1118
1181
|
children: [
|
|
1119
|
-
/* @__PURE__ */
|
|
1120
|
-
isEmpty && placeholder ? /* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ jsx5("div", { className: "w-full min-w-0", onKeyDownCapture: handleKeyDown, children: /* @__PURE__ */ jsx5(EditorContent, { editor }) }),
|
|
1183
|
+
isEmpty && placeholder ? /* @__PURE__ */ jsx5("div", { className: "pointer-events-none absolute top-0 right-0 left-0 px-0 py-0 text-[var(--text-placeholder)]", children: /* @__PURE__ */ jsx5(
|
|
1121
1184
|
"div",
|
|
1122
1185
|
{
|
|
1123
1186
|
className: cn(
|
|
@@ -1129,7 +1192,7 @@ function RichTextTriggerEditor({
|
|
|
1129
1192
|
}
|
|
1130
1193
|
) }) : null,
|
|
1131
1194
|
overlay,
|
|
1132
|
-
isMenuOpen && resolvedMenuAnchor ? /* @__PURE__ */
|
|
1195
|
+
isMenuOpen && resolvedMenuAnchor ? /* @__PURE__ */ jsx5(
|
|
1133
1196
|
ViewportMenuSurface,
|
|
1134
1197
|
{
|
|
1135
1198
|
open: true,
|
|
@@ -1139,7 +1202,7 @@ function RichTextTriggerEditor({
|
|
|
1139
1202
|
),
|
|
1140
1203
|
placement: resolveViewportMenuSurfacePlacement(resolvedMenuAnchor),
|
|
1141
1204
|
style: menuSurfaceStyle,
|
|
1142
|
-
children: paletteState && palette ? /* @__PURE__ */
|
|
1205
|
+
children: paletteState && palette ? /* @__PURE__ */ jsx5(
|
|
1143
1206
|
MentionPaletteFromState,
|
|
1144
1207
|
{
|
|
1145
1208
|
state: paletteState,
|
|
@@ -1166,7 +1229,7 @@ function RichTextTriggerEditor({
|
|
|
1166
1229
|
onSelectItem: applyMatch
|
|
1167
1230
|
}
|
|
1168
1231
|
}
|
|
1169
|
-
) : matches.length > 0 ? matches.map((match, index) => /* @__PURE__ */
|
|
1232
|
+
) : matches.length > 0 ? matches.map((match, index) => /* @__PURE__ */ jsx5(
|
|
1170
1233
|
RichTextTriggerMenuItem,
|
|
1171
1234
|
{
|
|
1172
1235
|
label: match.label,
|
|
@@ -1179,7 +1242,7 @@ function RichTextTriggerEditor({
|
|
|
1179
1242
|
onSelect: () => applyMatch(match)
|
|
1180
1243
|
},
|
|
1181
1244
|
`${match.providerId}:${match.key}`
|
|
1182
|
-
)) : /* @__PURE__ */
|
|
1245
|
+
)) : /* @__PURE__ */ jsx5("div", { className: "px-3 py-2 text-[11px] leading-4 text-[var(--text-secondary)]", children: isLoading ? text.loadingLabel : text.noMatchesLabel })
|
|
1183
1246
|
}
|
|
1184
1247
|
) : null
|
|
1185
1248
|
]
|
|
@@ -1400,9 +1463,9 @@ function normalizeMentionPresentation(value) {
|
|
|
1400
1463
|
|
|
1401
1464
|
// src/editor/RichTextTriggerTextarea.tsx
|
|
1402
1465
|
import {
|
|
1403
|
-
useEffect as
|
|
1466
|
+
useEffect as useEffect4,
|
|
1404
1467
|
useLayoutEffect as useLayoutEffect2,
|
|
1405
|
-
useMemo as
|
|
1468
|
+
useMemo as useMemo3,
|
|
1406
1469
|
useRef as useRef2,
|
|
1407
1470
|
useState as useState3
|
|
1408
1471
|
} from "react";
|
|
@@ -1536,7 +1599,7 @@ function getTextareaPresentationStyle(textarea) {
|
|
|
1536
1599
|
// src/editor/richTextTextareaDecorations.tsx
|
|
1537
1600
|
import { MentionPill as MentionPill3 } from "@tutti-os/ui-system/components";
|
|
1538
1601
|
import { cn as cn2 } from "@tutti-os/ui-system/utils";
|
|
1539
|
-
import { jsx as
|
|
1602
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1540
1603
|
var richTextWorkspaceReferencePillClassName2 = "max-w-[18rem]";
|
|
1541
1604
|
function RichTextTextareaDecoratedContent({
|
|
1542
1605
|
onClickSegment,
|
|
@@ -1547,7 +1610,7 @@ function RichTextTextareaDecoratedContent({
|
|
|
1547
1610
|
segments,
|
|
1548
1611
|
textareaStyle
|
|
1549
1612
|
}) {
|
|
1550
|
-
return /* @__PURE__ */
|
|
1613
|
+
return /* @__PURE__ */ jsx6("div", { className: "pointer-events-none absolute inset-0 z-10 overflow-hidden", children: /* @__PURE__ */ jsx6(
|
|
1551
1614
|
"div",
|
|
1552
1615
|
{
|
|
1553
1616
|
className: "min-h-full min-w-full",
|
|
@@ -1557,11 +1620,11 @@ function RichTextTextareaDecoratedContent({
|
|
|
1557
1620
|
},
|
|
1558
1621
|
children: segments.map((segment, index) => {
|
|
1559
1622
|
if (segment.type === "text") {
|
|
1560
|
-
return /* @__PURE__ */
|
|
1623
|
+
return /* @__PURE__ */ jsx6("span", { children: segment.text }, index);
|
|
1561
1624
|
}
|
|
1562
1625
|
return /* @__PURE__ */ jsxs4("span", { className: "relative", children: [
|
|
1563
|
-
/* @__PURE__ */
|
|
1564
|
-
/* @__PURE__ */
|
|
1626
|
+
/* @__PURE__ */ jsx6("span", { "aria-hidden": "true", className: "text-transparent", children: segment.text }),
|
|
1627
|
+
/* @__PURE__ */ jsx6(
|
|
1565
1628
|
MentionPill3,
|
|
1566
1629
|
{
|
|
1567
1630
|
className: cn2(
|
|
@@ -1579,7 +1642,7 @@ function RichTextTextareaDecoratedContent({
|
|
|
1579
1642
|
onRemoveSegment(segment);
|
|
1580
1643
|
}
|
|
1581
1644
|
},
|
|
1582
|
-
summary: /* @__PURE__ */
|
|
1645
|
+
summary: /* @__PURE__ */ jsx6(
|
|
1583
1646
|
"span",
|
|
1584
1647
|
{
|
|
1585
1648
|
className: cn2(
|
|
@@ -1704,11 +1767,12 @@ function getTextareaCaretViewportPoint(textarea, selectionStart) {
|
|
|
1704
1767
|
}
|
|
1705
1768
|
|
|
1706
1769
|
// src/editor/RichTextTriggerTextarea.tsx
|
|
1707
|
-
import { jsx as
|
|
1770
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1708
1771
|
function RichTextTriggerTextarea({
|
|
1709
1772
|
value,
|
|
1710
1773
|
onChange,
|
|
1711
|
-
triggerProviders
|
|
1774
|
+
triggerProviders,
|
|
1775
|
+
mentionService,
|
|
1712
1776
|
placeholder,
|
|
1713
1777
|
disabled = false,
|
|
1714
1778
|
className,
|
|
@@ -1742,27 +1806,27 @@ function RichTextTriggerTextarea({
|
|
|
1742
1806
|
const [textareaPresentationStyle, setTextareaPresentationStyle] = useState3(null);
|
|
1743
1807
|
const pendingSelectionRef = useRef2(null);
|
|
1744
1808
|
const suppressPastedAtQueryRef = useRef2(false);
|
|
1745
|
-
const registry =
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
);
|
|
1749
|
-
const activeTriggerConfigs =
|
|
1809
|
+
const registry = useEffectiveRichTextMentionService({
|
|
1810
|
+
mentionService,
|
|
1811
|
+
triggerProviders
|
|
1812
|
+
});
|
|
1813
|
+
const activeTriggerConfigs = useMemo3(
|
|
1750
1814
|
() => registry.listTriggerConfigs(),
|
|
1751
1815
|
[registry]
|
|
1752
1816
|
);
|
|
1753
|
-
const decorationSegments =
|
|
1817
|
+
const decorationSegments = useMemo3(
|
|
1754
1818
|
() => buildRichTextTextareaDecorationSegments(value),
|
|
1755
1819
|
[value]
|
|
1756
1820
|
);
|
|
1757
1821
|
const hasDecorations = hasRichTextTextareaDecorations(decorationSegments);
|
|
1758
|
-
const query =
|
|
1822
|
+
const query = useMemo3(
|
|
1759
1823
|
() => isFocused ? findRichTextTriggerQuery(value, selectionStart, activeTriggerConfigs) : null,
|
|
1760
1824
|
[activeTriggerConfigs, isFocused, selectionStart, value]
|
|
1761
1825
|
);
|
|
1762
1826
|
const visibleQuery = suppressPastedAtQueryRef.current && query?.trigger === "@" && query.keyword.length > 0 ? null : query;
|
|
1763
1827
|
const shouldQuery = visibleQuery !== null && visibleQuery.keyword.length >= minQueryLength && activeTriggerConfigs.length > 0;
|
|
1764
1828
|
const isMenuOpen = isFocused && shouldQuery && (isLoading || matches.length > 0);
|
|
1765
|
-
|
|
1829
|
+
useEffect4(() => {
|
|
1766
1830
|
const nextSelection = pendingSelectionRef.current;
|
|
1767
1831
|
if (nextSelection === null || !textareaRef.current) {
|
|
1768
1832
|
return;
|
|
@@ -1770,7 +1834,7 @@ function RichTextTriggerTextarea({
|
|
|
1770
1834
|
textareaRef.current.setSelectionRange(nextSelection, nextSelection);
|
|
1771
1835
|
pendingSelectionRef.current = null;
|
|
1772
1836
|
}, [value]);
|
|
1773
|
-
|
|
1837
|
+
useEffect4(() => {
|
|
1774
1838
|
if (!shouldQuery || !visibleQuery) {
|
|
1775
1839
|
setMatches([]);
|
|
1776
1840
|
setActiveIndex(0);
|
|
@@ -1839,7 +1903,7 @@ function RichTextTriggerTextarea({
|
|
|
1839
1903
|
y: caretPoint.y + caretPoint.lineHeight + menuOffset
|
|
1840
1904
|
});
|
|
1841
1905
|
}, [isMenuOpen, menuOffset, selectionStart, value, visibleQuery]);
|
|
1842
|
-
|
|
1906
|
+
useEffect4(() => {
|
|
1843
1907
|
if (!isMenuOpen || !visibleQuery || !textareaRef.current) {
|
|
1844
1908
|
return;
|
|
1845
1909
|
}
|
|
@@ -1966,7 +2030,7 @@ function RichTextTriggerTextarea({
|
|
|
1966
2030
|
}
|
|
1967
2031
|
};
|
|
1968
2032
|
return /* @__PURE__ */ jsxs5("div", { className: cn3("relative min-w-0 w-full", className), children: [
|
|
1969
|
-
hasDecorations && textareaPresentationStyle ? /* @__PURE__ */
|
|
2033
|
+
hasDecorations && textareaPresentationStyle ? /* @__PURE__ */ jsx7(
|
|
1970
2034
|
RichTextTextareaDecoratedContent,
|
|
1971
2035
|
{
|
|
1972
2036
|
onClickSegment: handleClickDecoration,
|
|
@@ -1978,7 +2042,7 @@ function RichTextTriggerTextarea({
|
|
|
1978
2042
|
textareaStyle: textareaPresentationStyle
|
|
1979
2043
|
}
|
|
1980
2044
|
) : null,
|
|
1981
|
-
/* @__PURE__ */
|
|
2045
|
+
/* @__PURE__ */ jsx7(
|
|
1982
2046
|
"textarea",
|
|
1983
2047
|
{
|
|
1984
2048
|
ref: textareaRef,
|
|
@@ -2058,7 +2122,7 @@ function RichTextTriggerTextarea({
|
|
|
2058
2122
|
}
|
|
2059
2123
|
),
|
|
2060
2124
|
overlay,
|
|
2061
|
-
isMenuOpen && menuPoint ? /* @__PURE__ */
|
|
2125
|
+
isMenuOpen && menuPoint ? /* @__PURE__ */ jsx7(
|
|
2062
2126
|
ViewportMenuSurface2,
|
|
2063
2127
|
{
|
|
2064
2128
|
open: true,
|
|
@@ -2074,7 +2138,7 @@ function RichTextTriggerTextarea({
|
|
|
2074
2138
|
height: 256
|
|
2075
2139
|
}
|
|
2076
2140
|
},
|
|
2077
|
-
children: matches.length > 0 ? matches.map((match, index) => /* @__PURE__ */
|
|
2141
|
+
children: matches.length > 0 ? matches.map((match, index) => /* @__PURE__ */ jsx7(
|
|
2078
2142
|
RichTextTriggerMenuItem,
|
|
2079
2143
|
{
|
|
2080
2144
|
label: match.label,
|
|
@@ -2084,48 +2148,39 @@ function RichTextTriggerTextarea({
|
|
|
2084
2148
|
onSelect: () => applyMatch(match)
|
|
2085
2149
|
},
|
|
2086
2150
|
`${match.providerId}:${match.key}`
|
|
2087
|
-
)) : /* @__PURE__ */
|
|
2151
|
+
)) : /* @__PURE__ */ jsx7("div", { className: "px-3 py-2 text-[11px] leading-4 text-[var(--text-secondary)]", children: isLoading ? text.loadingLabel : text.noMatchesLabel })
|
|
2088
2152
|
}
|
|
2089
2153
|
) : null
|
|
2090
2154
|
] });
|
|
2091
2155
|
}
|
|
2092
2156
|
|
|
2093
2157
|
// src/editor/RichTextMentionReadonly.tsx
|
|
2094
|
-
import {
|
|
2158
|
+
import { MentionPill as MentionPill4 } from "@tutti-os/ui-system/components";
|
|
2159
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
2095
2160
|
var baseStyle = {
|
|
2096
2161
|
alignItems: "center",
|
|
2097
|
-
border: "1px solid transparent",
|
|
2098
|
-
borderRadius: "999px",
|
|
2099
2162
|
display: "inline-flex",
|
|
2100
|
-
fontSize: "0.95em",
|
|
2101
|
-
gap: "0.25rem",
|
|
2102
|
-
lineHeight: 1.4,
|
|
2103
2163
|
maxWidth: "100%",
|
|
2104
|
-
padding: "0.05rem 0.45rem",
|
|
2105
2164
|
textDecoration: "none",
|
|
2106
2165
|
verticalAlign: "baseline",
|
|
2107
2166
|
whiteSpace: "nowrap"
|
|
2108
2167
|
};
|
|
2109
2168
|
var stateStyles = {
|
|
2110
2169
|
active: {
|
|
2111
|
-
background: "var(--tutti-rich-text-mention-active-bg, color-mix(in srgb, currentColor 12%, transparent))",
|
|
2112
2170
|
color: "var(--tutti-rich-text-mention-active-fg, inherit)",
|
|
2113
2171
|
cursor: "pointer"
|
|
2114
2172
|
},
|
|
2115
2173
|
missing: {
|
|
2116
|
-
background: "var(--tutti-rich-text-mention-missing-bg, color-mix(in srgb, currentColor 6%, transparent))",
|
|
2117
2174
|
color: "var(--tutti-rich-text-mention-missing-fg, color-mix(in srgb, currentColor 48%, transparent))",
|
|
2118
2175
|
cursor: "default",
|
|
2119
2176
|
textDecoration: "line-through"
|
|
2120
2177
|
},
|
|
2121
2178
|
disabled: {
|
|
2122
|
-
background: "var(--tutti-rich-text-mention-disabled-bg, color-mix(in srgb, currentColor 6%, transparent))",
|
|
2123
2179
|
color: "var(--tutti-rich-text-mention-disabled-fg, color-mix(in srgb, currentColor 58%, transparent))",
|
|
2124
2180
|
cursor: "not-allowed",
|
|
2125
2181
|
opacity: 0.88
|
|
2126
2182
|
},
|
|
2127
2183
|
loading: {
|
|
2128
|
-
background: "var(--tutti-rich-text-mention-loading-bg, color-mix(in srgb, currentColor 8%, transparent))",
|
|
2129
2184
|
color: "var(--tutti-rich-text-mention-loading-fg, color-mix(in srgb, currentColor 82%, transparent))",
|
|
2130
2185
|
cursor: "progress",
|
|
2131
2186
|
opacity: 0.92
|
|
@@ -2148,10 +2203,20 @@ function RichTextMentionReadonly({
|
|
|
2148
2203
|
mention,
|
|
2149
2204
|
resolved: view
|
|
2150
2205
|
};
|
|
2151
|
-
const label = renderLabel?.(payload) ?? getRichTextMentionDisplayText({
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2206
|
+
const label = renderLabel?.(payload) ?? getRichTextMentionDisplayText({ ...mention, label: view.label });
|
|
2207
|
+
const content = /* @__PURE__ */ jsx8(
|
|
2208
|
+
MentionPill4,
|
|
2209
|
+
{
|
|
2210
|
+
className: "top-0",
|
|
2211
|
+
iconUrl: resolveMentionPillIconUrl({
|
|
2212
|
+
presentation: view.presentation,
|
|
2213
|
+
scope: mention.scope
|
|
2214
|
+
}) ?? void 0,
|
|
2215
|
+
kind: resolveMentionPillKind(mention.providerId, mention.scope),
|
|
2216
|
+
label,
|
|
2217
|
+
removable: false
|
|
2218
|
+
}
|
|
2219
|
+
);
|
|
2155
2220
|
const elementTitle = title ?? view.tooltip;
|
|
2156
2221
|
const handleClick = (event) => {
|
|
2157
2222
|
if (!view.interactive) {
|
|
@@ -2177,7 +2242,7 @@ function RichTextMentionReadonly({
|
|
|
2177
2242
|
title: elementTitle
|
|
2178
2243
|
};
|
|
2179
2244
|
if (view.interactive && onClick) {
|
|
2180
|
-
return /* @__PURE__ */
|
|
2245
|
+
return /* @__PURE__ */ jsx8(
|
|
2181
2246
|
"button",
|
|
2182
2247
|
{
|
|
2183
2248
|
...sharedProps,
|
|
@@ -2187,19 +2252,22 @@ function RichTextMentionReadonly({
|
|
|
2187
2252
|
style: {
|
|
2188
2253
|
...sharedProps.style,
|
|
2189
2254
|
appearance: "none",
|
|
2190
|
-
|
|
2255
|
+
background: "transparent",
|
|
2256
|
+
border: 0,
|
|
2257
|
+
font: "inherit",
|
|
2258
|
+
padding: 0
|
|
2191
2259
|
},
|
|
2192
2260
|
type: "button",
|
|
2193
|
-
children:
|
|
2261
|
+
children: content
|
|
2194
2262
|
}
|
|
2195
2263
|
);
|
|
2196
2264
|
}
|
|
2197
|
-
return /* @__PURE__ */
|
|
2265
|
+
return /* @__PURE__ */ jsx8("span", { ...sharedProps, children: content });
|
|
2198
2266
|
}
|
|
2199
2267
|
|
|
2200
2268
|
// src/editor/RichTextReadonlyContent.tsx
|
|
2201
2269
|
import {
|
|
2202
|
-
MentionPill as
|
|
2270
|
+
MentionPill as MentionPill5,
|
|
2203
2271
|
Tooltip as Tooltip2,
|
|
2204
2272
|
TooltipContent as TooltipContent2,
|
|
2205
2273
|
TooltipTrigger as TooltipTrigger2
|
|
@@ -2234,27 +2302,34 @@ function buildRichTextReadonlyInlineSegments(content) {
|
|
|
2234
2302
|
}
|
|
2235
2303
|
|
|
2236
2304
|
// src/editor/RichTextReadonlyContent.tsx
|
|
2237
|
-
import { jsx as
|
|
2305
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2238
2306
|
var externalHrefPattern = /^(?:[a-z]+:)?\/\//i;
|
|
2239
2307
|
var richTextWorkspaceReferencePillClassName3 = "max-w-[18rem]";
|
|
2240
2308
|
function RichTextReadonlyContent({
|
|
2241
2309
|
value,
|
|
2242
2310
|
className,
|
|
2243
2311
|
paragraphClassName,
|
|
2312
|
+
triggerProviders,
|
|
2313
|
+
mentionService,
|
|
2244
2314
|
onMentionAction,
|
|
2245
2315
|
onOpenWorkspaceReference
|
|
2246
2316
|
}) {
|
|
2247
2317
|
const normalizedValue = normalizeRichTextContent(value).trim();
|
|
2318
|
+
const effectiveMentionService = useEffectiveRichTextMentionService({
|
|
2319
|
+
mentionService,
|
|
2320
|
+
triggerProviders
|
|
2321
|
+
});
|
|
2248
2322
|
if (!normalizedValue) {
|
|
2249
2323
|
return null;
|
|
2250
2324
|
}
|
|
2251
2325
|
const paragraphs = normalizedValue.split(/\n{2,}/).map((paragraph) => paragraph.trim()).filter(Boolean);
|
|
2252
|
-
return /* @__PURE__ */
|
|
2326
|
+
return /* @__PURE__ */ jsx9("div", { className: cn4("space-y-4", className), children: paragraphs.map((paragraph, paragraphIndex) => /* @__PURE__ */ jsx9(
|
|
2253
2327
|
"p",
|
|
2254
2328
|
{
|
|
2255
2329
|
className: cn4("whitespace-pre-wrap", paragraphClassName),
|
|
2256
2330
|
children: renderReadonlyInlineMarkdown(
|
|
2257
2331
|
paragraph,
|
|
2332
|
+
effectiveMentionService,
|
|
2258
2333
|
onOpenWorkspaceReference,
|
|
2259
2334
|
onMentionAction
|
|
2260
2335
|
)
|
|
@@ -2262,22 +2337,23 @@ function RichTextReadonlyContent({
|
|
|
2262
2337
|
`${paragraphIndex}:${paragraph}`
|
|
2263
2338
|
)) });
|
|
2264
2339
|
}
|
|
2265
|
-
function renderReadonlyInlineMarkdown(content, onOpenWorkspaceReference, onMentionAction) {
|
|
2340
|
+
function renderReadonlyInlineMarkdown(content, mentionService, onOpenWorkspaceReference, onMentionAction) {
|
|
2266
2341
|
const parts = [];
|
|
2267
2342
|
const segments = buildRichTextReadonlyInlineSegments(content);
|
|
2268
2343
|
segments.forEach((segment, index) => {
|
|
2269
2344
|
if (segment.type === "text") {
|
|
2270
|
-
parts.push(/* @__PURE__ */
|
|
2345
|
+
parts.push(/* @__PURE__ */ jsx9("span", { children: segment.text }, `text:${index}`));
|
|
2271
2346
|
return;
|
|
2272
2347
|
}
|
|
2273
2348
|
parts.push(
|
|
2274
|
-
/* @__PURE__ */
|
|
2349
|
+
/* @__PURE__ */ jsx9(
|
|
2275
2350
|
RichTextReadonlyInlineLink,
|
|
2276
2351
|
{
|
|
2277
2352
|
href: segment.href,
|
|
2278
2353
|
label: segment.label,
|
|
2279
2354
|
onMentionAction,
|
|
2280
|
-
onOpenWorkspaceReference
|
|
2355
|
+
onOpenWorkspaceReference,
|
|
2356
|
+
mentionService
|
|
2281
2357
|
},
|
|
2282
2358
|
`link:${index}:${segment.href}`
|
|
2283
2359
|
)
|
|
@@ -2289,26 +2365,28 @@ function RichTextReadonlyInlineLink({
|
|
|
2289
2365
|
href,
|
|
2290
2366
|
label,
|
|
2291
2367
|
onMentionAction,
|
|
2292
|
-
onOpenWorkspaceReference
|
|
2368
|
+
onOpenWorkspaceReference,
|
|
2369
|
+
mentionService
|
|
2293
2370
|
}) {
|
|
2294
2371
|
const trimmedHref = href.trim();
|
|
2295
2372
|
const mention = parseRichTextMentionHref(trimmedHref, label);
|
|
2296
2373
|
if (mention) {
|
|
2297
|
-
return /* @__PURE__ */
|
|
2298
|
-
|
|
2374
|
+
return /* @__PURE__ */ jsx9(
|
|
2375
|
+
HydratedRichTextMentionReadonly,
|
|
2299
2376
|
{
|
|
2300
2377
|
mention,
|
|
2301
2378
|
onClick: onMentionAction ? ({ mention: mention2 }) => {
|
|
2302
2379
|
void onMentionAction(mention2);
|
|
2303
|
-
} : void 0
|
|
2380
|
+
} : void 0,
|
|
2381
|
+
mentionService
|
|
2304
2382
|
}
|
|
2305
2383
|
);
|
|
2306
2384
|
}
|
|
2307
2385
|
if (!trimmedHref) {
|
|
2308
|
-
return /* @__PURE__ */
|
|
2386
|
+
return /* @__PURE__ */ jsx9("span", { children: label });
|
|
2309
2387
|
}
|
|
2310
2388
|
if (externalHrefPattern.test(trimmedHref) && !isRichTextMentionHref(trimmedHref)) {
|
|
2311
|
-
return /* @__PURE__ */
|
|
2389
|
+
return /* @__PURE__ */ jsx9(
|
|
2312
2390
|
"a",
|
|
2313
2391
|
{
|
|
2314
2392
|
className: "font-medium text-[var(--text-primary)] underline decoration-[var(--border-1)] underline-offset-4 hover:text-[var(--text-primary-hover)]",
|
|
@@ -2321,7 +2399,7 @@ function RichTextReadonlyInlineLink({
|
|
|
2321
2399
|
}
|
|
2322
2400
|
const kind = trimmedHref.endsWith("/") ? "folder" : "file";
|
|
2323
2401
|
const path = normalizeRichTextLinkHref(trimmedHref, kind);
|
|
2324
|
-
return /* @__PURE__ */
|
|
2402
|
+
return /* @__PURE__ */ jsx9(
|
|
2325
2403
|
WorkspaceReferenceReadonly,
|
|
2326
2404
|
{
|
|
2327
2405
|
reference: {
|
|
@@ -2333,6 +2411,22 @@ function RichTextReadonlyInlineLink({
|
|
|
2333
2411
|
}
|
|
2334
2412
|
);
|
|
2335
2413
|
}
|
|
2414
|
+
function HydratedRichTextMentionReadonly({
|
|
2415
|
+
mention,
|
|
2416
|
+
onClick,
|
|
2417
|
+
mentionService
|
|
2418
|
+
}) {
|
|
2419
|
+
const snapshot = useResolvedRichTextMention(mention, mentionService);
|
|
2420
|
+
const resolved = snapshot.state === "ready" ? { state: "active", ...snapshot.resolved } : snapshot.state === "loading" ? { state: "loading" } : snapshot.state === "missing" ? { state: "missing" } : void 0;
|
|
2421
|
+
return /* @__PURE__ */ jsx9(
|
|
2422
|
+
RichTextMentionReadonly,
|
|
2423
|
+
{
|
|
2424
|
+
mention,
|
|
2425
|
+
onClick,
|
|
2426
|
+
resolved
|
|
2427
|
+
}
|
|
2428
|
+
);
|
|
2429
|
+
}
|
|
2336
2430
|
function WorkspaceReferenceReadonly({
|
|
2337
2431
|
reference,
|
|
2338
2432
|
onOpenWorkspaceReference
|
|
@@ -2341,8 +2435,8 @@ function WorkspaceReferenceReadonly({
|
|
|
2341
2435
|
reference.label,
|
|
2342
2436
|
reference.path
|
|
2343
2437
|
);
|
|
2344
|
-
const content = /* @__PURE__ */
|
|
2345
|
-
|
|
2438
|
+
const content = /* @__PURE__ */ jsx9(
|
|
2439
|
+
MentionPill5,
|
|
2346
2440
|
{
|
|
2347
2441
|
className: richTextWorkspaceReferencePillClassName3,
|
|
2348
2442
|
fileKind: reference.kind,
|
|
@@ -2352,7 +2446,7 @@ function WorkspaceReferenceReadonly({
|
|
|
2352
2446
|
}
|
|
2353
2447
|
);
|
|
2354
2448
|
return /* @__PURE__ */ jsxs6(Tooltip2, { children: [
|
|
2355
|
-
/* @__PURE__ */
|
|
2449
|
+
/* @__PURE__ */ jsx9(TooltipTrigger2, { asChild: true, children: onOpenWorkspaceReference ? /* @__PURE__ */ jsx9(
|
|
2356
2450
|
"button",
|
|
2357
2451
|
{
|
|
2358
2452
|
className: "inline-flex max-w-full appearance-none items-baseline bg-transparent p-0 text-inherit",
|
|
@@ -2362,8 +2456,8 @@ function WorkspaceReferenceReadonly({
|
|
|
2362
2456
|
},
|
|
2363
2457
|
children: content
|
|
2364
2458
|
}
|
|
2365
|
-
) : /* @__PURE__ */
|
|
2366
|
-
/* @__PURE__ */
|
|
2459
|
+
) : /* @__PURE__ */ jsx9("span", { className: "inline-flex max-w-full align-baseline", children: content }) }),
|
|
2460
|
+
/* @__PURE__ */ jsx9(
|
|
2367
2461
|
TooltipContent2,
|
|
2368
2462
|
{
|
|
2369
2463
|
className: "max-w-md whitespace-normal break-all",
|
|
@@ -2375,11 +2469,15 @@ function WorkspaceReferenceReadonly({
|
|
|
2375
2469
|
}
|
|
2376
2470
|
export {
|
|
2377
2471
|
RichTextMentionReadonly,
|
|
2472
|
+
RichTextMentionServiceProvider,
|
|
2378
2473
|
RichTextReadonlyContent,
|
|
2379
2474
|
RichTextTriggerEditor,
|
|
2380
2475
|
RichTextTriggerTextarea,
|
|
2381
2476
|
findRichTextTriggerQuery,
|
|
2382
2477
|
isRichTextTriggerPrefixBoundary,
|
|
2383
|
-
queryRichTextTriggerMatches
|
|
2478
|
+
queryRichTextTriggerMatches,
|
|
2479
|
+
useEffectiveRichTextMentionService,
|
|
2480
|
+
useResolvedRichTextMention,
|
|
2481
|
+
useRichTextMentionService
|
|
2384
2482
|
};
|
|
2385
2483
|
//# sourceMappingURL=index.js.map
|