updated stuff
This commit is contained in:
@@ -492,7 +492,7 @@ export function Artboard({
|
||||
onSnapshotReady={(dataUrl, nodeId) => setElementSnapshot(id, nodeId, dataUrl)}
|
||||
/>
|
||||
|
||||
{/* Static-page banner — shown when the proxy serves a non-React page */}
|
||||
{/* Static-page banner — shown when no React commits arrive after load */}
|
||||
{isStaticPage && (
|
||||
<div style={{
|
||||
position: 'absolute', bottom: 0, left: 0, right: 0,
|
||||
@@ -505,7 +505,9 @@ export function Artboard({
|
||||
fontFamily: "'JetBrains Mono', monospace", fontSize: '0.5875rem',
|
||||
color: '#1C1917', letterSpacing: '-0.01em',
|
||||
}}>
|
||||
Static HTML page — no React components detected. Navigate to a React route to enable inspection.
|
||||
No React detected — add{' '}
|
||||
<strong>import "@originmain/live"</strong>
|
||||
{' '}before React in your app, then redeploy.
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -472,9 +472,10 @@ export function Canvas() {
|
||||
}
|
||||
|
||||
/* ── URL onboarding overlay ───────────────────────────────── */
|
||||
// Shown when the canvas has no artboards. Lets the user paste their CLI proxy
|
||||
// URL to auto-create the first artboard; route discovery will then fire and
|
||||
// populate the remaining pages automatically.
|
||||
// Shown when the canvas has no artboards. Lets the user paste their app URL
|
||||
// (Vercel, Netlify, or any deployment where @originmain/live is installed).
|
||||
// Route discovery fires after the first React commit and populates remaining
|
||||
// pages automatically.
|
||||
function UrlOnboardingOverlay({
|
||||
workspaceId,
|
||||
projectId,
|
||||
@@ -547,18 +548,30 @@ function UrlOnboardingOverlay({
|
||||
Connect your app
|
||||
</div>
|
||||
<div style={{ fontFamily: "'Inter', sans-serif", fontSize: '0.7rem', color: 'rgba(255,255,255,0.35)', lineHeight: 1.5 }}>
|
||||
Paste the CLI proxy URL — all your app's pages will be auto-rendered as artboards
|
||||
Paste your app URL — all your pages will be auto-rendered as artboards
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* CLI hint */}
|
||||
<div style={{
|
||||
width: '100%', padding: '6px 10px',
|
||||
background: 'rgba(51,133,255,0.08)', border: '1px solid rgba(51,133,255,0.18)',
|
||||
borderRadius: 6, fontFamily: "'JetBrains Mono', monospace",
|
||||
fontSize: '0.5625rem', color: 'rgba(51,133,255,0.75)', letterSpacing: '-0.01em',
|
||||
}}>
|
||||
npx @originmain/cli dev --target http://localhost:3000
|
||||
{/* SDK install hint */}
|
||||
<div style={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 4 }}>
|
||||
<div style={{
|
||||
padding: '6px 10px',
|
||||
background: 'rgba(51,133,255,0.08)', border: '1px solid rgba(51,133,255,0.18)',
|
||||
borderRadius: 6, fontFamily: "'JetBrains Mono', monospace",
|
||||
fontSize: '0.5625rem', color: 'rgba(51,133,255,0.75)', letterSpacing: '-0.01em',
|
||||
}}>
|
||||
npm install @originmain/live
|
||||
</div>
|
||||
<div style={{
|
||||
padding: '6px 10px',
|
||||
background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.08)',
|
||||
borderRadius: 6, fontFamily: "'JetBrains Mono', monospace",
|
||||
fontSize: '0.5625rem', color: 'rgba(255,255,255,0.35)', letterSpacing: '-0.01em',
|
||||
}}>
|
||||
{'// layout.tsx — must be before React'}
|
||||
<br />
|
||||
{'import "@originmain/live";'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* URL input */}
|
||||
@@ -569,7 +582,7 @@ function UrlOnboardingOverlay({
|
||||
value={url}
|
||||
onChange={e => { setUrl(e.target.value); setErrorMsg(''); }}
|
||||
onKeyDown={e => { if (e.key === 'Enter') void handleConnect(); e.stopPropagation(); }}
|
||||
placeholder="http://localhost:4170"
|
||||
placeholder="https://your-app.vercel.app"
|
||||
style={{
|
||||
flex: 1, background: 'rgba(255,255,255,0.05)',
|
||||
border: '1px solid rgba(255,255,255,0.12)', borderRadius: 6,
|
||||
|
||||
@@ -206,6 +206,9 @@ export function LiveArtboard({
|
||||
const removeElementEvent = useCanvas((s) => s.removeElementEvent);
|
||||
const clearRemoveElement = useCanvas((s) => s.clearRemoveElement);
|
||||
|
||||
// Ref so the refresh timer can be cancelled when a faster patch arrives.
|
||||
const styleRefreshTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const mine = styleEditQueue.filter((e) => e.artboardId === id);
|
||||
if (mine.length === 0 || !isReadyRef.current) return;
|
||||
@@ -213,6 +216,17 @@ export function LiveArtboard({
|
||||
sendMessage('PATCH_ELEMENT_STYLE', { nodeId: e.nodeId, property: e.property, value: e.value });
|
||||
}
|
||||
clearStyleEdits(id);
|
||||
|
||||
// Refresh the design panel after the browser has applied the inline styles.
|
||||
// We debounce at 120 ms so rapid dragging (color picker, resize) only fires
|
||||
// one REQUEST_ELEMENT_STYLES at the end of the gesture, not on every event.
|
||||
if (styleRefreshTimerRef.current) clearTimeout(styleRefreshTimerRef.current);
|
||||
styleRefreshTimerRef.current = setTimeout(() => {
|
||||
const nodeId = mine[mine.length - 1]?.nodeId;
|
||||
if (nodeId && isReadyRef.current) {
|
||||
sendMessage('REQUEST_ELEMENT_STYLES', { nodeId });
|
||||
}
|
||||
}, 120);
|
||||
}, [id, styleEditQueue, sendMessage, clearStyleEdits]);
|
||||
|
||||
// ── Children style edit queue (PATCH_CHILDREN_STYLE — paragraph spacing etc.) ──
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useState, useMemo, useEffect } from 'react';
|
||||
import { Badge } from '@fluentui/react-components';
|
||||
import { useCanvas } from '@/store/canvas';
|
||||
import { useCanvasTheme } from '@/store/canvasTheme';
|
||||
import { useHistory } from '@/store/history';
|
||||
import { useDlf } from '@/hooks/useDlf';
|
||||
import { checkComponentConstraints } from '@originmain/design-language';
|
||||
import type { Violation } from '@originmain/design-language';
|
||||
@@ -92,11 +93,13 @@ export function DesignTab({
|
||||
const {
|
||||
patchStyleEdit,
|
||||
patchChildrenStyleEdit,
|
||||
setComponentStyles,
|
||||
indexerStatus,
|
||||
selectedComponentHasDirectText,
|
||||
selectedComponentHasParagraphChildren,
|
||||
setActiveViolations,
|
||||
} = useCanvas();
|
||||
const { pushEdit } = useHistory();
|
||||
const { dlf } = useDlf(workspaceId);
|
||||
|
||||
// Re-run constraint checks whenever selected component or active DLF changes.
|
||||
@@ -149,9 +152,35 @@ export function DesignTab({
|
||||
);
|
||||
}
|
||||
|
||||
// ── patch: design panel → live artboard + history + optimistic panel refresh ──
|
||||
// Three things happen on every edit:
|
||||
// 1. patchStyleEdit → PATCH_ELEMENT_STYLE → SDK → inline style on DOM element
|
||||
// 2. setComponentStyles (optimistic) → panel inputs immediately show the new
|
||||
// value without waiting for the next REQUEST_ELEMENT_STYLES round-trip
|
||||
// 3. pushEdit → history store → Diff tab tracks it → code export works
|
||||
const patch = (prop: string, val: string) => {
|
||||
if (!artboardId || !componentId) return;
|
||||
|
||||
// 1. Send to iframe.
|
||||
patchStyleEdit(artboardId, componentId, prop, val);
|
||||
|
||||
// 2. Optimistically reflect the change in the design panel immediately.
|
||||
if (styles) {
|
||||
setComponentStyles({ ...styles, [prop]: val });
|
||||
}
|
||||
|
||||
// 3. Push to history so the Diff tab can generate a code patch.
|
||||
pushEdit(artboardId, {
|
||||
componentId,
|
||||
componentName: componentData?.name ?? componentId,
|
||||
changes: [{
|
||||
key: prop,
|
||||
before: styles?.[prop] ?? '',
|
||||
after: val,
|
||||
changeType: 'modified',
|
||||
}],
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
};
|
||||
|
||||
const patchChildren = (selector: string, prop: string, val: string) => {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user