-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'trunk' into ci/update-concurrency-group-for-pr-label
- Loading branch information
Showing
61 changed files
with
1,797 additions
and
645 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 4 additions & 0 deletions
4
packages/js/product-editor/changelog/update-add-field-textarea-block-doc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: patch | ||
Type: add | ||
|
||
[Product Block Editor]: document woocommerce/product-text-area-field field block |
4 changes: 4 additions & 0 deletions
4
packages/js/product-editor/changelog/update-introduce-product-entity-source-handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: patch | ||
Type: add | ||
|
||
[Product Block Editor]: introduce `woocommerce/entity-product` binding source handler |
89 changes: 89 additions & 0 deletions
89
packages/js/product-editor/src/bindings-sources/entity/product/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { useEntityProp } from '@wordpress/core-data'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { useCallback } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import type { | ||
BindingSourceHandlerProps, | ||
BindingUseSourceProps, | ||
BlockProps, | ||
} from '../../../bindings/types'; | ||
import type { WooCommerceEntityProductSourceArgs } from './types'; | ||
|
||
/** | ||
* React custom hook to bind a source to a block. | ||
* | ||
* @param {BlockProps} blockProps - The block props. | ||
* @param {WooCommerceEntityProductSourceArgs} sourceArgs - The source args. | ||
* @return {BindingUseSourceProps} The source value and setter. | ||
*/ | ||
const useSource = ( | ||
blockProps: BlockProps, | ||
sourceArgs: WooCommerceEntityProductSourceArgs | ||
): BindingUseSourceProps => { | ||
if ( typeof sourceArgs === 'undefined' ) { | ||
throw new Error( 'The "args" argument is required.' ); | ||
} | ||
|
||
if ( ! sourceArgs?.prop ) { | ||
throw new Error( 'The "prop" argument is required.' ); | ||
} | ||
|
||
const { prop, id } = sourceArgs; | ||
|
||
const [ value, updateValue ] = useEntityProp( | ||
'postType', | ||
'product', | ||
prop, | ||
id | ||
); | ||
|
||
const updateValueHandler = useCallback( | ||
( nextEntityPropValue: string ) => { | ||
updateValue( nextEntityPropValue ); | ||
}, | ||
[ updateValue ] | ||
); | ||
|
||
return { | ||
placeholder: null, | ||
value, | ||
updateValue: updateValueHandler, | ||
}; | ||
}; | ||
|
||
/* | ||
* Create the product-entity | ||
* block binding source handler. | ||
* | ||
* source ID: `woocommerce/entity-product` | ||
* args: | ||
* - prop: The name of the entity property to bind. | ||
* | ||
* In the example below, | ||
* the `content` attribute is bound to the `short_description` property. | ||
* `product` entity and `postType` kind are defined by the context. | ||
* | ||
* ``` | ||
* metadata: { | ||
* bindings: { | ||
* content: { | ||
* source: 'woocommerce/entity-product', | ||
* args: { | ||
* prop: 'short_description', | ||
* }, | ||
* }, | ||
* }, | ||
* ``` | ||
*/ | ||
export default { | ||
name: 'woocommerce/entity-product', | ||
label: __( 'Product Entity', 'woocommerce' ), | ||
useSource, | ||
lockAttributesEditing: true, | ||
} as BindingSourceHandlerProps< WooCommerceEntityProductSourceArgs >; |
74 changes: 74 additions & 0 deletions
74
packages/js/product-editor/src/bindings-sources/entity/product/test/test-use-source.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import productEntitySourceHandler from '..'; | ||
|
||
let mockState; | ||
|
||
jest.mock( '@wordpress/core-data', () => ( { | ||
useEntityProp: jest.fn().mockImplementation( ( kind, name, key ) => { | ||
return mockState?.[ key ] ? mockState[ key ] : []; | ||
} ), | ||
} ) ); | ||
|
||
describe( 'useSource', () => { | ||
let blockInstance; | ||
|
||
mockState = { | ||
external_property_name: [ 'External source property Value' ], | ||
}; | ||
|
||
beforeEach( () => { | ||
blockInstance = { | ||
name: 'woocommerce/block-with-entity', | ||
attributes: { | ||
prop: 'value', | ||
}, | ||
className: 'wp-block-woocommerce-block-with-entity', | ||
context: {}, | ||
clientId: '<client-id-instance>', | ||
isSelected: false, | ||
setAttributes: jest.fn(), | ||
}; | ||
} ); | ||
|
||
it( 'throws an error if sourceArgs is undefined', () => { | ||
const { useSource } = productEntitySourceHandler; | ||
const { result } = renderHook( () => | ||
useSource( blockInstance, undefined ) | ||
); | ||
|
||
expect( result.error ).toEqual( | ||
new Error( 'The "args" argument is required.' ) | ||
); | ||
} ); | ||
|
||
it( 'throws an error if prop in sourceArgs is undefined', () => { | ||
const { useSource } = productEntitySourceHandler; | ||
const { result } = renderHook( () => | ||
useSource( blockInstance, { prop: undefined } ) | ||
); | ||
|
||
expect( result.error ).toEqual( | ||
new Error( 'The "prop" argument is required.' ) | ||
); | ||
} ); | ||
|
||
it( 'return the value of the product entity property', () => { | ||
const { useSource } = productEntitySourceHandler; | ||
const { result } = renderHook( () => | ||
useSource( blockInstance, { | ||
prop: 'external_property_name', | ||
} ) | ||
); | ||
|
||
expect( result.current.value ).toEqual( | ||
'External source property Value' | ||
); | ||
} ); | ||
} ); |
11 changes: 11 additions & 0 deletions
11
packages/js/product-editor/src/bindings-sources/entity/product/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export type WooCommerceEntityProductSourceArgs = { | ||
/* | ||
* The name of the entity property to bind. | ||
*/ | ||
prop: string; | ||
|
||
/* | ||
* The ID of the entity to bind. | ||
*/ | ||
id?: string; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import type { BlockEditProps, BlockAttributes } from '@wordpress/blocks'; | ||
import { | ||
// @ts-expect-error no exported member. | ||
type ComponentType, | ||
} from '@wordpress/element'; | ||
|
||
export type AttributeBindingProps = { | ||
source: string; | ||
args: { prop: string }; | ||
}; | ||
|
||
export type MetadataBindingsProps = Record< string, AttributeBindingProps >; | ||
|
||
export type BoundBlockAttributes = BlockAttributes & { | ||
metadata?: { | ||
bindings: MetadataBindingsProps; | ||
}; | ||
}; | ||
|
||
export type BoundBlockEditInstance = CoreBlockEditProps< BoundBlockAttributes >; | ||
export type BoundBlockEditComponent = ComponentType< BoundBlockEditInstance >; | ||
|
||
/* | ||
* Block Binding API | ||
*/ | ||
export type BindingUseSourceProps = { | ||
/* | ||
* The placeholder value for the source. | ||
*/ | ||
placeholder: string | null; | ||
/* | ||
* The value of the source. | ||
*/ | ||
value: any; // eslint-disable-line @typescript-eslint/no-explicit-any | ||
/* | ||
* Callback function to set the source value. | ||
*/ | ||
updateValue: ( newValue: any ) => void; // eslint-disable-line @typescript-eslint/no-explicit-any | ||
}; | ||
|
||
export interface BindingSourceHandlerProps< T > { | ||
/* | ||
* The name of the binding source handler. | ||
*/ | ||
name: string; | ||
|
||
/* | ||
* The human-readable label for the binding source handler. | ||
*/ | ||
label: string; | ||
|
||
/* | ||
* React custom hook to bind a source to a block. | ||
*/ | ||
useSource: ( | ||
blockProps: CoreBlockEditProps< BlockAttributes >, | ||
sourceArgs: T | ||
) => BindingUseSourceProps; | ||
|
||
lockAttributesEditing: boolean; | ||
} | ||
|
||
/* | ||
* Core Types | ||
*/ | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export interface CoreBlockEditProps< T extends Record< string, any > > | ||
extends BlockEditProps< T > { | ||
readonly name: string; | ||
readonly context: Record< string, string >; | ||
} | ||
|
||
export type BlockProps = CoreBlockEditProps< BlockAttributes >; |
102 changes: 102 additions & 0 deletions
102
packages/js/product-editor/src/blocks/generic/text-area/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
# woocommerce/product-text-area-field | ||
|
||
A reusable text area field for the product editor, enhancing product data input with a multiline text area suitable for detailed information, descriptions, and more. | ||
|
||
## Attributes | ||
|
||
### label | ||
|
||
- **Type:** `String` | ||
- **Required:** `Yes` | ||
|
||
The label appears above the textarea field. | ||
|
||
### property | ||
|
||
- **Type:** `String` | ||
- **Required:** `Yes` | ||
|
||
The product entity property where the value is stored. | ||
|
||
### help | ||
|
||
- **Type:** `String` | ||
- **Required:** `No` | ||
|
||
Help text that appears below the field, providing additional guidance to the user. | ||
|
||
### required | ||
|
||
- **Type:** `Boolean`|`String` | ||
- **Required:** `No` | ||
|
||
Indicates that the field is required. | ||
|
||
### tooltip | ||
|
||
- **Type:** `String` | ||
- **Required:** `No` | ||
|
||
Shows a tooltip next to the label with additional information when provided. | ||
|
||
### placeholder | ||
|
||
- **Type:** `String` | ||
- **Required:** `No` | ||
|
||
Placeholder text that appears within the textarea when it is empty. | ||
|
||
### mode | ||
|
||
- **Type:** `String` | ||
- **Required:** `No` | ||
- **Default:** `'rich-text'` | ||
|
||
Defines the editing mode of the textarea. Options are `'plain-text'` or `'rich-text'`. | ||
|
||
### allowedFormats | ||
|
||
- **Type:** `Array` | ||
- **Required:** `No` | ||
- **Default:** `['core/bold', 'core/italic', 'core/link', etc.]` | ||
|
||
Specifies the allowed formatting options when in 'rich-text' mode. | ||
|
||
### direction | ||
|
||
- **Type:** `String` | ||
- **Required:** `No` | ||
- **Default:** `'ltr'` | ||
- **Options:** `'ltr'`, `'rtl'` | ||
|
||
The text directionality for the textarea, supporting left-to-right (ltr) or right-to-left (rtl) content. | ||
|
||
### align | ||
|
||
- **Type:** `String` | ||
- **Required:** `No` | ||
- **Options:** `'left'`, `'center'`, `'right'`, `'justify'` | ||
|
||
Aligns the text within the text area field according to the specified value. | ||
|
||
## Usage | ||
|
||
Here's a snippet that adds a text area field to the product editor, similar to the screenshot: | ||
|
||
```php | ||
$section->add_block( | ||
array( | ||
'id' => 'example-text-area-meta', | ||
'blockName' => 'woocommerce/product-text-area-field', | ||
'order' => 15, | ||
'attributes' => array( | ||
'label' => 'Detailed Description', | ||
'property' => 'short_description', | ||
'placeholder' => 'Enter a short product information here', | ||
'required' => false, | ||
'help' => 'Add any additional details or information that customers should know.', | ||
'mode' => 'rich-text', | ||
'allowedFormats' => [ 'core/bold', 'core/italic', 'core/link' ], | ||
), | ||
) | ||
); |
Oops, something went wrong.