Components:Prefabs (Experimental) - bettyblocks/cli GitHub Wiki
THIS VERSION OF WRITING PREFABS IS EXPERIMENTAL AND SUBJECT TO CHANGE
A Prefab is something you can drag onto the canvas inside the Page Builder. Prefabs appear in the sidebar of the Page Builder. The following screenshot shows four Prefabs in the category NAVIGATION
in the sidebar of the Page Builder.
A Prefab is configured by a typescript file returning a prefab structure.
This example configures a heading Prefab containing a single Heading
Component:
import { component, prefab, text } from '@betty-blocks/component-sdk';
const attributes = {
category: 'CONTENT',
icon: 'HEADING_ICON',
}
const options = {
text: text('Heading text')
}
export default prefab('Hello World', attributes, undefined, [
component('Heading', { options }, []);
])
Options are created by functions that can be imported from the component-sdk, they take a label as the first argument and the second argument takes a configuration object that looks the same as it did in the old prefab system.
Examples:
const options = {
content: variable('Content', { value: ['Default text']}),
show: toggle('Show', { value: false }),
backgroundColor: color('Background Color', { value: 'Accent3' })
}
There are some convenience functions for creating conditions in configurations, these are used to show or hide options based on the value of another option (e.g. show styling options, show advanced options, etc.)
const backgroundColor = color('Background color', {
value: 'Accent3',
configuration: {
condition: showIfTrue('styling'),
/* condition: showIf('styling', false) */
/* condition: hideIf('styling', false) */
}
})
Refer to the component-sdk documentation for all the types of options and convenience functions we support.
Now that the component set is being properly transpiled by the typescript compiler, it is now possible to import files and/or libraries to generate your prefabs. This needs to be thoroughly tested.
When you want to create a React component in the beforeCreate
make sure you import React the following way and give your file the .tsx
extension.
import * as React from 'react';
Another important note, files in the root of the prefabs directory are assumed to result in a prefab. If you want to reuse pieces of code, please put them in a subdirectory (e.g. ./src/prefabs/data-table/Column.tsx
)
Before create functions allow you to configure what models and/or properties you want to use in your component. Following examples are for many usecases expand them to see the full code, the LoginFormWizard also contains an example of how to include an interaction (not required). It looks much the same as it did in the previous prefab style.
LoginFormWizard
import * as React from 'react';
import {
component,
option,
prefab,
BeforeCreateArgs,
PrefabInteraction,
InteractionType,
} from '@betty-blocks/component-sdk';
const beforeCreate = ({
close,
components: { CreateLoginFormWizard },
prefab,
prefabs,
save,
}: BeforeCreateArgs) => {
return (
<CreateLoginFormWizard
close={close}
prefab={prefab}
prefabs={prefabs}
save={save}
/>
);
};
const interactions: PrefabInteraction[] = [
{
name: 'login',
sourceEvent: 'onActionSuccess',
ref: {
sourceComponentId: '#formId',
},
parameters: [],
type: InteractionType.Global,
},
];
const attributes = {
category: 'FORM',
icon: 'LoginFormIcon',
interactions,
};
const options = {
actionId: option('ACTION_JS', { label: 'Action', value: '' }),
};
export default prefab('Login Form', attributes, beforeCreate, [
component('Form', { options, ref: { id: '#formId' } }, []),
]);
(Create)FormWizard
import * as React from 'react';
import {
component,
option,
prefab,
model,
filter,
BeforeCreateArgs,
} from '@betty-blocks/component-sdk';
import { Icon } from '@betty-blocks/component-sdk';
const beforeCreate = ({
close,
components: { CreateFormCreateWizard },
prefab,
prefabs,
save,
}: BeforeCreateArgs) => {
return (
<CreateFormCreateWizard
close={close}
prefab={prefab}
prefabs={prefabs}
save={save}
/>
);
};
const attributes = {
category: 'FORMV2',
icon: Icon.CreateFormIcon,
};
const options = {
actionId: option('ACTION_JS', { label: 'Action', value: '' }),
modelId: model('Model'),
filter: filter('Filter', { configuration: { dependsOn: 'modelId' } }),
};
export default prefab('Create Form Beta', attributes, beforeCreate, [
component('Action Form Beta', { options }, []),
]);
UpdateFormWizard
import * as React from 'react';
import {
component,
option,
prefab,
model,
filter,
BeforeCreateArgs,
} from '@betty-blocks/component-sdk';
import { Icon } from '@betty-blocks/component-sdk';
const beforeCreate = ({
close,
components: { CreateFormUpdateWizard },
prefab,
prefabs,
save,
}: BeforeCreateArgs) => {
return (
<CreateFormUpdateWizard
close={close}
prefab={prefab}
prefabs={prefabs}
save={save}
/>
);
};
const attributes = {
category: 'FORMV2',
icon: Icon.UpdateFormIcon,
};
const options = {
actionId: option('ACTION_JS', { label: 'Action', value: '' }),
modelId: model('Model'),
filter: filter('Filter', { configuration: { dependsOn: 'modelId' } }),
};
export default prefab('Update Form Beta', attributes, beforeCreate, [
component('Action Form Beta', { options }, []),
]);
CreateInputWizard
import * as React from 'react';
import { BeforeCreateArgs, Icon, prefab } from '@betty-blocks/component-sdk';
import { TextInput } from './structures/TextInput';
const beforeCreate = ({
close,
components: { CreateFormInputWizard },
prefab,
save,
}: BeforeCreateArgs) => {
const actionVariableOption = prefab.structure[0].options.find(
(option: { type: string }) => option.type === 'ACTION_JS_VARIABLE',
);
if (!actionVariableOption) {
return <div>Prefab is missing the actionVariable component option</div>;
}
return (
<CreateFormInputWizard
supportedKinds={['TEXT', 'URL', 'IBAN', 'STRING']}
actionVariableOption={actionVariableOption.key}
labelOptionKey="label"
nameOptionKey="actionVariableId"
close={close}
prefab={prefab}
save={save}
/>
);
};
const attributes = {
category: 'FORMV2',
icon: Icon.TextInputIcon,
keywords: ['Form', 'input'],
};
export default prefab('Text Field Beta', attributes, beforeCreate, [
TextInput({ label: 'Textfield', type: 'text' }),
]);
These new ActionJs options are introduced to connect the components directly to the action, any change made is directly change in the action, whether you add, remove or duplicate components the action variables will be in sync.
- ACTION_JS_PROPERTY
Option that contains the model property.
- ACTION_JS_VARIABLE
Option that contains action variable information connected to this component, usually being used to get the action variable id.
- ACTION_JS
Option that contains data about the action itself, usually being used to get the action id.
ACTION_JS_PROPERTY example
actionProperty: option('ACTION_JS_PROPERTY', {
label: 'Property',
value: '',
}),
ACTION_JS_VARIABLE example
actionVariableId: option('ACTION_JS_VARIABLE', { label: 'Name', value: '' }),
ACTION_JS example
actionId: option('ACTION_JS', { label: 'Action', value: '' }),
Make sure that your component uses the FormHelper to wrap all form inputs.
const { Form } = B;
<Form>
<input id="example">
</Form>
It is important that your inputs use the name of the action variable as part of their name attribute. Like so
const { actionVariableId } = options;
<input name={actionVariableId} value={...} />