diff --git a/packages/iconography/includes/IconographyService.php b/packages/iconography/includes/IconographyService.php
index dacaeff..c23292b 100644
--- a/packages/iconography/includes/IconographyService.php
+++ b/packages/iconography/includes/IconographyService.php
@@ -29,6 +29,7 @@ public function __construct( private ConfigurationParser $configuration_parser )
* Init Hooks
*/
public function init(): void {
+ add_action( 'init', array( $this, 'register_block' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'register_assets' ) );
add_action( 'wp_footer', array( $this, 'enqueue_assets' ), 1, 0 );
add_action( 'enqueue_block_assets', array( $this, 'register_assets' ), 1, 0 );
@@ -36,6 +37,17 @@ public function init(): void {
add_action( 'enqueue_block_assets', array( $this, 'enqueue_all_assets' ) );
}
+ /**
+ * Register the block
+ *
+ * @return void
+ */
+ public function register_block(): void {
+ register_block_type_from_metadata(
+ plugin_dir_path( __DIR__ ) . 'build/block'
+ );
+ }
+
/**
* Register all assets in WP
*
diff --git a/packages/iconography/src/AddReactionOutlined.svg b/packages/iconography/src/Icon.svg
similarity index 100%
rename from packages/iconography/src/AddReactionOutlined.svg
rename to packages/iconography/src/Icon.svg
diff --git a/packages/iconography/src/block/Attributes.type.ts b/packages/iconography/src/block/Attributes.type.ts
index e8960e2..09828b7 100644
--- a/packages/iconography/src/block/Attributes.type.ts
+++ b/packages/iconography/src/block/Attributes.type.ts
@@ -1,7 +1,7 @@
import type { WPFormat } from '@wordpress/rich-text/build-types/register-format-type';
export type Attributes = Partial< {
- className: WPFormat[ 'className' ];
- tagName: WPFormat[ 'tagName' ];
+ iconClass: WPFormat[ 'className' ];
+ iconTag: WPFormat[ 'tagName' ];
iconContent: string;
} >;
diff --git a/packages/iconography/src/block/Edit.tsx b/packages/iconography/src/block/Edit.tsx
index 7aebe25..254de1a 100644
--- a/packages/iconography/src/block/Edit.tsx
+++ b/packages/iconography/src/block/Edit.tsx
@@ -1,28 +1,27 @@
import React from 'react';
-import { IconToolbarButton } from '../IconToolbarButton';
-import {
- BlockControls,
- InspectorControls,
- useBlockProps,
-} from '@wordpress/block-editor';
+/* WordPress Dependencies */
+import { useBlockProps } from '@wordpress/block-editor';
import { store as RichTextStore } from '@wordpress/rich-text';
import { useSelect } from '@wordpress/data';
-import { useState } from '@wordpress/element';
-import { Button, Panel, PanelBody } from '@wordpress/components';
+import { Icon, Spinner } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+import { replace } from '@wordpress/icons';
+
+/* Internal deps */
+import { IconToolbarButton } from '../shared';
+import './style.scss';
/* Types */
import type { Attributes } from './Attributes.type';
import type { BlockEditProps } from '@wordpress/blocks';
import type { RichTextValue } from '@wordpress/rich-text';
import type { WPFormat } from '@wordpress/rich-text/build-types/register-format-type';
-import { IconModal } from '../IconModal';
export const Edit = ( {
attributes,
setAttributes,
}: BlockEditProps< Attributes > ) => {
- const [ showIconModal, setShowIconModal ] = useState( false );
const blockProps = useBlockProps();
const { getFormatType } = useSelect(
( select ) =>
@@ -42,52 +41,35 @@ export const Edit = ( {
setAttributes( {
iconContent: value.text,
- tagName: format.tagName,
- className: format.className,
+ iconTag: format.tagName,
+ iconClass: format.className,
} );
};
const TagName =
- ( attributes.tagName as keyof HTMLElementTagNameMap ) ?? 'span';
-
- const ShowModalButton = () => (
-
- );
+ ( attributes.iconTag as keyof HTMLElementTagNameMap ) ?? 'span';
return (
<>
-
-
-
-
-
-
-
+ }
+ onChange={ handleChange }
+ value={ {
+ text: '',
+ formats: [],
+ replacements: [],
+ start: 0,
+ end: 0,
+ } }
+ initialOpen={ ! attributes.iconContent }
+ />
{ attributes.iconContent && (
-
+
{ attributes.iconContent }
) }
- { ! attributes.iconContent && }
- { showIconModal && (
- setShowIconModal( false ) }
- onChange={ handleChange }
- value={ {
- text: '',
- formats: [],
- replacements: [],
- start: 0,
- end: 0,
- } }
- />
- ) }
+ { ! attributes.iconContent && }
>
);
diff --git a/packages/iconography/src/block/Save.tsx b/packages/iconography/src/block/Save.tsx
index f514a23..f377fc1 100644
--- a/packages/iconography/src/block/Save.tsx
+++ b/packages/iconography/src/block/Save.tsx
@@ -1,5 +1,6 @@
import React from 'react';
+/* WordPress Dependencies */
import { useBlockProps } from '@wordpress/block-editor';
/* Types */
@@ -7,12 +8,12 @@ import type { Attributes } from './Attributes.type';
import type { BlockSaveProps } from '@wordpress/blocks';
export const Save = ( { attributes }: BlockSaveProps< Attributes > ) => {
- const { className, tagName, iconContent } = attributes;
- const TagName = ( tagName as keyof HTMLElementTagNameMap ) ?? 'span';
+ const { iconClass, iconTag, iconContent } = attributes;
+ const TagName = ( iconTag as keyof HTMLElementTagNameMap ) ?? 'span';
return (
- { iconContent }
+ { iconContent }
);
};
diff --git a/packages/iconography/src/block/block.json b/packages/iconography/src/block/block.json
index ad0c210..c17ba7e 100644
--- a/packages/iconography/src/block/block.json
+++ b/packages/iconography/src/block/block.json
@@ -8,24 +8,33 @@
"icon": "star-filled",
"keywords": [ "icon", "emoji", "symbol" ],
"textdomain": "boxuk",
+ "style": "file:./style-index.css",
+ "editorScript": "file:./index.ts",
"supports": {
- "align": [ "wide", "full" ],
- "alignWide": true,
+ "anchor": false,
+ "align": [],
+ "alignWide": false,
+ "ariaLabel": true,
+ "background": {
+ "backgroundImage": false,
+ "backgroundSize": false
+ },
+ "className": true,
"color": {
"background": true,
"text": true
},
- "background": { "backgroundImage": true, "backgroundSize": true },
- "anchor": false,
- "ariaLabel": true,
- "className": true,
"customClassName": true,
- "dimensions": { "aspectRatio": false, "minHeight": true },
- "filter": { "duotone": false },
+ "dimensions": {
+ "aspectRatio": false,
+ "minHeight": false
+ },
+ "filter": {
+ "duotone": false
+ },
"html": false,
"inserter": true,
"interactivity": false,
- "layout": true,
"lock": true,
"multiple": true,
"position": {
@@ -33,26 +42,33 @@
},
"renaming": true,
"reusable": true,
- "shadow": false,
+ "shadow": true,
"spacing": {
"margin": true,
- "padding": true
+ "padding": true,
+ "blockGrap": false
},
"typography": {
"fontSize": true,
- "lineHeight": true,
+ "lineHeight": false,
"textAlign": true
}
},
"attributes": {
- "className": {
+ "iconClass": {
"type": "string"
},
- "tagName": {
+ "iconTag": {
"type": "string"
},
"iconContent": {
"type": "string"
+ },
+ "style": {
+ "type": "object",
+ "default": {
+ "textAlign": "center"
+ }
}
},
"example": {}
diff --git a/packages/iconography/src/block/index.ts b/packages/iconography/src/block/index.ts
new file mode 100644
index 0000000..4410280
--- /dev/null
+++ b/packages/iconography/src/block/index.ts
@@ -0,0 +1,14 @@
+/* WordPress Dependencies */
+import { registerBlockType } from '@wordpress/blocks';
+
+/* Internal deps */
+import metadata from './block.json';
+import { Edit } from './Edit';
+import { Save } from './Save';
+import { ReactComponent as AddReactionOutlined } from '../Icon.svg';
+
+registerBlockType( metadata, {
+ icon: AddReactionOutlined,
+ edit: Edit,
+ save: Save,
+} );
diff --git a/packages/iconography/src/block/style.scss b/packages/iconography/src/block/style.scss
new file mode 100644
index 0000000..8adde7c
--- /dev/null
+++ b/packages/iconography/src/block/style.scss
@@ -0,0 +1,3 @@
+.wp-block-boxuk-icon {
+ text-align: center;
+}
diff --git a/packages/iconography/src/index.ts b/packages/iconography/src/index.ts
new file mode 100644
index 0000000..5ca17b9
--- /dev/null
+++ b/packages/iconography/src/index.ts
@@ -0,0 +1,14 @@
+/* WordPress Dependencies */
+import domReady from '@wordpress/dom-ready';
+
+/* Internal deps */
+import registerInlineIconography from './registerInlineIconography';
+
+domReady( () => {
+ registerInlineIconography();
+} );
+
+/* Export for other packages to consume */
+export * from './types';
+export * from './shared';
+export * from './utils';
diff --git a/packages/iconography/src/index.tsx b/packages/iconography/src/registerInlineIconography.tsx
similarity index 74%
rename from packages/iconography/src/index.tsx
rename to packages/iconography/src/registerInlineIconography.tsx
index 67c28d0..719b5aa 100644
--- a/packages/iconography/src/index.tsx
+++ b/packages/iconography/src/registerInlineIconography.tsx
@@ -1,22 +1,16 @@
import React, { ComponentProps } from 'react';
/* WordPress Dependencies */
-import domReady from '@wordpress/dom-ready';
import { registerFormatType } from '@wordpress/rich-text';
-import { registerBlockType } from '@wordpress/blocks';
-import { BlockControls } from '@wordpress/block-editor';
/* Internal deps */
-import metadata from './block/block.json';
-import { Edit } from './block/Edit';
-import { Save } from './block/Save';
-import { IconToolbarButton } from './IconToolbarButton';
+import { IconToolbarButton } from './shared';
import { getIconGroups, selectIconAtCurrentCursor } from './utils';
/* Types */
import type { IconGroup } from './types';
-export const handleKeyDown =
+const handleKeyDown =
( iconGroups: IconGroup[] | undefined ) => ( event: KeyboardEvent ) => {
switch ( event.key ) {
case 'ArrowLeft':
@@ -29,7 +23,7 @@ export const handleKeyDown =
}
};
-export const handleKeyUp =
+const handleKeyUp =
( iconGroups: IconGroup[] | undefined ) => ( event: KeyboardEvent ) => {
if ( 'ArrowRight' === event.key ) {
const { selection, icon } = selectIconAtCurrentCursor( iconGroups );
@@ -55,7 +49,7 @@ export const handleKeyEvent =
}
};
-export const registerIconography = () => {
+export const registerInlineIconography = () => {
const iconGroups = getIconGroups();
if ( ! iconGroups ) {
return;
@@ -65,11 +59,7 @@ export const registerIconography = () => {
if ( index === 0 ) {
iconGroup.edit = (
props: ComponentProps< typeof IconToolbarButton >
- ) => (
-
-
-
- );
+ ) => ;
}
registerFormatType( iconGroup.name, iconGroup );
} );
@@ -80,11 +70,4 @@ export const registerIconography = () => {
document.addEventListener( 'keyup', handleKeyEvent( iconGroups ) );
};
-domReady( () => {
- registerIconography();
-} );
-
-registerBlockType( metadata, {
- edit: Edit,
- save: Save,
-} );
+export default registerInlineIconography;
diff --git a/packages/iconography/src/IconModal.tsx b/packages/iconography/src/shared/IconModal.tsx
similarity index 97%
rename from packages/iconography/src/IconModal.tsx
rename to packages/iconography/src/shared/IconModal.tsx
index 82ab1e5..3d76c20 100644
--- a/packages/iconography/src/IconModal.tsx
+++ b/packages/iconography/src/shared/IconModal.tsx
@@ -8,7 +8,7 @@ import { useState, useMemo } from '@wordpress/element';
/* Internal Dependencies */
import { PlaceholderIconPanel } from './PlaceholderIconPanel';
-import { getIconGroups } from './utils';
+import { getIconGroups } from '../utils';
/* Types */
import type { RichTextValue } from '@wordpress/rich-text';
diff --git a/packages/iconography/src/tests/IconPanel.test.tsx b/packages/iconography/src/shared/IconPanel.test.tsx
similarity index 97%
rename from packages/iconography/src/tests/IconPanel.test.tsx
rename to packages/iconography/src/shared/IconPanel.test.tsx
index 1e9eee0..e7ce27a 100644
--- a/packages/iconography/src/tests/IconPanel.test.tsx
+++ b/packages/iconography/src/shared/IconPanel.test.tsx
@@ -3,7 +3,7 @@ import { describe, expect, jest, test } from '@jest/globals';
import { render, screen } from '@testing-library/react';
import { generateRichTextFormat } from '../utils';
-import { IconPanel } from '../IconPanel';
+import { IconPanel } from './IconPanel';
jest.mock( '../utils', () => ( {
generateRichTextFormat: jest.fn(),
diff --git a/packages/iconography/src/IconPanel.tsx b/packages/iconography/src/shared/IconPanel.tsx
similarity index 93%
rename from packages/iconography/src/IconPanel.tsx
rename to packages/iconography/src/shared/IconPanel.tsx
index 9e221ed..2c0b675 100644
--- a/packages/iconography/src/IconPanel.tsx
+++ b/packages/iconography/src/shared/IconPanel.tsx
@@ -8,10 +8,10 @@ import {
} from '@wordpress/components';
/* Internal Dependencies */
-import { generateRichTextFormat } from './utils';
+import { generateRichTextFormat } from '../utils';
/* Types */
-import type { IconGroup } from './types';
+import type { IconGroup } from '../types';
import type { RichTextValue } from '@wordpress/rich-text';
export type IconPanelProps = {
diff --git a/packages/iconography/src/IconToolbarButton.tsx b/packages/iconography/src/shared/IconToolbarButton.tsx
similarity index 62%
rename from packages/iconography/src/IconToolbarButton.tsx
rename to packages/iconography/src/shared/IconToolbarButton.tsx
index 299486f..6d0826b 100644
--- a/packages/iconography/src/IconToolbarButton.tsx
+++ b/packages/iconography/src/shared/IconToolbarButton.tsx
@@ -1,33 +1,38 @@
-import React from 'react';
+import React, { ComponentProps } from 'react';
/* WordPress Dependencies */
import { __ } from '@wordpress/i18n';
import { useState } from '@wordpress/element';
+import { BlockControls } from '@wordpress/block-editor';
import { ToolbarButton } from '@wordpress/components';
/* Internal Dependencies */
-import { ReactComponent as AddReactionOutlined } from './AddReactionOutlined.svg';
+import { ReactComponent as Icon } from '../Icon.svg';
+import { IconModal } from './IconModal';
/* Types */
import type { RichTextValue } from '@wordpress/rich-text';
-import { IconModal } from './IconModal';
export type IconToolbarButtonProps = {
onChange: ( value: RichTextValue ) => void;
value: RichTextValue;
+ icon: ComponentProps< typeof ToolbarButton >[ 'icon' ];
+ initialOpen?: boolean;
};
export const IconToolbarButton = ( {
onChange,
value,
+ icon = ,
+ initialOpen = false,
}: IconToolbarButtonProps ) => {
- const [ open, setOpen ] = useState( false );
+ const [ open, setOpen ] = useState( initialOpen );
return (
- <>
+
}
- label={ __( 'Add an icon', 'boxuk' ) }
+ icon={ icon }
+ label={ __( 'Select icon', 'boxuk' ) }
onClick={ () => setOpen( ! open ) }
/>
{ open && (
@@ -37,6 +42,6 @@ export const IconToolbarButton = ( {
value={ value }
/>
) }
- >
+
);
};
diff --git a/packages/iconography/src/PlaceholderIconPanel.tsx b/packages/iconography/src/shared/PlaceholderIconPanel.tsx
similarity index 95%
rename from packages/iconography/src/PlaceholderIconPanel.tsx
rename to packages/iconography/src/shared/PlaceholderIconPanel.tsx
index ea5f05c..c5566c6 100644
--- a/packages/iconography/src/PlaceholderIconPanel.tsx
+++ b/packages/iconography/src/shared/PlaceholderIconPanel.tsx
@@ -10,7 +10,7 @@ import {
} from '@wordpress/components';
/* Types */
-import type { IconGroup } from './types';
+import type { IconGroup } from '../types';
import type { RichTextValue } from '@wordpress/rich-text';
export type IconPanelProps = {
diff --git a/packages/iconography/src/tests/__snapshots__/IconPanel.test.tsx.snap b/packages/iconography/src/shared/__snapshots__/IconPanel.test.tsx.snap
similarity index 100%
rename from packages/iconography/src/tests/__snapshots__/IconPanel.test.tsx.snap
rename to packages/iconography/src/shared/__snapshots__/IconPanel.test.tsx.snap
diff --git a/packages/iconography/src/shared/index.ts b/packages/iconography/src/shared/index.ts
new file mode 100644
index 0000000..42e0aa4
--- /dev/null
+++ b/packages/iconography/src/shared/index.ts
@@ -0,0 +1,6 @@
+import { IconModal } from './IconModal';
+import { IconPanel } from './IconPanel';
+import { IconToolbarButton } from './IconToolbarButton';
+import { PlaceholderIconPanel } from './PlaceholderIconPanel';
+
+export { IconModal, IconPanel, IconToolbarButton, PlaceholderIconPanel };
diff --git a/packages/iconography/src/tests/index.test.ts b/packages/iconography/src/tests/registerInlineIconography.test.ts
similarity index 93%
rename from packages/iconography/src/tests/index.test.ts
rename to packages/iconography/src/tests/registerInlineIconography.test.ts
index 05e4409..487644b 100644
--- a/packages/iconography/src/tests/index.test.ts
+++ b/packages/iconography/src/tests/registerInlineIconography.test.ts
@@ -3,13 +3,16 @@ import { registerFormatType } from '@wordpress/rich-text';
/* Internal Dependencies */
import { selectIconAtCurrentCursor, getIconGroups } from '../utils';
-import { handleKeyEvent, registerIconography } from '../';
+import {
+ handleKeyEvent,
+ registerInlineIconography,
+} from '../registerInlineIconography';
jest.mock( '@wordpress/rich-text', () => ( {
registerFormatType: jest.fn(),
} ) );
-jest.mock( '../IconToolbarButton', () => ( {
+jest.mock( '../shared', () => ( {
IconToolbarButton: jest.fn(),
} ) );
@@ -26,6 +29,7 @@ jest.mock( '../utils', () => ( {
describe( 'registering iconography', () => {
test( 'should register all 3 types by default', () => {
+ registerInlineIconography();
expect( getIconGroups ).toBeCalledTimes( 1 );
// just by having imported the file, the registerFormatType should be called 3 times as per the 3 mocked values.
expect( registerFormatType ).toBeCalledTimes( 3 );
@@ -35,7 +39,7 @@ describe( 'registering iconography', () => {
jest.clearAllMocks();
getIconGroups.mockReturnValue( undefined );
expect( registerFormatType ).toBeCalledTimes( 0 );
- registerIconography();
+ registerInlineIconography();
} );
} );
diff --git a/packages/iconography/src/tests/utils.test.ts b/packages/iconography/src/tests/utils.test.ts
index 3a0d37d..003501f 100644
--- a/packages/iconography/src/tests/utils.test.ts
+++ b/packages/iconography/src/tests/utils.test.ts
@@ -9,7 +9,7 @@ import { IconGroup } from '../types';
jest.mock( '@wordpress/rich-text', () => ( {} ) );
-jest.mock( '../IconToolbarButton', () => ( {
+jest.mock( '../shared', () => ( {
IconToolbarButton: jest.fn(),
} ) );
diff --git a/packages/iconography/svg.d.ts b/packages/iconography/svg.d.ts
deleted file mode 100644
index 3222202..0000000
--- a/packages/iconography/svg.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-declare module '*.svg' {
- import React = require('react');
- export const ReactComponent: React.FunctionComponent<
- React.SVGProps< SVGSVGElement >
- >;
- const src: string;
- export default src;
-}
diff --git a/packages/iconography/tests/TestIcononographyService.php b/packages/iconography/tests/TestIcononographyService.php
index c9b87c6..ec1397c 100644
--- a/packages/iconography/tests/TestIcononographyService.php
+++ b/packages/iconography/tests/TestIcononographyService.php
@@ -25,6 +25,7 @@ class TestIcononographyService extends TestCase {
*/
public function testInit(): void {
$class_in_test = new IconographyService( new ConfigurationParser() );
+ \WP_Mock::expectActionAdded( 'init', array( $class_in_test, 'register_block' ) );
\WP_Mock::expectActionAdded( 'wp_enqueue_scripts', array( $class_in_test, 'register_assets' ) );
\WP_Mock::expectActionAdded( 'wp_footer', array( $class_in_test, 'enqueue_assets' ), 1, 0 );
\WP_Mock::expectActionAdded( 'enqueue_block_assets', array( $class_in_test, 'register_assets' ), 1, 0 );
@@ -35,6 +36,25 @@ public function testInit(): void {
$this->assertConditionsMet();
}
+ /**
+ * Test Register Block
+ *
+ * @return void
+ */
+ public function testRegisterBlock(): void {
+ \WP_Mock::userFunction( 'plugin_dir_path' )
+ ->once()
+ ->andReturn( 'test/' );
+
+ \WP_Mock::userFunction( 'register_block_type_from_metadata' )
+ ->once()
+ ->with( 'test/build/block' );
+
+ $class_in_test = new IconographyService( new ConfigurationParser() );
+ $class_in_test->register_block();
+ $this->assertConditionsMet();
+ }
+
/**
* Test Register Assets
*
diff --git a/packages/iconography/webpack.config.js b/packages/iconography/webpack.config.js
new file mode 100644
index 0000000..d2df2dd
--- /dev/null
+++ b/packages/iconography/webpack.config.js
@@ -0,0 +1,9 @@
+const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
+
+module.exports = {
+ ...defaultConfig,
+ entry: {
+ ...defaultConfig.entry(),
+ index: './src/index.ts',
+ },
+};