Triggers revamp (#212)

* Simplify composio trigger name to be computed directly from Slug

* Show log and friendly name in composio trigger cards

* Standardize buttons in all trigger creation flows

* Update trigger cards look

* Remove extra ring around fields in trigger config form

* Add copilot welcome message

* Update copilot welcome message

* Fix @ mentions deletion glitch
This commit is contained in:
Akhilesh Sudhakar 2025-08-19 21:35:03 +08:00 committed by GitHub
parent 82e8b6fadf
commit 9bee30aade
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 201 additions and 161 deletions

View file

@ -251,7 +251,7 @@ function TextInputField({
<div className="w-full min-h-[300px]">
<MentionsEditor
atValues={mentionsAtValues}
value={value}
value={localValue}
placeholder={placeholder}
onValueChange={setLocalValue}
autoFocus
@ -337,14 +337,14 @@ function TextInputField({
"whitespace-pre-wrap": multiline,
"flex items-center": !multiline,
})}>
{value ? (
{(mentions ? localValue : value) ? (
<>
{markdown ? (
<div className={clsx("prose prose-sm max-w-none", {
"max-h-[420px] overflow-y-auto": multiline
})}>
<MarkdownContent
content={value}
content={mentions ? localValue : value}
atValues={mentionsAtValues}
onMentionNavigate={handleMentionNavigate}
/>
@ -355,7 +355,7 @@ function TextInputField({
"max-h-[420px] overflow-y-auto": multiline
})}>
<MarkdownContent
content={value}
content={mentions ? localValue : value}
atValues={mentionsAtValues}
onMentionNavigate={handleMentionNavigate}
/>

View file

@ -97,13 +97,20 @@ export default function MentionEditor({
}) {
const containerRef = useRef<HTMLDivElement>(null);
const quillRef = useRef<Quill | null>(null);
const atValuesRef = useRef<Match[]>(atValues);
const onValueChangeRef = useRef<typeof onValueChange>(onValueChange);
const externalValueRef = useRef<string>(value);
const isApplyingExternalRef = useRef<boolean>(false);
function getMarkdown(): string {
if (!quillRef.current) {
return "";
}
// generate markdown representation of content
const markdown = quillRef.current.getContents().map((op) => {
const delta = quillRef.current.getContents() as unknown as Delta;
// Quill Delta has .ops
const ops: any[] = (delta as any).ops || [];
const markdown = ops.map((op) => {
if (op.insert && typeof op.insert === 'object' && 'mention' in op.insert) {
const mentionOp = op.insert as { mention: Match };
return `[@${mentionOp.mention.id}](#mention)`;
@ -120,6 +127,20 @@ export default function MentionEditor({
navigator.clipboard.writeText(getMarkdown());
}
// Keep refs up to date without re-initializing Quill
useEffect(() => {
atValuesRef.current = atValues;
}, [atValues]);
useEffect(() => {
onValueChangeRef.current = onValueChange;
}, [onValueChange]);
useEffect(() => {
externalValueRef.current = value;
}, [value]);
// Initialize Quill once
useEffect(() => {
if (!containerRef.current) {
return;
@ -140,15 +161,14 @@ export default function MentionEditor({
mentionDenotationChars: ["@"],
showDenotationChar: true,
source: async function (searchTerm: string, renderList: (values: Match[], searchTerm: string) => void) {
const list = atValuesRef.current || [];
if (searchTerm.length === 0) {
renderList(atValues, searchTerm);
renderList(list, searchTerm);
} else {
const matches = [];
for (let i = 0; i < atValues.length; i++) {
if (
atValues[i].value.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1
) {
matches.push(atValues[i]);
const matches: Match[] = [];
for (let i = 0; i < list.length; i++) {
if (list[i].value.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1) {
matches.push(list[i]);
}
}
renderList(matches, searchTerm);
@ -165,15 +185,18 @@ export default function MentionEditor({
});
// clear the quill contents
quill.setContents([]);
quill.setText('', Quill.sources.SILENT);
// convert the markdown to parts
const parts = markdownToParts(value, atValues);
const parts = markdownToParts(externalValueRef.current, atValuesRef.current);
insertPartsIntoQuill(quill, parts);
quill.on(Quill.events.TEXT_CHANGE, (delta: Delta, oldDelta: Delta, source: string) => {
if (onValueChange) {
onValueChange(getMarkdown());
if (isApplyingExternalRef.current) {
return;
}
if (onValueChangeRef.current) {
onValueChangeRef.current(getMarkdown());
}
});
quillRef.current = quill;
@ -193,7 +216,22 @@ export default function MentionEditor({
quillRef.current.off(Quill.events.TEXT_CHANGE);
}
}
}, [atValues, onValueChange, placeholder, value, autoFocus]);
// Mount once
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// Sync external value into the editor without re-initializing
useEffect(() => {
if (!quillRef.current) return;
const current = getMarkdown();
if (value === current) return;
const quill = quillRef.current;
isApplyingExternalRef.current = true;
quill.setText('', Quill.sources.SILENT);
const parts = markdownToParts(value, atValuesRef.current);
insertPartsIntoQuill(quill, parts);
isApplyingExternalRef.current = false;
}, [value]);
return <div className="relative">
<button className="absolute top-2 right-2 z-10">