Skip to content

Commit

Permalink
Refactor Single Choice field
Browse files Browse the repository at this point in the history
  • Loading branch information
monsieur-z committed Sep 12, 2024
1 parent f2eca3a commit 9e64f38
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 397 deletions.
115 changes: 9 additions & 106 deletions projects/packages/forms/src/blocks/contact-form/child-blocks.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
import { createBlock } from '@wordpress/blocks';
import { Path } from '@wordpress/components';
import { Fragment } from '@wordpress/element';
Expand All @@ -9,10 +8,10 @@ import JetpackFieldCheckbox from './components/jetpack-field-checkbox';
import JetpackFieldConsent from './components/jetpack-field-consent';
import JetpackDatePicker from './components/jetpack-field-datepicker';
import JetpackDropdown from './components/jetpack-field-dropdown';
import JetpackFieldMultiple from './components/jetpack-field-multiple';
import JetpackFieldMultipleChoice from './components/jetpack-field-multiple-choice';
import JetpackFieldMultipleChoiceItem from './components/jetpack-field-multiple-choice/item';
import { JetpackFieldOptionEdit } from './components/jetpack-field-option';
import JetpackFieldSingleChoice from './components/jetpack-field-single-choice';
import JetpackFieldSingleChoiceItem from './components/jetpack-field-single-choice/item';
import JetpackFieldTextarea from './components/jetpack-field-textarea';
import { getIconColor } from './util/block-icons';
import { useFormWrapper } from './util/form';
Expand Down Expand Up @@ -233,26 +232,6 @@ const FieldDefaults = {
example: {},
};

const OptionFieldDefaults = {
apiVersion: 3,
category: 'contact-form',
edit: JetpackFieldOptionEdit,
attributes: {
label: {
type: 'string',
},
fieldType: {
enum: [ 'checkbox', 'radio' ],
default: 'checkbox',
},
},
supports: {
reusable: false,
html: false,
splitting: true,
},
};

