Add MindSpace visual page editor and Plaza local Tunnel deployment.
In-preview HTML editing with undo/redo sync replaces Agent patch auto-save; Plaza runs on local Mac via Cloudflare Tunnel with embed height and CSP fixes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { fetchMindSpacePageDraftPreview } from '../api/client';
|
||||
import { bindIframeDocumentHeightSync } from '../utils/iframeContentHeight';
|
||||
import { applyPageChangeHighlight } from '../utils/mindspacePageChangeHighlight';
|
||||
|
||||
export type MindSpacePreviewChangeHighlight = {
|
||||
@@ -15,8 +16,9 @@ export function MindSpacePageDraftPreviewFrame({
|
||||
content,
|
||||
templateId,
|
||||
reloadKey = 0,
|
||||
liveUpdate = true,
|
||||
minHeight = 680,
|
||||
maxHeight = 4800,
|
||||
maxHeight = 12000,
|
||||
className = 'mindspace-page-preview-frame',
|
||||
changeHighlight = null,
|
||||
}: {
|
||||
@@ -26,6 +28,7 @@ export function MindSpacePageDraftPreviewFrame({
|
||||
content: string;
|
||||
templateId: string;
|
||||
reloadKey?: number;
|
||||
liveUpdate?: boolean;
|
||||
minHeight?: number;
|
||||
maxHeight?: number;
|
||||
className?: string;
|
||||
@@ -62,7 +65,9 @@ export function MindSpacePageDraftPreviewFrame({
|
||||
}, hasRenderedRef.current ? 450 : 120);
|
||||
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [pageId, title, summary, content, templateId, reloadKey]);
|
||||
}, liveUpdate
|
||||
? [pageId, title, summary, content, templateId, reloadKey]
|
||||
: [pageId, reloadKey, templateId]);
|
||||
|
||||
useEffect(() => {
|
||||
setHeight(minHeight);
|
||||
@@ -72,27 +77,16 @@ export function MindSpacePageDraftPreviewFrame({
|
||||
const iframe = iframeRef.current;
|
||||
if (!iframe || !srcdoc) return;
|
||||
|
||||
const syncHeight = () => {
|
||||
try {
|
||||
const doc = iframe.contentDocument;
|
||||
if (!doc) return;
|
||||
const body = doc.body;
|
||||
const root = doc.documentElement;
|
||||
const next = Math.ceil(
|
||||
Math.max(
|
||||
body?.scrollHeight ?? 0,
|
||||
body?.offsetHeight ?? 0,
|
||||
root?.scrollHeight ?? 0,
|
||||
root?.offsetHeight ?? 0,
|
||||
minHeight,
|
||||
),
|
||||
);
|
||||
setHeight(Math.min(next, maxHeight));
|
||||
const applyHeight = (nextHeight: number) => {
|
||||
setHeight(nextHeight);
|
||||
|
||||
if (
|
||||
changeHighlight &&
|
||||
appliedHighlightRevisionRef.current !== changeHighlight.revision
|
||||
) {
|
||||
if (
|
||||
changeHighlight &&
|
||||
appliedHighlightRevisionRef.current !== changeHighlight.revision
|
||||
) {
|
||||
try {
|
||||
const doc = iframe.contentDocument;
|
||||
if (!doc) return;
|
||||
appliedHighlightRevisionRef.current = changeHighlight.revision;
|
||||
applyPageChangeHighlight(doc, {
|
||||
previousTitle: changeHighlight.previousTitle,
|
||||
@@ -100,14 +94,17 @@ export function MindSpacePageDraftPreviewFrame({
|
||||
previousContent: changeHighlight.previousContent,
|
||||
nextContent: content,
|
||||
});
|
||||
} catch {
|
||||
// ignore highlight errors in sandboxed preview
|
||||
}
|
||||
} catch {
|
||||
setHeight(minHeight);
|
||||
}
|
||||
};
|
||||
|
||||
iframe.addEventListener('load', syncHeight);
|
||||
return () => iframe.removeEventListener('load', syncHeight);
|
||||
return bindIframeDocumentHeightSync(iframe, {
|
||||
minHeight,
|
||||
maxHeight,
|
||||
onHeight: applyHeight,
|
||||
});
|
||||
}, [changeHighlight, content, maxHeight, minHeight, srcdoc, title]);
|
||||
|
||||
if (error) {
|
||||
|
||||
Reference in New Issue
Block a user