Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/block-components/block-link/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Edit } from './edit'
* External dependencies
*/
import { Link } from '~stackable/components'
import { CustomAttributes } from '../custom-attributes'

export const BlockLink = () => {
return null
Expand All @@ -21,9 +22,11 @@ BlockLink.Content = props => {
if ( ! attributes.blockLinkUrl ) {
return null
}
const customAttributes = CustomAttributes.getCustomAttributes( attributes, 'blockLinkCustomAttributes' )

return (
<Link.Content
{ ...customAttributes }
className="stk-block-link stk--transparent-overlay"
href={ href || attributes.blockLinkUrl }
target={ attributes.blockLinkNewTab ? '_blank' : '' }
Expand Down
30 changes: 30 additions & 0 deletions src/block-components/custom-attributes/__test__/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { CustomAttributes } from '..'

describe( 'CustomAttributes.getCustomAttributes', () => {
it( 'resolves a named custom attribute list', () => {
const attributes = {
text: 'Product details',
linkCustomAttributes: [
[ 'aria-label', 'Open %text%' ],
[ 'data-link-id', 'details' ],
],
}

expect( CustomAttributes.getCustomAttributes( attributes, 'linkCustomAttributes' ) ).toEqual( {
'aria-label': 'Open Product details',
'data-link-id': 'details',
} )
} )

it( 'does not resolve the custom attribute list into itself', () => {
const attributes = {
linkCustomAttributes: [
[ 'data-value', '%linkCustomAttributes%' ],
],
}

expect( CustomAttributes.getCustomAttributes( attributes, 'linkCustomAttributes' ) ).toEqual( {
'data-value': '%linkCustomAttributes%',
} )
} )
} )
10 changes: 8 additions & 2 deletions src/block-components/custom-attributes/attributes.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
export const addAttributes = attrObject => {
export const addAttributes = ( attrObject, options = {} ) => {
const {
attrNameTemplate = '%s',
versionAdded = '3.0.0',
} = options

attrObject.add( {
attributes: {
customAttributes: {
type: 'array',
default: [],
},
},
versionAdded: '3.0.0',
attrNameTemplate,
versionAdded,
versionDeprecated: '',
} )
}
47 changes: 44 additions & 3 deletions src/block-components/custom-attributes/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,38 @@ import { useBlockAttributesContext, useBlockSetAttributesContext } from '~stacka
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n'
import { ExternalLink } from '@wordpress/components'
import { INVALID_HTML_ATTRIBUTES } from '.'

export const Edit = () => {
const customAttributes = useBlockAttributesContext( attributes => attributes.customAttributes )
const CustomAttributesHelp = ( { hasLink } ) => {
return <>
{ hasLink
? __( 'You can type in custom HTML attributes for this block or its link in the fields above. Examples:', i18n )
: __( 'You can type in custom HTML attributes for this block in the field above. Example:', i18n ) }
<br />
<code>data-id=&quot;my-title&quot;</code>
{ hasLink && <>
<br />
<code>aria-label=&quot;Learn more&quot;</code>
</> }
<br />
<ExternalLink
href="https://docs.wpstackable.com/article/461-how-to-use-custom-attributes?utm_source=inspector&utm_campaign=learnmore&utm_medium=gutenberg"
target="_docs"
>
{ __( 'Learn more about Custom Attributes', i18n ) }
</ExternalLink>
</>
}

export const Edit = props => {
const {
customAttributes,
linkCustomAttributes,
} = useBlockAttributesContext( attributes => ( {
customAttributes: attributes.customAttributes,
linkCustomAttributes: props.linkAttributeName ? attributes[ props.linkAttributeName ] : undefined,
} ) )
const setAttributes = useBlockSetAttributesContext()

return (
Expand All @@ -30,12 +58,25 @@ export const Edit = () => {
id="custom-attributes"
>
<CustomAttributesControl
label={ __( 'Custom Attributes', i18n ) }
label={ props.linkAttributeName ? __( 'Block Custom Attributes', i18n ) : __( 'Custom Attributes', i18n ) }
value={ customAttributes }
invalidHtmlAttributes={ INVALID_HTML_ATTRIBUTES }
onChange={ customAttributes => setAttributes( { customAttributes } ) }
help={ ! props.linkAttributeName && <CustomAttributesHelp hasLink={ false } /> }
/>
{ props.linkAttributeName && <CustomAttributesControl
label={ __( 'Link Custom Attributes', i18n ) }
value={ linkCustomAttributes }
invalidHtmlAttributes={ INVALID_HTML_ATTRIBUTES }
onChange={ linkCustomAttributes => setAttributes( { [ props.linkAttributeName ]: linkCustomAttributes } ) }
help={ <CustomAttributesHelp hasLink /> }
/>
}
</PanelAdvancedSettings>
</InspectorAdvancedControls>
)
}

Edit.defaultProps = {
linkAttributeName: '',
}
9 changes: 5 additions & 4 deletions src/block-components/custom-attributes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ CustomAttributes.addAttributes = addAttributes

// CustomAttributes.Style = Style

CustomAttributes.getCustomAttributes = attributes => {
if ( ! Array.isArray( attributes.customAttributes ) || attributes.customAttributes.length === 0 ) {
CustomAttributes.getCustomAttributes = ( attributes, attributeName = 'customAttributes' ) => {
if ( ! Array.isArray( attributes[ attributeName ] ) || attributes[ attributeName ].length === 0 ) {
return {}
}

const customAttributes = Object.fromEntries( attributes.customAttributes )
const customAttributes = Object.fromEntries( attributes[ attributeName ] )
const invalidBlockAttributes = [ ...INVALID_BLOCK_ATTRIBUTES, attributeName ]
Object.keys( customAttributes ).forEach( key => {
// Unescape the value, since we're storing them as escaped strings.
let value = unescape( customAttributes[ key ] )
Expand All @@ -44,7 +45,7 @@ CustomAttributes.getCustomAttributes = attributes => {
dynamicAttributeMatch.forEach( _match => {
const match = _match.substr( 1, _match.length - 2 )
if (
! INVALID_BLOCK_ATTRIBUTES.includes( match ) &&
! invalidBlockAttributes.includes( match ) &&
attributes.hasOwnProperty( match ) &&
! isUndefined( attributes[ match ] )
) {
Expand Down
13 changes: 11 additions & 2 deletions src/block-components/custom-attributes/readme.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
# Custom Attributes Block Component

Gives the ability to add your own custom attributes which will be placed on the block.
Gives the ability to add custom attributes to a block or its generated link.

## Usage

The custom attribute implementation is already handled by the Block Div Block Component
The block custom attribute implementation is already handled by the Block Div Block Component.
For a link, render the attributes with `CustomAttributes.getCustomAttributes( attributes, 'linkCustomAttributes' )` or its block-link equivalent.

### Adding inspector controls in `edit.js`

```
<CustomAttributes.InspectorControls />
```

For a block with a configurable link, pass the link attribute name to add a second field below the block attributes.

```
<CustomAttributes.InspectorControls linkAttributeName="linkCustomAttributes" />
```

### Adding attributes in `schema.js`

```
CustomAttributes.addAttributes( attrObject )
```

Link attributes are registered through `Link.addAttributes` or `BlockLink.addAttributes`.
7 changes: 7 additions & 0 deletions src/block-components/helpers/link/attributes.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { addAttributes as addCustomAttributes } from '../../custom-attributes/attributes'

export const linkAttributes = ( selector = 'a' ) => {
return {
hasLink: {
Expand Down Expand Up @@ -50,4 +52,9 @@ export const addLinkAttributes = ( attrObject, attrNameTemplate = '%s', selector
versionAdded: '3.0.0',
versionDeprecated: '',
} )

addCustomAttributes( attrObject, {
attrNameTemplate,
versionAdded: '3.20.1',
} )
}
4 changes: 3 additions & 1 deletion src/block-components/link/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import { addAttributes } from './attributes'
import { Edit } from './edit'
import { CustomAttributes } from '../custom-attributes'

/*+
* External dependencies
Expand Down Expand Up @@ -42,13 +43,15 @@ Link.Content = props => {
linkProps = {},
attributes,
} = props
const customAttributes = CustomAttributes.getCustomAttributes( attributes, 'linkCustomAttributes' )

if ( ! attributes.linkHasLink ) {
return props.children
}

return (
<LinkComponent.Content
{ ...customAttributes }
{ ...linkProps }
className={ props.className }
href={ attributes.linkUrl || undefined }
Expand All @@ -64,4 +67,3 @@ Link.Content = props => {
Link.InspectorControls = Edit

Link.addAttributes = addAttributes

2 changes: 1 addition & 1 deletion src/block/call-to-action/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ const InspectorControls = memo( () => {
<Transform.InspectorControls />
<Separator.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-call-to-action" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/card/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ const InspectorControls = memo( props => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-card" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/column/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ const InspectorControls = memo( props => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-column" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/icon-box/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ const InspectorControls = memo( () => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-icon-box" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/icon/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ const InspectorControls = memo( props => {
<Transform.InspectorControls />

<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="linkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-icon" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/image-box/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ const InspectorControls = memo( () => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-image-box" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const InspectorControls = memo( props => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="linkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-image" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/notification/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ const InspectorControls = memo( props => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-notification" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/pricing-box/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ const InspectorControls = memo( () => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-pricing-box" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/team-member/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ const InspectorControls = memo( () => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-team-member" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
2 changes: 1 addition & 1 deletion src/block/testimonial/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ const InspectorControls = memo( () => {
<Advanced.InspectorControls />
<Transform.InspectorControls />
<EffectsAnimations.InspectorControls />
<CustomAttributes.InspectorControls />
<CustomAttributes.InspectorControls linkAttributeName="blockLinkCustomAttributes" />
<CustomCSS.InspectorControls mainBlockClass="stk-block-testimonial" />
<Responsive.InspectorControls />
<ConditionalDisplay.InspectorControls />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ describe( 'CustomAttributesControl', () => {
}

const {
getByTestId, getByText,
getByTestId, getByText, rerender,
} = render( <CustomAttributesControl { ...dummyProps } /> )
expect( getByText( 'Custom Attributes' ) ).toBeTruthy()

rerender( <CustomAttributesControl { ...dummyProps } label="Link Custom Attributes" /> )
expect( getByText( 'Link Custom Attributes' ) ).toBeTruthy()

const invalidInputs = [
`test`,
`key=value`,
Expand Down
Loading
Loading