const multiFieldV1 = fieldType => ( {
attributes: {
...FieldDefaults.attributes,
Expand Down Expand Up @@ -299,27 +278,6 @@ const editField = type => props => {
);
};

const editMultiField = type => props => {
useFormWrapper( props );

return (
<JetpackFieldMultiple
className={ props.className }
clientId={ props.clientId }
label={ getFieldLabel( props.attributes, props.name ) }
required={ props.attributes.required }
requiredText={ props.attributes.requiredText }
options={ props.attributes.options }
setAttributes={ props.setAttributes }
type={ type }
isSelected={ props.isSelected }
id={ props.attributes.id }
width={ props.attributes.width }
attributes={ props.attributes }
/>
);
};

const EditTextarea = props => {
useFormWrapper( props );

Expand Down Expand Up @@ -631,76 +589,21 @@ export const childBlocks = [
},
},
{
name: 'field-option-radio',
settings: {
...OptionFieldDefaults,
parent: [ 'jetpack/field-radio' ],
title: __( 'Single Choice Option', 'jetpack-forms' ),
icon: renderMaterialIcon(
<Path
d="M7.5 13.5C6.67157 13.5 6 12.8284 6 12C6 11.1716 6.67157 10.5 7.5 10.5C8.32843 10.5 9 11.1716 9 12C9 12.8284 8.32843 13.5 7.5 13.5ZM4.5 12C4.5 13.6569 5.84315 15 7.5 15C9.15685 15 10.5 13.6569 10.5 12C10.5 10.3431 9.15685 9 7.5 9C5.84315 9 4.5 10.3431 4.5 12ZM12.5 12.75H20.5V11.25H12.5V12.75Z"
fill={ getIconColor() }
/>
),
},
name: JetpackFieldSingleChoice.name,
settings: mergeSettings( FieldDefaults, {
...JetpackFieldSingleChoice.settings,
deprecated: [ multiFieldV1( 'radio' ) ],
} ),
},
JetpackFieldSingleChoiceItem,
{
name: JetpackFieldMultipleChoice.name,
settings: mergeSettings( FieldDefaults, {
...JetpackFieldMultipleChoice.settings,
deprecated: [ multiFieldV1( 'checkbox' ) ],
} ),
},
{
name: JetpackFieldMultipleChoiceItem.name,
settings: mergeSettings( OptionFieldDefaults, JetpackFieldMultipleChoiceItem.settings ),
},
{
name: 'field-radio',
settings: {
...FieldDefaults,
title: __( 'Single Choice (Radio)', 'jetpack-forms' ),
keywords: [
__( 'Choose', 'jetpack-forms' ),
__( 'Select', 'jetpack-forms' ),
__( 'Option', 'jetpack-forms' ),
],
description: __(
'Offer users a list of choices, and allow them to select a single option.',
'jetpack-forms'
),
icon: renderMaterialIcon(
<Fragment>
<Path
fill={ getIconColor() }
d="M4 7.75C4 9.40685 5.34315 10.75 7 10.75C8.65685 10.75 10 9.40685 10 7.75C10 6.09315 8.65685 4.75 7 4.75C5.34315 4.75 4 6.09315 4 7.75ZM20 8.5H12V7H20V8.5ZM20 17H12V15.5H20V17ZM7 17.75C6.17157 17.75 5.5 17.0784 5.5 16.25C5.5 15.4216 6.17157 14.75 7 14.75C7.82843 14.75 8.5 15.4216 8.5 16.25C8.5 17.0784 7.82843 17.75 7 17.75ZM4 16.25C4 17.9069 5.34315 19.25 7 19.25C8.65685 19.25 10 17.9069 10 16.25C10 14.5931 8.65685 13.25 7 13.25C5.34315 13.25 4 14.5931 4 16.25Z"
/>
</Fragment>
),
edit: editMultiField( 'radio' ),
save: () => {
const blockProps = useBlockProps.save();

return (
<div { ...blockProps }>
<InnerBlocks.Content />
</div>
);
},
attributes: {
...FieldDefaults.attributes,
label: {
type: 'string',
default: 'Choose one option',
},
},
styles: [
{ name: 'list', label: 'List', isDefault: true },
{ name: 'button', label: 'Button' },
],
deprecated: [ multiFieldV1( 'radio' ) ],
},
},
JetpackFieldMultipleChoiceItem,
{
name: 'field-select',
settings: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,40 @@
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
import { compose, withInstanceId } from '@wordpress/compose';
import { useSelect } from '@wordpress/data';
import clsx from 'clsx';
import { useFormStyle } from '../util/form';
import { withSharedFieldAttributes } from '../util/with-shared-field-attributes';
import JetpackFieldControls from './jetpack-field-controls';
import JetpackFieldLabel from './jetpack-field-label';
import { useJetpackFieldStyles } from './use-jetpack-field-styles';
import { useFormStyle, useFormWrapper } from '../../util/form';
import getFieldLabel from '../../util/get-field-label';
import { withSharedFieldAttributes } from '../../util/with-shared-field-attributes';
import JetpackFieldControls from '../jetpack-field-controls';
import JetpackFieldLabel from '../jetpack-field-label';
import { useJetpackFieldStyles } from '../use-jetpack-field-styles';

const ALLOWED_BLOCKS = [ 'jetpack/field-option' ];
const JetpackFieldChoiceEdit = props => {
const { name, className, clientId, instanceId, setAttributes, isSelected, attributes, type } =
props;
const { required, requiredText, options, id, width } = attributes;

function JetpackFieldMultiple( props ) {
const {
className,
clientId,
id,
type,
instanceId,
required,
requiredText,
label,
setAttributes,
isSelected,
width,
options,
attributes,
} = props;
const formStyle = useFormStyle( clientId );
useFormWrapper( props );

const innerBlocks = useSelect(
select => {
return select( 'core/block-editor' ).getBlock( clientId ).innerBlocks;
},
select => select( 'core/block-editor' ).getBlock( clientId ).innerBlocks,
[ clientId ]
);

const classes = clsx( className, 'jetpack-field jetpack-field-multiple', {
'is-selected': isSelected,
'has-placeholder': ( options && options.length ) || innerBlocks.length,
} );

const formStyle = useFormStyle( clientId );
const { blockStyle } = useJetpackFieldStyles( attributes );
const blockProps = useBlockProps( {
id: `jetpack-field-multiple-${ instanceId }`,
className: classes,
style: blockStyle,
className: classes,
} );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
defaultBlock: `jetpack/field-option-${ type }`,
template: [ [ `jetpack/field-option-${ type }` ] ],
templateInsertUpdatesSelection: true,
} );

return (
Expand All @@ -53,19 +43,13 @@ function JetpackFieldMultiple( props ) {
<JetpackFieldLabel
required={ required }
requiredText={ requiredText }
label={ label }
label={ getFieldLabel( attributes, name ) }
setAttributes={ setAttributes }
isSelected={ isSelected }
attributes={ attributes }
style={ formStyle }
/>
<div className="jetpack-field-multiple__list">
<InnerBlocks
allowedBlocks={ ALLOWED_BLOCKS }
template={ [ [ `jetpack/field-option-${ type }`, {} ] ] }
templateInsertUpdatesSelection={ true }
/>
</div>
<ul { ...innerBlocksProps } className="jetpack-field-multiple__list" />
</div>

<JetpackFieldControls
Expand All @@ -81,7 +65,7 @@ function JetpackFieldMultiple( props ) {
/>
</>
);
}
};

export default compose(
withSharedFieldAttributes( [
Expand All @@ -100,4 +84,4 @@ export default compose(
'borderColor',
] ),
withInstanceId
)( JetpackFieldMultiple );
)( JetpackFieldChoiceEdit );
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { RichText, useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
import { createBlock } from '@wordpress/blocks';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import clsx from 'clsx';
import { first } from 'lodash';
import { supportsParagraphSplitting } from '../../../util/block-support';
import { useParentAttributes } from '../../../util/use-parent-attributes';
import { useJetpackFieldStyles } from '../../use-jetpack-field-styles';

export default function JetpackFieldChoiceItemEdit( {
attributes,
clientId,
name,
onReplace,
setAttributes,
type,
} ) {
const { removeBlock } = useDispatch( 'core/block-editor' );
const parentAttributes = useParentAttributes( clientId );
const { optionStyle } = useJetpackFieldStyles( parentAttributes );
const siblingsCount = useSelect(
select => {
const blockEditor = select( 'core/block-editor' );
const parentBlockId = first( blockEditor.getBlockParents( clientId, true ) );
return blockEditor.getBlock( parentBlockId ).innerBlocks.length;
},
[ clientId ]
);
const blockProps = useBlockProps();

const handleSplit = label => {
return createBlock( name, {
...attributes,
clientId: label && attributes.label.indexOf( label ) === 0 ? attributes.clientId : undefined,
label,
} );
};

const handleDelete = () => {
if ( siblingsCount <= 1 ) {
return;
}

removeBlock( clientId );
};

const supportsSplitting = supportsParagraphSplitting();
const classes = clsx( 'jetpack-field-option', `field-option-${ type }`, blockProps.className );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
className: classes,
style: optionStyle,
} );

return (
<>
<li { ...innerBlocksProps }>
<input type={ type } className="jetpack-option__type" tabIndex="-1" />
<RichText
identifier="label"
tagName="div"
className="wp-block"
value={ attributes.label }
placeholder={ __( 'Add option…', 'jetpack-forms' ) }
allowedFormats={ [] }
onChange={ newLabel => setAttributes( { label: newLabel } ) }
preserveWhiteSpace={ false }
withoutInteractiveFormatting
onRemove={ handleDelete }
onReplace={ onReplace }
{ ...( supportsSplitting ? {} : { onSplit: handleSplit } ) }
/>
</li>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default {
apiVersion: 3,
category: 'contact-form',
attributes: {
label: {
type: 'string',
},
fieldType: {
enum: [ 'checkbox', 'radio' ],
default: 'checkbox',
},
},
supports: {
reusable: false,
html: false,
splitting: true,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
styles: [
{ name: 'list', label: 'List', isDefault: true },
{ name: 'button', label: 'Button' },
],
};
Loading

0 comments on commit 9e64f38

Please sign in to comment.