@agent-native/core 0.125.0 → 0.127.1
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 +2 -2
- package/corpus/core/CHANGELOG.md +79 -0
- package/corpus/core/docs/content/external-agents-catalog.mdx +14 -11
- package/corpus/core/docs/content/mcp-protocol.mdx +9 -4
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/index.ts +2 -0
- package/corpus/core/src/agent/production-agent.ts +6 -1
- package/corpus/core/src/agent/run-manager.ts +37 -0
- package/corpus/core/src/agent/run-store.ts +18 -0
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +75 -43
- package/corpus/core/src/client/agent-chat.ts +19 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +25 -0
- package/corpus/core/src/client/resources/mcp-integration-catalog.ts +23 -0
- package/corpus/core/src/client/settings/AgentsSection.tsx +565 -71
- package/corpus/core/src/client/settings/SecretsSection.tsx +71 -36
- package/corpus/core/src/client/use-chat-models.ts +54 -37
- package/corpus/core/src/localization/default-messages.ts +11 -0
- package/corpus/core/src/mcp/ask-app-task-handle.ts +183 -0
- package/corpus/core/src/mcp/builtin-tools.ts +146 -34
- package/corpus/core/src/server/agent-capabilities.ts +8 -1
- package/corpus/core/src/server/agent-chat-plugin.ts +17 -0
- package/corpus/core/src/server/agent-discovery.ts +1 -1
- package/corpus/core/src/server/agent-peer-probe.ts +133 -0
- package/corpus/core/src/server/core-routes-plugin.ts +67 -0
- package/corpus/core/src/server/email-template.ts +13 -0
- package/corpus/core/src/server/email.ts +40 -4
- package/corpus/core/src/shared/mcp-embed-headers.ts +4 -0
- package/corpus/core/src/sharing/actions/share-resource.ts +55 -5
- package/corpus/core/src/sharing/registry.ts +41 -1
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
- package/corpus/templates/assets/actions/edit-image.ts +31 -18
- package/corpus/templates/assets/actions/refine-image.ts +43 -29
- package/corpus/templates/assets/actions/restyle-image.ts +30 -19
- package/corpus/templates/assets/actions/variant-slots.ts +26 -0
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +85 -17
- package/corpus/templates/clips/changelog/2026-07-27-share-notification-emails-now-include-a-clickable-recording-.md +6 -0
- package/corpus/templates/clips/server/db/index.ts +28 -6
- package/corpus/templates/clips/server/lib/share-email-hero.ts +105 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +100 -12
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +17 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +169 -22
- package/corpus/templates/design/app/hooks/use-question-flow.ts +21 -1
- package/corpus/templates/design/changelog/2026-07-28-the-model-you-pick-when-starting-a-new-design-is-now-used-fo.md +6 -0
- package/corpus/templates/dispatch/changelog/2026-07-28-pending-apps-are-hidden-by-default-and-app-ownership-details.md +6 -0
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +5 -1
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +5 -0
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +31 -8
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +15 -0
- package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +78 -8
- package/corpus/templates/slides/app/components/presentation/PresenterView.tsx +179 -0
- package/corpus/templates/slides/app/components/presentation/present-channel.ts +15 -0
- package/corpus/templates/slides/app/i18n/en-US.ts +10 -1
- package/corpus/templates/slides/app/lib/export-google-slides-client.ts +67 -0
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +16 -3
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +11 -0
- package/corpus/templates/slides/app/pages/Presentation.tsx +11 -3
- package/corpus/templates/slides/changelog/2026-07-28-export-to-google-slides-now-creates-the-deck-directly-in-you.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-28-opening-a-presentation-link-directly-no-longer-bounces-back-.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-28-presenter-view-open-a-second-window-while-presenting-to-see-.md +6 -0
- package/corpus/templates/slides/server/routes/api/exports/google-slides.post.ts +90 -0
- package/corpus/toolkit/CHANGELOG.md +6 -0
- package/corpus/toolkit/package.json +1 -1
- package/corpus/toolkit/src/composer/TiptapComposer.tsx +143 -111
- package/corpus/toolkit/src/composer/runtime-adapters.tsx +2 -0
- package/dist/a2a/index.d.ts +2 -0
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -0
- package/dist/a2a/index.js.map +1 -1
- package/dist/agent/production-agent.d.ts +2 -2
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +6 -3
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +11 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +34 -1
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +8 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +16 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +60 -31
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts +6 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +13 -1
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +14 -0
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.d.ts +6 -0
- package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
- package/dist/client/resources/mcp-integration-catalog.js +16 -0
- package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
- package/dist/client/settings/AgentsSection.d.ts.map +1 -1
- package/dist/client/settings/AgentsSection.js +250 -30
- package/dist/client/settings/AgentsSection.js.map +1 -1
- package/dist/client/settings/SecretsSection.d.ts.map +1 -1
- package/dist/client/settings/SecretsSection.js +16 -2
- package/dist/client/settings/SecretsSection.js.map +1 -1
- package/dist/client/use-chat-models.d.ts.map +1 -1
- package/dist/client/use-chat-models.js +46 -27
- package/dist/client/use-chat-models.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/localization/default-messages.d.ts +9 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +9 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/mcp/ask-app-task-handle.d.ts +25 -0
- package/dist/mcp/ask-app-task-handle.d.ts.map +1 -0
- package/dist/mcp/ask-app-task-handle.js +136 -0
- package/dist/mcp/ask-app-task-handle.js.map +1 -0
- package/dist/mcp/builtin-tools.d.ts +3 -3
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +115 -38
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +6 -6
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-capabilities.d.ts +7 -1
- package/dist/server/agent-capabilities.d.ts.map +1 -1
- package/dist/server/agent-capabilities.js +1 -0
- package/dist/server/agent-capabilities.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +7 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +16 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-discovery.d.ts +1 -0
- package/dist/server/agent-discovery.d.ts.map +1 -1
- package/dist/server/agent-discovery.js +1 -1
- package/dist/server/agent-discovery.js.map +1 -1
- package/dist/server/agent-peer-probe.d.ts +37 -0
- package/dist/server/agent-peer-probe.d.ts.map +1 -0
- package/dist/server/agent-peer-probe.js +90 -0
- package/dist/server/agent-peer-probe.js.map +1 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +53 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/email-template.d.ts +6 -0
- package/dist/server/email-template.d.ts.map +1 -1
- package/dist/server/email-template.js +6 -0
- package/dist/server/email-template.js.map +1 -1
- package/dist/server/email.d.ts +7 -0
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +31 -6
- package/dist/server/email.js.map +1 -1
- package/dist/shared/mcp-embed-headers.d.ts +1 -0
- package/dist/shared/mcp-embed-headers.d.ts.map +1 -1
- package/dist/shared/mcp-embed-headers.js +4 -0
- package/dist/shared/mcp-embed-headers.js.map +1 -1
- package/dist/sharing/actions/share-resource.d.ts.map +1 -1
- package/dist/sharing/actions/share-resource.js +49 -5
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/sharing/registry.d.ts +40 -1
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js.map +1 -1
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
- package/docs/content/external-agents-catalog.mdx +14 -11
- package/docs/content/mcp-protocol.mdx +9 -4
- package/package.json +2 -2
- package/src/a2a/index.ts +2 -0
- package/src/agent/production-agent.ts +6 -1
- package/src/agent/run-manager.ts +37 -0
- package/src/agent/run-store.ts +18 -0
- package/src/client/MultiTabAssistantChat.tsx +75 -43
- package/src/client/agent-chat.ts +19 -1
- package/src/client/chat/tool-call-display.tsx +25 -0
- package/src/client/resources/mcp-integration-catalog.ts +23 -0
- package/src/client/settings/AgentsSection.tsx +565 -71
- package/src/client/settings/SecretsSection.tsx +71 -36
- package/src/client/use-chat-models.ts +54 -37
- package/src/localization/default-messages.ts +11 -0
- package/src/mcp/ask-app-task-handle.ts +183 -0
- package/src/mcp/builtin-tools.ts +146 -34
- package/src/server/agent-capabilities.ts +8 -1
- package/src/server/agent-chat-plugin.ts +17 -0
- package/src/server/agent-discovery.ts +1 -1
- package/src/server/agent-peer-probe.ts +133 -0
- package/src/server/core-routes-plugin.ts +67 -0
- package/src/server/email-template.ts +13 -0
- package/src/server/email.ts +40 -4
- package/src/shared/mcp-embed-headers.ts +4 -0
- package/src/sharing/actions/share-resource.ts +55 -5
- package/src/sharing/registry.ts +41 -1
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +159 -119
|
@@ -23,6 +23,13 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
23
23
|
return false;
|
|
24
24
|
}
|
|
25
25
|
})();
|
|
26
|
+
var selectedLayerDragPriorityEnabled = (function() {
|
|
27
|
+
try {
|
|
28
|
+
return !!__SELECTED_LAYER_DRAG_PRIORITY__;
|
|
29
|
+
} catch (_e) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
})();
|
|
26
33
|
var scaleToolEnabled = false;
|
|
27
34
|
function dndLog(phase, data) {
|
|
28
35
|
if (!window.__DND_DEBUG) return;
|
|
@@ -1596,6 +1603,7 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
1596
1603
|
clearComponentTag();
|
|
1597
1604
|
}
|
|
1598
1605
|
var selectedEl = null;
|
|
1606
|
+
var selectionChromeHidden = false;
|
|
1599
1607
|
var hoveredEl = null;
|
|
1600
1608
|
var highlightOverlayStyle = "default";
|
|
1601
1609
|
var activeNodeHtmlPreview = null;
|
|
@@ -2773,7 +2781,11 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
2773
2781
|
hideSelectionOverlay();
|
|
2774
2782
|
}
|
|
2775
2783
|
} else if (selectedEl) {
|
|
2776
|
-
|
|
2784
|
+
if (selectionChromeHidden) {
|
|
2785
|
+
hideSelectionOverlay();
|
|
2786
|
+
} else {
|
|
2787
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
2788
|
+
}
|
|
2777
2789
|
} else {
|
|
2778
2790
|
hideParentAutoLayoutOverlay();
|
|
2779
2791
|
}
|
|
@@ -3507,29 +3519,27 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
3507
3519
|
document.addEventListener(events.move, onMove, true);
|
|
3508
3520
|
document.addEventListener(events.up, onUp, true);
|
|
3509
3521
|
}
|
|
3510
|
-
function
|
|
3511
|
-
stopNativeInteraction(e);
|
|
3512
|
-
blurActiveTextEditor();
|
|
3522
|
+
function collectLayerHitCandidates(clientX, clientY) {
|
|
3513
3523
|
var shieldPointerEvents = shieldOverlay.style.pointerEvents;
|
|
3514
3524
|
var selectionPointerEvents = selectionOverlay.style.pointerEvents;
|
|
3515
3525
|
var highlightPointerEvents = highlightOverlay.style.pointerEvents;
|
|
3516
3526
|
shieldOverlay.style.pointerEvents = "none";
|
|
3517
3527
|
selectionOverlay.style.pointerEvents = "none";
|
|
3518
3528
|
highlightOverlay.style.pointerEvents = "none";
|
|
3519
|
-
var pointTargets = document.elementsFromPoint ? document.elementsFromPoint(
|
|
3529
|
+
var pointTargets = document.elementsFromPoint ? document.elementsFromPoint(clientX, clientY) : [document.elementFromPoint(clientX, clientY)];
|
|
3520
3530
|
shieldOverlay.style.pointerEvents = shieldPointerEvents;
|
|
3521
3531
|
selectionOverlay.style.pointerEvents = selectionPointerEvents;
|
|
3522
3532
|
highlightOverlay.style.pointerEvents = highlightPointerEvents;
|
|
3523
|
-
var
|
|
3533
|
+
var elements = [];
|
|
3524
3534
|
var layerCandidates = [];
|
|
3525
3535
|
pointTargets.forEach(function(pointTarget) {
|
|
3526
3536
|
if (!pointTarget || pointTarget.nodeType !== 1) return;
|
|
3527
3537
|
if (isOverlayElement(pointTarget)) return;
|
|
3528
3538
|
var candidate = selectionTargetForHit(pointTarget);
|
|
3529
|
-
if (!candidate || isDocumentRootElement(candidate) || isOverlayElement(candidate) || isLayerInteractionBlocked(candidate) || isTemplateCloneElement(candidate) ||
|
|
3539
|
+
if (!candidate || isDocumentRootElement(candidate) || isOverlayElement(candidate) || isLayerInteractionBlocked(candidate) || isTemplateCloneElement(candidate) || elements.indexOf(candidate) !== -1) {
|
|
3530
3540
|
return;
|
|
3531
3541
|
}
|
|
3532
|
-
|
|
3542
|
+
elements.push(candidate);
|
|
3533
3543
|
var candidateInfo = getElementInfo(candidate);
|
|
3534
3544
|
var explicitLabel = candidate.getAttribute && candidate.getAttribute("data-agent-native-layer-name") || "";
|
|
3535
3545
|
var textLabel = (candidate.textContent || "").trim().replace(/\\s+/g, " ");
|
|
@@ -3541,6 +3551,30 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
3541
3551
|
info: candidateInfo
|
|
3542
3552
|
});
|
|
3543
3553
|
});
|
|
3554
|
+
return { elements, layerCandidates };
|
|
3555
|
+
}
|
|
3556
|
+
function stackCycleTarget(clientX, clientY, currentEl) {
|
|
3557
|
+
if (!currentEl) return null;
|
|
3558
|
+
var stack = collectLayerHitCandidates(clientX, clientY);
|
|
3559
|
+
var currentIdx = stack.elements.indexOf(currentEl);
|
|
3560
|
+
if (currentIdx === -1) return null;
|
|
3561
|
+
var keys = stack.layerCandidates.map(function(candidate) {
|
|
3562
|
+
return candidate.key;
|
|
3563
|
+
});
|
|
3564
|
+
var nextKey = nextStackCandidate(
|
|
3565
|
+
keys,
|
|
3566
|
+
stack.layerCandidates[currentIdx].key
|
|
3567
|
+
);
|
|
3568
|
+
if (nextKey === null) return null;
|
|
3569
|
+
var nextEl = stack.elements[keys.indexOf(nextKey)];
|
|
3570
|
+
return nextEl && !isLayerInteractionBlocked(nextEl) ? nextEl : null;
|
|
3571
|
+
}
|
|
3572
|
+
function openContextMenuAtEvent(e) {
|
|
3573
|
+
stopNativeInteraction(e);
|
|
3574
|
+
blurActiveTextEditor();
|
|
3575
|
+
var collected = collectLayerHitCandidates(e.clientX, e.clientY);
|
|
3576
|
+
var candidateElements = collected.elements;
|
|
3577
|
+
var layerCandidates = collected.layerCandidates;
|
|
3544
3578
|
var target = candidateElements[0] || null;
|
|
3545
3579
|
var info = null;
|
|
3546
3580
|
if (target) {
|
|
@@ -6238,7 +6272,8 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
6238
6272
|
height: dragElStartHeight
|
|
6239
6273
|
},
|
|
6240
6274
|
snapCandidateRects,
|
|
6241
|
-
|
|
6275
|
+
// Convert the screen-space base to content px (1/zoom).
|
|
6276
|
+
SNAP_THRESHOLD_PX * chromeLineScale()
|
|
6242
6277
|
) : { dx: 0, dy: 0, guideV: null, guideH: null };
|
|
6243
6278
|
nextLeft += snapResult.dx;
|
|
6244
6279
|
nextTop += snapResult.dy;
|
|
@@ -6726,6 +6761,29 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
6726
6761
|
}
|
|
6727
6762
|
pendingShieldDrag = null;
|
|
6728
6763
|
}
|
|
6764
|
+
function dragTargetForPointerDown(args) {
|
|
6765
|
+
var selectedEl2 = args.selectedEl;
|
|
6766
|
+
var hitEl = args.hitEl;
|
|
6767
|
+
var hitRaw = args.hitRaw || hitEl;
|
|
6768
|
+
var selectedAlive = !!args.selectedAlive;
|
|
6769
|
+
if (selectedEl2 && selectedAlive && selectedEl2.contains && selectedEl2.contains(hitRaw)) {
|
|
6770
|
+
return selectedEl2;
|
|
6771
|
+
}
|
|
6772
|
+
if (args.preferSelected && selectedEl2 && selectedAlive) {
|
|
6773
|
+
var r = args.selectedRect;
|
|
6774
|
+
var p = args.point;
|
|
6775
|
+
if (r && p && r.width > 0 && r.height > 0 && p.x >= r.left && p.x <= r.right && p.y >= r.top && p.y <= r.bottom) {
|
|
6776
|
+
return selectedEl2;
|
|
6777
|
+
}
|
|
6778
|
+
}
|
|
6779
|
+
return hitEl;
|
|
6780
|
+
}
|
|
6781
|
+
function nextStackCandidate(candidateKeys, currentKey) {
|
|
6782
|
+
if (!candidateKeys || candidateKeys.length === 0) return null;
|
|
6783
|
+
var idx = candidateKeys.indexOf(currentKey);
|
|
6784
|
+
if (idx === -1) return null;
|
|
6785
|
+
return candidateKeys[(idx + 1) % candidateKeys.length];
|
|
6786
|
+
}
|
|
6729
6787
|
function beginPotentialShieldDrag(e) {
|
|
6730
6788
|
stopNativeInteraction(e);
|
|
6731
6789
|
if (e.button !== 0) return;
|
|
@@ -6737,7 +6795,17 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
6737
6795
|
beginMarqueeSelection(e);
|
|
6738
6796
|
return;
|
|
6739
6797
|
}
|
|
6740
|
-
var
|
|
6798
|
+
var selectedAlive = !!selectedEl && document.documentElement.contains(selectedEl);
|
|
6799
|
+
var selectedRect = selectedAlive && selectedEl.getBoundingClientRect ? selectedEl.getBoundingClientRect() : null;
|
|
6800
|
+
var dragTarget = dragTargetForPointerDown({
|
|
6801
|
+
selectedEl,
|
|
6802
|
+
selectedAlive,
|
|
6803
|
+
selectedRect,
|
|
6804
|
+
hitEl: hitTarget,
|
|
6805
|
+
hitRaw: hit,
|
|
6806
|
+
point: { x: e.clientX, y: e.clientY },
|
|
6807
|
+
preferSelected: selectedLayerDragPriorityEnabled
|
|
6808
|
+
});
|
|
6741
6809
|
var clickTarget = hitTarget;
|
|
6742
6810
|
if (!dragTarget || dragTarget === document.body || dragTarget === document.documentElement || isLayerInteractionBlocked(dragTarget)) {
|
|
6743
6811
|
return;
|
|
@@ -6793,7 +6861,12 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
6793
6861
|
postCrossScreenDrag("cancel");
|
|
6794
6862
|
}
|
|
6795
6863
|
if (ev) stopNativeInteraction(ev);
|
|
6796
|
-
|
|
6864
|
+
var cycledEl = !readOnly && (e.metaKey || e.ctrlKey) && !e.shiftKey ? stackCycleTarget(e.clientX, e.clientY, selectedEl) : null;
|
|
6865
|
+
if (cycledEl) {
|
|
6866
|
+
selectTarget(cycledEl);
|
|
6867
|
+
} else {
|
|
6868
|
+
selectTarget(clickTarget || dragTarget, ev);
|
|
6869
|
+
}
|
|
6797
6870
|
suppressNextShieldClickBriefly();
|
|
6798
6871
|
}
|
|
6799
6872
|
clearPendingShieldDrag();
|
|
@@ -7876,6 +7949,17 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
7876
7949
|
);
|
|
7877
7950
|
return;
|
|
7878
7951
|
}
|
|
7952
|
+
if (e.data.type === "set-selection-chrome-hidden") {
|
|
7953
|
+
selectionChromeHidden = !!e.data.hidden;
|
|
7954
|
+
if (selectionChromeHidden) {
|
|
7955
|
+
hideSelectionOverlay();
|
|
7956
|
+
} else if (selectedEl) {
|
|
7957
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
7958
|
+
updateParentAutoLayoutOverlay(selectedEl);
|
|
7959
|
+
refreshOverlays();
|
|
7960
|
+
}
|
|
7961
|
+
return;
|
|
7962
|
+
}
|
|
7879
7963
|
if (e.data.type === "select-element") {
|
|
7880
7964
|
var candidates = [];
|
|
7881
7965
|
if (Array.isArray(e.data.selectorCandidates)) {
|
|
@@ -7908,7 +7992,11 @@ export const editorChromeBridgeScript: string = `"use strict";
|
|
|
7908
7992
|
hoveredSpacingHandleKey = "";
|
|
7909
7993
|
}
|
|
7910
7994
|
selectedEl = target;
|
|
7911
|
-
|
|
7995
|
+
if (selectionChromeHidden) {
|
|
7996
|
+
hideSelectionOverlay();
|
|
7997
|
+
} else {
|
|
7998
|
+
positionOverlay(selectionOverlay, target);
|
|
7999
|
+
}
|
|
7912
8000
|
if (hoveredEl === selectedEl) highlightOverlay.style.display = "none";
|
|
7913
8001
|
if (selectionChangedByHost) {
|
|
7914
8002
|
postElementSelect(target);
|
|
@@ -316,6 +316,15 @@ ${editorChromeBridgeScript}
|
|
|
316
316
|
*/
|
|
317
317
|
const LIVE_REFLOW_ENABLED = true;
|
|
318
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Rollout gate: when on, a pointerdown inside the current selection's box keeps
|
|
321
|
+
* the selected element as the drag target even when an overlapping
|
|
322
|
+
* non-descendant sibling wins the hit test. Baked into the bridge as
|
|
323
|
+
* `__SELECTED_LAYER_DRAG_PRIORITY__`; flip to `false` for descendant-only
|
|
324
|
+
* behavior.
|
|
325
|
+
*/
|
|
326
|
+
const SELECTED_LAYER_DRAG_PRIORITY_ENABLED = true;
|
|
327
|
+
|
|
319
328
|
interface DesignCanvasProps {
|
|
320
329
|
content: string;
|
|
321
330
|
contentKey?: string;
|
|
@@ -950,6 +959,10 @@ function buildEditorChromeBridgeScript(args: {
|
|
|
950
959
|
"__LIVE_REFLOW_ENABLED__",
|
|
951
960
|
LIVE_REFLOW_ENABLED ? "true" : "false",
|
|
952
961
|
)
|
|
962
|
+
.replace(
|
|
963
|
+
"__SELECTED_LAYER_DRAG_PRIORITY__",
|
|
964
|
+
SELECTED_LAYER_DRAG_PRIORITY_ENABLED ? "true" : "false",
|
|
965
|
+
)
|
|
953
966
|
);
|
|
954
967
|
}
|
|
955
968
|
|
|
@@ -2131,6 +2144,10 @@ export function DesignCanvas({
|
|
|
2131
2144
|
.replace(
|
|
2132
2145
|
"__LIVE_REFLOW_ENABLED__",
|
|
2133
2146
|
LIVE_REFLOW_ENABLED ? "true" : "false",
|
|
2147
|
+
)
|
|
2148
|
+
.replace(
|
|
2149
|
+
"__SELECTED_LAYER_DRAG_PRIORITY__",
|
|
2150
|
+
SELECTED_LAYER_DRAG_PRIORITY_ENABLED ? "true" : "false",
|
|
2134
2151
|
);
|
|
2135
2152
|
// ALWAYS injected (like the other always-on bridges above) so
|
|
2136
2153
|
// MultiScreenCanvas's cross-screen drag hit-testing
|
|
@@ -35,6 +35,7 @@ declare var __DESIGN_CANVAS_CONTENT_OFFSET_X__: number;
|
|
|
35
35
|
declare var __DESIGN_CANVAS_CONTENT_OFFSET_Y__: number;
|
|
36
36
|
declare var __RUNTIME_LAYER_SNAPSHOT_ENABLED__: boolean;
|
|
37
37
|
declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
38
|
+
declare var __SELECTED_LAYER_DRAG_PRIORITY__: boolean;
|
|
38
39
|
|
|
39
40
|
(function () {
|
|
40
41
|
// Idempotency guard: replace-document-content / srcdoc rebuilds can end up
|
|
@@ -78,6 +79,16 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
78
79
|
return false;
|
|
79
80
|
}
|
|
80
81
|
})();
|
|
82
|
+
// Selected-layer drag priority: when on, a pointerdown inside the selection
|
|
83
|
+
// box keeps the selected element as the drag target even when an overlapping
|
|
84
|
+
// non-descendant sibling wins the hit test.
|
|
85
|
+
var selectedLayerDragPriorityEnabled = (function () {
|
|
86
|
+
try {
|
|
87
|
+
return !!__SELECTED_LAYER_DRAG_PRIORITY__;
|
|
88
|
+
} catch (_e) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
})();
|
|
81
92
|
var scaleToolEnabled = false;
|
|
82
93
|
|
|
83
94
|
// ── Drag-and-drop debug logging ────────────────────────────────────
|
|
@@ -2248,6 +2259,9 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
2248
2259
|
}
|
|
2249
2260
|
|
|
2250
2261
|
var selectedEl: Element | null = null;
|
|
2262
|
+
// When true, selection chrome stays hidden through async reflows so a
|
|
2263
|
+
// keyboard-nudge burst does not flicker; selection itself is unchanged.
|
|
2264
|
+
var selectionChromeHidden = false;
|
|
2251
2265
|
var hoveredEl: Element | null = null;
|
|
2252
2266
|
var highlightOverlayStyle: "default" | "soft" = "default";
|
|
2253
2267
|
type NodeHtmlPreviewSession = {
|
|
@@ -4080,7 +4094,11 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
4080
4094
|
hideSelectionOverlay();
|
|
4081
4095
|
}
|
|
4082
4096
|
} else if (selectedEl) {
|
|
4083
|
-
|
|
4097
|
+
if (selectionChromeHidden) {
|
|
4098
|
+
hideSelectionOverlay();
|
|
4099
|
+
} else {
|
|
4100
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
4101
|
+
}
|
|
4084
4102
|
} else {
|
|
4085
4103
|
hideParentAutoLayoutOverlay();
|
|
4086
4104
|
}
|
|
@@ -5103,9 +5121,17 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
5103
5121
|
document.addEventListener(events.up, onUp, true);
|
|
5104
5122
|
}
|
|
5105
5123
|
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5124
|
+
// Returns the full z-stack of selectable layers under a point (topmost
|
|
5125
|
+
// first), each element index-aligned with a { key, label, info } descriptor.
|
|
5126
|
+
// Overlays are briefly made pointer-transparent so elementsFromPoint sees
|
|
5127
|
+
// through the editor chrome.
|
|
5128
|
+
function collectLayerHitCandidates(
|
|
5129
|
+
clientX: number,
|
|
5130
|
+
clientY: number,
|
|
5131
|
+
): {
|
|
5132
|
+
elements: Element[];
|
|
5133
|
+
layerCandidates: Array<{ key: string; label: string; info: unknown }>;
|
|
5134
|
+
} {
|
|
5109
5135
|
var shieldPointerEvents = shieldOverlay.style.pointerEvents;
|
|
5110
5136
|
var selectionPointerEvents = selectionOverlay.style.pointerEvents;
|
|
5111
5137
|
var highlightPointerEvents = highlightOverlay.style.pointerEvents;
|
|
@@ -5113,13 +5139,13 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
5113
5139
|
selectionOverlay.style.pointerEvents = "none";
|
|
5114
5140
|
highlightOverlay.style.pointerEvents = "none";
|
|
5115
5141
|
var pointTargets = document.elementsFromPoint
|
|
5116
|
-
? document.elementsFromPoint(
|
|
5117
|
-
: [document.elementFromPoint(
|
|
5142
|
+
? document.elementsFromPoint(clientX, clientY)
|
|
5143
|
+
: [document.elementFromPoint(clientX, clientY)];
|
|
5118
5144
|
shieldOverlay.style.pointerEvents = shieldPointerEvents;
|
|
5119
5145
|
selectionOverlay.style.pointerEvents = selectionPointerEvents;
|
|
5120
5146
|
highlightOverlay.style.pointerEvents = highlightPointerEvents;
|
|
5121
5147
|
|
|
5122
|
-
var
|
|
5148
|
+
var elements: Element[] = [];
|
|
5123
5149
|
var layerCandidates: Array<{
|
|
5124
5150
|
key: string;
|
|
5125
5151
|
label: string;
|
|
@@ -5135,11 +5161,11 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
5135
5161
|
isOverlayElement(candidate) ||
|
|
5136
5162
|
isLayerInteractionBlocked(candidate) ||
|
|
5137
5163
|
isTemplateCloneElement(candidate) ||
|
|
5138
|
-
|
|
5164
|
+
elements.indexOf(candidate) !== -1
|
|
5139
5165
|
) {
|
|
5140
5166
|
return;
|
|
5141
5167
|
}
|
|
5142
|
-
|
|
5168
|
+
elements.push(candidate);
|
|
5143
5169
|
var candidateInfo = getElementInfo(candidate);
|
|
5144
5170
|
var explicitLabel =
|
|
5145
5171
|
(candidate.getAttribute &&
|
|
@@ -5162,6 +5188,39 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
5162
5188
|
info: candidateInfo,
|
|
5163
5189
|
});
|
|
5164
5190
|
});
|
|
5191
|
+
return { elements: elements, layerCandidates: layerCandidates };
|
|
5192
|
+
}
|
|
5193
|
+
|
|
5194
|
+
// Given a point and the current selection, return the next layer BELOW it in
|
|
5195
|
+
// the hit stack (wrapping at the bottom), or null when the selection is not
|
|
5196
|
+
// in the stack or the next layer is blocked. Backs Cmd/Ctrl+click deep-select.
|
|
5197
|
+
function stackCycleTarget(
|
|
5198
|
+
clientX: number,
|
|
5199
|
+
clientY: number,
|
|
5200
|
+
currentEl: Element | null,
|
|
5201
|
+
): Element | null {
|
|
5202
|
+
if (!currentEl) return null;
|
|
5203
|
+
var stack = collectLayerHitCandidates(clientX, clientY);
|
|
5204
|
+
var currentIdx = stack.elements.indexOf(currentEl);
|
|
5205
|
+
if (currentIdx === -1) return null;
|
|
5206
|
+
var keys = stack.layerCandidates.map(function (candidate) {
|
|
5207
|
+
return candidate.key;
|
|
5208
|
+
});
|
|
5209
|
+
var nextKey = nextStackCandidate(
|
|
5210
|
+
keys,
|
|
5211
|
+
stack.layerCandidates[currentIdx].key,
|
|
5212
|
+
);
|
|
5213
|
+
if (nextKey === null) return null;
|
|
5214
|
+
var nextEl = stack.elements[keys.indexOf(nextKey)];
|
|
5215
|
+
return nextEl && !isLayerInteractionBlocked(nextEl) ? nextEl : null;
|
|
5216
|
+
}
|
|
5217
|
+
|
|
5218
|
+
function openContextMenuAtEvent(e) {
|
|
5219
|
+
stopNativeInteraction(e);
|
|
5220
|
+
blurActiveTextEditor();
|
|
5221
|
+
var collected = collectLayerHitCandidates(e.clientX, e.clientY);
|
|
5222
|
+
var candidateElements = collected.elements;
|
|
5223
|
+
var layerCandidates = collected.layerCandidates;
|
|
5165
5224
|
|
|
5166
5225
|
var target = candidateElements[0] || null;
|
|
5167
5226
|
var info = null;
|
|
@@ -8227,10 +8286,9 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
8227
8286
|
// Minimal, dependency-free port of the overview canvas's edge/center snap
|
|
8228
8287
|
// routine (shared/canvas-math.ts computeMoveSnap) for in-iframe element
|
|
8229
8288
|
// dragging. The bridge's pointer coordinates and getBoundingClientRect()
|
|
8230
|
-
// values are
|
|
8231
|
-
//
|
|
8232
|
-
//
|
|
8233
|
-
// its own camera zoom — no extra scale correction is needed here.
|
|
8289
|
+
// values are iframe-local content px, so SNAP_THRESHOLD_PX is a screen-space
|
|
8290
|
+
// base converted to content px at snap time via chromeLineScale (1/zoom) to
|
|
8291
|
+
// keep the snap tolerance constant on screen at any zoom.
|
|
8234
8292
|
var SNAP_THRESHOLD_PX = 6;
|
|
8235
8293
|
var SNAP_CANDIDATE_CAP = 200;
|
|
8236
8294
|
|
|
@@ -9321,7 +9379,8 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
9321
9379
|
height: dragElStartHeight,
|
|
9322
9380
|
},
|
|
9323
9381
|
snapCandidateRects,
|
|
9324
|
-
|
|
9382
|
+
// Convert the screen-space base to content px (1/zoom).
|
|
9383
|
+
SNAP_THRESHOLD_PX * chromeLineScale(),
|
|
9325
9384
|
)
|
|
9326
9385
|
: { dx: 0, dy: 0, guideV: null, guideH: null };
|
|
9327
9386
|
nextLeft += snapResult.dx;
|
|
@@ -9970,6 +10029,53 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
9970
10029
|
pendingShieldDrag = null;
|
|
9971
10030
|
}
|
|
9972
10031
|
|
|
10032
|
+
// Decides the drag target for a pointerdown. Descendant hits keep the
|
|
10033
|
+
// selected element; with preferSelected on, a point inside the selection box
|
|
10034
|
+
// also keeps it over an overlapping non-descendant sibling. Falls through to
|
|
10035
|
+
// hitEl when the selection is detached or zero-area. Pure and self-contained
|
|
10036
|
+
// so the snap test can brace-extract and evaluate it in isolation.
|
|
10037
|
+
function dragTargetForPointerDown(args) {
|
|
10038
|
+
var selectedEl = args.selectedEl;
|
|
10039
|
+
var hitEl = args.hitEl;
|
|
10040
|
+
var hitRaw = args.hitRaw || hitEl;
|
|
10041
|
+
var selectedAlive = !!args.selectedAlive;
|
|
10042
|
+
if (
|
|
10043
|
+
selectedEl &&
|
|
10044
|
+
selectedAlive &&
|
|
10045
|
+
selectedEl.contains &&
|
|
10046
|
+
selectedEl.contains(hitRaw)
|
|
10047
|
+
) {
|
|
10048
|
+
return selectedEl;
|
|
10049
|
+
}
|
|
10050
|
+
if (args.preferSelected && selectedEl && selectedAlive) {
|
|
10051
|
+
var r = args.selectedRect;
|
|
10052
|
+
var p = args.point;
|
|
10053
|
+
if (
|
|
10054
|
+
r &&
|
|
10055
|
+
p &&
|
|
10056
|
+
r.width > 0 &&
|
|
10057
|
+
r.height > 0 &&
|
|
10058
|
+
p.x >= r.left &&
|
|
10059
|
+
p.x <= r.right &&
|
|
10060
|
+
p.y >= r.top &&
|
|
10061
|
+
p.y <= r.bottom
|
|
10062
|
+
) {
|
|
10063
|
+
return selectedEl;
|
|
10064
|
+
}
|
|
10065
|
+
}
|
|
10066
|
+
return hitEl;
|
|
10067
|
+
}
|
|
10068
|
+
|
|
10069
|
+
// Given the hit-stack candidate keys (topmost first) and the current
|
|
10070
|
+
// selection key, returns the next key below it, wrapping to the top. Returns
|
|
10071
|
+
// null when the selection is not in the stack. Pure, for the snap test.
|
|
10072
|
+
function nextStackCandidate(candidateKeys, currentKey) {
|
|
10073
|
+
if (!candidateKeys || candidateKeys.length === 0) return null;
|
|
10074
|
+
var idx = candidateKeys.indexOf(currentKey);
|
|
10075
|
+
if (idx === -1) return null;
|
|
10076
|
+
return candidateKeys[(idx + 1) % candidateKeys.length];
|
|
10077
|
+
}
|
|
10078
|
+
|
|
9973
10079
|
function beginPotentialShieldDrag(e) {
|
|
9974
10080
|
stopNativeInteraction(e);
|
|
9975
10081
|
if (e.button !== 0) return;
|
|
@@ -9988,12 +10094,21 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
9988
10094
|
beginMarqueeSelection(e);
|
|
9989
10095
|
return;
|
|
9990
10096
|
}
|
|
9991
|
-
var
|
|
9992
|
-
selectedEl &&
|
|
9993
|
-
|
|
9994
|
-
selectedEl.
|
|
9995
|
-
? selectedEl
|
|
9996
|
-
:
|
|
10097
|
+
var selectedAlive =
|
|
10098
|
+
!!selectedEl && document.documentElement.contains(selectedEl);
|
|
10099
|
+
var selectedRect =
|
|
10100
|
+
selectedAlive && selectedEl.getBoundingClientRect
|
|
10101
|
+
? selectedEl.getBoundingClientRect()
|
|
10102
|
+
: null;
|
|
10103
|
+
var dragTarget = dragTargetForPointerDown({
|
|
10104
|
+
selectedEl: selectedEl,
|
|
10105
|
+
selectedAlive: selectedAlive,
|
|
10106
|
+
selectedRect: selectedRect,
|
|
10107
|
+
hitEl: hitTarget,
|
|
10108
|
+
hitRaw: hit,
|
|
10109
|
+
point: { x: e.clientX, y: e.clientY },
|
|
10110
|
+
preferSelected: selectedLayerDragPriorityEnabled,
|
|
10111
|
+
});
|
|
9997
10112
|
var clickTarget = hitTarget;
|
|
9998
10113
|
if (
|
|
9999
10114
|
!dragTarget ||
|
|
@@ -10073,7 +10188,21 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
10073
10188
|
postCrossScreenDrag("cancel");
|
|
10074
10189
|
}
|
|
10075
10190
|
if (ev) stopNativeInteraction(ev);
|
|
10076
|
-
|
|
10191
|
+
// Cmd/Ctrl+click (no Shift) deep-selects the next layer below the current
|
|
10192
|
+
// selection in the z-stack under the pointer, wrapping at the bottom.
|
|
10193
|
+
// Runs here (not in selectElementAtEvent) because a shield click resolves
|
|
10194
|
+
// selection in this onUp and then suppresses the click handler. Selected
|
|
10195
|
+
// plain (no ev) so it replaces the selection rather than adding to it;
|
|
10196
|
+
// Shift-click stays additive via the normal path below.
|
|
10197
|
+
var cycledEl =
|
|
10198
|
+
!readOnly && (e.metaKey || e.ctrlKey) && !e.shiftKey
|
|
10199
|
+
? stackCycleTarget(e.clientX, e.clientY, selectedEl)
|
|
10200
|
+
: null;
|
|
10201
|
+
if (cycledEl) {
|
|
10202
|
+
selectTarget(cycledEl);
|
|
10203
|
+
} else {
|
|
10204
|
+
selectTarget(clickTarget || dragTarget, ev);
|
|
10205
|
+
}
|
|
10077
10206
|
suppressNextShieldClickBriefly();
|
|
10078
10207
|
}
|
|
10079
10208
|
clearPendingShieldDrag();
|
|
@@ -11599,6 +11728,17 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
11599
11728
|
);
|
|
11600
11729
|
return;
|
|
11601
11730
|
}
|
|
11731
|
+
if (e.data.type === "set-selection-chrome-hidden") {
|
|
11732
|
+
selectionChromeHidden = !!e.data.hidden;
|
|
11733
|
+
if (selectionChromeHidden) {
|
|
11734
|
+
hideSelectionOverlay();
|
|
11735
|
+
} else if (selectedEl) {
|
|
11736
|
+
positionOverlay(selectionOverlay, selectedEl);
|
|
11737
|
+
updateParentAutoLayoutOverlay(selectedEl);
|
|
11738
|
+
refreshOverlays();
|
|
11739
|
+
}
|
|
11740
|
+
return;
|
|
11741
|
+
}
|
|
11602
11742
|
if (e.data.type === "select-element") {
|
|
11603
11743
|
var candidates: string[] = [];
|
|
11604
11744
|
if (Array.isArray(e.data.selectorCandidates)) {
|
|
@@ -11650,7 +11790,14 @@ declare var __LIVE_REFLOW_ENABLED__: boolean;
|
|
|
11650
11790
|
hoveredSpacingHandleKey = "";
|
|
11651
11791
|
}
|
|
11652
11792
|
selectedEl = target;
|
|
11653
|
-
|
|
11793
|
+
// Respect a nudge-burst chrome-hide: the host re-sends select-element on
|
|
11794
|
+
// every poll tick, and repeated nudges don't resend hidden:true (its ref
|
|
11795
|
+
// stays set), so a replay must not re-show the overlay on its own.
|
|
11796
|
+
if (selectionChromeHidden) {
|
|
11797
|
+
hideSelectionOverlay();
|
|
11798
|
+
} else {
|
|
11799
|
+
positionOverlay(selectionOverlay, target);
|
|
11800
|
+
}
|
|
11654
11801
|
if (hoveredEl === selectedEl) highlightOverlay.style.display = "none";
|
|
11655
11802
|
// A host-driven selection (e.g. picking a layer in the Layers panel)
|
|
11656
11803
|
// only ever moved the overlay above — it never sent the rich
|
|
@@ -3,14 +3,28 @@ import {
|
|
|
3
3
|
useGuidedQuestionFlow,
|
|
4
4
|
type GuidedQuestionAnswers,
|
|
5
5
|
} from "@agent-native/core/client/agent-chat";
|
|
6
|
+
import { type PromptComposerSubmitOptions } from "@agent-native/core/client/composer";
|
|
6
7
|
import { useCallback } from "react";
|
|
7
8
|
|
|
8
9
|
import { sendToDesignAgentChat } from "@/lib/agent-chat";
|
|
9
10
|
|
|
11
|
+
export interface QuestionFlowModelSelection {
|
|
12
|
+
model?: string;
|
|
13
|
+
engine?: string;
|
|
14
|
+
effort?: PromptComposerSubmitOptions["effort"];
|
|
15
|
+
}
|
|
16
|
+
|
|
10
17
|
interface UseQuestionFlowOptions {
|
|
11
18
|
enabled?: boolean;
|
|
12
19
|
continuationTabId?: string | null;
|
|
13
20
|
onContinue?: (tabId: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* The model this generation started with, read AT SEND TIME. The continuation
|
|
23
|
+
* is the turn that generates and it opens a fresh thread, which has no
|
|
24
|
+
* override to inherit. A getter, not a value: the caller's source is a ref
|
|
25
|
+
* filled after render, so a snapshot taken here would be the pre-kickoff one.
|
|
26
|
+
*/
|
|
27
|
+
getModelSelection?: () => QuestionFlowModelSelection | null | undefined;
|
|
14
28
|
}
|
|
15
29
|
|
|
16
30
|
function designQuestionsStateKey(designId: string | undefined): string {
|
|
@@ -32,6 +46,7 @@ export function useQuestionFlow(
|
|
|
32
46
|
enabled = true,
|
|
33
47
|
continuationTabId,
|
|
34
48
|
onContinue,
|
|
49
|
+
getModelSelection,
|
|
35
50
|
}: UseQuestionFlowOptions = {},
|
|
36
51
|
) {
|
|
37
52
|
const stateKey = designQuestionsStateKey(designId);
|
|
@@ -65,6 +80,8 @@ export function useQuestionFlow(
|
|
|
65
80
|
|
|
66
81
|
const sendContinuation = useCallback(
|
|
67
82
|
(message: string, context?: string) => {
|
|
83
|
+
const selection = getModelSelection?.() ?? {};
|
|
84
|
+
const { model, engine, effort } = selection;
|
|
68
85
|
// Always request `newTab` (mirroring useAgentGenerating.submit's
|
|
69
86
|
// default). Without it, when there is no continuationTabId yet the
|
|
70
87
|
// message goes to whatever tab is currently active, but the id we
|
|
@@ -83,11 +100,14 @@ export function useQuestionFlow(
|
|
|
83
100
|
submit: true,
|
|
84
101
|
newTab: true,
|
|
85
102
|
...(continuationTabId ? { tabId: continuationTabId } : {}),
|
|
103
|
+
...(model ? { model } : {}),
|
|
104
|
+
...(engine ? { engine } : {}),
|
|
105
|
+
...(effort ? { effort } : {}),
|
|
86
106
|
});
|
|
87
107
|
onContinue?.(tabId);
|
|
88
108
|
flow.clear();
|
|
89
109
|
},
|
|
90
|
-
[continuationTabId, flow, onContinue],
|
|
110
|
+
[continuationTabId, designId, flow, getModelSelection, onContinue],
|
|
91
111
|
);
|
|
92
112
|
|
|
93
113
|
const handleSubmit = useCallback(
|
|
@@ -28,7 +28,10 @@ import { toast } from "sonner";
|
|
|
28
28
|
|
|
29
29
|
import SlideRenderer from "@/components/deck/SlideRenderer";
|
|
30
30
|
import { GoogleDocImportHint } from "@/components/editor/GoogleDocImportHint";
|
|
31
|
-
import
|
|
31
|
+
import {
|
|
32
|
+
isInsidePortaledLayer,
|
|
33
|
+
type UploadedFile,
|
|
34
|
+
} from "@/components/editor/PromptDialog";
|
|
32
35
|
import {
|
|
33
36
|
Tooltip,
|
|
34
37
|
TooltipContent,
|
|
@@ -366,6 +369,7 @@ function AddSlidePopover({
|
|
|
366
369
|
useEffect(() => {
|
|
367
370
|
if (!open) return;
|
|
368
371
|
const handleClick = (e: MouseEvent) => {
|
|
372
|
+
if (isInsidePortaledLayer(e.target)) return;
|
|
369
373
|
if (
|
|
370
374
|
panelRef.current &&
|
|
371
375
|
!panelRef.current.contains(e.target as Node) &&
|
|
@@ -64,6 +64,7 @@ import {
|
|
|
64
64
|
type AspectRatio,
|
|
65
65
|
DEFAULT_ASPECT_RATIO,
|
|
66
66
|
} from "@/lib/aspect-ratios";
|
|
67
|
+
import type { GoogleSlidesExportResult } from "@/lib/export-google-slides-client";
|
|
67
68
|
import { parseUploadResponse } from "@/lib/upload-response";
|
|
68
69
|
import { shortcutLabel } from "@/lib/utils";
|
|
69
70
|
|
|
@@ -134,6 +135,8 @@ interface EditorToolbarProps {
|
|
|
134
135
|
onExportPdf?: () => void;
|
|
135
136
|
/** Export the deck as PPTX */
|
|
136
137
|
onExportPptx?: () => Promise<void> | void;
|
|
138
|
+
/** Create the deck in the user's Google Drive as native Google Slides */
|
|
139
|
+
onExportGoogleSlides?: () => Promise<GoogleSlidesExportResult>;
|
|
137
140
|
/** Active deck aspect ratio (defaults to 16:9 when omitted) */
|
|
138
141
|
aspectRatio?: AspectRatio;
|
|
139
142
|
/** Change the deck's aspect ratio */
|
|
@@ -267,6 +270,7 @@ export default function EditorToolbar({
|
|
|
267
270
|
onDuplicateDeck,
|
|
268
271
|
onExportPdf,
|
|
269
272
|
onExportPptx,
|
|
273
|
+
onExportGoogleSlides,
|
|
270
274
|
aspectRatio,
|
|
271
275
|
onSetAspectRatio,
|
|
272
276
|
designSystemTitle,
|
|
@@ -998,6 +1002,7 @@ graph TD
|
|
|
998
1002
|
onDuplicate={onDuplicateDeck ?? (() => {})}
|
|
999
1003
|
onExportPdf={onExportPdf ?? (() => {})}
|
|
1000
1004
|
onExportPptx={onExportPptx ?? (() => {})}
|
|
1005
|
+
onExportGoogleSlides={onExportGoogleSlides}
|
|
1001
1006
|
/>
|
|
1002
1007
|
</div>
|
|
1003
1008
|
|