@plaudit/gutenberg-api-extensions 2.84.4 → 2.85.1

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 (32) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/blocks/common-native-property-constructors.js +12 -0
  3. package/dist/blocks/common-native-property-constructors.js.map +1 -1
  4. package/dist/blocks/csnp-api.d.ts +4 -3
  5. package/dist/blocks/csnp-api.js +3 -2
  6. package/dist/blocks/csnp-api.js.map +1 -1
  7. package/dist/blocks/data-controller/reducer.js +3 -2
  8. package/dist/blocks/data-controller/reducer.js.map +1 -1
  9. package/dist/blocks/data-controller/trigger-handlers.js +3 -3
  10. package/dist/blocks/data-controller/trigger-handlers.js.map +1 -1
  11. package/dist/blocks/data-controller/utils.d.ts +5 -2
  12. package/dist/blocks/data-controller/utils.js +25 -2
  13. package/dist/blocks/data-controller/utils.js.map +1 -1
  14. package/dist/blocks/data-controller.d.ts +1 -1
  15. package/dist/blocks/data-controller.js +1 -1
  16. package/dist/blocks/data-controller.js.map +1 -1
  17. package/dist/controls/FileControl.d.ts +9 -0
  18. package/dist/controls/FileControl.js +27 -0
  19. package/dist/controls/FileControl.js.map +1 -0
  20. package/dist/controls/index.d.ts +1 -0
  21. package/dist/controls/index.js +1 -0
  22. package/dist/controls/index.js.map +1 -1
  23. package/package.json +5 -5
  24. package/simple-native-properties.md +122 -89
  25. package/src/blocks/common-native-property-constructors.tsx +13 -1
  26. package/src/blocks/csnp-api.ts +11 -8
  27. package/src/blocks/data-controller/reducer.ts +4 -3
  28. package/src/blocks/data-controller/trigger-handlers.ts +5 -4
  29. package/src/blocks/data-controller/utils.ts +27 -4
  30. package/src/blocks/data-controller.ts +2 -2
  31. package/src/controls/FileControl.tsx +48 -0
  32. package/src/controls/index.ts +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileControl.js","sourceRoot":"","sources":["../../src/controls/FileControl.tsx"],"names":[],"mappings":";;AAgBA,kCA+BC;;AA/CD,0DAAsE;AACtE,sDAA+E;AAC/E,oDAAwD;AACxD,0CAAkD;AAClD,gDAA+C;AAC/C,0CAAmC;AAWnC,SAAgB,WAAW,CAAC,KAAuB;IAClD,MAAM,EAAC,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAC,GAAG,KAAK,CAAC;IAC3D,MAAM,QAAQ,GAAG,IAAA,qBAAW,EAAC,CAAC,KAAmB,EAAE,EAAE;QACpD,IAAI,KAAK,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;IACF,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAEtB,MAAM,UAAU,GAAG,IAAA,wBAAiB,EAAC,MAAM,CAAC,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7H,MAAM,EAAC,gBAAgB,EAAE,YAAY,EAAC,GAAG,IAAA,gCAAmB,EAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,CAAC;IAC5E,OAAO,uBAAC,wBAAW,OAAK,gBAAgB,YACvC,uBAAC,+BAAgB,cAChB,uBAAC,0BAAW,IACX,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,IAAA,qBAAW,EAAC,CAAC,EAAC,IAAI,EAAC,EAAE,EAAE;oBAC9B,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC;wBACrB,OAAO,mCAAS,YAAY,YAAE,uBAAC,mBAAM,IAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAA,SAAE,EAAC,eAAe,EAAE,SAAS,CAAC,GAAG,GAAM,CAAA;oBACvG,CAAC;oBACD,OAAO,oCAAS,YAAY,aAC3B,0CAAI,IAAA,SAAE,EAAC,eAAe,EAAE,SAAS,CAAC,QAAG,8BAAG,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,YAAE,UAAU,CAAC,KAAK,CAAC,QAAQ,GAAK,IAAI,EAClJ,iCAAK,SAAS,EAAC,+BAA+B,aAC7C,uBAAC,mBAAM,IAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAC,WAAW,EAAC,QAAQ,EAAC,cAAc,GAAG,EACrE,uBAAC,mBAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,QAAC,QAAQ,EAAE,IAAA,SAAE,EAAC,aAAa,EAAE,SAAS,CAAC,GAAI,IAC/F,IACD,CAAC;gBACR,CAAC,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,GACvC,GACgB,GACN,CAAC;AAChB,CAAC"}
