Verified Commit fc76c8e6 authored by Kevin Cristiano's avatar Kevin Cristiano 🌎
Browse files

npm pack



Signed-off-by: Kevin Cristiano's avatarKevin Cristiano <kcristiano@kcristiano.com>
parents
MIT License
Copyright (c) 2020 Josh Pollock
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
# Calderajs Form Builder
> Install from [npmjs](https://www.npmjs.com/package/@calderajs/form-builder) > `yarn add @calderajs/form-builder`
Components for building the Caldera Forms form builder. This library is used in caldera-forms/clients/form-builder/index.js
The boundry between this library and that file **should** be that in CF, componets interact with the DOM and legacy state. Everything below that, goes here. That's why it's one file.
The components in Caldera Forms core mainly do not render anything, they just bind to DOM events to watch for changes in state.
## Usage
### Import Components
See `src/exports.text.ts` for the full list of importable elements.
```tsx
import {
SubscribesToFormFields,
useCurrentFormFields,
useNotAllowedFields,
useFormFields,
SelectFormField,
Page,
Section,
ProcessorConditionalEditor,
prepareConditionalForSave,
prepareConditionalsForSave,
conditionalsFromCfConfig,
conditionalFromCfConfig,
useProcessorConditonals,
useConditionals,
ConditionalEditor,
RenderViaPortal,
} from '@calderajs/form-builder';
```
### Use Portals Always
Beacuse this library lives on the same page as legacy code, we will never render on the element provided to ReactDOM. Instead Portals are always used. The `RenderViaPortal` component should be used for this:
```jsx
import { RenderViaPortal } from '@calderajs/form-builder';
function SomethingPortal() {
const node = document.getElmentById(`whatever`);
if (!node) {
return <React.Fragment />;
}
return (
<RenderViaPortal domNode={node}>
<Something />
</RenderViaPortal>
);
}
```
### Context Providers
> [Short Intro To React Context](https://codesandbox.io/s/react-context-tldr-bey3y?file=/src/index.js)
This package makes use of [React's Context API](https://reactjs.org/docs/context.html). Context provides shared state and functions to update state between components without passing props. Doing so decouples state logic from position in the (virtual-)DOM.
The component `<FormBuilder />` uses all four providers:
- `<FormFieldsProvider intitalFields={intitalFields} />`
- State for form fields
- `<MagicTagProvider systemValues={systemValues} />`
- Magic tags state. Must be under FormFieldsProvider.
- `<ConditionalsProvider initialConditionals={initialConditionals}>`
- Conditional logic state. Must be under FormFieldsProvider and MagicTagProvider providers.
- `<ProcessorsProvider initialProcessors={initialProcessors} jQuery=jQuery} />`
- Must be under FormFieldsProvider, MagicTagProvider and ConditionalsProvider providers.
## Development
- Install
- `git clone`
- `yarn`
- Test
- `yarn test --watch`
- Build
- `yarn build`
- Start Storybook
- `yarn storybook`
### Storybook
> [Related documentation](https://storybook.js.org/docs/guides/guide-react/)
This repo is intentionally isolated from Caldera Forms core to encourage test-driven development and to constrain the boundries.
You can start a Storybook site to visualize the componets.
The `yarn storybook` command will start a "Storybook" site. You can use this to experiment with the componets. The file `.storybook\preview-head.html` is used to add style tags that bring in a lot of Caldera Forms' admin styles, using CalderaForms.com. That's a hack, and isn't perfect looking at all, but it's enough for now.
### Devloping With Caldera Forms
It reamins neccasary, to test with Caldera Forms. You should use [Yarn Link](https://classic.yarnpkg.com/en/docs/cli/link/) to install this project via symlink in Caldera Forms.
- In this directory, build for production.
- `yarn build`
- In this directory, enable other projects to link to this project.
- `yarn link`
- In Caldera Forms, link to this project
- `yarn link @calderajs/form-builder`
- In Caldera Forms, rebuild clients
- `yarn build:clients`
### Releasing A Version And Updating In Caldera Forms
> [Related Docs](https://classic.yarnpkg.com/en/docs/cli/publish/)
Using link to test before releasing an update is strongly encouraged. After doing so, you must unlink the package, release an update and update Caldera Forms.
Before begining, make sure you are [logged in to npmjs.com using Yarn's cli](https://classic.yarnpkg.com/en/docs/cli/login). Also, make sure you are Josh or Nico. If you are not Josh or Nico, please open a message in the engineering team in Basecamp and request you be granted acess. Please tag Josh and Nico and include your npmjs.com username in the message.
Please follow these steps:
- In Caldera Forms, unlink
- `yarn unlink @calderajs/form-builder`
- In this directory, unlink
- `yarn link`
- In this directory, publish
- `yarn publish`
- You will be prompted to provide a new version.
- Please [observer semver](https://semver.org/)
- In Caldera Forms force reinstall old version -- removing symlink totally.
- `yarn install --force`
- In Caldera Forms, add the new version
- `yarn add @calderajs/form-builder@<new-version>`
/// <reference types="react" />
import { formFieldsCollection } from 'useFormsFields/useFormFields';
import { conditionals } from 'editor-state/conditonalsState';
/**
* Set condtional types in fields when saving
*/
export declare const handleAddConditonalsToFields: (config: any, conditionals: conditionals) => void;
/**
* Handles saving via cf.presave action
*/
export declare const handleSaveConditionals: (config: any, conditionals: conditionals) => void;
/**
* The main Caldera Forms conditional logic editor
*/
declare const ConditionalEditor: (props: {
formFields: formFieldsCollection;
strings: any;
}) => JSX.Element;
export default ConditionalEditor;
/// <reference types="react" />
import { conditionals, conditional, conditionalId } from 'editor-state/conditonalsState';
export declare type ConditionalsContextValue = {
conditionals: conditionals;
updateConditional: (conditional: conditional) => void;
removeConditional: (conditionalId: conditionalId) => void;
getConditional: () => conditional;
getConditionals: () => conditionals;
getNotAllowedFields: (conditionalId: conditionalId) => void;
addConditional: (conditional: conditional) => void;
hasConditionals: () => boolean;
getAppliedFields: () => {
[key: string]: string;
};
};
export declare const ConditionalsContext: any;
export declare const ConditionalsProvider: (props: {
children: any;
initialConditionals: conditionals;
}) => JSX.Element;
/// <reference types="react" />
import { conditionalLinesGroup, conditionalLineGroups, conditionalLine, conditionalCompareType } from '../../editor-state/conditonalsState';
import { formFieldsCollection } from '../../useFormsFields/useFormFields';
export declare type processorConditionalType = 'use' | 'not' | '';
/**
* Represents how CF saves processor conditonals
*/
export declare type savedProcessorConditonal = {
type: processorConditionalType;
group: {
[key: string]: {
[key: string]: {
value: string;
field: string;
compare: conditionalCompareType;
id: string;
};
};
};
runtimes?: {
insert: 1 | 0;
};
};
/**
* Represents how CF saves a processor
*/
export declare type savedProcessor = {
ID: string;
type: string;
conditions: savedProcessorConditonal;
runtimes?: {
insert: 1 | 0;
};
config?: any;
};
/**
* Represents how CF saves processors
*/
export declare type savedProcessors = {
[key: string]: savedProcessor;
};
/**
* Processor conditonal as used by this system/
*/
export declare type processorConditional = {
type: processorConditionalType;
groups?: conditionalLineGroups;
};
/**
* Props for processor conditonal editor
*/
declare type processorConditionalEditorProps = {
conditional: processorConditional;
processorId: string;
formFields: formFieldsCollection | Array<any>;
strings: any;
onChangeType: (type: processorConditionalType) => void;
onUpdateLine: (update: conditionalLine, groupId: string, lineId: string) => void;
onAddLine: (groupId: string) => void;
onRemoveLine: (lineId: string, groupId: string) => void;
onAddGroup: (group: conditionalLinesGroup) => void;
};
/**
* Convert saved CF processor conditonal to correct type
* @param saved
*/
export declare const prepareProcessorConditonalFromSaved: (saved: savedProcessorConditonal) => processorConditional;
/**
* Editor for the conditonals of one processor.
*/
declare function ProcessorConditionalEditor(props: processorConditionalEditorProps): JSX.Element;
export default ProcessorConditionalEditor;
declare const _default: {
_last_updated: string;
ID: string;
cf_version: string;
name: string;
scroll_top: number;
success: string;
db_support: number;
pinned: number;
hide_form: number;
check_honey: number;
avatar_field: string;
form_ajax: number;
custom_callback: string;
layout_grid: {
fields: {
fld_29462: string;
fld_8768091: string;
fld_9970286: string;
fld_6009157: string;
fld_2758980: string;
fld_7683514: string;
fld_7908577: string;
};
structure: string;
};
fields: {
fld_29462: {
ID: string;
type: string;
label: string;
slug: string;
conditions: {
type: string;
};
caption: string;
config: {
custom_class: string;
default: string;
};
};
fld_8768091: {
ID: string;
type: string;
label: string;
slug: string;
conditions: {
type: string;
};
required: number;
caption: string;
config: {
custom_class: string;
placeholder: string;
default: string;
type_override: string;
mask: string;
email_identifier: number;
personally_identifying: number;
};
};
fld_9970286: {
ID: string;
type: string;
label: string;
slug: string;
conditions: {
type: string;
};
required: number;
caption: string;
config: {
custom_class: string;
placeholder: string;
default: string;
type_override: string;
mask: string;
email_identifier: number;
personally_identifying: number;
};
};
fld_6009157: {
ID: string;
type: string;
label: string;
slug: string;
conditions: {
type: string;
};
required: number;
caption: string;
config: {
custom_class: string;
placeholder: string;
default: string;
email_identifier: number;
personally_identifying: number;
};
};
fld_2758980: {
ID: string;
type: string;
label: string;
slug: string;
conditions: {
type: string;
};
caption: string;
config: {
custom_class: string;
default: string;
};
};
fld_7683514: {
ID: string;
type: string;
label: string;
slug: string;
conditions: {
type: string;
};
required: number;
caption: string;
config: {
custom_class: string;
placeholder: string;
rows: number;
default: string;
email_identifier: number;
personally_identifying: number;
};
};
fld_7908577: {
ID: string;
type: string;
label: string;
slug: string;
conditions: {
type: string;
};
caption: string;
config: {
custom_class: string;
type: string;
class: string;
target: string;
};
};
};
page_names: string[];
mailer: {
on_insert: number;
sender_name: string;
sender_email: string;
reply_to: string;
email_type: string;
recipients: string;
bcc_to: string;
email_subject: string;
email_message: string;
};
processors: {
fp_17689566: {
ID: string;
runtimes: {
insert: number;
};
type: string;
config: {
sender_name: string;
sender_email: string;
reply_to: string;
cc: string;
bcc: string;
subject: string;
recipient_name: string;
recipient_email: string;
message: string;
};
conditions: {
type: string;
group: {
rw6683006041: {
cl3730073711: {
field: string;
compare: string;
value: string;
};
cl11929307640: {
field: string;
compare: string;
value: string;
};
};
rw14635302975: {
cl9669649272: {
field: string;
compare: string;
value: number;
};
};
};
};
};
};
conditional_groups: never[];
settings: {
responsive: {
break_point: string;
};
};
privacy_exporter_enabled: boolean;
version: string;
db_id: string;
type: string;
};
export default _default;
import { conditionalLinesGroup } from './../../editor-state/conditonalsState';
import { conditionalLine } from '../../editor-state/conditonalsState';
import { processorConditional, processorConditionalType } from './ProcessorConditionalEditor';
/**
* Hook for working with the conditonals of one processor
*
* @param props
*/
export default function useProcessorConditionals(props: {
conditional: processorConditional;
onUpdate?: (conditional: processorConditional) => void;
}): {
conditional: processorConditional;
onChangeType(type: processorConditionalType): void;
onAddGroup(group: conditionalLinesGroup): void;
onRemoveLine(lineId: string, groupId: string): void;
onUpdateLine(update: conditionalLine, groupId: string, lineId: string): void;
onAddLine(groupId: string): void;
getGroup: (groupId: string) => conditionalLinesGroup | undefined;
getLine(groupId: string, lineId: string): conditionalLine | undefined;
};
/// <reference types="react" />
import { conditional } from 'editor-state/conditonalsState';
/**
* The section to set which fields it applies to
*
*/
declare const AppliesToFields: (props: {
formFields: any[];
conditional: conditional;
strings: any;
onChange: (value: string[]) => void;
groupId: string;
}) => JSX.Element;
export default AppliesToFields;
/// <reference types="react" />
import { formFieldsCollection } from 'useFormsFields/useFormFields';
import { conditionalLine } from 'editor-state/conditonalsState';
/**
* A group of conditional lines
* @param props
*/
declare const ConditionalLines: (props: {
lines: conditionalLine[];
strings: any;
formFields: formFieldsCollection;
onRemoveLine: (lineId: string, parent: string) => void;
onUpdateLine: (update: conditionalLine, lineId: string) => void;
onAddLine: (groupId: string) => void;
appliesToFields?: string[] | undefined;
groupId: string;
}) => JSX.Element;
export default ConditionalLines;
/// <reference types="react" />
import { formFieldsCollection, formField } from '../../../useFormsFields/useFormFields';
import { conditionalLine } from '../../../editor-state/conditonalsState';
/**
* Check if its a type of field that can have options
* @param fieldType
*/
export declare const isFieldTypeWithOptions: (fieldType: string) => boolean;
/**
* The value field for one conditonal line
* @param props
*/
export declare const ConditionalLineValueField: (props: {
fieldConfig: formField;
formFields: formFieldsCollection;