🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

react-drupal-webform

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-drupal-webform - npm Package Compare versions

Comparing version
1.0.0-alpha
to
1.0.1-alpha
+3
dist/components/special-display/confirmationView.d.ts
import React from 'react';
declare const _default: React.MemoExoticComponent<() => import("react/jsx-runtime").JSX.Element>;
export default _default;
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import cn from 'classnames';
import styles from './confirmationView.module.scss';
const ConfirmationView = () => {
return (_jsxs("div", { className: cn(styles.submittedMessage), role: "status", "aria-live": "polite", children: [_jsxs("div", { className: styles.header, children: [_jsx("span", { className: styles.icon, "aria-hidden": "true" }), _jsx("span", { className: styles.title, children: "Submission received" })] }), _jsx("p", { className: styles.text, children: "Thanks! Your form has been successfully submitted." })] }));
};
export default React.memo(ConfirmationView);
.submittedMessage {
position: relative;
width: 100%;
padding: 1rem;
border-radius: 4px;
background: var(--color-text);
color: white;
overflow: hidden;
}
.header {
display: flex;
align-items: center;
gap: 0.5rem;
}
.icon {
position: relative;
width: 0.9rem;
height: 0.9rem;
border-radius: 999px;
background: rgba(87, 230, 230, 0.9);
flex: 0 0 auto;
}
.icon::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 0.45rem;
height: 0.25rem;
border-left: 2px solid rgba(0, 0, 0, 0.75);
border-bottom: 2px solid rgba(0, 0, 0, 0.75);
transform: translate(-50%, -60%) rotate(-45deg);
}
.title {
font-size: 0.95rem;
font-weight: 600;
line-height: 1.3;
}
.text {
margin: 0.5rem 0 0;
font-size: 0.85rem;
line-height: 1.5;
color: rgba(255, 255, 255, 0.9);
}
import { TWebformNormalizedStateMessages, TWebformResolvedStateMessages, TWebformStateMessages } from '../../types/form.d';
export declare const normalizeStateMessages: (messages: Partial<TWebformStateMessages>, defaults: TWebformResolvedStateMessages) => TWebformNormalizedStateMessages;
export const normalizeStateMessages = (messages, defaults) => {
return {
general: {
errorMessage: messages.general?.errorMessage ?? defaults.general.errorMessage,
requiredMessage: messages.general?.requiredMessage ?? defaults.general.requiredMessage,
minLengthMessage: messages.general?.minLengthMessage ?? defaults.general.minLengthMessage,
maxLengthMessage: messages.general?.maxLengthMessage ?? defaults.general.maxLengthMessage,
},
fields: {
errorMessages: {
...defaults.fields.errorMessages,
...messages.fields?.errorMessages,
},
requiredMessages: {
...defaults.fields.requiredMessages,
...messages.fields?.requiredMessages,
},
minLengthMessages: {
...defaults.fields.minLengthMessage,
...messages.fields?.minLengthMessages,
},
maxLengthMessages: {
...defaults.fields.maxLengthMessage,
...messages.fields?.maxLengthMessages,
},
},
};
};
import { ComponentType } from 'react';
import { TFieldWebformObj } from './components/field';
import { IWysiwygProps } from './components/wysiwyg';
import { IErrorMessageWebformProps } from './components/errorMessage';
export type TWebformComponents = {
Action: ComponentType<TFieldWebformObj>;
Checkbox: ComponentType<TFieldWebformObj>;
Checkboxes: ComponentType<TFieldWebformObj>;
Hidden: ComponentType<TFieldWebformObj>;
Input: ComponentType<TFieldWebformObj>;
Layout: ComponentType<TFieldWebformObj>;
ManagedFile: ComponentType<TFieldWebformObj>;
Markup: ComponentType<TFieldWebformObj>;
Radios: ComponentType<TFieldWebformObj>;
Select: ComponentType<TFieldWebformObj>;
Textarea: ComponentType<TFieldWebformObj>;
Wysiwyg: ComponentType<IWysiwygProps>;
ErrorFieldMessage: ComponentType<IErrorMessageWebformProps>;
};
.submittedMessage {
position: relative;
width: 100%;
padding: 1rem;
border-radius: 4px;
background: var(--color-text);
color: white;
overflow: hidden;
}
.header {
display: flex;
align-items: center;
gap: 0.5rem;
}
.icon {
position: relative;
width: 0.9rem;
height: 0.9rem;
border-radius: 999px;
background: rgba(87, 230, 230, 0.9);
flex: 0 0 auto;
}
.icon::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 0.45rem;
height: 0.25rem;
border-left: 2px solid rgba(0, 0, 0, 0.75);
border-bottom: 2px solid rgba(0, 0, 0, 0.75);
transform: translate(-50%, -60%) rotate(-45deg);
}
.title {
font-size: 0.95rem;
font-weight: 600;
line-height: 1.3;
}
.text {
margin: 0.5rem 0 0;
font-size: 0.85rem;
line-height: 1.5;
color: rgba(255, 255, 255, 0.9);
}
+4
-1

@@ -9,2 +9,3 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";

const title = field?.['#title'];
const isRequired = Boolean(field?.['#required']);
const { control } = useFormContext();

@@ -14,3 +15,5 @@ const CustomCheckbox = components?.fieldById?.[fieldKey] ?? components?.checkbox;

const { field: fieldController, fieldState } = controller;
return (_jsx(Wrapper, { field: field, classNames: classNames, classNameFieldName: "fieldCheckboxes", stateError: fieldState?.error, components: components, fieldKey: fieldKey, children: CustomCheckbox ? (_jsx(CustomCheckbox, { ...props })) : (_jsxs("div", { className: cn(classNames.fields.checkbox?.itemWrapper, styles.checkbox), children: [_jsx("input", { id: fieldKey, className: cn(classNames.fields.checkbox.input), name: fieldController.name, type: "checkbox", value: title, checked: Boolean(fieldController.value), onChange: (e) => fieldController.onChange(e.target.checked), onBlur: onBlur }), title && (_jsx("label", { htmlFor: fieldKey, className: cn(classNames.fields.checkbox.label), children: title }))] })) }, fieldKey));
return (_jsx(Wrapper, { field: field, classNames: classNames, classNameFieldName: "fieldCheckboxes", stateError: fieldState?.error, isLabel: false, components: components, fieldKey: fieldKey, children: CustomCheckbox ? (_jsx(CustomCheckbox, { ...props })) : (_jsxs("div", { className: cn(classNames.fields.checkbox?.itemWrapper, styles.checkbox), children: [_jsx("input", { id: fieldKey, className: cn(classNames.fields.checkbox.input), name: fieldController.name, type: "checkbox", value: title, checked: Boolean(fieldController.value), onChange: (e) => fieldController.onChange(e.target.checked), onBlur: onBlur }), title && (_jsx("label", { htmlFor: fieldKey, className: cn(classNames.fields.checkbox.label, styles.checkboxLabel, {
[styles.isRequired]: isRequired,
}), children: title }))] })) }, fieldKey));
};
+2
-1

@@ -20,4 +20,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";

: false;
return (_jsxs("div", { className: cn(classNames.fields.checkboxes?.itemWrapper, styles.checkbox), children: [_jsx("input", { id: `checkboxes-${optionKey}-${i}`, className: cn(classNames.fields.checkboxes?.input, styles.field), name: fieldController.name, type: "checkbox", value: optionKey, checked: checked, onChange: (e) => handleChangeOptionsCheckboxes(e.target.value, e.target.checked, fieldController), onBlur: onBlur }), _jsx("label", { htmlFor: `checkboxes-${optionKey}-${i}`, className: cn(classNames.fields.checkboxes?.label), children: optionValue })] }, optionKey));
const correctOptionKey = optionKey.trim();
return (_jsxs("div", { className: cn(classNames.fields.checkboxes?.itemWrapper, styles.checkbox), children: [_jsx("input", { id: `checkboxes-${correctOptionKey}-${i}`, className: cn(classNames.fields.checkboxes?.input, styles.field), name: fieldController.name, type: "checkbox", value: optionKey, checked: checked, onChange: (e) => handleChangeOptionsCheckboxes(e.target.value, e.target.checked, fieldController), onBlur: onBlur }), _jsx("label", { htmlFor: `checkboxes-${correctOptionKey}-${i}`, className: cn(classNames.fields.checkboxes?.label, styles.labelCheckbox), children: optionValue })] }, optionKey));
}) })) }, fieldKey));
};

@@ -28,2 +28,9 @@ .input, .select {

padding-inline: var(--input-pading-horizontal);
&:hover {
box-shadow: inset 0 0 0 0.063rem var(--color-text);
}
&:focus, &:focus-visible {
outline: none;
box-shadow: 0 0 0 1px var(--border-form-element),0 0 0 4px var(--input-focus)
}
}

@@ -72,2 +79,5 @@

font-size: var(--font-size-s);
.labelCheckbox {
cursor: pointer;
}
}

@@ -90,4 +100,19 @@