@@ -7,6 +7,7 @@ export * from "./ExtendedTaxonomyPicker";
7
7
  export * from "./ExtendedTermPicker";
8
8
  export * from "./ExtendedTextareaControl";
9
9
  export * from "./ExtendedUserPicker";
10
+ export * from "./FileControl";
10
11
  export * from "./FullSizeToggleControl";
11
12
  export * from "./ImageControl";
12
13
  export * from "./InspectorPanel";
@@ -25,6 +25,7 @@ __exportStar(require("./ExtendedTaxonomyPicker"), exports);
25
25
  __exportStar(require("./ExtendedTermPicker"), exports);
26
26
  __exportStar(require("./ExtendedTextareaControl"), exports);
27
27
  __exportStar(require("./ExtendedUserPicker"), exports);
28
+ __exportStar(require("./FileControl"), exports);
28
29
  __exportStar(require("./FullSizeToggleControl"), exports);
29
30
  __exportStar(require("./ImageControl"), exports);
30
31
  __exportStar(require("./InspectorPanel"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/controls/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2EAAwE;AAAhE,wIAAA,0BAA0B,OAAA;AAClC,6DAA2C;AAC3C,2DAAyC;AACzC,uDAAqC;AACrC,yDAAuC;AACvC,2DAAyC;AACzC,uDAAqC;AACrC,4DAA0C;AAC1C,uDAAqC;AACrC,0DAAwC;AACxC,iDAA+B;AAC/B,mDAAiC;AACjC,mEAAiD;AACjD,uDAAqC;AACrC,4CAA0B;AAC1B,wDAAsC;AACtC,sDAAoC;AACpC,iDAA+B;AAC/B,iEAA+C;AAC/C,yDAAuC;AAEvC,mCAA+C;AAAtC,6GAAA,mBAAmB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/controls/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2EAAwE;AAAhE,wIAAA,0BAA0B,OAAA;AAClC,6DAA2C;AAC3C,2DAAyC;AACzC,uDAAqC;AACrC,yDAAuC;AACvC,2DAAyC;AACzC,uDAAqC;AACrC,4DAA0C;AAC1C,uDAAqC;AACrC,gDAA8B;AAC9B,0DAAwC;AACxC,iDAA+B;AAC/B,mDAAiC;AACjC,mEAAiD;AACjD,uDAAqC;AACrC,4CAA0B;AAC1B,wDAAsC;AACtC,sDAAoC;AACpC,iDAA+B;AAC/B,iEAA+C;AAC/C,yDAAuC;AAEvC,mCAA+C;AAAtC,6GAAA,mBAAmB,OAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plaudit/gutenberg-api-extensions",
3
- "version": "2.84.4",
3
+ "version": "2.85.1",
4
4
  "license": "SEE LICENSE IN LICENSE.md",
5
5
  "files": [
6
6
  "./dist",
@@ -24,7 +24,7 @@
24
24
  "@reduxjs/toolkit": "^2.11.2",
25
25
  "@types/react": "^18.3.28",
26
26
  "@types/wordpress__block-editor": "^15.0.0",
27
- "@types/wordpress__blocks": "^12.5.18",
27
+ "@types/wordpress__blocks": "^15.10.0",
28
28
  "@wordpress/block-editor": "^15.12.0",
29
29
  "@wordpress/blocks": "^15.12.0",
30
30
  "@wordpress/components": "^30.9.0",
@@ -36,9 +36,9 @@
36
36
  "@wordpress/hooks": "^4.39.0",
37
37
  "@wordpress/i18n": "^6.12.0",
38
38
  "@wordpress/icons": "^11.6.0",
39
- "framer-motion": "^12.33.0",
40
- "html-react-parser": "^5.2.16",
41
- "immer": "^11.1.3",
39
+ "framer-motion": "^12.34.0",
40
+ "html-react-parser": "^5.2.17",
41
+ "immer": "^11.1.4",
42
42
  "react": "^18.3.1",
43
43
  "react-dom": "^18.3.1",
44
44
  "react-error-boundary": "^6.1.0",
@@ -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
 
@@ -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` |
@@ -440,9 +454,28 @@ Color picker with theme palette integration.
440
454
 
441
455
  ---
442
456
 
443
- ### Media & Relational Controls
457
+ ## Media & Relational Controls
458
+
459
+ ### `file`
460
+ File selector with media library integration.
461
+
462
+ **Value Type:** `number` (attachment id)
463
+
464
+ **Additional Properties:**
465
+ - `allowedTypes` (string[]): An array of [File Type Specifiers](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/file#unique_file_type_specifiers) to which the field should be restricted. Default: `undefined` (allows any file).
466
+
467
+ **Example:**
468
+
469
+ ```json
470
+ {
471
+ "name": "someFile",
472
+ "label": "Some File",
473
+ "control": "file",
474
+ "allowedTypes": ["text/csv", "application/pdf"]
475
+ }
476
+ ```
444
477
 
445
- #### `image`
478
+ ### `image`
446
479
  Image selector with media library integration.
447
480
 
448
481
  **Value Type:** `object` (ImageData)
@@ -464,7 +497,7 @@ Image selector with media library integration.
464
497
 
465
498
  ---
466
499
 
467
- #### `link`
500
+ ### `link`
468
501
  Link picker for URLs, pages, posts, etc.
469
502
 
470
503
  **Value Type:** `object`
@@ -485,7 +518,7 @@ Link picker for URLs, pages, posts, etc.
485
518
 
486
519
  ---
487
520
 
488
- #### `post`
521
+ ### `post`
489
522
  Post/page selector with search functionality.
490
523
 
491
524
  **Value Type:** `number` (single) or `number[]` (multiple)
@@ -523,7 +556,7 @@ Post/page selector with search functionality.
523
556
 
524
557
  ---
525
558
 
526
- #### `taxonomy`
559
+ ### `taxonomy`
527
560
  Taxonomy selector (categories, tags, custom taxonomies).
528
561
 
529
562
  **Value Type:** `string` (single) or `string[]` (multiple)
@@ -550,7 +583,7 @@ Taxonomy selector (categories, tags, custom taxonomies).
550
583
 
551
584
  ---
552
585
 
553
- #### `term`
586
+ ### `term`
554
587
  Taxonomy term selector (specific category/tag picker).
555
588
 
556
589
  **Value Type:** `string` (single) or `string[]` (multiple)
@@ -574,7 +607,7 @@ Taxonomy term selector (specific category/tag picker).
574
607
 
575
608
  ---
576
609
 
577
- #### `user`
610
+ ### `user`
578
611
  User selector with role filtering.
579
612
 
580
613
  **Value Type:** `number` (single) or `number[]` (multiple)
@@ -610,9 +643,9 @@ User selector with role filtering.
610
643
 
611
644
  ---
612
645
 
613
- ### Structure & Collection Controls
646
+ ## Structure & Collection Controls
614
647
 
615
- #### `group`
648
+ ### `group`
616
649
  Groups related controls together visually.
617
650
 
618
651
  **Value Type:** `object`
@@ -652,7 +685,7 @@ Groups related controls together visually.
652
685
 
653
686
  ---
654
687
 
655
- #### `list`
688
+ ### `list`
656
689
  Repeatable list of items (simple strings/numbers or complex objects).
657
690
 
658
691
  **Value Type:** `array`
@@ -741,7 +774,7 @@ Repeatable list of items (simple strings/numbers or complex objects).
741
774
 
742
775
  ---
743
776
 
744
- #### `date`
777
+ ### `date`
745
778
  Date and optional time picker.
746
779
 
747
780
  **Value Type:** `number` (Unix timestamp in milliseconds)
@@ -762,7 +795,7 @@ Date and optional time picker.
762
795
 
763
796
  ---
764
797
 
765
- #### `constant`
798
+ ### `constant`
766
799
  Hidden field with a constant value (not editable by users).
767
800
 
768
801
  **Value Type:** Depends on `type` property
@@ -785,9 +818,9 @@ Hidden field with a constant value (not editable by users).
785
818
 
786
819
  ---
787
820
 
788
- ## 🏗️ Organization & Logic
821
+ # 🏗️ Organization & Logic
789
822
 
790
- ### 1. Structure (Panels & Tabs)
823
+ ## 1. Structure (Panels & Tabs)
791
824
 
792
825
  Wrap your controls in **Panels** to create collapsible sections in the sidebar.
793
826
 
@@ -849,7 +882,7 @@ You can also organize panels into tabs:
849
882
 
850
883
  ---
851
884
 
852
- ### 2. Layout (Rows)
885
+ ## 2. Layout (Rows)
853
886
 
854
887
  - **Single Control:** One control object per row.
855
888
  - **Multiple Controls:** Wrap controls in an array to display them side-by-side.
@@ -865,7 +898,7 @@ You can also organize panels into tabs:
865
898
 
866
899
  ---
867
900
 
868
- ### 3. Conditions (Show/Hide Logic)
901
+ ## 3. Conditions (Show/Hide Logic)
869
902
 
870
903
  Add a `condition` array to any control or panel to show/hide it based on other property values.
871
904
 
@@ -946,14 +979,14 @@ Add a `condition` array to any control or panel to show/hide it based on other p
946
979
 
947
980
  ---
948
981
 
949
- ### 4. Option Sources (Dynamic Options)
982
+ ## 4. Option Sources (Dynamic Options)
950
983
 
951
984
  For `select`, `radio`, `colorPalette`, and `toggleGroup` controls, you can use shorthand strings to load dynamic options:
952
985
 
953
- #### Source Syntax
986
+ ### Source Syntax
954
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.
955
988
 
956
- ##### The `select` Protocol
989
+ #### The `select` Protocol
957
990
  **Notes:**
958
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.
959
992
  - At present, that means using the `plaudit/simple-gutenberg-apis` store.
@@ -964,7 +997,7 @@ For `select`, `radio`, `colorPalette`, and `toggleGroup` controls, you can use s
964
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
965
998
 
966
999
 
967
- ##### The `settings` Protocol
1000
+ #### The `settings` Protocol
968
1001
  **Notes:**
969
1002
  - This protocol is used to get values from the theme.json file
970
1003
  - The returned values are effected by the current block (this is to allow for block-specific values, most-commonly font sizes and colors)
@@ -997,9 +1030,9 @@ For `select`, `radio`, `colorPalette`, and `toggleGroup` controls, you can use s
997
1030
 
998
1031
  ---
999
1032
 
1000
- ## 🔧 Advanced Features
1033
+ # 🔧 Advanced Features
1001
1034
 
1002
- ### Style Properties
1035
+ ## Style Properties
1003
1036
 
1004
1037
  This feature is intended for setting CSS custom variables based on a block's properties.
1005
1038
 
@@ -1028,7 +1061,7 @@ When the user enters `"20px 40px"`, the block wrapper will receive:
1028
1061
 
1029
1062
  ---
1030
1063
 
1031
- ### Validators & Transformers
1064
+ ## Validators & Transformers
1032
1065
 
1033
1066
  **Note:** These features are only available when using TypeScript/React to define properties programmatically.
1034
1067
 
@@ -1070,7 +1103,7 @@ When the user enters `"20px 40px"`, the block wrapper will receive:
1070
1103
 
1071
1104
  ---
1072
1105
 
1073
- ## Tips & Best Practices
1106
+ # Tips & Best Practices
1074
1107
 
1075
1108
  1. **Add Help Text:** Use the `help` property to guide users, especially for complex controls.
1076
1109
 
@@ -20,7 +20,7 @@ import {
20
20
  ExtendedPostPicker, ExtendedRadioControl, ImageControl, type ImageData,
21
21
  ExtendedTextareaControl, MultiSelectControl, type Dict,
22
22
  ProperLinkControl, SortableItemsControl, type PickableOptions,
23
- FullSizeToggleControl, ToggleGroupControlOptionWithOptionalIcon, ExtendedTaxonomyPicker, ExtendedTermPicker, ExtendedUserPicker
23
+ FullSizeToggleControl, ToggleGroupControlOptionWithOptionalIcon, ExtendedTaxonomyPicker, ExtendedTermPicker, ExtendedUserPicker, FileControl
24
24
  } from "../controls";
25
25
  import {normalizePickableOptionsToObjects, normalizePickableOptionsToPairs} from "../controls/shared";
26
26
  import {recordCloneableDefaultValueForNode} from "./data-controller/utils";
@@ -181,6 +181,18 @@ function hydrateDesiccatedSimpleNativeProperty(
181
181
  </BaseControl>;
182
182
  }
183
183
  }
184
+ case "file":
185
+ return {
186
+ type: 'number',
187
+ alwaysStore: config.alwaysStore,
188
+ default: config.default,
189
+ ...passthroughProps,
190
+ validator: config.validator,
191
+ transformer: config.transformer,
192
+ control({value, onChange, slots: {Label}}) {
193
+ return <FileControl label={<Label />} help={config.help} onChange={onChange} value={value} allowedTypes={config.allowedTypes} />;
194
+ }
195
+ };
184
196
  case "group":
185
197
  registerPlainTextLabelRequiredMarker("post", " > .components-tools-panel > .components-tools-panel-header > *");
186
198
  const currentTypes = parentTypes.toSpliced(parentTypes.length - 1, 0, 'object');
@@ -12,9 +12,9 @@ import type {
12
12
  __experimentalToolsPanel as ToolsPanel
13
13
  } from "@wordpress/components";
14
14
 
15
- import type {
15
+ import {
16
16
  ExtendedPostPickerProps, ExtendedTaxonomyPickerProps, ExtendedTaxonomyPickerPropsMultiple, ExtendedTaxonomyPickerPropsSingle,
17
- ExtendedTermPickerProps, ExtendedTermPickerPropsMultiple, ExtendedTermPickerPropsSingle, ExtendedUserPickerProps,
17
+ ExtendedTermPickerProps, ExtendedTermPickerPropsMultiple, ExtendedTermPickerPropsSingle, ExtendedUserPickerProps, FileControl, FileControlProps,
18
18
  FlexibleItem, ImageControl, PickableOptions, ProperLinkControlProps, SortableItemsControlProps, TextareaControlPropsExtension
19
19
  } from "../controls";
20
20
  import type {IconName} from "./shared-exportable-types";
@@ -52,6 +52,8 @@ export type ConstantPropertyCSNPConfig = Omit<BaseConstantPropertyCSNPConfig, 'd
52
52
  export type DatePropertyCSNPConfig = CommonSimpleNativePropertyWithEnum<'date', number, ComponentPropsWithoutRef<typeof DateTimePicker>, 'number', {time: true}>
53
53
  |CommonSimpleNativePropertyWithEnum<'date', number, ComponentPropsWithoutRef<typeof DatePicker>, 'number', {time?: false|undefined}>;
54
54
 
55
+ export type FilePropertyCSNPConfig = CommonSimpleNativeProperty<'file', number, Omit<ComponentPropsWithoutRef<typeof FileControl>, 'allowedTypes'>, 'number', Pick<FileControlProps, 'allowedTypes'>>;
56
+
55
57
  type NormalGroupPropertyCSNPConfig = CommonPropertyConfig<'group', Record<string, unknown>, HTMLAttributes<HTMLFieldSetElement>, 'object'>&{
56
58
  fields?: PDSimpleNativeProperty[],
57
59
  interface?: 'default'
@@ -137,14 +139,14 @@ type UserPropertyTypeSingle = CommonPropertyConfig<'user', number, ExtendedUserP
137
139
  type UserPropertyTypeMultiple = CommonPropertyConfig<'user', number[], ExtendedUserPickerProps, 'array'>&{userRoles?: string[], multiple: true};
138
140
  export type UserPropertyCSNPConfig = UserPropertyTypeSingle|UserPropertyTypeMultiple;
139
141
 
140
- export type CSNPConfig = ColorPaletteCSNPConfig|ConstantPropertyCSNPConfig|DatePropertyCSNPConfig|GroupPropertyCSNPConfig|ImagePropertyCSNPConfig
141
- |LinkPropertyCSNPConfig|ListPropertyCSNPConfig|NumberPropertyCSNPConfig|PostPropertyCSNPConfig|RadioPropertyCSNPConfig|RangePropertyCSNPConfig
142
- |SelectPropertyCSNPConfig|TaxonomyPropertyCSNPConfig|TermPropertyCSNPConfig|TextareaPropertyCSNPConfig|TextPropertyCSNPConfig|ToggleGroupPropertyCSNPConfig
143
- |TogglePropertyCSNPConfig|UserPropertyCSNPConfig;
142
+ export type CSNPConfig = ColorPaletteCSNPConfig|ConstantPropertyCSNPConfig|DatePropertyCSNPConfig|FilePropertyCSNPConfig|GroupPropertyCSNPConfig
143
+ |ImagePropertyCSNPConfig|LinkPropertyCSNPConfig|ListPropertyCSNPConfig|NumberPropertyCSNPConfig|PostPropertyCSNPConfig|RadioPropertyCSNPConfig
144
+ |RangePropertyCSNPConfig|SelectPropertyCSNPConfig|TaxonomyPropertyCSNPConfig|TermPropertyCSNPConfig|TextareaPropertyCSNPConfig|TextPropertyCSNPConfig
145
+ |ToggleGroupPropertyCSNPConfig|TogglePropertyCSNPConfig|UserPropertyCSNPConfig;
144
146
 
145
147
  export const CSNPControlNames = [
146
- 'colorPalette', 'constant', 'date', 'group', 'image', 'link', 'list', 'number', 'post', 'radio', 'range', 'select', 'taxonomy', 'term', 'text', 'textarea',
147
- 'toggle', 'toggleGroup', 'user'
148
+ 'colorPalette', 'constant', 'date', 'file', 'group', 'image', 'link', 'list', 'number', 'post', 'radio', 'range', 'select', 'taxonomy', 'term', 'text',
149
+ 'textarea', 'toggle', 'toggleGroup', 'user'
148
150
  ] as const;
149
151
 
150
152
  export function getPropType(config: PDSimpleNativeProperty): SimpleNativePropertyType {
@@ -155,6 +157,7 @@ export function getPropType(config: PDSimpleNativeProperty): SimpleNativePropert
155
157
  case "constant":
156
158
  return config.type;
157
159
  case "date":
160
+ case "file":
158
161
  return 'number';
159
162
  case "group":
160
163
  case "image":
@@ -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
  }