refactor(site-builder): extract HtmlCodeField out of GenericPropsEditor
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
TEXT_COLORS,
|
TEXT_COLORS,
|
||||||
BG_COLORS,
|
BG_COLORS,
|
||||||
@@ -17,79 +17,7 @@ import {
|
|||||||
useNodeProp,
|
useNodeProp,
|
||||||
} from './shared';
|
} from './shared';
|
||||||
import { ArrayItemFieldsEditor } from './ArrayItemFields';
|
import { ArrayItemFieldsEditor } from './ArrayItemFields';
|
||||||
import { Modal } from '../../../ui/Modal';
|
import { HtmlCodeField } from './HtmlCodeField';
|
||||||
import { CodeEditor } from '../../../ui/CodeEditor';
|
|
||||||
|
|
||||||
/* ---------- "Edit HTML" modal for the HtmlBlock `code` prop ----------
|
|
||||||
`code` is raw HTML (potentially many lines, embedded <style>/<script>),
|
|
||||||
so it gets a dedicated syntax-highlighted CodeEditor in a modal instead
|
|
||||||
of falling into the generic single-line/textarea string-prop rendering
|
|
||||||
below (see GenericPropsEditor's SKIP of the `code` key). */
|
|
||||||
const HtmlCodeField: React.FC<{ value: string; onChange: (v: string) => void }> = ({ value, onChange }) => {
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
return (
|
|
||||||
<CollapsibleSection title="HTML Code">
|
|
||||||
<div style={sectionGap}>
|
|
||||||
<button
|
|
||||||
onClick={() => setOpen(true)}
|
|
||||||
style={{
|
|
||||||
width: '100%', padding: '8px 12px', fontSize: 12, fontWeight: 600,
|
|
||||||
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
|
|
||||||
background: '#27272a', color: '#e4e4e7', border: '1px solid #3f3f46',
|
|
||||||
borderRadius: 6, cursor: 'pointer',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i className="fa fa-code" /> Edit HTML
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<Modal open={open} onClose={() => setOpen(false)} width="min(720px, 90vw)">
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
background: 'var(--color-bg-surface)',
|
|
||||||
border: '1px solid var(--color-border)',
|
|
||||||
borderRadius: 12,
|
|
||||||
boxShadow: '0 20px 60px rgba(0,0,0,0.5)',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<div style={{
|
|
||||||
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
|
||||||
padding: '14px 16px', borderBottom: '1px solid var(--color-border)',
|
|
||||||
}}>
|
|
||||||
<div style={{ fontSize: 14, fontWeight: 600, color: 'var(--color-text)' }}>Edit HTML</div>
|
|
||||||
<button
|
|
||||||
onClick={() => setOpen(false)}
|
|
||||||
style={{
|
|
||||||
width: 28, height: 28, display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
|
|
||||||
background: 'none', border: '1px solid var(--color-border)', borderRadius: 6,
|
|
||||||
color: 'var(--color-text-muted)', cursor: 'pointer', fontSize: 13,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i className="fa fa-times" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div style={{ padding: 16 }}>
|
|
||||||
<CodeEditor value={value} onChange={onChange} language="html" height={420} />
|
|
||||||
</div>
|
|
||||||
<div style={{ padding: '10px 16px', borderTop: '1px solid var(--color-border)', display: 'flex', justifyContent: 'flex-end' }}>
|
|
||||||
<button
|
|
||||||
onClick={() => setOpen(false)}
|
|
||||||
style={{
|
|
||||||
padding: '7px 20px', fontSize: 13, fontWeight: 600,
|
|
||||||
background: 'var(--color-accent)', color: '#fff', border: 'none', borderRadius: 6, cursor: 'pointer',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Done
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</CollapsibleSection>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ---------- SMART GENERIC PROPS EDITOR (Fallback) ---------- */
|
/* ---------- SMART GENERIC PROPS EDITOR (Fallback) ---------- */
|
||||||
export const GenericPropsEditor: React.FC<{ selectedId: string; nodeProps: Record<string, any>; typeName: string }> = ({
|
export const GenericPropsEditor: React.FC<{ selectedId: string; nodeProps: Record<string, any>; typeName: string }> = ({
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { CollapsibleSection, sectionGap } from './shared';
|
||||||
|
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>/<script>), so it gets a
|
||||||
|
dedicated syntax-highlighted CodeEditor in a modal rather than the
|
||||||
|
generic single-line/textarea string-prop rendering. */
|
||||||
|
export const HtmlCodeField: React.FC<{ value: string; onChange: (v: string) => void }> = ({ value, onChange }) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
return (
|
||||||
|
<CollapsibleSection title="HTML Code">
|
||||||
|
<div style={sectionGap}>
|
||||||
|
<button
|
||||||
|
onClick={() => setOpen(true)}
|
||||||
|
style={{
|
||||||
|
width: '100%', padding: '8px 12px', fontSize: 12, fontWeight: 600,
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
|
||||||
|
background: '#27272a', color: '#e4e4e7', border: '1px solid #3f3f46',
|
||||||
|
borderRadius: 6, cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fa fa-code" /> Edit HTML
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Modal open={open} onClose={() => setOpen(false)} width="min(720px, 90vw)">
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: 'var(--color-bg-surface)',
|
||||||
|
border: '1px solid var(--color-border)',
|
||||||
|
borderRadius: 12,
|
||||||
|
boxShadow: '0 20px 60px rgba(0,0,0,0.5)',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<div style={{
|
||||||
|
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||||
|
padding: '14px 16px', borderBottom: '1px solid var(--color-border)',
|
||||||
|
}}>
|
||||||
|
<div style={{ fontSize: 14, fontWeight: 600, color: 'var(--color-text)' }}>Edit HTML</div>
|
||||||
|
<button
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
|
style={{
|
||||||
|
width: 28, height: 28, display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
background: 'none', border: '1px solid var(--color-border)', borderRadius: 6,
|
||||||
|
color: 'var(--color-text-muted)', cursor: 'pointer', fontSize: 13,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="fa fa-times" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div style={{ padding: 16 }}>
|
||||||
|
<CodeEditor value={value} onChange={onChange} language="html" height={420} />
|
||||||
|
</div>
|
||||||
|
<div style={{ padding: '10px 16px', borderTop: '1px solid var(--color-border)', display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
|
<button
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
|
style={{
|
||||||
|
padding: '7px 20px', fontSize: 13, fontWeight: 600,
|
||||||
|
background: 'var(--color-accent)', color: '#fff', border: 'none', borderRadius: 6, cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Done
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</CollapsibleSection>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user