Skip to content

Prepare for 3.0#526

Closed
leopiccionia wants to merge 119 commits intomasterfrom
develop
Closed

Prepare for 3.0#526
leopiccionia wants to merge 119 commits intomasterfrom
develop

Conversation

@leopiccionia
Copy link
Copy Markdown
Collaborator

No description provided.

leopiccionia and others added 30 commits September 23, 2025 10:09
Minimal change: update apiVersion from 2 to 3 in all four block
registrations (JS) and both PHP register_block_type calls.

This declares the blocks as compatible with the WordPress iframe
editor, which will be the default in WordPress 7.

Part of #488

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Disable reuseMaps in both mapboxgl-react and maplibregl-react wrappers.
When reuseMaps is true, react-map-gl pools map instances across component
lifecycles. In the WordPress iframe editor (apiVersion 3), pooled maps
hold references to containers from a different document, causing
"container must be a String or HTMLElement" errors due to cross-document
instanceof failures.

Also move document.body.style.setProperty in storymap-editor from render
to a useEffect hook to ensure the DOM is ready in the iframe context.

Ref: #488

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MapboxGL/MapLibreGL check `container instanceof HTMLElement` in their
Map constructor. In WordPress Block API v3 the editor runs inside an
iframe, so the container element belongs to the iframe's document while
the map library may use the parent document's HTMLElement prototype.
This cross-document prototype mismatch causes `instanceof` to return
false even for valid DOM elements.

Fix by overriding `HTMLElement[Symbol.hasInstance]` with a duck-type
check (nodeType === 1) in all four map library files (both loaders
and both react wrappers). The patch covers both webpack chunks since
splitChunks is disabled and the map vendor may be bundled separately
in each chunk.

Ref: #488

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous Symbol.hasInstance override used a simple arrow function
that returned true for any object with nodeType === 1, which caused
false positives for HTMLElement subclasses (e.g. HTMLInputElement).
This made WordPress's @wordpress/components call setSelectionRange()
on non-input elements like <div>, producing runtime errors.

The fix uses a regular function (not arrow) so `this` refers to the
right-hand constructor in the instanceof expression:
- When `this === HTMLElement`: duck-type via nodeType === 1 (handles
  cross-document iframe checks for MapGL container validation)
- When `this` is a subclass: walk the prototype chain manually to
  preserve standard instanceof semantics

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two fixes:

1. class-jeo-map.js: One-time maps (no map_id) never called getLayers(),
   so this.layers stayed empty. When a layer had load_as_style=true,
   getStyleLayer() crashed on undefined.getStyleUrl(). Fix: call
   getLayers() for one-time maps too, and add a null guard.

2. storymap-editor: Settings panels were unresponsive in the iframe
   editor (Block API v3) for three reasons:
   - Missing position:relative on the block root. In v2 the outer
     .wp-block wrapper provided this; in v3 it no longer exists.
   - Show buttons were disabled when loadedLayers was null (loading
     or empty). Relaxed to only require loadedMap.
   - Added null-coalescing guards for navigateMapLayers and
     storymapLayers to prevent crashes when layers haven't loaded.
   - Added z-index on .storymap-controls to ensure panels stack
     above the map canvas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The layers-sidebar and maps-sidebar entry points used waitUntil()
to poll for .editor-post-title before calling registerPlugin().
In Block API v3, the post title lives inside the editor iframe
while these scripts run in the parent window, so the element was
never found and registerPlugin() was never called.

Fix: register plugins immediately on domReady (no waitUntil) and
move the preview-div creation into a useEffect that queries both
the parent document and the iframe's contentDocument.

Also fix storymap-editor.scss: add position:relative to
.storymap-controls so its z-index:10 actually takes effect
(z-index requires a positioned element).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Portal components (MapPreviewPortal, LayerPreviewPortal) crashed with
React error #200 when the target DOM element was null.  In Block API v3
the preview containers are created inside the editor iframe but the
sidebar runs in the parent window, so document.getElementById() could
not find them.  Now both portals try the parent document first, then
the iframe document, and fall back to rendering children inline if no
target is found.

