Skip to content

Commit 3ffff1e

Browse files
authored
Forms: add first/last name field variations (#45517)
1 parent b2d9287 commit 3ffff1e

File tree

6 files changed

+179
-0
lines changed

6 files changed

+179
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: added
3+
4+
Forms: add first and last name variations.

projects/packages/forms/src/blocks/field-name/edit.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { __ } from '@wordpress/i18n';
22
import JetpackField from '../shared/components/jetpack-field';
33
import useFormWrapper from '../shared/hooks/use-form-wrapper';
4+
import useNameLabelSync from './hooks/use-name-label-sync';
45

56
export default function NameFieldEdit( props ) {
67
useFormWrapper( props );
78

9+
useNameLabelSync( { clientId: props.clientId, id: props.attributes?.id } );
10+
811
return (
912
<JetpackField
1013
clientId={ props.clientId }
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { store as blockEditorStore } from '@wordpress/block-editor';
2+
import { useSelect, useDispatch } from '@wordpress/data';
3+
import { useEffect, useRef } from '@wordpress/element';
4+
import {
5+
FIRST_NAME_ID,
6+
LAST_NAME_ID,
7+
DEFAULT_FIRST_NAME_LABEL,
8+
DEFAULT_LAST_NAME_LABEL,
9+
DEFAULT_NAME_LABEL,
10+
} from '../variations';
11+
12+
const isKnownId = id => id === FIRST_NAME_ID || id === LAST_NAME_ID;
13+
14+
const getDefaultLabelForId = id => {
15+
if ( id === FIRST_NAME_ID ) return DEFAULT_FIRST_NAME_LABEL;
16+
if ( id === LAST_NAME_ID ) return DEFAULT_LAST_NAME_LABEL;
17+
return DEFAULT_NAME_LABEL;
18+
};
19+
20+
/**
21+
* Sync the nested label text with the Name field's variation id when users transform
22+
* between known variations (first-name/last-name).
23+
*
24+
* @param {object} params - Parameters.
25+
* @param {string} params.clientId - Block clientId for the Name field
26+
* @param {string} params.id - Current variation id (e.g., 'first-name' | 'last-name')
27+
*/
28+
export default function useNameLabelSync( { clientId, id } ) {
29+
const prevIdRef = useRef( id );
30+
const { updateBlockAttributes } = useDispatch( blockEditorStore );
31+
32+
const labelClientId = useSelect(
33+
select => {
34+
const block = select( blockEditorStore ).getBlock( clientId );
35+
const labelBlock = block?.innerBlocks?.find( b => b.name === 'jetpack/label' );
36+
return labelBlock?.clientId;
37+
},
38+
[ clientId ]
39+
);
40+
41+
const currentLabel = useSelect(
42+
select => {
43+
return labelClientId
44+
? select( blockEditorStore ).getBlockAttributes( labelClientId )?.label
45+
: undefined;
46+
},
47+
[ labelClientId ]
48+
);
49+
50+
useEffect( () => {
51+
const newId = id;
52+
const prevId = prevIdRef.current;
53+
54+
if ( ! labelClientId ) {
55+
prevIdRef.current = newId;
56+
return;
57+
}
58+
59+
// Handle transforms between known variations.
60+
if ( isKnownId( newId ) && newId !== prevId ) {
61+
const nextDefault = getDefaultLabelForId( newId );
62+
// Ensure the parent block id matches the variation id.
63+
if ( newId ) {
64+
updateBlockAttributes( clientId, { id: newId } );
65+
}
66+
// Always set the label to the default for the selected variation.
67+
updateBlockAttributes( labelClientId, { label: nextDefault } );
68+
}
69+
70+
// Handle transforms from a known variation back to the base Name (no id).
71+
const becameBase = isKnownId( prevId ) && ( newId === undefined || newId === '' );
72+
if ( becameBase ) {
73+
// Clear the parent block id when returning to base.
74+
updateBlockAttributes( clientId, { id: '' } );
75+
// Always set the label back to the base default.
76+
updateBlockAttributes( labelClientId, { label: DEFAULT_NAME_LABEL } );
77+
}
78+
79+
prevIdRef.current = newId;
80+
}, [ id, clientId, labelClientId, currentLabel, updateBlockAttributes ] );
81+
}

projects/packages/forms/src/blocks/field-name/index.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,30 @@ import { Path } from '@wordpress/components';
22
import { __ } from '@wordpress/i18n';
33
import renderMaterialIcon from '../shared/components/render-material-icon';
44
import defaultSettings from '../shared/settings';
5+
import transformsSource from '../shared/settings/transforms';
56
import { getIconColor } from '../shared/util/block-icons';
67
import deprecated from './deprecated';
78
import edit from './edit';
89
import save from './save';
10+
import variations from './variations';
911

1012
const name = 'field-name';
13+
14+
// We define variations for Name, First name, and Last name.
15+
// For this block only, override transforms to remove the generic self-transform
16+
// to `jetpack/field-name`, so the Transform menu doesn’t show duplicate “Name”.
17+
// Other blocks still use the shared transforms (and can transform to Name/its variations).
18+
function notSelfNameTransform( transform ) {
19+
return ! (
20+
Array.isArray( transform.blocks ) && transform.blocks.includes( 'jetpack/field-name' )
21+
);
22+
}
23+
24+
const transforms = {
25+
...transformsSource,
26+
to: transformsSource.to.filter( notSelfNameTransform ),
27+
};
28+
1129
const settings = {
1230
...defaultSettings,
1331
title: __( 'Name field', 'jetpack-forms' ),
@@ -18,6 +36,8 @@ const settings = {
1836
<Path d="M8.25 11.5C9.63071 11.5 10.75 10.3807 10.75 9C10.75 7.61929 9.63071 6.5 8.25 6.5C6.86929 6.5 5.75 7.61929 5.75 9C5.75 10.3807 6.86929 11.5 8.25 11.5ZM8.25 10C8.80228 10 9.25 9.55228 9.25 9C9.25 8.44772 8.80228 8 8.25 8C7.69772 8 7.25 8.44772 7.25 9C7.25 9.55228 7.69772 10 8.25 10ZM13 15.5V17.5H11.5V15.5C11.5 14.8096 10.9404 14.25 10.25 14.25H6.25C5.55964 14.25 5 14.8096 5 15.5V17.5H3.5V15.5C3.5 13.9812 4.73122 12.75 6.25 12.75H10.25C11.7688 12.75 13 13.9812 13 15.5ZM20.5 11H14.5V9.5H20.5V11ZM20.5 14.5H14.5V13H20.5V14.5Z" />
1937
),
2038
},
39+
transforms,
40+
variations,
2141
edit,
2242
deprecated,
2343
save,
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Path } from '@wordpress/components';
2+
import { __ } from '@wordpress/i18n';
3+
import renderMaterialIcon from '../shared/components/render-material-icon';
4+
import { getIconColor } from '../shared/util/block-icons';
5+
6+
const icon = {
7+
foreground: getIconColor(),
8+
src: renderMaterialIcon(
9+
<Path d="M8.25 11.5C9.63071 11.5 10.75 10.3807 10.75 9C10.75 7.61929 9.63071 6.5 8.25 6.5C6.86929 6.5 5.75 7.61929 5.75 9C5.75 10.3807 6.86929 11.5 8.25 11.5ZM8.25 10C8.80228 10 9.25 9.55228 9.25 9C9.25 8.44772 8.80228 8 8.25 8C7.69772 8 7.25 8.44772 7.25 9C7.25 9.55228 7.69772 10 8.25 10ZM13 15.5V17.5H11.5V15.5C11.5 14.8096 10.9404 14.25 10.25 14.25H6.25C5.55964 14.25 5 14.8096 5 15.5V17.5H3.5V15.5C3.5 13.9812 4.73122 12.75 6.25 12.75H10.25C11.7688 12.75 13 13.9812 13 15.5ZM20.5 11H14.5V9.5H20.5V11ZM20.5 14.5H14.5V13H20.5V14.5Z" />
10+
),
11+
};
12+
13+
export const FIRST_NAME_ID = 'first-name';
14+
export const LAST_NAME_ID = 'last-name';
15+
16+
export const DEFAULT_FIRST_NAME_LABEL = __( 'First name', 'jetpack-forms' );
17+
export const DEFAULT_LAST_NAME_LABEL = __( 'Last name', 'jetpack-forms' );
18+
export const DEFAULT_NAME_LABEL = __( 'Name', 'jetpack-forms' );
19+
20+
const variations = [
21+
{
22+
name: 'name',
23+
title: DEFAULT_NAME_LABEL,
24+
description: __( 'Collect the visitor’s name.', 'jetpack-forms' ),
25+
icon,
26+
scope: [ 'transform' ],
27+
attributes: {
28+
id: '',
29+
},
30+
innerBlocks: [
31+
[ 'jetpack/label', { label: DEFAULT_NAME_LABEL } ],
32+
[ 'jetpack/input', { type: 'text' } ],
33+
],
34+
},
35+
{
36+
name: FIRST_NAME_ID,
37+
title: DEFAULT_FIRST_NAME_LABEL,
38+
description: __( 'Collect the visitor’s first name.', 'jetpack-forms' ),
39+
icon,
40+
scope: [ 'inserter', 'transform' ],
41+
isActive: [ 'id' ],
42+
attributes: {
43+
id: FIRST_NAME_ID,
44+
},
45+
innerBlocks: [
46+
[ 'jetpack/label', { label: DEFAULT_FIRST_NAME_LABEL } ],
47+
[ 'jetpack/input', { type: 'text' } ],
48+
],
49+
},
50+
{
51+
name: LAST_NAME_ID,
52+
title: DEFAULT_LAST_NAME_LABEL,
53+
description: __( 'Collect the visitor’s last name.', 'jetpack-forms' ),
54+
icon,
55+
scope: [ 'inserter', 'transform' ],
56+
isActive: [ 'id' ],
57+
attributes: {
58+
id: LAST_NAME_ID,
59+
},
60+
innerBlocks: [
61+
[ 'jetpack/label', { label: DEFAULT_LAST_NAME_LABEL } ],
62+
[ 'jetpack/input', { type: 'text' } ],
63+
],
64+
},
65+
];
66+
67+
export default variations;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: enhancement
3+
4+
Forms: add first and last name variations.

0 commit comments

Comments
 (0)