@wordpress/dataviews 7.0.1-next.0f6f9d12c.0 → 7.0.1-next.f34ab90e9.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 +4 -1
- package/build/components/dataviews-item-actions/index.js +1 -10
- package/build/components/dataviews-item-actions/index.js.map +1 -1
- package/build/dataform-controls/boolean.js +15 -7
- package/build/dataform-controls/boolean.js.map +1 -1
- package/build/dataform-controls/email.js +14 -7
- package/build/dataform-controls/email.js.map +1 -1
- package/build/dataform-controls/integer.js +14 -7
- package/build/dataform-controls/integer.js.map +1 -1
- package/build/dataform-controls/text.js +14 -7
- package/build/dataform-controls/text.js.map +1 -1
- package/build/dataforms-layouts/panel/dropdown.js +124 -0
- package/build/dataforms-layouts/panel/dropdown.js.map +1 -0
- package/build/dataforms-layouts/panel/index.js +19 -127
- package/build/dataforms-layouts/panel/index.js.map +1 -1
- package/build/dataforms-layouts/panel/modal.js +125 -0
- package/build/dataforms-layouts/panel/modal.js.map +1 -0
- package/build/normalize-form-fields.js +3 -2
- package/build/normalize-form-fields.js.map +1 -1
- package/build/types.js.map +1 -1
- package/build-module/components/dataviews-item-actions/index.js +1 -10
- package/build-module/components/dataviews-item-actions/index.js.map +1 -1
- package/build-module/dataform-controls/boolean.js +15 -7
- package/build-module/dataform-controls/boolean.js.map +1 -1
- package/build-module/dataform-controls/email.js +15 -8
- package/build-module/dataform-controls/email.js.map +1 -1
- package/build-module/dataform-controls/integer.js +15 -8
- package/build-module/dataform-controls/integer.js.map +1 -1
- package/build-module/dataform-controls/text.js +15 -8
- package/build-module/dataform-controls/text.js.map +1 -1
- package/build-module/dataforms-layouts/panel/dropdown.js +118 -0
- package/build-module/dataforms-layouts/panel/dropdown.js.map +1 -0
- package/build-module/dataforms-layouts/panel/index.js +23 -131
- package/build-module/dataforms-layouts/panel/index.js.map +1 -1
- package/build-module/dataforms-layouts/panel/modal.js +119 -0
- package/build-module/dataforms-layouts/panel/modal.js.map +1 -0
- package/build-module/normalize-form-fields.js +3 -2
- package/build-module/normalize-form-fields.js.map +1 -1
- package/build-module/types.js.map +1 -1
- package/build-style/style-rtl.css +4 -0
- package/build-style/style.css +4 -0
- package/build-types/components/dataform/stories/index.story.d.ts +58 -25
- package/build-types/components/dataform/stories/index.story.d.ts.map +1 -1
- package/build-types/components/dataviews-item-actions/index.d.ts.map +1 -1
- package/build-types/dataform-controls/boolean.d.ts.map +1 -1
- package/build-types/dataform-controls/email.d.ts.map +1 -1
- package/build-types/dataform-controls/integer.d.ts.map +1 -1
- package/build-types/dataform-controls/text.d.ts.map +1 -1
- package/build-types/dataforms-layouts/panel/dropdown.d.ts +14 -0
- package/build-types/dataforms-layouts/panel/dropdown.d.ts.map +1 -0
- package/build-types/dataforms-layouts/panel/index.d.ts.map +1 -1
- package/build-types/dataforms-layouts/panel/modal.d.ts +13 -0
- package/build-types/dataforms-layouts/panel/modal.d.ts.map +1 -0
- package/build-types/normalize-form-fields.d.ts.map +1 -1
- package/build-types/types.d.ts +2 -0
- package/build-types/types.d.ts.map +1 -1
- package/build-wp/index.js +394 -178
- package/package.json +15 -15
- package/src/components/dataform/stories/index.story.tsx +354 -219
- package/src/components/dataviews-item-actions/index.tsx +7 -16
- package/src/dataform-controls/boolean.tsx +24 -10
- package/src/dataform-controls/email.tsx +24 -11
- package/src/dataform-controls/integer.tsx +27 -13
- package/src/dataform-controls/text.tsx +24 -11
- package/src/dataforms-layouts/panel/dropdown.tsx +160 -0
- package/src/dataforms-layouts/panel/index.tsx +28 -172
- package/src/dataforms-layouts/panel/modal.tsx +165 -0
- package/src/dataforms-layouts/panel/style.scss +4 -0
- package/src/normalize-form-fields.ts +1 -0
- package/src/test/dataform.tsx +169 -0
- package/src/test/normalize-form-fields.ts +15 -3
- package/src/types.ts +2 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -179,17 +179,6 @@ export default function ItemActions< Item >( {
|
|
|
179
179
|
);
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
// If all actions are primary, there is no need to render the dropdown.
|
|
183
|
-
if ( primaryActions.length === eligibleActions.length ) {
|
|
184
|
-
return (
|
|
185
|
-
<PrimaryActions
|
|
186
|
-
item={ item }
|
|
187
|
-
actions={ primaryActions }
|
|
188
|
-
registry={ registry }
|
|
189
|
-
/>
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
182
|
return (
|
|
194
183
|
<HStack
|
|
195
184
|
spacing={ 1 }
|
|
@@ -205,11 +194,13 @@ export default function ItemActions< Item >( {
|
|
|
205
194
|
actions={ primaryActions }
|
|
206
195
|
registry={ registry }
|
|
207
196
|
/>
|
|
208
|
-
<
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
197
|
+
{ primaryActions.length < eligibleActions.length && (
|
|
198
|
+
<CompactItemActions
|
|
199
|
+
item={ item }
|
|
200
|
+
actions={ eligibleActions }
|
|
201
|
+
registry={ registry }
|
|
202
|
+
/>
|
|
203
|
+
) }
|
|
213
204
|
</HStack>
|
|
214
205
|
);
|
|
215
206
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { privateApis } from '@wordpress/components';
|
|
5
|
+
import { useState } from '@wordpress/element';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Internal dependencies
|
|
@@ -18,23 +19,36 @@ export default function Boolean< Item >( {
|
|
|
18
19
|
hideLabelFromVision,
|
|
19
20
|
}: DataFormControlProps< Item > ) {
|
|
20
21
|
const { id, getValue, label } = field;
|
|
22
|
+
const [ customValidity, setCustomValidity ] =
|
|
23
|
+
useState<
|
|
24
|
+
React.ComponentProps<
|
|
25
|
+
typeof ValidatedToggleControl
|
|
26
|
+
>[ 'customValidity' ]
|
|
27
|
+
>( undefined );
|
|
21
28
|
|
|
22
29
|
return (
|
|
23
30
|
<ValidatedToggleControl
|
|
24
31
|
required={ !! field.isValid.required }
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
onValidate={ ( newValue: any ) => {
|
|
33
|
+
const message = field.isValid?.custom?.(
|
|
34
|
+
{
|
|
35
|
+
...data,
|
|
36
|
+
[ id ]: newValue,
|
|
37
|
+
},
|
|
38
|
+
field
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if ( message ) {
|
|
42
|
+
setCustomValidity( {
|
|
43
|
+
type: 'invalid',
|
|
44
|
+
message,
|
|
45
|
+
} );
|
|
46
|
+
return;
|
|
34
47
|
}
|
|
35
48
|
|
|
36
|
-
|
|
49
|
+
setCustomValidity( undefined );
|
|
37
50
|
} }
|
|
51
|
+
customValidity={ customValidity }
|
|
38
52
|
hidden={ hideLabelFromVision }
|
|
39
53
|
__nextHasNoMarginBottom
|
|
40
54
|
label={ label }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { privateApis } from '@wordpress/components';
|
|
5
|
-
import { useCallback } from '@wordpress/element';
|
|
5
|
+
import { useCallback, useState } from '@wordpress/element';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Internal dependencies
|
|
@@ -20,6 +20,12 @@ export default function Email< Item >( {
|
|
|
20
20
|
}: DataFormControlProps< Item > ) {
|
|
21
21
|
const { id, label, placeholder, description } = field;
|
|
22
22
|
const value = field.getValue( { item: data } );
|
|
23
|
+
const [ customValidity, setCustomValidity ] =
|
|
24
|
+
useState<
|
|
25
|
+
React.ComponentProps<
|
|
26
|
+
typeof ValidatedTextControl
|
|
27
|
+
>[ 'customValidity' ]
|
|
28
|
+
>( undefined );
|
|
23
29
|
|
|
24
30
|
const onChangeControl = useCallback(
|
|
25
31
|
( newValue: string ) =>
|
|
@@ -32,19 +38,26 @@ export default function Email< Item >( {
|
|
|
32
38
|
return (
|
|
33
39
|
<ValidatedTextControl
|
|
34
40
|
required={ !! field.isValid?.required }
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
onValidate={ ( newValue: any ) => {
|
|
42
|
+
const message = field.isValid?.custom?.(
|
|
43
|
+
{
|
|
44
|
+
...data,
|
|
45
|
+
[ id ]: newValue,
|
|
46
|
+
},
|
|
47
|
+
field
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if ( message ) {
|
|
51
|
+
setCustomValidity( {
|
|
52
|
+
type: 'invalid',
|
|
53
|
+
message,
|
|
54
|
+
} );
|
|
55
|
+
return;
|
|
44
56
|
}
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
setCustomValidity( undefined );
|
|
47
59
|
} }
|
|
60
|
+
customValidity={ customValidity }
|
|
48
61
|
type="email"
|
|
49
62
|
label={ label }
|
|
50
63
|
placeholder={ placeholder }
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
__experimentalNumberControl as NumberControl,
|
|
8
8
|
privateApis,
|
|
9
9
|
} from '@wordpress/components';
|
|
10
|
-
import { useCallback } from '@wordpress/element';
|
|
10
|
+
import { useCallback, useState } from '@wordpress/element';
|
|
11
11
|
import { __ } from '@wordpress/i18n';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -84,6 +84,13 @@ export default function Integer< Item >( {
|
|
|
84
84
|
}: DataFormControlProps< Item > ) {
|
|
85
85
|
const { id, label, description } = field;
|
|
86
86
|
const value = field.getValue( { item: data } ) ?? '';
|
|
87
|
+
const [ customValidity, setCustomValidity ] =
|
|
88
|
+
useState<
|
|
89
|
+
React.ComponentProps<
|
|
90
|
+
typeof ValidatedNumberControl
|
|
91
|
+
>[ 'customValidity' ]
|
|
92
|
+
>( undefined );
|
|
93
|
+
|
|
87
94
|
const onChangeControl = useCallback(
|
|
88
95
|
( newValue: string | undefined ) => {
|
|
89
96
|
onChange( {
|
|
@@ -112,21 +119,28 @@ export default function Integer< Item >( {
|
|
|
112
119
|
return (
|
|
113
120
|
<ValidatedNumberControl
|
|
114
121
|
required={ !! field.isValid?.required }
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
onValidate={ ( newValue: any ) => {
|
|
123
|
+
const message = field.isValid?.custom?.(
|
|
124
|
+
{
|
|
125
|
+
...data,
|
|
126
|
+
[ id ]: [ undefined, '', null ].includes( newValue )
|
|
127
|
+
? undefined
|
|
128
|
+
: Number( newValue ),
|
|
129
|
+
},
|
|
130
|
+
field
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
if ( message ) {
|
|
134
|
+
setCustomValidity( {
|
|
135
|
+
type: 'invalid',
|
|
136
|
+
message,
|
|
137
|
+
} );
|
|
138
|
+
return;
|
|
126
139
|
}
|
|
127
140
|
|
|
128
|
-
|
|
141
|
+
setCustomValidity( undefined );
|
|
129
142
|
} }
|
|
143
|
+
customValidity={ customValidity }
|
|
130
144
|
label={ label }
|
|
131
145
|
help={ description }
|
|
132
146
|
value={ value }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { privateApis } from '@wordpress/components';
|
|
5
|
-
import { useCallback } from '@wordpress/element';
|
|
5
|
+
import { useCallback, useState } from '@wordpress/element';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Internal dependencies
|
|
@@ -20,6 +20,12 @@ export default function Text< Item >( {
|
|
|
20
20
|
}: DataFormControlProps< Item > ) {
|
|
21
21
|
const { id, label, placeholder, description } = field;
|
|
22
22
|
const value = field.getValue( { item: data } );
|
|
23
|
+
const [ customValidity, setCustomValidity ] =
|
|
24
|
+
useState<
|
|
25
|
+
React.ComponentProps<
|
|
26
|
+
typeof ValidatedTextControl
|
|
27
|
+
>[ 'customValidity' ]
|
|
28
|
+
>( undefined );
|
|
23
29
|
|
|
24
30
|
const onChangeControl = useCallback(
|
|
25
31
|
( newValue: string ) =>
|
|
@@ -32,19 +38,26 @@ export default function Text< Item >( {
|
|
|
32
38
|
return (
|
|
33
39
|
<ValidatedTextControl
|
|
34
40
|
required={ !! field.isValid?.required }
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
onValidate={ ( newValue: any ) => {
|
|
42
|
+
const message = field.isValid?.custom?.(
|
|
43
|
+
{
|
|
44
|
+
...data,
|
|
45
|
+
[ id ]: newValue,
|
|
46
|
+
},
|
|
47
|
+
field
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if ( message ) {
|
|
51
|
+
setCustomValidity( {
|
|
52
|
+
type: 'invalid',
|
|
53
|
+
message,
|
|
54
|
+
} );
|
|
55
|
+
return;
|
|
44
56
|
}
|
|
45
57
|
|
|
46
|
-
|
|
58
|
+
setCustomValidity( undefined );
|
|
47
59
|
} }
|
|
60
|
+
customValidity={ customValidity }
|
|
48
61
|
label={ label }
|
|
49
62
|
placeholder={ placeholder }
|
|
50
63
|
value={ value ?? '' }
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
__experimentalVStack as VStack,
|
|
6
|
+
__experimentalHStack as HStack,
|
|
7
|
+
__experimentalHeading as Heading,
|
|
8
|
+
__experimentalSpacer as Spacer,
|
|
9
|
+
Dropdown,
|
|
10
|
+
Button,
|
|
11
|
+
} from '@wordpress/components';
|
|
12
|
+
import { sprintf, __, _x } from '@wordpress/i18n';
|
|
13
|
+
import { useMemo } from '@wordpress/element';
|
|
14
|
+
import { closeSmall } from '@wordpress/icons';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Internal dependencies
|
|
18
|
+
*/
|
|
19
|
+
import type { Form, FormField, NormalizedField } from '../../types';
|
|
20
|
+
import { DataFormLayout } from '../data-form-layout';
|
|
21
|
+
import { isCombinedField } from '../is-combined-field';
|
|
22
|
+
import { DEFAULT_LAYOUT } from '../../normalize-form-fields';
|
|
23
|
+
|
|
24
|
+
function DropdownHeader( {
|
|
25
|
+
title,
|
|
26
|
+
onClose,
|
|
27
|
+
}: {
|
|
28
|
+
title?: string;
|
|
29
|
+
onClose: () => void;
|
|
30
|
+
} ) {
|
|
31
|
+
return (
|
|
32
|
+
<VStack
|
|
33
|
+
className="dataforms-layouts-panel__dropdown-header"
|
|
34
|
+
spacing={ 4 }
|
|
35
|
+
>
|
|
36
|
+
<HStack alignment="center">
|
|
37
|
+
{ title && (
|
|
38
|
+
<Heading level={ 2 } size={ 13 }>
|
|
39
|
+
{ title }
|
|
40
|
+
</Heading>
|
|
41
|
+
) }
|
|
42
|
+
<Spacer />
|
|
43
|
+
{ onClose && (
|
|
44
|
+
<Button
|
|
45
|
+
label={ __( 'Close' ) }
|
|
46
|
+
icon={ closeSmall }
|
|
47
|
+
onClick={ onClose }
|
|
48
|
+
size="small"
|
|
49
|
+
/>
|
|
50
|
+
) }
|
|
51
|
+
</HStack>
|
|
52
|
+
</VStack>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function PanelDropdown< Item >( {
|
|
57
|
+
fieldDefinition,
|
|
58
|
+
popoverAnchor,
|
|
59
|
+
labelPosition = 'side',
|
|
60
|
+
data,
|
|
61
|
+
onChange,
|
|
62
|
+
field,
|
|
63
|
+
}: {
|
|
64
|
+
fieldDefinition: NormalizedField< Item >;
|
|
65
|
+
popoverAnchor: HTMLElement | null;
|
|
66
|
+
labelPosition: 'side' | 'top' | 'none';
|
|
67
|
+
data: Item;
|
|
68
|
+
onChange: ( value: any ) => void;
|
|
69
|
+
field: FormField;
|
|
70
|
+
} ) {
|
|
71
|
+
const fieldLabel = isCombinedField( field )
|
|
72
|
+
? field.label
|
|
73
|
+
: fieldDefinition?.label;
|
|
74
|
+
|
|
75
|
+
const form: Form = useMemo(
|
|
76
|
+
(): Form => ( {
|
|
77
|
+
layout: DEFAULT_LAYOUT,
|
|
78
|
+
fields: isCombinedField( field )
|
|
79
|
+
? field.children
|
|
80
|
+
: // If not explicit children return the field id itself.
|
|
81
|
+
[ { id: field.id } ],
|
|
82
|
+
} ),
|
|
83
|
+
[ field ]
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
// Memoize popoverProps to avoid returning a new object every time.
|
|
87
|
+
const popoverProps = useMemo(
|
|
88
|
+
() => ( {
|
|
89
|
+
// Anchor the popover to the middle of the entire row so that it doesn't
|
|
90
|
+
// move around when the label changes.
|
|
91
|
+
anchor: popoverAnchor,
|
|
92
|
+
placement: 'left-start',
|
|
93
|
+
offset: 36,
|
|
94
|
+
shift: true,
|
|
95
|
+
} ),
|
|
96
|
+
[ popoverAnchor ]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<Dropdown
|
|
101
|
+
contentClassName="dataforms-layouts-panel__field-dropdown"
|
|
102
|
+
popoverProps={ popoverProps }
|
|
103
|
+
focusOnMount
|
|
104
|
+
toggleProps={ {
|
|
105
|
+
size: 'compact',
|
|
106
|
+
variant: 'tertiary',
|
|
107
|
+
tooltipPosition: 'middle left',
|
|
108
|
+
} }
|
|
109
|
+
renderToggle={ ( { isOpen, onToggle } ) => (
|
|
110
|
+
<Button
|
|
111
|
+
className="dataforms-layouts-panel__field-control"
|
|
112
|
+
size="compact"
|
|
113
|
+
variant={
|
|
114
|
+
[ 'none', 'top' ].includes( labelPosition )
|
|
115
|
+
? 'link'
|
|
116
|
+
: 'tertiary'
|
|
117
|
+
}
|
|
118
|
+
aria-expanded={ isOpen }
|
|
119
|
+
aria-label={ sprintf(
|
|
120
|
+
// translators: %s: Field name.
|
|
121
|
+
_x( 'Edit %s', 'field' ),
|
|
122
|
+
fieldLabel || ''
|
|
123
|
+
) }
|
|
124
|
+
onClick={ onToggle }
|
|
125
|
+
disabled={ fieldDefinition.readOnly === true }
|
|
126
|
+
accessibleWhenDisabled
|
|
127
|
+
>
|
|
128
|
+
<fieldDefinition.render
|
|
129
|
+
item={ data }
|
|
130
|
+
field={ fieldDefinition }
|
|
131
|
+
/>
|
|
132
|
+
</Button>
|
|
133
|
+
) }
|
|
134
|
+
renderContent={ ( { onClose } ) => (
|
|
135
|
+
<>
|
|
136
|
+
<DropdownHeader title={ fieldLabel } onClose={ onClose } />
|
|
137
|
+
<DataFormLayout
|
|
138
|
+
data={ data }
|
|
139
|
+
form={ form }
|
|
140
|
+
onChange={ onChange }
|
|
141
|
+
>
|
|
142
|
+
{ ( FieldLayout, nestedField ) => (
|
|
143
|
+
<FieldLayout
|
|
144
|
+
key={ nestedField.id }
|
|
145
|
+
data={ data }
|
|
146
|
+
field={ nestedField }
|
|
147
|
+
onChange={ onChange }
|
|
148
|
+
hideLabelFromVision={
|
|
149
|
+
( form?.fields ?? [] ).length < 2
|
|
150
|
+
}
|
|
151
|
+
/>
|
|
152
|
+
) }
|
|
153
|
+
</DataFormLayout>
|
|
154
|
+
</>
|
|
155
|
+
) }
|
|
156
|
+
/>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export default PanelDropdown;
|
|
@@ -9,166 +9,22 @@ import clsx from 'clsx';
|
|
|
9
9
|
import {
|
|
10
10
|
__experimentalVStack as VStack,
|
|
11
11
|
__experimentalHStack as HStack,
|
|
12
|
-
__experimentalHeading as Heading,
|
|
13
|
-
__experimentalSpacer as Spacer,
|
|
14
|
-
Dropdown,
|
|
15
|
-
Button,
|
|
16
12
|
} from '@wordpress/components';
|
|
17
|
-
import {
|
|
18
|
-
import { useState, useMemo, useContext } from '@wordpress/element';
|
|
19
|
-
import { closeSmall } from '@wordpress/icons';
|
|
13
|
+
import { useState, useContext } from '@wordpress/element';
|
|
20
14
|
|
|
21
15
|
/**
|
|
22
16
|
* Internal dependencies
|
|
23
17
|
*/
|
|
24
18
|
import type {
|
|
25
|
-
Form,
|
|
26
|
-
FormField,
|
|
27
19
|
FieldLayoutProps,
|
|
28
20
|
NormalizedPanelLayout,
|
|
29
|
-
NormalizedField,
|
|
30
21
|
SimpleFormField,
|
|
31
22
|
} from '../../types';
|
|
32
23
|
import DataFormContext from '../../components/dataform-context';
|
|
33
|
-
import { DataFormLayout } from '../data-form-layout';
|
|
34
24
|
import { isCombinedField } from '../is-combined-field';
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
title,
|
|
39
|
-
onClose,
|
|
40
|
-
}: {
|
|
41
|
-
title?: string;
|
|
42
|
-
onClose: () => void;
|
|
43
|
-
} ) {
|
|
44
|
-
return (
|
|
45
|
-
<VStack
|
|
46
|
-
className="dataforms-layouts-panel__dropdown-header"
|
|
47
|
-
spacing={ 4 }
|
|
48
|
-
>
|
|
49
|
-
<HStack alignment="center">
|
|
50
|
-
{ title && (
|
|
51
|
-
<Heading level={ 2 } size={ 13 }>
|
|
52
|
-
{ title }
|
|
53
|
-
</Heading>
|
|
54
|
-
) }
|
|
55
|
-
<Spacer />
|
|
56
|
-
{ onClose && (
|
|
57
|
-
<Button
|
|
58
|
-
label={ __( 'Close' ) }
|
|
59
|
-
icon={ closeSmall }
|
|
60
|
-
onClick={ onClose }
|
|
61
|
-
size="small"
|
|
62
|
-
/>
|
|
63
|
-
) }
|
|
64
|
-
</HStack>
|
|
65
|
-
</VStack>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function PanelDropdown< Item >( {
|
|
70
|
-
fieldDefinition,
|
|
71
|
-
popoverAnchor,
|
|
72
|
-
labelPosition = 'side',
|
|
73
|
-
data,
|
|
74
|
-
onChange,
|
|
75
|
-
field,
|
|
76
|
-
}: {
|
|
77
|
-
fieldDefinition: NormalizedField< Item >;
|
|
78
|
-
popoverAnchor: HTMLElement | null;
|
|
79
|
-
labelPosition: 'side' | 'top' | 'none';
|
|
80
|
-
data: Item;
|
|
81
|
-
onChange: ( value: any ) => void;
|
|
82
|
-
field: FormField;
|
|
83
|
-
} ) {
|
|
84
|
-
const fieldLabel = isCombinedField( field )
|
|
85
|
-
? field.label
|
|
86
|
-
: fieldDefinition?.label;
|
|
87
|
-
|
|
88
|
-
const form: Form = useMemo(
|
|
89
|
-
(): Form => ( {
|
|
90
|
-
layout: DEFAULT_LAYOUT,
|
|
91
|
-
fields: isCombinedField( field )
|
|
92
|
-
? field.children
|
|
93
|
-
: // If not explicit children return the field id itself.
|
|
94
|
-
[ { id: field.id } ],
|
|
95
|
-
} ),
|
|
96
|
-
[ field ]
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
// Memoize popoverProps to avoid returning a new object every time.
|
|
100
|
-
const popoverProps = useMemo(
|
|
101
|
-
() => ( {
|
|
102
|
-
// Anchor the popover to the middle of the entire row so that it doesn't
|
|
103
|
-
// move around when the label changes.
|
|
104
|
-
anchor: popoverAnchor,
|
|
105
|
-
placement: 'left-start',
|
|
106
|
-
offset: 36,
|
|
107
|
-
shift: true,
|
|
108
|
-
} ),
|
|
109
|
-
[ popoverAnchor ]
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<Dropdown
|
|
114
|
-
contentClassName="dataforms-layouts-panel__field-dropdown"
|
|
115
|
-
popoverProps={ popoverProps }
|
|
116
|
-
focusOnMount
|
|
117
|
-
toggleProps={ {
|
|
118
|
-
size: 'compact',
|
|
119
|
-
variant: 'tertiary',
|
|
120
|
-
tooltipPosition: 'middle left',
|
|
121
|
-
} }
|
|
122
|
-
renderToggle={ ( { isOpen, onToggle } ) => (
|
|
123
|
-
<Button
|
|
124
|
-
className="dataforms-layouts-panel__field-control"
|
|
125
|
-
size="compact"
|
|
126
|
-
variant={
|
|
127
|
-
[ 'none', 'top' ].includes( labelPosition )
|
|
128
|
-
? 'link'
|
|
129
|
-
: 'tertiary'
|
|
130
|
-
}
|
|
131
|
-
aria-expanded={ isOpen }
|
|
132
|
-
aria-label={ sprintf(
|
|
133
|
-
// translators: %s: Field name.
|
|
134
|
-
_x( 'Edit %s', 'field' ),
|
|
135
|
-
fieldLabel || ''
|
|
136
|
-
) }
|
|
137
|
-
onClick={ onToggle }
|
|
138
|
-
disabled={ fieldDefinition.readOnly === true }
|
|
139
|
-
accessibleWhenDisabled
|
|
140
|
-
>
|
|
141
|
-
<fieldDefinition.render
|
|
142
|
-
item={ data }
|
|
143
|
-
field={ fieldDefinition }
|
|
144
|
-
/>
|
|
145
|
-
</Button>
|
|
146
|
-
) }
|
|
147
|
-
renderContent={ ( { onClose } ) => (
|
|
148
|
-
<>
|
|
149
|
-
<DropdownHeader title={ fieldLabel } onClose={ onClose } />
|
|
150
|
-
<DataFormLayout
|
|
151
|
-
data={ data }
|
|
152
|
-
form={ form }
|
|
153
|
-
onChange={ onChange }
|
|
154
|
-
>
|
|
155
|
-
{ ( FieldLayout, nestedField ) => (
|
|
156
|
-
<FieldLayout
|
|
157
|
-
key={ nestedField.id }
|
|
158
|
-
data={ data }
|
|
159
|
-
field={ nestedField }
|
|
160
|
-
onChange={ onChange }
|
|
161
|
-
hideLabelFromVision={
|
|
162
|
-
( form?.fields ?? [] ).length < 2
|
|
163
|
-
}
|
|
164
|
-
/>
|
|
165
|
-
) }
|
|
166
|
-
</DataFormLayout>
|
|
167
|
-
</>
|
|
168
|
-
) }
|
|
169
|
-
/>
|
|
170
|
-
);
|
|
171
|
-
}
|
|
25
|
+
import { normalizeLayout } from '../../normalize-form-fields';
|
|
26
|
+
import PanelDropdown from './dropdown';
|
|
27
|
+
import PanelModal from './modal';
|
|
172
28
|
|
|
173
29
|
export default function FormPanelField< Item >( {
|
|
174
30
|
data,
|
|
@@ -192,6 +48,7 @@ export default function FormPanelField< Item >( {
|
|
|
192
48
|
typeof simpleChildren[ 0 ] === 'string'
|
|
193
49
|
? simpleChildren[ 0 ]
|
|
194
50
|
: simpleChildren[ 0 ].id;
|
|
51
|
+
|
|
195
52
|
return _field.id === firstChildFieldId;
|
|
196
53
|
}
|
|
197
54
|
|
|
@@ -222,6 +79,26 @@ export default function FormPanelField< Item >( {
|
|
|
222
79
|
? field.label
|
|
223
80
|
: fieldDefinition?.label;
|
|
224
81
|
|
|
82
|
+
const renderedControl =
|
|
83
|
+
layout.openAs === 'modal' ? (
|
|
84
|
+
<PanelModal
|
|
85
|
+
field={ field }
|
|
86
|
+
fieldDefinition={ fieldDefinition }
|
|
87
|
+
data={ data }
|
|
88
|
+
onChange={ onChange }
|
|
89
|
+
labelPosition={ labelPosition }
|
|
90
|
+
/>
|
|
91
|
+
) : (
|
|
92
|
+
<PanelDropdown
|
|
93
|
+
field={ field }
|
|
94
|
+
popoverAnchor={ popoverAnchor }
|
|
95
|
+
fieldDefinition={ fieldDefinition }
|
|
96
|
+
data={ data }
|
|
97
|
+
onChange={ onChange }
|
|
98
|
+
labelPosition={ labelPosition }
|
|
99
|
+
/>
|
|
100
|
+
);
|
|
101
|
+
|
|
225
102
|
if ( labelPosition === 'top' ) {
|
|
226
103
|
return (
|
|
227
104
|
<VStack className="dataforms-layouts-panel__field" spacing={ 0 }>
|
|
@@ -232,14 +109,7 @@ export default function FormPanelField< Item >( {
|
|
|
232
109
|
{ fieldLabel }
|
|
233
110
|
</div>
|
|
234
111
|
<div className="dataforms-layouts-panel__field-control">
|
|
235
|
-
|
|
236
|
-
field={ field }
|
|
237
|
-
popoverAnchor={ popoverAnchor }
|
|
238
|
-
fieldDefinition={ fieldDefinition }
|
|
239
|
-
data={ data }
|
|
240
|
-
onChange={ onChange }
|
|
241
|
-
labelPosition={ labelPosition }
|
|
242
|
-
/>
|
|
112
|
+
{ renderedControl }
|
|
243
113
|
</div>
|
|
244
114
|
</VStack>
|
|
245
115
|
);
|
|
@@ -248,14 +118,7 @@ export default function FormPanelField< Item >( {
|
|
|
248
118
|
if ( labelPosition === 'none' ) {
|
|
249
119
|
return (
|
|
250
120
|
<div className="dataforms-layouts-panel__field">
|
|
251
|
-
|
|
252
|
-
field={ field }
|
|
253
|
-
popoverAnchor={ popoverAnchor }
|
|
254
|
-
fieldDefinition={ fieldDefinition }
|
|
255
|
-
data={ data }
|
|
256
|
-
onChange={ onChange }
|
|
257
|
-
labelPosition={ labelPosition }
|
|
258
|
-
/>
|
|
121
|
+
{ renderedControl }
|
|
259
122
|
</div>
|
|
260
123
|
);
|
|
261
124
|
}
|
|
@@ -268,14 +131,7 @@ export default function FormPanelField< Item >( {
|
|
|
268
131
|
>
|
|
269
132
|
<div className={ labelClassName }>{ fieldLabel }</div>
|
|
270
133
|
<div className="dataforms-layouts-panel__field-control">
|
|
271
|
-
|
|
272
|
-
field={ field }
|
|
273
|
-
popoverAnchor={ popoverAnchor }
|
|
274
|
-
fieldDefinition={ fieldDefinition }
|
|
275
|
-
data={ data }
|
|
276
|
-
onChange={ onChange }
|
|
277
|
-
labelPosition={ labelPosition }
|
|
278
|
-
/>
|
|
134
|
+
{ renderedControl }
|
|
279
135
|
</div>
|
|
280
136
|
</HStack>
|
|
281
137
|
);
|