Skip to content

Commit

Permalink
Feat: (editor-utils) EditorForm component. (#1559)
Browse files Browse the repository at this point in the history
* Feat: (editor-utils) EditorForm component.

* Refactor: Removed unused code in Edit.tsx

* Testing: Add unit tests.
  • Loading branch information
theodesp authored Sep 4, 2023
1 parent cf887d3 commit 350dc30
Show file tree
Hide file tree
Showing 7 changed files with 330 additions and 14,050 deletions.
14,181 changes: 144 additions & 14,037 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion packages/block-editor-utils/src/components/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ export default function Edit<T extends Record<string, any>>(
return (
<div {...blockProps}>
{props.isSelected ? (
<EditFormFields props={props} fields={fieldsConfig} />
<EditFormFields
props={props}
fields={fieldsConfig}
blockJson={blockJson}
/>
) : (
<Preview block={block} props={props} />
)}
Expand Down
10 changes: 8 additions & 2 deletions packages/block-editor-utils/src/components/EditFormFields.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import * as React from 'react';
import { BlockEditProps } from '@wordpress/blocks';
import { BlockConfiguration, BlockEditProps } from '@wordpress/blocks';
import InspectorFields from './InspectorFields.js';
import EditorForm from './EditorForm.js';
import { Field } from '../types/index.js';

interface EditFormFieldsProps<T extends Record<string, any>> {
props: BlockEditProps<T>;
fields: Field[];
blockJson: BlockConfiguration;
}

function EditFormFields<T extends Record<string, any>>({
props,
fields,
blockJson,
}: EditFormFieldsProps<T>) {
const inspectorFields = fields.filter(
(field: Field) => field.location === 'inspector',
);
const editorFields = fields.filter(
(field: Field) => field.location === 'editor',
);
return (
<>
<InspectorFields fields={inspectorFields} props={props} />
<div>Edit mode</div>
<EditorForm fields={editorFields} props={props} blockJson={blockJson} />
</>
);
}
Expand Down
63 changes: 63 additions & 0 deletions packages/block-editor-utils/src/components/EditorForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as React from 'react';
import { BlockConfiguration, BlockEditProps } from '@wordpress/blocks';
import { Icon } from '@wordpress/components';
import { applyFilters } from '@wordpress/hooks';
import { Control, Field } from '../types/index.js';

const styles = {
form: {
padding: '0 10px',
margin: '20px 0',
} as React.CSSProperties,
icon: {
marginRight: '10px',
} as React.CSSProperties,
heading: {
margin: '10px 0',
display: 'flex',
alignItems: 'center',
} as React.CSSProperties,
};

interface EditorFormProps<T extends Record<string, any>> {
fields: Field[];
props: BlockEditProps<T>;
blockJson: BlockConfiguration;
}

function EditorForm<T extends Record<string, any>>({
fields,
props,
blockJson,
}: EditorFormProps<T>) {
const loadedControls = applyFilters('faustBlockEditorUtils.controls', {}) as {
[key: string]: Control;
};
return (
<div
className="faust-editor-form"
aria-label="Faust block editor form"
style={styles.form}>
<h3 className="faust-editor-form__heading" style={styles.heading}>
<Icon size={24} icon={blockJson.icon} style={styles.icon} />
{blockJson.title}
</h3>
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-call */}
{fields.map((field: Field) => {
const ControlField = loadedControls[field.control];
if (!ControlField) {
return null;
}
return (
<ControlField
config={field}
props={props}
key={`editor-field-${field.name}`}
/>
);
})}
</div>
);
}

export default EditorForm;
16 changes: 13 additions & 3 deletions packages/block-editor-utils/tests/components/Edit.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,19 @@ describe('<Edit />', () => {
wp={null}
/>,
);
expect(screen.getByText('Edit mode')).toMatchInlineSnapshot(`
<div>
Edit mode
expect(screen.getByLabelText('Faust block editor form'))
.toMatchInlineSnapshot(`
<div
aria-label="Faust block editor form"
class="faust-editor-form"
style="padding: 0px 10px; margin: 20px 0px;"
>
<h3
class="faust-editor-form__heading"
style="margin: 10px 0px; display: flex; align-items: center;"
>
SimpleBlock
</h3>
</div>
`);
});
Expand Down
96 changes: 96 additions & 0 deletions packages/block-editor-utils/tests/components/EditorForm.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';
import EditorForm from '../../src/components/EditorForm.js';
import { actions, filters, addFilter } from '@wordpress/hooks';
import { Control, Field } from '../../src/types/index.js';

afterEach(() => {
jest.clearAllMocks();
});

beforeEach(() => {
[actions, filters].forEach((hooks) => {
for (const k in hooks) {
if ('__current' === k) {
continue;
}

delete hooks[k];
}
delete hooks.all;
});
});

function filterA(controls: { [key: string]: Control }) {
// eslint-disable-next-line no-param-reassign
controls.color = () => <div>Another Color</div>;
return controls;
}

const blockProps = {
clientId: '1',
setAttributes: () => null,
context: {},
attributes: {
message: 'Hello',
},
isSelected: false,
className: 'SimpleBlock',
};

const blockJson = {
title: 'SimpleBlock',
icon: 'star',
category: 'text',
attributes: {},
};

describe('<EditorForm />', () => {
it('renders an empty EditorForm if no fields are provided', () => {
const fields: Field[] = [];
addFilter('faustBlockEditorUtils.controls', 'my_callback', filterA);
render(
<EditorForm fields={fields} props={blockProps} blockJson={blockJson} />,
);
expect(screen.getByLabelText('Faust block editor form'))
.toMatchInlineSnapshot(`
<div
aria-label="Faust block editor form"
class="faust-editor-form"
style="padding: 0px 10px; margin: 20px 0px;"
>
<h3
class="faust-editor-form__heading"
style="margin: 10px 0px; display: flex; align-items: center;"
>
<span
class="dashicon dashicons dashicons-star"
style="font-size: 24px; width: 24px; height: 24px; margin-right: 10px;"
/>
SimpleBlock
</h3>
</div>
`);
});
it('renders EditorForm if matching fields are provided', () => {
const fields: Field[] = [
{
type: 'string',
control: 'color',
name: 'myColor',
location: 'editor',
},
{
type: 'string',
control: 'text',
name: 'myText',
location: 'inspector',
},
];
addFilter('faustBlockEditorUtils.controls', 'my_callback', filterA);
render(
<EditorForm fields={fields} props={blockProps} blockJson={blockJson} />,
);
expect(screen.getAllByText('Another Color')).toHaveLength(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ describe('<InspectorFields />', () => {
];
addFilter('faustBlockEditorUtils.controls', 'my_callback', filterA);
render(<InspectorFields fields={fields} props={blockProps} />);
expect(screen.getAllByText('Another Color')).toMatchInlineSnapshot(`
[
<div>
Another Color
</div>,
]
`);
expect(screen.getAllByText('Another Color')).toHaveLength(1);
});
});

1 comment on commit 350dc30

@headless-platform-by-wp-engine

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check out the recent updates to your Atlas environment:

App Environment URL Build
faustjs canary https://hg…wered.com ✅ (logs)

Learn more about building on Atlas in our documentation.

Please sign in to comment.