diff --git a/craft/src/panels/right/styles/GenericPropsEditor.tsx b/craft/src/panels/right/styles/GenericPropsEditor.tsx index ddba296..ed0233b 100644 --- a/craft/src/panels/right/styles/GenericPropsEditor.tsx +++ b/craft/src/panels/right/styles/GenericPropsEditor.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { TEXT_COLORS, BG_COLORS, @@ -17,12 +17,85 @@ import { useNodeProp, } from './shared'; import { ArrayItemFieldsEditor } from './ArrayItemFields'; +import { Modal } from '../../../ui/Modal'; +import { CodeEditor } from '../../../ui/CodeEditor'; + +/* ---------- "Edit HTML" modal for the HtmlBlock `code` prop ---------- + `code` is raw HTML (potentially many lines, embedded "} - style={{ - flex: 1, - minHeight: 300, - padding: 14, - background: '#0d0d0f', - color: '#e4e4e7', - border: '1px solid #3f3f46', - borderRadius: 8, - fontFamily: 'Source Code Pro, Consolas, monospace', - fontSize: 13, - lineHeight: 1.6, - resize: 'vertical', - outline: 'none', - tabSize: 2, - }} - spellCheck={false} - /> +
+ updateDesign({ headCode: code })} + language="html" + height="100%" + placeholder={"\n\n\n\n\n\n"} + /> +
{/* Footer */} diff --git a/craft/src/ui/CodeEditor.test.tsx b/craft/src/ui/CodeEditor.test.tsx new file mode 100644 index 0000000..7c8516f --- /dev/null +++ b/craft/src/ui/CodeEditor.test.tsx @@ -0,0 +1,90 @@ +import { describe, test, expect, vi, afterEach } from 'vitest'; +import React from 'react'; +import { createRoot, Root } from 'react-dom/client'; +import { act } from 'react-dom/test-utils'; +import { CodeEditor } from './CodeEditor'; + +/* ---------- DOM test harness (no @testing-library/react in this repo; see + src/ui/AssetPicker.test.tsx / src/ui/Modal.test.tsx for the same + react-dom/client + react-dom/test-utils `act` pattern). ---------- + + CodeMirror is loaded via dynamic import() (see CodeEditor.tsx), which is + always async -- even for an already-resolved/cached module, `import()` + only settles on a later microtask. That means immediately after the + initial synchronous `act(() => root.render(...))` below, the component is + still in its 'loading' state and renders the