diff --git a/craft/CLAUDE.md b/craft/CLAUDE.md index b918c25..555d58e 100644 --- a/craft/CLAUDE.md +++ b/craft/CLAUDE.md @@ -41,14 +41,12 @@ craft/ │ │ └── Canvas.tsx # Craft.js with device-width switching │ │ │ ├── components/ -│ │ ├── resolver.ts # Component map for Craft.js serialization (20 components) +│ │ ├── resolver.ts # Component map for Craft.js serialization (39 components) │ │ ├── layout/ │ │ │ ├── Container.tsx # Generic container (div/section/article/header/footer/main) │ │ │ ├── Section.tsx # Full-width section with centered inner container │ │ │ ├── ColumnLayout.tsx # Flex columns (1-6, with split ratios) -│ │ │ ├── BackgroundSection.tsx # Section with background image/gradient overlay -│ │ │ ├── HeaderZone.tsx # Page-level header zone wrapper -│ │ │ └── FooterZone.tsx # Page-level footer zone wrapper +│ │ │ └── BackgroundSection.tsx # Section with background image/gradient overlay │ │ ├── basic/ │ │ │ ├── Heading.tsx # Inline-editable heading (h1-h6) │ │ │ ├── TextBlock.tsx # Inline-editable paragraph @@ -73,7 +71,8 @@ craft/ │ ├── panels/ │ │ ├── topbar/ │ │ │ ├── TopBar.tsx # Back button, domain badge, device switcher, undo/redo, save, templates -│ │ │ └── TemplateModal.tsx # Template browser with categories and one-click loading +│ │ │ ├── TemplateModal.tsx # Template browser with categories and one-click loading +│ │ │ └── HeadCodeModal.tsx # Edits SiteDesign.headCode (site-wide, not per-page) │ │ ├── left/ │ │ │ ├── LeftPanel.tsx # Tabs: Blocks | Pages | Layers | Assets │ │ │ ├── BlocksPanel.tsx # Draggable block toolbox with categories @@ -81,9 +80,10 @@ craft/ │ │ │ ├── LayersPanel.tsx # Component hierarchy tree view │ │ │ └── AssetsPanel.tsx # Asset browser with upload, drag-drop, thumbnails │ │ ├── right/ -│ │ │ ├── RightPanel.tsx # Tabs: Styles | Settings | Head -│ │ │ ├── GuidedStyles.tsx # Context-aware style panel (shows selected type) -│ │ │ └── SiteDesignPanel.tsx # Site-wide design tokens editor (Basic/Advanced tabs) +│ │ │ ├── RightPanel.tsx # Single "Styles" tab -- renders GuidedStyles only +│ │ │ ├── GuidedStyles.tsx # Context-aware dispatcher: picks a StylePanel by selected type +│ │ │ ├── SiteDesignPanel.tsx # Site-wide design tokens editor (Basic/Advanced tabs) +│ │ │ └── styles/ # Per-type StylePanels (Text, Button, Image, Container, Nav, Form, etc.) │ │ └── context-menu/ │ │ └── ContextMenu.tsx # Right-click context menu (duplicate, copy, paste, delete, etc.) │ │ @@ -98,7 +98,8 @@ craft/ │ │ └── definitions.ts # 16 template definitions across 4 categories │ │ │ ├── ui/ -│ │ └── SettingsTabs.tsx # Reusable General/Style/Advanced tabs for component settings +│ │ ├── AssetPicker.tsx # Reusable image/video source picker (upload/browse-uploaded/URL), full+compact variants +│ │ └── Modal.tsx # Reusable modal dialog shell │ │ │ ├── constants/ │ │ └── presets.ts # Color, font, spacing, radius, gradient, device width presets @@ -165,7 +166,7 @@ The PHP wrapper (`/docker/whp/web/site-builder/index.php`) injects `WHP_CONFIG` 5. **API compatibility** - The save endpoint sends data in the same format as the GrapesJS version (`{ site_id, name, html, css, grapesjs: serializedJson }`), so the PHP backend doesn't need changes. -6. **Component-based architecture** - Each visual element is a React component that doubles as a Craft.js `UserComponent`. All rendering, settings UI, and HTML export are co-located in one file. +6. **Component-based architecture** - Each visual element is a React component that doubles as a Craft.js `UserComponent`. Rendering and HTML export are co-located in one file; style editing is handled by a shared per-type `StylePanel` in `src/panels/right/styles/` rather than a per-component settings panel. 7. **Site Design Tokens** - A `SiteDesignContext` provides 17 design properties (colors, fonts, radii, nav style) that components can reference. Templates import their own design tokens when loaded. @@ -188,28 +189,21 @@ export const MyComponent: UserComponent = ({ text, style }) => return
{ if (r) connect(drag(r)); }} style={style}>{text}
; }; -// 3. Settings panel (rendered in right panel when selected) -const MyComponentSettings: React.FC = () => { - const { actions: { setProp }, props } = useNode((node) => ({ - props: node.data.props as MyComponentProps, - })); - return
/* preset buttons, inputs, etc. */
; -}; - -// 4. Craft config (displayName, default props, rules, related settings) +// 3. Craft config (displayName, default props, rules) MyComponent.craft = { displayName: 'My Component', props: { text: 'Default text', style: {} }, rules: { canDrag: () => true, canMoveIn: () => false, canMoveOut: () => true }, - related: { settings: MyComponentSettings }, }; -// 5. HTML export (static method for serializing to HTML string) +// 4. HTML export (static method for serializing to HTML string) (MyComponent as any).toHtml = (props: MyComponentProps, childrenHtml: string) => { return { html: `
${childrenHtml}
` }; }; ``` +Style editing for the new type is added separately as a `StylePanel` under `src/panels/right/styles/` (or reuses an existing generic one), and wired into `GuidedStyles.tsx`'s type dispatch -- components no longer carry their own settings UI. + ### Component Resolver All components must be registered in `src/components/resolver.ts`. This map is passed to `` so Craft.js can serialize/deserialize the node tree. @@ -270,7 +264,7 @@ The editor auto-saves every 30 seconds when running inside WHP. The save status - `whpConfig` - The full config object (or null in standalone mode) - `isWHP` - Boolean shorthand for whether we're running inside WHP -## All Components (22) +## All Components (39) | # | Component | Type | File | Features | |---|-----------|------|------|----------| @@ -278,24 +272,41 @@ The editor auto-saves every 30 seconds when running inside WHP. The save status | 2 | Section | Layout | `layout/Section.tsx` | Full-width with centered inner container, bg color/gradient, vertical padding, inner max-width | | 3 | ColumnLayout | Layout | `layout/ColumnLayout.tsx` | 1-6 columns, split ratios (50-50, 30-70, 70-30, 33-33-33, 25-25-25-25, etc.), gap control | | 4 | BackgroundSection | Layout | `layout/BackgroundSection.tsx` | Section with background image, gradient overlay, parallax-ready | -| 5 | HeaderZone | Layout | `layout/HeaderZone.tsx` | Page-level header wrapper zone, used by PageContext | -| 6 | FooterZone | Layout | `layout/FooterZone.tsx` | Page-level footer wrapper zone, used by PageContext | -| 7 | Heading | Basic | `basic/Heading.tsx` | Inline-editable, h1-h6 level, color, font family/size/weight, text align | -| 8 | TextBlock | Basic | `basic/TextBlock.tsx` | Inline-editable paragraph, color, font family/size/weight, text align, line height | -| 9 | ButtonLink | Basic | `basic/ButtonLink.tsx` | Link text/URL/target, 8 color presets (auto text contrast), radius, padding, font size | +| 5 | Heading | Basic | `basic/Heading.tsx` | Inline-editable, h1-h6 level, color, font family/size/weight, text align | +| 6 | TextBlock | Basic | `basic/TextBlock.tsx` | Inline-editable paragraph, color, font family/size/weight, text align, line height | +| 7 | ButtonLink | Basic | `basic/ButtonLink.tsx` | Link text/URL/target, 8 color presets (auto text contrast), radius, padding, font size | +| 8 | Logo | Basic | `basic/Logo.tsx` | Text or image logo, link href, font family/size/weight, image width | +| 9 | Menu | Basic | `basic/Menu.tsx` | Link list with optional CTA styling, horizontal/vertical orientation, alignment, hover colors | | 10 | Navbar | Basic | `basic/Navbar.tsx` | Text or image logo, page links, external links, CTA buttons, light/dark nav style | | 11 | Footer | Basic | `basic/Footer.tsx` | Footer with links, copyright, social links | | 12 | Divider | Basic | `basic/Divider.tsx` | Horizontal rule with color and thickness controls | | 13 | Spacer | Basic | `basic/Spacer.tsx` | Vertical spacing element with height control | -| 14 | ImageBlock | Media | `media/ImageBlock.tsx` | SVG placeholder, URL input, upload, browse assets, alt text, width/height, object-fit, radius | -| 15 | VideoBlock | Media | `media/VideoBlock.tsx` | YouTube, Vimeo, direct files (.mp4/.webm/.ogg), background mode, autoplay, loop | -| 16 | HeroSimple | Section | `sections/HeroSimple.tsx` | Pre-built hero with heading, subtext, CTA button, gradient/color background | -| 17 | FeaturesGrid | Section | `sections/FeaturesGrid.tsx` | 3-column feature cards with icons, titles, descriptions | -| 18 | CTASection | Section | `sections/CTASection.tsx` | Call-to-action banner with heading, text, button | -| 19 | FormContainer | Form | `forms/FormContainer.tsx` | Form wrapper with action URL and method | -| 20 | InputField | Form | `forms/InputField.tsx` | Text input with label, placeholder, type (text/email/tel/password/number) | -| 21 | TextareaField | Form | `forms/TextareaField.tsx` | Textarea with label and placeholder | -| 22 | FormButton | Form | `forms/FormButton.tsx` | Submit button with color and style controls | +| 14 | Icon | Basic | `basic/Icon.tsx` | Font Awesome icon, size/color, background shape, optional link | +| 15 | ImageBlock | Media | `media/ImageBlock.tsx` | SVG placeholder, URL input, upload, browse assets, alt text, width/height, object-fit, radius | +| 16 | VideoBlock | Media | `media/VideoBlock.tsx` | YouTube, Vimeo, direct files (.mp4/.webm/.ogg), background mode, autoplay, loop | +| 17 | MapEmbed | Media | `media/MapEmbed.tsx` | Embedded map by address, zoom level, height | +| 18 | HeroSimple | Section | `sections/HeroSimple.tsx` | Pre-built hero with heading, subtext, CTA button, gradient/color background | +| 19 | FeaturesGrid | Section | `sections/FeaturesGrid.tsx` | 3-column feature cards with icons, titles, descriptions | +| 20 | CTASection | Section | `sections/CTASection.tsx` | Call-to-action banner with heading, text, button | +| 21 | Countdown | Section | `sections/Countdown.tsx` | Countdown timer to a target date, heading, digit/label colors | +| 22 | Testimonials | Section | `sections/Testimonials.tsx` | Grid or single-layout testimonial cards, star color, card background | +| 23 | FormContainer | Form | `forms/FormContainer.tsx` | Form wrapper with action URL and method | +| 24 | InputField | Form | `forms/InputField.tsx` | Text input with label, placeholder, type (text/email/tel/password/number) | +| 25 | TextareaField | Form | `forms/TextareaField.tsx` | Textarea with label and placeholder | +| 26 | FormButton | Form | `forms/FormButton.tsx` | Submit button with color and style controls | +| 27 | ContactForm | Form | `forms/ContactForm.tsx` | Configurable field list, recipient email, success message or thank-you URL redirect | +| 28 | StarRating | Basic | `basic/StarRating.tsx` | Star rating display, rating/max stars, filled/empty color | +| 29 | SocialLinks | Basic | `basic/SocialLinks.tsx` | Social icon links, size/color/shape, gap, alignment | +| 30 | CallToAction | Section | `sections/CallToAction.tsx` | Heading/description with 1-2 buttons, color/gradient/image background with overlay | +| 31 | Accordion | Section | `sections/Accordion.tsx` | Expand/collapse item list, header/content colors | +| 32 | Tabs | Section | `sections/Tabs.tsx` | Tabbed content panels, active/inactive tab colors | +| 33 | PricingTable | Section | `sections/PricingTable.tsx` | Pricing plan cards, featured plan highlight, bullet list | +| 34 | Gallery | Section | `sections/Gallery.tsx` | Image grid gallery, configurable columns/gap, optional lightbox | +| 35 | ContentSlider | Section | `sections/ContentSlider.tsx` | Auto-playing image/content slider, dots/arrows, configurable interval | +| 36 | NumberCounter | Section | `sections/NumberCounter.tsx` | Animated stat counters, columns, number/label colors | +| 37 | SubscribeForm | Form | `forms/SubscribeForm.tsx` | Inline/stacked email signup form, heading, button color | +| 38 | SearchBar | Basic | `basic/SearchBar.tsx` | Search input with optional button, placeholder text | +| 39 | HtmlBlock | Basic | `basic/HtmlBlock.tsx` | Raw/custom HTML embed block, sanitized on export | ## Site Design Tokens @@ -351,7 +362,7 @@ Templates are loaded via the Template Modal (opened from TopBar). Loading a temp ## Multi-Page System Pages are managed through `PageContext`: -- Each page has: `id`, `name`, `slug`, `craftState`, `headCode` +- Each page has: `id`, `name`, `slug`, `craftState` (`headCode` is site-wide only, on `SiteDesignContext`/`SiteDesign`, edited via the TopBar's Head Code modal -- not a per-page field) - Header and Footer are stored as separate "page" entries with fixed IDs (`__header__`, `__footer__`) - Page switching serializes the current canvas, stores it, then deserializes the target page - Header/Footer editing puts the canvas in a distinct mode @@ -392,21 +403,22 @@ The Assets panel (`AssetsPanel.tsx`) provides: - Delete asset - Integration with WHP API for server-side storage -Image and Video components also have inline asset selection (browse button in settings). +Image and video fields elsewhere in the editor (ImageStylePanel, MediaStylePanel, HeroStylePanel, NavStylePanel, BackgroundSectionStylePanel, and array-editor cards like FeaturesEditor) use the shared `AssetPicker` (`src/ui/AssetPicker.tsx`) for upload / browse-uploaded / paste-URL, in a `full` or `compact` variant depending on space. ## Adding New Components 1. Create `src/components//.tsx` following the pattern above 2. Add the component to `src/components/resolver.ts` 3. Add a block entry in `src/panels/left/BlocksPanel.tsx` under the appropriate category -4. Implement the `toHtml` static for HTML export -5. Build and test: `npm run dev`, drag the block onto the canvas, verify settings panel, verify HTML export +4. Add or extend a `StylePanel` in `src/panels/right/styles/` and wire it into `GuidedStyles.tsx`'s type dispatch so the new component is editable when selected +5. Implement the `toHtml` static for HTML export +6. Build and test: `npm run dev`, drag the block onto the canvas, verify the style panel, verify HTML export ### Checklist for a new component: - [ ] Props interface with `style?: CSSProperties` - [ ] `useNode()` with `connect(drag(ref))` on the root element -- [ ] Settings panel using `useNode()` with `setProp()` -- [ ] `.craft` config with `displayName`, default `props`, `rules`, `related.settings` +- [ ] `StylePanel` entry (new or reused) wired into `GuidedStyles.tsx` +- [ ] `.craft` config with `displayName`, default `props`, `rules` - [ ] `.toHtml()` static method using `cssPropsToString()` - [ ] Registered in `resolver.ts` - [ ] Block added to `BlocksPanel.tsx` @@ -421,7 +433,7 @@ The editor uses a dark theme defined via CSS custom properties in `src/styles/ed - **Border:** `#2d2d3a` - **Font:** Inter -All editor chrome (panels, topbar, settings) is styled via `editor.css`. User content on the canvas uses inline styles exclusively. +All editor chrome (panels, topbar, style panels) is styled via `editor.css`. User content on the canvas uses inline styles exclusively. ## Presets @@ -446,7 +458,7 @@ Every component has a static `toHtml(props, childrenHtml)` method. The `html-exp ## Testing Approach -- **Manual testing:** Run `npm run dev`, drag components, edit props, verify settings panels +- **Manual testing:** Run `npm run dev`, drag components, edit props, verify style panels - **Type checking:** `tsc --noEmit` (part of build step) - **HTML export:** Verify `toHtml()` output matches expected HTML structure - **Device preview:** Switch between desktop/tablet/mobile and verify responsive behavior @@ -455,9 +467,9 @@ Every component has a static `toHtml(props, childrenHtml)` method. The `html-exp ## Development Notes - Path alias `@/` maps to `./src/` (configured in both tsconfig.json and vite.config.ts) -- `GuidedStyles` shows selected component type and delegates to per-component settings panels +- `GuidedStyles` shows the selected component type and dispatches to a shared `StylePanel` in `src/panels/right/styles/` (components no longer carry their own settings UI) - Text components (Heading, TextBlock) use `contentEditable` for inline editing when selected - Button/link navigation is prevented in the editor via `e.preventDefault()` - Image upload integrates with WHP API; in standalone mode falls back to local `blob:` URLs - Auto-save runs every 30 seconds when connected to WHP API -- The SettingsTabs UI component provides a reusable General/Style/Advanced tab layout for component settings +- `AssetPicker` (`src/ui/AssetPicker.tsx`) is the shared upload/browse/URL control reused across StylePanels for every image and video field