@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.
Files changed (55) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/blocks/basic-custom-block-bindings-support.js +1 -2
  3. package/dist/blocks/basic-custom-block-bindings-support.js.map +1 -1
  4. package/dist/blocks/conditions.js +4 -2
  5. package/dist/blocks/conditions.js.map +1 -1
  6. package/dist/blocks/data-controller/reducer.js +3 -2
  7. package/dist/blocks/data-controller/reducer.js.map +1 -1
  8. package/dist/blocks/data-controller/trigger-handlers.js +3 -3
  9. package/dist/blocks/data-controller/trigger-handlers.js.map +1 -1
  10. package/dist/blocks/data-controller/utils.d.ts +5 -2
  11. package/dist/blocks/data-controller/utils.js +25 -2
  12. package/dist/blocks/data-controller/utils.js.map +1 -1
  13. package/dist/blocks/data-controller.d.ts +1 -1
  14. package/dist/blocks/data-controller.js +1 -1
  15. package/dist/blocks/data-controller.js.map +1 -1
  16. package/dist/blocks/hooks/built-in-suspendable-option-protocols/select.js +2 -2
  17. package/dist/blocks/hooks/built-in-suspendable-option-protocols/select.js.map +1 -1
  18. package/dist/blocks/hooks/useSuspendableOptions.js +5 -5
  19. package/dist/blocks/hooks/useSuspendableOptions.js.map +1 -1
  20. package/dist/blocks/snp-data-store.d.ts +1 -1
  21. package/dist/blocks/utilities.d.ts +0 -14
  22. package/dist/blocks/utilities.js +0 -3
  23. package/dist/blocks/utilities.js.map +1 -1
  24. package/dist/controls/ExtendedFormTokenField.js +3 -3
  25. package/dist/controls/ExtendedFormTokenField.js.map +1 -1
  26. package/dist/controls/ExtendedTaxonomyPicker.js +2 -2
  27. package/dist/controls/ExtendedTaxonomyPicker.js.map +1 -1
  28. package/dist/controls/hooks/useImprovedTokenManager.d.ts +1 -1
  29. package/dist/controls/hooks/useImprovedTokenManager.js +2 -2
  30. package/dist/controls/hooks/useImprovedTokenManager.js.map +1 -1
  31. package/dist/editor/post-featured-image.js +1 -2
  32. package/dist/editor/post-featured-image.js.map +1 -1
  33. package/dist/index.d.ts +0 -1
  34. package/dist/index.js +0 -1
  35. package/dist/index.js.map +1 -1
  36. package/package.json +16 -16
  37. package/simple-native-properties.md +106 -92
  38. package/src/blocks/basic-custom-block-bindings-support.tsx +2 -3
  39. package/src/blocks/conditions.ts +4 -3
  40. package/src/blocks/data-controller/reducer.ts +4 -3
  41. package/src/blocks/data-controller/trigger-handlers.ts +5 -4
  42. package/src/blocks/data-controller/utils.ts +27 -4
  43. package/src/blocks/data-controller.ts +2 -2
  44. package/src/blocks/hooks/built-in-suspendable-option-protocols/select.ts +2 -2
  45. package/src/blocks/hooks/useSuspendableOptions.ts +3 -4
  46. package/src/blocks/utilities.ts +0 -10
  47. package/src/controls/ExtendedFormTokenField.tsx +3 -4
  48. package/src/controls/ExtendedTaxonomyPicker.tsx +2 -2
  49. package/src/controls/hooks/useImprovedTokenManager.ts +2 -3
  50. package/src/editor/post-featured-image.tsx +3 -5
  51. package/src/index.ts +0 -1
  52. package/dist/lib/use-select-typed.d.ts +0 -3
  53. package/dist/lib/use-select-typed.js +0 -12
  54. package/dist/lib/use-select-typed.js.map +0 -1
  55. package/src/lib/use-select-typed.ts +0 -8
@@ -1,49 +1,63 @@
1
- # Simple Native Properties (SNP)
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
- SNP allows you to define Inspector (sidebar) controls in `block.json` purely with data, avoiding custom React code for standard use cases.
54
+ ---
4
55
 
5
- ## 📑 Table of Contents
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
- ## ⚡ Quick Start Example
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": "select:theme:colors" },
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
- ## 📋 Control Reference
116
+ # 📋 Control Reference
103
117
 
