diff --git a/craft/src/panels/right/GuidedStyles.tsx b/craft/src/panels/right/GuidedStyles.tsx index 59e0ff2..00cbec5 100644 --- a/craft/src/panels/right/GuidedStyles.tsx +++ b/craft/src/panels/right/GuidedStyles.tsx @@ -17,6 +17,7 @@ import { PricingStylePanel, BackgroundSectionStylePanel, GenericPropsEditor, + HtmlStylePanel, } from './styles'; /* ================================================================ @@ -75,8 +76,10 @@ export const GuidedStyles: React.FC = () => { const isSocial = /^social links$|^icon$|^star rating$/i.test(typeName); const isPricing = /^pricing/i.test(typeName); const isSection = /^accordion$|^tabs$|^testimonial|^countdown$|^number counter$|^cta section$|^call to action$|^features grid$/i.test(typeName); - // Utility types that need minimal controls - const isUtility = /^divider$|^spacer$|^html$/i.test(typeName); + const isHtml = /^html$/i.test(typeName); + // Utility types that need minimal controls. HTML is deliberately NOT here + // -- it gets HtmlStylePanel, which shows the code editor and nothing else. + const isUtility = /^divider$|^spacer$/i.test(typeName); // Icon for the type badge const typeIcon = isText ? 'fa-font' @@ -90,6 +93,7 @@ export const GuidedStyles: React.FC = () => { : isForm ? 'fa-wpforms' : isSocial ? 'fa-share-alt' : isSection ? 'fa-th-large' + : isHtml ? 'fa-code' : isUtility ? 'fa-ellipsis-h' : 'fa-cube'; @@ -158,11 +162,14 @@ export const GuidedStyles: React.FC = () => { {/* SECTION-TYPE (Accordion, Tabs, Testimonials, Countdown, Counter, CTA, Features) */} {isSection && } + {/* HTML -- code editor only */} + {isHtml && } + {/* UTILITY (Divider, Spacer, HTML) -- use generic but it works well for these */} {isUtility && } {/* FALLBACK: Anything not matched above */} - {!isText && !isButton && !isImage && !isBgSection && !isContainer && !isHero && !isNav && !isMedia && !isForm && !isSocial && !isPricing && !isSection && !isUtility && ( + {!isText && !isButton && !isImage && !isBgSection && !isContainer && !isHero && !isNav && !isMedia && !isForm && !isSocial && !isPricing && !isSection && !isUtility && !isHtml && ( )} diff --git a/craft/src/panels/right/styles/HtmlStylePanel.test.tsx b/craft/src/panels/right/styles/HtmlStylePanel.test.tsx new file mode 100644 index 0000000..891d2cd --- /dev/null +++ b/craft/src/panels/right/styles/HtmlStylePanel.test.tsx @@ -0,0 +1,38 @@ +import { describe, test, expect, vi } from 'vitest'; +import React from 'react'; +import { createRoot, Root } from 'react-dom/client'; +import { act } from 'react-dom/test-utils'; + +vi.mock('@craftjs/core', () => ({ + useEditor: () => ({ actions: { setProp: vi.fn() }, query: {} }), +})); + +import { HtmlStylePanel } from './HtmlStylePanel'; + +let container: HTMLDivElement; +let root: Root; + +function render(ui: React.ReactElement) { + container = document.createElement('div'); + document.body.appendChild(container); + act(() => { + root = createRoot(container); + root.render(ui); + }); +} + +describe('HtmlStylePanel', () => { + test('renders the Edit HTML control', () => { + render(x

', style: {} }} />); + expect(container.textContent).toContain('Edit HTML'); + }); + + test('renders NO colour or style controls (they never reach the live page)', () => { + render(x

', style: {} }} />); + expect(container.querySelector('input[type="color"]')).toBeNull(); + expect(container.textContent).not.toContain('Background'); + expect(container.textContent).not.toContain('Text Color'); + expect(container.textContent).not.toContain('Padding'); + expect(container.textContent).not.toContain('Border Radius'); + }); +}); diff --git a/craft/src/panels/right/styles/HtmlStylePanel.tsx b/craft/src/panels/right/styles/HtmlStylePanel.tsx new file mode 100644 index 0000000..224435f --- /dev/null +++ b/craft/src/panels/right/styles/HtmlStylePanel.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { useNodeProp } from './shared'; +import { HtmlCodeField } from './HtmlCodeField'; + +/** + * The HTML block's entire style panel. + * + * Deliberately ONLY the code editor. `HtmlBlock.toHtml()` emits nothing but + * the purified `code`, so every colour/padding/alignment control the generic + * editor used to offer here was dead on the published page. Styling an HTML + * block is done inside the user's own markup. + */ +export const HtmlStylePanel: React.FC<{ selectedId: string; nodeProps: Record }> = ({ + selectedId, + nodeProps, +}) => { + const { setProp: setPropValue } = useNodeProp(selectedId); + return ( + <> + setPropValue('code', v)} + /> +

+ Style this block inside your own markup — a wrapper set here would show + in the editor but not on the published page. +

+ + ); +}; diff --git a/craft/src/panels/right/styles/index.ts b/craft/src/panels/right/styles/index.ts index 7c6b328..757e3bd 100644 --- a/craft/src/panels/right/styles/index.ts +++ b/craft/src/panels/right/styles/index.ts @@ -11,3 +11,4 @@ export { SectionTypePanel } from './SectionTypePanel'; export { PricingStylePanel } from './PricingStylePanel'; export { BackgroundSectionStylePanel } from './BackgroundSectionStylePanel'; export { GenericPropsEditor } from './GenericPropsEditor'; +export { HtmlStylePanel } from './HtmlStylePanel';