Merge PR #16: enh code editor
This commit was merged in pull request #16.
This commit is contained in:
@@ -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>/<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) ---------- */
|
||||
export const GenericPropsEditor: React.FC<{ selectedId: string; nodeProps: Record<string, any>; typeName: string }> = ({
|
||||
selectedId, nodeProps, typeName,
|
||||
}) => {
|
||||
const SKIP_PROPS = new Set(['style', 'children', 'cssId', 'cssClass']);
|
||||
const SKIP_PROPS = new Set(['style', 'children', 'cssId', 'cssClass', 'code']);
|
||||
|
||||
const { setProp: setPropValue, setPropStyle: setStyleValue } = useNodeProp(selectedId);
|
||||
|
||||
@@ -35,9 +108,15 @@ export const GenericPropsEditor: React.FC<{ selectedId: string; nodeProps: Recor
|
||||
const arrayProps = allProps.filter(([_, val]) => Array.isArray(val));
|
||||
|
||||
const style = nodeProps.style || {};
|
||||
const hasCodeProp = typeof nodeProps.code === 'string';
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Raw HTML (HtmlBlock's `code` prop) -- dedicated CodeEditor modal */}
|
||||
{hasCodeProp && (
|
||||
<HtmlCodeField value={nodeProps.code} onChange={(v) => setPropValue('code', v)} />
|
||||
)}
|
||||
|
||||
{/* String props */}
|
||||
{stringProps.length > 0 && (
|
||||
<CollapsibleSection title="Properties">
|
||||
|
||||
Reference in New Issue
Block a user