Spaces:
Running
Running
fixed resize error
Browse files- public/index.html +31 -68
- src/App.scss +4 -5
- src/components/p5/P5WithEditor.tsx +110 -73
- src/components/p5/p5-with-editor.scss +3 -0
public/index.html
CHANGED
|
@@ -51,54 +51,7 @@
|
|
| 51 |
// Store container reference in p5 instance
|
| 52 |
p.containerWidth = container.clientWidth;
|
| 53 |
p.containerHeight = container.clientHeight;
|
| 54 |
-
|
| 55 |
-
let resizeTimeout = null;
|
| 56 |
-
let resizeObserver = null;
|
| 57 |
-
|
| 58 |
-
// Update container dimensions when needed
|
| 59 |
-
const updateContainerSize = () => {
|
| 60 |
-
const rect = container.getBoundingClientRect();
|
| 61 |
-
const newWidth = rect.width;
|
| 62 |
-
const newHeight = rect.height;
|
| 63 |
-
|
| 64 |
-
// Only update if dimensions actually changed
|
| 65 |
-
if (p.containerWidth !== newWidth || p.containerHeight !== newHeight) {
|
| 66 |
-
p.containerWidth = newWidth;
|
| 67 |
-
p.containerHeight = newHeight;
|
| 68 |
-
if (p.windowResized) {
|
| 69 |
-
p.windowResized();
|
| 70 |
-
}
|
| 71 |
-
}
|
| 72 |
-
};
|
| 73 |
-
|
| 74 |
-
// Debounced resize handler
|
| 75 |
-
const debouncedResize = () => {
|
| 76 |
-
if (resizeTimeout) {
|
| 77 |
-
clearTimeout(resizeTimeout);
|
| 78 |
-
}
|
| 79 |
-
resizeTimeout = setTimeout(() => {
|
| 80 |
-
updateContainerSize();
|
| 81 |
-
resizeTimeout = null;
|
| 82 |
-
}, 100); // Debounce for 100ms
|
| 83 |
-
};
|
| 84 |
-
|
| 85 |
-
// Setup resize observer
|
| 86 |
-
const setupResizeObserver = () => {
|
| 87 |
-
if (resizeObserver) {
|
| 88 |
-
resizeObserver.disconnect();
|
| 89 |
-
}
|
| 90 |
-
|
| 91 |
-
resizeObserver = new ResizeObserver((entries) => {
|
| 92 |
-
// Avoid processing if container is hidden or detached
|
| 93 |
-
if (container.offsetParent !== null) {
|
| 94 |
-
window.requestAnimationFrame(() => {
|
| 95 |
-
debouncedResize();
|
| 96 |
-
});
|
| 97 |
-
}
|
| 98 |
-
});
|
| 99 |
-
|
| 100 |
-
resizeObserver.observe(container);
|
| 101 |
-
};
|
| 102 |
|
| 103 |
// Add the sketch code to p5 instance scope
|
| 104 |
const sketchFunction = new Function('p', `
|
|
@@ -118,14 +71,23 @@
|
|
| 118 |
}
|
| 119 |
}
|
| 120 |
|
| 121 |
-
//
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
}
|
| 130 |
`);
|
| 131 |
|
|
@@ -149,25 +111,26 @@
|
|
| 149 |
// Add a custom class to help with styling
|
| 150 |
p._renderer.canvas.classList.add('p5-managed-canvas');
|
| 151 |
}
|
| 152 |
-
|
| 153 |
-
// Setup resize observer after canvas is added
|
| 154 |
-
setupResizeObserver();
|
| 155 |
}
|
| 156 |
};
|
| 157 |
|
| 158 |
p.draw = functions.draw.bind(p);
|
| 159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
|
| 161 |
// Cleanup when sketch is removed
|
| 162 |
p._cleanup = () => {
|
| 163 |
-
|
| 164 |
-
resizeObserver.disconnect();
|
| 165 |
-
resizeObserver = null;
|
| 166 |
-
}
|
| 167 |
-
if (resizeTimeout) {
|
| 168 |
-
clearTimeout(resizeTimeout);
|
| 169 |
-
resizeTimeout = null;
|
| 170 |
-
}
|
| 171 |
};
|
| 172 |
}, container);
|
| 173 |
|
|
|
|
| 51 |
// Store container reference in p5 instance
|
| 52 |
p.containerWidth = container.clientWidth;
|
| 53 |
p.containerHeight = container.clientHeight;
|
| 54 |
+
p.container = container; // Store container reference
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
// Add the sketch code to p5 instance scope
|
| 57 |
const sketchFunction = new Function('p', `
|
|
|
|
| 71 |
}
|
| 72 |
}
|
| 73 |
|
| 74 |
+
// Return all defined p5 functions
|
| 75 |
+
return {
|
| 76 |
+
setup,
|
| 77 |
+
draw,
|
| 78 |
+
// Mouse events
|
| 79 |
+
mousePressed: typeof mousePressed === 'function' ? mousePressed : undefined,
|
| 80 |
+
mouseReleased: typeof mouseReleased === 'function' ? mouseReleased : undefined,
|
| 81 |
+
mouseMoved: typeof mouseMoved === 'function' ? mouseMoved : undefined,
|
| 82 |
+
mouseDragged: typeof mouseDragged === 'function' ? mouseDragged : undefined,
|
| 83 |
+
mouseClicked: typeof mouseClicked === 'function' ? mouseClicked : undefined,
|
| 84 |
+
doubleClicked: typeof doubleClicked === 'function' ? doubleClicked : undefined,
|
| 85 |
+
mouseWheel: typeof mouseWheel === 'function' ? mouseWheel : undefined,
|
| 86 |
+
// Keyboard events
|
| 87 |
+
keyPressed: typeof keyPressed === 'function' ? keyPressed : undefined,
|
| 88 |
+
keyReleased: typeof keyReleased === 'function' ? keyReleased : undefined,
|
| 89 |
+
keyTyped: typeof keyTyped === 'function' ? keyTyped : undefined
|
| 90 |
+
};
|
| 91 |
}
|
| 92 |
`);
|
| 93 |
|
|
|
|
| 111 |
// Add a custom class to help with styling
|
| 112 |
p._renderer.canvas.classList.add('p5-managed-canvas');
|
| 113 |
}
|
|
|
|
|
|
|
|
|
|
| 114 |
}
|
| 115 |
};
|
| 116 |
|
| 117 |
p.draw = functions.draw.bind(p);
|
| 118 |
+
|
| 119 |
+
// Bind all mouse and keyboard event handlers
|
| 120 |
+
if (functions.mousePressed) p.mousePressed = functions.mousePressed.bind(p);
|
| 121 |
+
if (functions.mouseReleased) p.mouseReleased = functions.mouseReleased.bind(p);
|
| 122 |
+
if (functions.mouseMoved) p.mouseMoved = functions.mouseMoved.bind(p);
|
| 123 |
+
if (functions.mouseDragged) p.mouseDragged = functions.mouseDragged.bind(p);
|
| 124 |
+
if (functions.mouseClicked) p.mouseClicked = functions.mouseClicked.bind(p);
|
| 125 |
+
if (functions.doubleClicked) p.doubleClicked = functions.doubleClicked.bind(p);
|
| 126 |
+
if (functions.mouseWheel) p.mouseWheel = functions.mouseWheel.bind(p);
|
| 127 |
+
if (functions.keyPressed) p.keyPressed = functions.keyPressed.bind(p);
|
| 128 |
+
if (functions.keyReleased) p.keyReleased = functions.keyReleased.bind(p);
|
| 129 |
+
if (functions.keyTyped) p.keyTyped = functions.keyTyped.bind(p);
|
| 130 |
|
| 131 |
// Cleanup when sketch is removed
|
| 132 |
p._cleanup = () => {
|
| 133 |
+
// No cleanup needed anymore
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
};
|
| 135 |
}, container);
|
| 136 |
|
src/App.scss
CHANGED
|
@@ -198,12 +198,11 @@ body {
|
|
| 198 |
|
| 199 |
.p5-editor-container {
|
| 200 |
width: 100%;
|
| 201 |
-
height:
|
| 202 |
-
|
| 203 |
-
border: 2px solid var(--gray-600);
|
| 204 |
overflow: hidden;
|
| 205 |
-
|
| 206 |
-
background
|
| 207 |
|
| 208 |
@media (max-width: 1024px) {
|
| 209 |
width: 100%;
|
|
|
|
| 198 |
|
| 199 |
.p5-editor-container {
|
| 200 |
width: 100%;
|
| 201 |
+
height: 600px;
|
| 202 |
+
position: relative;
|
|
|
|
| 203 |
overflow: hidden;
|
| 204 |
+
border-radius: 10px;
|
| 205 |
+
background: #1e1e1e;
|
| 206 |
|
| 207 |
@media (max-width: 1024px) {
|
| 208 |
width: 100%;
|
src/components/p5/P5WithEditor.tsx
CHANGED
|
@@ -27,6 +27,7 @@ declare global {
|
|
| 27 |
initSketch: (container: HTMLElement) => void;
|
| 28 |
updateSketch: (code: string, container: HTMLElement) => boolean;
|
| 29 |
removeSketch: () => void;
|
|
|
|
| 30 |
}
|
| 31 |
}
|
| 32 |
|
|
@@ -47,8 +48,13 @@ function P5WithEditorComponent() {
|
|
| 47 |
const [isSending, setIsSending] = useState(false);
|
| 48 |
const [isAnimatingCode, setIsAnimatingCode] = useState(false);
|
| 49 |
const [cursorPosition, setCursorPosition] = useState<{ lineNumber: number, column: number } | null>(null);
|
|
|
|
| 50 |
const editorRef = useRef<any>(null);
|
| 51 |
const animationTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
// Function to handle editor mounting
|
| 54 |
const handleEditorDidMount = (editor: any) => {
|
|
@@ -190,20 +196,33 @@ function P5WithEditorComponent() {
|
|
| 190 |
// Convert to array if it's not already
|
| 191 |
const partsArray = Array.isArray(parts) ? parts : [parts];
|
| 192 |
|
| 193 |
-
// Check if there's text content
|
| 194 |
const hasTextContent = partsArray.some(part => part.text);
|
| 195 |
|
| 196 |
-
if (hasTextContent
|
| 197 |
// Show sending indicator
|
| 198 |
setIsSending(true);
|
| 199 |
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 207 |
|
| 208 |
// Hide sending indicator after a short delay
|
| 209 |
setTimeout(() => setIsSending(false), 1000);
|
|
@@ -217,7 +236,7 @@ function P5WithEditorComponent() {
|
|
| 217 |
return () => {
|
| 218 |
client.send = originalSend;
|
| 219 |
};
|
| 220 |
-
}, [client, editorContent]);
|
| 221 |
|
| 222 |
useEffect(() => {
|
| 223 |
if (containerRef.current) {
|
|
@@ -314,38 +333,42 @@ function windowResized() {
|
|
| 314 |
}
|
| 315 |
`;
|
| 316 |
|
|
|
|
|
|
|
|
|
|
| 317 |
// Set the editor content and displayed content
|
| 318 |
setEditorContent(testSketch);
|
| 319 |
setDisplayedContent(testSketch);
|
| 320 |
|
| 321 |
// Update the sketch with the test code
|
| 322 |
window.updateSketch(testSketch, containerRef.current);
|
| 323 |
-
}
|
| 324 |
-
|
| 325 |
-
// Cleanup on unmount
|
| 326 |
-
return () => {
|
| 327 |
-
window.removeSketch();
|
| 328 |
-
};
|
| 329 |
-
}, []);
|
| 330 |
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
|
|
|
| 341 |
}
|
| 342 |
}
|
| 343 |
-
}
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 349 |
|
| 350 |
When a user requests a sketch:
|
| 351 |
1. Always use the updateSketch function to create or modify sketches
|
|
@@ -360,31 +383,39 @@ You can create sketches using:
|
|
| 360 |
- Sprite-based games (p5.play library)
|
| 361 |
- Full window canvas with automatic resizing
|
| 362 |
|
|
|
|
|
|
|
| 363 |
Focus on creating visually engaging and interactive experiences. As soon as the user requests a sketch, confirm you heard them, THEN you should create the sketch and then explain what it does and how to interact with it. Be EXTREMELY brief and pithy.`
|
| 364 |
-
|
| 365 |
-
],
|
| 366 |
-
},
|
| 367 |
-
tools: [
|
| 368 |
-
{
|
| 369 |
-
functionDeclarations: [
|
| 370 |
-
{
|
| 371 |
-
name: "updateSketch",
|
| 372 |
-
description: "Create or update the P5.js sketch with new code. The sketch will run in a full-window canvas.",
|
| 373 |
-
parameters: {
|
| 374 |
-
type: SchemaType.OBJECT,
|
| 375 |
-
properties: {
|
| 376 |
-
sketch: {
|
| 377 |
-
type: SchemaType.STRING,
|
| 378 |
-
description: "Complete P5.js sketch code including all variable declarations, setup(), draw(), and any additional functions needed. The code should be a complete, self-contained sketch."
|
| 379 |
-
}
|
| 380 |
-
},
|
| 381 |
-
required: ["sketch"]
|
| 382 |
-
}
|
| 383 |
-
}
|
| 384 |
],
|
| 385 |
},
|
| 386 |
-
|
| 387 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 388 |
}, [setConfig]);
|
| 389 |
|
| 390 |
useEffect(() => {
|
|
@@ -487,22 +518,30 @@ Focus on creating visually engaging and interactive experiences. As soon as the
|
|
| 487 |
return;
|
| 488 |
}
|
| 489 |
|
| 490 |
-
// Always update
|
| 491 |
setEditorContent(value);
|
| 492 |
setDisplayedContent(value);
|
| 493 |
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
| 497 |
}
|
| 498 |
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 506 |
};
|
| 507 |
|
| 508 |
const startResizing = useCallback((e: React.MouseEvent) => {
|
|
@@ -527,13 +566,11 @@ Focus on creating visually engaging and interactive experiences. As soon as the
|
|
| 527 |
const newWidth = (e.clientX / containerWidth) * 100;
|
| 528 |
setEditorWidth(Math.min(Math.max(20, newWidth), 80)); // Limit between 20% and 80%
|
| 529 |
|
| 530 |
-
//
|
| 531 |
-
if (containerRef.current) {
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
window.dispatchEvent(event);
|
| 536 |
-
}, 50);
|
| 537 |
}
|
| 538 |
}
|
| 539 |
}
|
|
|
|
| 27 |
initSketch: (container: HTMLElement) => void;
|
| 28 |
updateSketch: (code: string, container: HTMLElement) => boolean;
|
| 29 |
removeSketch: () => void;
|
| 30 |
+
mySketch: any;
|
| 31 |
}
|
| 32 |
}
|
| 33 |
|
|
|
|
| 48 |
const [isSending, setIsSending] = useState(false);
|
| 49 |
const [isAnimatingCode, setIsAnimatingCode] = useState(false);
|
| 50 |
const [cursorPosition, setCursorPosition] = useState<{ lineNumber: number, column: number } | null>(null);
|
| 51 |
+
const [isFirstQuestion, setIsFirstQuestion] = useState(true); // Track if this is the first question
|
| 52 |
const editorRef = useRef<any>(null);
|
| 53 |
const animationTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
| 54 |
+
const updateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
| 55 |
+
|
| 56 |
+
// Store test sketch reference
|
| 57 |
+
const testSketchRef = useRef<string>("");
|
| 58 |
|
| 59 |
// Function to handle editor mounting
|
| 60 |
const handleEditorDidMount = (editor: any) => {
|
|
|
|
| 196 |
// Convert to array if it's not already
|
| 197 |
const partsArray = Array.isArray(parts) ? parts : [parts];
|
| 198 |
|
| 199 |
+
// Check if there's text content
|
| 200 |
const hasTextContent = partsArray.some(part => part.text);
|
| 201 |
|
| 202 |
+
if (hasTextContent) {
|
| 203 |
// Show sending indicator
|
| 204 |
setIsSending(true);
|
| 205 |
|
| 206 |
+
if (isFirstQuestion) {
|
| 207 |
+
// For the first question, include the initial test sketch code
|
| 208 |
+
const sketchToUse = testSketchRef.current || editorContent;
|
| 209 |
+
const formattedCode = formatCodeForModel(sketchToUse);
|
| 210 |
+
|
| 211 |
+
// Add the test sketch as context for the first question
|
| 212 |
+
partsArray.push({
|
| 213 |
+
text: `\n\n--- CURRENT P5.JS CODE IN EDITOR ---\n\`\`\`javascript\n${formattedCode}\n\`\`\`\n\nPlease use this code as a starting point. You can modify or improve it based on my request.`
|
| 214 |
+
});
|
| 215 |
+
|
| 216 |
+
// Mark first question as used
|
| 217 |
+
setIsFirstQuestion(false);
|
| 218 |
+
} else if (editorContent) {
|
| 219 |
+
// For subsequent questions, use the current editor content
|
| 220 |
+
const formattedCode = formatCodeForModel(editorContent);
|
| 221 |
+
|
| 222 |
+
partsArray.push({
|
| 223 |
+
text: `\n\n--- CURRENT P5.JS CODE IN EDITOR ---\n\`\`\`javascript\n${formattedCode}\n\`\`\`\n\nPlease consider this code when responding to my request. If I'm asking for changes or improvements, use this as the starting point.`
|
| 224 |
+
});
|
| 225 |
+
}
|
| 226 |
|
| 227 |
// Hide sending indicator after a short delay
|
| 228 |
setTimeout(() => setIsSending(false), 1000);
|
|
|
|
| 236 |
return () => {
|
| 237 |
client.send = originalSend;
|
| 238 |
};
|
| 239 |
+
}, [client, editorContent, isFirstQuestion]);
|
| 240 |
|
| 241 |
useEffect(() => {
|
| 242 |
if (containerRef.current) {
|
|
|
|
| 333 |
}
|
| 334 |
`;
|
| 335 |
|
| 336 |
+
// Store test sketch in the ref for later use
|
| 337 |
+
testSketchRef.current = testSketch;
|
| 338 |
+
|
| 339 |
// Set the editor content and displayed content
|
| 340 |
setEditorContent(testSketch);
|
| 341 |
setDisplayedContent(testSketch);
|
| 342 |
|
| 343 |
// Update the sketch with the test code
|
| 344 |
window.updateSketch(testSketch, containerRef.current);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 345 |
|
| 346 |
+
// Configure the model with the test sketch included in the system instruction
|
| 347 |
+
setConfig({
|
| 348 |
+
model: "models/gemini-2.0-flash-exp",
|
| 349 |
+
generationConfig: {
|
| 350 |
+
temperature: 0.1,
|
| 351 |
+
responseModalities: "audio",
|
| 352 |
+
speechConfig: {
|
| 353 |
+
voiceConfig: {
|
| 354 |
+
prebuiltVoiceConfig: {
|
| 355 |
+
voiceName: "Puck"
|
| 356 |
+
}
|
| 357 |
}
|
| 358 |
}
|
| 359 |
+
},
|
| 360 |
+
systemInstruction: {
|
| 361 |
+
parts: [
|
| 362 |
+
{
|
| 363 |
+
text: `You are a P5.js creative coding expert that helps users create interactive sketches.
|
| 364 |
+
|
| 365 |
+
INITIAL CODE IN EDITOR:
|
| 366 |
+
\`\`\`javascript
|
| 367 |
+
${testSketch}
|
| 368 |
+
\`\`\`
|
| 369 |
+
|
| 370 |
+
When the user asks their first question, use the above code as a starting point. Modify it based on their request.
|
| 371 |
+
Your responses should be direct, helpful, and technically accurate. Users are looking for creative coding help with p5.js sketches.
|
| 372 |
|
| 373 |
When a user requests a sketch:
|
| 374 |
1. Always use the updateSketch function to create or modify sketches
|
|
|
|
| 383 |
- Sprite-based games (p5.play library)
|
| 384 |
- Full window canvas with automatic resizing
|
| 385 |
|
| 386 |
+
In the setup() function, ALWAYS use the createCanvas(containerWidth, containerHeight) function to create the canvas. DO NOT EVER use windowWidth or windowHeight.
|
| 387 |
+
|
| 388 |
Focus on creating visually engaging and interactive experiences. As soon as the user requests a sketch, confirm you heard them, THEN you should create the sketch and then explain what it does and how to interact with it. Be EXTREMELY brief and pithy.`
|
| 389 |
+
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 390 |
],
|
| 391 |
},
|
| 392 |
+
tools: [
|
| 393 |
+
{
|
| 394 |
+
functionDeclarations: [
|
| 395 |
+
{
|
| 396 |
+
name: "updateSketch",
|
| 397 |
+
description: "Create or update the P5.js sketch with new code. The sketch will run in a full-window canvas.",
|
| 398 |
+
parameters: {
|
| 399 |
+
type: SchemaType.OBJECT,
|
| 400 |
+
properties: {
|
| 401 |
+
sketch: {
|
| 402 |
+
type: SchemaType.STRING,
|
| 403 |
+
description: "Complete P5.js sketch code including all variable declarations, setup(), draw(), and any additional functions needed. The code should be a complete, self-contained sketch. In the setup() function, ALWAYS use the createCanvas(containerWidth, containerHeight) function to create the canvas. DO NOT EVER use windowWidth or windowHeight."
|
| 404 |
+
}
|
| 405 |
+
},
|
| 406 |
+
required: ["sketch"]
|
| 407 |
+
}
|
| 408 |
+
}
|
| 409 |
+
],
|
| 410 |
+
},
|
| 411 |
+
],
|
| 412 |
+
});
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
// Cleanup on unmount
|
| 416 |
+
return () => {
|
| 417 |
+
window.removeSketch();
|
| 418 |
+
};
|
| 419 |
}, [setConfig]);
|
| 420 |
|
| 421 |
useEffect(() => {
|
|
|
|
| 518 |
return;
|
| 519 |
}
|
| 520 |
|
| 521 |
+
// Always update editor content immediately for responsiveness
|
| 522 |
setEditorContent(value);
|
| 523 |
setDisplayedContent(value);
|
| 524 |
|
| 525 |
+
// Clear any existing timeout
|
| 526 |
+
if (updateTimeoutRef.current) {
|
| 527 |
+
clearTimeout(updateTimeoutRef.current);
|
| 528 |
}
|
| 529 |
|
| 530 |
+
// Debounce the sketch update
|
| 531 |
+
updateTimeoutRef.current = setTimeout(() => {
|
| 532 |
+
if (!containerRef.current) {
|
| 533 |
+
console.warn("Container ref is not available");
|
| 534 |
+
return;
|
| 535 |
+
}
|
| 536 |
+
|
| 537 |
+
try {
|
| 538 |
+
console.log("Updating sketch from editor");
|
| 539 |
+
const result = window.updateSketch(value, containerRef.current);
|
| 540 |
+
console.log("Editor update result:", result);
|
| 541 |
+
} catch (error) {
|
| 542 |
+
console.error("Error updating sketch from editor:", error);
|
| 543 |
+
}
|
| 544 |
+
}, 1000); // Wait for 1 second of no changes before updating
|
| 545 |
};
|
| 546 |
|
| 547 |
const startResizing = useCallback((e: React.MouseEvent) => {
|
|
|
|
| 566 |
const newWidth = (e.clientX / containerWidth) * 100;
|
| 567 |
setEditorWidth(Math.min(Math.max(20, newWidth), 80)); // Limit between 20% and 80%
|
| 568 |
|
| 569 |
+
// Update sketch dimensions directly if needed
|
| 570 |
+
if (containerRef.current && window.mySketch) {
|
| 571 |
+
window.mySketch.containerWidth = containerRef.current.clientWidth;
|
| 572 |
+
window.mySketch.containerHeight = containerRef.current.clientHeight;
|
| 573 |
+
window.mySketch.resizeCanvas(window.mySketch.containerWidth, window.mySketch.containerHeight);
|
|
|
|
|
|
|
| 574 |
}
|
| 575 |
}
|
| 576 |
}
|
src/components/p5/p5-with-editor.scss
CHANGED
|
@@ -5,6 +5,7 @@
|
|
| 5 |
overflow: hidden;
|
| 6 |
position: relative;
|
| 7 |
border-radius: 10px;
|
|
|
|
| 8 |
|
| 9 |
@media (max-width: 768px) {
|
| 10 |
flex-direction: column;
|
|
@@ -107,6 +108,7 @@
|
|
| 107 |
position: relative;
|
| 108 |
background: #000;
|
| 109 |
overflow: hidden;
|
|
|
|
| 110 |
|
| 111 |
canvas {
|
| 112 |
display: block !important;
|
|
@@ -115,6 +117,7 @@
|
|
| 115 |
position: relative !important;
|
| 116 |
margin: auto;
|
| 117 |
object-fit: contain;
|
|
|
|
| 118 |
}
|
| 119 |
|
| 120 |
// Fix for p5.js accessibility tooltips
|
|
|
|
| 5 |
overflow: hidden;
|
| 6 |
position: relative;
|
| 7 |
border-radius: 10px;
|
| 8 |
+
border: 2px solid #2d2d2d;
|
| 9 |
|
| 10 |
@media (max-width: 768px) {
|
| 11 |
flex-direction: column;
|
|
|
|
| 108 |
position: relative;
|
| 109 |
background: #000;
|
| 110 |
overflow: hidden;
|
| 111 |
+
pointer-events: auto;
|
| 112 |
|
| 113 |
canvas {
|
| 114 |
display: block !important;
|
|
|
|
| 117 |
position: relative !important;
|
| 118 |
margin: auto;
|
| 119 |
object-fit: contain;
|
| 120 |
+
pointer-events: auto;
|
| 121 |
}
|
| 122 |
|
| 123 |
// Fix for p5.js accessibility tooltips
|