font-size: var(--font-size-s);
cursor: pointer;
}
}
}
.checkboxLabel {
cursor: pointer;
&.isRequired {
&::after {
content: "*";
color: var(--danger);
line-height: 1;
margin-inline: .15em;
vertical-align: text-top;
background: none;
}
}
}
import 'tippy.js/dist/tippy.css';
import { IDescriptionWebformProps } from "../../../../../lib/types/components/description";
declare const Description: ({ innerProps, custom_component_wysiwyg, processed, }: IDescriptionWebformProps) => import("react/jsx-runtime").JSX.Element;
import { IDescriptionWebformProps } from '../../../../../lib/types/components/description';
declare const Description: ({ innerProps, components, processed, }: IDescriptionWebformProps) => import("react/jsx-runtime").JSX.Element;
export default Description;
import { jsx as _jsx } from "react/jsx-runtime";
import 'tippy.js/dist/tippy.css';
import Wysiwyg from "../../fields-special-components/wysiwyg/wysiwyg";
const Description = ({ innerProps, custom_component_wysiwyg, processed, }) => {
const CustomWysiwyg = custom_component_wysiwyg ?? Wysiwyg;
import Wysiwyg from '../../fields-special-components/wysiwyg/wysiwyg';
const Description = ({ innerProps, components, processed, }) => {
const CustomWysiwyg = components.wysiwyg ?? Wysiwyg;
const { className, ...restInnerProps } = innerProps ?? {};
return (_jsx(CustomWysiwyg, { className: className, processed: processed, as: 'div', ...restInnerProps }));
return (_jsx(CustomWysiwyg, { className: className, processed: processed, as: 'div', source: 'description', ...restInnerProps }));
};
export default Description;
import 'tippy.js/dist/tippy.css';
import { IHelpProps } from "../../../../../lib/types/components/help";
declare const Help: ({ innerProps, custom_component_wysiwyg, helps }: IHelpProps) => import("react/jsx-runtime").JSX.Element;
import { IHelpProps } from '../../../../../lib/types/components/help';
declare const Help: ({ innerProps, components, helps }: IHelpProps) => import("react/jsx-runtime").JSX.Element;
export default Help;

@@ -8,7 +8,7 @@ import { jsx as _jsx } from "react/jsx-runtime";

import { createRoot } from 'react-dom/client';
import Wysiwyg from "../../fields-special-components/wysiwyg/wysiwyg";
const Help = ({ innerProps, custom_component_wysiwyg, helps }) => {
import Wysiwyg from '../../fields-special-components/wysiwyg/wysiwyg';
const Help = ({ innerProps, components, helps }) => {
const { className, ...restInnerProps } = innerProps ?? {};
const buttonRef = useRef(null);
const CustomWysiwyg = custom_component_wysiwyg ?? Wysiwyg;
const CustomWysiwyg = components.wysiwyg ?? Wysiwyg;
useEffect(() => {

@@ -25,3 +25,3 @@ if (!buttonRef.current)

`;
root.render(_jsx(CustomWysiwyg, { processed: html }));
root.render(_jsx(CustomWysiwyg, { source: 'help', processed: html }));
tippy(buttonRef.current, {

@@ -28,0 +28,0 @@ content: tooltipContainer,

@@ -1,3 +0,3 @@

import { ILabelWebformProps } from "../../../../../lib/types/components/label";
declare const Label: ({ title, innerProps, isRequired, innerPropsHelpComponent, custom_component_help, wrapperElement, }: ILabelWebformProps) => import("react/jsx-runtime").JSX.Element;
import { ILabelWebformProps } from '../../../../../lib/types/components/label';
declare const Label: ({ field, innerProps, innerPropsHelpComponent, custom_component_help, wrapperElement, }: ILabelWebformProps) => import("react/jsx-runtime").JSX.Element;
export default Label;
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import Help from "../help/help";
import Help from '../help/help';
import cn from 'classnames';
import styles from './label.module.scss';
const Label = ({ title, innerProps, isRequired, innerPropsHelpComponent, custom_component_help, wrapperElement, }) => {
const Label = ({ field, innerProps, innerPropsHelpComponent, custom_component_help, wrapperElement, }) => {
const CustomHelp = custom_component_help ?? Help;

@@ -10,2 +10,4 @@ const Element = wrapperElement ?? 'label';

const { className, ...restInnerProps } = filteredInnerProps ?? {};
const isRequired = field?.['#required'];
const title = field?.['#title'];
return (_jsxs(Element, { className: cn(styles.label, className, {

@@ -12,0 +14,0 @@ [styles.isRequired]: isRequired,

import React from 'react';
import { IMoreProps } from '../../../../../lib/types/components/more';
declare const _default: React.MemoExoticComponent<({ innerPropsContainer, innerPropsButton, innerPropsWysiwyg, moreTitle, customComponentWysiwyg, }: IMoreProps) => import("react/jsx-runtime").JSX.Element>;
declare const _default: React.MemoExoticComponent<({ innerPropsContainer, innerPropsButton, innerPropsWysiwyg, moreTitle, components, }: IMoreProps) => import("react/jsx-runtime").JSX.Element>;
export default _default;

@@ -6,4 +6,4 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";

import cn from 'classnames';
const More = ({ innerPropsContainer, innerPropsButton, innerPropsWysiwyg, moreTitle, customComponentWysiwyg, }) => {
const CustomWysiwyg = customComponentWysiwyg ?? Wysiwyg;
const More = ({ innerPropsContainer, innerPropsButton, innerPropsWysiwyg, moreTitle, components, }) => {
const CustomWysiwyg = components.wysiwyg ?? Wysiwyg;
const { className: containerClassName, ...containerProps } = innerPropsContainer ?? {};

@@ -10,0 +10,0 @@ const { className: buttonClassName, ...buttonProps } = innerPropsButton ?? {};

import React from 'react';
import { TWrapperDescriptionWebformProps } from "../../../../../lib/types/components/wrapperDescription";
import { TWrapperDescriptionWebformProps } from '../../../../../lib/types/components/wrapperDescription';
declare const _default: React.MemoExoticComponent<({ components, classNames, field, }: TWrapperDescriptionWebformProps) => import("react/jsx-runtime").JSX.Element>;
export default _default;
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import styles from "../wrapper.module.scss";
import styles from '../wrapper.module.scss';
import cn from 'classnames';
import Description from "../description/description";
import Description from '../description/description';
const WrapperDescription = ({ components, classNames, field, }) => {
const CustomDescription = components?.description ?? Description;
return (_jsx(CustomDescription, { custom_component_wysiwyg: components.wysiwyg, innerProps: {
return (_jsx(CustomDescription, { components: components, innerProps: {
className: cn(classNames.general.fieldDescription, styles.wysiwyg, classNames.general.fieldWysiwyg),

@@ -10,0 +10,0 @@ }, processed: (field?.['#description'] ?? field?.['#file_placeholder']) || '' }));

import React from 'react';
import { TWrapperLabelWebformProps } from "../../../../../lib/types/components/wrapperLabel";
import { TWrapperLabelWebformProps } from '../../../../../lib/types/components/wrapperLabel';
declare const _default: React.MemoExoticComponent<({ components, innerPropsLabelComponent, classNames, field, fieldKey, }: TWrapperLabelWebformProps) => import("react/jsx-runtime").JSX.Element>;
export default _default;
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import Label from "../label/label";
import Label from '../label/label';
const WrapperLabel = ({ components, innerPropsLabelComponent, classNames, field, fieldKey, }) => {

@@ -8,3 +8,3 @@ const CustomLabel = components?.label ?? Label;

const { wrapperElement = 'label', innerProps } = props;
const { title, isRequired, custom_component_help, innerPropsHelpComponent, ...rest } = props;
const { custom_component_help, innerPropsHelpComponent, ...rest } = props;
let computedInnerProps;

@@ -17,3 +17,3 @@ if (wrapperElement === 'label') {

};
return (_jsx(CustomLabel, { ...rest, wrapperElement: "label", title: title ?? field['#title'], innerProps: computedInnerProps, isRequired: isRequired ?? field?.['#required'], custom_component_help: custom_component_help ?? components.help, innerPropsHelpComponent: innerPropsHelpComponent ?? {
return (_jsx(CustomLabel, { ...rest, wrapperElement: "label", field: field, fieldKey: fieldKey, innerProps: computedInnerProps, custom_component_help: custom_component_help ?? components.help, innerPropsHelpComponent: innerPropsHelpComponent ?? {
innerProps: { className: classNames.general.fieldHelp },

@@ -24,3 +24,3 @@ helps: {

},
custom_component_wysiwyg: components.wysiwyg,
components: components,
} }));

@@ -32,3 +32,3 @@ }

};
return (_jsx(CustomLabel, { ...rest, wrapperElement: "legend", title: title ?? field['#title'], innerProps: computedInnerProps, isRequired: isRequired ?? field?.['#required'], custom_component_help: custom_component_help ?? components.help, innerPropsHelpComponent: innerPropsHelpComponent ?? {
return (_jsx(CustomLabel, { ...rest, wrapperElement: "legend", fieldKey: fieldKey, innerProps: computedInnerProps, custom_component_help: custom_component_help ?? components.help, field: field, innerPropsHelpComponent: innerPropsHelpComponent ?? {
innerProps: { className: classNames.general.fieldHelp },

@@ -39,5 +39,5 @@ helps: {

},
custom_component_wysiwyg: components.wysiwyg,
components: components,
} }));
};
export default React.memo(WrapperLabel);
import React from 'react';
import { TWrapperMoreWebformProps } from "../../../../../lib/types/components/wrapperMore";
import { TWrapperMoreWebformProps } from '../../../../../lib/types/components/wrapperMore';
declare const _default: React.MemoExoticComponent<({ components, classNames, fieldMore, fieldMoreTitle, }: TWrapperMoreWebformProps) => import("react/jsx-runtime").JSX.Element>;
export default _default;
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import cn from 'classnames';
import styles from "../wrapper.module.scss";
import More from "../more/more";
import styles from '../wrapper.module.scss';
import More from '../more/more';
const WrapperMore = ({ components, classNames, fieldMore, fieldMoreTitle, }) => {

@@ -13,4 +13,5 @@ const CustomMore = components?.more ?? More;

processed: fieldMore,
}, customComponentWysiwyg: components.wysiwyg, moreTitle: fieldMoreTitle }));
source: 'more',
}, moreTitle: fieldMoreTitle, components: components }));
};
export default React.memo(WrapperMore);

@@ -1,2 +0,2 @@

import { TFieldValidate } from "../../../../lib/types/components/validate";
import { TFieldValidate } from '../../../../lib/types/components/validate';
export declare const validateCheckbox: (props: TFieldValidate) => void;
import { boolean } from 'yup';
import { resolveCustomValidator, } from "../../../../lib/functions/webform_validation_functions/webform_validation_functions";
import { resolveCustomValidator, } from '../../../../lib/functions/webform_validation_functions/webform_validation_functions';
export const validateCheckbox = (props) => {
const { yupObject, defaultValues, key, field, required, defaultFieldValues, requiredMessage, customValidators, } = props;
const type = field?.['#type'];
const defaultSchema = boolean();
const customSchema = resolveCustomValidator(customValidators, key, type, props) ?? defaultSchema;
yupObject[key] = required
? customSchema.oneOf([true], requiredMessage)
: customSchema.notRequired();
const baseSchema = resolveCustomValidator(customValidators, key, type, props) ?? boolean();
if (required) {
yupObject[key] = baseSchema.test('is-checked', requiredMessage, (value) => value === true);
}
else {
yupObject[key] = baseSchema.notRequired();
}
defaultValues[key] =
typeof field?.['#default_value'] !== 'undefined'
? Boolean(field?.['#default_value'])
: defaultFieldValues.checkbox;
? Boolean(field['#default_value'])
: false;
};

@@ -1,2 +0,2 @@

import { TFieldValidate } from "../../../../lib/types/components/validate";
import { TFieldValidate } from '../../../../lib/types/components/validate';
export declare const validateEmail: (props: TFieldValidate) => void;
import { string } from 'yup';
import { resolveCustomValidator, } from "../../../../lib/functions/webform_validation_functions/webform_validation_functions";
import { applyMinMaxLength, resolveCustomValidator, } from '../../../../lib/functions/webform_validation_functions/webform_validation_functions';
export const validateEmail = (props) => {
const { yupObject, defaultValues, key, required, defaultFieldValues, errorMessage, requiredMessage, customValidators, field, } = props;
const { yupObject, defaultValues, key, required, defaultFieldValues, errorMessage, requiredMessage, customValidators, minLengthMessage, maxLengthMessage, field, } = props;
const type = field?.['#type'];
const emailWithTLDRegex = /^[^\s@]+@[^\s@]{2,}\.[^\s@]{2,}$/;
const defaultSchema = string()
let defaultSchema = string()
.test('valid-email-format', 'invalid email', (v) => !v || emailWithTLDRegex.test(v))
.email(errorMessage);
defaultSchema = applyMinMaxLength(defaultSchema, field, minLengthMessage, maxLengthMessage);
const customSchema = resolveCustomValidator(customValidators, key, type, props) ?? defaultSchema;

@@ -11,0 +12,0 @@ yupObject[key] = required

@@ -6,3 +6,3 @@ import { formatMessage } from '../../../../lib/functions/webform_validation_functions/webform_validation_functions';

export const validateLayout = (props) => {
const { yupObject, defaultValues, field, defaultFieldValues, defaultFieldStateMessages, customValidators, watchedValues = {}, } = props;
const { yupObject, defaultValues, field, defaultFieldValues, defaultFieldStateMessages, customValidators, watchedValues = {}, minLengthMessage, maxLengthMessage, } = props;
const childFields = Object.fromEntries(Object.entries(field).filter(([k]) => !k.startsWith('#')));

@@ -28,4 +28,6 @@ const childVisibleKeys = Object.keys(childFields).filter((childKey) => shouldFieldBeVisible(childKey, childFields, watchedValues));

watchedValues,
minLengthMessage,
maxLengthMessage,
});
});
};

@@ -1,2 +0,2 @@

import { TFieldValidate } from "../../../../lib/types/components/validate";
import { TFieldValidate } from '../../../../lib/types/components/validate';
export declare const validateTel: (props: TFieldValidate) => void;
import { string } from 'yup';
import { resolveCustomValidator, } from "../../../../lib/functions/webform_validation_functions/webform_validation_functions";
import { applyMinMaxLength, resolveCustomValidator, } from '../../../../lib/functions/webform_validation_functions/webform_validation_functions';
export const validateTel = (props) => {
const { yupObject, defaultValues, key, field, required, defaultFieldValues, requiredMessage, errorMessage, customValidators, } = props;
const { yupObject, defaultValues, key, field, required, defaultFieldValues, requiredMessage, errorMessage, customValidators, minLengthMessage, maxLengthMessage, } = props;
const type = field?.['#type'];
const defaultSchema = string().matches(/^[0-9]+$/, {
let defaultSchema = string().matches(/^[0-9]+$/, {
message: errorMessage,
excludeEmptyString: true,
});
defaultSchema = applyMinMaxLength(defaultSchema, field, minLengthMessage, maxLengthMessage);
const customSchema = resolveCustomValidator(customValidators, key, type, props) ?? defaultSchema;

@@ -11,0 +12,0 @@ yupObject[key] = required

@@ -1,2 +0,2 @@

import { TFieldValidate } from "../../../../lib/types/components/validate";
import { TFieldValidate } from '../../../../lib/types/components/validate';
export declare const validateTextArea: (props: TFieldValidate) => void;
import { string } from 'yup';
import { resolveCustomValidator, formatMessage, getRequiredMessage, } from "../../../../lib/functions/webform_validation_functions/webform_validation_functions";
import { resolveCustomValidator, formatMessage, getRequiredMessage, applyMinMaxLength, } from '../../../../lib/functions/webform_validation_functions/webform_validation_functions';
export const validateTextArea = (props) => {
const { yupObject, defaultValues, key, required, defaultFieldValues, defaultFieldStateMessages, field, customValidators, } = props;
const { yupObject, defaultValues, key, required, defaultFieldValues, defaultFieldStateMessages, field, customValidators, minLengthMessage, maxLengthMessage, } = props;
const type = field?.['#type'];
const requiredMessage = formatMessage(getRequiredMessage(defaultFieldStateMessages, 'textarea') ?? '', field?.['#title']);
const defaultSchema = string();
let defaultSchema = string();
defaultSchema = applyMinMaxLength(defaultSchema, field, minLengthMessage, maxLengthMessage);
const customSchema = resolveCustomValidator(customValidators, key, type, props) ?? defaultSchema;

@@ -9,0 +10,0 @@ yupObject[key] = required

import { string } from 'yup';
import { resolveCustomValidator, } from '../../../../lib/functions/webform_validation_functions/webform_validation_functions';
import { applyMinMaxLength, resolveCustomValidator, } from '../../../../lib/functions/webform_validation_functions/webform_validation_functions';
export const validateTextField = (props) => {
const { yupObject, defaultValues, key, required, defaultFieldValues, requiredMessage, field, customValidators, } = props;
const { yupObject, defaultValues, key, required, defaultFieldValues, requiredMessage, field, customValidators, minLengthMessage, maxLengthMessage, } = props;
const type = field?.['#type'];
const defaultSchema = string();
const customSchema = resolveCustomValidator(customValidators, key, type, props) ?? defaultSchema;
yupObject[key] = required
? customSchema.required(requiredMessage)
: customSchema;
let baseSchema = string();
baseSchema = applyMinMaxLength(baseSchema, field, minLengthMessage, maxLengthMessage);
if (required) {
baseSchema = baseSchema.required(requiredMessage);
}
yupObject[key] =
resolveCustomValidator(customValidators, key, type, props) ?? baseSchema;
defaultValues[key] = defaultFieldValues.textfield;
};
import { jsx as _jsx } from "react/jsx-runtime";
import DOMPurify from 'isomorphic-dompurify';
import styles from './field.module.scss';
import cn from 'classnames';
import Wysiwyg from './fields-special-components/wysiwyg/wysiwyg';
export const renderMarkup = (props) => {
const { field, fieldKey, classNames, components } = props;
if (!(field?.['#markup'] && field?.['#markup']?.length > 0)) {
if (!field?.['#markup']?.length) {
return null;

@@ -14,8 +13,7 @@ }

}
return (_jsx("div", { className: cn(...(field?.['#attributes']?.class ?? []), classNames.fields.markup.base, styles.fieldWrapper), dangerouslySetInnerHTML: {
__html: DOMPurify.sanitize(field['#markup'], {
ADD_TAGS: ['iframe'],
ADD_ATTR: ['target'],
}),
} }, fieldKey));
const CustomWysiwyg = components?.wysiwyg;
if (CustomWysiwyg) {
return (_jsx(CustomWysiwyg, { processed: field['#markup'], source: "markup", className: cn(...(field?.['#attributes']?.class ?? []), classNames.fields.markup.base) }));
}
return (_jsx(Wysiwyg, { processed: field['#markup'], source: "markup", className: cn(...(field?.['#attributes']?.class ?? []), classNames.fields.markup.base) }));
};

@@ -18,5 +18,5 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";

const checked = fieldController.value === optionKey;
const inputId = `${fieldKey}-${optionKey}`;
const inputId = `${fieldKey}-${optionKey.trim()}`;
return (_jsxs("div", { className: cn(classNames.fields.radios?.itemWrapper, styles.radiosItemWrapper), children: [_jsx("input", { className: classNames.fields.radios?.input, name: fieldController.name, id: inputId, type: "radio", checked: checked, value: optionKey, onChange: (e) => handleChangeOptions(e.target.value, fieldController), onBlur: onBlur }), _jsx("label", { htmlFor: inputId, className: cn(classNames.fields.radios?.label, styles.radioLabel), children: optionValue })] }, optionKey));
}) })) }, fieldKey));
};
import React from 'react';
import { IFormDefaultWebformProps } from '../../../lib/types/components/formDefault';
declare const _default: React.MemoExoticComponent<{
({ elementsSource, multiStepExtra, defaultFieldValues, yup: yupObj, defaultFieldStateMessages, components, classNames, includeInactiveFieldsInSubmit, onSubmit, customValidators, }: IFormDefaultWebformProps): import("react/jsx-runtime").JSX.Element;
whyDidYouRender: boolean;
}>;
declare const _default: React.MemoExoticComponent<(props: IFormDefaultWebformProps) => import("react/jsx-runtime").JSX.Element>;
export default _default;

@@ -9,8 +9,11 @@ import { jsx as _jsx } from "react/jsx-runtime";

import { getDummyDefaultFormDefault } from '../../../lib/functions/webform_validation_functions/webform_validation_functions';
const FormDefault = ({ elementsSource, multiStepExtra, defaultFieldValues, yup: yupObj, defaultFieldStateMessages, components, classNames, includeInactiveFieldsInSubmit, onSubmit, customValidators, }) => {
import ConfirmationView from '../../special-display/confirmationView';
const FormDefault = (props) => {
const { elementsSource, multiStepExtra, defaultFieldValues, yup: yupObj, defaultFieldStateMessages, components, classNames, includeInactiveFieldsInSubmit, onSubmit, customValidators, isSubmitted, showConfirmation, } = props;
const { yupUseFormProps } = yupObj || {};
const isMultiStep = Boolean(multiStepExtra);
const shouldShowConfirmation = Boolean(isSubmitted && showConfirmation);
const dependentFields = useMemo(() => getDependentFields(elementsSource), [elementsSource]);
const dependentFieldNames = useMemo(() => dependentFields.map((dep) => dep.name), [dependentFields]);
const dummyDefaultValues = useMemo(() => getDummyDefaultFormDefault(elementsSource), [elementsSource]);
const dummyDefaultValues = useMemo(() => getDummyDefaultFormDefault(elementsSource, defaultFieldValues), [elementsSource]);
const methods = useForm({

@@ -21,2 +24,3 @@ ...yupUseFormProps,

defaultValues: dummyDefaultValues,
shouldUnregister: false,
});

@@ -67,10 +71,12 @@ const { control, reset, getValues, handleSubmit } = methods;

}, [onSubmit, includeInactiveFieldsInSubmit, visibleElementsKeys]);
return (_jsx(FormProvider, { ...methods, children: _jsx("form", { className: styles.formDefault, onSubmit: handleSubmit(handleFormSubmit), children: visibleElementsKeys.map((key, index) => {
const field = elementsSource[key];
const type = field['#type'];
const isLayout = isLayoutType(type);
return (_jsx(FormFieldRendered, { fieldKey: key, index: index, field: field, components: components, classNames: classNames, isMultiStep: isMultiStep, ...(isLayout ? { watchedValues } : {}) }, key));
}) }) }));
const formContent = visibleElementsKeys.map((key, index) => {
const field = elementsSource[key];
const type = field['#type'];
const isLayout = isLayoutType(type);
return (_jsx(FormFieldRendered, { fieldKey: key, index: index, field: field, components: components, classNames: classNames, isMultiStep: isMultiStep, ...(isLayout ? { watchedValues } : {}) }, key));
});
const CustomForm = components?.form;
const ConfirmationComponent = components?.confirmationView ?? ConfirmationView;
return (_jsx(FormProvider, { ...methods, children: shouldShowConfirmation ? (_jsx(ConfirmationComponent, {})) : CustomForm ? (_jsx(CustomForm, { ...props, onSubmit: handleSubmit(handleFormSubmit), children: formContent })) : (_jsx("form", { className: styles.formDefault, onSubmit: handleSubmit(handleFormSubmit), children: formContent })) }));
};
FormDefault.whyDidYouRender = true;
export default React.memo(FormDefault);
import React from 'react';
import { TFormMultiStepProps } from '../../../lib/types/components/formMultiStep';
declare const _default: React.MemoExoticComponent<{
({ elementsSource, defaultFieldValues, yup: yupObj, defaultFieldStateMessages, components, classNames, onSubmit, includeInactiveFieldsInSubmit, customValidators, }: TFormMultiStepProps): import("react/jsx-runtime").JSX.Element;
whyDidYouRender: boolean;
}>;
declare const _default: React.MemoExoticComponent<(props: TFormMultiStepProps) => import("react/jsx-runtime").JSX.Element>;
export default _default;

@@ -1,2 +0,2 @@

import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import styles from './formMultiStep.module.scss';

@@ -13,6 +13,10 @@ import React, { useEffect, useMemo, useCallback, useState } from 'react';

import { MultiStepProvider } from './multiStepContext';
const FormMultiStep = ({ elementsSource, defaultFieldValues, yup: yupObj, defaultFieldStateMessages, components, classNames, onSubmit, includeInactiveFieldsInSubmit, customValidators, }) => {
import ConfirmationView from '../../special-display/confirmationView';
const FormMultiStep = (props) => {
const { elementsSource, defaultFieldValues, yup: yupObj, defaultFieldStateMessages, components, classNames, onSubmit, includeInactiveFieldsInSubmit, customValidators, isSubmitted, showConfirmation, } = props;
const totalSteps = Object.keys(elementsSource).length;
const shouldShowConfirmation = Boolean(isSubmitted && showConfirmation);
const stepKeys = useMemo(() => Object.keys(elementsSource), [elementsSource]);
const allFieldNames = useMemo(() => getAllFieldNames(elementsSource), [elementsSource]);
const dummyDefaultValues = useMemo(() => getDummyDefaultMultiStep(elementsSource), [elementsSource]);
const dummyDefaultValues = useMemo(() => getDummyDefaultMultiStep(elementsSource, defaultFieldValues), [elementsSource]);
const { yupUseFormProps } = yupObj || {};

@@ -118,17 +122,17 @@ const methods = useForm({

]);
return (_jsx(FormProvider, { ...methods, children: _jsxs(MultiStepProvider, { stepIndex: stepIndex, setStepIndex: setStepIndex, totalSteps: visibleStepKeys.length, allWatchedSteps: allWatchedSteps, setAllWatchedSteps: setAllWatchedSteps, watchedStepValues: watchedStepValues, children: [_jsx(MultiStepStepper, { components: components, currentStepObj: currentStepObj, classNames: classNames }), _jsxs("form", { className: styles.formMultiStep, onSubmit: handleSubmit(onFormSubmit), children: [visibleElementsKeys.map((key, index) => {
const field = currentStepObj[key];
const type = field['#type'];
const isLayout = [
'webform_section',
'webform_flexbox',
'container',
'details',
].includes(type);
return (_jsx(FormFieldRendered, { fieldKey: key, index: index, field: field, components: components, classNames: classNames, isMultiStep: true, ...(isLayout
? { watchedValues: watchedStepValuesGlobal }
: {}) }, key));
}), _jsx(MultiStepActions, { previousButtonLabel: previousButtonLabel, nextButtonLabel: nextButtonLabel, components: components, classNames: classNames })] })] }) }));
const formContent = (_jsxs(_Fragment, { children: [visibleElementsKeys.map((key, index) => {
const field = currentStepObj[key];
const type = field['#type'];
const isLayout = [
'webform_section',
'webform_flexbox',
'container',
'details',
].includes(type);
return (_jsx(FormFieldRendered, { fieldKey: key, index: index, field: field, components: components, classNames: classNames, isMultiStep: true, ...(isLayout ? { watchedValues: watchedStepValuesGlobal } : {}) }, key));
}), _jsx(MultiStepActions, { previousButtonLabel: previousButtonLabel, nextButtonLabel: nextButtonLabel, components: components, classNames: classNames })] }));
const CustomForm = components?.form;
const ConfirmationComponent = components?.confirmationView ?? ConfirmationView;
return (_jsx(FormProvider, { ...methods, children: _jsx(MultiStepProvider, { elementsSource: elementsSource, stepIndex: stepIndex, setStepIndex: setStepIndex, totalSteps: totalSteps, totalVisibleSteps: visibleStepKeys.length, allWatchedSteps: allWatchedSteps, currentStepKey: currentStepKey, setAllWatchedSteps: setAllWatchedSteps, watchedStepValues: watchedStepValues, children: shouldShowConfirmation ? (_jsx(ConfirmationComponent, {})) : (_jsxs(_Fragment, { children: [_jsx(MultiStepStepper, { components: components, currentStepObj: currentStepObj, elementsSource: elementsSource, classNames: classNames }), CustomForm ? (_jsx(CustomForm, { ...props, onSubmit: handleSubmit(onFormSubmit), children: formContent })) : (_jsx("form", { className: styles.formMultiStep, onSubmit: handleSubmit(onFormSubmit), children: formContent }))] })) }) }));
};
FormMultiStep.whyDidYouRender = true;
export default React.memo(FormMultiStep);

@@ -12,3 +12,3 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";

const { formState, trigger } = useFormContext();
const { stepIndex, totalSteps, goNext, goPrev } = useMultiStepContext();
const { stepIndex, totalVisibleSteps, goNext, goPrev } = useMultiStepContext();
const { isSubmitting, isValid: isStepValid } = formState;

@@ -19,3 +19,3 @@ const CustomMultiStepActions = components?.multiStepActions;

}
const isLastStep = stepIndex === totalSteps - 1;
const isLastStep = stepIndex === totalVisibleSteps - 1;
const handlePrev = () => {

@@ -30,3 +30,2 @@ goPrev();

if (valid) {
// ⚡ On passe les valeurs du step courant à goNext (le provider fera setAllWatchedSteps)
goNext();

@@ -33,0 +32,0 @@ }

import React from 'react';
type MultiStepContextType = {
type TMultiStepContextType = {
stepIndex: number;
setStepIndex: React.Dispatch<React.SetStateAction<number>>;
totalSteps: number;
totalVisibleSteps: number;
watchedStepValues: Record<string, any>;
allWatchedSteps: Record<string, any>;
elementsSource: Record<string, any>;
setAllWatchedSteps: React.Dispatch<React.SetStateAction<Record<string, any>>>;
currentStepKey: string;
goNext: () => void;
goPrev: () => void;
};
type MultiStepProviderProps = {
type TMultiStepProviderProps = {
children: React.ReactNode;

@@ -17,8 +20,11 @@ stepIndex: number;

totalSteps: number;
totalVisibleSteps: number;
watchedStepValues: Record<string, any>;
allWatchedSteps: Record<string, any>;
currentStepKey: string;
setAllWatchedSteps: React.Dispatch<React.SetStateAction<Record<string, any>>>;
elementsSource: Record<string, any>;
};
export declare const MultiStepProvider: ({ children, stepIndex, setStepIndex, totalSteps, watchedStepValues, allWatchedSteps, setAllWatchedSteps, }: MultiStepProviderProps) => import("react/jsx-runtime").JSX.Element;
export declare const useMultiStepContext: () => MultiStepContextType;
export declare const MultiStepProvider: ({ children, stepIndex, setStepIndex, totalSteps, totalVisibleSteps, watchedStepValues, allWatchedSteps, setAllWatchedSteps, currentStepKey, elementsSource, }: TMultiStepProviderProps) => import("react/jsx-runtime").JSX.Element;
export declare const useMultiStepContext: () => TMultiStepContextType;
export {};
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useContext } from 'react';
const MultiStepContext = createContext(undefined);
export const MultiStepProvider = ({ children, stepIndex, setStepIndex, totalSteps, watchedStepValues, allWatchedSteps, setAllWatchedSteps, }) => {
export const MultiStepProvider = ({ children, stepIndex, setStepIndex, totalSteps, totalVisibleSteps, watchedStepValues, allWatchedSteps, setAllWatchedSteps, currentStepKey, elementsSource, }) => {
const goNext = () => {

@@ -16,5 +16,8 @@ setAllWatchedSteps((prev) => ({ ...prev, ...watchedStepValues })); // ⚡ ici on fusionne

totalSteps,
totalVisibleSteps,
watchedStepValues,
allWatchedSteps, // ⚡ exposé
setAllWatchedSteps, // ⚡ exposé
allWatchedSteps,
setAllWatchedSteps,
currentStepKey,
elementsSource,
goNext,

@@ -21,0 +24,0 @@ goPrev,

@@ -8,3 +8,3 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";

const { multiStepTitleAs = 'span', currentStepObj, components, classNames, } = props;
const { stepIndex, totalSteps } = useMultiStepContext();
const { stepIndex, totalVisibleSteps } = useMultiStepContext();
const CustomMultiStepStepper = components?.multiStepStepper;

@@ -19,13 +19,13 @@ if (CustomMultiStepStepper) {

let percent = minPercent;
if (totalSteps > 1) {
if (totalVisibleSteps > 1) {
percent =
stepIndex === 0
? minPercent
: stepIndex === totalSteps - 1
: stepIndex === totalVisibleSteps - 1
? maxPercent
: minPercent +
((maxPercent - minPercent) / (totalSteps - 1)) * stepIndex;
((maxPercent - minPercent) / (totalVisibleSteps - 1)) * stepIndex;
}
return (_jsxs("div", { className: cn(styles.multiStepStepper, classNames.multiStep.stepperContainer), children: [_jsxs("div", { className: cn(styles.headerStepperContainer, classNames.multiStep?.stepperHeader), children: [title && title.length > 0 && (_jsx(TagTitle, { className: cn(styles.title, classNames.multiStep.stepperTitle), children: title })), _jsxs("span", { className: cn(styles.multiStepStepperCounter, classNames.multiStep.stepperCounter), children: [stepIndex + 1, "/", totalSteps] })] }), _jsx("div", { className: cn(styles.progressBarContainer, classNames.multiStep.stepperProgressBarContainer), children: _jsx("div", { className: cn(styles.progressBar, classNames.multiStep.stepperProgressBar), style: { width: `${percent}%` } }) })] }));
return (_jsxs("div", { className: cn(styles.multiStepStepper, classNames.multiStep.stepperContainer), children: [_jsxs("div", { className: cn(styles.headerStepperContainer, classNames.multiStep?.stepperHeader), children: [title && title.length > 0 && (_jsx(TagTitle, { className: cn(styles.title, classNames.multiStep.stepperTitle), children: title })), _jsxs("span", { className: cn(styles.multiStepStepperCounter, classNames.multiStep.stepperCounter), children: [stepIndex + 1, "/", totalVisibleSteps] })] }), _jsx("div", { className: cn(styles.progressBarContainer, classNames.multiStep.stepperProgressBarContainer), children: _jsx("div", { className: cn(styles.progressBar, classNames.multiStep.stepperProgressBar), style: { width: `${percent}%` } }) })] }));
};
export default React.memo(MultiStepStepper);
import { TWebform } from '../lib/types/form.d';
declare const Webform: ({ elementsSource, defaultFieldValues, classNames, defaultFieldStateMessages, components, onSubmit, includeInactiveFieldsInSubmit, customValidators, }: TWebform) => import("react/jsx-runtime").JSX.Element;
declare const Webform: ({ elementsSource, defaultFieldValues, classNames, defaultFieldStateMessages, components, onSubmit, includeInactiveFieldsInSubmit, customValidators, isSubmitted, showConfirmation, }: TWebform) => import("react/jsx-runtime").JSX.Element;
export default Webform;

@@ -1,9 +0,10 @@

import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
import { jsx as _jsx } from "react/jsx-runtime";
import { getWebformProperties } from '../lib/functions/webform_functions';
import FormDefault from './form/formDefault/formDefault';
import { defaultValuesClassnames, defaultValuesFieldStateMessages, defaultValuesObj, } from '../lib/const/const.form';
import { deepMergeDefaults, mergeObjects, } from '../lib/functions/utils_functions';
import { mergeObjects } from '../lib/functions/utils_functions';
import { useMemo } from 'react';
import FormMultiStep from './form/formMultiStep/formMultiStep';
const Webform = ({ elementsSource, defaultFieldValues = {}, classNames = {}, defaultFieldStateMessages = {}, components = {}, onSubmit, includeInactiveFieldsInSubmit = true, customValidators, }) => {
import { normalizeStateMessages } from '../lib/functions/webform-states-message-functions/webform-state-messages-functions';
const Webform = ({ elementsSource, defaultFieldValues = {}, classNames = {}, defaultFieldStateMessages = {}, components = {}, onSubmit, includeInactiveFieldsInSubmit = true, customValidators, isSubmitted, showConfirmation = true, }) => {
const yupUseFormProps = {

@@ -17,13 +18,23 @@ mode: 'onChange',

}), [defaultFieldValues]);
const mergedDefaultValuesStateMessages = useMemo(() => deepMergeDefaults(defaultValuesFieldStateMessages, defaultFieldStateMessages), [defaultFieldStateMessages]);
const mergedDefaultValuesStateMessages = useMemo(() => {
return normalizeStateMessages(defaultFieldStateMessages, defaultValuesFieldStateMessages);
}, [defaultFieldStateMessages]);
const mergedClassNames = useMemo(() => mergeObjects(defaultValuesClassnames, classNames), [classNames]);
const { isMultiStep, elementsSources } = getWebformProperties(elementsSource);
const Form = () => {
if (isMultiStep) {
return (_jsx(FormMultiStep, { yup: { yupUseFormProps }, elementsSource: elementsSources, defaultFieldValues: mergedDefaultFieldValues, defaultFieldStateMessages: mergedDefaultValuesStateMessages, classNames: mergedClassNames, components: components, onSubmit: onSubmit, includeInactiveFieldsInSubmit: includeInactiveFieldsInSubmit, customValidators: customValidators }));
}
return (_jsx(FormDefault, { yup: { yupUseFormProps }, elementsSource: elementsSources, defaultFieldValues: mergedDefaultFieldValues, defaultFieldStateMessages: mergedDefaultValuesStateMessages, classNames: mergedClassNames, components: components, onSubmit: onSubmit, includeInactiveFieldsInSubmit: includeInactiveFieldsInSubmit, customValidators: customValidators }));
const FormComponent = isMultiStep ? FormMultiStep : FormDefault;
const formProps = {
yup: { yupUseFormProps },
elementsSource: elementsSources,
defaultFieldValues: mergedDefaultFieldValues,
defaultFieldStateMessages: mergedDefaultValuesStateMessages,
classNames: mergedClassNames,
components,
onSubmit,
includeInactiveFieldsInSubmit,
customValidators,
isSubmitted,
showConfirmation,
};
return _jsx(_Fragment, { children: elementsSource && _jsx(Form, {}) });
return elementsSource ? _jsx(FormComponent, { ...formProps }) : null;
};
export default Webform;

@@ -1,15 +0,18 @@

import { TWebformDefaultFieldValues, TWebformStateMessages } from '../types/form.d';
import { DeepRequired } from 'react-hook-form';
import { TWebformDefaultFieldValues, TWebformResolvedStateMessages } from '../types/form.d';
import { TDeepRequiredClassNames } from '../types/deepRequired';
export declare const defaultValuesObj: Required<TWebformDefaultFieldValues>;
export declare const defaultValuesFieldStateMessages: DeepRequired<TWebformStateMessages>;
export declare const defaultValuesFieldStateMessages: TWebformResolvedStateMessages;
/**
* export type TDrupalNonValueFieldType =
* | 'webform_markup'
* | 'webform_actions'
* | 'container'
* | 'webform_flexbox'
* | 'webform_section'
* | 'details'
* | 'fieldset'
*/
export declare const defaultValuesClassnames: TDeepRequiredClassNames;
export declare const components: {
LabelWebform: ({ title, innerProps, isRequired, innerPropsHelpComponent, custom_component_help, wrapperElement, }: import("../types/components/label").ILabelWebformProps) => import("react/jsx-runtime").JSX.Element;
WrapperWebform: import("react").MemoExoticComponent<(props: import("../types/components/wrapper").IWrapperWebformProps) => import("react/jsx-runtime").JSX.Element>;
ErrorFieldMessageWebform: ({ message, children, className, }: import("../types/components/errorMessage").IErrorMessageWebformProps) => import("react/jsx-runtime").JSX.Element;
Input: (props: import("../types/components/fieldWebformObjCustom").TFieldWebformObjCustom) => import("react/jsx-runtime").JSX.Element;
Select: (props: import("../types/components/fieldWebformObjCustom").TFieldWebformObjCustom) => import("react/jsx-runtime").JSX.Element;
Checkboxes: (props: import("../types/components/fieldWebformObjCustom").TFieldWebformObjCustom) => import("react/jsx-runtime").JSX.Element;
Wysiwyg: (props: import("../../components/form/fields/fields-special-components/fieldWysiwygCustom").TFieldWysiwygCustom) => import("react/jsx-runtime").JSX.Element;
Wysiwyg: import("react").MemoExoticComponent<({ processed, as: Element, className, }: import("../types/components/wysiwyg").IWysiwygProps) => import("react/jsx-runtime").JSX.Element>;
};

@@ -1,6 +0,2 @@

import Label from '../../components/form/fields/fields-sub-components/label/label';
import ErrorFieldMessage from '../../components/form/fields/fields-sub-components/errorFieldMessage/errorFieldMessage';
import FieldObjCustom from '../../components/form/fields/fields-special-components/fieldObjCustom';
import FieldWysiwygCustom from '../../components/form/fields/fields-special-components/fieldWysiwygCustom';
import Wrapper from '../../components/form/fields/fields-sub-components/wrapper';
import Wysiwyg from '../../components/form/fields/fields-special-components/wysiwyg/wysiwyg';
export const defaultValuesObj = {

@@ -18,6 +14,3 @@ textfield: '',

select: '',
webform_markup: '',
webform_actions: '',
hidden: '',
fieldset: '',
};

@@ -28,2 +21,4 @@ export const defaultValuesFieldStateMessages = {

requiredMessage: 'Field "{fieldName}" is required.',
minLengthMessage: 'Field "{fieldName}" must contain at least {minLength} characters.',
maxLengthMessage: 'Field "{fieldName}" must contain no more than {maxLength} characters.',
},

@@ -41,2 +36,5 @@ fields: {

hidden: '',
checkbox: '',
checkboxes: '',
select: '',
},

@@ -57,4 +55,38 @@ requiredMessages: {

},
minLengthMessage: {
textfield: '',
textarea: '',
email: '',
radios: '',
checkboxes: '',
checkbox: '',
number: '',
tel: '',
date: '',
hidden: '',
},
maxLengthMessage: {
textfield: '',
textarea: '',
email: '',
radios: '',
checkboxes: '',
checkbox: '',
number: '',
tel: '',
date: '',
hidden: '',
},
},
};
/**
* export type TDrupalNonValueFieldType =
* | 'webform_markup'
* | 'webform_actions'
* | 'container'
* | 'webform_flexbox'
* | 'webform_section'
* | 'details'
* | 'fieldset'
*/
export const defaultValuesClassnames = {

@@ -82,7 +114,12 @@ wrappers: {

webform_actions: '',
container: '',
fieldset: '',
hidden: '',
details: '',
webform_section: '',
webform_flexbox: '',
},
},
general: {
fieldForm: '',
fieldLabel: '',

@@ -158,9 +195,3 @@ fieldDescription: '',

export const components = {
LabelWebform: Label,
WrapperWebform: Wrapper,
ErrorFieldMessageWebform: ErrorFieldMessage,
Input: FieldObjCustom,
Select: FieldObjCustom,
Checkboxes: FieldObjCustom,
Wysiwyg: FieldWysiwygCustom,
Wysiwyg: Wysiwyg,
};
declare const mergeObjects: (defaultObj: Record<string, any>, newObj: Record<string, any>) => Record<string, any>;
declare const deepMergeDefaults: <T extends object>(defaults: T, overrides: Partial<T>) => T;
export { mergeObjects, deepMergeDefaults };
export declare const toStringMessage: (value: any) => string;

@@ -30,1 +30,6 @@ const mergeObjects = (defaultObj, newObj) => {

export { mergeObjects, deepMergeDefaults };
export const toStringMessage = (value) => {
if (typeof value === 'function')
return '';
return value ?? '';
};

@@ -1,3 +0,2 @@

import { TWebformCustomValidators, TWebformDefaultFieldValues, TWebformStateMessages } from '../../types/form.d';
import { DeepRequired } from 'react-hook-form';
import { TWebformCustomValidators, TWebformDefaultFieldValues, TWebformNormalizedStateMessages } from '../../types/form.d';
import * as yup from 'yup';

@@ -20,3 +19,3 @@ export declare const checkVisibilityCondition: (watched: any, expectedValue: any, mode?: "is" | "isNot") => boolean;

defaultFieldValues: Required<TWebformDefaultFieldValues>;
defaultFieldStateMessages: DeepRequired<TWebformStateMessages>;
defaultFieldStateMessages: TWebformNormalizedStateMessages;
customValidators?: TWebformCustomValidators;

@@ -23,0 +22,0 @@ watchedValues?: Record<string, any>;

@@ -1,4 +0,4 @@

import { formatMessage, getErrorMessage, getRequiredMessage, } from '../webform_validation_functions/webform_validation_functions';
import FormMappingFields from '../../../components/form/formMappingFields/formMappingFields';
import * as yup from 'yup';
import { resolveFieldMessages } from '../webform_yup_functions/webform_yup_functions';
export const checkVisibilityCondition = (watched, expectedValue, mode = 'is') => {

@@ -112,5 +112,3 @@ if (mode === 'is') {

const required = Boolean(field?.['#required']);
const requiredMessage = formatMessage(getRequiredMessage(defaultFieldStateMessages, type) ?? '', field?.['#title']);
const errorMessage = formatMessage(getErrorMessage(defaultFieldStateMessages, type) ?? '', field?.['#title']);
FormMappingFields[type ?? 'default']?.validator?.({
const fieldValidateProps = {
yupObject: yupObjLocal,

@@ -123,6 +121,14 @@ defaultValues: defaults,

defaultFieldStateMessages,
requiredMessage,
customValidators,
errorMessage,
});
requiredMessage: '',
errorMessage: '',
minLengthMessage: '',
maxLengthMessage: '',
};
const resolvedMessages = resolveFieldMessages(fieldValidateProps);
fieldValidateProps.requiredMessage = resolvedMessages.required;
fieldValidateProps.errorMessage = resolvedMessages.error;
fieldValidateProps.minLengthMessage = resolvedMessages.minLength;
fieldValidateProps.maxLengthMessage = resolvedMessages.maxLength;
FormMappingFields[type ?? 'default']?.validator?.(fieldValidateProps);
});

@@ -129,0 +135,0 @@ return {

import { TKeyValue } from '../webform_functions';
import { TWebformDefaultFieldValues, TWebformStateMessages } from '../../types/form.d';
import { DeepRequired } from 'react-hook-form';
import { TWebformDefaultFieldValues, TWebformNormalizedStateMessages } from '../../types/form.d';
declare const isMultiStep: (elementsSource: TKeyValue<any>) => boolean;
export declare const getAllFieldNames: (elementsSource: Record<string, any>) => string[];
export declare const getDummyDefaultMultiStep: (elementsSource: Record<string, any>) => Record<string, any>;
export declare const getDummyDefaultMultiStep: (elementsSource: Record<string, any>, defaultFieldValues: Partial<TWebformDefaultFieldValues>) => Record<string, any>;
export declare const getAllDefaultValuesFromAllSteps: ({ elementsSource, defaultFieldValues, defaultFieldStateMessages, }: {
elementsSource: Record<string, any>;
defaultFieldValues: Required<TWebformDefaultFieldValues>;
defaultFieldStateMessages: DeepRequired<TWebformStateMessages>;
defaultFieldStateMessages: TWebformNormalizedStateMessages;
}) => Record<string, any>;
export { isMultiStep };

@@ -18,12 +18,23 @@ import { generateFormSchemaAndDefaults } from '../webform_fields_functions/webform_fields_conditional_functions';

};
export const getDummyDefaultMultiStep = (elementsSource) => {
const collectDefaultsFromObject = (obj, acc, defaultFieldValues) => {
Object.entries(obj).forEach(([key, value]) => {
if (key.startsWith('#') || typeof value !== 'object' || value === null) {
return;
}
const type = value?.['#type'];
if (!type) {
collectDefaultsFromObject(value, acc, defaultFieldValues);
return;
}
if (!(type in defaultFieldValues)) {
collectDefaultsFromObject(value, acc, defaultFieldValues);
return;
}
acc[key] = defaultFieldValues[type];
});
};
export const getDummyDefaultMultiStep = (elementsSource, defaultFieldValues) => {
const allDefaults = {};
Object.values(elementsSource).forEach((stepObj) => {
Object.keys(stepObj).forEach((key) => {
if (!key.startsWith('#') &&
typeof stepObj[key] === 'object' &&
Boolean(stepObj[key]['#type'])) {
allDefaults[key] = '';
}
});
collectDefaultsFromObject(stepObj, allDefaults, defaultFieldValues);
});

@@ -30,0 +41,0 @@ return allDefaults;

import { TWebformCustomValidators, TWebformStateMessages } from '../../types/form.d';
import { DeepRequired } from 'react-hook-form';
import { TDrupal_FieldType } from '../../types/components/field';
import { AnySchema } from 'yup';
import { TDrupal_FieldType, TElementSource } from '../../types/components/field';
import { AnySchema, StringSchema } from 'yup';
import { TFieldValidate } from '../../types/components/validate';

@@ -11,2 +11,4 @@ export declare const getRequiredMessage: (defaultFieldStateMessages: DeepRequired<TWebformStateMessages>, stateFieldName: TDrupal_FieldType) => any;

export declare const resolveCustomValidator: <S extends AnySchema>(customValidators: TWebformCustomValidators | undefined, key: string, type: TDrupal_FieldType_Validate | undefined, args: TFieldValidate) => S | null;
export declare const getDummyDefaultFormDefault: (elementsSource: Record<string, any>) => Record<string, any>;
export declare const extractValueFields: (elementsSource: Record<string, any>, acc?: Record<string, any>) => Record<string, any>;
export declare const getDummyDefaultFormDefault: (elementsSource: Record<string, any>, defaultFieldValues: Record<string, any>) => Record<string, any>;
export declare const applyMinMaxLength: (schema: StringSchema<string | undefined>, field: TElementSource, minLengthMessage: string, maxLengthMessage: string) => StringSchema<string | undefined>;

@@ -29,19 +29,64 @@ export const getRequiredMessage = (defaultFieldStateMessages, stateFieldName) => {

};
export const getDummyDefaultFormDefault = (elementsSource) => {
const allDefaults = {};
Object.keys(elementsSource).forEach((key) => {
const field = elementsSource[key];
const type = field?.['#type'];
if ([
'container',
'webform_flexbox',
'webform_section',
'details',
'webform_actions',
].includes(type)) {
const isLayoutField = (field) => [
'container',
'webform_flexbox',
'webform_section',
'details',
'fieldset',
].includes(field?.['#type']);
export const extractValueFields = (elementsSource, acc = {}) => {
Object.entries(elementsSource).forEach(([key, field]) => {
if (!field || typeof field !== 'object')
return;
if (isLayoutField(field)) {
Object.entries(field).forEach(([childKey, childField]) => {
if (!childKey.startsWith('#')) {
extractValueFields({ [childKey]: childField }, acc);
}
});
return;
}
allDefaults[key] = '';
if (field['#type'] === 'webform_markup')
return;
if (field['#type'] === 'webform_actions')
return;
acc[key] = field;
});
return allDefaults;
return acc;
};
export const getDummyDefaultFormDefault = (elementsSource, defaultFieldValues) => {
const fields = extractValueFields(elementsSource);
const defaults = {};
Object.entries(fields).forEach(([key, field]) => {
const type = field['#type'];
if (!(type in defaultFieldValues))
return;
defaults[key] = defaultFieldValues[type];
});
return defaults;
};
export const applyMinMaxLength = (schema, field, minLengthMessage, maxLengthMessage) => {
const isRequired = Boolean(field?.['#required']);
let nextSchema = schema;
if (typeof field?.['#minlength'] === 'number') {
const minLength = field['#minlength'];
nextSchema = nextSchema.test('min-length-if-not-empty', minLengthMessage, (value) => {
if (!isRequired && value === '')
return true;
if (value == null)
return true;
return value.length >= minLength;
});
}
if (typeof field?.['#maxlength'] === 'number') {
const maxLength = field['#maxlength'];
nextSchema = nextSchema.test('max-length-if-not-empty', maxLengthMessage, (value) => {
if (!isRequired && value === '')
return true;
if (value == null)
return true;
return value.length <= maxLength;
});
}
return nextSchema;
};

@@ -0,1 +1,4 @@

import { TFieldValidate } from '../../types/components/validate';
import { TDrupal_FieldType } from '../../types/components/field';
import { TWebformErrorMessageFieldType, TWebformLengthMessageFieldType } from '../../types/form.d';
export declare const useYupValidationResolver: (validationSchema: any) => (data: any) => Promise<{

@@ -8,1 +11,10 @@ values: any;

}>;
export type TResolvedFieldMessages = {
required: string;
error: string;
minLength: string;
maxLength: string;
};
export declare const isErrorMessageFieldType: (type: TDrupal_FieldType) => type is TWebformErrorMessageFieldType;
export declare const isLengthMessageFieldType: (type: unknown) => type is TWebformLengthMessageFieldType;
export declare const resolveFieldMessages: (props: TFieldValidate) => TResolvedFieldMessages;

@@ -24,1 +24,50 @@ export const useYupValidationResolver = (validationSchema) => async (data) => {

};
export const isErrorMessageFieldType = (type) => {
return (type !== 'webform_markup' &&
type !== 'webform_actions' &&
type !== 'fieldset');
};
export const isLengthMessageFieldType = (type) => {
return (typeof type === 'string' &&
type !== 'webform_markup' &&
type !== 'webform_actions' &&
type !== 'fieldset' &&
type !== 'select' &&
type !== 'managed_file');
};
export const resolveFieldMessages = (props) => {
const { field, defaultFieldStateMessages } = props;
const type = field?.['#type'];
const fieldName = field?.['#title'] ?? '';
const minLength = typeof field?.['#minlength'] === 'number' ? String(field['#minlength']) : '';
const maxLength = typeof field?.['#maxlength'] === 'number' ? String(field['#maxlength']) : '';
const resolve = (v) => {
if (!v)
return '';
return typeof v === 'function' ? v(field) : v;
};
const replaceTokens = (msg) => msg
.replace('{fieldName}', fieldName)
.replace('{minLength}', minLength)
.replace('{maxLength}', maxLength);
const general = defaultFieldStateMessages.general;
const fields = defaultFieldStateMessages.fields;
const required = isErrorMessageFieldType(type)
? resolve(fields.requiredMessages[type])
: '';
const error = isErrorMessageFieldType(type)
? resolve(fields.errorMessages[type])
: '';
const minLen = isLengthMessageFieldType(type)
? resolve(fields.minLengthMessages?.[type])
: '';
const maxLen = isLengthMessageFieldType(type)
? resolve(fields.maxLengthMessages?.[type])
: '';
return {
required: replaceTokens(required || resolve(general.requiredMessage)),
error: replaceTokens(error || resolve(general.errorMessage)),
minLength: replaceTokens(minLen || resolve(general.minLengthMessage)),
maxLength: replaceTokens(maxLen || resolve(general.maxLengthMessage)),
};
};
import { jsx } from '@emotion/react';
import { TWebformCustomComponents } from "../form.d";
import { TWebformCustomComponents } from '../form.d';
export interface IHelpProps {
innerProps?: jsx.JSX.IntrinsicElements['button'];
custom_component_wysiwyg?: TWebformCustomComponents['wysiwyg'];
components: TWebformCustomComponents;
helps?: {

@@ -7,0 +7,0 @@ help?: string;

import React from 'react';
export type TWysiwygSource = 'help' | 'more' | 'description' | 'markup';
export interface IWysiwygProps {
as?: React.ElementType;
className?: string;
source: TWysiwygSource;
processed: string;
}
import { AnySchema } from 'yup';
import { JSX } from 'react';
import React from 'react';
import { ILabelWebformProps } from './components/label';
import { TDrupal_FieldType, TFieldWebformObj } from './components/field';
import { TDrupal_FieldType, TDrupalNonValueFieldType, TDrupalValueFieldType, TElementSource, TFieldWebformObj } from './components/field';
import { IWrapperWebformProps } from './components/wrapper';

@@ -19,2 +19,4 @@ import { IErrorMessageWebformProps } from './components/errorMessage';

import { TFieldRendererProps } from './components/fieldRenderer';
import { IFormDefaultWebformProps } from './components/formDefault';
import { TFormMultiStepProps } from './components/formMultiStep';
export type TFileWithBase64 = {

@@ -31,10 +33,4 @@ name: string;

export type TWebformDefaultFieldValues = {
[K in TDrupal_FieldType]?: TDefaultValue;
[K in TDrupalValueFieldType]?: TDefaultValue;
};
type TWebformRequiredMessageFields = {
[K in Exclude<TDrupal_FieldType, 'webform_markup' | 'webform_actions' | 'fieldset'>]?: string | null;
};
type TWebformErrorMessageFields = {
[K in Exclude<TDrupal_FieldType, 'webform_markup' | 'webform_actions' | 'radio' | 'checkbox' | 'checkboxes' | 'select' | 'fieldset'>]?: string | null;
};
export type TWrapperCategory = 'textInput' | 'selectionInput' | 'booleanInput';

@@ -59,2 +55,3 @@ export type TWebformClassNameFields = {

general?: {
fieldForm?: string;
fieldLabel?: string;

@@ -122,35 +119,89 @@ fieldDescription?: string;

};
export type TWebformMessageResolver = (props: TElementSource) => string;
export type TWebformMessageStateValue = string | TWebformMessageResolver;
export type TWebformErrorMessageFieldType = Exclude<TDrupal_FieldType, TDrupalNonValueFieldType>;
export type TWebformRequiredMessageFieldType = Exclude<TDrupal_FieldType, TDrupalNonValueFieldType>;
export type TWebformLengthMessageFieldType = Exclude<TDrupal_FieldType, TDrupalNonValueFieldType | 'select' | 'managed_file'>;
export type TWebformResolvedStateMessages = {
general: {
errorMessage: string;
requiredMessage: string;
minLengthMessage: string;
maxLengthMessage: string;
};
fields: {
errorMessages: {
[K in TWebformErrorMessageFieldType]: string;
};
requiredMessages: {
[K in TWebformRequiredMessageFieldType]: string;
};
minLengthMessage: {
[K in TWebformLengthMessageFieldType]: string;
};
maxLengthMessage: {
[K in TWebformLengthMessageFieldType]: string;
};
};
};
export type TWebformStateMessages = {
general?: {
errorMessage?: string;
requiredMessage?: string;
errorMessage?: TWebformMessageStateValue;
requiredMessage?: TWebformMessageStateValue;
minLengthMessage?: TWebformMessageStateValue;
maxLengthMessage?: TWebformMessageStateValue;
};
fields?: {
errorMessages?: TWebformErrorMessageFields;
requiredMessages?: TWebformRequiredMessageFields;
errorMessages?: Partial<Record<TWebformErrorMessageFieldType, TWebformMessageStateValue>>;
requiredMessages?: Partial<Record<TWebformRequiredMessageFieldType, TWebformMessageStateValue>>;
minLengthMessages?: Partial<Record<TWebformLengthMessageFieldType, TWebformMessageStateValue>>;
maxLengthMessages?: Partial<Record<TWebformLengthMessageFieldType, TWebformMessageStateValue>>;
};
};
export type TWebformNormalizedStateMessages = {
general: {
errorMessage: TWebformMessageStateValue;
requiredMessage: TWebformMessageStateValue;
minLengthMessage: TWebformMessageStateValue;
maxLengthMessage: TWebformMessageStateValue;
};
fields: {
errorMessages: Record<TWebformErrorMessageFieldType, TWebformMessageStateValue>;
requiredMessages: Record<TWebformRequiredMessageFieldType, TWebformMessageStateValue>;
minLengthMessages: Record<TWebformLengthMessageFieldType, TWebformMessageStateValue>;
maxLengthMessages: Record<TWebformLengthMessageFieldType, TWebformMessageStateValue>;
};
};
export type TWebformCustomElementFormProps = (IFormDefaultWebformProps & {
children: React.ReactNode;
onSubmit: () => void;
}) | (TFormMultiStepProps & {
children: React.ReactNode;
onSubmit: () => void;
});
export type TWebformCustomComponents = {
label?: (_props: ILabelWebformProps) => JSX.Element | null;
wrapper?: (_props: IWrapperWebformProps) => JSX.Element | null;
errorFieldMessage?: (_props: IErrorMessageWebformProps) => JSX.Element | null;
input?: (_props: TFieldWebformObjCustom) => JSX.Element | null;
managedFile?: (_props: TFieldWebformObjCustom) => JSX.Element | null;
managedFilePreview?: (_props: IManagedFilePreviewWebformProps) => JSX.Element | null;
select?: (_props: TFieldWebformObjCustom) => JSX.Element | null;
checkboxes?: (_props: TFieldWebformObjCustom) => JSX.Element | null;
wysiwyg?: (_props: IWysiwygProps) => JSX.Element | null;
help?: (_props: IHelpProps) => JSX.Element | null;
description?: (_props: IDescriptionWebformProps) => JSX.Element | null;
managedFileInfo?: (_props: IManagedFileInfoProps) => JSX.Element | null;
more?: (_props: IMoreProps) => JSX.Element | null;
multiStepActions?: (_props: IMultiStepActionsProps) => JSX.Element | null;
multiStepStepper?: (_props: IMultiStepStepperProps) => JSX.Element | null;
layout?: (_props: ILayoutWrapperProps) => JSX.Element | null;
radios?: (_props: TFieldWebformObjCustom) => JSX.Element | null;
textarea?: (_props: TFieldWebformObjCustom) => JSX.Element | null;
checkbox?: (_props: TFieldWebformObjCustom) => JSX.Element | null;
hidden?: (_props: TFieldWebformObjCustom) => JSX.Element | null;
markup?: (_props: TFieldWebformObj) => JSX.Element | null;
fieldById?: Record<string, (_props: TFieldRendererProps) => JSX.Element | null>;
label?: React.ComponentType<ILabelWebformProps>;
wrapper?: React.ComponentType<IWrapperWebformProps>;
errorFieldMessage?: React.ComponentType<IErrorMessageWebformProps>;
input?: React.ComponentType<TFieldWebformObjCustom>;
managedFile?: React.ComponentType<TFieldWebformObjCustom>;
managedFilePreview?: React.ComponentType<IManagedFilePreviewWebformProps>;
select?: React.ComponentType<TFieldWebformObjCustom>;
checkboxes?: React.ComponentType<TFieldWebformObjCustom>;
radios?: React.ComponentType<TFieldWebformObjCustom>;
textarea?: React.ComponentType<TFieldWebformObjCustom>;
checkbox?: React.ComponentType<TFieldWebformObjCustom>;
hidden?: React.ComponentType<TFieldWebformObjCustom>;
wysiwyg?: React.ComponentType<IWysiwygProps>;
help?: React.ComponentType<IHelpProps>;
description?: React.ComponentType<IDescriptionWebformProps>;
managedFileInfo?: React.ComponentType<IManagedFileInfoProps>;
more?: React.ComponentType<IMoreProps>;
multiStepActions?: React.ComponentType<IMultiStepActionsProps>;
multiStepStepper?: React.ComponentType<IMultiStepStepperProps>;
layout?: React.ComponentType<ILayoutWrapperProps>;
markup?: React.ComponentType<TFieldWebformObj>;
fieldById?: Record<string, React.ComponentType<TFieldRendererProps>>;
form?: React.ComponentType<TWebformCustomElementFormProps>;
confirmationView?: React.ComponentType<any>;
};

@@ -172,3 +223,4 @@ export type TWebformValidatorFactory = (ctx: TFieldValidate) => AnySchema | null | undefined;

includeInactiveFieldsInSubmit?: boolean;
isSubmitted: boolean;
showConfirmation?: boolean;
};
export {};
{
"name": "react-drupal-webform",
"version": "1.0.0-alpha",
"version": "1.0.1-alpha",
"description": "React components using webform Drupal data",

@@ -29,4 +29,4 @@ "scripts": {

"react-dom": ">=18",
"yup": "^1.6.1",
"react-hook-form": "^7.54.2"
"react-hook-form": "^7.54.2",
"yup": "^1.6.1"
},

@@ -37,5 +37,4 @@ "devDependencies": {

"sass": "^1.94.2",
"tsup": "^8.5.1",
"typescript": "^5.9.2"
}
}
+71
-62

@@ -1,7 +0,8 @@

# React Drupal Webform components (Alpha Version)
<h1 style="color:#1f3a8a;">React Drupal Webform components (Alpha Version)</h1>
> This package is currently in **alpha** and under active development.
react-drupal-webform is a lightweight React integration for Drupal Webform.
react-drupal-webform is a lightweight React and Next js integration for Drupal Webform.
It allows you to take the Webform structure exported from Drupal (as a Javascript object), load it into a React application, and render the form with full control over its UI.

@@ -14,4 +15,8 @@

# Installation and usage
Somes exemples here : https://react-next-drupal-webform.vercel.app/
Github : https://github.com/stephen-97/react-drupal-webform/tree/main/packages/react-drupal-webform
<h2 style="color:#1f3a8a;">Installation and usage</h2>
The easiest way to use react-drupal-webform is to install it from npm and build it into your app with Webpack.

@@ -25,3 +30,3 @@

### Version Compatibility
<h3 style="color:#1f3a8a;">Version Compatibility</h3>

@@ -43,5 +48,5 @@ Tested and validated with:

## Allowed Webform features from DRUPAL
<h2 style="color:#1f3a8a;">Allowed Webform features from Drupal</h2>
### Allowed elements '#type'
<h3 style="color:#1f3a8a;">Allowed elements '#type'</h3>

@@ -69,6 +74,8 @@ - textfield

### Allowed element features
<h3 style="color:#1f3a8a;">Allowed element features from Webform Drupal</h3>
#### General
IMPORTANT : By using custom components, it becomes possible to extend and customize the behavior of the form by leveraging additional properties.
<h4 style="color:#1f3a8a;">General</h4>
- **Element settings**

@@ -107,3 +114,3 @@ - Title : ✅

#### Conditions
<h4 style="color:#1f3a8a;">Conditions</h4>

@@ -116,11 +123,11 @@ - States : only "Visible".

#### Advanced
<h4 style="color:#1f3a8a;">Advanced</h4>
No feature allowed
#### Access
<h4 style="color:#1f3a8a;">Access</h4>
No feature allowed
#### General (for wizard_page)
<h4 style="color:#1f3a8a;">General (for wizard_page)</h4>

@@ -137,22 +144,7 @@ - **Elements settings**

## Examples
<h3 style="color:#1f3a8a;">Differences with the Drupal version</h3>
Here is a simple webform created in Drupal : ![img_1.png](./img/img_1.png)
Here is the result on the React App:
![img.png](./img/img.png)
### Exemple 1 : Required field
![img_2.png](./img/img_2.png)
### Exemple 2 : Multiple pages
![img_3.png](./img/img_3.png)
### Differences with the Drupal version
There is some few CSS differences, the react-webform library uses Yup and RHF (React Hook Form), so the error-handling system is not native to HTML5.
### Use of React Hook Component
<h3 style="color:#1f3a8a;">Use of React Hook Component</h3>

@@ -182,3 +174,3 @@ ```js

## Props
<h2 style="color:#1f3a8a;">Props</h2>

@@ -190,3 +182,5 @@ Common props you may want to specify include:

- `components` - Javascript object to list all components
- `isSubmitted` - Check if the form is submitted or not, for show the confirmation page.
- `onSubmit` - An async function that is called after submitting the form.
- `showConfirmation` - Show (or not) the confirmation page when isSubmitted is true.
- `includeInactiveFieldsInSubmit` - Includes conditionally hidden fields in the submission result (except hidden inputs).

@@ -196,3 +190,3 @@ - `defaultFieldStateMessages` - Default messages for field errors, required fields, etc.

### Props - components
<h3 style="color:#1f3a8a;">Props – components</h3>

@@ -204,3 +198,4 @@ `TYPE` - TWebformCustomComponents

- `errorFieldMessage` – Displays validation and error messages for a field.
- `input` – Renders standard input fields (textfield, email, number).
- `confirmationView` – Display of the confirmationView (after the submit).
- `input` – Renders standard input fields (textfield, email, number, tel).
- `managedFile` – Renders a managed file input field.

@@ -236,3 +231,3 @@ - `managedFilePreview` – Displays a preview of the uploaded managed file.

```js
import React from 'react';
import React, {useState} from 'react';
import Webform from 'react-drupal-webform';

@@ -244,6 +239,7 @@ import { getWebform } from './api'

export default async function App() {
const webformElementsSource = await getWebform()
const correctElementsSource = await getWebform()
const [isSubmitted, setIsSubmitted] = useState(false)
const handleSubmit = async (formData: Record<any, string>) => {
console.log(formData)
setIsSubmitted(true)
}

@@ -262,2 +258,3 @@

onSubmit={handleSubmit}
isSubmitted={isSubmitted}
components={customComponents}

@@ -320,3 +317,3 @@ />

### Props - classNames
<h3 style="color:#1f3a8a;">Props – classNames</h3>

@@ -394,3 +391,3 @@ The classNames are only available for default css class and scss module class.

```js
import React from 'react';
import React, {useState} from 'react';
import Webform from 'react-drupal-webform';

@@ -401,6 +398,8 @@ import { getWebform } from './api'

export default async function App() {
const webformElementsSource = await getWebform()
const webformData = await getWebform()
const elementsSource = YAML.parse(webformData.elementsSource)
const [isSubmitted, setIsSubmitted] = useState(false)
const handleSubmit = async (formData: Record<any, string>) => {
console.log(formData)
setIsSubmitted(true)
}

@@ -421,3 +420,4 @@

<Webform
elementsSource={correctElementsSource}
elementsSource={elementsSource}
isSubmitted={isSubmitted}
onSubmit={handleSubmit}

@@ -430,3 +430,3 @@ classNames={customClassNames}

### Props - defaultFieldStateMessage
<h3 style="color:#1f3a8a;">Props – defaultFieldStateMessages</h3>

@@ -438,2 +438,4 @@ `TYPE` - TWebformStateMessages

- `requiredMessage` – Default message displayed when a required field is empty.
- `minLengthMessage`- Default error message displayed when the field value does not meet the minimum length defined in Drupal (when the minimum constraint is enabled). This applies only to field types that support length constraints.
- `maxLengthMessage`- Default error message displayed when the field value exceeds the maximum length defined in Drupal (when the maximum constraint is enabled). This applies only to field types that support length constraints.

@@ -443,6 +445,9 @@ - `fields` – Field-type–specific validation messages.

- `errorMessages` – Custom validation error messages mapped by Drupal field type.
- `minLengthMessage`- Field-type–specific error message displayed when the value is shorter than the minimum length configured in Drupal (if active). This is applied only to fields that support minimum length validation (e.g. text inputs, textareas).
- `maxLengthMessage`- Field-type–specific error message displayed when the value exceeds the maximum length configured in Drupal (if active). This is applied only to fields that support maximum length validation.
```js
import React from 'react';
import React, {useState} from 'react';
import Webform from 'react-drupal-webform';

@@ -452,6 +457,8 @@ import { getWebform } from './api'

export default async function App() {
const webformElementsSource = await getWebform()
const webformData = await getWebform()
const elementsSource = YAML.parse(webformData.elementsSource)
const [isSubmitted, setIsSubmitted] = useState(false)
const handleSubmit = async (formData: Record<any, string>) => {
console.log(formData)
const handleSubmit = async (formData: Record<any, string>) => {
setIsSubmitted(true)
}

@@ -469,3 +476,4 @@

<Webform
elementsSource={correctElementsSource}
elementsSource={elementsSource}
isSubmitted={isSubmitted}
onSubmit={handleSubmit}

@@ -481,3 +489,3 @@ defaultFieldStateMessages={defaultFieldsStateMessages}

```js
import React from 'react';
import React, {useState} from 'react';
import Webform from 'react-drupal-webform';

@@ -487,6 +495,8 @@ import { getWebform } from './api'

export default async function App() {
const webformElementsSource = await getWebform()
const webformData = await getWebform()
const elementsSource = YAML.parse(webformData.elementsSource)
const [isSubmitted, setIsSubmitted] = useState(false)
const handleSubmit = async (formData: Record<any, string>) => {
console.log(formData)
setIsSubmitted(true)
}

@@ -504,3 +514,4 @@

<Webform
elementsSource={correctElementsSource}
elementsSource={elementsSource}
isSubmitted={isSubmitted}
onSubmit={handleSubmit}

@@ -513,10 +524,4 @@ defaultFieldStateMessages={defaultFieldsStateMessages}

As you can see, you can also call the "{fieldName}".
<h3 style="color:#1f3a8a;">Props – includeInactiveFieldsInSubmit</h3>
Result :
![img.png](img/img_4.png)
### Props - includeInactiveFieldsInSubmit
`TYPE` - boolean

@@ -527,3 +532,3 @@

### Props - customValidators
<h3 style="color:#1f3a8a;">Props – customValidators</h3>

@@ -545,6 +550,9 @@ `TYPE` - TWebformCustomValidators

export default async function App() {
const webformElementsSource = await getWebform()
const webformData = await getWebform()
const elementsSource = YAML.parse(webformData.elementsSource)
const [isSubmitted, setIsSubmitted] = useState(false)
const handleSubmit = async (formData: Record<any, string>) => {
console.log(formData)
setIsSubmitted(true)
}

@@ -565,3 +573,4 @@

<Webform
elementsSource={correctElementsSource}
elementsSource={elementsSource}
isSubmitted={isSubmitted}
onSubmit={handleSubmit}

@@ -568,0 +577,0 @@ customValidators={customValidator}

@@ -28,2 +28,9 @@ .input, .select {

padding-inline: var(--input-pading-horizontal);
&:hover {
box-shadow: inset 0 0 0 0.063rem var(--color-text);
}
&:focus, &:focus-visible {
outline: none;
box-shadow: 0 0 0 1px var(--border-form-element),0 0 0 4px var(--input-focus)
}
}

@@ -72,2 +79,5 @@

font-size: var(--font-size-s);
.labelCheckbox {
cursor: pointer;
}
}

@@ -90,4 +100,19 @@

font-size: var(--font-size-s);
cursor: pointer;
}
}
}
.checkboxLabel {
cursor: pointer;
&.isRequired {
&::after {
content: "*";
color: var(--danger);
line-height: 1;
margin-inline: .15em;
vertical-align: text-top;
background: none;
}
}
}