@plaudit/gutenberg-api-extensions 2.85.0 → 2.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/blocks/basic-custom-block-bindings-support.js +1 -2
- package/dist/blocks/basic-custom-block-bindings-support.js.map +1 -1
- package/dist/blocks/conditions.js +4 -2
- package/dist/blocks/conditions.js.map +1 -1
- package/dist/blocks/data-controller/reducer.js +3 -2
- package/dist/blocks/data-controller/reducer.js.map +1 -1
- package/dist/blocks/data-controller/trigger-handlers.js +3 -3
- package/dist/blocks/data-controller/trigger-handlers.js.map +1 -1
- package/dist/blocks/data-controller/utils.d.ts +5 -2
- package/dist/blocks/data-controller/utils.js +25 -2
- package/dist/blocks/data-controller/utils.js.map +1 -1
- package/dist/blocks/data-controller.d.ts +1 -1
- package/dist/blocks/data-controller.js +1 -1
- package/dist/blocks/data-controller.js.map +1 -1
- package/dist/blocks/hooks/built-in-suspendable-option-protocols/select.js +2 -2
- package/dist/blocks/hooks/built-in-suspendable-option-protocols/select.js.map +1 -1
- package/dist/blocks/hooks/useSuspendableOptions.js +5 -5
- package/dist/blocks/hooks/useSuspendableOptions.js.map +1 -1
- package/dist/blocks/snp-data-store.d.ts +1 -1
- package/dist/blocks/utilities.d.ts +0 -14
- package/dist/blocks/utilities.js +0 -3
- package/dist/blocks/utilities.js.map +1 -1
- package/dist/controls/ExtendedFormTokenField.js +3 -3
- package/dist/controls/ExtendedFormTokenField.js.map +1 -1
- package/dist/controls/ExtendedTaxonomyPicker.js +2 -2
- package/dist/controls/ExtendedTaxonomyPicker.js.map +1 -1
- package/dist/controls/hooks/useImprovedTokenManager.d.ts +1 -1
- package/dist/controls/hooks/useImprovedTokenManager.js +2 -2
- package/dist/controls/hooks/useImprovedTokenManager.js.map +1 -1
- package/dist/editor/post-featured-image.js +1 -2
- package/dist/editor/post-featured-image.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +16 -16
- package/simple-native-properties.md +106 -92
- package/src/blocks/basic-custom-block-bindings-support.tsx +2 -3
- package/src/blocks/conditions.ts +4 -3
- package/src/blocks/data-controller/reducer.ts +4 -3
- package/src/blocks/data-controller/trigger-handlers.ts +5 -4
- package/src/blocks/data-controller/utils.ts +27 -4
- package/src/blocks/data-controller.ts +2 -2
- package/src/blocks/hooks/built-in-suspendable-option-protocols/select.ts +2 -2
- package/src/blocks/hooks/useSuspendableOptions.ts +3 -4
- package/src/blocks/utilities.ts +0 -10
- package/src/controls/ExtendedFormTokenField.tsx +3 -4
- package/src/controls/ExtendedTaxonomyPicker.tsx +2 -2
- package/src/controls/hooks/useImprovedTokenManager.ts +2 -3
- package/src/editor/post-featured-image.tsx +3 -5
- package/src/index.ts +0 -1
- package/dist/lib/use-select-typed.d.ts +0 -3
- package/dist/lib/use-select-typed.js +0 -12
- package/dist/lib/use-select-typed.js.map +0 -1
- package/src/lib/use-select-typed.ts +0 -8
|
@@ -1,49 +1,63 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- TOC -->
|
|
2
|
+
* [What are Simple Native Properties (SNPs)?](#what-are-simple-native-properties-snps)
|
|
3
|
+
* [⚡ Quick Start Example](#-quick-start-example)
|
|
4
|
+
* [📋 Control Reference](#-control-reference)
|
|
5
|
+
* [Common Properties (Available on All Controls)](#common-properties-available-on-all-controls)
|
|
6
|
+
* [🎛️ Control Types](#-control-types)
|
|
7
|
+
* [Basic Input Controls](#basic-input-controls)
|
|
8
|
+
* [`text`](#text)
|
|
9
|
+
* [Additional Properties](#additional-properties)
|
|
10
|
+
* [`textarea`](#textarea)
|
|
11
|
+
* [Additional Properties](#additional-properties-1)
|
|
12
|
+
* [`number`](#number)
|
|
13
|
+
* [Additional Properties](#additional-properties-2)
|
|
14
|
+
* [`range`](#range)
|
|
15
|
+
* [Additional Properties](#additional-properties-3)
|
|
16
|
+
* [Toggle & Choice Controls](#toggle--choice-controls)
|
|
17
|
+
* [`toggle`](#toggle)
|
|
18
|
+
* [Additional Properties](#additional-properties-4)
|
|
19
|
+
* [`toggleGroup`](#togglegroup)
|
|
20
|
+
* [Additional Properties](#additional-properties-5)
|
|
21
|
+
* [`select`](#select)
|
|
22
|
+
* [Additional Properties](#additional-properties-6)
|
|
23
|
+
* [`radio`](#radio)
|
|
24
|
+
* [Additional Properties](#additional-properties-7)
|
|
25
|
+
* [`colorPalette`](#colorpalette)
|
|
26
|
+
* [Additional Properties](#additional-properties-8)
|
|
27
|
+
* [Media & Relational Controls](#media--relational-controls)
|
|
28
|
+
* [`file`](#file)
|
|
29
|
+
* [`image`](#image)
|
|
30
|
+
* [`link`](#link)
|
|
31
|
+
* [`post`](#post)
|
|
32
|
+
* [`taxonomy`](#taxonomy)
|
|
33
|
+
* [`term`](#term)
|
|
34
|
+
* [`user`](#user)
|
|
35
|
+
* [Structure & Collection Controls](#structure--collection-controls)
|
|
36
|
+
* [`group`](#group)
|
|
37
|
+
* [`list`](#list)
|
|
38
|
+
* [`date`](#date)
|
|
39
|
+
* [`constant`](#constant)
|
|
40
|
+
* [🏗️ Organization & Logic](#-organization--logic)
|
|
41
|
+
* [1. Structure (Panels & Tabs)](#1-structure-panels--tabs)
|
|
42
|
+
* [2. Layout (Rows)](#2-layout-rows)
|
|
43
|
+
* [3. Conditions (Show/Hide Logic)](#3-conditions-showhide-logic)
|
|
44
|
+
* [4. Option Sources (Dynamic Options)](#4-option-sources-dynamic-options)
|
|
45
|
+
* [Source Syntax](#source-syntax)
|
|
46
|
+
* [The `select` Protocol](#the-select-protocol)
|
|
47
|
+
* [The `settings` Protocol](#the-settings-protocol)
|
|
48
|
+
* [🔧 Advanced Features](#-advanced-features)
|
|
49
|
+
* [Style Properties](#style-properties)
|
|
50
|
+
* [Validators & Transformers](#validators--transformers)
|
|
51
|
+
* [Tips & Best Practices](#tips--best-practices)
|
|
52
|
+
<!-- TOC -->
|
|
2
53
|
|
|
3
|
-
|
|
54
|
+
---
|
|
4
55
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- [Quick Start Example](#-quick-start-example)
|
|
8
|
-
- [Control Reference](#-control-reference)
|
|
9
|
-
- [Common Properties](#common-properties-available-on-all-controls)
|
|
10
|
-
- [Control Types](#️-control-types)
|
|
11
|
-
- [Basic Input Controls](#basic-input-controls)
|
|
12
|
-
- [`text`](#text)
|
|
13
|
-
- [`textarea`](#textarea)
|
|
14
|
-
- [`number`](#number)
|
|
15
|
-
- [`range`](#range)
|
|
16
|
-
- [Toggle & Choice Controls](#toggle--choice-controls)
|
|
17
|
-
- [`toggle`](#toggle)
|
|
18
|
-
- [`toggleGroup`](#togglegroup)
|
|
19
|
-
- [`select`](#select)
|
|
20
|
-
- [`radio`](#radio)
|
|
21
|
-
- [`colorPalette`](#colorpalette)
|
|
22
|
-
- [Media & Relational Controls](#media--relational-controls)
|
|
23
|
-
- [`image`](#image)
|
|
24
|
-
- [`link`](#link)
|
|
25
|
-
- [`post`](#post)
|
|
26
|
-
- [`taxonomy`](#taxonomy)
|
|
27
|
-
- [`term`](#term)
|
|
28
|
-
- [`user`](#user)
|
|
29
|
-
- [Structure & Collection Controls](#structure--collection-controls)
|
|
30
|
-
- [`group`](#group)
|
|
31
|
-
- [`list`](#list)
|
|
32
|
-
- [`date`](#date)
|
|
33
|
-
- [`constant`](#constant)
|
|
34
|
-
- [Organization & Logic](#️-organization--logic)
|
|
35
|
-
- [1. Structure (Panels & Tabs)](#1-structure-panels--tabs)
|
|
36
|
-
- [2. Layout (Rows)](#2-layout-rows)
|
|
37
|
-
- [3. Conditions (Show/Hide Logic)](#3-conditions-showhide-logic)
|
|
38
|
-
- [4. Option Sources (Dynamic Options)](#4-option-sources-dynamic-options)
|
|
39
|
-
- [Advanced Features](#-advanced-features)
|
|
40
|
-
- [Style Properties](#style-properties)
|
|
41
|
-
- [Validators & Transformers](#validators--transformers)
|
|
42
|
-
- [Tips & Best Practices](#tips--best-practices)
|
|
56
|
+
# What are Simple Native Properties (SNPs)?
|
|
43
57
|
|
|
44
|
-
|
|
58
|
+
SNP allows you to define Inspector (sidebar) controls in `block.json` purely with data, avoiding custom React code for standard use cases.
|
|
45
59
|
|
|
46
|
-
|
|
60
|
+
# ⚡ Quick Start Example
|
|
47
61
|
|
|
48
62
|
Copy and adapt this block to cover 90% of your use cases. It demonstrates **Panels**, **Layouts**, **Conditions**, and **Common Controls**.
|
|
49
63
|
|
|
@@ -81,7 +95,7 @@ Copy and adapt this block to cover 90% of your use cases. It demonstrates **Pane
|
|
|
81
95
|
"title": "Design Settings",
|
|
82
96
|
"group": "styles",
|
|
83
97
|
"properties": [
|
|
84
|
-
{ "name": "bgColor", "label": "Background", "control": "colorPalette", "options": "
|
|
98
|
+
{ "name": "bgColor", "label": "Background", "control": "colorPalette", "options": "settings://color.palette" },
|
|
85
99
|
{ "name": "opacity", "label": "Opacity", "control": "range", "min": 0, "max": 100, "step": 10 },
|
|
86
100
|
{
|
|
87
101
|
"name": "align", "label": "Alignment", "control": "select",
|
|
@@ -99,11 +113,11 @@ Copy and adapt this block to cover 90% of your use cases. It demonstrates **Pane
|
|
|
99
113
|
|
|
100
114
|
---
|
|
101
115
|
|
|
102
|
-
|
|
116
|
+
# 📋 Control Reference
|
|
103
117
|
|
|
104
118
|
All controls require three properties: `"control"`, `"name"`, and `"label"`.
|
|
105
119
|
|
|
106
|
-
|
|
120
|
+
## Common Properties (Available on All Controls)
|
|
107
121
|
|
|
108
122
|
| Property | Type | Description |
|
|
109
123
|
|:----------------|:---------|:-----------------------------------------------------------------------------------------------|
|
|
@@ -122,16 +136,16 @@ All controls require three properties: `"control"`, `"name"`, and `"label"`.
|
|
|
122
136
|
|
|
123
137
|
---
|
|
124
138
|
|
|
125
|
-
|
|
139
|
+
# 🎛️ Control Types
|
|
126
140
|
|
|
127
|
-
|
|
141
|
+
## Basic Input Controls
|
|
128
142
|
|
|
129
|
-
|
|
143
|
+
### `text`
|
|
130
144
|
Single-line text input.
|
|
131
145
|
|
|
132
146
|
**Value Type:** `string`
|
|
133
147
|
|
|
134
|
-
|
|
148
|
+
#### Additional Properties
|
|
135
149
|
| Property | Type | Description | Default |
|
|
136
150
|
|:--------------|:---------|:-----------------------------------|:--------|
|
|
137
151
|
| `placeholder` | `string` | Placeholder text shown when empty. | `''` |
|
|
@@ -150,12 +164,12 @@ Single-line text input.
|
|
|
150
164
|
|
|
151
165
|
---
|
|
152
166
|
|
|
153
|
-
|
|
167
|
+
### `textarea`
|
|
154
168
|
Multi-line text input.
|
|
155
169
|
|
|
156
170
|
**Value Type:** `string`
|
|
157
171
|
|
|
158
|
-
|
|
172
|
+
#### Additional Properties
|
|
159
173
|
| Property | Type | Description | Default |
|
|
160
174
|
|:-----------------|:---------|:----------------------------|:--------|
|
|
161
175
|
| `component.rows` | `number` | Number of visible text rows | `4` |
|
|
@@ -174,12 +188,12 @@ Multi-line text input.
|
|
|
174
188
|
|
|
175
189
|
---
|
|
176
190
|
|
|
177
|
-
|
|
191
|
+
### `number`
|
|
178
192
|
Numeric input with optional constraints.
|
|
179
193
|
|
|
180
194
|
**Value Type:** `number`
|
|
181
195
|
|
|
182
|
-
|
|
196
|
+
#### Additional Properties
|
|
183
197
|
| Property | Type | Description | Default |
|
|
184
198
|
|:--------------|:------------------|:------------------------------------------------------|:--------|
|
|
185
199
|
| `min` | `number` | Minimum allowed value | `unset` |
|
|
@@ -204,12 +218,12 @@ Numeric input with optional constraints.
|
|
|
204
218
|
|
|
205
219
|
---
|
|
206
220
|
|
|
207
|
-
|
|
221
|
+
### `range`
|
|
208
222
|
Slider control for selecting numeric values.
|
|
209
223
|
|
|
210
224
|
**Value Type:** `number`
|
|
211
225
|
|
|
212
|
-
|
|
226
|
+
#### Additional Properties
|
|
213
227
|
| Property | Type | Description | Default |
|
|
214
228
|
|:---------|:---------|:------------------------------------|:--------|
|
|
215
229
|
| `min` | `number` | **Required.** Minimum allowed value | `unset` |
|
|
@@ -232,14 +246,14 @@ Slider control for selecting numeric values.
|
|
|
232
246
|
|
|
233
247
|
---
|
|
234
248
|
|
|
235
|
-
|
|
249
|
+
## Toggle & Choice Controls
|
|
236
250
|
|
|
237
|
-
|
|
251
|
+
### `toggle`
|
|
238
252
|
Boolean on/off switch.
|
|
239
253
|
|
|
240
254
|
**Value Type:** `boolean`
|
|
241
255
|
|
|
242
|
-
|
|
256
|
+
#### Additional Properties
|
|
243
257
|
- `switch` (`string | object`): Switch style configuration.
|
|
244
258
|
- String values: `"yesNo"`, `"showHide"`
|
|
245
259
|
- Object with properties:
|
|
@@ -291,12 +305,12 @@ Boolean on/off switch.
|
|
|
291
305
|
|
|
292
306
|
---
|
|
293
307
|
|
|
294
|
-
|
|
308
|
+
### `toggleGroup`
|
|
295
309
|
Button group for selecting one value from multiple options.
|
|
296
310
|
|
|
297
311
|
**Value Type:** `string` or `number`
|
|
298
312
|
|
|
299
|
-
|
|
313
|
+
#### Additional Properties
|
|
300
314
|
| Property | Type | Description | Default |
|
|
301
315
|
|:------------|:-----------------------|:---------------------------------------------------------------------------------------------------------------------------------|:-----------|
|
|
302
316
|
| `options` | `array \| string` | **Required.** Array of `[value, label]` tuples or option objects or a [dynamic source string](#4-option-sources-dynamic-options) | `unset` |
|
|
@@ -335,12 +349,12 @@ Button group for selecting one value from multiple options.
|
|
|
335
349
|
|
|
336
350
|
---
|
|
337
351
|
|
|
338
|
-
|
|
352
|
+
### `select`
|
|
339
353
|
Dropdown selection control.
|
|
340
354
|
|
|
341
355
|
**Value Type:** `string` (single) or `string[]` (multiple)
|
|
342
356
|
|
|
343
|
-
|
|
357
|
+
#### Additional Properties
|
|
344
358
|
| Property | Type | Description | Default |
|
|
345
359
|
|:----------------|:------------------|:---------------------------------------------------------------------------------------------------------------------------------|:--------|
|
|
346
360
|
| `options` | `array \| string` | **Required.** Array of `[value, label]` tuples or option objects or a [dynamic source string](#4-option-sources-dynamic-options) | `unset` |
|
|
@@ -384,12 +398,12 @@ Dropdown selection control.
|
|
|
384
398
|
|
|
385
399
|
---
|
|
386
400
|
|
|
387
|
-
|
|
401
|
+
### `radio`
|
|
388
402
|
Radio button group for selecting one option.
|
|
389
403
|
|
|
390
404
|
**Value Type:** `string`
|
|
391
405
|
|
|
392
|
-
|
|
406
|
+
#### Additional Properties
|
|
393
407
|
| Property | Type | Description | Default |
|
|
394
408
|
|:--------------|:------------------|:---------------------------------------------------------------------------------------------------------------------------------|:--------|
|
|
395
409
|
| `options` | `array \| string` | **Required.** Array of `[value, label]` tuples or option objects or a [dynamic source string](#4-option-sources-dynamic-options) | `unset` |
|
|
@@ -414,12 +428,12 @@ Radio button group for selecting one option.
|
|
|
414
428
|
|
|
415
429
|
---
|
|
416
430
|
|
|
417
|
-
|
|
431
|
+
### `colorPalette`
|
|
418
432
|
Color picker with theme palette integration.
|
|
419
433
|
|
|
420
434
|
**Value Type:** `string`
|
|
421
435
|
|
|
422
|
-
|
|
436
|
+
#### Additional Properties
|
|
423
437
|
| Property | Type | Description | Default |
|
|
424
438
|
|:--------------|:------------------|:----------------------------------------------------------------------------------------------------------------------------------------|:--------|
|
|
425
439
|
| `options` | `array \| string` | **Required.** Array of `[color string, label]` tuples or option objects or a [dynamic source string](#4-option-sources-dynamic-options) | `unset` |
|
|
@@ -433,16 +447,16 @@ Color picker with theme palette integration.
|
|
|
433
447
|
"name": "backgroundColor",
|
|
434
448
|
"label": "Background Color",
|
|
435
449
|
"control": "colorPalette",
|
|
436
|
-
"options": "
|
|
450
|
+
"options": "settings://color.palette",
|
|
437
451
|
"clearable": true
|
|
438
452
|
}
|
|
439
453
|
```
|
|
440
454
|
|
|
441
455
|
---
|
|
442
456
|
|
|
443
|
-
|
|
457
|
+
## Media & Relational Controls
|
|
444
458
|
|
|
445
|
-
|
|
459
|
+
### `file`
|
|
446
460
|
File selector with media library integration.
|
|
447
461
|
|
|
448
462
|
**Value Type:** `number` (attachment id)
|
|
@@ -461,7 +475,7 @@ File selector with media library integration.
|
|
|
461
475
|
}
|
|
462
476
|
```
|
|
463
477
|
|
|
464
|
-
|
|
478
|
+
### `image`
|
|
465
479
|
Image selector with media library integration.
|
|
466
480
|
|
|
467
481
|
**Value Type:** `object` (ImageData)
|
|
@@ -483,7 +497,7 @@ Image selector with media library integration.
|
|
|
483
497
|
|
|
484
498
|
---
|
|
485
499
|
|
|
486
|
-
|
|
500
|
+
### `link`
|
|
487
501
|
Link picker for URLs, pages, posts, etc.
|
|
488
502
|
|
|
489
503
|
**Value Type:** `object`
|
|
@@ -504,7 +518,7 @@ Link picker for URLs, pages, posts, etc.
|
|
|
504
518
|
|
|
505
519
|
---
|
|
506
520
|
|
|
507
|
-
|
|
521
|
+
### `post`
|
|
508
522
|
Post/page selector with search functionality.
|
|
509
523
|
|
|
510
524
|
**Value Type:** `number` (single) or `number[]` (multiple)
|
|
@@ -542,7 +556,7 @@ Post/page selector with search functionality.
|
|
|
542
556
|
|
|
543
557
|
---
|
|
544
558
|
|
|
545
|
-
|
|
559
|
+
### `taxonomy`
|
|
546
560
|
Taxonomy selector (categories, tags, custom taxonomies).
|
|
547
561
|
|
|
548
562
|
**Value Type:** `string` (single) or `string[]` (multiple)
|
|
@@ -569,7 +583,7 @@ Taxonomy selector (categories, tags, custom taxonomies).
|
|
|
569
583
|
|
|
570
584
|
---
|
|
571
585
|
|
|
572
|
-
|
|
586
|
+
### `term`
|
|
573
587
|
Taxonomy term selector (specific category/tag picker).
|
|
574
588
|
|
|
575
589
|
**Value Type:** `string` (single) or `string[]` (multiple)
|
|
@@ -593,7 +607,7 @@ Taxonomy term selector (specific category/tag picker).
|
|
|
593
607
|
|
|
594
608
|
---
|
|
595
609
|
|
|
596
|
-
|
|
610
|
+
### `user`
|
|
597
611
|
User selector with role filtering.
|
|
598
612
|
|
|
599
613
|
**Value Type:** `number` (single) or `number[]` (multiple)
|
|
@@ -629,9 +643,9 @@ User selector with role filtering.
|
|
|
629
643
|
|
|
630
644
|
---
|
|
631
645
|
|
|
632
|
-
|
|
646
|
+
## Structure & Collection Controls
|
|
633
647
|
|
|
634
|
-
|
|
648
|
+
### `group`
|
|
635
649
|
Groups related controls together visually.
|
|
636
650
|
|
|
637
651
|
**Value Type:** `object`
|
|
@@ -671,7 +685,7 @@ Groups related controls together visually.
|
|
|
671
685
|
|
|
672
686
|
---
|
|
673
687
|
|
|
674
|
-
|
|
688
|
+
### `list`
|
|
675
689
|
Repeatable list of items (simple strings/numbers or complex objects).
|
|
676
690
|
|
|
677
691
|
**Value Type:** `array`
|
|
@@ -760,7 +774,7 @@ Repeatable list of items (simple strings/numbers or complex objects).
|
|
|
760
774
|
|
|
761
775
|
---
|
|
762
776
|
|
|
763
|
-
|
|
777
|
+
### `date`
|
|
764
778
|
Date and optional time picker.
|
|
765
779
|
|
|
766
780
|
**Value Type:** `number` (Unix timestamp in milliseconds)
|
|
@@ -781,7 +795,7 @@ Date and optional time picker.
|
|
|
781
795
|
|
|
782
796
|
---
|
|
783
797
|
|
|
784
|
-
|
|
798
|
+
### `constant`
|
|
785
799
|
Hidden field with a constant value (not editable by users).
|
|
786
800
|
|
|
787
801
|
**Value Type:** Depends on `type` property
|
|
@@ -804,9 +818,9 @@ Hidden field with a constant value (not editable by users).
|
|
|
804
818
|
|
|
805
819
|
---
|
|
806
820
|
|
|
807
|
-
|
|
821
|
+
# 🏗️ Organization & Logic
|
|
808
822
|
|
|
809
|
-
|
|
823
|
+
## 1. Structure (Panels & Tabs)
|
|
810
824
|
|
|
811
825
|
Wrap your controls in **Panels** to create collapsible sections in the sidebar.
|
|
812
826
|
|
|
@@ -868,7 +882,7 @@ You can also organize panels into tabs:
|
|
|
868
882
|
|
|
869
883
|
---
|
|
870
884
|
|
|
871
|
-
|
|
885
|
+
## 2. Layout (Rows)
|
|
872
886
|
|
|
873
887
|
- **Single Control:** One control object per row.
|
|
874
888
|
- **Multiple Controls:** Wrap controls in an array to display them side-by-side.
|
|
@@ -884,7 +898,7 @@ You can also organize panels into tabs:
|
|
|
884
898
|
|
|
885
899
|
---
|
|
886
900
|
|
|
887
|
-
|
|
901
|
+
## 3. Conditions (Show/Hide Logic)
|
|
888
902
|
|
|
889
903
|
Add a `condition` array to any control or panel to show/hide it based on other property values.
|
|
890
904
|
|
|
@@ -965,14 +979,14 @@ Add a `condition` array to any control or panel to show/hide it based on other p
|
|
|
965
979
|
|
|
966
980
|
---
|
|
967
981
|
|
|
968
|
-
|
|
982
|
+
## 4. Option Sources (Dynamic Options)
|
|
969
983
|
|
|
970
984
|
For `select`, `radio`, `colorPalette`, and `toggleGroup` controls, you can use shorthand strings to load dynamic options:
|
|
971
985
|
|
|
972
|
-
|
|
986
|
+
### Source Syntax
|
|
973
987
|
- The source syntax is based off of the URI syntax and uses custom protocols. The two built-in protocols are `select` and `settings`; however, new ones can be registered via filters.
|
|
974
988
|
|
|
975
|
-
|
|
989
|
+
#### The `select` Protocol
|
|
976
990
|
**Notes:**
|
|
977
991
|
- This protocol is used to extract values from a Redux data store that has a `get` or `resolve` function that takes a `string` and `Record<string, any>` as its parameters.
|
|
978
992
|
- At present, that means using the `plaudit/simple-gutenberg-apis` store.
|
|
@@ -983,7 +997,7 @@ For `select`, `radio`, `colorPalette`, and `toggleGroup` controls, you can use s
|
|
|
983
997
|
- To test one of the registered endpoints, run `(await wp.data.select('plaudit/simple-gutenberg-apis').resolve('endpoint.name.here'))` in the same context
|
|
984
998
|
|
|
985
999
|
|
|
986
|
-
|
|
1000
|
+
#### The `settings` Protocol
|
|
987
1001
|
**Notes:**
|
|
988
1002
|
- This protocol is used to get values from the theme.json file
|
|
989
1003
|
- The returned values are effected by the current block (this is to allow for block-specific values, most-commonly font sizes and colors)
|
|
@@ -1016,9 +1030,9 @@ For `select`, `radio`, `colorPalette`, and `toggleGroup` controls, you can use s
|
|
|
1016
1030
|
|
|
1017
1031
|
---
|
|
1018
1032
|
|
|
1019
|
-
|
|
1033
|
+
# 🔧 Advanced Features
|
|
1020
1034
|
|
|
1021
|
-
|
|
1035
|
+
## Style Properties
|
|
1022
1036
|
|
|
1023
1037
|
This feature is intended for setting CSS custom variables based on a block's properties.
|
|
1024
1038
|
|
|
@@ -1047,7 +1061,7 @@ When the user enters `"20px 40px"`, the block wrapper will receive:
|
|
|
1047
1061
|
|
|
1048
1062
|
---
|
|
1049
1063
|
|
|
1050
|
-
|
|
1064
|
+
## Validators & Transformers
|
|
1051
1065
|
|
|
1052
1066
|
**Note:** These features are only available when using TypeScript/React to define properties programmatically.
|
|
1053
1067
|
|
|
@@ -1089,7 +1103,7 @@ When the user enters `"20px 40px"`, the block wrapper will receive:
|
|
|
1089
1103
|
|
|
1090
1104
|
---
|
|
1091
1105
|
|
|
1092
|
-
|
|
1106
|
+
# Tips & Best Practices
|
|
1093
1107
|
|
|
1094
1108
|
1. **Add Help Text:** Use the `help` property to guide users, especially for complex controls.
|
|
1095
1109
|
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
SelectControl, Spinner, TextControl, Tooltip
|
|
8
8
|
} from '@wordpress/components';
|
|
9
9
|
import {createHigherOrderComponent} from "@wordpress/compose";
|
|
10
|
-
import {dispatch, select} from "@wordpress/data";
|
|
10
|
+
import {dispatch, select, useSuspenseSelect} from "@wordpress/data";
|
|
11
11
|
import {store as editorStore} from "@wordpress/editor";
|
|
12
12
|
import {memo, useMemo} from "@wordpress/element";
|
|
13
13
|
import {addFilter} from "@wordpress/hooks";
|
|
@@ -16,7 +16,6 @@ import {registerSimpleGutenbergApiEndpoint} from "../editor/simple-gutenberg-end
|
|
|
16
16
|
import {store as endpointsStore} from "../editor/simple-gutenberg-endpoints-impl";
|
|
17
17
|
import {store as apiExtensionsStore} from "../lib/gutenberg-api-extensions-state";
|
|
18
18
|
import type {ActualBlockEditProps, BlockName} from "../lib/useful-types";
|
|
19
|
-
import {useSuspenseSelectTyped} from "../lib/use-select-typed";
|
|
20
19
|
|
|
21
20
|
import {type ReactElement, Suspense} from "react";
|
|
22
21
|
import {ErrorBoundary, FallbackProps} from "react-error-boundary";
|
|
@@ -140,7 +139,7 @@ export function installCustomBlockBindingsSupport() {
|
|
|
140
139
|
});
|
|
141
140
|
const SourceSubconfig = memo(({currentPost, value, binding}: Omit<BlockBindingToolProps, 'label'>) => {
|
|
142
141
|
type SuspenseResult = {selectableOptions: NonNullable<Parameters<typeof SelectControl>[0]['options']>, params: CBBParams};
|
|
143
|
-
const {selectableOptions, params: {dbSources/*, supportsContext*/}} =
|
|
142
|
+
const {selectableOptions, params: {dbSources/*, supportsContext*/}} = useSuspenseSelect((select): SuspenseResult => {
|
|
144
143
|
if (value?.source) {
|
|
145
144
|
const sourceQueryArgs = {current_post: currentPost, source: value.source};
|
|
146
145
|
const sourceOptions = select(endpointsStore).get("plaudit-base.custom-bindings.source.options", sourceQueryArgs) as GetSelectableOptionsResponse;
|
package/src/blocks/conditions.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import {store as blocksStore, type BlockInstance} from "@wordpress/blocks";
|
|
2
|
+
import {store as blockEditorStore} from "@wordpress/block-editor";
|
|
2
3
|
import {select} from "@wordpress/data";
|
|
3
4
|
|
|
4
5
|
import type {DataStore, NodePath, RawPath} from "./simple-native-property-api";
|
|
@@ -116,7 +117,7 @@ function testConditionStruct(conditions: ConditionStruct, propertyValueResolver:
|
|
|
116
117
|
export function resolveValueForCondition(propertyPath: RawPath, contextPath: RawPath, blockClientId: string, getDataStore: (property: string) => DataStore|undefined) {
|
|
117
118
|
if (propertyPath[0] === "@block") {
|
|
118
119
|
if (propertyPath.length >= 2) {
|
|
119
|
-
const blockEditorSelect = select(
|
|
120
|
+
const blockEditorSelect = select(blockEditorStore);
|
|
120
121
|
if (typeof propertyPath[1] === 'string') {
|
|
121
122
|
if (propertyPath[1] === 'parentClientId') {
|
|
122
123
|
console.warn("Using parentClientId is deprecated. Please use clientId(1) instead.");
|
|
@@ -158,7 +159,7 @@ export function resolveValueForCondition(propertyPath: RawPath, contextPath: Raw
|
|
|
158
159
|
case "name":
|
|
159
160
|
return targetBlockInstance.name;
|
|
160
161
|
case "variation":
|
|
161
|
-
return (select(
|
|
162
|
+
return (select(blocksStore) as any).getActiveBlockVariation(targetBlockInstance.name, targetBlockInstance.attributes)?.name;
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
165
|
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
applyToTree, buildDefaultValueFromDefinition,
|
|
11
11
|
buildNodeFromDataAndDefinition, getDataStore,
|
|
12
12
|
moveNodeWithinParent,
|
|
13
|
-
populateValueBasedOnDefinition, recordCloneableDefaultValueForNode,
|
|
13
|
+
populateValueBasedOnDefinition, recordCloneableDefaultValueForNode, removeBackupForNode,
|
|
14
14
|
removeFromParentNode, removeValueFromBackingDataStore,
|
|
15
15
|
resolveParentNodeDefinition, TreeMutatorResult,
|
|
16
16
|
walkToNode, writeValueToBackingDataStoreWithCorrections
|
|
@@ -123,7 +123,8 @@ export function buildReducer(blockClientId: string) {
|
|
|
123
123
|
.addCase(actions.node.remove, (state, {payload: {path}}) => {
|
|
124
124
|
const parentNode = walkToNode(state.treeRoot, path.slice(0, path.length - 1));
|
|
125
125
|
removeFromParentNode(parentNode.children, path);
|
|
126
|
-
removeValueFromBackingDataStore(getDataStore(path[0], state), path);
|
|
126
|
+
removeValueFromBackingDataStore(getDataStore(path[0], state, true), path);
|
|
127
|
+
removeBackupForNode(walkToNode(state.treeRoot, path));
|
|
127
128
|
})
|
|
128
129
|
.addCase(actions.node.move, (state, {payload: {path, ...action}}) => {
|
|
129
130
|
// If from and to are the same, then this is a no-op, so we can just skip it
|
|
@@ -132,7 +133,7 @@ export function buildReducer(blockClientId: string) {
|
|
|
132
133
|
}
|
|
133
134
|
state.changedByManagedControl = true;
|
|
134
135
|
moveNodeWithinParent(walkToNode(state.treeRoot, path).children, path, action);
|
|
135
|
-
const dataStore = getDataStore(path[0], state);
|
|
136
|
+
const dataStore = getDataStore(path[0], state, true);
|
|
136
137
|
dataStore.setValue(path[0], produce(dataStore.getValue(path[0]), (dsDraft: any) => {
|
|
137
138
|
moveNodeWithinParent(walkToNodeInValue(dsDraft, path), path, action);
|
|
138
139
|
}));
|
|
@@ -7,10 +7,11 @@ import type {DCNode, DCStoreState} from "../data-controller";
|
|
|
7
7
|
import {resolveValueForCondition, testCondition} from "../conditions";
|
|
8
8
|
import {
|
|
9
9
|
applyToTree,
|
|
10
|
-
buildDefaultValueFromDefinition,
|
|
11
10
|
getDataStore,
|
|
12
11
|
getOptionalValue,
|
|
12
|
+
recordBackupForNode,
|
|
13
13
|
removeValueFromBackingDataStore,
|
|
14
|
+
restoreValueFromPotentialBackup,
|
|
14
15
|
TreeMutatorResult,
|
|
15
16
|
walkToNode,
|
|
16
17
|
walkToNodeInValue,
|
|
@@ -111,7 +112,7 @@ function performConditionChecks(state: Draft<DCStoreState>) {
|
|
|
111
112
|
} else {
|
|
112
113
|
const newRendered = testCondition(condition, propertyValueResolverBuilder(path));
|
|
113
114
|
if (newRendered !== node.rendered) {
|
|
114
|
-
const dataStore = getDataStore(path[0], state);
|
|
115
|
+
const dataStore = getDataStore(path[0], state, true);
|
|
115
116
|
let currentValue: any;
|
|
116
117
|
try {
|
|
117
118
|
currentValue = walkToNodeInValue(dataStore.getValue(path[0]), path);
|
|
@@ -123,12 +124,12 @@ function performConditionChecks(state: Draft<DCStoreState>) {
|
|
|
123
124
|
}
|
|
124
125
|
if (!newRendered) {
|
|
125
126
|
// Create a backup if we are transitioning from rendered -> unrendered
|
|
126
|
-
node
|
|
127
|
+
recordBackupForNode(node, currentValue);
|
|
127
128
|
removeValueFromBackingDataStore(dataStore, path);
|
|
128
129
|
} else if (currentValue === undefined) {
|
|
129
130
|
// Restore from backup if we are transitioning from unrendered -> rendered
|
|
130
131
|
const stateNode = walkToNode(state.treeRoot, path);
|
|
131
|
-
writeValueToBackingDataStore(dataStore, path,
|
|
132
|
+
writeValueToBackingDataStore(dataStore, path, restoreValueFromPotentialBackup(stateNode));
|
|
132
133
|
}
|
|
133
134
|
node.rendered = newRendered;
|
|
134
135
|
}
|
|
@@ -109,8 +109,8 @@ export function descendIntoDCNodeChild(current: DCNode|undefined, path: RawPath,
|
|
|
109
109
|
return current;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError:
|
|
113
|
-
export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError?: undefined|
|
|
112
|
+
export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError: true): DataStore;
|
|
113
|
+
export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError?: undefined|boolean|false): DataStore|undefined;
|
|
114
114
|
export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError = true): DataStore|undefined {
|
|
115
115
|
let dataStore = state.dataStores.byProperty[property];
|
|
116
116
|
if (dataStore) {
|
|
@@ -127,7 +127,7 @@ export function getDataStore(property: string, state: Draft<DCStoreState>, throw
|
|
|
127
127
|
|
|
128
128
|
export function getOptionalValue(path: NodePath, state: Draft<DCStoreState>) {
|
|
129
129
|
try {
|
|
130
|
-
return walkToNodeInValue(getDataStore(path[0], state).getValue(path[0]), path);
|
|
130
|
+
return walkToNodeInValue(getDataStore(path[0], state, true).getValue(path[0]), path);
|
|
131
131
|
} catch (e) {
|
|
132
132
|
if (e instanceof PathError) {
|
|
133
133
|
return undefined;
|
|
@@ -162,7 +162,7 @@ export function writeValueToBackingDataStoreWithCorrections(path: NodePath, stat
|
|
|
162
162
|
if (rootDCNode === undefined) {
|
|
163
163
|
throw new PathError("Encountered a path pointing to a non-existent root node.", path, 0);
|
|
164
164
|
}
|
|
165
|
-
const dataStore = getDataStore(path[0], state);
|
|
165
|
+
const dataStore = getDataStore(path[0], state, true);
|
|
166
166
|
|
|
167
167
|
// This path both handles scalar values and ensures that the root "value" of Groups and Lists are initialized before writing the actual attribute
|
|
168
168
|
// To avoid accidentally overwriting group data when lazily adding items (i.e., via a ToolsPanel instance), we skip this code path if the group's root value has already been initialized
|
|
@@ -306,6 +306,29 @@ export function recordCloneableDefaultValueForNode<T extends HydratedSimpleNativ
|
|
|
306
306
|
return definition as HydratedSimpleNativeProperty<{uuid: UUID}>;
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
+
const recordedBackupValues: Record<UUID, any> = {};
|
|
310
|
+
export function recordBackupForNode(node: DCNode, value: any) {
|
|
311
|
+
if (!node.backup) {
|
|
312
|
+
node.backup = crypto.randomUUID();
|
|
313
|
+
}
|
|
314
|
+
recordedBackupValues[node.backup] = value;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export function restoreValueFromPotentialBackup(node: DCNode) {
|
|
318
|
+
if (node.backup && node.backup in recordedBackupValues) {
|
|
319
|
+
const res = recordedBackupValues[node.backup];
|
|
320
|
+
delete recordedBackupValues[node.backup];
|
|
321
|
+
return res ?? buildDefaultValueFromDefinition(node.definition);
|
|
322
|
+
}
|
|
323
|
+
return buildDefaultValueFromDefinition(node.definition)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export function removeBackupForNode(node: DCNode) {
|
|
327
|
+
if (node.backup && node.backup in recordedBackupValues) {
|
|
328
|
+
delete recordedBackupValues[node.backup];
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
309
332
|
export function buildDefaultValueFromDefinition(definition: (HydratedSimpleNativeProperty<{uuid: UUID}>)|undefined, requireNonNullValueOnObject = true): any {
|
|
310
333
|
if (definition === undefined) {
|
|
311
334
|
return undefined;
|
|
@@ -15,7 +15,7 @@ import {getDataStore, getOptionalValue, UUID, walkToNode} from "./data-controlle
|
|
|
15
15
|
|
|
16
16
|
type DescendantsWrapper = {[key: string]: DCNode}|DCNode[];
|
|
17
17
|
export type DCNode = {
|
|
18
|
-
backup?:
|
|
18
|
+
backup?: UUID,
|
|
19
19
|
rendered?: boolean,
|
|
20
20
|
condition?: Condition,
|
|
21
21
|
children?: DescendantsWrapper,
|
|
@@ -39,7 +39,7 @@ export function useDataController(blockClientId: string): DataController {
|
|
|
39
39
|
function getDataStoreImpl(property: string, required: true): DataStore;
|
|
40
40
|
function getDataStoreImpl(property: string, required?: undefined|false): DataStore|undefined;
|
|
41
41
|
function getDataStoreImpl(property: string, required?: boolean): DataStore|undefined {
|
|
42
|
-
return
|
|
42
|
+
return getDataStore(property, store.getState(), required);
|
|
43
43
|
}
|
|
44
44
|
const dataController: DataController = {
|
|
45
45
|
getDataStore: getDataStoreImpl,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import {useSuspenseSelect} from "@wordpress/data";
|
|
1
2
|
import {useMemo} from "@wordpress/element";
|
|
2
3
|
import {addFilter} from "@wordpress/hooks";
|
|
3
4
|
|
|
4
5
|
import {produce} from "immer";
|
|
5
6
|
|
|
6
7
|
import {useNodeContext} from "../../layout/NodeContext";
|
|
7
|
-
import {useSuspenseSelectTyped} from "../../../lib/use-select-typed";
|
|
8
8
|
|
|
9
9
|
export default function() {
|
|
10
10
|
addFilter(
|
|
@@ -43,7 +43,7 @@ export default function() {
|
|
|
43
43
|
return undefined;
|
|
44
44
|
}
|
|
45
45
|
}, [attributes, nodeContext]);
|
|
46
|
-
return
|
|
46
|
+
return useSuspenseSelect(select => {
|
|
47
47
|
return (select(selectorInfo.hostname + selectorInfo.pathname) as any).get(selectorInfo.username, trimmedAttributes);
|
|
48
48
|
}, [selectorInfo, trimmedAttributes]);
|
|
49
49
|
}, 100_000
|