Add editor package
Scope: External — the full documented outcome is shippable from a 3rd-party plugin via
elementor/editor/v2/packagesand your own packageinit(); no Core changes required. Editing core packages is Core-only. Full split + disclaimer: skills-scope.md.
Implementation location
- Editor JS/TS: third-party plugin repo — own package bundle with
init()(npm/webpack or hand-built script). - PHP: filter
elementor/editor/v2/packagesand optionalelementor/editor/v2/scripts/env; for hand-built bundles also hookelementor/editor/v2/scripts/register+scripts/enqueue. - Do not modify Elementor Core. Core packages live in
packages/packages/core/editor-*— reference only. - Runnable reference: examples/example-plugin/ (
editor-example-featureplain JS bundle).
Prerequisites
- Experiment
e_atomic_elements(and oftene_opt_in_v4) — getting-started/experiments.md. - In-editor MCP has no separate experiment gate beyond editor availability.
Read first: editor-packages/extending-editor.md, docs/atomic-builder/examples/add-editor-package.md. Monorepo package creation (Core contributors): packages/docs/creating-a-new-package.md.
Checklist
A. npm / webpack path (preferred for React UI)
- PHP: register package slug — append to
elementor/editor/v2/packages(e.g.editor-my-feature). Optional env viaelementor/editor/v2/scripts/env. - Build — webpack (or Vite) with
@elementor/*as externals resolved at runtime viawindow.elementorV2.*— see packages/docs/architecture.md and editor-packages/libs.md. - Output contract — bundle exposes
window.elementorV2.{camelCaseSlug}(e.g.editor-my-feature→editorMyFeature). Slug → global:kebabToCamelCaseinscripts/vite/shared/packages-externals.mjs(drop hyphens, uppercase the following letter). Core Vite build footer auto-calls?.init?.()for packages built into Core assets. - Enqueue your bundle —
wp_register_script()/wp_enqueue_script()with the plugin's own URL (e.g.plugins_url( 'assets/js/my-bundle.js', MY_PLUGIN_FILE )); the packages filter does not load third-party JS. src/init.ts(x)— synchronous registration only; re-export fromsrc/index.ts.
B. Hand-built script path (no npm pipeline)
- Hook
elementor/editor/v2/scripts/registertowp_register_script()your plugin JS (URL viaplugins_url( ..., MY_PLUGIN_FILE )) with deps on requiredelementor-v2-*handles. Common verified handles (fromcore/editor/loader/editor-loader.php+scripts/vite/build-packages.mjselementor-v2-${name}):elementor-v2-editor,elementor-v2-editor-app-bar,elementor-v2-editor-panels,elementor-v2-ui,elementor-v2-icons. - Hook
elementor/editor/v2/scripts/enqueueto enqueue that handle. - You must call
init()yourself — append at end of bundle:
window.elementorV2.editorMyFeature?.init?.();
Adding the slug to elementor/editor/v2/packages alone does nothing if no Core .asset.php exists for that slug — manual script registration carries the load.
- No JSX build step — use
window.React+React.createElement(React is externalized as globalReactinscripts/vite/shared/packages-externals.mjs). - Slug → global — same
kebabToCamelCaserule as path A (e.g.editor-my-feature→window.elementorV2.editorMyFeature). - Late-loaded global alternative —
window.elementorV2.{camelCasePackage}for scripts enqueued after editor packages; see extending-editor.md.
C. Common init() work
- Pick injection API (read doc for full list):
- Shell:
injectIntoTop,injectIntoLogic(@elementor/editor) - App bar:
injectIntoPageIndication,toolsMenu(@elementor/editor-app-bar) - Editing panel:
injectIntoStyleTab,registerEditingPanelReplacement(@elementor/editor-editing-panel) - Elements panel:
injectTab(@elementor/editor-elements-panel) - Site Settings:
injectSiteSettingsTab(@elementor/editor-site-settings) - Slide-in panels:
registerPanel(@elementor/editor-panels;__registerPanelis a legacy alias) - Styles:
stylesRepository.register(@elementor/editor-styles-repository) - Legacy bridge:
registerDataHook,blockCommand,__privateListenTo( v1ReadyEvent(), fn )(@elementor/editor-v1-adapters)
- Shell:
- In-editor MCP only —
getMCPByDomain()+ Zod from@elementor/schema; namespace/^[a-z_]+$/. Not PHPmodules/mcp/abilities — see mcp/overview.md.
Verify
- Script loads in editor network tab;
window.elementorV2.{camelCaseSlug}exists. - UI renders in chosen slot.
- MCP tools visible when Angie / WebMCP is enabled.
Minimal init skeleton
import { injectIntoPageIndication, toolsMenu } from '@elementor/editor-app-bar';
export function init() {
injectIntoPageIndication( { id: 'my-indicator', component: MyIndicator } );
toolsMenu.registerToggleAction( { id: 'toggle-my-panel', priority: 20, useProps: useMyToggleProps } );
}
Reference: packages/packages/core/editor-site-navigation/src/init.ts.
External implementation path
- Third-party plugin ships own editor bundle; filter
elementor/editor/v2/packages(+ manual script hooks for non-Core-built bundles). - Register MCP tools only for in-editor agent workflows via
@elementor/editor-mcp.
Core reference paths (do not edit)
- Core packages:
packages/packages/core/editor-*. - Pro extensions:
packages/packages/pro/editor-*-extended(elementor-pro sibling repo). - Loader:
core/editor/loader/.
See also
- editor-packages/overview.md
- extend-variables —
registerVariableTypein your packageinit() - mcp/registering-editor-tools.md