The storymap CSS regression is also fixed: position: relative was
removed from .storymap-controls (which turned it into a containing
block for all absolutely-positioned children, displacing settings
panels, the search bar, and the current-slide box).  Instead,
z-index: 10 is applied directly to each absolutely-positioned child
that needs to stack above the map canvas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
crypto.randomUUID() requires a secure context (HTTPS) but many dev
environments use plain HTTP, causing crashes in the legend editors
and in JeoLegend.typeOptionsShape().  A new generateUUID() utility
function tries crypto.randomUUID() first, then falls back to
crypto.getRandomValues() which works regardless of the transport
protocol.

Also add a null guard on the storymap "lock current spot" buttons:
the map reference (selectedMap) may not be set yet if the map hasn't
finished loading when the button is clicked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In Block API v3 the editor content lives inside an iframe.
createPortal cannot reliably render React content across document
boundaries (parent window → iframe), so the preview containers that
were created inside the iframe were unreachable from the sidebar
React tree.

Instead of trying to portal across documents, the map and layer
previews now render inline inside the sidebar panel when no portal
target exists in the parent document.  The useEffect hooks that
created preview divs inside the iframe are removed since they are
no longer needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The preview portals were rendering outside any slot-fill component,
making them invisible in the sidebar.  Wrapping them in
PluginDocumentSettingPanel makes the map/layer preview visible as a
collapsible panel in the document settings sidebar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Register jeo/map-editor and jeo/layer-editor blocks whose edit
components render the interactive map preview inside the block
editor content area (the iframe).  This mirrors the approach used
by jeo/storymap: the post type declares a block template containing
the preview block, locked so users cannot remove it.

The blocks are hidden from the inserter (supports.inserter = false)
and have no frontend output (save returns null) — they exist only
to provide an in-editor preview with zoom controls and layer
rendering.

Both blocks read/write post meta through the wp.data store, so
changes made in the sidebar settings panels are immediately
reflected in the content area preview.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…te mismatch

- Remove Map Preview panel from maps-sidebar (now handled by jeo/map-editor block)
- Remove Layer Preview panel from layers-sidebar (now handled by jeo/layer-editor block)
- Fix layer Publish button staying grayed: add unlockPostSaving to 'ready' status
- Fix template mismatch warning on existing posts via REST API filter that
  auto-injects the editor block into content for edit context requests
- Add full-width CSS for map-editor and layer-editor preview blocks
- Hide block selection outline for editor-only preview blocks
- Add block supports (html:false, reusable:false, lock:false) to reduce toolbar
- Remove stray console.log({instanceId}) from map-editor.js
- Expose setPanLimitsFromMap from MapEditorPreview block via window reference

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap Map components in a div with onMouseDown/onTouchStart
  stopPropagation to prevent the block editor from capturing
  pointer events, restoring map drag/zoom interaction
- Add align:'full' support with default value to map-editor and
  layer-editor blocks so they use the editor's full-width layout
- Update PHP templates and REST injection to include align attribute
- Add jeo-preview-area class wrapper for consistent styling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- MapLibreGL: patch MouseEvent/WheelEvent Symbol.hasInstance so drag
  and scroll events from the iframe document pass instanceof checks
  in isPointableEvent(), restoring map interaction in the editor

- MapLibreGL/MapboxGL: patch FullscreenControl.onAdd at instance level
  to redirect fullscreenElement, exitFullscreen() and fullscreenchange
  listeners to the iframe's ownerDocument instead of the parent window,
  fixing the fullscreen toggle exit button

- MapLibreGL react wrapper: add patchIframeListeners() to duplicate
  pointer/wheel listeners from the map canvas onto the iframe's
  ownerDocument as a defence-in-depth for cross-document events

