Skip to content

Commit bdc5c90

Browse files
Atomic Editor first docs (#337)
1 parent cbc7db9 commit bdc5c90

13 files changed

Lines changed: 822 additions & 0 deletions

src/.vuepress/sidebars/data-structure.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,16 @@ module.exports = [
3737
'global-styles',
3838
]
3939
},
40+
{
41+
title: 'Atomic Structure',
42+
collapsable: false,
43+
sidebarDepth: -1,
44+
children: [
45+
'atomic-elements',
46+
'atomic-widgets',
47+
'atomic-prop-values',
48+
'atomic-styles',
49+
'atomic-global-classes',
50+
]
51+
},
4052
];

src/.vuepress/sidebars/hooks.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ module.exports = [
3131
'font-display',
3232
'form-validation',
3333
'forms',
34+
'kit-meta-to-preserve-on-import',
35+
'atomic-global-classes-update',
36+
'atomic-widgets-styles-register',
37+
'atomic-widgets-styles-clear',
3438
]
3539
},
3640
{
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Atomic Elements
2+
3+
<Badge type="tip" vertical="top" text="Elementor Core" /> <Badge type="warning" vertical="top" text="Advanced" />
4+
5+
Atomic elements are the new generation of layout elements introduced as part of Elementor's atomic architecture. Like containers, they are layout elements with nested capabilities, meaning that they can hold other elements. Each atomic element object contains information like the element id, element type, version, styling settings, interactions, editor settings and all the elements inside it.
6+
7+
## JSON Structure
8+
9+
Atomic element structure:
10+
11+
```json
12+
{
13+
"id": "12345678",
14+
"version": "0.0",
15+
"elType": "e-div-block",
16+
"isInner": false,
17+
"interactions": [],
18+
"settings": [],
19+
"editor_settings": [],
20+
"styles": [],
21+
"elements": []
22+
}
23+
```
24+
25+
## JSON Values
26+
27+
| Argument | Type | Description |
28+
|-------------------|----------------------|-------------|
29+
| `id` | _`string`_ | The unique identification key representing the element. |
30+
| `version` | _`string`_ | The element schema version, used for data migrations. |
31+
| `elType` | _`string`_ | The element type. Such as `e-div-block`, `e-flexbox`, or `e-grid`. |
32+
| `isInner` | _`boolean`_ | Whether the element is an inner element. |
33+
| `settings` | _`array`_/_`object`_ | The element data holding the values from the editor controls. It's an empty `array` if settings are not defined, or an `object` if the element has settings. |
34+
| `editor_settings` | _`array`_/_`object`_ | Editor-only metadata used by the Elementor editor (for example, the element label). Not rendered on the frontend. |
35+
| `interactions` | _`array`_ | A list of interactions (such as event-driven behaviors) attached to the element. |
36+
| `styles` | _`array`_/_`object`_ | Local style definitions attached to the element, including responsive variants and pseudo-state styles. |
37+
| `elements` | _`array`_ | An array of objects that holds all the nested elements. |
38+
39+
## Nested Elements
40+
41+
By design, atomic elements can hold nested elements. All the inner elements are stored in the `elements` value, and they can have their own nested elements. Atomic layout elements can be freely nested within each other – for example, an `e-div-block` can contain an `e-grid`, which in turn can contain an `e-flexbox`.
42+
43+
## Examples
44+
45+
### A Page with an Atomic Div Block
46+
47+
An example of a page that has a single empty atomic div block:
48+
49+
```json
50+
{
51+
"title": "Sample Page",
52+
"type": "page",
53+
"version": "0.4",
54+
"page_settings": [],
55+
"content": [
56+
{
57+
"id": "6edaa5b1",
58+
"version": "0.0",
59+
"elType": "e-div-block",
60+
"isInner": false,
61+
"settings": [],
62+
"editor_settings": [],
63+
"interactions": [],
64+
"styles": [],
65+
"elements": []
66+
}
67+
]
68+
}
69+
```
70+
71+
### A Page with Nested Atomic Elements
72+
73+
An example of a page that has an atomic div block containing an atomic grid, which in turn contains an atomic flexbox:
74+
75+
```json
76+
{
77+
"title": "atomic test",
78+
"type": "page",
79+
"version": "0.4",
80+
"page_settings": [],
81+
"content": [
82+
{
83+
"id": "6edaa5b1",
84+
"version": "0.0",
85+
"elType": "e-div-block",
86+
"isInner": false,
87+
"settings": [],
88+
"editor_settings": [],
89+
"interactions": [],
90+
"styles": [],
91+
"elements": [
92+
{
93+
"id": "3e443808",
94+
"version": "0.0",
95+
"elType": "e-grid",
96+
"isInner": false,
97+
"settings": [],
98+
"editor_settings": [],
99+
"interactions": [],
100+
"styles": [],
101+
"elements": [
102+
{
103+
"id": "6c95f17f",
104+
"version": "0.0",
105+
"elType": "e-flexbox",
106+
"isInner": false,
107+
"settings": [],
108+
"editor_settings": [],
109+
"interactions": [],
110+
"styles": [],
111+
"elements": []
112+
}
113+
]
114+
}
115+
]
116+
}
117+
]
118+
}
119+
```
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Atomic Global Classes
2+
3+
<Badge type="tip" vertical="top" text="Elementor Core" /> <Badge type="warning" vertical="top" text="Intermediate" />
4+
5+
Reads and writes use two contexts. **Frontend** is published data. **Preview** is the editor draft. Each side uses its own meta keys (`` vs `…_preview`).
6+
7+
Global classes live on `e_global_class` posts. Class JSON is `_elementor_global_class_data` / `_elementor_global_class_data_preview`. Documents store usage in `_elementor_used_global_class` / `_elementor_used_global_class_preview`. Reverse indexes: `_elementor_global_class_using_documents` (+ preview). Documents may also set `_elementor_global_class_usage_indexed` flags. The active Kit stores display order, `class_id → label` maps (frontend vs preview), a design-system sync map, and `class_id → post_id` lookup.
8+
9+
Each item matches the [atomic style](./atomic-styles.md) shape (`id`, `label`, `type`, `variants`).
10+
11+
## PHP access
12+
13+
```php
14+
use Elementor\Modules\GlobalClasses\Global_Classes_Repository;
15+
16+
$repository = Global_Classes_Repository::make();
17+
$repository->set_preview( true ); // draft
18+
$repository->set_preview( false ); // published (default)
19+
```
20+
21+
| Method | Role |
22+
|--------|------|
23+
| `all_labels()` | Ordered `class_id → label` (cheap). |
24+
| `get()`, `get_by_ids()` | One or many items; missing → `null` / omitted. |
25+
| `get_order()` | Ordered ID list. |
26+
| `each_item( $cb, … )` | Stream all classes in order. |
27+
| `all( $force )` | Full `Global_Classes` — heavy. |
28+
| `apply_changes` / `put` | Persist diffs or replace-all; both fire `elementor/global_classes/update`. |
29+
| `update_order_and_labels` | Kit order/labels only. |
30+
| `delete_all()` | Remove all classes in the current context. |
31+
32+
## REST API
33+
34+
Prefix every route with `/wp-json/elementor/v1/`. On **GET**, optional `context`: `frontend` (default) or `preview`.
35+
36+
| Method | Suffix | Notes |
37+
|--------|--------|-------|
38+
| `GET` | `global-classes` | Labels only, in order. |
39+
| `GET` | `global-classes/post` | Query: `post_id`. Full items for that document. |
40+
| `GET` | `global-classes/styles` | Query: `ids` (comma-separated). Bulk by ID. |
41+
| `GET` | `global-classes/usage` | Site-wide usage; `manage_options`. |
42+
| `PUT` | `global-classes` | Body: `changes`, `items`, `order`; optional `context`. Update-class capability. |
43+
44+
**`PUT` body (minimal):** `changes` = `{ added, deleted, modified, order? }`. `items` = only touched classes, `class_id` → full item. `order` = full ID list after the op. Set `changes.order: true` when reordering so caches invalidate. Hard cap: **1000** classes.
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Atomic Prop Values
2+
3+
<Badge type="tip" vertical="top" text="Elementor Core" /> <Badge type="warning" vertical="top" text="Advanced" />
4+
5+
Atomic controls often save values as a small object: a `$$type` string plus a `value` payload. The props resolver uses `$$type` to match the schema (and union members), to recurse into nested object/array props, and to pick the **transformer** that receives `value` (after nested resolution) and returns frontend-ready data. An optional `disabled` flag is passed through on the transform context.
6+
7+
## JSON Structure
8+
9+
```json
10+
{
11+
"$$type": "string",
12+
"value": "Hello"
13+
}
14+
```
15+
16+
## JSON Values
17+
18+
| Argument | Type | Description |
19+
|----------|------------|-------------|
20+
| `$$type` | _`string`_ | Prop kind / transformer key; must match the prop type for that control (and selects the branch for union types). |
21+
| `value` | _varies_ | Input passed to the transformer for that `$$type`; may contain further `{ $$type, value }` objects when the prop is composite. |
22+
23+
Allowed `$$type` values and the exact shape of `value` come from each widget’s schema in code. See [atomic widgets](./atomic-widgets.md) for how `settings` use these objects, and [atomic styles](./atomic-styles.md) for the same pattern inside style `variants[].props`.
24+
25+
## Examples by structure
26+
27+
The snippets below are trimmed from real document data. They highlight **shape**: whether `value` is a scalar, a sparse object, a nested tree of typed nodes, a homogeneous map, or a typed array—regardless of which widget or control produced them. Resolution still walks every nested `{ "$$type", "value" }` until the tree is plain JSON (strings, numbers, booleans, or `null`). Concrete `$$type` strings always come from the control schema in code.
28+
29+
### Composite object (mixed typed fields and plain data)
30+
31+
`value` is an object where **named keys** carry further typed props, plain arrays, or literals. One branch might be a full `{ "$$type", "value" }` while another stays a raw array or string.
32+
33+
```json
34+
{
35+
"$$type": "html-v3",
36+
"value": {
37+
"content": {
38+
"$$type": "string",
39+
"value": "My title"
40+
}
41+
}
42+
}
43+
```
44+
45+
46+
### Deep nesting (typed object inside typed object)
47+
48+
The same sparse shell can grow a **chain** of wrappers: a key inside `value` is itself a typed object whose own `value` contains more typed leaves (here, internal targets resolved as id + label).
49+
50+
```json
51+
{
52+
"$$type": "link",
53+
"value": {
54+
"destination": {
55+
"$$type": "query",
56+
"value": {
57+
"id": {
58+
"$$type": "number",
59+
"value": 33514
60+
},
61+
"label": {
62+
"$$type": "string",
63+
"value": "About Us"
64+
}
65+
}
66+
},
67+
"isTargetBlank": null
68+
}
69+
}
70+
```
71+
72+
### Typed array of primitives
73+
74+
`value` is an array at the top level; elements are **not** wrapped again unless the schema says so. Typical case: a list of stable ids referenced elsewhere (for example keys under `styles` on the element).
75+
76+
```json
77+
{
78+
"$$type": "classes",
79+
"value": ["e-132b96e-91b05d4"]
80+
}
81+
```
82+
83+
### Composite object with a single nested typed subtree
84+
85+
A flat-looking object whose fields are mostly **one** nested typed prop (plus room for more keys in other saves).
86+
87+
```json
88+
{
89+
"$$type": "background",
90+
"value": {
91+
"color": {
92+
"$$type": "color",
93+
"value": "#e8e8e8"
94+
}
95+
}
96+
}
97+
```
98+
99+
### Homogeneous map (same inner shape per key)
100+
101+
`value` behaves like a **record**: several keys share the same structural pattern (here every side resolves through the same `size` shape).
102+
103+
```json
104+
{
105+
"$$type": "dimensions",
106+
"value": {
107+
"block-start": {
108+
"$$type": "size",
109+
"value": {
110+
"unit": "px",
111+
"size": 15
112+
}
113+
},
114+
"block-end": {
115+
"$$type": "size",
116+
"value": {
117+
"unit": "px",
118+
"size": 15
119+
}
120+
},
121+
"inline-start": {
122+
"$$type": "size",
123+
"value": {
124+
"unit": "px",
125+
"size": 5
126+
}
127+
},
128+
"inline-end": {
129+
"$$type": "size",
130+
"value": {
131+
"unit": "px",
132+
"size": 5
133+
}
134+
}
135+
}
136+
}
137+
```
138+
139+
### Array of composite items
140+
141+
`value` is an array whose **items** are full typed objects again—useful for ordered lists such as shadow layers.
142+
143+
```json
144+
{
145+
"$$type": "box-shadow",
146+
"value": [
147+
{
148+
"$$type": "shadow",
149+
"value": {
150+
"hOffset": {
151+
"$$type": "size",
152+
"value": {
153+
"unit": "px",
154+
"size": 0
155+
}
156+
},
157+
"vOffset": {
158+
"$$type": "size",
159+
"value": {
160+
"unit": "px",
161+
"size": 0
162+
}
163+
},
164+
"blur": {
165+
"$$type": "size",
166+
"value": {
167+
"unit": "px",
168+
"size": 10
169+
}
170+
},
171+
"spread": {
172+
"$$type": "size",
173+
"value": {
174+
"unit": "px",
175+
"size": 0
176+
}
177+
},
178+
"color": {
179+
"$$type": "color",
180+
"value": "rgba(0, 0, 0, 0.75)"
181+
},
182+
"position": null
183+
}
184+
}
185+
]
186+
}
187+
```
188+

0 commit comments

Comments
 (0)