@alpaca-editor/core 1.0.4086 → 1.0.4089
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/components/ui/card.d.ts +1 -1
- package/dist/config/config.js +10 -3
- package/dist/config/config.js.map +1 -1
- package/dist/config/types.d.ts +4 -0
- package/dist/editor/ContentTree.js +43 -21
- package/dist/editor/ContentTree.js.map +1 -1
- package/dist/editor/FieldListField.js +12 -1
- package/dist/editor/FieldListField.js.map +1 -1
- package/dist/editor/ai/AgentTerminal.d.ts +3 -1
- package/dist/editor/ai/AgentTerminal.js +96 -74
- package/dist/editor/ai/AgentTerminal.js.map +1 -1
- package/dist/editor/ai/Agents.js +50 -2
- package/dist/editor/ai/Agents.js.map +1 -1
- package/dist/editor/ai/AiResponseMessage.js +171 -75
- package/dist/editor/ai/AiResponseMessage.js.map +1 -1
- package/dist/editor/ai/AiTerminal.js +27 -14
- package/dist/editor/ai/AiTerminal.js.map +1 -1
- package/dist/editor/client/EditorShell.js +121 -17
- package/dist/editor/client/EditorShell.js.map +1 -1
- package/dist/editor/client/editContext.d.ts +4 -0
- package/dist/editor/client/editContext.js.map +1 -1
- package/dist/editor/client/hooks/useSocketMessageHandler.d.ts +1 -0
- package/dist/editor/client/hooks/useSocketMessageHandler.js +54 -20
- package/dist/editor/client/hooks/useSocketMessageHandler.js.map +1 -1
- package/dist/editor/client/hooks/useWorkbox.d.ts +1 -1
- package/dist/editor/client/hooks/useWorkbox.js +4 -4
- package/dist/editor/client/hooks/useWorkbox.js.map +1 -1
- package/dist/editor/client/itemsRepository.d.ts +13 -1
- package/dist/editor/client/itemsRepository.js +34 -21
- package/dist/editor/client/itemsRepository.js.map +1 -1
- package/dist/editor/client/pageModelBuilder.js +1 -1
- package/dist/editor/client/pageModelBuilder.js.map +1 -1
- package/dist/editor/control-center/Setup.js +12 -223
- package/dist/editor/control-center/Setup.js.map +1 -1
- package/dist/editor/control-center/setup-steps/AiSetupStep.d.ts +2 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep.js +287 -0
- package/dist/editor/control-center/setup-steps/AiSetupStep.js.map +1 -0
- package/dist/editor/control-center/setup-steps/DbSetupStep.d.ts +2 -0
- package/dist/editor/control-center/setup-steps/DbSetupStep.js +46 -0
- package/dist/editor/control-center/setup-steps/DbSetupStep.js.map +1 -0
- package/dist/editor/control-center/setup-steps/IndexSetupStep.d.ts +2 -0
- package/dist/editor/control-center/setup-steps/IndexSetupStep.js +34 -0
- package/dist/editor/control-center/setup-steps/IndexSetupStep.js.map +1 -0
- package/dist/editor/control-center/setup-steps/SettingsSetupStep.d.ts +2 -0
- package/dist/editor/control-center/setup-steps/SettingsSetupStep.js +104 -0
- package/dist/editor/control-center/setup-steps/SettingsSetupStep.js.map +1 -0
- package/dist/editor/field-types/ImageFieldEditor.js +1 -1
- package/dist/editor/field-types/ImageFieldEditor.js.map +1 -1
- package/dist/editor/field-types/MultiLineText.js +1 -1
- package/dist/editor/field-types/MultiLineText.js.map +1 -1
- package/dist/editor/field-types/PictureFieldEditor.js +1 -1
- package/dist/editor/field-types/PictureFieldEditor.js.map +1 -1
- package/dist/editor/field-types/RawEditor.js +1 -1
- package/dist/editor/field-types/RawEditor.js.map +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js +1 -1
- package/dist/editor/field-types/RichTextEditorComponent.js.map +1 -1
- package/dist/editor/field-types/SingleLineText.js +1 -1
- package/dist/editor/field-types/SingleLineText.js.map +1 -1
- package/dist/editor/field-types/richtext/components/ReactSlate.js +2 -2
- package/dist/editor/field-types/richtext/components/ReactSlate.js.map +1 -1
- package/dist/editor/field-types/richtext/utils/profileServiceCache.d.ts +1 -1
- package/dist/editor/field-types/richtext/utils/profileServiceCache.js +16 -14
- package/dist/editor/field-types/richtext/utils/profileServiceCache.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/CompareControls.js +1 -1
- package/dist/editor/menubar/toolbar-sections/CompareControls.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/EditControls.js +1 -1
- package/dist/editor/menubar/toolbar-sections/EditControls.js.map +1 -1
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js +1 -1
- package/dist/editor/menubar/toolbar-sections/ViewportControls.js.map +1 -1
- package/dist/editor/page-editor-chrome/InlineEditor.js +25 -6
- package/dist/editor/page-editor-chrome/InlineEditor.js.map +1 -1
- package/dist/editor/page-viewer/EditorForm.js +9 -2
- package/dist/editor/page-viewer/EditorForm.js.map +1 -1
- package/dist/editor/page-viewer/PageViewerFrame.js +6 -1
- package/dist/editor/page-viewer/PageViewerFrame.js.map +1 -1
- package/dist/editor/pageModel.d.ts +1 -0
- package/dist/editor/reviews/Comment.js +1 -1
- package/dist/editor/reviews/Comment.js.map +1 -1
- package/dist/editor/reviews/CommentDisplayPopover.js +3 -24
- package/dist/editor/reviews/CommentDisplayPopover.js.map +1 -1
- package/dist/editor/reviews/CommentPopover.js +3 -23
- package/dist/editor/reviews/CommentPopover.js.map +1 -1
- package/dist/editor/reviews/CommentView.js +2 -1
- package/dist/editor/reviews/CommentView.js.map +1 -1
- package/dist/editor/reviews/Comments.js +88 -37
- package/dist/editor/reviews/Comments.js.map +1 -1
- package/dist/editor/reviews/commentAi.js +3 -0
- package/dist/editor/reviews/commentAi.js.map +1 -1
- package/dist/editor/sidebar/Debug.js +1 -5
- package/dist/editor/sidebar/Debug.js.map +1 -1
- package/dist/editor/sidebar/ViewSelector.js +72 -6
- package/dist/editor/sidebar/ViewSelector.js.map +1 -1
- package/dist/editor/ui/Icons.d.ts +5 -0
- package/dist/editor/ui/Icons.js +14 -0
- package/dist/editor/ui/Icons.js.map +1 -1
- package/dist/revision.d.ts +2 -2
- package/dist/revision.js +2 -2
- package/dist/splash-screen/SplashScreen.js +2 -2
- package/dist/splash-screen/SplashScreen.js.map +1 -1
- package/dist/styles.css +0 -5
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/ui/card.tsx +1 -1
- package/src/config/config.tsx +9 -2
- package/src/config/types.ts +5 -0
- package/src/editor/ContentTree.tsx +48 -23
- package/src/editor/FieldListField.tsx +13 -2
- package/src/editor/ai/AgentTerminal.tsx +118 -71
- package/src/editor/ai/Agents.tsx +56 -1
- package/src/editor/ai/AiResponseMessage.tsx +234 -78
- package/src/editor/ai/AiTerminal.tsx +30 -14
- package/src/editor/client/EditorShell.tsx +140 -25
- package/src/editor/client/editContext.ts +1 -0
- package/src/editor/client/hooks/useSocketMessageHandler.ts +70 -21
- package/src/editor/client/hooks/useWorkbox.ts +4 -4
- package/src/editor/client/itemsRepository.ts +56 -25
- package/src/editor/client/pageModelBuilder.ts +1 -1
- package/src/editor/control-center/Setup.tsx +14 -420
- package/src/editor/control-center/setup-steps/AiSetupStep.tsx +462 -0
- package/src/editor/control-center/setup-steps/DbSetupStep.tsx +84 -0
- package/src/editor/control-center/setup-steps/IndexSetupStep.tsx +56 -0
- package/src/editor/control-center/setup-steps/SettingsSetupStep.tsx +176 -0
- package/src/editor/field-types/ImageFieldEditor.tsx +0 -1
- package/src/editor/field-types/MultiLineText.tsx +0 -1
- package/src/editor/field-types/PictureFieldEditor.tsx +0 -1
- package/src/editor/field-types/RawEditor.tsx +0 -1
- package/src/editor/field-types/RichTextEditorComponent.tsx +0 -1
- package/src/editor/field-types/SingleLineText.tsx +0 -1
- package/src/editor/field-types/richtext/components/ReactSlate.tsx +14 -6
- package/src/editor/field-types/richtext/utils/profileServiceCache.ts +42 -32
- package/src/editor/menubar/toolbar-sections/CompareControls.tsx +1 -0
- package/src/editor/menubar/toolbar-sections/EditControls.tsx +1 -0
- package/src/editor/menubar/toolbar-sections/ViewportControls.tsx +1 -0
- package/src/editor/page-editor-chrome/InlineEditor.tsx +29 -6
- package/src/editor/page-viewer/EditorForm.tsx +13 -2
- package/src/editor/page-viewer/PageViewerFrame.tsx +5 -1
- package/src/editor/pageModel.ts +1 -0
- package/src/editor/reviews/Comment.tsx +1 -1
- package/src/editor/reviews/CommentDisplayPopover.tsx +2 -22
- package/src/editor/reviews/CommentPopover.tsx +3 -24
- package/src/editor/reviews/CommentView.tsx +3 -2
- package/src/editor/reviews/Comments.tsx +162 -35
- package/src/editor/reviews/commentAi.ts +5 -0
- package/src/editor/sidebar/Debug.tsx +1 -5
- package/src/editor/sidebar/ViewSelector.tsx +144 -28
- package/src/editor/ui/Icons.tsx +55 -0
- package/src/revision.ts +2 -2
- package/src/splash-screen/SplashScreen.tsx +5 -6
- package/src/types.ts +3 -0
|
@@ -11,10 +11,7 @@ import {
|
|
|
11
11
|
} from "../client/editContext";
|
|
12
12
|
import type { SelectionRange } from "../client/editContext";
|
|
13
13
|
import type { FieldDescriptor } from "../../types";
|
|
14
|
-
import {
|
|
15
|
-
createOrUpdateComment,
|
|
16
|
-
getAvailableCommentTags,
|
|
17
|
-
} from "../services/reviewsService";
|
|
14
|
+
import { createOrUpdateComment } from "../services/reviewsService";
|
|
18
15
|
import {
|
|
19
16
|
Popover,
|
|
20
17
|
PopoverContent,
|
|
@@ -41,11 +38,9 @@ export function CommentPopover({
|
|
|
41
38
|
}) {
|
|
42
39
|
const [isOpen, setIsOpen] = useState(!!position);
|
|
43
40
|
const [saving, setSaving] = useState(false);
|
|
44
|
-
const [availableTags, setAvailableTags] = useState<
|
|
45
|
-
{ label: string; color: string }[]
|
|
46
|
-
>([]);
|
|
47
41
|
const contextFromHook = useEditContext();
|
|
48
42
|
const editContext = externalEditContext || contextFromHook;
|
|
43
|
+
const availableTags = editContext?.availableCommentTags || [];
|
|
49
44
|
const fieldsContext = useFieldsEditContext();
|
|
50
45
|
const contentRef = React.useRef<HTMLDivElement | null>(null);
|
|
51
46
|
|
|
@@ -53,23 +48,7 @@ export function CommentPopover({
|
|
|
53
48
|
if (position) setIsOpen(true);
|
|
54
49
|
}, [position?.x, position?.y]);
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
let cancelled = false;
|
|
58
|
-
const loadTags = async () => {
|
|
59
|
-
try {
|
|
60
|
-
const descriptor = editContext?.contentEditorItem?.descriptor;
|
|
61
|
-
if (!descriptor) return;
|
|
62
|
-
const tags = await getAvailableCommentTags(descriptor);
|
|
63
|
-
if (!cancelled) setAvailableTags(tags || []);
|
|
64
|
-
} catch {
|
|
65
|
-
if (!cancelled) setAvailableTags([]);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
loadTags();
|
|
69
|
-
return () => {
|
|
70
|
-
cancelled = true;
|
|
71
|
-
};
|
|
72
|
-
}, [editContext?.contentEditorItem?.descriptor?.id]);
|
|
51
|
+
// Tags are now provided by editContext.availableCommentTags
|
|
73
52
|
|
|
74
53
|
const handleSave = async (text: string, tags: string[]) => {
|
|
75
54
|
if (!editContext || !text || saving) return;
|
|
@@ -43,7 +43,8 @@ export function CommentView({
|
|
|
43
43
|
const [resolvePopoverOpen, setResolvePopoverOpen] = React.useState(false);
|
|
44
44
|
|
|
45
45
|
const renderTags = () => {
|
|
46
|
-
|
|
46
|
+
// Canonical: parse labels from comment.tags (comma-separated string)
|
|
47
|
+
const tagLabels: string[] = (comment.tags || "")
|
|
47
48
|
.split(",")
|
|
48
49
|
.map((t) => t.trim())
|
|
49
50
|
.filter(Boolean);
|
|
@@ -192,7 +193,7 @@ export function CommentView({
|
|
|
192
193
|
>
|
|
193
194
|
<Check
|
|
194
195
|
className="h-3.5 w-3.5 text-green-500"
|
|
195
|
-
strokeWidth={
|
|
196
|
+
strokeWidth={1}
|
|
196
197
|
/>
|
|
197
198
|
</button>
|
|
198
199
|
</PopoverTrigger>
|
|
@@ -5,12 +5,21 @@ import { SuggestedEditComponent } from "./SuggestedEdit";
|
|
|
5
5
|
import { Comment as CommentType, SuggestedEdit } from "../../types";
|
|
6
6
|
import { SimpleToolbar } from "../ui/SimpleToolbar";
|
|
7
7
|
import { SimpleIconButton } from "../ui/SimpleIconButton";
|
|
8
|
+
import { Button } from "../../components/ui/button";
|
|
9
|
+
import {
|
|
10
|
+
Popover,
|
|
11
|
+
PopoverContent,
|
|
12
|
+
PopoverTrigger,
|
|
13
|
+
} from "../../components/ui/popover";
|
|
8
14
|
import {
|
|
9
15
|
FileDiff,
|
|
10
16
|
SquarePen,
|
|
11
17
|
CheckCircle,
|
|
12
18
|
CheckCircle2,
|
|
13
19
|
MessageSquareMore,
|
|
20
|
+
Plus,
|
|
21
|
+
GitBranch,
|
|
22
|
+
Tags,
|
|
14
23
|
} from "lucide-react";
|
|
15
24
|
|
|
16
25
|
// Define a union type for feedback items:
|
|
@@ -21,9 +30,29 @@ export function Comments() {
|
|
|
21
30
|
const [feedbackItems, setFeedbackItems] = useState<FeedbackItem[]>([]);
|
|
22
31
|
const [hideAppliedSuggestions, setHideAppliedSuggestions] =
|
|
23
32
|
useState<boolean>(true);
|
|
24
|
-
const [
|
|
25
|
-
{
|
|
26
|
-
|
|
33
|
+
const [selectedTagsFilter, setSelectedTagsFilter] = useState<string[]>(() => {
|
|
34
|
+
try {
|
|
35
|
+
const raw =
|
|
36
|
+
typeof window !== "undefined"
|
|
37
|
+
? localStorage.getItem("editor.comments.tagsFilter")
|
|
38
|
+
: null;
|
|
39
|
+
return raw ? (JSON.parse(raw) as string[]) : [];
|
|
40
|
+
} catch {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
const [scope, setScope] = useState<"all" | "itemOnly">(() => {
|
|
45
|
+
try {
|
|
46
|
+
const raw =
|
|
47
|
+
typeof window !== "undefined"
|
|
48
|
+
? localStorage.getItem("editor.comments.scope")
|
|
49
|
+
: null;
|
|
50
|
+
return raw === "itemOnly" ? "itemOnly" : "all";
|
|
51
|
+
} catch {
|
|
52
|
+
return "all";
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const availableTags = editContext?.availableCommentTags || [];
|
|
27
56
|
|
|
28
57
|
useEffect(() => {
|
|
29
58
|
// Retrieve your list of comments (and ensure there's an array of suggested edits,
|
|
@@ -36,47 +65,69 @@ export function Comments() {
|
|
|
36
65
|
? suggestedEdits.filter((edit) => edit.status !== "applied")
|
|
37
66
|
: suggestedEdits;
|
|
38
67
|
|
|
68
|
+
// Start with combined list
|
|
39
69
|
const combined: FeedbackItem[] = [...comments, ...filteredSuggestedEdits];
|
|
40
70
|
|
|
71
|
+
// Apply scope filter (item-only vs item + children)
|
|
72
|
+
const baseItemId =
|
|
73
|
+
(editContext?.selection && editContext.selection[0]) ||
|
|
74
|
+
editContext?.currentItemDescriptor?.id ||
|
|
75
|
+
undefined;
|
|
76
|
+
|
|
77
|
+
const scoped =
|
|
78
|
+
scope === "itemOnly" && baseItemId
|
|
79
|
+
? combined.filter((item: any) => item.itemId === baseItemId)
|
|
80
|
+
: combined;
|
|
81
|
+
|
|
82
|
+
// Apply tag filter to comments only (suggested edits do not have tags)
|
|
83
|
+
const tagFiltered = selectedTagsFilter.length
|
|
84
|
+
? scoped.filter((item: any) => {
|
|
85
|
+
// Keep suggested edits
|
|
86
|
+
if ("oldValue" in item && "newValue" in item) return true;
|
|
87
|
+
const tags = (item.tags || "")
|
|
88
|
+
.split(",")
|
|
89
|
+
.map((t: string) => t.trim())
|
|
90
|
+
.filter(Boolean);
|
|
91
|
+
// OR logic: include if any selected tag matches
|
|
92
|
+
return selectedTagsFilter.some((t) => tags.includes(t));
|
|
93
|
+
})
|
|
94
|
+
: scoped;
|
|
95
|
+
|
|
41
96
|
// Sort by creation date. Adjust the comparison as needed if the date properties differ.
|
|
42
|
-
|
|
97
|
+
tagFiltered.sort(
|
|
43
98
|
(a, b) =>
|
|
44
99
|
new Date(b.created || "").getTime() -
|
|
45
100
|
new Date(a.created || "").getTime(),
|
|
46
101
|
);
|
|
47
102
|
|
|
48
|
-
setFeedbackItems(
|
|
49
|
-
}, [editContext, hideAppliedSuggestions]);
|
|
103
|
+
setFeedbackItems(tagFiltered);
|
|
104
|
+
}, [editContext, hideAppliedSuggestions, scope, selectedTagsFilter]);
|
|
50
105
|
|
|
51
|
-
// Load available tags once per context for color mapping in child comments
|
|
52
106
|
useEffect(() => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (!cancelled) setAvailableTags([]);
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const { getAvailableCommentTags } = await import(
|
|
62
|
-
"../services/reviewsService"
|
|
107
|
+
try {
|
|
108
|
+
if (typeof window !== "undefined")
|
|
109
|
+
localStorage.setItem(
|
|
110
|
+
"editor.comments.tagsFilter",
|
|
111
|
+
JSON.stringify(selectedTagsFilter),
|
|
63
112
|
);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
113
|
+
} catch {}
|
|
114
|
+
}, [selectedTagsFilter]);
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
try {
|
|
118
|
+
if (typeof window !== "undefined")
|
|
119
|
+
localStorage.setItem("editor.comments.scope", scope);
|
|
120
|
+
} catch {}
|
|
121
|
+
}, [scope]);
|
|
122
|
+
|
|
123
|
+
// Tags are provided once via editContext.availableCommentTags
|
|
75
124
|
|
|
76
125
|
return (
|
|
77
126
|
<div className="flex h-full flex-col">
|
|
78
127
|
<div className="border-gray-3 flex-1 overflow-auto border-b">
|
|
79
128
|
<div className="h-fill-available p-4">
|
|
129
|
+
{/* Filters moved to bottom toolbar */}
|
|
130
|
+
|
|
80
131
|
{feedbackItems.map((item) => {
|
|
81
132
|
// Use a discriminator check. Here we assume suggested edits have the properties oldValue and newValue.
|
|
82
133
|
if ("oldValue" in item && "newValue" in item) {
|
|
@@ -100,7 +151,7 @@ export function Comments() {
|
|
|
100
151
|
<SimpleToolbar>
|
|
101
152
|
<SimpleIconButton
|
|
102
153
|
id="add-comment"
|
|
103
|
-
icon="
|
|
154
|
+
icon={<Plus size={16} strokeWidth={1} className="p-0.5" />}
|
|
104
155
|
label="Add Comment"
|
|
105
156
|
onClick={() => {
|
|
106
157
|
editContext?.addComment();
|
|
@@ -108,7 +159,9 @@ export function Comments() {
|
|
|
108
159
|
/>
|
|
109
160
|
<SimpleIconButton
|
|
110
161
|
selected={editContext?.showComments}
|
|
111
|
-
icon={
|
|
162
|
+
icon={
|
|
163
|
+
<MessageSquareMore size={16} strokeWidth={1} className="p-0.5" />
|
|
164
|
+
}
|
|
112
165
|
label="Show Comments"
|
|
113
166
|
onClick={() => {
|
|
114
167
|
editContext?.setShowComments((x) => !x);
|
|
@@ -116,7 +169,7 @@ export function Comments() {
|
|
|
116
169
|
/>
|
|
117
170
|
<SimpleIconButton
|
|
118
171
|
selected={editContext?.showSuggestedEdits}
|
|
119
|
-
icon={<SquarePen size={16} className="p-0.5" />}
|
|
172
|
+
icon={<SquarePen size={16} strokeWidth={1} className="p-0.5" />}
|
|
120
173
|
label="Show Suggestions"
|
|
121
174
|
onClick={() => {
|
|
122
175
|
editContext?.setShowSuggestedEdits((x) => !x);
|
|
@@ -124,7 +177,7 @@ export function Comments() {
|
|
|
124
177
|
/>
|
|
125
178
|
<SimpleIconButton
|
|
126
179
|
selected={!!editContext?.showResolvedComments}
|
|
127
|
-
icon={<CheckCircle2 size={16} className="p-0.5" />}
|
|
180
|
+
icon={<CheckCircle2 size={16} strokeWidth={1} className="p-0.5" />}
|
|
128
181
|
label={
|
|
129
182
|
editContext?.showResolvedComments
|
|
130
183
|
? "Hide Resolved Comments"
|
|
@@ -137,7 +190,7 @@ export function Comments() {
|
|
|
137
190
|
{editContext?.showSuggestedEdits && (
|
|
138
191
|
<SimpleIconButton
|
|
139
192
|
selected={editContext?.showSuggestedEditsDiff}
|
|
140
|
-
icon={<FileDiff size={16} className="p-0.5" />}
|
|
193
|
+
icon={<FileDiff size={16} strokeWidth={1} className="p-0.5" />}
|
|
141
194
|
label="Show Suggestions Diff"
|
|
142
195
|
onClick={() => {
|
|
143
196
|
editContext?.setShowSuggestedEditsDiff((x) => !x);
|
|
@@ -148,9 +201,9 @@ export function Comments() {
|
|
|
148
201
|
selected={hideAppliedSuggestions}
|
|
149
202
|
icon={
|
|
150
203
|
hideAppliedSuggestions ? (
|
|
151
|
-
<CheckCircle2 size={16} className="p-0.5" />
|
|
204
|
+
<CheckCircle2 size={16} strokeWidth={1} className="p-0.5" />
|
|
152
205
|
) : (
|
|
153
|
-
<CheckCircle size={16} className="p-0.5" />
|
|
206
|
+
<CheckCircle size={16} strokeWidth={1} className="p-0.5" />
|
|
154
207
|
)
|
|
155
208
|
}
|
|
156
209
|
label={
|
|
@@ -162,6 +215,80 @@ export function Comments() {
|
|
|
162
215
|
setHideAppliedSuggestions((x) => !x);
|
|
163
216
|
}}
|
|
164
217
|
/>
|
|
218
|
+
<div className="ml-auto flex items-center gap-2">
|
|
219
|
+
<SimpleIconButton
|
|
220
|
+
selected={scope === "all"}
|
|
221
|
+
icon={<GitBranch size={16} strokeWidth={1} className="p-0.5" />}
|
|
222
|
+
label={
|
|
223
|
+
scope === "all"
|
|
224
|
+
? "Include Children (on)"
|
|
225
|
+
: "Include Children (off)"
|
|
226
|
+
}
|
|
227
|
+
onClick={() => setScope(scope === "all" ? "itemOnly" : "all")}
|
|
228
|
+
/>
|
|
229
|
+
|
|
230
|
+
{availableTags.length > 0 && (
|
|
231
|
+
<Popover>
|
|
232
|
+
<PopoverTrigger asChild>
|
|
233
|
+
<SimpleIconButton
|
|
234
|
+
showTooltip={false}
|
|
235
|
+
selected={selectedTagsFilter.length > 0}
|
|
236
|
+
icon={<Tags size={16} strokeWidth={1} className="p-0.5" />}
|
|
237
|
+
label={
|
|
238
|
+
selectedTagsFilter.length > 0
|
|
239
|
+
? `Tags (${selectedTagsFilter.length})`
|
|
240
|
+
: "Tags"
|
|
241
|
+
}
|
|
242
|
+
onClick={() => {}}
|
|
243
|
+
/>
|
|
244
|
+
</PopoverTrigger>
|
|
245
|
+
<PopoverContent className="w-72 p-3" align="start">
|
|
246
|
+
<div className="mb-2 text-xs text-gray-600">Filter by tags</div>
|
|
247
|
+
<div className="flex flex-wrap gap-2">
|
|
248
|
+
{availableTags.map((tag) => {
|
|
249
|
+
const isSelected = selectedTagsFilter.includes(tag.label);
|
|
250
|
+
return (
|
|
251
|
+
<Button
|
|
252
|
+
key={tag.label}
|
|
253
|
+
type="button"
|
|
254
|
+
size="sm"
|
|
255
|
+
variant={isSelected ? "secondary" : "outline"}
|
|
256
|
+
className="h-6 px-2 text-xs"
|
|
257
|
+
onClick={() => {
|
|
258
|
+
setSelectedTagsFilter((prev) =>
|
|
259
|
+
prev.includes(tag.label)
|
|
260
|
+
? prev.filter((l) => l !== tag.label)
|
|
261
|
+
: [...prev, tag.label],
|
|
262
|
+
);
|
|
263
|
+
}}
|
|
264
|
+
style={{
|
|
265
|
+
borderColor: isSelected ? tag.color : undefined,
|
|
266
|
+
backgroundColor: isSelected
|
|
267
|
+
? tag.color + "22"
|
|
268
|
+
: undefined,
|
|
269
|
+
}}
|
|
270
|
+
>
|
|
271
|
+
{tag.label}
|
|
272
|
+
</Button>
|
|
273
|
+
);
|
|
274
|
+
})}
|
|
275
|
+
</div>
|
|
276
|
+
{selectedTagsFilter.length > 0 && (
|
|
277
|
+
<div className="mt-3 text-right">
|
|
278
|
+
<Button
|
|
279
|
+
size="sm"
|
|
280
|
+
variant="ghost"
|
|
281
|
+
className="h-6 px-2 text-xs"
|
|
282
|
+
onClick={() => setSelectedTagsFilter([])}
|
|
283
|
+
>
|
|
284
|
+
Clear
|
|
285
|
+
</Button>
|
|
286
|
+
</div>
|
|
287
|
+
)}
|
|
288
|
+
</PopoverContent>
|
|
289
|
+
</Popover>
|
|
290
|
+
)}
|
|
291
|
+
</div>
|
|
165
292
|
</SimpleToolbar>
|
|
166
293
|
</div>
|
|
167
294
|
);
|
|
@@ -88,6 +88,11 @@ export function openAiAgentForComment(
|
|
|
88
88
|
rangeEnd: comment.rangeEnd,
|
|
89
89
|
},
|
|
90
90
|
},
|
|
91
|
+
// Seed profile from editor settings if available
|
|
92
|
+
profileId:
|
|
93
|
+
editContext.editorSettings?.commentResolveProfileId || undefined,
|
|
94
|
+
profileName:
|
|
95
|
+
editContext.editorSettings?.commentResolveProfileName || undefined,
|
|
91
96
|
},
|
|
92
97
|
} as any;
|
|
93
98
|
|
|
@@ -34,11 +34,7 @@ export function Debug({}: {}) {
|
|
|
34
34
|
setPageLayout(layout);
|
|
35
35
|
};
|
|
36
36
|
loadLayout();
|
|
37
|
-
}, [
|
|
38
|
-
editContext.contentEditorItem,
|
|
39
|
-
editContext.itemsRepository.revision,
|
|
40
|
-
pageViewContext.isHeadless,
|
|
41
|
-
]);
|
|
37
|
+
}, [editContext.contentEditorItem, pageViewContext.isHeadless]);
|
|
42
38
|
|
|
43
39
|
const page = pageLayout; // editContext.page;
|
|
44
40
|
let component = null;
|
|
@@ -17,7 +17,14 @@ import {
|
|
|
17
17
|
TooltipProvider,
|
|
18
18
|
TooltipTrigger,
|
|
19
19
|
} from "../../components/ui/tooltip";
|
|
20
|
+
import {
|
|
21
|
+
ContextMenu,
|
|
22
|
+
ContextMenuContent,
|
|
23
|
+
ContextMenuItem,
|
|
24
|
+
ContextMenuTrigger,
|
|
25
|
+
} from "../../components/ui/context-menu";
|
|
20
26
|
import { DrawingPinFilledIcon, DrawingPinIcon } from "@radix-ui/react-icons";
|
|
27
|
+
import { Pin, PinOff } from "lucide-react";
|
|
21
28
|
|
|
22
29
|
function ViewSelectorComponent() {
|
|
23
30
|
const editContext = useEditContext();
|
|
@@ -51,6 +58,7 @@ function ViewSelectorComponent() {
|
|
|
51
58
|
);
|
|
52
59
|
|
|
53
60
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
|
61
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
54
62
|
|
|
55
63
|
const views = useMemo(() => {
|
|
56
64
|
return (
|
|
@@ -71,6 +79,22 @@ function ViewSelectorComponent() {
|
|
|
71
79
|
// Use visibleViews from editContext instead of calculating locally
|
|
72
80
|
const visibleViews = editContext?.visibleViews ?? [];
|
|
73
81
|
|
|
82
|
+
// Order visible views so pinned ones follow the user's pinnedViews order
|
|
83
|
+
const orderedVisibleViews = useMemo(() => {
|
|
84
|
+
const shown = visibleViews.filter((x) => x.icon);
|
|
85
|
+
const pinnedOrder = contextValues.pinnedViews;
|
|
86
|
+
const pinnedSet = new Set(pinnedOrder);
|
|
87
|
+
|
|
88
|
+
const pinnedOrdered = pinnedOrder
|
|
89
|
+
.map((name) => shown.find((v) => v.name === name))
|
|
90
|
+
.filter((v): v is NonNullable<typeof v> => Boolean(v));
|
|
91
|
+
|
|
92
|
+
const selected = shown.find((v) => v.name === contextValues.viewName);
|
|
93
|
+
if (selected && !pinnedSet.has(selected.name)) pinnedOrdered.push(selected);
|
|
94
|
+
|
|
95
|
+
return pinnedOrdered;
|
|
96
|
+
}, [visibleViews, contextValues.pinnedViews, contextValues.viewName]);
|
|
97
|
+
|
|
74
98
|
const togglePin = useCallback(
|
|
75
99
|
(viewName: string) => {
|
|
76
100
|
const newPinnedViews = contextValues.pinnedViews.includes(viewName)
|
|
@@ -103,11 +127,12 @@ function ViewSelectorComponent() {
|
|
|
103
127
|
|
|
104
128
|
const handleViewClick = useCallback(
|
|
105
129
|
(viewName: string) => {
|
|
130
|
+
if (isDragging) return;
|
|
106
131
|
if (viewName !== contextValues.viewName) {
|
|
107
132
|
contextValues.switchView?.(viewName);
|
|
108
133
|
}
|
|
109
134
|
},
|
|
110
|
-
[contextValues.viewName, contextValues.switchView],
|
|
135
|
+
[isDragging, contextValues.viewName, contextValues.switchView],
|
|
111
136
|
);
|
|
112
137
|
|
|
113
138
|
const handleViewClickAndClosePopover = useCallback(
|
|
@@ -126,41 +151,132 @@ function ViewSelectorComponent() {
|
|
|
126
151
|
[togglePin],
|
|
127
152
|
);
|
|
128
153
|
|
|
154
|
+
const handleDragStart = useCallback(
|
|
155
|
+
(e: React.DragEvent<HTMLDivElement>, viewName: string) => {
|
|
156
|
+
setIsDragging(true);
|
|
157
|
+
e.dataTransfer.setData("text/alpaca-view", viewName);
|
|
158
|
+
e.dataTransfer.effectAllowed = "move";
|
|
159
|
+
},
|
|
160
|
+
[],
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const handleDragEnd = useCallback(() => {
|
|
164
|
+
setIsDragging(false);
|
|
165
|
+
}, []);
|
|
166
|
+
|
|
167
|
+
const handleDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
|
168
|
+
// Allow drop
|
|
169
|
+
e.preventDefault();
|
|
170
|
+
e.dataTransfer.dropEffect = "move";
|
|
171
|
+
}, []);
|
|
172
|
+
|
|
173
|
+
const handleDrop = useCallback(
|
|
174
|
+
(e: React.DragEvent<HTMLDivElement>, targetViewName: string) => {
|
|
175
|
+
e.preventDefault();
|
|
176
|
+
const sourceViewName =
|
|
177
|
+
e.dataTransfer.getData("text/alpaca-view") ||
|
|
178
|
+
e.dataTransfer.getData("text/plain");
|
|
179
|
+
|
|
180
|
+
if (!sourceViewName || sourceViewName === targetViewName) return;
|
|
181
|
+
|
|
182
|
+
const pinned = contextValues.pinnedViews;
|
|
183
|
+
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
|
|
184
|
+
const before = e.clientY < rect.top + rect.height / 2;
|
|
185
|
+
|
|
186
|
+
// Remove source first, then insert relative to target (even if not currently pinned)
|
|
187
|
+
const newPinned = pinned.filter((n) => n !== sourceViewName);
|
|
188
|
+
const targetIndex = newPinned.indexOf(targetViewName);
|
|
189
|
+
const baseIndex = targetIndex >= 0 ? targetIndex : newPinned.length - 1;
|
|
190
|
+
const insertIndex = before
|
|
191
|
+
? Math.max(0, baseIndex)
|
|
192
|
+
: Math.max(0, baseIndex + 1);
|
|
193
|
+
|
|
194
|
+
newPinned.splice(insertIndex, 0, sourceViewName);
|
|
195
|
+
contextValues.setUserPreferences?.({ pinnedViews: newPinned });
|
|
196
|
+
},
|
|
197
|
+
[contextValues.pinnedViews, contextValues.setUserPreferences],
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// Drop between helpers
|
|
201
|
+
const handleDropBetween = useCallback(
|
|
202
|
+
(
|
|
203
|
+
e: React.DragEvent<HTMLDivElement>,
|
|
204
|
+
beforeIndex: number, // insert at this index
|
|
205
|
+
) => {
|
|
206
|
+
e.preventDefault();
|
|
207
|
+
const sourceViewName =
|
|
208
|
+
e.dataTransfer.getData("text/alpaca-view") ||
|
|
209
|
+
e.dataTransfer.getData("text/plain");
|
|
210
|
+
if (!sourceViewName) return;
|
|
211
|
+
|
|
212
|
+
const pinned = contextValues.pinnedViews;
|
|
213
|
+
const newPinned = pinned.filter((n) => n !== sourceViewName);
|
|
214
|
+
const clamped = Math.max(0, Math.min(beforeIndex, newPinned.length));
|
|
215
|
+
newPinned.splice(clamped, 0, sourceViewName);
|
|
216
|
+
contextValues.setUserPreferences?.({ pinnedViews: newPinned });
|
|
217
|
+
},
|
|
218
|
+
[contextValues.pinnedViews, contextValues.setUserPreferences],
|
|
219
|
+
);
|
|
220
|
+
|
|
129
221
|
return (
|
|
130
222
|
<TooltipProvider delayDuration={500} skipDelayDuration={0}>
|
|
131
223
|
{/* Visible views (pinned + selected) */}
|
|
132
|
-
{
|
|
133
|
-
|
|
134
|
-
|
|
224
|
+
{orderedVisibleViews.map((view, i) => {
|
|
225
|
+
const isPinned = contextValues.pinnedViews.includes(view.name);
|
|
226
|
+
return (
|
|
135
227
|
<Tooltip key={`visible-${i}`} delayDuration={500}>
|
|
136
|
-
<
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
228
|
+
<ContextMenu>
|
|
229
|
+
<ContextMenuTrigger asChild>
|
|
230
|
+
<TooltipTrigger asChild>
|
|
231
|
+
<div
|
|
232
|
+
className={classNames(
|
|
233
|
+
contextValues.viewName === view.name
|
|
234
|
+
? "active bg-theme-secondary-light text-theme-secondary rounded-sm"
|
|
235
|
+
: "text-dark hover:bg-gray-5",
|
|
236
|
+
"relative flex cursor-pointer flex-col items-center justify-center select-none",
|
|
237
|
+
contextValues.showViewNames ? "p-1" : "p-1.5",
|
|
238
|
+
contextValues.isMobile ? "flex-shrink-0" : "",
|
|
239
|
+
)}
|
|
240
|
+
data-sidebarview-name={view.name}
|
|
241
|
+
onDragOver={handleDragOver}
|
|
242
|
+
onDrop={(e) => handleDrop(e, view.name)}
|
|
243
|
+
draggable={true}
|
|
244
|
+
onDragStart={(e) => handleDragStart(e, view.name)}
|
|
245
|
+
onDragEnd={handleDragEnd}
|
|
246
|
+
onClick={() => handleViewClick(view.name)}
|
|
247
|
+
>
|
|
248
|
+
<div className={contextValues.showViewNames ? "p-0.5" : ""}>
|
|
249
|
+
{renderViewIcon(view)}
|
|
250
|
+
</div>
|
|
251
|
+
{contextValues.showViewNames && (
|
|
252
|
+
<span className="mt-1 max-w-[60px] text-center text-xs leading-tight break-words">
|
|
253
|
+
{view.title || view.name}
|
|
254
|
+
</span>
|
|
255
|
+
)}
|
|
256
|
+
</div>
|
|
257
|
+
</TooltipTrigger>
|
|
258
|
+
</ContextMenuTrigger>
|
|
259
|
+
<ContextMenuContent>
|
|
260
|
+
<ContextMenuItem
|
|
261
|
+
onSelect={() => {
|
|
262
|
+
togglePin(view.name);
|
|
263
|
+
}}
|
|
264
|
+
>
|
|
265
|
+
{isPinned ? (
|
|
266
|
+
<PinOff className="size-4" strokeWidth={1} />
|
|
267
|
+
) : (
|
|
268
|
+
<Pin className="size-4" strokeWidth={1} />
|
|
269
|
+
)}
|
|
270
|
+
{isPinned ? "Unpin view" : "Pin view"}
|
|
271
|
+
</ContextMenuItem>
|
|
272
|
+
</ContextMenuContent>
|
|
273
|
+
</ContextMenu>
|
|
159
274
|
<TooltipContent side="right">
|
|
160
275
|
{view.title || view.name}
|
|
161
276
|
</TooltipContent>
|
|
162
277
|
</Tooltip>
|
|
163
|
-
)
|
|
278
|
+
);
|
|
279
|
+
})}
|
|
164
280
|
|
|
165
281
|
{/* Three dots menu for non-selected views */}
|
|
166
282
|
{views.length > 0 && (
|
package/src/editor/ui/Icons.tsx
CHANGED
|
@@ -921,3 +921,58 @@ export function SecretAgentIcon({
|
|
|
921
921
|
</svg>
|
|
922
922
|
);
|
|
923
923
|
}
|
|
924
|
+
|
|
925
|
+
export function AnimatedSunIcon({
|
|
926
|
+
size = 36,
|
|
927
|
+
style,
|
|
928
|
+
...props
|
|
929
|
+
}: {
|
|
930
|
+
size?: number;
|
|
931
|
+
style?: React.CSSProperties;
|
|
932
|
+
props?: React.SVGProps<SVGSVGElement>;
|
|
933
|
+
}) {
|
|
934
|
+
return (
|
|
935
|
+
<svg
|
|
936
|
+
width={size}
|
|
937
|
+
height={size}
|
|
938
|
+
viewBox="0 0 24 24"
|
|
939
|
+
fill="none"
|
|
940
|
+
role="img"
|
|
941
|
+
aria-label="Animated Sun"
|
|
942
|
+
stroke="currentColor"
|
|
943
|
+
strokeWidth={1.6}
|
|
944
|
+
strokeLinecap="round"
|
|
945
|
+
strokeLinejoin="round"
|
|
946
|
+
style={style}
|
|
947
|
+
{...props}
|
|
948
|
+
>
|
|
949
|
+
<style>{`
|
|
950
|
+
@media (prefers-reduced-motion: reduce) {
|
|
951
|
+
.sun-spin { animation: none !important; }
|
|
952
|
+
}
|
|
953
|
+
.sun-spin {
|
|
954
|
+
transform-origin: 12px 12px;
|
|
955
|
+
animation: sun-rotate 8s linear infinite;
|
|
956
|
+
}
|
|
957
|
+
@keyframes sun-rotate {
|
|
958
|
+
to { transform: rotate(360deg); }
|
|
959
|
+
}
|
|
960
|
+
`}</style>
|
|
961
|
+
|
|
962
|
+
{/* Rays spin */}
|
|
963
|
+
<g className="sun-spin">
|
|
964
|
+
<line x1="12" y1="2.5" x2="12" y2="4.2" />
|
|
965
|
+
<line x1="12" y1="19.8" x2="12" y2="21.5" />
|
|
966
|
+
<line x1="4.2" y1="12" x2="2.5" y2="12" />
|
|
967
|
+
<line x1="21.5" y1="12" x2="19.8" y2="12" />
|
|
968
|
+
<line x1="5.6" y1="5.6" x2="4.4" y2="4.4" />
|
|
969
|
+
<line x1="19.6" y1="19.6" x2="18.4" y2="18.4" />
|
|
970
|
+
<line x1="5.6" y1="18.4" x2="4.4" y2="19.6" />
|
|
971
|
+
<line x1="19.6" y1="4.4" x2="18.4" y2="5.6" />
|
|
972
|
+
</g>
|
|
973
|
+
|
|
974
|
+
{/* Core stays still */}
|
|
975
|
+
<circle cx="12" cy="12" r="4.2" />
|
|
976
|
+
</svg>
|
|
977
|
+
);
|
|
978
|
+
}
|
package/src/revision.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const version = "1.0.
|
|
2
|
-
export const buildDate = "2025-09-
|
|
1
|
+
export const version = "1.0.4089";
|
|
2
|
+
export const buildDate = "2025-09-16 09:23:08";
|