| 1 |
// Repeater scope-lock drag gate. |
| 2 |
// |
| 3 |
// Repeater sub-fields must stay bound to their parent (legacy user_meta uses |
| 4 |
// `_{N}` suffixes that change semantics if a field crosses the boundary). |
| 5 |
// Rather than a per-frame JS reconciler that snaps cross-boundary moves back |
| 6 |
// (which fights Gutenberg's live drop-preview reordering and lagged the drag), |
| 7 |
// we gate drop detection at the CSS layer. |
| 8 |
// |
| 9 |
// `pointer-events` is INHERITED: setting `none` on a senior wrapper makes the |
| 10 |
// whole subtree transparent to pointer/drag events, so Gutenberg's dropzone |
| 11 |
// listener (on the inner `.block-editor-block-list__layout`) never gets |
| 12 |
// `dragover`, never computes a drop position, never calls `showInsertionPoint` |
| 13 |
// → no blue line. Setting `none` only on descendants does NOT work: the wrapper |
| 14 |
// stays pe:auto and events still reach the listener. Anchoring at the senior |
| 15 |
// wrapper is what works. |
| 16 |
// |
| 17 |
// Classes are applied to the canvas root by `useRepeaterScopeGuard` in |
| 18 |
// components/RepeaterScopeGuard.js — they flip only on drag start/end, not per |
| 19 |
// frame. |
| 20 |
.wppb-fb-drag-from-outside { |
| 21 |
// Dragging a top-level field. Make the entire Repeater block |
| 22 |
// transparent to drag events. Events pass through to the root |
| 23 |
// dropzone, which correctly shows indicators above/below the |
| 24 |
// Repeater (valid top-level drop positions) — never inside. |
| 25 |
[data-type="profile-builder/field-repeater"]="profile-builder/field-repeater""] { |
| 26 |
pointer-events: none !important; |
| 27 |
|
| 28 |
// Visual hint for the gated zone. The actual gate is the pe:none |
| 29 |
// above; this is purely communicative. |
| 30 |
.block-editor-inner-blocks { |
| 31 |
filter: blur(2px); |
| 32 |
opacity: 0.5; |
| 33 |
transition: filter 0.1s ease, opacity 0.1s ease; |
| 34 |
} |
| 35 |
} |
| 36 |
} |
| 37 |
|
| 38 |
.wppb-fb-drag-from-repeater { |
| 39 |
// Dragging a sub-field. Make the entire root layout transparent to |
| 40 |
// drag events so no top-level indicators show, then explicitly |
| 41 |
// re-enable the dragged-from Repeater so intra-Repeater reorder |
| 42 |
// works. |
| 43 |
.is-root-container { |
| 44 |
pointer-events: none !important; |
| 45 |
} |
| 46 |
.is-root-container > [data-block]]:not(.wppb-fb-drag-allowed-parent) { |
| 47 |
filter: blur(2px); |
| 48 |
opacity: 0.5; |
| 49 |
transition: filter 0.1s ease, opacity 0.1s ease; |
| 50 |
} |
| 51 |
// Re-enable on the allowed parent. pe:auto on it re-enables the |
| 52 |
// whole subtree (inheritance), so its inner block list's dropzone |
| 53 |
// fires and indicators show between sub-fields. |
| 54 |
.wppb-fb-drag-allowed-parent { |
| 55 |
pointer-events: auto !important; |
| 56 |
} |
| 57 |
} |
| 58 |
|