- MapboxGL react wrapper: add patchIframeAndResize() with a
  ResizeObserver that calls map.resize() when the container changes
  dimensions in the iframe, fixing the blank canvas on initial load

- Map/layer editor preview: stop pointer/mouse/touch events from
  propagating to Gutenberg's block selection handler so the map
  remains draggable inside the editor block

- CSS: let Gutenberg's alignfull negative-margin mechanism handle
  full-width stretching; only set box-sizing on the block wrapper
  and width:100% on the inner .jeo-preview-area

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dashicons require the dashicons font which is not available inside the
Block API v3 iframe. Switch to the SVG-based Icon component and
@wordpress/icons equivalents so icons render correctly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Codex OpenAI <codex@openai.com>
Switch the storymap editors from the legacy ckeditor5-build-full bundle to the modular ckeditor5 package and update the React integration to @ckeditor/ckeditor5-react 9.5.0. Refresh the npm lockfile to match the new CKEditor 5 packages.

Improve storymap text editing by preserving the selected range when toolbar formatting is applied, so bold, italic, underline, text color, and background color now work both on selected text and for subsequent typing. Reuse the shared editor setup across storymap fields, keep the content editor multiline, and turn the title editor into a compact single-line field with a reduced inline-formatting toolbar.

Tighten the editor styling by containing overflow and scroll anchoring inside the storymap editors, keep frontend storymap images responsive with height: auto, and remove the temporary CKEditor debugging hooks and console logging used during troubleshooting.

Co-authored-by: Codex OpenAI <codex@openai.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Codex OpenAI <codex@openai.com>
Co-authored-by: Codex OpenAI <codex@openai.com>
Co-authored-by: Codex OpenAI <codex@openai.com>
Wire the sidebar action to the editor preview, prevent the settings button from submitting the form, and map bounds to north/east/south/west correctly in both map editors.

Intended for PR #490.

Co-authored-by: Codex OpenAI <codex@openai.com>
Use the shared WordPress control wrapper for FormTokenField so the editor opts into the next spacing and size defaults and stops emitting the deprecation warnings.

Intended for PR #492.

Co-authored-by: Codex OpenAI <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Codex <codex@openai.com>
bwstefano and others added 29 commits April 9, 2026 11:03
Switch the storymap editors from the legacy ckeditor5-build-full bundle to the modular ckeditor5 package and update the React integration to @ckeditor/ckeditor5-react 9.5.0. Refresh the npm lockfile to match the new CKEditor 5 packages.

Improve storymap text editing by preserving the selected range when toolbar formatting is applied, so bold, italic, underline, text color, and background color now work both on selected text and for subsequent typing. Reuse the shared editor setup across storymap fields, keep the content editor multiline, and turn the title editor into a compact single-line field with a reduced inline-formatting toolbar.

Tighten the editor styling by containing overflow and scroll anchoring inside the storymap editors, keep frontend storymap images responsive with height: auto, and remove the temporary CKEditor debugging hooks and console logging used during troubleshooting.

Co-authored-by: Codex OpenAI <codex@openai.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Codex OpenAI <codex@openai.com>
Co-authored-by: Codex OpenAI <codex@openai.com>
…ix' into codex/block-api-v3-migration-authorfix
Co-authored-by: Codex OpenAI <codex@openai.com>
Co-authored-by: Codex OpenAI <codex@openai.com>
Co-authored-by: Codex OpenAI <codex@openai.com>
Wire the sidebar action to the editor preview, prevent the settings button from submitting the form, and map bounds to north/east/south/west correctly in both map editors.

Intended for PR #490.

Co-authored-by: Codex OpenAI <codex@openai.com>
Use the shared WordPress control wrapper for FormTokenField so the editor opts into the next spacing and size defaults and stops emitting the deprecation warnings.

Intended for PR #492.

Co-authored-by: Codex OpenAI <codex@openai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants