@agent-native/core 0.137.1 → 0.137.3
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/corpus/README.md +1 -1
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +258 -0
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +130 -0
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +25 -337
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +73 -53
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +804 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +101 -45
- package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +7 -4
- package/corpus/templates/slides/app/components/editor/bullet-editing.ts +11 -3
- package/corpus/templates/slides/app/components/editor/commit-active-edit.ts +21 -0
- package/corpus/templates/slides/app/components/editor/list-editing.ts +219 -0
- package/corpus/templates/slides/app/components/editor/selection-overlay-measurement.ts +0 -3
- package/corpus/templates/slides/app/components/editor/slide-style.ts +199 -0
- package/corpus/templates/slides/app/global.css +14 -3
- package/corpus/templates/slides/app/i18n/en-US.ts +8 -1
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +48 -22
- package/corpus/templates/slides/changelog/2026-08-01-add-slide-moved-to-the-toolbar-and-the-slide-rail-is-now-mor.md +9 -0
- package/corpus/templates/slides/changelog/2026-08-01-add-slide-undo-redo-and-the-text-tool-now-lead-the-slide-too.md +9 -0
- package/corpus/templates/slides/changelog/2026-08-01-slide-styling-now-appears-in-a-contextual-toolbar-above-the-.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-01-the-slide-style-side-panel-is-retired-all-styling-now-lives-.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-03-the-slide-toolbar-is-denser-swatch-only-colors-dropdowns-for.md +10 -0
- package/corpus/templates/slides/changelog/2026-08-04-bullet-and-numbered-list-buttons-in-the-slide-toolbar-conver.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-04-italic-and-underline-are-now-one-click-away-in-the-slide-too.md +6 -0
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +2 -2
- package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +0 -763
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { DesignSystemData } from "@shared/api";
|
|
2
|
+
|
|
3
|
+
import type { InlineTextStyleKey } from "./rich-text-selection";
|
|
4
|
+
|
|
5
|
+
export interface SlideStyleSnapshot {
|
|
6
|
+
/** Omitted snapshots are existing object snapshots for backward compatibility. */
|
|
7
|
+
mode?: "object";
|
|
8
|
+
selector: string;
|
|
9
|
+
label: string;
|
|
10
|
+
tagName: string;
|
|
11
|
+
textPreview: string;
|
|
12
|
+
isText: boolean;
|
|
13
|
+
isImage: boolean;
|
|
14
|
+
isAbsolute: boolean;
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
rotation: number;
|
|
20
|
+
slideWidth: number;
|
|
21
|
+
slideHeight: number;
|
|
22
|
+
color: string;
|
|
23
|
+
backgroundColor: string;
|
|
24
|
+
fontSize: number;
|
|
25
|
+
fontWeight: string;
|
|
26
|
+
fontStyle: string;
|
|
27
|
+
textDecoration: string;
|
|
28
|
+
lineHeight: number;
|
|
29
|
+
textAlign: string;
|
|
30
|
+
opacity: number;
|
|
31
|
+
borderRadius: number;
|
|
32
|
+
borderWidth: number;
|
|
33
|
+
borderColor: string;
|
|
34
|
+
paddingX: number;
|
|
35
|
+
paddingY: number;
|
|
36
|
+
zIndex: number;
|
|
37
|
+
listKind: "bullet" | "ordered" | null;
|
|
38
|
+
textStyleScope?: "block" | "selection";
|
|
39
|
+
mixedTextStyles?: InlineTextStyleKey[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type SlideStylePatch = Partial<{
|
|
43
|
+
color: string;
|
|
44
|
+
backgroundColor: string;
|
|
45
|
+
fontSize: string;
|
|
46
|
+
fontWeight: string;
|
|
47
|
+
fontStyle: string;
|
|
48
|
+
textDecoration: string;
|
|
49
|
+
lineHeight: string;
|
|
50
|
+
textAlign: string;
|
|
51
|
+
opacity: string;
|
|
52
|
+
borderRadius: string;
|
|
53
|
+
borderWidth: string;
|
|
54
|
+
borderColor: string;
|
|
55
|
+
paddingLeft: string;
|
|
56
|
+
paddingRight: string;
|
|
57
|
+
paddingTop: string;
|
|
58
|
+
paddingBottom: string;
|
|
59
|
+
left: string;
|
|
60
|
+
top: string;
|
|
61
|
+
width: string;
|
|
62
|
+
height: string;
|
|
63
|
+
transform: string;
|
|
64
|
+
zIndex: string;
|
|
65
|
+
}>;
|
|
66
|
+
|
|
67
|
+
export function tokenPalette(
|
|
68
|
+
designSystem: DesignSystemData | undefined,
|
|
69
|
+
t: (key: string) => string,
|
|
70
|
+
) {
|
|
71
|
+
const colors = designSystem?.colors;
|
|
72
|
+
const base = colors
|
|
73
|
+
? [
|
|
74
|
+
{
|
|
75
|
+
label: t("styleInspector.primary"),
|
|
76
|
+
value: colors.primary,
|
|
77
|
+
color: colors.primary,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
label: t("styleInspector.secondary"),
|
|
81
|
+
value: colors.secondary,
|
|
82
|
+
color: colors.secondary,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
label: t("styleInspector.accent"),
|
|
86
|
+
value: colors.accent,
|
|
87
|
+
color: colors.accent,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
label: t("styleInspector.surface"),
|
|
91
|
+
value: colors.surface,
|
|
92
|
+
color: colors.surface,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: t("styleInspector.background"),
|
|
96
|
+
value: colors.background,
|
|
97
|
+
color: colors.background,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
label: t("styleInspector.text"),
|
|
101
|
+
value: colors.text,
|
|
102
|
+
color: colors.text,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
label: t("styleInspector.muted"),
|
|
106
|
+
value: colors.textMuted,
|
|
107
|
+
color: colors.textMuted,
|
|
108
|
+
},
|
|
109
|
+
]
|
|
110
|
+
: [];
|
|
111
|
+
|
|
112
|
+
// Fixed swatches offered when a deck has no design system. These are
|
|
113
|
+
// document colors the user paints onto slide content, so they must stay
|
|
114
|
+
// literal — theming them would repaint finished decks on a theme switch.
|
|
115
|
+
const presets: Array<[key: string, hex: string]> = [
|
|
116
|
+
["white", "#ffffff"], // guard:allow-raw-color
|
|
117
|
+
["black", "#000000"], // guard:allow-raw-color
|
|
118
|
+
["slate", "#1f2937"], // guard:allow-raw-color
|
|
119
|
+
["blue", "#609ff8"], // guard:allow-raw-color
|
|
120
|
+
["cyan", "#22d3ee"], // guard:allow-raw-color
|
|
121
|
+
["emerald", "#34d399"], // guard:allow-raw-color
|
|
122
|
+
["amber", "#fbbf24"], // guard:allow-raw-color
|
|
123
|
+
["rose", "#fb7185"], // guard:allow-raw-color
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
return [
|
|
127
|
+
...base,
|
|
128
|
+
...presets.map(([key, hex]) => ({
|
|
129
|
+
label: t(`styleInspector.${key}`),
|
|
130
|
+
value: hex,
|
|
131
|
+
color: hex,
|
|
132
|
+
})),
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// `slide.background` holds either a raw CSS value or a Tailwind arbitrary
|
|
137
|
+
// class (`bg-[...]`), which SlideRenderer applies as a class rather than
|
|
138
|
+
// an inline style. The picker only speaks CSS colors, so unwrap the arbitrary
|
|
139
|
+
// form and report anything else (named utilities, gradients) as unreadable
|
|
140
|
+
// rather than guessing a hex the slide is not actually using.
|
|
141
|
+
export function backgroundCssValue(
|
|
142
|
+
background: string | undefined,
|
|
143
|
+
): string | null {
|
|
144
|
+
// guard:allow-raw-color — mirrors SlideRenderer's own default slide fill
|
|
145
|
+
if (!background) return "#000000";
|
|
146
|
+
const arbitrary = background.match(/^bg-\[(.+)\]$/);
|
|
147
|
+
if (arbitrary) return arbitrary[1].replace(/_/g, " ");
|
|
148
|
+
return background.startsWith("bg-") ? null : background;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function formatValue(value: number) {
|
|
152
|
+
return Number.isInteger(value)
|
|
153
|
+
? String(value)
|
|
154
|
+
: String(Number(value.toFixed(2)));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function rotationTransform(rotation: number) {
|
|
158
|
+
return `rotate(${formatValue(rotation)}deg)`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function resolveHorizontalAlignment(snapshot: SlideStyleSnapshot) {
|
|
162
|
+
if (snapshot.x <= 0) return "left";
|
|
163
|
+
const centered = (snapshot.slideWidth - snapshot.width) / 2;
|
|
164
|
+
return Math.abs(snapshot.x - centered) < 1 ? "center" : "right";
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function resolveVerticalAlignment(snapshot: SlideStyleSnapshot) {
|
|
168
|
+
if (snapshot.y <= 0) return "top";
|
|
169
|
+
const centered = (snapshot.slideHeight - snapshot.height) / 2;
|
|
170
|
+
return Math.abs(snapshot.y - centered) < 1 ? "middle" : "bottom";
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function horizontalAlignPatch(
|
|
174
|
+
snapshot: SlideStyleSnapshot,
|
|
175
|
+
alignment: string,
|
|
176
|
+
): SlideStylePatch {
|
|
177
|
+
const available = Math.max(0, snapshot.slideWidth - snapshot.width);
|
|
178
|
+
const x =
|
|
179
|
+
alignment === "left"
|
|
180
|
+
? 0
|
|
181
|
+
: alignment === "center"
|
|
182
|
+
? available / 2
|
|
183
|
+
: available;
|
|
184
|
+
return { left: `${formatValue(x)}px` };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function verticalAlignPatch(
|
|
188
|
+
snapshot: SlideStyleSnapshot,
|
|
189
|
+
alignment: string,
|
|
190
|
+
): SlideStylePatch {
|
|
191
|
+
const available = Math.max(0, snapshot.slideHeight - snapshot.height);
|
|
192
|
+
const y =
|
|
193
|
+
alignment === "top"
|
|
194
|
+
? 0
|
|
195
|
+
: alignment === "middle"
|
|
196
|
+
? available / 2
|
|
197
|
+
: available;
|
|
198
|
+
return { top: `${formatValue(y)}px` };
|
|
199
|
+
}
|
|
@@ -109,9 +109,10 @@ button[title="Open agent sidebar"] {
|
|
|
109
109
|
--accent-cyan: 193 82% 31%;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
/* Slides keeps the shared visual inspector behavior, but the dock
|
|
112
|
+
/* Slides keeps the shared visual inspector behavior, but the dock and context toolbar need the
|
|
113
113
|
flatter, filled-control treatment used by the slide editor. */
|
|
114
|
-
.slide-style-inspector
|
|
114
|
+
.slide-style-inspector,
|
|
115
|
+
.slide-context-toolbar {
|
|
115
116
|
--slides-inspector-control-background: hsl(var(--muted) / 0.82);
|
|
116
117
|
--slides-inspector-divider: hsl(var(--border) / 0.7);
|
|
117
118
|
--design-editor-control-bg: var(--slides-inspector-control-background);
|
|
@@ -161,11 +162,21 @@ button[title="Open agent sidebar"] {
|
|
|
161
162
|
box-shadow: none;
|
|
162
163
|
}
|
|
163
164
|
|
|
165
|
+
/* The toolbar sits on a muted surface, so its inputs need the opposite
|
|
166
|
+
treatment to stay readable: a light box rather than a darker fill. */
|
|
167
|
+
.slide-context-toolbar input {
|
|
168
|
+
border: 1px solid var(--slides-inspector-divider);
|
|
169
|
+
border-radius: 0.25rem;
|
|
170
|
+
background: hsl(var(--background));
|
|
171
|
+
box-shadow: none;
|
|
172
|
+
}
|
|
173
|
+
|
|
164
174
|
.slide-style-inspector input:focus {
|
|
165
175
|
border: 0;
|
|
166
176
|
}
|
|
167
177
|
|
|
168
|
-
.slide-style-inspector .slides-inspector-segment
|
|
178
|
+
.slide-style-inspector .slides-inspector-segment,
|
|
179
|
+
.slide-context-toolbar .slides-inspector-segment {
|
|
169
180
|
min-height: 1.5rem;
|
|
170
181
|
border: 0;
|
|
171
182
|
border-radius: 0.125rem;
|
|
@@ -404,6 +404,14 @@ const messages = {
|
|
|
404
404
|
cornerRadius: "Corner radius",
|
|
405
405
|
strokeWeight: "Weight",
|
|
406
406
|
typography: "Typography",
|
|
407
|
+
weight: "Weight",
|
|
408
|
+
italic: "Italic",
|
|
409
|
+
underline: "Underline",
|
|
410
|
+
bulletList: "Bullet list",
|
|
411
|
+
numberedList: "Numbered list",
|
|
412
|
+
align: "Align",
|
|
413
|
+
decreaseSize: "Decrease font size",
|
|
414
|
+
increaseSize: "Increase font size",
|
|
407
415
|
mixed: "Mixed",
|
|
408
416
|
textColor: "Text color",
|
|
409
417
|
primary: "Primary",
|
|
@@ -501,7 +509,6 @@ const messages = {
|
|
|
501
509
|
noAi: "no AI",
|
|
502
510
|
duplicateCurrentSlide: "Duplicate current slide",
|
|
503
511
|
promptPlaceholder: "Describe the slides you want...",
|
|
504
|
-
slides: "Slides",
|
|
505
512
|
},
|
|
506
513
|
presentation: {
|
|
507
514
|
loadFailed: "Could not load this presentation.",
|
|
@@ -31,6 +31,7 @@ import { SlideCommentsPanel } from "@/components/comments/SlideCommentsPanel";
|
|
|
31
31
|
import { AnimationsPanel } from "@/components/editor/AnimationsPanel";
|
|
32
32
|
import AssetLibraryPanel from "@/components/editor/AssetLibraryPanel";
|
|
33
33
|
import { DeckEditorSkeleton } from "@/components/editor/DeckEditorSkeleton";
|
|
34
|
+
import { EditorActionCluster } from "@/components/editor/EditorActionCluster";
|
|
34
35
|
import EditorSidebar from "@/components/editor/EditorSidebar";
|
|
35
36
|
import EditorToolbar from "@/components/editor/EditorToolbar";
|
|
36
37
|
import GeneratingOverlay from "@/components/editor/GeneratingOverlay";
|
|
@@ -78,7 +79,7 @@ import { TAB_ID } from "@/lib/tab-id";
|
|
|
78
79
|
import { shouldActivateTextTool } from "@/lib/text-tool-shortcut";
|
|
79
80
|
import { shortcutLabel } from "@/lib/utils";
|
|
80
81
|
|
|
81
|
-
type EditorSidePanel = "
|
|
82
|
+
type EditorSidePanel = "comments" | null;
|
|
82
83
|
|
|
83
84
|
function MissingDeckAccessPane({
|
|
84
85
|
hasTeamJoinOption,
|
|
@@ -184,6 +185,8 @@ export default function DeckEditor() {
|
|
|
184
185
|
const [sidebarOpen, setSidebarOpen] = useState(
|
|
185
186
|
() => typeof window !== "undefined" && window.innerWidth >= 768,
|
|
186
187
|
);
|
|
188
|
+
const [contextToolbarSlot, setContextToolbarSlot] =
|
|
189
|
+
useState<HTMLDivElement | null>(null);
|
|
187
190
|
const [retryingMissingDeck, setRetryingMissingDeck] = useState(false);
|
|
188
191
|
const [checkedDeckAccessKey, setCheckedDeckAccessKey] = useState<
|
|
189
192
|
string | null
|
|
@@ -285,7 +288,6 @@ export default function DeckEditor() {
|
|
|
285
288
|
});
|
|
286
289
|
const { designSystem } = useDeckDesignSystem(deck?.designSystemId);
|
|
287
290
|
const commentsOpen = sidePanel === "comments";
|
|
288
|
-
const styleOpen = sidePanel === "style";
|
|
289
291
|
|
|
290
292
|
const {
|
|
291
293
|
questions: questionFlowQuestions,
|
|
@@ -330,6 +332,12 @@ export default function DeckEditor() {
|
|
|
330
332
|
if (!generatingSlideVisible) setGeneratingSlideSelected(false);
|
|
331
333
|
}, [generatingSlideVisible]);
|
|
332
334
|
|
|
335
|
+
// The add-slide request is finished once the agent stops generating, so the
|
|
336
|
+
// rail's placeholder must not outlive it.
|
|
337
|
+
useEffect(() => {
|
|
338
|
+
if (!generating) setAddSlideGenerating(false);
|
|
339
|
+
}, [generating]);
|
|
340
|
+
|
|
333
341
|
const previousSlideCountRef = useRef(slideCount);
|
|
334
342
|
useEffect(() => {
|
|
335
343
|
if (previousSlideCountRef.current === slideCount) return;
|
|
@@ -941,6 +949,13 @@ export default function DeckEditor() {
|
|
|
941
949
|
? `Current slide: ${currentSlide.id} (index ${currentIndex >= 0 ? currentIndex : 0}). Deck: ${id}.`
|
|
942
950
|
: `Deck: ${id}.`;
|
|
943
951
|
|
|
952
|
+
const handleAddEmptySlide = () => {
|
|
953
|
+
const activeIdx = deck.slides.findIndex((s) => s.id === activeSlideId);
|
|
954
|
+
setActiveSlideId(
|
|
955
|
+
addSlide(id, "blank", activeIdx >= 0 ? activeIdx : undefined),
|
|
956
|
+
);
|
|
957
|
+
};
|
|
958
|
+
|
|
944
959
|
return (
|
|
945
960
|
<div
|
|
946
961
|
className="flex h-full min-h-0 flex-1 flex-col overflow-hidden bg-background"
|
|
@@ -978,10 +993,6 @@ export default function DeckEditor() {
|
|
|
978
993
|
onToggleComments={() =>
|
|
979
994
|
setSidePanel((panel) => (panel === "comments" ? null : "comments"))
|
|
980
995
|
}
|
|
981
|
-
styleOpen={styleOpen}
|
|
982
|
-
onToggleStyle={() =>
|
|
983
|
-
setSidePanel((panel) => (panel === "style" ? null : "style"))
|
|
984
|
-
}
|
|
985
996
|
unresolvedCommentCount={unresolvedCommentCount}
|
|
986
997
|
currentUserEmail={session?.email}
|
|
987
998
|
animationsOpen={animationsOpen}
|
|
@@ -1052,8 +1063,19 @@ export default function DeckEditor() {
|
|
|
1052
1063
|
updateDeck(id, { aspectRatio: previous });
|
|
1053
1064
|
});
|
|
1054
1065
|
}}
|
|
1066
|
+
currentSlideId={currentSlide?.id}
|
|
1067
|
+
addSlideGenerating={addSlideGenerating}
|
|
1068
|
+
onAddSlideGeneratingChange={setAddSlideGenerating}
|
|
1069
|
+
onAddEmptySlide={handleAddEmptySlide}
|
|
1070
|
+
onDuplicateCurrentSlide={
|
|
1071
|
+
currentSlide ? () => duplicateSlide(id, currentSlide.id) : undefined
|
|
1072
|
+
}
|
|
1055
1073
|
/>
|
|
1056
1074
|
|
|
1075
|
+
{/* Full-width host for the slide's contextual style toolbar: it spans the
|
|
1076
|
+
* slide rail as well as the canvas, matching the deck toolbar above it. */}
|
|
1077
|
+
<div ref={setContextToolbarSlot} className="shrink-0" />
|
|
1078
|
+
|
|
1057
1079
|
<div className="relative flex min-h-0 flex-1 overflow-hidden">
|
|
1058
1080
|
{sidebarOpen && (
|
|
1059
1081
|
<>
|
|
@@ -1071,24 +1093,12 @@ export default function DeckEditor() {
|
|
|
1071
1093
|
slides={deck.slides}
|
|
1072
1094
|
activeSlideId={currentSlide?.id || ""}
|
|
1073
1095
|
deckId={id}
|
|
1074
|
-
deckTitle={deck.title}
|
|
1075
1096
|
onSelectSlide={(slideId) => {
|
|
1076
1097
|
setGeneratingSlideSelected(false);
|
|
1077
1098
|
setActiveSlideId(slideId);
|
|
1078
1099
|
if (window.innerWidth < 768) setSidebarOpen(false);
|
|
1079
1100
|
}}
|
|
1080
1101
|
onDuplicateSlide={(slideId) => duplicateSlide(id, slideId)}
|
|
1081
|
-
onAddEmptySlide={() => {
|
|
1082
|
-
const activeIdx = deck.slides.findIndex(
|
|
1083
|
-
(s) => s.id === activeSlideId,
|
|
1084
|
-
);
|
|
1085
|
-
const newId = addSlide(
|
|
1086
|
-
id,
|
|
1087
|
-
"blank",
|
|
1088
|
-
activeIdx >= 0 ? activeIdx : undefined,
|
|
1089
|
-
);
|
|
1090
|
-
setActiveSlideId(newId);
|
|
1091
|
-
}}
|
|
1092
1102
|
onDeleteSlide={(slideId) => {
|
|
1093
1103
|
const idx = deck.slides.findIndex((s) => s.id === slideId);
|
|
1094
1104
|
const nextSlide =
|
|
@@ -1113,8 +1123,6 @@ export default function DeckEditor() {
|
|
|
1113
1123
|
setGeneratingSlideSelected(true);
|
|
1114
1124
|
if (window.innerWidth < 768) setSidebarOpen(false);
|
|
1115
1125
|
}}
|
|
1116
|
-
addSlideGenerating={addSlideGenerating}
|
|
1117
|
-
onAddSlideGeneratingChange={setAddSlideGenerating}
|
|
1118
1126
|
/>
|
|
1119
1127
|
</DndContext>
|
|
1120
1128
|
</div>
|
|
@@ -1165,6 +1173,26 @@ export default function DeckEditor() {
|
|
|
1165
1173
|
slide={currentSlide}
|
|
1166
1174
|
deckId={id}
|
|
1167
1175
|
readOnly={!canEdit}
|
|
1176
|
+
contextToolbarSlot={contextToolbarSlot}
|
|
1177
|
+
contextToolbarLeading={
|
|
1178
|
+
canEdit ? (
|
|
1179
|
+
<EditorActionCluster
|
|
1180
|
+
deckId={id}
|
|
1181
|
+
deckTitle={deck.title}
|
|
1182
|
+
currentSlideId={currentSlide.id}
|
|
1183
|
+
slideCount={deck.slides.length}
|
|
1184
|
+
currentSlideIndex={currentIndex >= 0 ? currentIndex : 0}
|
|
1185
|
+
addSlideGenerating={addSlideGenerating}
|
|
1186
|
+
onAddSlideGeneratingChange={setAddSlideGenerating}
|
|
1187
|
+
onAddEmptySlide={handleAddEmptySlide}
|
|
1188
|
+
onDuplicateCurrentSlide={() =>
|
|
1189
|
+
duplicateSlide(id, currentSlide.id)
|
|
1190
|
+
}
|
|
1191
|
+
textBoxMode={textBoxMode}
|
|
1192
|
+
onToggleTextBoxMode={toggleTextBoxMode}
|
|
1193
|
+
/>
|
|
1194
|
+
) : undefined
|
|
1195
|
+
}
|
|
1168
1196
|
onUpdateSlide={(updates, slideIdOverride, options) =>
|
|
1169
1197
|
updateSlide(
|
|
1170
1198
|
id,
|
|
@@ -1197,8 +1225,6 @@ export default function DeckEditor() {
|
|
|
1197
1225
|
slideIndex={currentIndex >= 0 ? currentIndex : 0}
|
|
1198
1226
|
slideCount={deck.slides.length}
|
|
1199
1227
|
designSystem={designSystem}
|
|
1200
|
-
stylePanelOpen={styleOpen}
|
|
1201
|
-
onCloseStylePanel={() => setSidePanel(null)}
|
|
1202
1228
|
aspectRatio={deck.aspectRatio}
|
|
1203
1229
|
collabUser={
|
|
1204
1230
|
currentUser
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: changed
|
|
3
|
+
date: 2026-08-01
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Adding a slide now starts from a `+` at the head of the editor toolbar, next to
|
|
7
|
+
the deck title, instead of a header above the slide thumbnails. The rail itself
|
|
8
|
+
drops that header, tucks the drag handle onto the thumbnail on hover, and is
|
|
9
|
+
narrower — so more slides fit on screen and the canvas gets the width back.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: changed
|
|
3
|
+
date: 2026-08-01
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The contextual slide toolbar now opens with the actions that never change: add
|
|
7
|
+
slide, undo, redo, and the text-box tool. Undo and redo previously worked only
|
|
8
|
+
through Cmd+Z with no visible control; clicking them commits whatever text you
|
|
9
|
+
are editing first, so nothing you just typed is lost.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: changed
|
|
3
|
+
date: 2026-08-03
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Colour controls in the slide toolbar are now just the swatch, with no hex code
|
|
7
|
+
beside it. Font weight and text alignment collapsed from four buttons each into
|
|
8
|
+
a single control with a dropdown, and alignment uses standard icons instead of
|
|
9
|
+
words. Undo and redo moved out of the toolbar into the overflow menu, since
|
|
10
|
+
Cmd+Z already covers the common case.
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
error: string;
|
|
17
16
|
ok?: undefined;
|
|
17
|
+
error: string;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -41,16 +41,16 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
+
error?: undefined;
|
|
44
45
|
summary: import("./types.js").TraceSummary;
|
|
45
46
|
spans: import("./types.js").TraceSpan[];
|
|
46
47
|
id?: undefined;
|
|
47
|
-
error?: undefined;
|
|
48
48
|
ok?: undefined;
|
|
49
49
|
} | {
|
|
50
|
+
error?: undefined;
|
|
50
51
|
summary?: undefined;
|
|
51
52
|
spans?: undefined;
|
|
52
53
|
id: string;
|
|
53
|
-
error?: undefined;
|
|
54
54
|
ok?: undefined;
|
|
55
55
|
} | {
|
|
56
56
|
summary?: undefined;
|
|
@@ -59,10 +59,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
59
59
|
error: any;
|
|
60
60
|
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
|
+
error?: undefined;
|
|
62
63
|
summary?: undefined;
|
|
63
64
|
spans?: undefined;
|
|
64
65
|
id?: undefined;
|
|
65
|
-
error?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|
|
68
68
|
//# sourceMappingURL=routes.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.137.
|
|
3
|
+
"version": "0.137.3",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -401,7 +401,7 @@
|
|
|
401
401
|
"yjs": "^13.6.31",
|
|
402
402
|
"zod": "^4.3.6",
|
|
403
403
|
"@agent-native/recap-cli": "0.5.3",
|
|
404
|
-
"@agent-native/toolkit": "^0.
|
|
404
|
+
"@agent-native/toolkit": "^0.13.0"
|
|
405
405
|
},
|
|
406
406
|
"devDependencies": {
|
|
407
407
|
"@ai-sdk/anthropic": "^3.0.71",
|