@agent-native/core 0.153.9 → 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/DataSources.tsx +2 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/ViewSqlPopover.tsx +1 -1
- package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +4 -2
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -2
- 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/app/root.tsx +4 -1
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -2
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +43 -8
- package/corpus/templates/clips/desktop/src/app.tsx +27 -13
- 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/DesignImportPanel.tsx +2 -1
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
- 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/plan/app/pages/PlansPage.tsx +5 -2
- 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/skills-content/help.d.ts +1 -1
- package/dist/cli/skills-content/help.js +2 -1
- package/dist/cli/skills.js +2 -1
- package/dist/cli/visualize-repo.js +1 -1
- package/dist/client/FeedbackButton.js +12 -12
- package/dist/client/NewWorkspaceAppFlow.js +4 -1
- package/dist/client/agent-chat-adapter.js +3 -4
- package/dist/client/agent-page/AgentTabsPage.d.ts +2 -2
- package/dist/client/agent-page/AgentTabsPage.js +12 -9
- 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/ExtensionsSidebarSection.js +2 -1
- 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/onboarding/FirstRunOnboarding.js +2 -1
- package/dist/client/org/TeamPage.js +14 -3
- package/dist/client/settings/SettingsPanel.js +26 -1
- 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/extensions/html-shell.js +5 -0
- package/dist/integrations/catalog.js +9 -8
- package/dist/observability/routes.d.ts +2 -2
- package/dist/secrets/routes.d.ts +6 -6
- 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 +31 -9
- 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/dist/server/onboarding-html.js +2 -1
- package/dist/shared/docs-url.d.ts +24 -0
- package/dist/shared/docs-url.js +39 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/templates/default/app/routes/_index.tsx +2 -1
- package/package.json +2 -2
- package/src/templates/default/app/routes/_index.tsx +2 -1
|
@@ -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={
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
IconCopy,
|
|
12
12
|
IconShare2,
|
|
13
13
|
IconBrandGoogle,
|
|
14
|
-
IconPlugConnected,
|
|
15
14
|
} from "@tabler/icons-react";
|
|
16
15
|
import { forwardRef, useImperativeHandle, useRef, useState } from "react";
|
|
17
16
|
import { toast } from "sonner";
|
|
@@ -32,6 +31,9 @@ import {
|
|
|
32
31
|
DropdownMenuLabel,
|
|
33
32
|
DropdownMenuSeparator,
|
|
34
33
|
DropdownMenuTrigger,
|
|
34
|
+
DropdownMenuSub,
|
|
35
|
+
DropdownMenuSubContent,
|
|
36
|
+
DropdownMenuSubTrigger,
|
|
35
37
|
} from "@/components/ui/dropdown-menu";
|
|
36
38
|
import type { GoogleSlidesExportResult } from "@/lib/export-google-slides-client";
|
|
37
39
|
|
|
@@ -53,7 +55,6 @@ interface ExportMenuProps {
|
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
export interface ExportMenuHandle {
|
|
56
|
-
connectGoogle: () => Promise<void>;
|
|
57
58
|
exportGoogleSlides: () => Promise<void>;
|
|
58
59
|
exportHtml: () => Promise<void>;
|
|
59
60
|
exportPptx: () => Promise<void>;
|
|
@@ -121,44 +122,7 @@ export const ExportMenu = forwardRef<ExportMenuHandle, ExportMenuProps>(
|
|
|
121
122
|
}
|
|
122
123
|
};
|
|
123
124
|
|
|
124
|
-
const
|
|
125
|
-
if (!onExportGoogleSlides) return;
|
|
126
|
-
// Opened up-front: browsers only honour window.open() inside the click
|
|
127
|
-
// gesture, and building the PPTX is async.
|
|
128
|
-
const target = window.open("", "_blank");
|
|
129
|
-
googleSlidesImportTarget.current = target;
|
|
130
|
-
try {
|
|
131
|
-
const result = await onExportGoogleSlides();
|
|
132
|
-
if (result.url !== null) {
|
|
133
|
-
googleSlidesImportTarget.current = null;
|
|
134
|
-
if (target) target.location.href = result.url;
|
|
135
|
-
toast.success(t("editorExport.googleSlidesCreated"), {
|
|
136
|
-
description: t("editorExport.googleSlidesCreatedHint"),
|
|
137
|
-
});
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (target) target.location.href = GOOGLE_SLIDES_IMPORT_URL;
|
|
141
|
-
setGoogleSlidesImportOpen(true);
|
|
142
|
-
// The deck did not reach Drive. Saying "success" here is why users read
|
|
143
|
-
// the .pptx download as the intended result and never learn that their
|
|
144
|
-
// Google account is unconnected or that Drive rejected the upload.
|
|
145
|
-
toast.warning(t("editorExport.googleSlidesDownloaded"), {
|
|
146
|
-
description: `${result.reason} ${t("editorExport.googleSlidesImportHint")}`,
|
|
147
|
-
});
|
|
148
|
-
} catch (err) {
|
|
149
|
-
googleSlidesImportTarget.current = null;
|
|
150
|
-
target?.close();
|
|
151
|
-
console.error("Export failed:", err);
|
|
152
|
-
toast.error(t("editorExport.exportFailed"), {
|
|
153
|
-
description:
|
|
154
|
-
err instanceof Error
|
|
155
|
-
? err.message
|
|
156
|
-
: t("editorExport.exportGoogleSlidesError"),
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
const handleConnectGoogle = async () => {
|
|
125
|
+
const handleConnectGoogle = async (target?: Window | null) => {
|
|
162
126
|
const authUrl = new URL(
|
|
163
127
|
agentNativePath("/_agent-native/google-docs/auth-url"),
|
|
164
128
|
window.location.origin,
|
|
@@ -168,11 +132,9 @@ export const ExportMenu = forwardRef<ExportMenuHandle, ExportMenuProps>(
|
|
|
168
132
|
window.location.pathname + window.location.search,
|
|
169
133
|
);
|
|
170
134
|
|
|
171
|
-
const popup =
|
|
172
|
-
|
|
173
|
-
"google-docs-oauth",
|
|
174
|
-
"popup,width=520,height=720",
|
|
175
|
-
);
|
|
135
|
+
const popup =
|
|
136
|
+
target ??
|
|
137
|
+
window.open("", "google-docs-oauth", "popup,width=520,height=720");
|
|
176
138
|
if (!popup) {
|
|
177
139
|
toast.error(t("editorExport.exportFailed"), {
|
|
178
140
|
description: t("editorExport.exportGoogleSlidesError"),
|
|
@@ -209,6 +171,49 @@ export const ExportMenu = forwardRef<ExportMenuHandle, ExportMenuProps>(
|
|
|
209
171
|
}
|
|
210
172
|
};
|
|
211
173
|
|
|
174
|
+
const handleExportGoogleSlides = async () => {
|
|
175
|
+
if (!onExportGoogleSlides) return;
|
|
176
|
+
// Opened up-front: browsers only honour window.open() inside the click
|
|
177
|
+
// gesture, and building the PPTX is async. If the account is missing,
|
|
178
|
+
// the same tab becomes the OAuth popup so the export action owns setup.
|
|
179
|
+
const target = window.open("", "_blank");
|
|
180
|
+
googleSlidesImportTarget.current = target;
|
|
181
|
+
try {
|
|
182
|
+
const result = await onExportGoogleSlides();
|
|
183
|
+
if ("requiresConnection" in result && result.requiresConnection) {
|
|
184
|
+
googleSlidesImportTarget.current = null;
|
|
185
|
+
await handleConnectGoogle(target);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (result.url !== null) {
|
|
189
|
+
googleSlidesImportTarget.current = null;
|
|
190
|
+
if (target) target.location.href = result.url;
|
|
191
|
+
toast.success(t("editorExport.googleSlidesCreated"), {
|
|
192
|
+
description: t("editorExport.googleSlidesCreatedHint"),
|
|
193
|
+
});
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (target) target.location.href = GOOGLE_SLIDES_IMPORT_URL;
|
|
197
|
+
setGoogleSlidesImportOpen(true);
|
|
198
|
+
// The deck did not reach Drive. Saying "success" here is why users read
|
|
199
|
+
// the .pptx download as the intended result and never learn that Drive
|
|
200
|
+
// rejected the upload.
|
|
201
|
+
toast.warning(t("editorExport.googleSlidesDownloaded"), {
|
|
202
|
+
description: `${result.reason} ${t("editorExport.googleSlidesImportHint")}`,
|
|
203
|
+
});
|
|
204
|
+
} catch (err) {
|
|
205
|
+
googleSlidesImportTarget.current = null;
|
|
206
|
+
target?.close();
|
|
207
|
+
console.error("Export failed:", err);
|
|
208
|
+
toast.error(t("editorExport.exportFailed"), {
|
|
209
|
+
description:
|
|
210
|
+
err instanceof Error
|
|
211
|
+
? err.message
|
|
212
|
+
: t("editorExport.exportGoogleSlidesError"),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
212
217
|
const handleExportHtml = async () => {
|
|
213
218
|
try {
|
|
214
219
|
const res = await fetch(`${appBasePath()}/api/exports/html`, {
|
|
@@ -241,79 +246,102 @@ export const ExportMenu = forwardRef<ExportMenuHandle, ExportMenuProps>(
|
|
|
241
246
|
useImperativeHandle(
|
|
242
247
|
ref,
|
|
243
248
|
() => ({
|
|
244
|
-
connectGoogle: handleConnectGoogle,
|
|
245
249
|
exportGoogleSlides: handleExportGoogleSlides,
|
|
246
250
|
exportHtml: handleExportHtml,
|
|
247
251
|
exportPptx: handleExportPptx,
|
|
248
252
|
}),
|
|
249
|
-
[
|
|
250
|
-
handleConnectGoogle,
|
|
251
|
-
handleExportGoogleSlides,
|
|
252
|
-
handleExportHtml,
|
|
253
|
-
handleExportPptx,
|
|
254
|
-
],
|
|
253
|
+
[handleExportGoogleSlides, handleExportHtml, handleExportPptx],
|
|
255
254
|
);
|
|
256
255
|
|
|
257
|
-
const
|
|
256
|
+
const exportActions = (
|
|
257
|
+
<>
|
|
258
|
+
<DropdownMenuItem onClick={handleExportHtml} className="cursor-pointer">
|
|
259
|
+
<IconCode className="size-4" />
|
|
260
|
+
{t("editorExport.downloadHtml")}
|
|
261
|
+
</DropdownMenuItem>
|
|
262
|
+
<DropdownMenuItem onClick={onExportPdf} className="cursor-pointer">
|
|
263
|
+
<IconFileTypePdf className="size-4" />
|
|
264
|
+
{t("editorExport.exportPdf")}
|
|
265
|
+
</DropdownMenuItem>
|
|
266
|
+
<DropdownMenuItem onClick={handleExportPptx} className="cursor-pointer">
|
|
267
|
+
<IconDownload className="size-4" />
|
|
268
|
+
{t("editorExport.exportPptx")}
|
|
269
|
+
</DropdownMenuItem>
|
|
270
|
+
{onExportGoogleSlides && (
|
|
271
|
+
<DropdownMenuItem
|
|
272
|
+
onClick={handleExportGoogleSlides}
|
|
273
|
+
className="cursor-pointer"
|
|
274
|
+
>
|
|
275
|
+
<IconBrandGoogle className="size-4" />
|
|
276
|
+
{t("editorExport.openInGoogleSlides")}
|
|
277
|
+
</DropdownMenuItem>
|
|
278
|
+
)}
|
|
279
|
+
</>
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
const shareActions = (
|
|
258
283
|
<>
|
|
259
|
-
<DropdownMenuLabel className="text-[11px] text-muted-foreground">
|
|
260
|
-
{t("editorExport.exportAndDuplicate")}
|
|
261
|
-
</DropdownMenuLabel>
|
|
262
284
|
{onShareTeam && (
|
|
263
285
|
<DropdownMenuItem onClick={onShareTeam} className="cursor-pointer">
|
|
264
|
-
<IconShare2 className="
|
|
286
|
+
<IconShare2 className="size-4" />
|
|
265
287
|
{t("editorExport.shareWithTeam")}
|
|
266
288
|
</DropdownMenuItem>
|
|
267
289
|
)}
|
|
268
290
|
{onShareLink && (
|
|
269
291
|
<DropdownMenuItem onClick={onShareLink} className="cursor-pointer">
|
|
270
|
-
<IconShare2 className="
|
|
292
|
+
<IconShare2 className="size-4" />
|
|
271
293
|
{t("editorExport.publicShareLink")}
|
|
272
294
|
</DropdownMenuItem>
|
|
273
295
|
)}
|
|
296
|
+
</>
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const duplicateAction = (
|
|
300
|
+
<DropdownMenuItem onClick={onDuplicate} className="cursor-pointer">
|
|
301
|
+
<IconCopy className="size-4" />
|
|
302
|
+
{t("editorExport.duplicateDeck")}
|
|
303
|
+
</DropdownMenuItem>
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
const menuContent = (
|
|
307
|
+
<>
|
|
308
|
+
<DropdownMenuLabel className="text-[11px] text-muted-foreground">
|
|
309
|
+
{t("editorExport.exportAndDuplicate")}
|
|
310
|
+
</DropdownMenuLabel>
|
|
311
|
+
{shareActions}
|
|
274
312
|
<DropdownMenuSeparator />
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
<IconDownload className="w-4 h-4 mr-2" />
|
|
285
|
-
{t("editorExport.exportPptx")}
|
|
286
|
-
</DropdownMenuItem>
|
|
287
|
-
{onExportGoogleSlides && (
|
|
313
|
+
{exportActions}
|
|
314
|
+
<DropdownMenuSeparator />
|
|
315
|
+
{duplicateAction}
|
|
316
|
+
</>
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
const inlineMenuContent = (
|
|
320
|
+
<>
|
|
321
|
+
{onShareTeam || onShareLink ? (
|
|
288
322
|
<>
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
className="cursor-pointer"
|
|
292
|
-
>
|
|
293
|
-
<IconPlugConnected className="w-4 h-4 mr-2" />
|
|
294
|
-
{t("editorExport.connectGoogle")}
|
|
295
|
-
</DropdownMenuItem>
|
|
296
|
-
<DropdownMenuItem
|
|
297
|
-
onClick={handleExportGoogleSlides}
|
|
298
|
-
className="cursor-pointer"
|
|
299
|
-
>
|
|
300
|
-
<IconBrandGoogle className="w-4 h-4 mr-2" />
|
|
301
|
-
{t("editorExport.openInGoogleSlides")}
|
|
302
|
-
</DropdownMenuItem>
|
|
323
|
+
{shareActions}
|
|
324
|
+
<DropdownMenuSeparator />
|
|
303
325
|
</>
|
|
304
|
-
)}
|
|
326
|
+
) : null}
|
|
327
|
+
<DropdownMenuSub>
|
|
328
|
+
<DropdownMenuSubTrigger className="cursor-pointer gap-2">
|
|
329
|
+
<IconUpload className="size-4" />
|
|
330
|
+
{t("editorExport.export")}
|
|
331
|
+
</DropdownMenuSubTrigger>
|
|
332
|
+
<DropdownMenuSubContent className="w-56">
|
|
333
|
+
{exportActions}
|
|
334
|
+
</DropdownMenuSubContent>
|
|
335
|
+
</DropdownMenuSub>
|
|
305
336
|
<DropdownMenuSeparator />
|
|
306
|
-
|
|
307
|
-
<IconCopy className="w-4 h-4 mr-2" />
|
|
308
|
-
{t("editorExport.duplicateDeck")}
|
|
309
|
-
</DropdownMenuItem>
|
|
337
|
+
{duplicateAction}
|
|
310
338
|
</>
|
|
311
339
|
);
|
|
312
340
|
|
|
313
341
|
return (
|
|
314
342
|
<>
|
|
315
343
|
{inline ? (
|
|
316
|
-
|
|
344
|
+
inlineMenuContent
|
|
317
345
|
) : (
|
|
318
346
|
<DropdownMenu>
|
|
319
347
|
<DropdownMenuTrigger asChild>
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
IconPhoto,
|
|
4
4
|
IconFolderOpen,
|
|
5
5
|
IconUpload,
|
|
6
|
+
IconDownload,
|
|
6
7
|
IconMaximize,
|
|
7
8
|
IconMinimize,
|
|
8
9
|
} from "@tabler/icons-react";
|
|
@@ -11,20 +12,24 @@ import { createPortal } from "react-dom";
|
|
|
11
12
|
|
|
12
13
|
interface ImageOverlayProps {
|
|
13
14
|
anchorRect: DOMRect;
|
|
15
|
+
src: string;
|
|
14
16
|
objectFit: "cover" | "contain";
|
|
15
17
|
onGenerate: () => void;
|
|
16
18
|
onLibrary: () => void;
|
|
17
19
|
onUpload: () => void;
|
|
20
|
+
onDownload: () => void;
|
|
18
21
|
onToggleObjectFit: () => void;
|
|
19
22
|
onClose: () => void;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
export default function ImageOverlay({
|
|
23
26
|
anchorRect,
|
|
27
|
+
src,
|
|
24
28
|
objectFit,
|
|
25
29
|
onGenerate,
|
|
26
30
|
onLibrary,
|
|
27
31
|
onUpload,
|
|
32
|
+
onDownload,
|
|
28
33
|
onToggleObjectFit,
|
|
29
34
|
onClose,
|
|
30
35
|
}: ImageOverlayProps) {
|
|
@@ -100,6 +105,17 @@ export default function ImageOverlay({
|
|
|
100
105
|
<IconUpload className="w-3.5 h-3.5 text-muted-foreground" />
|
|
101
106
|
Upload
|
|
102
107
|
</button>
|
|
108
|
+
<button
|
|
109
|
+
onClick={() => {
|
|
110
|
+
onDownload();
|
|
111
|
+
onClose();
|
|
112
|
+
}}
|
|
113
|
+
className="image-overlay-btn"
|
|
114
|
+
disabled={!src}
|
|
115
|
+
>
|
|
116
|
+
<IconDownload className="w-3.5 h-3.5 text-muted-foreground" />
|
|
117
|
+
Download
|
|
118
|
+
</button>
|
|
103
119
|
<div className="mx-1.5 border-t border-border" />
|
|
104
120
|
<button onClick={onToggleObjectFit} className="image-overlay-btn">
|
|
105
121
|
{objectFit === "cover" ? (
|