@wordpress/dataviews 9.0.1-next.6f42e1382.0 → 9.0.1-next.a730c9c8c.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 +7 -1
- package/README.md +106 -11
- package/build/components/dataviews-filters/input-widget.js +48 -4
- package/build/components/dataviews-filters/input-widget.js.map +1 -1
- package/build/dataform-controls/array.js +9 -7
- package/build/dataform-controls/array.js.map +1 -1
- package/build/dataform-controls/checkbox.js +31 -20
- package/build/dataform-controls/checkbox.js.map +1 -1
- package/build/dataform-controls/color.js +29 -24
- package/build/dataform-controls/color.js.map +1 -1
- package/build/dataform-controls/date.js +32 -24
- package/build/dataform-controls/date.js.map +1 -1
- package/build/dataform-controls/datetime.js +133 -19
- package/build/dataform-controls/datetime.js.map +1 -1
- package/build/dataform-controls/email.js +7 -1
- package/build/dataform-controls/email.js.map +1 -1
- package/build/dataform-controls/index.js +23 -0
- package/build/dataform-controls/index.js.map +1 -1
- package/build/dataform-controls/integer.js +47 -34
- package/build/dataform-controls/integer.js.map +1 -1
- package/build/dataform-controls/radio.js +42 -9
- package/build/dataform-controls/radio.js.map +1 -1
- package/build/dataform-controls/relative-date-control.js +6 -10
- package/build/dataform-controls/relative-date-control.js.map +1 -1
- package/build/dataform-controls/select.js +41 -10
- package/build/dataform-controls/select.js.map +1 -1
- package/build/dataform-controls/telephone.js +7 -1
- package/build/dataform-controls/telephone.js.map +1 -1
- package/build/dataform-controls/text.js +14 -2
- package/build/dataform-controls/text.js.map +1 -1
- package/build/dataform-controls/textarea.js +33 -20
- package/build/dataform-controls/textarea.js.map +1 -1
- package/build/dataform-controls/toggle-group.js +36 -6
- package/build/dataform-controls/toggle-group.js.map +1 -1
- package/build/dataform-controls/toggle.js +33 -22
- package/build/dataform-controls/toggle.js.map +1 -1
- package/build/dataform-controls/url.js +7 -1
- package/build/dataform-controls/url.js.map +1 -1
- package/build/dataform-controls/utils/validated-input.js +34 -32
- package/build/dataform-controls/utils/validated-input.js.map +1 -1
- package/build/dataforms-layouts/panel/dropdown.js +10 -14
- package/build/dataforms-layouts/panel/dropdown.js.map +1 -1
- package/build/dataforms-layouts/panel/index.js +24 -11
- package/build/dataforms-layouts/panel/index.js.map +1 -1
- package/build/dataforms-layouts/panel/modal.js +22 -27
- package/build/dataforms-layouts/panel/modal.js.map +1 -1
- package/build/dataforms-layouts/panel/summary-button.js +67 -0
- package/build/dataforms-layouts/panel/summary-button.js.map +1 -0
- package/build/normalize-fields.js +17 -0
- package/build/normalize-fields.js.map +1 -1
- package/build/types.js.map +1 -1
- package/build-module/components/dataviews-filters/input-widget.js +48 -4
- package/build-module/components/dataviews-filters/input-widget.js.map +1 -1
- package/build-module/dataform-controls/array.js +9 -7
- package/build-module/dataform-controls/array.js.map +1 -1
- package/build-module/dataform-controls/checkbox.js +31 -21
- package/build-module/dataform-controls/checkbox.js.map +1 -1
- package/build-module/dataform-controls/color.js +28 -24
- package/build-module/dataform-controls/color.js.map +1 -1
- package/build-module/dataform-controls/date.js +32 -24
- package/build-module/dataform-controls/date.js.map +1 -1
- package/build-module/dataform-controls/datetime.js +135 -21
- package/build-module/dataform-controls/datetime.js.map +1 -1
- package/build-module/dataform-controls/email.js +7 -1
- package/build-module/dataform-controls/email.js.map +1 -1
- package/build-module/dataform-controls/index.js +23 -0
- package/build-module/dataform-controls/index.js.map +1 -1
- package/build-module/dataform-controls/integer.js +46 -34
- package/build-module/dataform-controls/integer.js.map +1 -1
- package/build-module/dataform-controls/radio.js +44 -11
- package/build-module/dataform-controls/radio.js.map +1 -1
- package/build-module/dataform-controls/relative-date-control.js +6 -10
- package/build-module/dataform-controls/relative-date-control.js.map +1 -1
- package/build-module/dataform-controls/select.js +43 -12
- package/build-module/dataform-controls/select.js.map +1 -1
- package/build-module/dataform-controls/telephone.js +7 -1
- package/build-module/dataform-controls/telephone.js.map +1 -1
- package/build-module/dataform-controls/text.js +14 -2
- package/build-module/dataform-controls/text.js.map +1 -1
- package/build-module/dataform-controls/textarea.js +32 -20
- package/build-module/dataform-controls/textarea.js.map +1 -1
- package/build-module/dataform-controls/toggle-group.js +38 -8
- package/build-module/dataform-controls/toggle-group.js.map +1 -1
- package/build-module/dataform-controls/toggle.js +33 -23
- package/build-module/dataform-controls/toggle.js.map +1 -1
- package/build-module/dataform-controls/url.js +7 -1
- package/build-module/dataform-controls/url.js.map +1 -1
- package/build-module/dataform-controls/utils/validated-input.js +34 -33
- package/build-module/dataform-controls/utils/validated-input.js.map +1 -1
- package/build-module/dataforms-layouts/panel/dropdown.js +10 -15
- package/build-module/dataforms-layouts/panel/dropdown.js.map +1 -1
- package/build-module/dataforms-layouts/panel/index.js +24 -11
- package/build-module/dataforms-layouts/panel/index.js.map +1 -1
- package/build-module/dataforms-layouts/panel/modal.js +22 -28
- package/build-module/dataforms-layouts/panel/modal.js.map +1 -1
- package/build-module/dataforms-layouts/panel/summary-button.js +60 -0
- package/build-module/dataforms-layouts/panel/summary-button.js.map +1 -0
- package/build-module/normalize-fields.js +15 -0
- package/build-module/normalize-fields.js.map +1 -1
- package/build-module/types.js.map +1 -1
- package/build-types/components/dataform/stories/index.story.d.ts +3 -0
- package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
- package/build-types/components/dataviews/stories/fixtures.d.ts +4 -2
- package/build-types/components/dataviews/stories/fixtures.d.ts.map +1 -1
- package/build-types/components/dataviews-filters/input-widget.d.ts.map +1 -1
- package/build-types/dataform-controls/array.d.ts.map +1 -1
- package/build-types/dataform-controls/checkbox.d.ts.map +1 -1
- package/build-types/dataform-controls/color.d.ts.map +1 -1
- package/build-types/dataform-controls/date.d.ts.map +1 -1
- package/build-types/dataform-controls/datetime.d.ts.map +1 -1
- package/build-types/dataform-controls/email.d.ts.map +1 -1
- package/build-types/dataform-controls/index.d.ts +1 -1
- package/build-types/dataform-controls/index.d.ts.map +1 -1
- package/build-types/dataform-controls/integer.d.ts.map +1 -1
- package/build-types/dataform-controls/radio.d.ts.map +1 -1
- package/build-types/dataform-controls/relative-date-control.d.ts +6 -5
- package/build-types/dataform-controls/relative-date-control.d.ts.map +1 -1
- package/build-types/dataform-controls/select.d.ts.map +1 -1
- package/build-types/dataform-controls/telephone.d.ts.map +1 -1
- package/build-types/dataform-controls/text.d.ts +1 -1
- package/build-types/dataform-controls/text.d.ts.map +1 -1
- package/build-types/dataform-controls/textarea.d.ts +1 -1
- package/build-types/dataform-controls/textarea.d.ts.map +1 -1
- package/build-types/dataform-controls/toggle-group.d.ts.map +1 -1
- package/build-types/dataform-controls/toggle.d.ts.map +1 -1
- package/build-types/dataform-controls/url.d.ts.map +1 -1
- package/build-types/dataform-controls/utils/validated-input.d.ts +4 -4
- package/build-types/dataform-controls/utils/validated-input.d.ts.map +1 -1
- package/build-types/dataforms-layouts/panel/dropdown.d.ts +2 -1
- package/build-types/dataforms-layouts/panel/dropdown.d.ts.map +1 -1
- package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
- package/build-types/dataforms-layouts/panel/modal.d.ts +2 -1
- package/build-types/dataforms-layouts/panel/modal.d.ts.map +1 -1
- package/build-types/dataforms-layouts/panel/summary-button.d.ts +15 -0
- package/build-types/dataforms-layouts/panel/summary-button.d.ts.map +1 -0
- package/build-types/field-types/stories/index.story.d.ts.map +1 -1
- package/build-types/normalize-fields.d.ts +3 -0
- package/build-types/normalize-fields.d.ts.map +1 -1
- package/build-types/types.d.ts +66 -3
- package/build-types/types.d.ts.map +1 -1
- package/build-wp/index.js +1468 -1422
- package/package.json +16 -15
- package/src/components/dataform/stories/index.story.tsx +436 -7
- package/src/components/dataviews/stories/fixtures.tsx +99 -41
- package/src/components/dataviews/stories/index.story.tsx +1 -1
- package/src/components/dataviews-filters/input-widget.tsx +44 -5
- package/src/components/dataviews-picker/stories/index.story.tsx +1 -1
- package/src/dataform-controls/array.tsx +4 -6
- package/src/dataform-controls/checkbox.tsx +41 -24
- package/src/dataform-controls/color.tsx +33 -24
- package/src/dataform-controls/date.tsx +47 -21
- package/src/dataform-controls/datetime.tsx +171 -23
- package/src/dataform-controls/email.tsx +9 -1
- package/src/dataform-controls/index.tsx +26 -0
- package/src/dataform-controls/integer.tsx +82 -49
- package/src/dataform-controls/radio.tsx +53 -11
- package/src/dataform-controls/relative-date-control.tsx +11 -10
- package/src/dataform-controls/select.tsx +53 -10
- package/src/dataform-controls/telephone.tsx +9 -1
- package/src/dataform-controls/text.tsx +18 -1
- package/src/dataform-controls/textarea.tsx +38 -24
- package/src/dataform-controls/toggle-group.tsx +50 -10
- package/src/dataform-controls/toggle.tsx +41 -24
- package/src/dataform-controls/url.tsx +9 -1
- package/src/dataform-controls/utils/validated-input.tsx +50 -50
- package/src/dataforms-layouts/panel/dropdown.tsx +12 -23
- package/src/dataforms-layouts/panel/index.tsx +39 -16
- package/src/dataforms-layouts/panel/modal.tsx +24 -30
- package/src/dataforms-layouts/panel/summary-button.tsx +92 -0
- package/src/field-types/stories/index.story.tsx +89 -1
- package/src/normalize-fields.ts +18 -0
- package/src/test/filter-and-sort-data-view.js +148 -138
- package/src/test/normalize-fields.ts +114 -0
- package/src/types.ts +73 -3
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/dataviews",
|
|
3
|
-
"version": "9.0.1-next.
|
|
3
|
+
"version": "9.0.1-next.a730c9c8c.0",
|
|
4
4
|
"description": "DataViews is a component that provides an API to render datasets using different types of layouts (table, grid, list, etc.).",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -46,22 +46,23 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@ariakit/react": "^0.4.15",
|
|
48
48
|
"@babel/runtime": "7.25.7",
|
|
49
|
-
"@wordpress/base-styles": "^6.6.1-next.
|
|
50
|
-
"@wordpress/components": "^30.3.2-next.
|
|
51
|
-
"@wordpress/compose": "^7.30.1-next.
|
|
52
|
-
"@wordpress/data": "^10.30.1-next.
|
|
53
|
-
"@wordpress/date": "^5.30.1-next.
|
|
54
|
-
"@wordpress/element": "^6.30.1-next.
|
|
55
|
-
"@wordpress/i18n": "^6.3.1-next.
|
|
56
|
-
"@wordpress/icons": "^10.30.1-next.
|
|
57
|
-
"@wordpress/keycodes": "^4.30.1-next.
|
|
58
|
-
"@wordpress/primitives": "^4.30.1-next.
|
|
59
|
-
"@wordpress/private-apis": "^1.30.1-next.
|
|
60
|
-
"@wordpress/url": "^4.30.1-next.
|
|
61
|
-
"@wordpress/warning": "^3.30.1-next.
|
|
49
|
+
"@wordpress/base-styles": "^6.6.1-next.a730c9c8c.0",
|
|
50
|
+
"@wordpress/components": "^30.3.2-next.a730c9c8c.0",
|
|
51
|
+
"@wordpress/compose": "^7.30.1-next.a730c9c8c.0",
|
|
52
|
+
"@wordpress/data": "^10.30.1-next.a730c9c8c.0",
|
|
53
|
+
"@wordpress/date": "^5.30.1-next.a730c9c8c.0",
|
|
54
|
+
"@wordpress/element": "^6.30.1-next.a730c9c8c.0",
|
|
55
|
+
"@wordpress/i18n": "^6.3.1-next.a730c9c8c.0",
|
|
56
|
+
"@wordpress/icons": "^10.30.1-next.a730c9c8c.0",
|
|
57
|
+
"@wordpress/keycodes": "^4.30.1-next.a730c9c8c.0",
|
|
58
|
+
"@wordpress/primitives": "^4.30.1-next.a730c9c8c.0",
|
|
59
|
+
"@wordpress/private-apis": "^1.30.1-next.a730c9c8c.0",
|
|
60
|
+
"@wordpress/url": "^4.30.1-next.a730c9c8c.0",
|
|
61
|
+
"@wordpress/warning": "^3.30.1-next.a730c9c8c.0",
|
|
62
62
|
"clsx": "^2.1.1",
|
|
63
63
|
"colord": "^2.7.0",
|
|
64
64
|
"date-fns": "^4.1.0",
|
|
65
|
+
"deepmerge": "4.3.1",
|
|
65
66
|
"fast-deep-equal": "^3.1.3",
|
|
66
67
|
"remove-accents": "^0.5.0"
|
|
67
68
|
},
|
|
@@ -75,5 +76,5 @@
|
|
|
75
76
|
"scripts": {
|
|
76
77
|
"build:wp": "node build"
|
|
77
78
|
},
|
|
78
|
-
"gitHead": "
|
|
79
|
+
"gitHead": "85a580bd2c55f811c8969b42dbb10209d19d514e"
|
|
79
80
|
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import deepMerge from 'deepmerge';
|
|
5
|
+
|
|
1
6
|
/**
|
|
2
7
|
* WordPress dependencies
|
|
3
8
|
*/
|
|
@@ -41,6 +46,14 @@ type SamplePost = {
|
|
|
41
46
|
address1?: string;
|
|
42
47
|
address2?: string;
|
|
43
48
|
city?: string;
|
|
49
|
+
comment_status?: string;
|
|
50
|
+
ping_status?: boolean;
|
|
51
|
+
longDescription?: string;
|
|
52
|
+
origin?: string;
|
|
53
|
+
destination?: string;
|
|
54
|
+
flight_status?: string;
|
|
55
|
+
gate?: string;
|
|
56
|
+
seat?: string;
|
|
44
57
|
};
|
|
45
58
|
|
|
46
59
|
const fields: Field< SamplePost >[] = [
|
|
@@ -79,6 +92,9 @@ const fields: Field< SamplePost >[] = [
|
|
|
79
92
|
{ value: 3, label: 'Alice' },
|
|
80
93
|
{ value: 4, label: 'Bob' },
|
|
81
94
|
],
|
|
95
|
+
setValue: ( { value } ) => ( {
|
|
96
|
+
author: Number( value ),
|
|
97
|
+
} ),
|
|
82
98
|
},
|
|
83
99
|
{
|
|
84
100
|
id: 'reviewer',
|
|
@@ -174,6 +190,80 @@ const fields: Field< SamplePost >[] = [
|
|
|
174
190
|
type: 'text',
|
|
175
191
|
Edit: 'textarea',
|
|
176
192
|
},
|
|
193
|
+
{
|
|
194
|
+
id: 'longDescription',
|
|
195
|
+
label: 'Long Description',
|
|
196
|
+
type: 'text',
|
|
197
|
+
Edit: {
|
|
198
|
+
control: 'textarea',
|
|
199
|
+
rows: 5,
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
id: 'comment_status',
|
|
204
|
+
label: 'Comment Status',
|
|
205
|
+
type: 'text',
|
|
206
|
+
Edit: 'radio',
|
|
207
|
+
elements: [
|
|
208
|
+
{ value: 'open', label: 'Allow comments' },
|
|
209
|
+
{ value: 'closed', label: 'Comments closed' },
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: 'ping_status',
|
|
214
|
+
label: 'Allow Pings/Trackbacks',
|
|
215
|
+
type: 'boolean',
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
id: 'discussion',
|
|
219
|
+
label: 'Discussion',
|
|
220
|
+
type: 'text',
|
|
221
|
+
render: ( { item } ) => {
|
|
222
|
+
const commentLabel =
|
|
223
|
+
item.comment_status === 'open'
|
|
224
|
+
? 'Allow comments'
|
|
225
|
+
: 'Comments closed';
|
|
226
|
+
const pingLabel = item.ping_status
|
|
227
|
+
? 'Pings enabled'
|
|
228
|
+
: 'Pings disabled';
|
|
229
|
+
return (
|
|
230
|
+
<span>
|
|
231
|
+
{ commentLabel }, { pingLabel }
|
|
232
|
+
</span>
|
|
233
|
+
);
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
id: 'origin',
|
|
238
|
+
label: 'Origin',
|
|
239
|
+
type: 'text',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: 'destination',
|
|
243
|
+
label: 'Destination',
|
|
244
|
+
type: 'text',
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: 'flight_status',
|
|
248
|
+
label: 'Flight Status',
|
|
249
|
+
type: 'text',
|
|
250
|
+
Edit: 'radio',
|
|
251
|
+
elements: [
|
|
252
|
+
{ value: 'on-time', label: 'On Time' },
|
|
253
|
+
{ value: 'delayed', label: 'Delayed' },
|
|
254
|
+
{ value: 'cancelled', label: 'Cancelled' },
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
id: 'gate',
|
|
259
|
+
label: 'Gate',
|
|
260
|
+
type: 'text',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: 'seat',
|
|
264
|
+
label: 'Seat',
|
|
265
|
+
type: 'text',
|
|
266
|
+
},
|
|
177
267
|
];
|
|
178
268
|
|
|
179
269
|
const LayoutRegularComponent = ( {
|
|
@@ -220,6 +310,7 @@ const LayoutRegularComponent = ( {
|
|
|
220
310
|
'dimensions',
|
|
221
311
|
'tags',
|
|
222
312
|
'description',
|
|
313
|
+
'longDescription',
|
|
223
314
|
],
|
|
224
315
|
} ),
|
|
225
316
|
[ labelPosition ]
|
|
@@ -308,6 +399,13 @@ const LayoutPanelComponent = ( {
|
|
|
308
399
|
address1: '123 Main St',
|
|
309
400
|
address2: 'Apt 4B',
|
|
310
401
|
city: 'New York',
|
|
402
|
+
comment_status: 'open',
|
|
403
|
+
ping_status: true,
|
|
404
|
+
origin: 'New York (JFK)',
|
|
405
|
+
destination: 'Los Angeles (LAX)',
|
|
406
|
+
flight_status: 'on-time',
|
|
407
|
+
gate: 'A12',
|
|
408
|
+
seat: '14F',
|
|
311
409
|
} );
|
|
312
410
|
|
|
313
411
|
const form: Form = useMemo( () => {
|
|
@@ -329,11 +427,34 @@ const LayoutPanelComponent = ( {
|
|
|
329
427
|
'filesize',
|
|
330
428
|
'dimensions',
|
|
331
429
|
'tags',
|
|
430
|
+
{
|
|
431
|
+
id: 'discussion',
|
|
432
|
+
label: 'Discussion',
|
|
433
|
+
children: [ 'comment_status', 'ping_status' ],
|
|
434
|
+
summary: 'discussion',
|
|
435
|
+
},
|
|
332
436
|
{
|
|
333
437
|
id: 'address1',
|
|
334
438
|
label: 'Combined Address',
|
|
335
439
|
children: [ 'address1', 'address2', 'city' ],
|
|
336
440
|
},
|
|
441
|
+
{
|
|
442
|
+
id: 'flight_info',
|
|
443
|
+
label: 'Flight Information',
|
|
444
|
+
children: [
|
|
445
|
+
'origin',
|
|
446
|
+
'destination',
|
|
447
|
+
'flight_status',
|
|
448
|
+
'gate',
|
|
449
|
+
],
|
|
450
|
+
summary: [ 'origin', 'destination', 'flight_status' ],
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
id: 'passenger_details',
|
|
454
|
+
label: 'Passenger Details',
|
|
455
|
+
children: [ 'author', 'seat' ],
|
|
456
|
+
summary: [ 'author', 'seat' ],
|
|
457
|
+
},
|
|
337
458
|
],
|
|
338
459
|
};
|
|
339
460
|
}, [ labelPosition, openAs ] );
|
|
@@ -359,15 +480,13 @@ function CustomEditControl< Item >( {
|
|
|
359
480
|
onChange,
|
|
360
481
|
hideLabelFromVision,
|
|
361
482
|
}: DataFormControlProps< Item > ) {
|
|
362
|
-
const {
|
|
363
|
-
const value =
|
|
483
|
+
const { label, placeholder, description, getValue, setValue } = field;
|
|
484
|
+
const value = getValue( { item: data } );
|
|
364
485
|
|
|
365
486
|
const onChangeControl = useCallback(
|
|
366
487
|
( newValue: string ) =>
|
|
367
|
-
onChange( {
|
|
368
|
-
|
|
369
|
-
} ),
|
|
370
|
-
[ id, onChange ]
|
|
488
|
+
onChange( setValue( { item: data, value: newValue } ) ),
|
|
489
|
+
[ data, onChange, setValue ]
|
|
371
490
|
);
|
|
372
491
|
|
|
373
492
|
return (
|
|
@@ -396,6 +515,8 @@ const ValidationComponent = ( {
|
|
|
396
515
|
} ) => {
|
|
397
516
|
type ValidatedItem = {
|
|
398
517
|
text: string;
|
|
518
|
+
select?: string;
|
|
519
|
+
textWithRadio?: string;
|
|
399
520
|
textarea: string;
|
|
400
521
|
email: string;
|
|
401
522
|
telephone: string;
|
|
@@ -405,10 +526,14 @@ const ValidationComponent = ( {
|
|
|
405
526
|
boolean: boolean;
|
|
406
527
|
customEdit: string;
|
|
407
528
|
password: string;
|
|
529
|
+
toggle?: boolean;
|
|
530
|
+
toggleGroup?: string;
|
|
408
531
|
};
|
|
409
532
|
|
|
410
533
|
const [ post, setPost ] = useState< ValidatedItem >( {
|
|
411
534
|
text: 'Can have letters and spaces',
|
|
535
|
+
select: undefined,
|
|
536
|
+
textWithRadio: undefined,
|
|
412
537
|
textarea: 'Can have letters and spaces',
|
|
413
538
|
email: 'hi@example.com',
|
|
414
539
|
telephone: '+306978241796',
|
|
@@ -418,6 +543,8 @@ const ValidationComponent = ( {
|
|
|
418
543
|
boolean: true,
|
|
419
544
|
customEdit: 'custom control',
|
|
420
545
|
password: 'secretpassword123',
|
|
546
|
+
toggle: undefined,
|
|
547
|
+
toggleGroup: undefined,
|
|
421
548
|
} );
|
|
422
549
|
|
|
423
550
|
const customTextRule = ( value: ValidatedItem ) => {
|
|
@@ -427,6 +554,22 @@ const ValidationComponent = ( {
|
|
|
427
554
|
|
|
428
555
|
return null;
|
|
429
556
|
};
|
|
557
|
+
|
|
558
|
+
const customSelectRule = ( value: ValidatedItem ) => {
|
|
559
|
+
if ( value.select !== 'option1' ) {
|
|
560
|
+
return 'Value must be Option 1.';
|
|
561
|
+
}
|
|
562
|
+
return null;
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
const customTextRadioRule = ( value: ValidatedItem ) => {
|
|
566
|
+
if ( value.textWithRadio !== 'item1' ) {
|
|
567
|
+
return 'Value must be Item 1.';
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return null;
|
|
571
|
+
};
|
|
572
|
+
|
|
430
573
|
const customTextareaRule = ( value: ValidatedItem ) => {
|
|
431
574
|
if ( ! /^[a-zA-Z ]+$/.test( value.textarea ) ) {
|
|
432
575
|
return 'Value must only contain letters and spaces.';
|
|
@@ -469,6 +612,27 @@ const ValidationComponent = ( {
|
|
|
469
612
|
|
|
470
613
|
return null;
|
|
471
614
|
};
|
|
615
|
+
const customBooleanRule = ( value: ValidatedItem ) => {
|
|
616
|
+
if ( value.boolean !== true ) {
|
|
617
|
+
return 'Boolean must be active.';
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
return null;
|
|
621
|
+
};
|
|
622
|
+
const customToggleRule = ( value: ValidatedItem ) => {
|
|
623
|
+
if ( value.toggle !== true ) {
|
|
624
|
+
return 'Toggle must be checked.';
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
return null;
|
|
628
|
+
};
|
|
629
|
+
const customToggleGroupRule = ( value: ValidatedItem ) => {
|
|
630
|
+
if ( value.toggleGroup !== 'option1' ) {
|
|
631
|
+
return 'Value must be Option 1.';
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return null;
|
|
635
|
+
};
|
|
472
636
|
|
|
473
637
|
const customPasswordRule = ( value: ValidatedItem ) => {
|
|
474
638
|
if ( value.password.length < 8 ) {
|
|
@@ -500,6 +664,33 @@ const ValidationComponent = ( {
|
|
|
500
664
|
custom: maybeCustomRule( customTextRule ),
|
|
501
665
|
},
|
|
502
666
|
},
|
|
667
|
+
{
|
|
668
|
+
id: 'select',
|
|
669
|
+
type: 'text',
|
|
670
|
+
label: 'Select',
|
|
671
|
+
elements: [
|
|
672
|
+
{ value: 'option1', label: 'Option 1' },
|
|
673
|
+
{ value: 'option2', label: 'Option 2' },
|
|
674
|
+
],
|
|
675
|
+
isValid: {
|
|
676
|
+
required,
|
|
677
|
+
custom: maybeCustomRule( customSelectRule ),
|
|
678
|
+
},
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
id: 'textWithRadio',
|
|
682
|
+
type: 'text',
|
|
683
|
+
Edit: 'radio',
|
|
684
|
+
label: 'Text with radio',
|
|
685
|
+
elements: [
|
|
686
|
+
{ value: 'item1', label: 'Item 1' },
|
|
687
|
+
{ value: 'item2', label: 'Item 2' },
|
|
688
|
+
],
|
|
689
|
+
isValid: {
|
|
690
|
+
required,
|
|
691
|
+
custom: maybeCustomRule( customTextRadioRule ),
|
|
692
|
+
},
|
|
693
|
+
},
|
|
503
694
|
{
|
|
504
695
|
id: 'textarea',
|
|
505
696
|
type: 'text',
|
|
@@ -561,6 +752,7 @@ const ValidationComponent = ( {
|
|
|
561
752
|
label: 'Boolean',
|
|
562
753
|
isValid: {
|
|
563
754
|
required,
|
|
755
|
+
custom: maybeCustomRule( customBooleanRule ),
|
|
564
756
|
},
|
|
565
757
|
},
|
|
566
758
|
{
|
|
@@ -580,12 +772,39 @@ const ValidationComponent = ( {
|
|
|
580
772
|
custom: maybeCustomRule( customPasswordRule ),
|
|
581
773
|
},
|
|
582
774
|
},
|
|
775
|
+
{
|
|
776
|
+
id: 'toggle',
|
|
777
|
+
type: 'boolean',
|
|
778
|
+
label: 'Toggle',
|
|
779
|
+
Edit: 'toggle',
|
|
780
|
+
isValid: {
|
|
781
|
+
required,
|
|
782
|
+
custom: maybeCustomRule( customToggleRule ),
|
|
783
|
+
},
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
id: 'toggleGroup',
|
|
787
|
+
type: 'text',
|
|
788
|
+
label: 'Toggle Group',
|
|
789
|
+
Edit: 'toggleGroup',
|
|
790
|
+
elements: [
|
|
791
|
+
{ value: 'option1', label: 'Option 1' },
|
|
792
|
+
{ value: 'option2', label: 'Option 2' },
|
|
793
|
+
{ value: 'option3', label: 'Option 3' },
|
|
794
|
+
],
|
|
795
|
+
isValid: {
|
|
796
|
+
required,
|
|
797
|
+
custom: maybeCustomRule( customToggleGroupRule ),
|
|
798
|
+
},
|
|
799
|
+
},
|
|
583
800
|
];
|
|
584
801
|
|
|
585
802
|
const form = {
|
|
586
803
|
layout: { type },
|
|
587
804
|
fields: [
|
|
588
805
|
'text',
|
|
806
|
+
'select',
|
|
807
|
+
'textWithRadio',
|
|
589
808
|
'textarea',
|
|
590
809
|
'email',
|
|
591
810
|
'telephone',
|
|
@@ -593,8 +812,10 @@ const ValidationComponent = ( {
|
|
|
593
812
|
'color',
|
|
594
813
|
'integer',
|
|
595
814
|
'boolean',
|
|
596
|
-
'
|
|
815
|
+
'toggle',
|
|
816
|
+
'toggleGroup',
|
|
597
817
|
'password',
|
|
818
|
+
'customEdit',
|
|
598
819
|
],
|
|
599
820
|
};
|
|
600
821
|
|
|
@@ -1261,3 +1482,211 @@ export const Validation = {
|
|
|
1261
1482
|
export const Visibility = {
|
|
1262
1483
|
render: VisibilityComponent,
|
|
1263
1484
|
};
|
|
1485
|
+
|
|
1486
|
+
const DataAdapterComponent = () => {
|
|
1487
|
+
type DataAdapterItem = {
|
|
1488
|
+
user: {
|
|
1489
|
+
profile: {
|
|
1490
|
+
name: string;
|
|
1491
|
+
email: string;
|
|
1492
|
+
};
|
|
1493
|
+
preferences: {
|
|
1494
|
+
notifications: boolean;
|
|
1495
|
+
};
|
|
1496
|
+
};
|
|
1497
|
+
revenue: {
|
|
1498
|
+
total: number;
|
|
1499
|
+
units: number;
|
|
1500
|
+
pricePerUnit: number;
|
|
1501
|
+
};
|
|
1502
|
+
};
|
|
1503
|
+
|
|
1504
|
+
const [ data, setData ] = useState< DataAdapterItem >( {
|
|
1505
|
+
user: {
|
|
1506
|
+
profile: {
|
|
1507
|
+
name: 'John Doe',
|
|
1508
|
+
email: 'john@example.com',
|
|
1509
|
+
},
|
|
1510
|
+
preferences: {
|
|
1511
|
+
notifications: true,
|
|
1512
|
+
},
|
|
1513
|
+
},
|
|
1514
|
+
revenue: {
|
|
1515
|
+
total: 30,
|
|
1516
|
+
units: 10,
|
|
1517
|
+
pricePerUnit: 3,
|
|
1518
|
+
},
|
|
1519
|
+
} );
|
|
1520
|
+
|
|
1521
|
+
const nestedFields: Field< DataAdapterItem >[] = [
|
|
1522
|
+
// Examples of autogenerated getValue/setValue methods
|
|
1523
|
+
// for nested data based on the field id.
|
|
1524
|
+
{
|
|
1525
|
+
id: 'user.profile.name',
|
|
1526
|
+
label: 'User Name',
|
|
1527
|
+
type: 'text',
|
|
1528
|
+
},
|
|
1529
|
+
{
|
|
1530
|
+
id: 'user.profile.email',
|
|
1531
|
+
label: 'User Email',
|
|
1532
|
+
type: 'email',
|
|
1533
|
+
},
|
|
1534
|
+
// Example of adapting a data value to a control value
|
|
1535
|
+
// by providing getValue/setValue methods.
|
|
1536
|
+
{
|
|
1537
|
+
id: 'user.preferences.notifications',
|
|
1538
|
+
label: 'Notifications',
|
|
1539
|
+
type: 'boolean',
|
|
1540
|
+
Edit: 'radio',
|
|
1541
|
+
elements: [
|
|
1542
|
+
{ label: 'Enabled', value: 'enabled' },
|
|
1543
|
+
{ label: 'Disabled', value: 'disabled' },
|
|
1544
|
+
],
|
|
1545
|
+
getValue: ( { item } ) =>
|
|
1546
|
+
item.user.preferences.notifications === true
|
|
1547
|
+
? 'enabled'
|
|
1548
|
+
: 'disabled',
|
|
1549
|
+
setValue: ( { value } ) => ( {
|
|
1550
|
+
user: {
|
|
1551
|
+
preferences: { notifications: value === 'enabled' },
|
|
1552
|
+
},
|
|
1553
|
+
} ),
|
|
1554
|
+
},
|
|
1555
|
+
// Example of deriving data by leveraging setValue method.
|
|
1556
|
+
{
|
|
1557
|
+
id: 'revenue.total',
|
|
1558
|
+
label: 'Total Revenue',
|
|
1559
|
+
type: 'integer',
|
|
1560
|
+
readOnly: true,
|
|
1561
|
+
},
|
|
1562
|
+
{
|
|
1563
|
+
id: 'revenue.pricePerUnit',
|
|
1564
|
+
label: 'Price Per Unit',
|
|
1565
|
+
type: 'integer',
|
|
1566
|
+
setValue: ( { item, value } ) => ( {
|
|
1567
|
+
revenue: {
|
|
1568
|
+
total: value * item.revenue.units,
|
|
1569
|
+
pricePerUnit: value,
|
|
1570
|
+
},
|
|
1571
|
+
} ),
|
|
1572
|
+
},
|
|
1573
|
+
{
|
|
1574
|
+
id: 'revenue.units',
|
|
1575
|
+
label: 'Units',
|
|
1576
|
+
type: 'integer',
|
|
1577
|
+
setValue: ( { item, value } ) => ( {
|
|
1578
|
+
revenue: {
|
|
1579
|
+
total: item.revenue.pricePerUnit * value,
|
|
1580
|
+
units: value,
|
|
1581
|
+
},
|
|
1582
|
+
} ),
|
|
1583
|
+
},
|
|
1584
|
+
];
|
|
1585
|
+
|
|
1586
|
+
const handleChange = useCallback( ( edits: any ) => {
|
|
1587
|
+
// Edits will respect the shape of the data
|
|
1588
|
+
// because fields provide the proper information
|
|
1589
|
+
// (via field.id or via field.setValue).
|
|
1590
|
+
setData( ( prev ) => deepMerge( prev, edits ) );
|
|
1591
|
+
}, [] );
|
|
1592
|
+
|
|
1593
|
+
return (
|
|
1594
|
+
<>
|
|
1595
|
+
<h1>Data adapter</h1>
|
|
1596
|
+
<p>
|
|
1597
|
+
This story is best looked at with the code on the side. It aims
|
|
1598
|
+
to highlight how DataForm can wrangle data in scenarios such as
|
|
1599
|
+
nested data, bridge data to/from UI controls, and derived data.
|
|
1600
|
+
</p>
|
|
1601
|
+
<p>
|
|
1602
|
+
<b>Current data snapshot:</b>
|
|
1603
|
+
</p>
|
|
1604
|
+
<pre>{ JSON.stringify( data, null, 2 ) }</pre>
|
|
1605
|
+
<h2>Nested data</h2>
|
|
1606
|
+
<p>
|
|
1607
|
+
The first example demonstrates how to signal nested data via{ ' ' }
|
|
1608
|
+
<code>field.id</code>.
|
|
1609
|
+
</p>
|
|
1610
|
+
<p>
|
|
1611
|
+
By using <code>{ `{ id: 'user.profile.name' }` }</code> as field
|
|
1612
|
+
id, when users edit the name, the edits will come in this shape:
|
|
1613
|
+
<code>{ `{ user: { profile: { name: 'John Doe' } } }` }</code>
|
|
1614
|
+
</p>
|
|
1615
|
+
<DataForm< DataAdapterItem >
|
|
1616
|
+
data={ data }
|
|
1617
|
+
fields={ nestedFields }
|
|
1618
|
+
form={ {
|
|
1619
|
+
layout: {
|
|
1620
|
+
type: 'panel',
|
|
1621
|
+
labelPosition: 'top',
|
|
1622
|
+
openAs: 'modal',
|
|
1623
|
+
},
|
|
1624
|
+
fields: [
|
|
1625
|
+
{
|
|
1626
|
+
id: 'userProfile',
|
|
1627
|
+
label: 'User Profile',
|
|
1628
|
+
children: [
|
|
1629
|
+
'user.profile.name',
|
|
1630
|
+
'user.profile.email',
|
|
1631
|
+
],
|
|
1632
|
+
},
|
|
1633
|
+
],
|
|
1634
|
+
} }
|
|
1635
|
+
onChange={ handleChange }
|
|
1636
|
+
/>
|
|
1637
|
+
<h2>Adapt data and UI control</h2>
|
|
1638
|
+
<p>
|
|
1639
|
+
Sometimes, we need to adapt the data type to and from the UI
|
|
1640
|
+
control response. This example demonstrates how to adapt a
|
|
1641
|
+
boolean to a text string (Enabled/Disabled).
|
|
1642
|
+
</p>
|
|
1643
|
+
<DataForm< DataAdapterItem >
|
|
1644
|
+
data={ data }
|
|
1645
|
+
fields={ nestedFields }
|
|
1646
|
+
form={ {
|
|
1647
|
+
layout: {
|
|
1648
|
+
type: 'panel',
|
|
1649
|
+
labelPosition: 'top',
|
|
1650
|
+
openAs: 'modal',
|
|
1651
|
+
},
|
|
1652
|
+
fields: [ 'user.preferences.notifications' ],
|
|
1653
|
+
} }
|
|
1654
|
+
onChange={ handleChange }
|
|
1655
|
+
/>
|
|
1656
|
+
<h2>Derived data</h2>
|
|
1657
|
+
<p>
|
|
1658
|
+
Last, but not least, this example showcases how to work with
|
|
1659
|
+
derived data by providing a custom setValue function. Note how,
|
|
1660
|
+
changing UNITS or PRICE PER UNIT, updates the TOTAL value as
|
|
1661
|
+
well.
|
|
1662
|
+
</p>
|
|
1663
|
+
<DataForm< DataAdapterItem >
|
|
1664
|
+
data={ data }
|
|
1665
|
+
fields={ nestedFields }
|
|
1666
|
+
form={ {
|
|
1667
|
+
layout: {
|
|
1668
|
+
type: 'panel',
|
|
1669
|
+
labelPosition: 'top',
|
|
1670
|
+
openAs: 'modal',
|
|
1671
|
+
},
|
|
1672
|
+
fields: [
|
|
1673
|
+
{
|
|
1674
|
+
id: 'revenue',
|
|
1675
|
+
label: 'Revenue',
|
|
1676
|
+
children: [
|
|
1677
|
+
'revenue.pricePerUnit',
|
|
1678
|
+
'revenue.units',
|
|
1679
|
+
'revenue.total',
|
|
1680
|
+
],
|
|
1681
|
+
},
|
|
1682
|
+
],
|
|
1683
|
+
} }
|
|
1684
|
+
onChange={ handleChange }
|
|
1685
|
+
/>
|
|
1686
|
+
</>
|
|
1687
|
+
);
|
|
1688
|
+
};
|
|
1689
|
+
|
|
1690
|
+
export const DataAdapter = {
|
|
1691
|
+
render: DataAdapterComponent,
|
|
1692
|
+
};
|