initial commit
This commit is contained in:
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import { HOME_URL } from '@woocommerce/settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './editor.scss';
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* Component displaying a product search form.
|
||||
*
|
||||
* @param {Object} props Incoming props for the component.
|
||||
* @param {Object} props.attributes Incoming block attributes.
|
||||
* @param {string} props.attributes.label
|
||||
* @param {string} props.attributes.placeholder
|
||||
* @param {string} props.attributes.formId
|
||||
* @param {string} props.attributes.className
|
||||
* @param {boolean} props.attributes.hasLabel
|
||||
* @param {string} props.attributes.align
|
||||
*/
|
||||
const ProductSearchBlock = ( {
|
||||
attributes: { label, placeholder, formId, className, hasLabel, align },
|
||||
} ) => {
|
||||
const classes = classnames(
|
||||
'wc-block-product-search',
|
||||
align ? 'align' + align : '',
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={ classes }>
|
||||
<form role="search" method="get" action={ HOME_URL }>
|
||||
<label
|
||||
htmlFor={ formId }
|
||||
className={
|
||||
hasLabel
|
||||
? 'wc-block-product-search__label'
|
||||
: 'wc-block-product-search__label screen-reader-text'
|
||||
}
|
||||
>
|
||||
{ label }
|
||||
</label>
|
||||
<div className="wc-block-product-search__fields">
|
||||
<input
|
||||
type="search"
|
||||
id={ formId }
|
||||
className="wc-block-product-search__field"
|
||||
placeholder={ placeholder }
|
||||
name="s"
|
||||
/>
|
||||
<input type="hidden" name="post_type" value="product" />
|
||||
<button
|
||||
type="submit"
|
||||
className="wc-block-product-search__button"
|
||||
label={ __( 'Search', 'woocommerce' ) }
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
focusable="false"
|
||||
className="dashicon dashicons-arrow-right-alt2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M6 15l5-5-5-5 1-2 7 7-7 7z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ProductSearchBlock.propTypes = {
|
||||
/**
|
||||
* The attributes for this block.
|
||||
*/
|
||||
attributes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ProductSearchBlock;
|
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import { InspectorControls, PlainText } from '@wordpress/block-editor';
|
||||
import { PanelBody, ToggleControl, TextControl } from '@wordpress/components';
|
||||
import { withInstanceId } from '@wordpress/compose';
|
||||
import { useEffect } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './editor.scss';
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* Component displaying a product search form.
|
||||
*
|
||||
* @param {Object} props Incoming props for the component.
|
||||
* @param {Object} props.attributes Incoming block attributes.
|
||||
* @param {string} props.attributes.label
|
||||
* @param {string} props.attributes.placeholder
|
||||
* @param {string} props.attributes.formId
|
||||
* @param {string} props.attributes.className
|
||||
* @param {boolean} props.attributes.hasLabel
|
||||
* @param {string} props.attributes.align
|
||||
* @param {string} props.instanceId
|
||||
* @param {function(any):any} props.setAttributes Setter for block attributes.
|
||||
*/
|
||||
const Edit = ( {
|
||||
attributes: { label, placeholder, formId, className, hasLabel, align },
|
||||
instanceId,
|
||||
setAttributes,
|
||||
} ) => {
|
||||
const classes = classnames(
|
||||
'wc-block-product-search',
|
||||
align ? 'align' + align : '',
|
||||
className
|
||||
);
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! formId ) {
|
||||
setAttributes( {
|
||||
formId: `wc-block-product-search-${ instanceId }`,
|
||||
} );
|
||||
}
|
||||
}, [ formId, setAttributes, instanceId ] );
|
||||
|
||||
return (
|
||||
<>
|
||||
<InspectorControls key="inspector">
|
||||
<PanelBody
|
||||
title={ __( 'Content', 'woocommerce' ) }
|
||||
initialOpen
|
||||
>
|
||||
<ToggleControl
|
||||
label={ __(
|
||||
'Show search field label',
|
||||
'woocommerce'
|
||||
) }
|
||||
help={
|
||||
hasLabel
|
||||
? __(
|
||||
'Label is visible.',
|
||||
'woocommerce'
|
||||
)
|
||||
: __(
|
||||
'Label is hidden.',
|
||||
'woocommerce'
|
||||
)
|
||||
}
|
||||
checked={ hasLabel }
|
||||
onChange={ () =>
|
||||
setAttributes( { hasLabel: ! hasLabel } )
|
||||
}
|
||||
/>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<div className={ classes }>
|
||||
{ !! hasLabel && (
|
||||
<PlainText
|
||||
className="wc-block-product-search__label"
|
||||
value={ label }
|
||||
onChange={ ( value ) =>
|
||||
setAttributes( { label: value } )
|
||||
}
|
||||
/>
|
||||
) }
|
||||
<div className="wc-block-product-search__fields">
|
||||
<TextControl
|
||||
className="wc-block-product-search__field input-control"
|
||||
value={ placeholder }
|
||||
onChange={ ( value ) =>
|
||||
setAttributes( { placeholder: value } )
|
||||
}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="wc-block-product-search__button"
|
||||
label={ __( 'Search', 'woocommerce' ) }
|
||||
onClick={ ( e ) => e.preventDefault() }
|
||||
tabIndex="-1"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
focusable="false"
|
||||
className="dashicon dashicons-arrow-right-alt2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M6 15l5-5-5-5 1-2 7 7-7 7z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Edit.propTypes = {
|
||||
/**
|
||||
* The attributes for this block.
|
||||
*/
|
||||
attributes: PropTypes.object.isRequired,
|
||||
/**
|
||||
* A unique ID for identifying the label for the select dropdown.
|
||||
*/
|
||||
instanceId: PropTypes.number,
|
||||
/**
|
||||
* Whether it's in the editor or frontend display.
|
||||
*/
|
||||
isEditor: PropTypes.bool,
|
||||
/**
|
||||
* A callback to update attributes.
|
||||
*/
|
||||
setAttributes: PropTypes.func,
|
||||
};
|
||||
|
||||
export default withInstanceId( Edit );
|
@ -0,0 +1,10 @@
|
||||
.wc-block-product-search__field.input-control {
|
||||
color: #828b96 !important;
|
||||
}
|
||||
.wc-block-product-search {
|
||||
.wc-block-product-search__fields {
|
||||
.block-editor-rich-text {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { createBlock, registerBlockType } from '@wordpress/blocks';
|
||||
import { Icon, search } from '@woocommerce/icons';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import './editor.scss';
|
||||
import Block from './block.js';
|
||||
import edit from './edit.js';
|
||||
|
||||
const attributes = {
|
||||
/**
|
||||
* Whether to show the field label.
|
||||
*/
|
||||
hasLabel: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
},
|
||||
|
||||
/**
|
||||
* Search field label.
|
||||
*/
|
||||
label: {
|
||||
type: 'string',
|
||||
default: __( 'Search', 'woocommerce' ),
|
||||
},
|
||||
|
||||
/**
|
||||
* Search field placeholder.
|
||||
*/
|
||||
placeholder: {
|
||||
type: 'string',
|
||||
default: __( 'Search products…', 'woocommerce' ),
|
||||
},
|
||||
|
||||
/**
|
||||
* Store the instance ID.
|
||||
*/
|
||||
formId: {
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
};
|
||||
|
||||
registerBlockType( 'woocommerce/product-search', {
|
||||
title: __( 'Product Search', 'woocommerce' ),
|
||||
icon: {
|
||||
src: <Icon srcElement={ search } />,
|
||||
foreground: '#96588a',
|
||||
},
|
||||
category: 'woocommerce',
|
||||
keywords: [ __( 'WooCommerce', 'woocommerce' ) ],
|
||||
description: __(
|
||||
'A search box to allow customers to search for products by keyword.',
|
||||
'woocommerce'
|
||||
),
|
||||
supports: {
|
||||
align: [ 'wide', 'full' ],
|
||||
},
|
||||
example: {
|
||||
attributes: {
|
||||
hasLabel: true,
|
||||
},
|
||||
},
|
||||
attributes,
|
||||
transforms: {
|
||||
from: [
|
||||
{
|
||||
type: 'block',
|
||||
blocks: [ 'core/legacy-widget' ],
|
||||
// We can't transform if raw instance isn't shown in the REST API.
|
||||
isMatch: ( { idBase, instance } ) =>
|
||||
idBase === 'woocommerce_product_search' && !! instance?.raw,
|
||||
transform: ( { instance } ) =>
|
||||
createBlock( 'woocommerce/product-search', {
|
||||
label:
|
||||
instance.raw.title === ''
|
||||
? __( 'Search', 'woocommerce' )
|
||||
: instance.raw.title,
|
||||
} ),
|
||||
},
|
||||
],
|
||||
},
|
||||
deprecated: [
|
||||
{
|
||||
attributes,
|
||||
save( props ) {
|
||||
return (
|
||||
<div>
|
||||
<Block { ...props } />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
edit,
|
||||
save() {
|
||||
return null;
|
||||
},
|
||||
} );
|
@ -0,0 +1,38 @@
|
||||
.wc-block-product-search {
|
||||
.wc-block-product-search__fields {
|
||||
display: flex;
|
||||
}
|
||||
.wc-block-product-search__field {
|
||||
padding: 6px 8px;
|
||||
line-height: 1.8;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.wc-block-product-search__button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 0 0 6px;
|
||||
cursor: pointer;
|
||||
padding: 0 0.5em;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
svg {
|
||||
fill: currentColor;
|
||||
outline: none;
|
||||
.rtl & {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
color: currentColor;
|
||||
}
|
||||
&:disabled,
|
||||
&[aria-disabled="true"] {
|
||||
cursor: default;
|
||||
opacity: 0.3;
|
||||
}
|
||||
&[aria-disabled="true"]:focus,
|
||||
&:disabled:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user