Skip to content

Commit f42cb6a

Browse files
committed
fix: No droppable zone when no widget
1 parent d1070d6 commit f42cb6a

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

packages/evershop/src/components/common/page-builder/PageBuilderBridge.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
isInPageBuilderIframe,
55
markPageBuilderActive
66
} from './pageBuilderMode.js';
7+
import { ensureChromeStyleInjected } from './WidgetChrome.js';
78

89
/**
910
* Listens for `data-update` postMessages from the admin window and applies
@@ -102,6 +103,12 @@ export function PageBuilderBridge(): null {
102103
markPageBuilderActive();
103104

104105
ensureGlobalsOutlineStyle();
106+
// The chrome stylesheet carries the `[data-evershop-pb-dropzone]` sizing /
107+
// visibility rules. `WidgetChrome` injects it too, but only mounts per
108+
// existing widget — so on a route with no widgets the drop zones would
109+
// have no CSS and stay invisible / zero-height. Inject here (always
110+
// mounted in the iframe) so drop zones work on a fresh, empty store.
111+
ensureChromeStyleInjected();
105112

106113
// Capture-phase link guard: edit mode disables in-preview navigation.
107114
// The page-builder session lives in the iframe's URL (`?changeset=`),
@@ -154,6 +161,22 @@ export function PageBuilderBridge(): null {
154161
| null;
155162
if (!raw) return;
156163

164+
// Drag lifecycle: the admin posts `pb-drag-start` / `pb-drag-end` when a
165+
// palette drag begins / ends. Toggling `body[data-evershop-pb-drag]`
166+
// reveals every drop zone via the chrome CSS. `WidgetChrome` also
167+
// listens, but only when a widget is mounted — handling it here too
168+
// makes drops work on a route with no widgets. Setting / removing the
169+
// attribute is idempotent, so both listeners firing is harmless.
170+
const dragType = (raw as { type?: string }).type;
171+
if (dragType === 'pb-drag-start') {
172+
document.body.setAttribute('data-evershop-pb-drag', 'true');
173+
return;
174+
}
175+
if (dragType === 'pb-drag-end') {
176+
document.body.removeAttribute('data-evershop-pb-drag');
177+
return;
178+
}
179+
157180
// Globals-view toggle: outline `[data-evershop-global]` areas.
158181
if ((raw as GlobalsViewMessage).type === 'globals-view') {
159182
const enabled = !!(raw as GlobalsViewMessage).enabled;

packages/evershop/src/components/common/page-builder/WidgetChrome.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,17 @@ const CHROME_CSS = `
8989
}
9090
`;
9191

92-
function ensureChromeStyleInjected(): void {
92+
/**
93+
* Inject the page-builder chrome stylesheet (widget outlines, toolbar
94+
* visibility, and — critically — the `[data-evershop-pb-dropzone]` sizing /
95+
* visibility rules) once per document. Idempotent via the element-id guard.
96+
*
97+
* Exported because the drop-zone rules must exist even on a route with **no
98+
* widgets** (a fresh store): `WidgetChrome` only mounts per existing widget,
99+
* so `PageBuilderBridge` (always mounted in the iframe) also calls this to
100+
* guarantee the stylesheet is present regardless of widget count.
101+
*/
102+
export function ensureChromeStyleInjected(): void {
93103
if (typeof document === 'undefined') return;
94104
if (document.getElementById(CHROME_STYLE_ID)) return;
95105
const el = document.createElement('style');

0 commit comments

Comments
 (0)