@agent-native/core 0.153.10 → 0.154.0
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/analytics/AGENTS.md +20 -30
- package/corpus/templates/analytics/actions/search-dashboard-references.ts +58 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/analytics/app/lib/utils.ts +1 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewSqlPopover.tsx +1 -1
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +2 -0
- package/corpus/templates/analytics/server/lib/dashboards-store.ts +366 -3
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +3 -1
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +6 -2
- package/corpus/templates/calendar/app/components/calendar/EventDialog.tsx +1 -1
- package/corpus/templates/calendar/app/lib/utils.ts +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +32 -5
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +15 -15
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -3
- package/corpus/templates/clips/app/lib/utils.ts +5 -6
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +43 -8
- package/corpus/templates/clips/desktop/src/app.tsx +26 -12
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +23 -9
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +261 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +21 -3
- package/corpus/templates/clips/shared/mic-audio-cleanup.ts +350 -0
- package/corpus/templates/content/app/i18n-data.ts +10 -10
- package/corpus/templates/content/scripts/check-native-deps.mjs +181 -15
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +79 -7
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +14 -2
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +2 -2
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +35 -11
- package/corpus/templates/design/actions/get-design-system.ts +103 -3
- package/corpus/templates/design/actions/import-design-tokens.ts +37 -8
- package/corpus/templates/design/actions/import-github.ts +32 -138
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +49 -16
- package/corpus/templates/design/actions/present-design-variants.ts +93 -4
- package/corpus/templates/design/actions/run-design-audit.ts +229 -0
- package/corpus/templates/design/actions/sync-design-system-with-builder.ts +64 -0
- package/corpus/templates/design/app/components/design/code-workbench/commands.ts +2 -2
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +17 -4
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +5 -1
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +5 -1
- package/corpus/templates/design/app/hooks/use-question-flow.ts +81 -5
- package/corpus/templates/design/app/i18n/en-US.ts +1 -1
- package/corpus/templates/design/app/i18n-data.ts +32 -1
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +10 -10
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +83 -11
- package/corpus/templates/design/app/pages/DesignSystems.tsx +14 -0
- package/corpus/templates/design/app/pages/design-editor/generation-prompt-directives.ts +22 -0
- package/corpus/templates/design/changelog/2026-08-13-a-screen-that-would-render-behind-an-invisible-alpine-overla.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-attach-a-ui-screenshot-and-the-design-is-reproduced-not-rein.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-linking-a-design-system-means-you-never-get-generic-directio.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-audit-now-reports-when-a-screen-ignores-its-linke.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-the-design-system-preview-now-shows-how-many-named-tokens-we.md +6 -0
- package/corpus/templates/design/changelog/2026-08-13-your-design-system-prompt-and-reference-screenshots-now-reac.md +6 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +18 -2
- package/corpus/templates/design/shared/design-review.ts +1 -0
- package/corpus/templates/design/shared/html-integrity.ts +171 -0
- package/corpus/templates/mail/app/lib/utils.ts +1 -1
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +10 -6
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +41 -3
- package/corpus/templates/slides/actions/sync-design-system-with-builder.ts +64 -0
- package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -1
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +193 -20
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +58 -33
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +28 -41
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +119 -91
- package/corpus/templates/slides/app/components/editor/ImageOverlay.tsx +16 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +158 -31
- package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +30 -14
- package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +2 -2
- package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +4 -1
- package/corpus/templates/slides/app/components/editor/rich-text-selection.ts +14 -0
- package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +24 -0
- package/corpus/templates/slides/app/global.css +24 -0
- package/corpus/templates/slides/app/hooks/use-navigation-state.ts +5 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +19 -10
- package/corpus/templates/slides/app/lib/deck-filter.ts +47 -0
- package/corpus/templates/slides/app/lib/export-google-slides-client.ts +15 -4
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +637 -1
- package/corpus/templates/slides/app/lib/image-download.ts +84 -0
- package/corpus/templates/slides/app/lib/utils.ts +1 -1
- package/corpus/templates/slides/app/pages/Index.tsx +25 -9
- package/corpus/templates/slides/netlify.toml +1 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +14 -2
- package/dist/agent/production-agent.js +1 -1
- package/dist/brand-kit/types.d.ts +10 -2
- package/dist/cli/code.js +1 -1
- package/dist/cli/index.js +30 -1
- package/dist/cli/native-dependencies.d.ts +24 -0
- package/dist/cli/native-dependencies.js +264 -0
- package/dist/cli/plan-local.js +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
- package/dist/cli/skills-content/design-visual-edit-skill.js +2 -2
- package/dist/cli/visualize-repo.js +1 -1
- package/dist/client/FeedbackButton.js +12 -12
- package/dist/client/agent-chat-adapter.js +3 -4
- package/dist/client/assistant-ui-recovery.d.ts +1 -1
- package/dist/client/assistant-ui-recovery.js +4 -0
- package/dist/client/chat/message-components.d.ts +11 -3
- package/dist/client/chat/message-components.js +31 -5
- package/dist/client/chat/tool-call-display.d.ts +2 -1
- package/dist/client/chat/tool-call-display.js +33 -15
- package/dist/client/db-admin/SqlEditor.js +1 -1
- package/dist/client/dev-overlay/DevOverlay.js +2 -2
- package/dist/client/extensions/portable-extension.js +4 -0
- package/dist/client/guided-questions.d.ts +8 -0
- package/dist/client/guided-questions.js +12 -3
- package/dist/client/sharing/ShareButton.js +16 -24
- package/dist/client/sse-event-processor.js +35 -15
- package/dist/client/tool-display.d.ts +9 -0
- package/dist/client/tool-display.js +39 -0
- package/dist/client/vite-dev-recovery-script.js +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/extensions/html-shell.js +5 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/agent-chat/prompt-resources.js +17 -16
- package/dist/server/agent-chat-plugin.d.ts +9 -0
- package/dist/server/agent-chat-plugin.js +29 -7
- package/dist/server/builder-design-systems.d.ts +33 -1
- package/dist/server/builder-design-systems.js +293 -11
- package/dist/server/design-token-utils.d.ts +11 -0
- package/dist/server/design-token-utils.js +68 -16
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +3 -3
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
IconCheck,
|
|
20
20
|
IconExternalLink,
|
|
21
21
|
IconChevronDown,
|
|
22
|
+
IconRefresh,
|
|
22
23
|
} from "@tabler/icons-react";
|
|
23
24
|
import { useState, useCallback, useEffect, useRef, useMemo } from "react";
|
|
24
25
|
import { toast } from "sonner";
|
|
@@ -59,6 +60,8 @@ interface DesignSystemSetupProps {
|
|
|
59
60
|
interface GitHubLink {
|
|
60
61
|
id: string;
|
|
61
62
|
url: string;
|
|
63
|
+
ref?: string;
|
|
64
|
+
include?: string[];
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
interface UploadedFile {
|
|
@@ -81,6 +84,13 @@ interface BuilderSourceDetails {
|
|
|
81
84
|
tokenValues?: Record<string, string>;
|
|
82
85
|
docCount?: number;
|
|
83
86
|
warning?: string;
|
|
87
|
+
githubSources?: Array<{
|
|
88
|
+
repoUrl: string;
|
|
89
|
+
ref?: string;
|
|
90
|
+
include?: string[];
|
|
91
|
+
exclude?: string[];
|
|
92
|
+
}>;
|
|
93
|
+
syncedAt?: string;
|
|
84
94
|
}
|
|
85
95
|
|
|
86
96
|
interface ExistingDesignSystem {
|
|
@@ -91,6 +101,25 @@ interface ExistingDesignSystem {
|
|
|
91
101
|
builder?: BuilderSourceDetails | null;
|
|
92
102
|
}
|
|
93
103
|
|
|
104
|
+
interface BuilderIndexInput {
|
|
105
|
+
projectName?: string;
|
|
106
|
+
description?: string;
|
|
107
|
+
githubSources?: Array<{
|
|
108
|
+
repoUrl: string;
|
|
109
|
+
ref?: string;
|
|
110
|
+
include?: string[];
|
|
111
|
+
exclude?: string[];
|
|
112
|
+
}>;
|
|
113
|
+
githubRepoUrl?: string;
|
|
114
|
+
codeFiles?: Array<{
|
|
115
|
+
filename: string;
|
|
116
|
+
content: string;
|
|
117
|
+
mimeType?: string;
|
|
118
|
+
encoding?: "utf8" | "base64";
|
|
119
|
+
}>;
|
|
120
|
+
designMd?: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
94
123
|
type OtherSource = "brand" | "code" | "files" | "existing" | "context";
|
|
95
124
|
|
|
96
125
|
function normalizeWebsiteUrlInput(input: string): string | null {
|
|
@@ -134,6 +163,8 @@ export function DesignSystemSetup({
|
|
|
134
163
|
const [websiteUrl, setWebsiteUrl] = useState("");
|
|
135
164
|
const [websiteUrls, setWebsiteUrls] = useState<string[]>([]);
|
|
136
165
|
const [githubUrl, setGithubUrl] = useState("");
|
|
166
|
+
const [githubRef, setGithubRef] = useState("");
|
|
167
|
+
const [githubPaths, setGithubPaths] = useState("");
|
|
137
168
|
const [githubLinks, setGithubLinks] = useState<GitHubLink[]>([]);
|
|
138
169
|
const [codeFiles, setCodeFiles] = useState<UploadedFile[]>([]);
|
|
139
170
|
const [docFiles, setDocFiles] = useState<UploadedFile[]>([]);
|
|
@@ -211,6 +242,13 @@ export function DesignSystemSetup({
|
|
|
211
242
|
const imageInputRef = useRef<HTMLInputElement>(null);
|
|
212
243
|
const figInputRef = useRef<HTMLInputElement>(null);
|
|
213
244
|
const updateSystemMutation = useActionMutation("update-design-system");
|
|
245
|
+
const syncSystemMutation = useActionMutation(
|
|
246
|
+
"sync-design-system-with-builder",
|
|
247
|
+
);
|
|
248
|
+
const indexSystemMutation = useActionMutation<
|
|
249
|
+
BuilderIndexResult,
|
|
250
|
+
BuilderIndexInput
|
|
251
|
+
>("index-design-system-with-builder");
|
|
214
252
|
|
|
215
253
|
const {
|
|
216
254
|
data: existingDs,
|
|
@@ -267,6 +305,8 @@ export function DesignSystemSetup({
|
|
|
267
305
|
setWebsiteUrl("");
|
|
268
306
|
setWebsiteUrls([]);
|
|
269
307
|
setGithubUrl("");
|
|
308
|
+
setGithubRef("");
|
|
309
|
+
setGithubPaths("");
|
|
270
310
|
setGithubLinks([]);
|
|
271
311
|
setCodeFiles([]);
|
|
272
312
|
setDocFiles([]);
|
|
@@ -323,9 +363,23 @@ export function DesignSystemSetup({
|
|
|
323
363
|
const addGithubLink = useCallback(() => {
|
|
324
364
|
const url = githubUrl.trim();
|
|
325
365
|
if (!url) return;
|
|
326
|
-
|
|
366
|
+
const include = githubPaths
|
|
367
|
+
.split(/[\n,]/)
|
|
368
|
+
.map((path) => path.trim().replace(/^\/+|\/+$/g, ""))
|
|
369
|
+
.filter(Boolean);
|
|
370
|
+
setGithubLinks((prev) => [
|
|
371
|
+
...prev,
|
|
372
|
+
{
|
|
373
|
+
id: crypto.randomUUID(),
|
|
374
|
+
url,
|
|
375
|
+
...(githubRef.trim() ? { ref: githubRef.trim() } : {}),
|
|
376
|
+
...(include.length > 0 ? { include: [...new Set(include)] } : {}),
|
|
377
|
+
},
|
|
378
|
+
]);
|
|
327
379
|
setGithubUrl("");
|
|
328
|
-
|
|
380
|
+
setGithubRef("");
|
|
381
|
+
setGithubPaths("");
|
|
382
|
+
}, [githubPaths, githubRef, githubUrl]);
|
|
329
383
|
|
|
330
384
|
const readTextFiles = useCallback(
|
|
331
385
|
(
|
|
@@ -432,12 +486,66 @@ export function DesignSystemSetup({
|
|
|
432
486
|
}
|
|
433
487
|
};
|
|
434
488
|
|
|
489
|
+
const handleSync = useCallback(async () => {
|
|
490
|
+
if (!editingId || !existingDs?.builder?.githubSources?.length) return;
|
|
491
|
+
setGenerating(true);
|
|
492
|
+
try {
|
|
493
|
+
await syncSystemMutation.mutateAsync({ id: editingId });
|
|
494
|
+
toast.success(t("designSystemSetup.syncStarted"));
|
|
495
|
+
} catch (error) {
|
|
496
|
+
toast.error(t("designSystemSetup.syncFailed"), {
|
|
497
|
+
description:
|
|
498
|
+
error instanceof Error
|
|
499
|
+
? error.message
|
|
500
|
+
: t("designSystemSetup.syncFailed"),
|
|
501
|
+
});
|
|
502
|
+
} finally {
|
|
503
|
+
setGenerating(false);
|
|
504
|
+
}
|
|
505
|
+
}, [editingId, existingDs, syncSystemMutation, t]);
|
|
506
|
+
|
|
435
507
|
const handleGenerate = useCallback(async () => {
|
|
436
508
|
if (editingId) {
|
|
437
509
|
await handleEditSave();
|
|
438
510
|
return;
|
|
439
511
|
}
|
|
440
512
|
|
|
513
|
+
const isGithubOnlySource =
|
|
514
|
+
githubLinks.length > 0 &&
|
|
515
|
+
websiteUrls.length === 0 &&
|
|
516
|
+
codeFiles.length === 0 &&
|
|
517
|
+
!builderIndexResult &&
|
|
518
|
+
docFiles.length === 0 &&
|
|
519
|
+
imageFiles.length === 0 &&
|
|
520
|
+
!selectedSystemId &&
|
|
521
|
+
!brandNotes.trim() &&
|
|
522
|
+
!customInstructions.trim();
|
|
523
|
+
if (isGithubOnlySource) {
|
|
524
|
+
setGenerating(true);
|
|
525
|
+
try {
|
|
526
|
+
await indexSystemMutation.mutateAsync({
|
|
527
|
+
projectName: companyName.trim() || undefined,
|
|
528
|
+
githubSources: githubLinks.map((link) => ({
|
|
529
|
+
repoUrl: link.url,
|
|
530
|
+
...(link.ref ? { ref: link.ref } : {}),
|
|
531
|
+
...(link.include?.length ? { include: link.include } : {}),
|
|
532
|
+
})),
|
|
533
|
+
});
|
|
534
|
+
toast.success(t("designSystemSetup.generationStarted"));
|
|
535
|
+
onComplete();
|
|
536
|
+
} catch (error) {
|
|
537
|
+
toast.error(t("designSystemSetup.updateFailed"), {
|
|
538
|
+
description:
|
|
539
|
+
error instanceof Error
|
|
540
|
+
? error.message
|
|
541
|
+
: t("designSystemSetup.updateFailed"),
|
|
542
|
+
});
|
|
543
|
+
} finally {
|
|
544
|
+
setGenerating(false);
|
|
545
|
+
}
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
|
|
441
549
|
const requestedTitle = companyName.trim();
|
|
442
550
|
const localDesignSystemId = builderIndexResult?.localDesignSystemId;
|
|
443
551
|
if (requestedTitle && localDesignSystemId) {
|
|
@@ -485,7 +593,15 @@ export function DesignSystemSetup({
|
|
|
485
593
|
|
|
486
594
|
if (githubLinks.length > 0) {
|
|
487
595
|
parts.push(
|
|
488
|
-
`\n## Connect Code: GitHub Repositories\
|
|
596
|
+
`\n## Connect Code: GitHub Repositories\nMake one call to \`index-design-system-with-builder\` with \`githubSources\` set to this JSON array:\n\n\`\`\`json\n${JSON.stringify(
|
|
597
|
+
githubLinks.map((link) => ({
|
|
598
|
+
repoUrl: link.url,
|
|
599
|
+
...(link.ref ? { ref: link.ref } : {}),
|
|
600
|
+
...(link.include?.length ? { include: link.include } : {}),
|
|
601
|
+
})),
|
|
602
|
+
null,
|
|
603
|
+
2,
|
|
604
|
+
)}\n\`\`\`\n\nBuilder is the source of truth for repo/code design-system indexing. The action creates one local selectable proxy design system for Slides flows. If Builder is not connected, stop and tell me to connect Builder (free tier available) from Settings.`,
|
|
489
605
|
);
|
|
490
606
|
}
|
|
491
607
|
|
|
@@ -610,6 +726,7 @@ export function DesignSystemSetup({
|
|
|
610
726
|
onComplete,
|
|
611
727
|
t,
|
|
612
728
|
updateSystemMutation,
|
|
729
|
+
indexSystemMutation,
|
|
613
730
|
existingDs,
|
|
614
731
|
]);
|
|
615
732
|
|
|
@@ -651,7 +768,16 @@ export function DesignSystemSetup({
|
|
|
651
768
|
</div>
|
|
652
769
|
|
|
653
770
|
{editingId && existingDs?.builder ? (
|
|
654
|
-
<BuilderSourceStatus
|
|
771
|
+
<BuilderSourceStatus
|
|
772
|
+
builder={existingDs.builder}
|
|
773
|
+
onSync={
|
|
774
|
+
existingDs.builder.githubSources?.length &&
|
|
775
|
+
existingDs.builder.sourceKind !== "mixed"
|
|
776
|
+
? handleSync
|
|
777
|
+
: undefined
|
|
778
|
+
}
|
|
779
|
+
syncing={syncSystemMutation.isPending}
|
|
780
|
+
/>
|
|
655
781
|
) : null}
|
|
656
782
|
|
|
657
783
|
{!editingId && (
|
|
@@ -895,8 +1021,28 @@ export function DesignSystemSetup({
|
|
|
895
1021
|
{t("designSystemSetup.add")}
|
|
896
1022
|
</Button>
|
|
897
1023
|
</div>
|
|
1024
|
+
<div className="grid gap-2 sm:grid-cols-2">
|
|
1025
|
+
<Input
|
|
1026
|
+
value={githubRef}
|
|
1027
|
+
onChange={(e) => setGithubRef(e.target.value)}
|
|
1028
|
+
placeholder={t("designSystemSetup.githubRef")}
|
|
1029
|
+
aria-label={t("designSystemSetup.githubRef")}
|
|
1030
|
+
className="bg-accent border-border text-foreground placeholder:text-muted-foreground"
|
|
1031
|
+
/>
|
|
1032
|
+
<Input
|
|
1033
|
+
value={githubPaths}
|
|
1034
|
+
onChange={(e) => setGithubPaths(e.target.value)}
|
|
1035
|
+
placeholder={t("designSystemSetup.githubPaths")}
|
|
1036
|
+
aria-label={t("designSystemSetup.githubPaths")}
|
|
1037
|
+
className="bg-accent border-border text-foreground placeholder:text-muted-foreground"
|
|
1038
|
+
/>
|
|
1039
|
+
</div>
|
|
898
1040
|
<TagList
|
|
899
|
-
items={githubLinks.map((l) =>
|
|
1041
|
+
items={githubLinks.map((l) =>
|
|
1042
|
+
[l.url, l.ref, l.include?.join(", ")]
|
|
1043
|
+
.filter(Boolean)
|
|
1044
|
+
.join(" · "),
|
|
1045
|
+
)}
|
|
900
1046
|
onRemove={(i) =>
|
|
901
1047
|
setGithubLinks((p) => p.filter((_, j) => j !== i))
|
|
902
1048
|
}
|
|
@@ -1253,7 +1399,15 @@ function SourceAccordionRow({
|
|
|
1253
1399
|
);
|
|
1254
1400
|
}
|
|
1255
1401
|
|
|
1256
|
-
function BuilderSourceStatus({
|
|
1402
|
+
function BuilderSourceStatus({
|
|
1403
|
+
builder,
|
|
1404
|
+
onSync,
|
|
1405
|
+
syncing = false,
|
|
1406
|
+
}: {
|
|
1407
|
+
builder: BuilderSourceDetails;
|
|
1408
|
+
onSync?: () => void;
|
|
1409
|
+
syncing?: boolean;
|
|
1410
|
+
}) {
|
|
1257
1411
|
const t = useT();
|
|
1258
1412
|
const docs = builder.docCount ?? builder.docs?.length ?? 0;
|
|
1259
1413
|
const tokens = Object.keys(builder.tokenValues ?? {}).length;
|
|
@@ -1357,20 +1511,39 @@ function BuilderSourceStatus({ builder }: { builder: BuilderSourceDetails }) {
|
|
|
1357
1511
|
{statusTitle}
|
|
1358
1512
|
</div>
|
|
1359
1513
|
</div>
|
|
1360
|
-
{builder.builderUrl ? (
|
|
1361
|
-
<div className="mt-3 border-t border-border pt-3">
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1514
|
+
{builder.builderUrl || onSync ? (
|
|
1515
|
+
<div className="mt-3 flex flex-wrap items-center gap-3 border-t border-border pt-3">
|
|
1516
|
+
{builder.builderUrl ? (
|
|
1517
|
+
<a
|
|
1518
|
+
href={withBuilderUtmTrackingParams(builder.builderUrl, {
|
|
1519
|
+
campaign: "product",
|
|
1520
|
+
content: "design_system_intelligence",
|
|
1521
|
+
})}
|
|
1522
|
+
target="_blank"
|
|
1523
|
+
rel="noreferrer"
|
|
1524
|
+
className="inline-flex items-center gap-1.5 text-xs font-medium text-foreground underline-offset-4 hover:underline"
|
|
1525
|
+
>
|
|
1526
|
+
{t("designSystemSetup.sourceOpenInBuilder")}
|
|
1527
|
+
<IconExternalLink className="size-3.5" />
|
|
1528
|
+
</a>
|
|
1529
|
+
) : null}
|
|
1530
|
+
{onSync ? (
|
|
1531
|
+
<Button
|
|
1532
|
+
type="button"
|
|
1533
|
+
variant="ghost"
|
|
1534
|
+
size="sm"
|
|
1535
|
+
onClick={onSync}
|
|
1536
|
+
disabled={syncing}
|
|
1537
|
+
className="h-7 gap-1.5 px-2 text-xs"
|
|
1538
|
+
>
|
|
1539
|
+
<IconRefresh
|
|
1540
|
+
className={cn("size-3.5", syncing && "animate-spin")}
|
|
1541
|
+
/>
|
|
1542
|
+
{syncing
|
|
1543
|
+
? t("designSystemSetup.syncingSource")
|
|
1544
|
+
: t("designSystemSetup.syncSource")}
|
|
1545
|
+
</Button>
|
|
1546
|
+
) : null}
|
|
1374
1547
|
</div>
|
|
1375
1548
|
) : null}
|
|
1376
1549
|
</section>
|
|
@@ -17,8 +17,7 @@ import {
|
|
|
17
17
|
import { CSS } from "@dnd-kit/utilities";
|
|
18
18
|
import { appStateKeyForBrowserTab } from "@shared/app-state-tabs";
|
|
19
19
|
import { hashSlideContent, type DeckFitState } from "@shared/slide-fit";
|
|
20
|
-
import {
|
|
21
|
-
import { useCallback } from "react";
|
|
20
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
22
21
|
|
|
23
22
|
import SlideRenderer from "@/components/deck/SlideRenderer";
|
|
24
23
|
import type { SlideOverflowInfo } from "@/components/deck/SlideRenderer";
|
|
@@ -34,6 +33,7 @@ import { getAspectRatioDims, type AspectRatio } from "@/lib/aspect-ratios";
|
|
|
34
33
|
import { TAB_ID } from "@/lib/tab-id";
|
|
35
34
|
|
|
36
35
|
import type { DesignSystemData } from "../../../shared/api";
|
|
36
|
+
import { isSlideTextEditingTarget } from "./slide-text-targets";
|
|
37
37
|
|
|
38
38
|
interface EditorSidebarProps {
|
|
39
39
|
slides: Slide[];
|
|
@@ -317,6 +317,7 @@ export default function EditorSidebar({
|
|
|
317
317
|
generatingSlideSelected = false,
|
|
318
318
|
onSelectGeneratingSlide,
|
|
319
319
|
}: EditorSidebarProps) {
|
|
320
|
+
const [thumbnailListScrolled, setThumbnailListScrolled] = useState(false);
|
|
320
321
|
const slideButtonRefs = useRef(new Map<string, HTMLButtonElement>());
|
|
321
322
|
const measurementsRef = useRef(
|
|
322
323
|
new Map<
|
|
@@ -391,6 +392,10 @@ export default function EditorSidebar({
|
|
|
391
392
|
measurementsRef.current.clear();
|
|
392
393
|
}, [deckId, aspectRatio]);
|
|
393
394
|
|
|
395
|
+
useEffect(() => {
|
|
396
|
+
setThumbnailListScrolled(false);
|
|
397
|
+
}, [deckId]);
|
|
398
|
+
|
|
394
399
|
useEffect(() => {
|
|
395
400
|
return () => {
|
|
396
401
|
if (writeTimerRef.current) clearTimeout(writeTimerRef.current);
|
|
@@ -419,12 +424,20 @@ export default function EditorSidebar({
|
|
|
419
424
|
useEffect(() => {
|
|
420
425
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
421
426
|
if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
|
|
422
|
-
//
|
|
427
|
+
// Text editing and selected canvas objects own arrow keys. The marker
|
|
428
|
+
// query also covers a transient focus loss after a native selection.
|
|
423
429
|
const tag = (e.target as HTMLElement)?.tagName;
|
|
424
430
|
if (
|
|
425
431
|
tag === "INPUT" ||
|
|
426
432
|
tag === "TEXTAREA" ||
|
|
427
|
-
(
|
|
433
|
+
isSlideTextEditingTarget(
|
|
434
|
+
e.target,
|
|
435
|
+
document.activeElement,
|
|
436
|
+
document.querySelector(
|
|
437
|
+
'[contenteditable="true"], [data-editing-block="true"]',
|
|
438
|
+
),
|
|
439
|
+
) ||
|
|
440
|
+
document.querySelector('[data-slide-element-selected="true"]')
|
|
428
441
|
)
|
|
429
442
|
return;
|
|
430
443
|
|
|
@@ -454,39 +467,51 @@ export default function EditorSidebar({
|
|
|
454
467
|
|
|
455
468
|
return (
|
|
456
469
|
<div className="flex h-full min-h-0 w-48 flex-shrink-0 flex-col bg-background sm:w-52">
|
|
457
|
-
<div
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
470
|
+
<div
|
|
471
|
+
className="relative min-h-0 flex-1"
|
|
472
|
+
data-slides-thumbnail-scroll={
|
|
473
|
+
thumbnailListScrolled ? "scrolled" : "top"
|
|
474
|
+
}
|
|
475
|
+
>
|
|
476
|
+
<div
|
|
477
|
+
className="h-full min-h-0 space-y-1 overflow-y-auto overscroll-contain p-2"
|
|
478
|
+
onScroll={(event) => {
|
|
479
|
+
setThumbnailListScrolled(event.currentTarget.scrollTop > 1);
|
|
480
|
+
}}
|
|
461
481
|
>
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
482
|
+
<SortableContext
|
|
483
|
+
items={slides.map((s) => s.id)}
|
|
484
|
+
strategy={verticalListSortingStrategy}
|
|
485
|
+
>
|
|
486
|
+
{slides.map((slide, index) => (
|
|
487
|
+
<SortableSlideThumb
|
|
488
|
+
key={slide.id}
|
|
489
|
+
slide={slide}
|
|
490
|
+
index={index}
|
|
491
|
+
isActive={slide.id === activeSlideId}
|
|
492
|
+
onSelect={() => onSelectSlide(slide.id)}
|
|
493
|
+
readOnly={readOnly}
|
|
494
|
+
registerButtonRef={registerSlideButton}
|
|
495
|
+
presenceUsers={slidePresence?.get(slide.id) ?? []}
|
|
496
|
+
aspectRatio={aspectRatio}
|
|
497
|
+
designSystem={designSystem}
|
|
498
|
+
aiEditing={aiEditedSlideIds.has(slide.id)}
|
|
499
|
+
onOverflowChange={(info) =>
|
|
500
|
+
handleSlideOverflowChange(slide, info)
|
|
501
|
+
}
|
|
502
|
+
/>
|
|
503
|
+
))}
|
|
504
|
+
</SortableContext>
|
|
505
|
+
{generatingSlide && (
|
|
506
|
+
<GeneratingSlideSkeleton
|
|
507
|
+
index={generatingSlide.index}
|
|
472
508
|
aspectRatio={aspectRatio}
|
|
473
509
|
designSystem={designSystem}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
handleSlideOverflowChange(slide, info)
|
|
477
|
-
}
|
|
510
|
+
selected={generatingSlideSelected}
|
|
511
|
+
onSelect={onSelectGeneratingSlide}
|
|
478
512
|
/>
|
|
479
|
-
)
|
|
480
|
-
</
|
|
481
|
-
{generatingSlide && (
|
|
482
|
-
<GeneratingSlideSkeleton
|
|
483
|
-
index={generatingSlide.index}
|
|
484
|
-
aspectRatio={aspectRatio}
|
|
485
|
-
designSystem={designSystem}
|
|
486
|
-
selected={generatingSlideSelected}
|
|
487
|
-
onSelect={onSelectGeneratingSlide}
|
|
488
|
-
/>
|
|
489
|
-
)}
|
|
513
|
+
)}
|
|
514
|
+
</div>
|
|
490
515
|
</div>
|
|
491
516
|
</div>
|
|
492
517
|
);
|
|
@@ -31,7 +31,6 @@ import {
|
|
|
31
31
|
IconCode,
|
|
32
32
|
IconCopy,
|
|
33
33
|
IconFileTypePdf,
|
|
34
|
-
IconPlugConnected,
|
|
35
34
|
} from "@tabler/icons-react";
|
|
36
35
|
import { useTheme } from "next-themes";
|
|
37
36
|
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
@@ -439,24 +438,14 @@ export default function EditorToolbar({
|
|
|
439
438
|
},
|
|
440
439
|
);
|
|
441
440
|
if (onExportGoogleSlides) {
|
|
442
|
-
commands.push(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
},
|
|
451
|
-
{
|
|
452
|
-
id: "open-in-google-slides",
|
|
453
|
-
group: "deck",
|
|
454
|
-
label: t("editorExport.openInGoogleSlides"),
|
|
455
|
-
keywords: ["google", "slides", "export"],
|
|
456
|
-
icon: IconBrandGoogle,
|
|
457
|
-
run: () => void exportMenuRef.current?.exportGoogleSlides(),
|
|
458
|
-
},
|
|
459
|
-
);
|
|
441
|
+
commands.push({
|
|
442
|
+
id: "export-to-google-slides",
|
|
443
|
+
group: "deck",
|
|
444
|
+
label: t("editorExport.openInGoogleSlides"),
|
|
445
|
+
keywords: ["google", "slides", "export"],
|
|
446
|
+
icon: IconBrandGoogle,
|
|
447
|
+
run: () => void exportMenuRef.current?.exportGoogleSlides(),
|
|
448
|
+
});
|
|
460
449
|
}
|
|
461
450
|
if (onDuplicateDeck) {
|
|
462
451
|
commands.push({
|
|
@@ -632,7 +621,7 @@ export default function EditorToolbar({
|
|
|
632
621
|
agentActive={agentActive}
|
|
633
622
|
showAgentEditingDot={false}
|
|
634
623
|
currentUserEmail={currentUserEmail}
|
|
635
|
-
className="flex-shrink-0 mr-0.5"
|
|
624
|
+
className="ml-auto flex-shrink-0 mr-0.5 pl-2"
|
|
636
625
|
/>
|
|
637
626
|
|
|
638
627
|
{/* Consolidated editor menu */}
|
|
@@ -657,26 +646,8 @@ export default function EditorToolbar({
|
|
|
657
646
|
</Tooltip>
|
|
658
647
|
<DropdownMenuContent
|
|
659
648
|
align="end"
|
|
660
|
-
className="max-h-[
|
|
649
|
+
className="max-h-[90vh] w-64 overflow-y-auto"
|
|
661
650
|
>
|
|
662
|
-
{canEdit && (
|
|
663
|
-
<>
|
|
664
|
-
<DropdownMenuLabel>
|
|
665
|
-
{t("editorToolbar.media")}
|
|
666
|
-
</DropdownMenuLabel>
|
|
667
|
-
<DropdownMenuGroup>
|
|
668
|
-
<DropdownMenuItem onSelect={onGenerateImage}>
|
|
669
|
-
<IconPhoto className="size-4" />
|
|
670
|
-
{t("editorToolbar.generateImage")}
|
|
671
|
-
</DropdownMenuItem>
|
|
672
|
-
<DropdownMenuItem onSelect={onOpenAssetLibrary}>
|
|
673
|
-
<IconFolderOpen className="size-4" />
|
|
674
|
-
{t("editorToolbar.assetLibrary")}
|
|
675
|
-
</DropdownMenuItem>
|
|
676
|
-
</DropdownMenuGroup>
|
|
677
|
-
</>
|
|
678
|
-
)}
|
|
679
|
-
|
|
680
651
|
{((canEdit &&
|
|
681
652
|
(onToggleAnimations || onToggleTweaks || onToggleDrawMode)) ||
|
|
682
653
|
(canComment && onTogglePinMode)) && (
|
|
@@ -742,12 +713,28 @@ export default function EditorToolbar({
|
|
|
742
713
|
</>
|
|
743
714
|
)}
|
|
744
715
|
|
|
745
|
-
{
|
|
716
|
+
{canEdit && (
|
|
746
717
|
<>
|
|
747
718
|
<DropdownMenuSeparator />
|
|
748
719
|
<DropdownMenuLabel>
|
|
749
|
-
{t("editorToolbar.
|
|
720
|
+
{t("editorToolbar.media")}
|
|
750
721
|
</DropdownMenuLabel>
|
|
722
|
+
<DropdownMenuGroup>
|
|
723
|
+
<DropdownMenuItem onSelect={onGenerateImage}>
|
|
724
|
+
<IconPhoto className="size-4" />
|
|
725
|
+
{t("editorToolbar.generateImage")}
|
|
726
|
+
</DropdownMenuItem>
|
|
727
|
+
<DropdownMenuItem onSelect={onOpenAssetLibrary}>
|
|
728
|
+
<IconFolderOpen className="size-4" />
|
|
729
|
+
{t("editorToolbar.assetLibrary")}
|
|
730
|
+
</DropdownMenuItem>
|
|
731
|
+
</DropdownMenuGroup>
|
|
732
|
+
</>
|
|
733
|
+
)}
|
|
734
|
+
|
|
735
|
+
{onToggleComments && (
|
|
736
|
+
<>
|
|
737
|
+
<DropdownMenuSeparator />
|
|
751
738
|
<DropdownMenuItem
|
|
752
739
|
onSelect={onToggleComments}
|
|
753
740
|
className={
|