104
118
  All controls require three properties: `"control"`, `"name"`, and `"label"`.
105
119
 
106
- ### Common Properties (Available on All Controls)
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
- ## 🎛️ Control Types
139
+ # 🎛️ Control Types
126
140
 
127
- ### Basic Input Controls
141
+ ## Basic Input Controls
128
142
 
129
- #### `text`
143
+ ### `text`
130
144
  Single-line text input.
131
145
 
132
146
  **Value Type:** `string`
133
147
 
134
- ##### Additional Properties
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
- #### `textarea`
167
+ ### `textarea`
154
168
  Multi-line text input.
155
169
 
156
170
  **Value Type:** `string`
157
171
 
158
- ##### Additional Properties
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
- #### `number`
191
+ ### `number`
178
192
  Numeric input with optional constraints.
179
193
 
180
194
  **Value Type:** `number`
181
195
 
182
- ##### Additional Properties
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
- #### `range`
221
+ ### `range`
208
222
  Slider control for selecting numeric values.
209
223
 
210
224
  **Value Type:** `number`
211
225
 
212
- ##### Additional Properties
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
- ### Toggle & Choice Controls
249
+ ## Toggle & Choice Controls
236
250
 
237
- #### `toggle`
251
+ ### `toggle`
238
252
  Boolean on/off switch.
239
253
 
240
254
  **Value Type:** `boolean`
241
255
 
242
- ##### Additional Properties
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
- #### `toggleGroup`
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
- ##### Additional Properties
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
- #### `select`
352
+ ### `select`
339
353
  Dropdown selection control.
340
354
 
341
355
  **Value Type:** `string` (single) or `string[]` (multiple)
342
356
 
343
- ##### Additional Properties
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
- #### `radio`
401
+ ### `radio`
388
402
  Radio button group for selecting one option.
389
403
 
390
404
  **Value Type:** `string`
391
405
 
392
- ##### Additional Properties
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
- #### `colorPalette`
431
+ ### `colorPalette`
418
432
  Color picker with theme palette integration.
419
433
 
420
434
  **Value Type:** `string`
421
435
 
422
- ##### Additional Properties
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": "select:theme:colors",
450
+ "options": "settings://color.palette",
437
451
  "clearable": true
438
452
  }
439
453
  ```
440
454
 
441
455
  ---
442
456
 
443
- ### Media & Relational Controls
457
+ ## Media & Relational Controls
444
458
 
445
- #### `file`
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
- #### `image`
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
- #### `link`
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
- #### `post`
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
- #### `taxonomy`
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
- #### `term`
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
- #### `user`
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
- ### Structure & Collection Controls
646
+ ## Structure & Collection Controls
633
647
 
634
- #### `group`
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
- #### `list`
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
- #### `date`
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
- #### `constant`
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
- ## 🏗️ Organization & Logic
821
+ # 🏗️ Organization & Logic
808
822
 
809
- ### 1. Structure (Panels & Tabs)
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
- ### 2. Layout (Rows)
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
- ### 3. Conditions (Show/Hide Logic)
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
- ### 4. Option Sources (Dynamic Options)
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
- #### Source Syntax
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
- ##### The `select` Protocol
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
- ##### The `settings` Protocol
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
- ## 🔧 Advanced Features
1033
+ # 🔧 Advanced Features
1020
1034
 
1021
- ### Style Properties
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
- ### Validators & Transformers
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
- ## Tips & Best Practices
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*/}} = useSuspenseSelectTyped((select): SuspenseResult => {
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;
@@ -1,4 +1,5 @@
1
- import type {BlockInstance} from "@wordpress/blocks";
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("core/block-editor");
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("core/blocks") as any).getActiveBlockVariation(targetBlockInstance.name, targetBlockInstance.attributes)?.name;
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.backup = currentValue;
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, stateNode.backup ?? buildDefaultValueFromDefinition(stateNode.definition));
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: false): DataStore|undefined;
113
- export function getDataStore(property: string, state: Draft<DCStoreState>, throwOnError?: undefined|true): DataStore;
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?: any,
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 required ? getDataStore(property, store.getState(), true) : getDataStore(property, store.getState(), false);
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 useSuspenseSelectTyped(select => {
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