Component render/toHtml now use var(--wsb-*) instead of hex so Site Design
palette changes reach FeaturesGrid, Testimonials, Accordion, PricingTable,
CTA/CallToAction, forms, Gallery, Tabs and others. Exemption lists removed.
Refs #44
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A page-scope Sitesmith replace with a master zone open loaded the AI page
onto the zone canvas. On Done, its first section became the new master and
the sync rewrote every instance on every page with it, orphaning all
overrides. replaceCurrentPage now returns false inside a master zone and
the apply path reports an error asking the user to click Done first.
Refs #57
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Make a top-level section global (context menu), place instances from the
Section library's new Global tab, edit the master once in its own zone
("Editing global section" banner, Done - update N instances) and every
instance on every page/header/footer is rebuilt from it. Instances are real
inlined subtrees (custom.global on the root, custom.gkey on every node), so
export and published output are unchanged static HTML.
- utils/global-sections.ts: pure model (createMaster, instantiate,
syncInstances, collectOverridesFromInstance, applyOverrides, detach,
findInstanceRoot, master zone round trip). Unchanged input returns the
identical string; sync keeps the instance root id and the instance's own
inner ids per gkey.
- PageContext: __global__:<id> zone (editGlobal / finishGlobal); leaving it
commits the master (rev + 1 only when it changed), syncs every stored
slot and applies the sync to the returned-to canvas as ONE undo step.
- GlobalSectionsContext: makeGlobal / insertInstance / detach / setOverride
/ resetOverride / remove (refused while used), one undo step each.
- Inline text edits inside an instance record an override (text + html)
via useGlobalOverrideCommit; GuidedStyles shows a Global section panel
(Edit master, Detach, content override fields) instead of style panels.
- RenderNode: Global badge, dashed outline, lock icon on inner nodes.
- buildSavePayload: a master zone on the canvas is never saved into a page.
Refs #57
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Registers site.download-zip (WHP mode only; shows in the ⋯ menu and the
palette) via ExportCommand, mounted in CanvasOverlays. useSiteExport POSTs
?action=export_zip with the CSRF header: a zip answer is saved through a
Blob + anchor click, anything else (JSON error, older backend, network
failure, a stream cut short) becomes an error notice.
Refs #42
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Token-based sections (21 total across four families) with tests covering
insert, export (no stray hex, alt on images, relative links) and tree shape.
Refs #52
Adds 17 token-based sections across contact, hours, gallery and local strips,
with a real-editor test covering insert, hex-free export, alt text and links.
Refs #52
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
URL/anchor/tel/mailto edits from LinkPicker now go through
continuousSetProp (key link:<i>:href); a page pick stays a discrete
step via discreteSetProp. source/pageId stripping and the followPages
mergeLinks re-merge remain inside the updater.
Refs #53
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Publish now runs client-side checks (image alt, meta description, title
length, H1, empty links, contrast, noindex landing, empty page) over the
current state and shows a grouped checklist with Fix links and
"Publish anyway". Adds ExportOptions.canonicalUrl -> <link rel="canonical">
after the favicon line in both Preview and export.
Refs #54
Adds a site.history command (WHP mode, only when history_list answers) opening
a modal of saves/publishes by day. Preview opens the snapshot re-exported with
its own design; Restore site / Restore one page load the snapshot as unsaved
state (history cleared, dirty marked) so the user still clicks Save.
Refs #51
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- utils/nav-links.ts: shared NavLink type (source/pageId/children),
pageHref, buildPageLinks, mergeLinks, adoptPageLinks, rewriteHeaderLinks
- PageData.nav {show, parentId, label} + updatePageNav; a nav-sync effect in
PageProvider materialises page-following links into the stored header
(or the live header nodes while it is being edited); string/identity
guards keep it a no-op when nothing changed
- Navbar/Menu: followPages prop (default false; the default header seed is
true), one-level dropdowns (hover/focus-within + inline click toggle,
indented in the hamburger layout), hover/CTA colours default to the
primary token
- NavStylePanel: Follow pages toggle (adopts matching manual links, keeps
custom text as the page's menu label), read-only page rows with Hide from
menu, sub-link editor for manual links, LinkPicker records pageId
- Page Settings: Show in menu / Menu label / Nest under; Pages panel badge
- useWhpApi: nav passes through pages_craft_state on save and load
Legacy navs (no followPages) are never rewritten.
Refs #53
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Edge handles on a selected Section/Container/Columns write padding via the
per-device setter as one undo burst; Alt = opposite side, Shift = all four,
Ctrl/Cmd snaps to 8px, Escape cancels.
Refs #56
SectionType, Social, Pricing, Form and the generic props editor already
wrote tablet/mobile overrides through the device-aware useNodeProp setters
but still read nodeProps.style, so a mobile padding/margin/alignment edit
looked like a no-op and had no reset dot. They now read useResolvedStyle()
and show OverrideDots on Padding, Margin and Text Alignment.
NavStylePanel has the same gap but is outside this task's files.
Refs #45
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5-step profile wizard (name/type, services, area, tone, palette preview) saved to
extras.sitesmithProfile and sent with every Sitesmith request. Regenerate this
section rewrites the selected block for the business as a single undo step.
Refs #58
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Search + type chips in the Assets panel and picker library; Stock photos
entry in the picker (feature-detected, hidden when stock_disabled/absent);
bgPosition focal point for Hero and Background Section.
Refs #55
Catalog skeleton with per-family files (one seed each for hero, services,
contact), live token-styled thumbnails, insert-after-selection, and
save-as-section into project extras.
Refs #52
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
On tablet/mobile the useNodeProp style setters now route responsive keys
(spacing, font size, line height, letter spacing, alignment, size, flex
layout) into styleTablet/styleMobile; colours and other keys still write
style. An empty value removes the override. Continuous-burst keys include
the device so a desktop drag and a mobile drag never merge.
- shared.tsx: device-aware setters, new setResponsiveStyleProp /
clearResponsiveStyleProp exports, setPropStylesContinuous
- responsive-panel.tsx: useResolvedStyle, useOverrideState, DeviceBanner
- OverrideDot: filled dot resets the override (one undo step), hollow dot
marks an inherited value; wired into Text/Button/Container/Image/Media/
BackgroundSection panels and both box-model sections
- Columns: "Stack on this device" toggle (flexDirection override)
- GuidedStyles: device banner under the type header
- RenderNode: every component node renders through one stable
ResolvedRender so gaining/losing an override or switching device no
longer remounts the node (the remount dropped inline-edit focus/caret
and blanked a selected Heading)
Refs #45
Core editor shortcuts become registry commands run by the single
useCommandShortcuts dispatcher: undo/redo, delete, duplicate (after +
select), copy/paste, Alt+arrow move, 1/2/3 device, Cmd+S/Shift+P/P site
commands and Cmd+/ cheat sheet. Tab/Esc no longer fire from buttons or
dialogs. Context menu labels come from formatShortcut.
Refs #39