@boomerang-io/carbon-addons-boomerang-react 4.6.11-beta.22 → 4.6.11-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +162 -162
- package/dist/cjs/components/AboutPlatform/AboutPlatform.js +50 -50
- package/dist/cjs/components/AdvantageSideNav/AdvantageSideNav.js +245 -211
- package/dist/cjs/components/AutoSuggest/AutoSuggest.js +101 -101
- package/dist/cjs/components/Avatar/Avatar.js +18 -18
- package/dist/cjs/components/CheckboxList/CheckboxList.js +34 -34
- package/dist/cjs/components/ComboBox/ComboBox.js +103 -103
- package/dist/cjs/components/ComboBoxMultiSelect/ComboBoxMultiSelect.js +32 -32
- package/dist/cjs/components/ComboBoxMultiSelect/MultiSelect.js +208 -208
- package/dist/cjs/components/ComposedModal/ComposedModal.js +80 -80
- package/dist/cjs/components/ConfirmModal/ConfirmModal.js +43 -43
- package/dist/cjs/components/Creatable/Creatable.js +137 -137
- package/dist/cjs/components/DataDrivenInput/DataDrivenInput.js +226 -226
- package/dist/cjs/components/DateInput/DateInput.js +35 -35
- package/dist/cjs/components/DecisionButtons/DecisionButtons.js +61 -61
- package/dist/cjs/components/DelayedRender/DelayedRender.js +17 -17
- package/dist/cjs/components/DynamicFormik/DynamicFormik.js +578 -578
- package/dist/cjs/components/Error403/Error403.js +13 -13
- package/dist/cjs/components/Error403/ForbiddenErrorBackground.js +113 -113
- package/dist/cjs/components/Error403/GraphicWrangler/GraphicWrangler.js +62 -62
- package/dist/cjs/components/Error404/Error404.js +13 -13
- package/dist/cjs/components/Error404/GraphicLoch/GraphicLoch.js +17 -17
- package/dist/cjs/components/Error404/NotFoundErrorBackground.js +129 -129
- package/dist/cjs/components/ErrorBoundary/ErrorBoundary.js +32 -32
- package/dist/cjs/components/ErrorDragon/ErrorDragon.js +13 -13
- package/dist/cjs/components/ErrorDragon/assets/ErrorGraphic.js +35 -35
- package/dist/cjs/components/ErrorFullPage/ErrorFullPage.js +10 -10
- package/dist/cjs/components/ErrorMessage/ErrorMessage.js +22 -22
- package/dist/cjs/components/ErrorPage/ErrorPage.js +11 -11
- package/dist/cjs/components/ErrorPageCore/ErrorPageCore.js +15 -15
- package/dist/cjs/components/ErrorPageCore/GenericErrorBackground.js +124 -124
- package/dist/cjs/components/FeatureHeader/FeatureHeader.js +29 -29
- package/dist/cjs/components/FeatureNavTab/FeatureNavTab.js +12 -12
- package/dist/cjs/components/FeatureNavTabs/FeatureNavTabs.js +12 -12
- package/dist/cjs/components/FeatureSideNav/FeatureSideNav.js +12 -12
- package/dist/cjs/components/FeatureSideNav/FeatureSideNavFooter.js +8 -8
- package/dist/cjs/components/FeatureSideNav/FeatureSideNavHeader.js +8 -8
- package/dist/cjs/components/FeatureSideNav/FeatureSideNavLinks.js +14 -14
- package/dist/cjs/components/FeatureSideNavLink/FeatureSideNavLink.js +12 -12
- package/dist/cjs/components/Feedback/Feedback.js +40 -40
- package/dist/cjs/components/FlowModal/FlowModal.js +141 -141
- package/dist/cjs/components/FlowModal/FlowModalForm.js +12 -12
- package/dist/cjs/components/Header/Header.js +179 -179
- package/dist/cjs/components/Header/HeaderAppSwitcher.js +94 -94
- package/dist/cjs/components/Header/HeaderMenu.js +7 -7
- package/dist/cjs/components/Header/HeaderMenuItem.js +52 -52
- package/dist/cjs/components/Header/HeaderTeamSwitcher.js +303 -303
- package/dist/cjs/components/Header/UserRequests.js +29 -29
- package/dist/cjs/components/ImageModal/ImageModal.js +17 -17
- package/dist/cjs/components/Loading/Loading.js +8 -8
- package/dist/cjs/components/MemberBar/MemberBar.js +20 -20
- package/dist/cjs/components/Modal/Modal.js +20 -20
- package/dist/cjs/components/ModalConfirmEdit/ModalConfirmArray.js +14 -14
- package/dist/cjs/components/ModalConfirmEdit/ModalConfirmDetails.js +11 -11
- package/dist/cjs/components/ModalConfirmEdit/ModalConfirmEdit.js +17 -17
- package/dist/cjs/components/ModalForm/ModalForm.js +9 -9
- package/dist/cjs/components/Notifications/NotificationsContainer.js +22 -22
- package/dist/cjs/components/Notifications/ToastNotification.js +21 -21
- package/dist/cjs/components/Notifications/notify.js +17 -17
- package/dist/cjs/components/PlatformBanner/PlatformBanner.js +8 -8
- package/dist/cjs/components/PlatformNotifications/PlatformNotification.js +17 -17
- package/dist/cjs/components/PlatformNotifications/PlatformNotificationsContainer.js +136 -136
- package/dist/cjs/components/Portal/Portal.js +14 -14
- package/dist/cjs/components/PrivacyRedirect/PrivacyRedirect.js +30 -30
- package/dist/cjs/components/PrivacyStatement/PrivacyStatement.js +90 -90
- package/dist/cjs/components/ProfileSettings/ProfileSettings.js +124 -124
- package/dist/cjs/components/ProtectedRoute/ProtectedRoute.js +13 -13
- package/dist/cjs/components/RadioGroup/RadioGroup.js +33 -33
- package/dist/cjs/components/RichTextArea/RichTextArea.js +142 -142
- package/dist/cjs/components/SignOut/SignOut.js +27 -27
- package/dist/cjs/components/SupportCenter/SupportCenter.js +65 -65
- package/dist/cjs/components/TextArea/TextArea.js +16 -16
- package/dist/cjs/components/TextInput/TextInput.js +13 -13
- package/dist/cjs/components/Toggle/Toggle.js +22 -22
- package/dist/cjs/components/TooltipHover/TooltipHover.js +39 -39
- package/dist/cjs/components/UIShell/UIShell.js +94 -94
- package/dist/cjs/config/servicesConfig.js +21 -21
- package/dist/cjs/constants/DataDrivenInputTypes.js +74 -74
- package/dist/cjs/constants/UserType.js +13 -13
- package/dist/cjs/hooks/useHeaderMenu.js +49 -49
- package/dist/cjs/hooks/usePortal.js +74 -74
- package/dist/cjs/hooks/useWindowSize.js +33 -33
- package/dist/cjs/internal/ListBox/ListBox.js +41 -41
- package/dist/cjs/internal/ListBox/ListBoxField.js +19 -19
- package/dist/cjs/internal/ListBox/ListBoxMenu.js +19 -19
- package/dist/cjs/internal/ListBox/ListBoxMenuIcon.js +31 -31
- package/dist/cjs/internal/ListBox/ListBoxMenuItem.js +38 -38
- package/dist/cjs/internal/ListBox/ListBoxSelection.js +64 -64
- package/dist/cjs/internal/ListBox/index.js +10 -10
- package/dist/cjs/internal/keyboard/keys.js +16 -16
- package/dist/cjs/internal/keyboard/match.js +67 -67
- package/dist/cjs/internal/settings.js +5 -5
- package/dist/cjs/tools/accessibility.js +13 -13
- package/dist/cjs/tools/createPropAdapter.js +44 -44
- package/dist/cjs/tools/isUrl.js +39 -39
- package/dist/cjs/tools/setupGetInstanceId.js +20 -20
- package/dist/cjs/tools/useSetState.js +12 -12
- package/dist/cjs/tools/yupAst/astGenerator.js +212 -212
- package/dist/cjs/tools/yupAst/customValidators.js +17 -17
- package/dist/esm/components/AboutPlatform/AboutPlatform.js +50 -50
- package/dist/esm/components/AdvantageSideNav/AdvantageSideNav.js +246 -212
- package/dist/esm/components/AutoSuggest/AutoSuggest.js +101 -101
- package/dist/esm/components/Avatar/Avatar.js +18 -18
- package/dist/esm/components/CheckboxList/CheckboxList.js +34 -34
- package/dist/esm/components/ComboBox/ComboBox.js +103 -103
- package/dist/esm/components/ComboBoxMultiSelect/ComboBoxMultiSelect.js +32 -32
- package/dist/esm/components/ComboBoxMultiSelect/MultiSelect.js +208 -208
- package/dist/esm/components/ComposedModal/ComposedModal.js +80 -80
- package/dist/esm/components/ConfirmModal/ConfirmModal.js +43 -43
- package/dist/esm/components/Creatable/Creatable.js +137 -137
- package/dist/esm/components/DataDrivenInput/DataDrivenInput.js +226 -226
- package/dist/esm/components/DateInput/DateInput.js +35 -35
- package/dist/esm/components/DecisionButtons/DecisionButtons.js +61 -61
- package/dist/esm/components/DelayedRender/DelayedRender.js +17 -17
- package/dist/esm/components/DynamicFormik/DynamicFormik.js +578 -578
- package/dist/esm/components/Error403/Error403.js +13 -13
- package/dist/esm/components/Error403/ForbiddenErrorBackground.js +113 -113
- package/dist/esm/components/Error403/GraphicWrangler/GraphicWrangler.js +62 -62
- package/dist/esm/components/Error404/Error404.js +13 -13
- package/dist/esm/components/Error404/GraphicLoch/GraphicLoch.js +17 -17
- package/dist/esm/components/Error404/NotFoundErrorBackground.js +129 -129
- package/dist/esm/components/ErrorBoundary/ErrorBoundary.js +32 -32
- package/dist/esm/components/ErrorDragon/ErrorDragon.js +13 -13
- package/dist/esm/components/ErrorDragon/assets/ErrorGraphic.js +35 -35
- package/dist/esm/components/ErrorFullPage/ErrorFullPage.js +10 -10
- package/dist/esm/components/ErrorMessage/ErrorMessage.js +22 -22
- package/dist/esm/components/ErrorPage/ErrorPage.js +11 -11
- package/dist/esm/components/ErrorPageCore/ErrorPageCore.js +15 -15
- package/dist/esm/components/ErrorPageCore/GenericErrorBackground.js +124 -124
- package/dist/esm/components/FeatureHeader/FeatureHeader.js +29 -29
- package/dist/esm/components/FeatureNavTab/FeatureNavTab.js +12 -12
- package/dist/esm/components/FeatureNavTabs/FeatureNavTabs.js +12 -12
- package/dist/esm/components/FeatureSideNav/FeatureSideNav.js +12 -12
- package/dist/esm/components/FeatureSideNav/FeatureSideNavFooter.js +8 -8
- package/dist/esm/components/FeatureSideNav/FeatureSideNavHeader.js +8 -8
- package/dist/esm/components/FeatureSideNav/FeatureSideNavLinks.js +14 -14
- package/dist/esm/components/FeatureSideNavLink/FeatureSideNavLink.js +12 -12
- package/dist/esm/components/Feedback/Feedback.js +40 -40
- package/dist/esm/components/FlowModal/FlowModal.js +141 -141
- package/dist/esm/components/FlowModal/FlowModalForm.js +12 -12
- package/dist/esm/components/Header/Header.js +179 -179
- package/dist/esm/components/Header/HeaderAppSwitcher.js +94 -94
- package/dist/esm/components/Header/HeaderMenu.js +7 -7
- package/dist/esm/components/Header/HeaderMenuItem.js +52 -52
- package/dist/esm/components/Header/HeaderTeamSwitcher.js +303 -303
- package/dist/esm/components/Header/UserRequests.js +29 -29
- package/dist/esm/components/ImageModal/ImageModal.js +17 -17
- package/dist/esm/components/Loading/Loading.js +8 -8
- package/dist/esm/components/MemberBar/MemberBar.js +20 -20
- package/dist/esm/components/Modal/Modal.js +20 -20
- package/dist/esm/components/ModalConfirmEdit/ModalConfirmArray.js +14 -14
- package/dist/esm/components/ModalConfirmEdit/ModalConfirmDetails.js +11 -11
- package/dist/esm/components/ModalConfirmEdit/ModalConfirmEdit.js +17 -17
- package/dist/esm/components/ModalForm/ModalForm.js +9 -9
- package/dist/esm/components/Notifications/NotificationsContainer.js +22 -22
- package/dist/esm/components/Notifications/ToastNotification.js +21 -21
- package/dist/esm/components/Notifications/notify.js +17 -17
- package/dist/esm/components/PlatformBanner/PlatformBanner.js +8 -8
- package/dist/esm/components/PlatformNotifications/PlatformNotification.js +17 -17
- package/dist/esm/components/PlatformNotifications/PlatformNotificationsContainer.js +136 -136
- package/dist/esm/components/Portal/Portal.js +14 -14
- package/dist/esm/components/PrivacyRedirect/PrivacyRedirect.js +30 -30
- package/dist/esm/components/PrivacyStatement/PrivacyStatement.js +90 -90
- package/dist/esm/components/ProfileSettings/ProfileSettings.js +124 -124
- package/dist/esm/components/ProtectedRoute/ProtectedRoute.js +13 -13
- package/dist/esm/components/RadioGroup/RadioGroup.js +33 -33
- package/dist/esm/components/RichTextArea/RichTextArea.js +142 -142
- package/dist/esm/components/SignOut/SignOut.js +27 -27
- package/dist/esm/components/SupportCenter/SupportCenter.js +65 -65
- package/dist/esm/components/TextArea/TextArea.js +16 -16
- package/dist/esm/components/TextInput/TextInput.js +13 -13
- package/dist/esm/components/Toggle/Toggle.js +22 -22
- package/dist/esm/components/TooltipHover/TooltipHover.js +39 -39
- package/dist/esm/components/UIShell/UIShell.js +94 -94
- package/dist/esm/config/servicesConfig.js +21 -21
- package/dist/esm/constants/DataDrivenInputTypes.js +74 -74
- package/dist/esm/constants/UserType.js +13 -13
- package/dist/esm/hooks/useHeaderMenu.js +49 -49
- package/dist/esm/hooks/usePortal.js +74 -74
- package/dist/esm/hooks/useWindowSize.js +33 -33
- package/dist/esm/internal/ListBox/ListBox.js +41 -41
- package/dist/esm/internal/ListBox/ListBoxField.js +19 -19
- package/dist/esm/internal/ListBox/ListBoxMenu.js +19 -19
- package/dist/esm/internal/ListBox/ListBoxMenuIcon.js +31 -31
- package/dist/esm/internal/ListBox/ListBoxMenuItem.js +38 -38
- package/dist/esm/internal/ListBox/ListBoxSelection.js +64 -64
- package/dist/esm/internal/ListBox/index.js +10 -10
- package/dist/esm/internal/keyboard/keys.js +16 -16
- package/dist/esm/internal/keyboard/match.js +67 -67
- package/dist/esm/internal/settings.js +5 -5
- package/dist/esm/tools/accessibility.js +13 -13
- package/dist/esm/tools/createPropAdapter.js +44 -44
- package/dist/esm/tools/isUrl.js +39 -39
- package/dist/esm/tools/setupGetInstanceId.js +20 -20
- package/dist/esm/tools/useSetState.js +12 -12
- package/dist/esm/tools/yupAst/astGenerator.js +212 -212
- package/dist/esm/tools/yupAst/customValidators.js +17 -17
- package/dist/types/index.d.ts +1335 -1420
- package/package.json +167 -167
- package/scss/components/AboutPlatform/_aboutPlatform.scss +139 -139
- package/scss/components/AdvantageSideNav/_advantageSideNav.scss +261 -261
- package/scss/components/AutoSuggest/_autoSuggest.scss +62 -62
- package/scss/components/Avatar/_avatar.scss +32 -32
- package/scss/components/CheckboxList/_checkboxList.scss +26 -26
- package/scss/components/ComboBox/_combobox.scss +23 -23
- package/scss/components/ComboBoxMultiSelect/_comboBoxMultiSelect.scss +53 -53
- package/scss/components/ConfirmModal/_confirmModal.scss +12 -12
- package/scss/components/Creatable/_creatable.scss +48 -48
- package/scss/components/DateInput/_dateInput.scss +36 -36
- package/scss/components/DecisionButtons/_decisionButtons.scss +132 -132
- package/scss/components/DynamicFormik/_dynamicFormik.scss +17 -17
- package/scss/components/ErrorBoundary/_errorBoundary.scss +12 -12
- package/scss/components/ErrorDragon/_errorDragon.scss +55 -55
- package/scss/components/ErrorMessage/_errorMessage.scss +43 -43
- package/scss/components/ErrorPage/_errorPage.scss +66 -66
- package/scss/components/ErrorPageCore/_errorPageCore.scss +73 -73
- package/scss/components/FeatureHeader/_featureHeader.scss +67 -67
- package/scss/components/FeatureNavTab/_featureNavTab.scss +27 -27
- package/scss/components/FeatureSideNav/_featureSideNav.scss +76 -76
- package/scss/components/FeatureSideNavLink/_featureSideNavLink.scss +49 -49
- package/scss/components/Feedback/_feedback.scss +46 -46
- package/scss/components/Header/_header.scss +179 -179
- package/scss/components/Header/_headerAppSwitcher.scss +117 -117
- package/scss/components/Header/_headerMenu.scss +30 -30
- package/scss/components/Header/_headerMenuItem.scss +65 -65
- package/scss/components/Header/_headerTeamSwitcher.scss +195 -195
- package/scss/components/Header/_userRequests.scss +36 -36
- package/scss/components/ImageModal/_imageModal.scss +51 -51
- package/scss/components/MemberBar/_memberBar.scss +99 -99
- package/scss/components/Modal/_modal.scss +163 -163
- package/scss/components/ModalConfirmEdit/_modalConfirmEdit.scss +113 -113
- package/scss/components/Notifications/_notifications.scss +57 -57
- package/scss/components/PlatformBanner/_platformBanner.scss +30 -30
- package/scss/components/PlatformNotifications/_platformNotifications.scss +230 -230
- package/scss/components/PrivacyRedirect/_privacyRedirect.scss +43 -43
- package/scss/components/PrivacyStatement/_privacyStatement.scss +137 -137
- package/scss/components/ProfileSettings/_profileSettings.scss +117 -117
- package/scss/components/ProtectedRoute/_protectedRoute.scss +32 -32
- package/scss/components/RadioGroup/_radioGroup.scss +46 -46
- package/scss/components/RichTextArea/_richTextArea.scss +82 -82
- package/scss/components/SignOut/_signOut.scss +51 -51
- package/scss/components/SupportCenter/_supportCenter.scss +16 -16
- package/scss/components/TextArea/_textArea.scss +19 -19
- package/scss/components/TextInput/_textInput.scss +26 -26
- package/scss/components/Toggle/_toggle.scss +80 -80
- package/scss/components/TooltipHover/_tooltip.scss +48 -48
- package/scss/global/_config.scss +14 -14
- package/scss/global/_tippy.scss +49 -49
- package/scss/global/index.scss +401 -401
- package/scss/global/themes/_boomerang.scss +184 -184
- package/scss/global/themes/_default.scss +79 -79
- package/scss/global/themes/_shell-tokens.scss +42 -42
- package/scss/global/utils/_animations.scss +15 -15
- package/scss/global/utils/_mixins.scss +67 -67
- package/scss/global/utils/index.scss +10 -10
|
@@ -37,584 +37,584 @@ var React__default = /*#__PURE__*/_interopDefault(React);
|
|
|
37
37
|
var yup__namespace = /*#__PURE__*/_interopNamespace(yup);
|
|
38
38
|
var get__default = /*#__PURE__*/_interopDefault(get);
|
|
39
39
|
|
|
40
|
-
/*
|
|
41
|
-
IBM Confidential
|
|
42
|
-
694970X, 69497O0
|
|
43
|
-
© Copyright IBM Corp. 2022, 2024
|
|
44
|
-
*/
|
|
45
|
-
/**
|
|
46
|
-
*
|
|
47
|
-
* @param {string} value - value to test for valid property syntax
|
|
48
|
-
*/
|
|
49
|
-
function isPropertySyntaxValid({ value, customPropertySyntaxPattern, propsSyntaxFound }) {
|
|
50
|
-
// Look property pattern and capture group for the property itself
|
|
51
|
-
let match = value.match(customPropertySyntaxPattern);
|
|
52
|
-
// if the first matched group is truthy, then a property has been entered
|
|
53
|
-
// Empty properties are not valid
|
|
54
|
-
if (Array.isArray(match) && match.length === propsSyntaxFound) {
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function validateUrlWithProperties(customPropertySyntaxPattern, customPropertyStartsWithPattern) {
|
|
62
|
-
return function () {
|
|
63
|
-
return this.transform(function (value, originalValue) {
|
|
64
|
-
const propsSyntaxFound = value.match(customPropertyStartsWithPattern)?.length ?? 0;
|
|
65
|
-
if ((isUrl.default(value) && !Boolean(propsSyntaxFound)) ||
|
|
66
|
-
isPropertySyntaxValid({ value, customPropertySyntaxPattern, propsSyntaxFound })) {
|
|
67
|
-
return value;
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
function validateEmailWithProperties(customPropertySyntaxPattern, customPropertyStartsWithPattern) {
|
|
74
|
-
return function () {
|
|
75
|
-
return this.transform(function (value, originalValue) {
|
|
76
|
-
// Simple pattern for emails
|
|
77
|
-
const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
78
|
-
const propsSyntaxFound = value.match(customPropertyStartsWithPattern)?.length ?? 0;
|
|
79
|
-
if ((isValidEmail && !Boolean(propsSyntaxFound)) ||
|
|
80
|
-
isPropertySyntaxValid({ value, customPropertySyntaxPattern, propsSyntaxFound })) {
|
|
81
|
-
return value;
|
|
82
|
-
}
|
|
83
|
-
return false;
|
|
84
|
-
});
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
function registerCustomPropertyMethods(customPropertySyntaxPattern, customPropertyStartsWithPattern) {
|
|
88
|
-
const validateUrl = validateUrlWithProperties(customPropertySyntaxPattern, customPropertyStartsWithPattern);
|
|
89
|
-
const validateEmail = validateEmailWithProperties(customPropertySyntaxPattern, customPropertyStartsWithPattern);
|
|
90
|
-
yup__namespace.addMethod(yup__namespace.string, "urlWithCustomProperty", validateUrl);
|
|
91
|
-
yup__namespace.addMethod(yup__namespace.string, "emailWithCustomProperty", validateEmail);
|
|
92
|
-
}
|
|
93
|
-
function getGoverningSelectKeysMap({ governingKey, governingJsonKey, governingKeys, inputs, }) {
|
|
94
|
-
if (Boolean(governingKey) && governingKey !== governingJsonKey)
|
|
95
|
-
governingKeys.unshift(governingKey);
|
|
96
|
-
const governingInput = inputs.find((input) => input.key === governingKey) ?? {};
|
|
97
|
-
/** Continue recursion if the governing select has a governingKey */
|
|
98
|
-
if (Boolean(governingInput.governingKey)) {
|
|
99
|
-
return getGoverningSelectKeysMap({
|
|
100
|
-
governingKey: governingInput.governingKey,
|
|
101
|
-
governingJsonKey,
|
|
102
|
-
governingKeys,
|
|
103
|
-
inputs,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
return governingKeys;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
function getGoverningSelectDeepOptions({ formikValues, governingInputJsonObject, governingKeys, input, inputs, }) {
|
|
111
|
-
const nextKey = governingKeys.shift();
|
|
112
|
-
if (nextKey) {
|
|
113
|
-
const nextKeyInput = inputs.find((input) => input.key === nextKey) ?? {};
|
|
114
|
-
const nextInputJsonObject = governingInputJsonObject[nextKey].find((jsonElement) => jsonElement[nextKeyInput.jsonKey] === formikValues[nextKey]);
|
|
115
|
-
return getGoverningSelectDeepOptions({
|
|
116
|
-
formikValues,
|
|
117
|
-
governingInputJsonObject: nextInputJsonObject,
|
|
118
|
-
governingKeys,
|
|
119
|
-
input,
|
|
120
|
-
inputs,
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
return governingInputJsonObject[input.key].map((option) => ({
|
|
125
|
-
label: option[input.jsonLabel],
|
|
126
|
-
value: option[input.jsonKey],
|
|
127
|
-
}));
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
async function handleGoverningSelectChange({ formikProps, input, inputs, isInputBeingChanged, selectedItem, }) {
|
|
131
|
-
const { key, value } = input;
|
|
132
|
-
const inputsGovernedByCurrentOne = inputs.filter((formikInput) => formikInput.governingKey === key);
|
|
133
|
-
if (selectedItem?.value !== value) {
|
|
134
|
-
/** Erase value of governed inputs */
|
|
135
|
-
if (inputsGovernedByCurrentOne.length) {
|
|
136
|
-
await inputsGovernedByCurrentOne.forEach(async (input) => {
|
|
137
|
-
await handleGoverningSelectChange({ formikProps, input, inputs, isInputBeingChanged: false, selectedItem: null });
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
// only the top governing select should display warnings if changed and reset touched status for governed ones
|
|
141
|
-
await formikProps.setFieldTouched(`['${key}']`, isInputBeingChanged);
|
|
142
|
-
formikProps.setFieldValue(`['${key}']`, selectedItem ? selectedItem.value : "");
|
|
143
|
-
formikProps.setFieldValue(`['${key}-keyLabel']`, selectedItem ? selectedItem.label : "");
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
function generateYupAst({ inputs, allowCustomPropertySyntax, customPropertySyntaxPattern, customPropertyStartsWithPattern, useCSVforArrays, }) {
|
|
147
|
-
if (allowCustomPropertySyntax) {
|
|
148
|
-
registerCustomPropertyMethods(customPropertySyntaxPattern, customPropertyStartsWithPattern);
|
|
149
|
-
}
|
|
150
|
-
let yupShape = {};
|
|
151
|
-
inputs.forEach((input) => {
|
|
152
|
-
let yupValidationArray = [];
|
|
153
|
-
const inputType = input.type ?? "";
|
|
154
|
-
if (!DataDrivenInputTypes.INPUT_TYPES_ARRAY.includes(inputType)) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (inputType === DataDrivenInputTypes.DATE_TYPES.DATE) {
|
|
158
|
-
yupValidationArray.push(["yup.date", "Enter a valid date"]);
|
|
159
|
-
}
|
|
160
|
-
if (inputType === DataDrivenInputTypes.TEXT_AREA_TYPES.TEXT_AREA ||
|
|
161
|
-
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.EMAIL ||
|
|
162
|
-
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.PASSWORD ||
|
|
163
|
-
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.SECURED ||
|
|
164
|
-
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.TEL ||
|
|
165
|
-
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.TEXT ||
|
|
166
|
-
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.TIME ||
|
|
167
|
-
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.URL ||
|
|
168
|
-
inputType === DataDrivenInputTypes.RADIO_TYPES.RADIO ||
|
|
169
|
-
inputType === DataDrivenInputTypes.SELECT_TYPES.SELECT ||
|
|
170
|
-
inputType?.startsWith(DataDrivenInputTypes.TEXT_EDITOR_TYPES.TEXT_EDITOR)) {
|
|
171
|
-
yupValidationArray.push(["yup.string"]);
|
|
172
|
-
// if (
|
|
173
|
-
// allowCustomPropertySyntax &&
|
|
174
|
-
// inputType !== TEXT_INPUT_TYPES.EMAIL &&
|
|
175
|
-
// inputType !== TEXT_INPUT_TYPES.URL &&
|
|
176
|
-
// inputType !== TEXT_INPUT_TYPES.SECURED &&
|
|
177
|
-
// inputType !== TEXT_INPUT_TYPES.PASSWORD
|
|
178
|
-
// )
|
|
179
|
-
// yupValidationArray.push(
|
|
180
|
-
// ['yup.customProperty'],
|
|
181
|
-
// ['yup.typeError', 'Enter valid syntax for a property']
|
|
182
|
-
// );
|
|
183
|
-
// Create a customValidator for each input b/c regex deserialization
|
|
184
|
-
// does not work currently
|
|
185
|
-
const { pattern } = input;
|
|
186
|
-
if (typeof pattern === "string") {
|
|
187
|
-
customValidators.addCustomValidator(`${input.key}-matches`, yup__namespace.string().test(`${input.key}-matches`, input.patternInvalidText || `Enter a value that matches pattern: ${input.pattern}`, (value) => {
|
|
188
|
-
if (!input.required && !Boolean(value)) {
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
else
|
|
192
|
-
return new RegExp(pattern).test(value);
|
|
193
|
-
}));
|
|
194
|
-
yupValidationArray.push([`${input.key}-matches`]);
|
|
195
|
-
}
|
|
196
|
-
//TODO: figure out how to update serialization in yup-ast so we can use the native "matches" validator
|
|
197
|
-
// if (input.pattern) {
|
|
198
|
-
// yupValidationArray.push([
|
|
199
|
-
// 'yup.matches',
|
|
200
|
-
// new RegExp(input.pattern),
|
|
201
|
-
// {
|
|
202
|
-
// message: `Enter a value that matches pattern ${input.pattern}`,
|
|
203
|
-
// excludeEmptyString: true,
|
|
204
|
-
// },
|
|
205
|
-
// ]);
|
|
206
|
-
// }
|
|
207
|
-
if (inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.EMAIL) {
|
|
208
|
-
if (allowCustomPropertySyntax)
|
|
209
|
-
yupValidationArray.push(["yup.emailWithCustomProperty"], ["yup.typeError", "Enter a valid email"]);
|
|
210
|
-
else
|
|
211
|
-
yupValidationArray.push(["yup.email", "Enter a valid email"]);
|
|
212
|
-
}
|
|
213
|
-
if (inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.URL) {
|
|
214
|
-
if (allowCustomPropertySyntax)
|
|
215
|
-
yupValidationArray.push(["yup.urlWithCustomProperty"], ["yup.typeError", "Enter a valid URL"]);
|
|
216
|
-
else
|
|
217
|
-
yupValidationArray.push(["yup.url", "Enter a valid URL"]);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
if (inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.NUMBER) {
|
|
221
|
-
yupValidationArray.push(["yup.number", "Enter a number"]);
|
|
222
|
-
}
|
|
223
|
-
if (inputType === DataDrivenInputTypes.BOOLEAN_TYPES.BOOLEAN) {
|
|
224
|
-
yupValidationArray.push(["yup.boolean"]);
|
|
225
|
-
}
|
|
226
|
-
if (inputType === DataDrivenInputTypes.MULTI_SELECT_TYPES.MULTI_SELECT ||
|
|
227
|
-
inputType === DataDrivenInputTypes.CREATABLE_TYPES.CREATABLE_SINGLE ||
|
|
228
|
-
inputType === DataDrivenInputTypes.CREATABLE_TYPES.CREATABLE_SINGLE_NON_DELETABLE ||
|
|
229
|
-
inputType === DataDrivenInputTypes.CREATABLE_TYPES.CREATABLE_PAIR ||
|
|
230
|
-
inputType === DataDrivenInputTypes.CREATABLE_TYPES.CREATABLE_PAIR_NON_DELETABLE ||
|
|
231
|
-
inputType === DataDrivenInputTypes.CHECKBOX_TYPES.CHECKBOX) {
|
|
232
|
-
if (useCSVforArrays) {
|
|
233
|
-
yupValidationArray.push(["yup.string"]);
|
|
234
|
-
const { pattern } = input;
|
|
235
|
-
if (pattern === typeof "string") {
|
|
236
|
-
customValidators.addCustomValidator(`${input.key}-matches`, yup__namespace.string().test(`${input.key}-matches`, input.patternInvalidText || `Enter values that matches pattern: ${input.pattern}`, (csv) => {
|
|
237
|
-
const regexTester = new RegExp(pattern);
|
|
238
|
-
return csv?.split(",").every((val) => regexTester.test(val)) ?? false;
|
|
239
|
-
}));
|
|
240
|
-
yupValidationArray.push([`${input.key}-matches`]);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
yupValidationArray.push(["yup.array"]);
|
|
245
|
-
const { pattern } = input;
|
|
246
|
-
if (typeof pattern === "string") {
|
|
247
|
-
customValidators.addCustomValidator(`${input.key}-matches`, yup__namespace.array().test(`${input.key}-matches`, input.patternInvalidText || `Enter values that matches pattern: ${pattern}`, (values) => {
|
|
248
|
-
const regexTester = new RegExp(pattern);
|
|
249
|
-
return values?.every((val) => regexTester.test(val)) ?? false;
|
|
250
|
-
}));
|
|
251
|
-
yupValidationArray.push([`${input.key}-matches`]);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
if (Object.values(DataDrivenInputTypes.TEXT_INPUT_TYPES).includes(inputType) ||
|
|
256
|
-
inputType === DataDrivenInputTypes.TEXT_AREA_TYPES.TEXT_AREA ||
|
|
257
|
-
inputType === DataDrivenInputTypes.TEXT_EDITOR_TYPES.TEXT_EDITOR) {
|
|
258
|
-
if (inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.NUMBER) {
|
|
259
|
-
if (input.min) {
|
|
260
|
-
yupValidationArray.push(["yup.min", input.min, `Enter value greater than ${input.min}`]);
|
|
261
|
-
}
|
|
262
|
-
if (input.max) {
|
|
263
|
-
yupValidationArray.push(["yup.max", input.max, `Enter value less than ${input.max}`]);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
if (input.min) {
|
|
268
|
-
yupValidationArray.push(["yup.min", input.min, `Enter at least ${input.min} characters`]);
|
|
269
|
-
}
|
|
270
|
-
if (input.max) {
|
|
271
|
-
yupValidationArray.push(["yup.max", input.max, `Enter at most ${input.max} characters`]);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
if (Array.isArray(input.invalidValues)) {
|
|
276
|
-
yupValidationArray.push(["yup.notOneOf", input.invalidValues, `Enter an allowed value`]);
|
|
277
|
-
}
|
|
278
|
-
if (input.required) {
|
|
279
|
-
if (inputType === DataDrivenInputTypes.BOOLEAN_TYPES.BOOLEAN) {
|
|
280
|
-
yupValidationArray.push(["yup.oneOf", [true], "Toggle must be checked"]);
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
yupValidationArray.push(["yup.required", `Enter a value for ${input.label}`]);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
if (yupValidationArray.length > 0) {
|
|
287
|
-
yupShape[input.key] = yupValidationArray;
|
|
288
|
-
}
|
|
289
|
-
});
|
|
290
|
-
return [["yup.object"], ["yup.shape", yupShape]];
|
|
291
|
-
}
|
|
292
|
-
function generateYupSchema({ inputs, allowCustomPropertySyntax, customPropertySyntaxPattern, customPropertyStartsWithPattern, useCSVforArrays, validationSchemaExtension, }) {
|
|
293
|
-
let validationSchema = astGenerator.transformAll(generateYupAst({
|
|
294
|
-
inputs,
|
|
295
|
-
allowCustomPropertySyntax,
|
|
296
|
-
customPropertySyntaxPattern,
|
|
297
|
-
customPropertyStartsWithPattern,
|
|
298
|
-
useCSVforArrays,
|
|
299
|
-
}));
|
|
300
|
-
if (validationSchemaExtension) {
|
|
301
|
-
validationSchema = validationSchema.concat(validationSchemaExtension);
|
|
302
|
-
}
|
|
303
|
-
return validationSchema;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Get initial values of each input in array of inputs
|
|
307
|
-
*/
|
|
308
|
-
const determineInitialValues = (inputs, useCSVforArrays) => {
|
|
309
|
-
const values = {};
|
|
310
|
-
inputs.forEach((input) => {
|
|
311
|
-
let value = "";
|
|
312
|
-
let valueToCheck = input.value || input.defaultValue;
|
|
313
|
-
const isArrayInput = !useCSVforArrays && Object.values(DataDrivenInputTypes.ARRAY_INPUT_TYPES).includes(input.type);
|
|
314
|
-
if (isArrayInput) {
|
|
315
|
-
valueToCheck = input.value || input.defaultValue || input.values || input.defaultValues;
|
|
316
|
-
}
|
|
317
|
-
if (valueToCheck) {
|
|
318
|
-
switch (valueToCheck) {
|
|
319
|
-
case "false": {
|
|
320
|
-
value = false;
|
|
321
|
-
break;
|
|
322
|
-
}
|
|
323
|
-
case "true": {
|
|
324
|
-
value = true;
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
default: {
|
|
328
|
-
value = valueToCheck;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
values[input.key] = value;
|
|
333
|
-
});
|
|
334
|
-
return values;
|
|
335
|
-
};
|
|
336
|
-
/**
|
|
337
|
-
* Check if an input X needs to be conditionally rendered
|
|
338
|
-
* If it does, then find an input Y in the same section that has key equal to the input X's requiredForKey
|
|
339
|
-
* If input Y has a value that is present in input X's requiredValueOf array, then render X
|
|
340
|
-
*/
|
|
341
|
-
const conditionallyRenderInput = (input, values) => {
|
|
342
|
-
if (!input.conditionallyRender) {
|
|
343
|
-
return true;
|
|
344
|
-
}
|
|
345
|
-
if (input.requiredForKey && input.requiredValueOf) {
|
|
346
|
-
/**
|
|
347
|
-
* Check which input in this section has the key equal to requiredForKey and get its value
|
|
348
|
-
*/
|
|
349
|
-
const requiredForKeyInputValue = values[input.requiredForKey];
|
|
350
|
-
const valuesInputIsRenderedFor = input.requiredValueOf;
|
|
351
|
-
/**
|
|
352
|
-
* If the value of the input this input is required for is an array loop through those values to find a matching one
|
|
353
|
-
* by going through all of configured values for the input - the "requiredValueOf" of property
|
|
354
|
-
* Check for the value and the string of the value bc of how the services work. "true" and "false" are strings not boolean values
|
|
355
|
-
*/
|
|
356
|
-
if (Array.isArray(requiredForKeyInputValue)) {
|
|
357
|
-
for (let requiredForValue of valuesInputIsRenderedFor) {
|
|
358
|
-
for (let singleRequiredForKeyInputValue of requiredForKeyInputValue) {
|
|
359
|
-
if (requiredForValue === singleRequiredForKeyInputValue ||
|
|
360
|
-
requiredForValue === String(singleRequiredForKeyInputValue)) {
|
|
361
|
-
return true;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
for (let requiredForValue of valuesInputIsRenderedFor) {
|
|
368
|
-
if (requiredForValue === requiredForKeyInputValue || requiredForValue === String(requiredForKeyInputValue)) {
|
|
369
|
-
return true;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
else {
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
/**
|
|
379
|
-
* Map of the input groups to specifc props to be passed
|
|
380
|
-
*/
|
|
381
|
-
const TYPE_PROPS = {
|
|
382
|
-
[DataDrivenInputTypes.INPUT_GROUPS.CHECKBOX]: (formikProps, { key }, inputs, useCSVforArrays) => ({
|
|
383
|
-
onChange: (value, id, event, selectedItems) => {
|
|
384
|
-
if (useCSVforArrays) {
|
|
385
|
-
formikProps.setFieldValue(`['${key}']`, selectedItems?.join() ?? "");
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
formikProps.setFieldValue(`['${key}']`, selectedItems);
|
|
389
|
-
}
|
|
390
|
-
},
|
|
391
|
-
}),
|
|
392
|
-
[DataDrivenInputTypes.INPUT_GROUPS.CREATABLE]: (formikProps, { key }, inputs, useCSVforArrays) => ({
|
|
393
|
-
onChange: (createdItems) => {
|
|
394
|
-
formikProps.setFieldTouched(`['${key}']`, true);
|
|
395
|
-
if (useCSVforArrays) {
|
|
396
|
-
formikProps.setFieldValue(`['${key}']`, createdItems?.join() ?? "");
|
|
397
|
-
}
|
|
398
|
-
else {
|
|
399
|
-
formikProps.setFieldValue(`['${key}']`, createdItems);
|
|
400
|
-
}
|
|
401
|
-
},
|
|
402
|
-
onInputBlur: () => formikProps.setFieldTouched(`['${key}']`, true, true),
|
|
403
|
-
}),
|
|
404
|
-
[DataDrivenInputTypes.INPUT_GROUPS.DATE]: (formikProps, { key, type }) => type === DataDrivenInputTypes.DATE_TYPES.DATE_RANGE
|
|
405
|
-
? {
|
|
406
|
-
onChange: (dateArray) => formikProps.setFieldValue(`['${key}']`, dateArray?.map((date) => date.toISOString())),
|
|
407
|
-
}
|
|
408
|
-
: {
|
|
409
|
-
onChange: formikProps.handleChange,
|
|
410
|
-
onCalendarChange: (dateArray) => formikProps.setFieldValue(`['${key}']`, dateArray[0]?.toISOString()),
|
|
411
|
-
},
|
|
412
|
-
[DataDrivenInputTypes.INPUT_GROUPS.MULTI_SELECT]: (formikProps, { key }, inputs, useCSVforArrays) => ({
|
|
413
|
-
onChange: async ({ selectedItems }) => {
|
|
414
|
-
await formikProps.setFieldTouched(`['${key}']`, true);
|
|
415
|
-
if (useCSVforArrays) {
|
|
416
|
-
formikProps.setFieldValue(`['${key}']`, selectedItems ? selectedItems.map((item) => item && item.value).join() : "");
|
|
417
|
-
}
|
|
418
|
-
else {
|
|
419
|
-
formikProps.setFieldValue(`['${key}']`, selectedItems.map((item) => item && item.value));
|
|
420
|
-
}
|
|
421
|
-
},
|
|
422
|
-
onInputBlur: () => formikProps.setFieldTouched(`['${key}']`, true, true),
|
|
423
|
-
}),
|
|
424
|
-
[DataDrivenInputTypes.INPUT_GROUPS.RADIO]: (formikProps, { key }) => ({
|
|
425
|
-
onChange: (value) => formikProps.setFieldValue(`['${key}']`, value),
|
|
426
|
-
}),
|
|
427
|
-
[DataDrivenInputTypes.INPUT_GROUPS.SELECT]: (formikProps, input, inputs) => {
|
|
428
|
-
const { key, value } = input;
|
|
429
|
-
let typeProps = {
|
|
430
|
-
onChange: async ({ selectedItem }) => {
|
|
431
|
-
if (selectedItem.value !== value) {
|
|
432
|
-
await formikProps.setFieldTouched(`['${key}']`, true);
|
|
433
|
-
formikProps.setFieldValue(`['${key}']`, selectedItem ? selectedItem.value : "");
|
|
434
|
-
}
|
|
435
|
-
},
|
|
436
|
-
onInputBlur: () => formikProps.setFieldTouched(`['${key}']`, true, true),
|
|
437
|
-
};
|
|
438
|
-
/**
|
|
439
|
-
* Start Governing Selects logic if input contains governingJsonKey
|
|
440
|
-
*/
|
|
441
|
-
if (Boolean(input.governingJsonKey)) {
|
|
442
|
-
const { governingJsonKey, governingKey, jsonKey, jsonLabel } = input;
|
|
443
|
-
const governingJsonInput = inputs.find((input) => input.key === governingJsonKey);
|
|
444
|
-
/** Check if governingJson with all governing selects data exists as an array */
|
|
445
|
-
if (governingJsonInput && Array.isArray(governingJsonInput.governingJson)) {
|
|
446
|
-
const { governingJson } = governingJsonInput;
|
|
447
|
-
let governingOptions = [];
|
|
448
|
-
let governingDisabled = false;
|
|
449
|
-
/**
|
|
450
|
-
* Select "governingOptions"
|
|
451
|
-
* If current select is the top level governing select, just get the top level options from the json
|
|
452
|
-
*/
|
|
453
|
-
if (key === governingJsonKey) {
|
|
454
|
-
governingOptions = governingJson.map((option) => ({
|
|
455
|
-
label: option[jsonLabel],
|
|
456
|
-
value: option[jsonKey],
|
|
457
|
-
}));
|
|
458
|
-
}
|
|
459
|
-
else {
|
|
460
|
-
/** Check if the select that governs this one has a value and disable if it doesn't */
|
|
461
|
-
const governingSelectValue = formikProps.values[governingKey];
|
|
462
|
-
if (Boolean(governingSelectValue)) {
|
|
463
|
-
let governingKeys = getGoverningSelectKeysMap({
|
|
464
|
-
governingKey,
|
|
465
|
-
governingJsonKey,
|
|
466
|
-
governingKeys: [],
|
|
467
|
-
inputs,
|
|
468
|
-
});
|
|
469
|
-
governingOptions = getGoverningSelectDeepOptions({
|
|
470
|
-
formikValues: formikProps.values,
|
|
471
|
-
governingInputJsonObject: governingJson.find((jsonElement) => jsonElement[governingJsonInput.jsonKey] === formikProps.values[governingJsonKey]),
|
|
472
|
-
governingKeys: [...governingKeys],
|
|
473
|
-
input,
|
|
474
|
-
inputs,
|
|
475
|
-
});
|
|
476
|
-
}
|
|
477
|
-
else {
|
|
478
|
-
governingDisabled = true;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
typeProps = {
|
|
482
|
-
...typeProps,
|
|
483
|
-
onChange: ({ selectedItem }) => handleGoverningSelectChange({ formikProps, input, inputs, selectedItem, isInputBeingChanged: true }),
|
|
484
|
-
governingOptions,
|
|
485
|
-
governingDisabled,
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
return typeProps;
|
|
490
|
-
},
|
|
491
|
-
[DataDrivenInputTypes.INPUT_GROUPS.TEXT_AREA]: (formikProps) => ({
|
|
492
|
-
onChange: formikProps.handleChange,
|
|
493
|
-
}),
|
|
494
|
-
[DataDrivenInputTypes.INPUT_GROUPS.TEXT_EDITOR]: (formikProps) => ({
|
|
495
|
-
onChange: formikProps.handleChange,
|
|
496
|
-
}),
|
|
497
|
-
[DataDrivenInputTypes.INPUT_GROUPS.TEXT_INPUT]: (formikProps) => ({
|
|
498
|
-
onChange: formikProps.handleChange,
|
|
499
|
-
}),
|
|
500
|
-
[DataDrivenInputTypes.INPUT_GROUPS.BOOLEAN]: (formikProps, { key }) => ({
|
|
501
|
-
onChange: (value) => {
|
|
502
|
-
formikProps.setFieldTouched(`['${key}']`, true, true);
|
|
503
|
-
formikProps.setFieldValue(`['${key}']`, value);
|
|
504
|
-
},
|
|
505
|
-
}),
|
|
506
|
-
};
|
|
507
|
-
function determineTypeProps(type, otherProps) {
|
|
508
|
-
const { checkboxListProps, creatableProps, dateProps, multiSelectProps, radioProps, selectProps, textAreaProps, textEditorProps, textInputProps, toggleProps, } = otherProps;
|
|
509
|
-
if (Object.values(DataDrivenInputTypes.CHECKBOX_TYPES).includes(type)) {
|
|
510
|
-
return {
|
|
511
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.CHECKBOX],
|
|
512
|
-
additionalTypeProps: checkboxListProps,
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
if (Object.values(DataDrivenInputTypes.CREATABLE_TYPES).includes(type)) {
|
|
516
|
-
return {
|
|
517
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.CREATABLE],
|
|
518
|
-
additionalTypeProps: creatableProps,
|
|
519
|
-
};
|
|
520
|
-
}
|
|
521
|
-
if (Object.values(DataDrivenInputTypes.DATE_TYPES).includes(type)) {
|
|
522
|
-
return {
|
|
523
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.DATE],
|
|
524
|
-
additionalTypeProps: dateProps,
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
if (Object.values(DataDrivenInputTypes.MULTI_SELECT_TYPES).includes(type)) {
|
|
528
|
-
return {
|
|
529
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.MULTI_SELECT],
|
|
530
|
-
additionalTypeProps: multiSelectProps,
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
if (Object.values(DataDrivenInputTypes.RADIO_TYPES).includes(type)) {
|
|
534
|
-
return {
|
|
535
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.RADIO],
|
|
536
|
-
additionalTypeProps: radioProps,
|
|
537
|
-
};
|
|
538
|
-
}
|
|
539
|
-
if (Object.values(DataDrivenInputTypes.SELECT_TYPES).includes(type)) {
|
|
540
|
-
return {
|
|
541
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.SELECT],
|
|
542
|
-
additionalTypeProps: selectProps,
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
if (Object.values(DataDrivenInputTypes.TEXT_AREA_TYPES).includes(type)) {
|
|
546
|
-
return {
|
|
547
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.TEXT_AREA],
|
|
548
|
-
additionalTypeProps: textAreaProps,
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
if (type.startsWith(DataDrivenInputTypes.TEXT_EDITOR_TYPES.TEXT_EDITOR)) {
|
|
552
|
-
return {
|
|
553
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.TEXT_EDITOR],
|
|
554
|
-
additionalTypeProps: textEditorProps,
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
if (Object.values(DataDrivenInputTypes.TEXT_INPUT_TYPES).includes(type)) {
|
|
558
|
-
return {
|
|
559
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.TEXT_INPUT],
|
|
560
|
-
additionalTypeProps: textInputProps,
|
|
561
|
-
};
|
|
562
|
-
}
|
|
563
|
-
if (Object.values(DataDrivenInputTypes.BOOLEAN_TYPES).includes(type)) {
|
|
564
|
-
return {
|
|
565
|
-
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.BOOLEAN],
|
|
566
|
-
additionalTypeProps: toggleProps,
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
return { typeProps: () => { }, additionalTypeProps: () => { } };
|
|
570
|
-
}
|
|
571
|
-
DynamicFormik.defaultProps = {
|
|
572
|
-
checkboxListProps: (...args) => ({}),
|
|
573
|
-
creatableProps: (...args) => ({}),
|
|
574
|
-
dateProps: (...args) => ({}),
|
|
575
|
-
multiSelectProps: (...args) => ({}),
|
|
576
|
-
radioProps: (...args) => ({}),
|
|
577
|
-
selectProps: (...args) => ({}),
|
|
578
|
-
textAreaProps: (...args) => ({}),
|
|
579
|
-
textEditorProps: (...args) => ({}),
|
|
580
|
-
textInputProps: (...args) => ({}),
|
|
581
|
-
toggleProps: (...args) => ({}),
|
|
582
|
-
};
|
|
583
|
-
function DynamicFormik({ additionalInitialValues = {}, allowCustomPropertySyntax = false, customPropertySyntaxPattern = /\$\{p:([a-zA-Z0-9_.-]+)\}|\$\(([a-zA-Z0-9_.-\s]+)\)/g, customPropertyStartsWithPattern = /\$\{|\$\(/g, children, dataDrivenInputProps, inputProps, initialValues, inputs, onSubmit, useCSVforArrays = false, validationSchema, validationSchemaExtension, ...otherProps }) {
|
|
584
|
-
return (React__default.default.createElement(formik.Formik, { initialValues: (Boolean(initialValues) && initialValues) || {
|
|
585
|
-
...determineInitialValues(inputs, useCSVforArrays),
|
|
586
|
-
...additionalInitialValues,
|
|
587
|
-
}, validationSchema: validationSchema ||
|
|
588
|
-
generateYupSchema({
|
|
589
|
-
inputs,
|
|
590
|
-
allowCustomPropertySyntax,
|
|
591
|
-
customPropertySyntaxPattern,
|
|
592
|
-
customPropertyStartsWithPattern,
|
|
593
|
-
useCSVforArrays,
|
|
594
|
-
validationSchemaExtension,
|
|
595
|
-
}), onSubmit: (values, actions) => {
|
|
596
|
-
if (onSubmit)
|
|
597
|
-
onSubmit(values, actions);
|
|
598
|
-
}, ...otherProps }, (formikProps) => {
|
|
599
|
-
const { values, touched, errors, handleBlur } = formikProps;
|
|
600
|
-
const finalInputs = inputs.filter((input) => conditionallyRenderInput(input, values));
|
|
601
|
-
const dataDrivenInputs = finalInputs.map((input) => {
|
|
602
|
-
const { key, type, value, // eslint-disable-line
|
|
603
|
-
...otherInputsProps } = input;
|
|
604
|
-
const inputValue = values[key] !== undefined &&
|
|
605
|
-
values[key] !== null &&
|
|
606
|
-
(Object.values(DataDrivenInputTypes.TEXT_INPUT_TYPES).includes(type) ||
|
|
607
|
-
type === DataDrivenInputTypes.TEXT_AREA_TYPES.TEXT_AREA ||
|
|
608
|
-
type === DataDrivenInputTypes.TEXT_EDITOR_TYPES.TEXT_EDITOR)
|
|
609
|
-
? values[key].toString()
|
|
610
|
-
: values[key];
|
|
611
|
-
const invalidText = get__default.default(errors, key);
|
|
612
|
-
const invalid = invalidText && get__default.default(touched, key);
|
|
613
|
-
const { typeProps = () => { }, additionalTypeProps = () => { } } = determineTypeProps(type, otherProps);
|
|
614
|
-
return (React__default.default.createElement(DataDrivenInput.default, { key: key, customComponent: input.customComponent, formikProps: formikProps, id: `['${key}']`, invalid: invalid, invalidText: invalidText, name: `['${key}']`, onBlur: handleBlur, type: type, value: inputValue, ...typeProps(formikProps, input, finalInputs, useCSVforArrays), ...otherInputsProps, ...inputProps, ...additionalTypeProps({ formikProps, input }), ...dataDrivenInputProps }));
|
|
615
|
-
});
|
|
616
|
-
return (React__default.default.createElement("div", { className: `${settings.prefix}--bmrg-dynamic-formik` }, children({ inputs: dataDrivenInputs, formikProps })));
|
|
617
|
-
}));
|
|
40
|
+
/*
|
|
41
|
+
IBM Confidential
|
|
42
|
+
694970X, 69497O0
|
|
43
|
+
© Copyright IBM Corp. 2022, 2024
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {string} value - value to test for valid property syntax
|
|
48
|
+
*/
|
|
49
|
+
function isPropertySyntaxValid({ value, customPropertySyntaxPattern, propsSyntaxFound }) {
|
|
50
|
+
// Look property pattern and capture group for the property itself
|
|
51
|
+
let match = value.match(customPropertySyntaxPattern);
|
|
52
|
+
// if the first matched group is truthy, then a property has been entered
|
|
53
|
+
// Empty properties are not valid
|
|
54
|
+
if (Array.isArray(match) && match.length === propsSyntaxFound) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function validateUrlWithProperties(customPropertySyntaxPattern, customPropertyStartsWithPattern) {
|
|
62
|
+
return function () {
|
|
63
|
+
return this.transform(function (value, originalValue) {
|
|
64
|
+
const propsSyntaxFound = value.match(customPropertyStartsWithPattern)?.length ?? 0;
|
|
65
|
+
if ((isUrl.default(value) && !Boolean(propsSyntaxFound)) ||
|
|
66
|
+
isPropertySyntaxValid({ value, customPropertySyntaxPattern, propsSyntaxFound })) {
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function validateEmailWithProperties(customPropertySyntaxPattern, customPropertyStartsWithPattern) {
|
|
74
|
+
return function () {
|
|
75
|
+
return this.transform(function (value, originalValue) {
|
|
76
|
+
// Simple pattern for emails
|
|
77
|
+
const isValidEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
78
|
+
const propsSyntaxFound = value.match(customPropertyStartsWithPattern)?.length ?? 0;
|
|
79
|
+
if ((isValidEmail && !Boolean(propsSyntaxFound)) ||
|
|
80
|
+
isPropertySyntaxValid({ value, customPropertySyntaxPattern, propsSyntaxFound })) {
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function registerCustomPropertyMethods(customPropertySyntaxPattern, customPropertyStartsWithPattern) {
|
|
88
|
+
const validateUrl = validateUrlWithProperties(customPropertySyntaxPattern, customPropertyStartsWithPattern);
|
|
89
|
+
const validateEmail = validateEmailWithProperties(customPropertySyntaxPattern, customPropertyStartsWithPattern);
|
|
90
|
+
yup__namespace.addMethod(yup__namespace.string, "urlWithCustomProperty", validateUrl);
|
|
91
|
+
yup__namespace.addMethod(yup__namespace.string, "emailWithCustomProperty", validateEmail);
|
|
92
|
+
}
|
|
93
|
+
function getGoverningSelectKeysMap({ governingKey, governingJsonKey, governingKeys, inputs, }) {
|
|
94
|
+
if (Boolean(governingKey) && governingKey !== governingJsonKey)
|
|
95
|
+
governingKeys.unshift(governingKey);
|
|
96
|
+
const governingInput = inputs.find((input) => input.key === governingKey) ?? {};
|
|
97
|
+
/** Continue recursion if the governing select has a governingKey */
|
|
98
|
+
if (Boolean(governingInput.governingKey)) {
|
|
99
|
+
return getGoverningSelectKeysMap({
|
|
100
|
+
governingKey: governingInput.governingKey,
|
|
101
|
+
governingJsonKey,
|
|
102
|
+
governingKeys,
|
|
103
|
+
inputs,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
return governingKeys;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function getGoverningSelectDeepOptions({ formikValues, governingInputJsonObject, governingKeys, input, inputs, }) {
|
|
111
|
+
const nextKey = governingKeys.shift();
|
|
112
|
+
if (nextKey) {
|
|
113
|
+
const nextKeyInput = inputs.find((input) => input.key === nextKey) ?? {};
|
|
114
|
+
const nextInputJsonObject = governingInputJsonObject[nextKey].find((jsonElement) => jsonElement[nextKeyInput.jsonKey] === formikValues[nextKey]);
|
|
115
|
+
return getGoverningSelectDeepOptions({
|
|
116
|
+
formikValues,
|
|
117
|
+
governingInputJsonObject: nextInputJsonObject,
|
|
118
|
+
governingKeys,
|
|
119
|
+
input,
|
|
120
|
+
inputs,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
return governingInputJsonObject[input.key].map((option) => ({
|
|
125
|
+
label: option[input.jsonLabel],
|
|
126
|
+
value: option[input.jsonKey],
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function handleGoverningSelectChange({ formikProps, input, inputs, isInputBeingChanged, selectedItem, }) {
|
|
131
|
+
const { key, value } = input;
|
|
132
|
+
const inputsGovernedByCurrentOne = inputs.filter((formikInput) => formikInput.governingKey === key);
|
|
133
|
+
if (selectedItem?.value !== value) {
|
|
134
|
+
/** Erase value of governed inputs */
|
|
135
|
+
if (inputsGovernedByCurrentOne.length) {
|
|
136
|
+
await inputsGovernedByCurrentOne.forEach(async (input) => {
|
|
137
|
+
await handleGoverningSelectChange({ formikProps, input, inputs, isInputBeingChanged: false, selectedItem: null });
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
// only the top governing select should display warnings if changed and reset touched status for governed ones
|
|
141
|
+
await formikProps.setFieldTouched(`['${key}']`, isInputBeingChanged);
|
|
142
|
+
formikProps.setFieldValue(`['${key}']`, selectedItem ? selectedItem.value : "");
|
|
143
|
+
formikProps.setFieldValue(`['${key}-keyLabel']`, selectedItem ? selectedItem.label : "");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function generateYupAst({ inputs, allowCustomPropertySyntax, customPropertySyntaxPattern, customPropertyStartsWithPattern, useCSVforArrays, }) {
|
|
147
|
+
if (allowCustomPropertySyntax) {
|
|
148
|
+
registerCustomPropertyMethods(customPropertySyntaxPattern, customPropertyStartsWithPattern);
|
|
149
|
+
}
|
|
150
|
+
let yupShape = {};
|
|
151
|
+
inputs.forEach((input) => {
|
|
152
|
+
let yupValidationArray = [];
|
|
153
|
+
const inputType = input.type ?? "";
|
|
154
|
+
if (!DataDrivenInputTypes.INPUT_TYPES_ARRAY.includes(inputType)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (inputType === DataDrivenInputTypes.DATE_TYPES.DATE) {
|
|
158
|
+
yupValidationArray.push(["yup.date", "Enter a valid date"]);
|
|
159
|
+
}
|
|
160
|
+
if (inputType === DataDrivenInputTypes.TEXT_AREA_TYPES.TEXT_AREA ||
|
|
161
|
+
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.EMAIL ||
|
|
162
|
+
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.PASSWORD ||
|
|
163
|
+
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.SECURED ||
|
|
164
|
+
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.TEL ||
|
|
165
|
+
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.TEXT ||
|
|
166
|
+
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.TIME ||
|
|
167
|
+
inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.URL ||
|
|
168
|
+
inputType === DataDrivenInputTypes.RADIO_TYPES.RADIO ||
|
|
169
|
+
inputType === DataDrivenInputTypes.SELECT_TYPES.SELECT ||
|
|
170
|
+
inputType?.startsWith(DataDrivenInputTypes.TEXT_EDITOR_TYPES.TEXT_EDITOR)) {
|
|
171
|
+
yupValidationArray.push(["yup.string"]);
|
|
172
|
+
// if (
|
|
173
|
+
// allowCustomPropertySyntax &&
|
|
174
|
+
// inputType !== TEXT_INPUT_TYPES.EMAIL &&
|
|
175
|
+
// inputType !== TEXT_INPUT_TYPES.URL &&
|
|
176
|
+
// inputType !== TEXT_INPUT_TYPES.SECURED &&
|
|
177
|
+
// inputType !== TEXT_INPUT_TYPES.PASSWORD
|
|
178
|
+
// )
|
|
179
|
+
// yupValidationArray.push(
|
|
180
|
+
// ['yup.customProperty'],
|
|
181
|
+
// ['yup.typeError', 'Enter valid syntax for a property']
|
|
182
|
+
// );
|
|
183
|
+
// Create a customValidator for each input b/c regex deserialization
|
|
184
|
+
// does not work currently
|
|
185
|
+
const { pattern } = input;
|
|
186
|
+
if (typeof pattern === "string") {
|
|
187
|
+
customValidators.addCustomValidator(`${input.key}-matches`, yup__namespace.string().test(`${input.key}-matches`, input.patternInvalidText || `Enter a value that matches pattern: ${input.pattern}`, (value) => {
|
|
188
|
+
if (!input.required && !Boolean(value)) {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
else
|
|
192
|
+
return new RegExp(pattern).test(value);
|
|
193
|
+
}));
|
|
194
|
+
yupValidationArray.push([`${input.key}-matches`]);
|
|
195
|
+
}
|
|
196
|
+
//TODO: figure out how to update serialization in yup-ast so we can use the native "matches" validator
|
|
197
|
+
// if (input.pattern) {
|
|
198
|
+
// yupValidationArray.push([
|
|
199
|
+
// 'yup.matches',
|
|
200
|
+
// new RegExp(input.pattern),
|
|
201
|
+
// {
|
|
202
|
+
// message: `Enter a value that matches pattern ${input.pattern}`,
|
|
203
|
+
// excludeEmptyString: true,
|
|
204
|
+
// },
|
|
205
|
+
// ]);
|
|
206
|
+
// }
|
|
207
|
+
if (inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.EMAIL) {
|
|
208
|
+
if (allowCustomPropertySyntax)
|
|
209
|
+
yupValidationArray.push(["yup.emailWithCustomProperty"], ["yup.typeError", "Enter a valid email"]);
|
|
210
|
+
else
|
|
211
|
+
yupValidationArray.push(["yup.email", "Enter a valid email"]);
|
|
212
|
+
}
|
|
213
|
+
if (inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.URL) {
|
|
214
|
+
if (allowCustomPropertySyntax)
|
|
215
|
+
yupValidationArray.push(["yup.urlWithCustomProperty"], ["yup.typeError", "Enter a valid URL"]);
|
|
216
|
+
else
|
|
217
|
+
yupValidationArray.push(["yup.url", "Enter a valid URL"]);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.NUMBER) {
|
|
221
|
+
yupValidationArray.push(["yup.number", "Enter a number"]);
|
|
222
|
+
}
|
|
223
|
+
if (inputType === DataDrivenInputTypes.BOOLEAN_TYPES.BOOLEAN) {
|
|
224
|
+
yupValidationArray.push(["yup.boolean"]);
|
|
225
|
+
}
|
|
226
|
+
if (inputType === DataDrivenInputTypes.MULTI_SELECT_TYPES.MULTI_SELECT ||
|
|
227
|
+
inputType === DataDrivenInputTypes.CREATABLE_TYPES.CREATABLE_SINGLE ||
|
|
228
|
+
inputType === DataDrivenInputTypes.CREATABLE_TYPES.CREATABLE_SINGLE_NON_DELETABLE ||
|
|
229
|
+
inputType === DataDrivenInputTypes.CREATABLE_TYPES.CREATABLE_PAIR ||
|
|
230
|
+
inputType === DataDrivenInputTypes.CREATABLE_TYPES.CREATABLE_PAIR_NON_DELETABLE ||
|
|
231
|
+
inputType === DataDrivenInputTypes.CHECKBOX_TYPES.CHECKBOX) {
|
|
232
|
+
if (useCSVforArrays) {
|
|
233
|
+
yupValidationArray.push(["yup.string"]);
|
|
234
|
+
const { pattern } = input;
|
|
235
|
+
if (pattern === typeof "string") {
|
|
236
|
+
customValidators.addCustomValidator(`${input.key}-matches`, yup__namespace.string().test(`${input.key}-matches`, input.patternInvalidText || `Enter values that matches pattern: ${input.pattern}`, (csv) => {
|
|
237
|
+
const regexTester = new RegExp(pattern);
|
|
238
|
+
return csv?.split(",").every((val) => regexTester.test(val)) ?? false;
|
|
239
|
+
}));
|
|
240
|
+
yupValidationArray.push([`${input.key}-matches`]);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
yupValidationArray.push(["yup.array"]);
|
|
245
|
+
const { pattern } = input;
|
|
246
|
+
if (typeof pattern === "string") {
|
|
247
|
+
customValidators.addCustomValidator(`${input.key}-matches`, yup__namespace.array().test(`${input.key}-matches`, input.patternInvalidText || `Enter values that matches pattern: ${pattern}`, (values) => {
|
|
248
|
+
const regexTester = new RegExp(pattern);
|
|
249
|
+
return values?.every((val) => regexTester.test(val)) ?? false;
|
|
250
|
+
}));
|
|
251
|
+
yupValidationArray.push([`${input.key}-matches`]);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (Object.values(DataDrivenInputTypes.TEXT_INPUT_TYPES).includes(inputType) ||
|
|
256
|
+
inputType === DataDrivenInputTypes.TEXT_AREA_TYPES.TEXT_AREA ||
|
|
257
|
+
inputType === DataDrivenInputTypes.TEXT_EDITOR_TYPES.TEXT_EDITOR) {
|
|
258
|
+
if (inputType === DataDrivenInputTypes.TEXT_INPUT_TYPES.NUMBER) {
|
|
259
|
+
if (input.min) {
|
|
260
|
+
yupValidationArray.push(["yup.min", input.min, `Enter value greater than ${input.min}`]);
|
|
261
|
+
}
|
|
262
|
+
if (input.max) {
|
|
263
|
+
yupValidationArray.push(["yup.max", input.max, `Enter value less than ${input.max}`]);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
if (input.min) {
|
|
268
|
+
yupValidationArray.push(["yup.min", input.min, `Enter at least ${input.min} characters`]);
|
|
269
|
+
}
|
|
270
|
+
if (input.max) {
|
|
271
|
+
yupValidationArray.push(["yup.max", input.max, `Enter at most ${input.max} characters`]);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (Array.isArray(input.invalidValues)) {
|
|
276
|
+
yupValidationArray.push(["yup.notOneOf", input.invalidValues, `Enter an allowed value`]);
|
|
277
|
+
}
|
|
278
|
+
if (input.required) {
|
|
279
|
+
if (inputType === DataDrivenInputTypes.BOOLEAN_TYPES.BOOLEAN) {
|
|
280
|
+
yupValidationArray.push(["yup.oneOf", [true], "Toggle must be checked"]);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
yupValidationArray.push(["yup.required", `Enter a value for ${input.label}`]);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (yupValidationArray.length > 0) {
|
|
287
|
+
yupShape[input.key] = yupValidationArray;
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
return [["yup.object"], ["yup.shape", yupShape]];
|
|
291
|
+
}
|
|
292
|
+
function generateYupSchema({ inputs, allowCustomPropertySyntax, customPropertySyntaxPattern, customPropertyStartsWithPattern, useCSVforArrays, validationSchemaExtension, }) {
|
|
293
|
+
let validationSchema = astGenerator.transformAll(generateYupAst({
|
|
294
|
+
inputs,
|
|
295
|
+
allowCustomPropertySyntax,
|
|
296
|
+
customPropertySyntaxPattern,
|
|
297
|
+
customPropertyStartsWithPattern,
|
|
298
|
+
useCSVforArrays,
|
|
299
|
+
}));
|
|
300
|
+
if (validationSchemaExtension) {
|
|
301
|
+
validationSchema = validationSchema.concat(validationSchemaExtension);
|
|
302
|
+
}
|
|
303
|
+
return validationSchema;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Get initial values of each input in array of inputs
|
|
307
|
+
*/
|
|
308
|
+
const determineInitialValues = (inputs, useCSVforArrays) => {
|
|
309
|
+
const values = {};
|
|
310
|
+
inputs.forEach((input) => {
|
|
311
|
+
let value = "";
|
|
312
|
+
let valueToCheck = input.value || input.defaultValue;
|
|
313
|
+
const isArrayInput = !useCSVforArrays && Object.values(DataDrivenInputTypes.ARRAY_INPUT_TYPES).includes(input.type);
|
|
314
|
+
if (isArrayInput) {
|
|
315
|
+
valueToCheck = input.value || input.defaultValue || input.values || input.defaultValues;
|
|
316
|
+
}
|
|
317
|
+
if (valueToCheck) {
|
|
318
|
+
switch (valueToCheck) {
|
|
319
|
+
case "false": {
|
|
320
|
+
value = false;
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
case "true": {
|
|
324
|
+
value = true;
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
327
|
+
default: {
|
|
328
|
+
value = valueToCheck;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
values[input.key] = value;
|
|
333
|
+
});
|
|
334
|
+
return values;
|
|
335
|
+
};
|
|
336
|
+
/**
|
|
337
|
+
* Check if an input X needs to be conditionally rendered
|
|
338
|
+
* If it does, then find an input Y in the same section that has key equal to the input X's requiredForKey
|
|
339
|
+
* If input Y has a value that is present in input X's requiredValueOf array, then render X
|
|
340
|
+
*/
|
|
341
|
+
const conditionallyRenderInput = (input, values) => {
|
|
342
|
+
if (!input.conditionallyRender) {
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
if (input.requiredForKey && input.requiredValueOf) {
|
|
346
|
+
/**
|
|
347
|
+
* Check which input in this section has the key equal to requiredForKey and get its value
|
|
348
|
+
*/
|
|
349
|
+
const requiredForKeyInputValue = values[input.requiredForKey];
|
|
350
|
+
const valuesInputIsRenderedFor = input.requiredValueOf;
|
|
351
|
+
/**
|
|
352
|
+
* If the value of the input this input is required for is an array loop through those values to find a matching one
|
|
353
|
+
* by going through all of configured values for the input - the "requiredValueOf" of property
|
|
354
|
+
* Check for the value and the string of the value bc of how the services work. "true" and "false" are strings not boolean values
|
|
355
|
+
*/
|
|
356
|
+
if (Array.isArray(requiredForKeyInputValue)) {
|
|
357
|
+
for (let requiredForValue of valuesInputIsRenderedFor) {
|
|
358
|
+
for (let singleRequiredForKeyInputValue of requiredForKeyInputValue) {
|
|
359
|
+
if (requiredForValue === singleRequiredForKeyInputValue ||
|
|
360
|
+
requiredForValue === String(singleRequiredForKeyInputValue)) {
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
for (let requiredForValue of valuesInputIsRenderedFor) {
|
|
368
|
+
if (requiredForValue === requiredForKeyInputValue || requiredForValue === String(requiredForKeyInputValue)) {
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* Map of the input groups to specifc props to be passed
|
|
380
|
+
*/
|
|
381
|
+
const TYPE_PROPS = {
|
|
382
|
+
[DataDrivenInputTypes.INPUT_GROUPS.CHECKBOX]: (formikProps, { key }, inputs, useCSVforArrays) => ({
|
|
383
|
+
onChange: (value, id, event, selectedItems) => {
|
|
384
|
+
if (useCSVforArrays) {
|
|
385
|
+
formikProps.setFieldValue(`['${key}']`, selectedItems?.join() ?? "");
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
formikProps.setFieldValue(`['${key}']`, selectedItems);
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
}),
|
|
392
|
+
[DataDrivenInputTypes.INPUT_GROUPS.CREATABLE]: (formikProps, { key }, inputs, useCSVforArrays) => ({
|
|
393
|
+
onChange: (createdItems) => {
|
|
394
|
+
formikProps.setFieldTouched(`['${key}']`, true);
|
|
395
|
+
if (useCSVforArrays) {
|
|
396
|
+
formikProps.setFieldValue(`['${key}']`, createdItems?.join() ?? "");
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
formikProps.setFieldValue(`['${key}']`, createdItems);
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
onInputBlur: () => formikProps.setFieldTouched(`['${key}']`, true, true),
|
|
403
|
+
}),
|
|
404
|
+
[DataDrivenInputTypes.INPUT_GROUPS.DATE]: (formikProps, { key, type }) => type === DataDrivenInputTypes.DATE_TYPES.DATE_RANGE
|
|
405
|
+
? {
|
|
406
|
+
onChange: (dateArray) => formikProps.setFieldValue(`['${key}']`, dateArray?.map((date) => date.toISOString())),
|
|
407
|
+
}
|
|
408
|
+
: {
|
|
409
|
+
onChange: formikProps.handleChange,
|
|
410
|
+
onCalendarChange: (dateArray) => formikProps.setFieldValue(`['${key}']`, dateArray[0]?.toISOString()),
|
|
411
|
+
},
|
|
412
|
+
[DataDrivenInputTypes.INPUT_GROUPS.MULTI_SELECT]: (formikProps, { key }, inputs, useCSVforArrays) => ({
|
|
413
|
+
onChange: async ({ selectedItems }) => {
|
|
414
|
+
await formikProps.setFieldTouched(`['${key}']`, true);
|
|
415
|
+
if (useCSVforArrays) {
|
|
416
|
+
formikProps.setFieldValue(`['${key}']`, selectedItems ? selectedItems.map((item) => item && item.value).join() : "");
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
formikProps.setFieldValue(`['${key}']`, selectedItems.map((item) => item && item.value));
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
onInputBlur: () => formikProps.setFieldTouched(`['${key}']`, true, true),
|
|
423
|
+
}),
|
|
424
|
+
[DataDrivenInputTypes.INPUT_GROUPS.RADIO]: (formikProps, { key }) => ({
|
|
425
|
+
onChange: (value) => formikProps.setFieldValue(`['${key}']`, value),
|
|
426
|
+
}),
|
|
427
|
+
[DataDrivenInputTypes.INPUT_GROUPS.SELECT]: (formikProps, input, inputs) => {
|
|
428
|
+
const { key, value } = input;
|
|
429
|
+
let typeProps = {
|
|
430
|
+
onChange: async ({ selectedItem }) => {
|
|
431
|
+
if (selectedItem.value !== value) {
|
|
432
|
+
await formikProps.setFieldTouched(`['${key}']`, true);
|
|
433
|
+
formikProps.setFieldValue(`['${key}']`, selectedItem ? selectedItem.value : "");
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
onInputBlur: () => formikProps.setFieldTouched(`['${key}']`, true, true),
|
|
437
|
+
};
|
|
438
|
+
/**
|
|
439
|
+
* Start Governing Selects logic if input contains governingJsonKey
|
|
440
|
+
*/
|
|
441
|
+
if (Boolean(input.governingJsonKey)) {
|
|
442
|
+
const { governingJsonKey, governingKey, jsonKey, jsonLabel } = input;
|
|
443
|
+
const governingJsonInput = inputs.find((input) => input.key === governingJsonKey);
|
|
444
|
+
/** Check if governingJson with all governing selects data exists as an array */
|
|
445
|
+
if (governingJsonInput && Array.isArray(governingJsonInput.governingJson)) {
|
|
446
|
+
const { governingJson } = governingJsonInput;
|
|
447
|
+
let governingOptions = [];
|
|
448
|
+
let governingDisabled = false;
|
|
449
|
+
/**
|
|
450
|
+
* Select "governingOptions"
|
|
451
|
+
* If current select is the top level governing select, just get the top level options from the json
|
|
452
|
+
*/
|
|
453
|
+
if (key === governingJsonKey) {
|
|
454
|
+
governingOptions = governingJson.map((option) => ({
|
|
455
|
+
label: option[jsonLabel],
|
|
456
|
+
value: option[jsonKey],
|
|
457
|
+
}));
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
/** Check if the select that governs this one has a value and disable if it doesn't */
|
|
461
|
+
const governingSelectValue = formikProps.values[governingKey];
|
|
462
|
+
if (Boolean(governingSelectValue)) {
|
|
463
|
+
let governingKeys = getGoverningSelectKeysMap({
|
|
464
|
+
governingKey,
|
|
465
|
+
governingJsonKey,
|
|
466
|
+
governingKeys: [],
|
|
467
|
+
inputs,
|
|
468
|
+
});
|
|
469
|
+
governingOptions = getGoverningSelectDeepOptions({
|
|
470
|
+
formikValues: formikProps.values,
|
|
471
|
+
governingInputJsonObject: governingJson.find((jsonElement) => jsonElement[governingJsonInput.jsonKey] === formikProps.values[governingJsonKey]),
|
|
472
|
+
governingKeys: [...governingKeys],
|
|
473
|
+
input,
|
|
474
|
+
inputs,
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
governingDisabled = true;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
typeProps = {
|
|
482
|
+
...typeProps,
|
|
483
|
+
onChange: ({ selectedItem }) => handleGoverningSelectChange({ formikProps, input, inputs, selectedItem, isInputBeingChanged: true }),
|
|
484
|
+
governingOptions,
|
|
485
|
+
governingDisabled,
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return typeProps;
|
|
490
|
+
},
|
|
491
|
+
[DataDrivenInputTypes.INPUT_GROUPS.TEXT_AREA]: (formikProps) => ({
|
|
492
|
+
onChange: formikProps.handleChange,
|
|
493
|
+
}),
|
|
494
|
+
[DataDrivenInputTypes.INPUT_GROUPS.TEXT_EDITOR]: (formikProps) => ({
|
|
495
|
+
onChange: formikProps.handleChange,
|
|
496
|
+
}),
|
|
497
|
+
[DataDrivenInputTypes.INPUT_GROUPS.TEXT_INPUT]: (formikProps) => ({
|
|
498
|
+
onChange: formikProps.handleChange,
|
|
499
|
+
}),
|
|
500
|
+
[DataDrivenInputTypes.INPUT_GROUPS.BOOLEAN]: (formikProps, { key }) => ({
|
|
501
|
+
onChange: (value) => {
|
|
502
|
+
formikProps.setFieldTouched(`['${key}']`, true, true);
|
|
503
|
+
formikProps.setFieldValue(`['${key}']`, value);
|
|
504
|
+
},
|
|
505
|
+
}),
|
|
506
|
+
};
|
|
507
|
+
function determineTypeProps(type, otherProps) {
|
|
508
|
+
const { checkboxListProps, creatableProps, dateProps, multiSelectProps, radioProps, selectProps, textAreaProps, textEditorProps, textInputProps, toggleProps, } = otherProps;
|
|
509
|
+
if (Object.values(DataDrivenInputTypes.CHECKBOX_TYPES).includes(type)) {
|
|
510
|
+
return {
|
|
511
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.CHECKBOX],
|
|
512
|
+
additionalTypeProps: checkboxListProps,
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
if (Object.values(DataDrivenInputTypes.CREATABLE_TYPES).includes(type)) {
|
|
516
|
+
return {
|
|
517
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.CREATABLE],
|
|
518
|
+
additionalTypeProps: creatableProps,
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
if (Object.values(DataDrivenInputTypes.DATE_TYPES).includes(type)) {
|
|
522
|
+
return {
|
|
523
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.DATE],
|
|
524
|
+
additionalTypeProps: dateProps,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
if (Object.values(DataDrivenInputTypes.MULTI_SELECT_TYPES).includes(type)) {
|
|
528
|
+
return {
|
|
529
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.MULTI_SELECT],
|
|
530
|
+
additionalTypeProps: multiSelectProps,
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
if (Object.values(DataDrivenInputTypes.RADIO_TYPES).includes(type)) {
|
|
534
|
+
return {
|
|
535
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.RADIO],
|
|
536
|
+
additionalTypeProps: radioProps,
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
if (Object.values(DataDrivenInputTypes.SELECT_TYPES).includes(type)) {
|
|
540
|
+
return {
|
|
541
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.SELECT],
|
|
542
|
+
additionalTypeProps: selectProps,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
if (Object.values(DataDrivenInputTypes.TEXT_AREA_TYPES).includes(type)) {
|
|
546
|
+
return {
|
|
547
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.TEXT_AREA],
|
|
548
|
+
additionalTypeProps: textAreaProps,
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
if (type.startsWith(DataDrivenInputTypes.TEXT_EDITOR_TYPES.TEXT_EDITOR)) {
|
|
552
|
+
return {
|
|
553
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.TEXT_EDITOR],
|
|
554
|
+
additionalTypeProps: textEditorProps,
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
if (Object.values(DataDrivenInputTypes.TEXT_INPUT_TYPES).includes(type)) {
|
|
558
|
+
return {
|
|
559
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.TEXT_INPUT],
|
|
560
|
+
additionalTypeProps: textInputProps,
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
if (Object.values(DataDrivenInputTypes.BOOLEAN_TYPES).includes(type)) {
|
|
564
|
+
return {
|
|
565
|
+
typeProps: TYPE_PROPS[DataDrivenInputTypes.INPUT_GROUPS.BOOLEAN],
|
|
566
|
+
additionalTypeProps: toggleProps,
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
return { typeProps: () => { }, additionalTypeProps: () => { } };
|
|
570
|
+
}
|
|
571
|
+
DynamicFormik.defaultProps = {
|
|
572
|
+
checkboxListProps: (...args) => ({}),
|
|
573
|
+
creatableProps: (...args) => ({}),
|
|
574
|
+
dateProps: (...args) => ({}),
|
|
575
|
+
multiSelectProps: (...args) => ({}),
|
|
576
|
+
radioProps: (...args) => ({}),
|
|
577
|
+
selectProps: (...args) => ({}),
|
|
578
|
+
textAreaProps: (...args) => ({}),
|
|
579
|
+
textEditorProps: (...args) => ({}),
|
|
580
|
+
textInputProps: (...args) => ({}),
|
|
581
|
+
toggleProps: (...args) => ({}),
|
|
582
|
+
};
|
|
583
|
+
function DynamicFormik({ additionalInitialValues = {}, allowCustomPropertySyntax = false, customPropertySyntaxPattern = /\$\{p:([a-zA-Z0-9_.-]+)\}|\$\(([a-zA-Z0-9_.-\s]+)\)/g, customPropertyStartsWithPattern = /\$\{|\$\(/g, children, dataDrivenInputProps, inputProps, initialValues, inputs, onSubmit, useCSVforArrays = false, validationSchema, validationSchemaExtension, ...otherProps }) {
|
|
584
|
+
return (React__default.default.createElement(formik.Formik, { initialValues: (Boolean(initialValues) && initialValues) || {
|
|
585
|
+
...determineInitialValues(inputs, useCSVforArrays),
|
|
586
|
+
...additionalInitialValues,
|
|
587
|
+
}, validationSchema: validationSchema ||
|
|
588
|
+
generateYupSchema({
|
|
589
|
+
inputs,
|
|
590
|
+
allowCustomPropertySyntax,
|
|
591
|
+
customPropertySyntaxPattern,
|
|
592
|
+
customPropertyStartsWithPattern,
|
|
593
|
+
useCSVforArrays,
|
|
594
|
+
validationSchemaExtension,
|
|
595
|
+
}), onSubmit: (values, actions) => {
|
|
596
|
+
if (onSubmit)
|
|
597
|
+
onSubmit(values, actions);
|
|
598
|
+
}, ...otherProps }, (formikProps) => {
|
|
599
|
+
const { values, touched, errors, handleBlur } = formikProps;
|
|
600
|
+
const finalInputs = inputs.filter((input) => conditionallyRenderInput(input, values));
|
|
601
|
+
const dataDrivenInputs = finalInputs.map((input) => {
|
|
602
|
+
const { key, type, value, // eslint-disable-line
|
|
603
|
+
...otherInputsProps } = input;
|
|
604
|
+
const inputValue = values[key] !== undefined &&
|
|
605
|
+
values[key] !== null &&
|
|
606
|
+
(Object.values(DataDrivenInputTypes.TEXT_INPUT_TYPES).includes(type) ||
|
|
607
|
+
type === DataDrivenInputTypes.TEXT_AREA_TYPES.TEXT_AREA ||
|
|
608
|
+
type === DataDrivenInputTypes.TEXT_EDITOR_TYPES.TEXT_EDITOR)
|
|
609
|
+
? values[key].toString()
|
|
610
|
+
: values[key];
|
|
611
|
+
const invalidText = get__default.default(errors, key);
|
|
612
|
+
const invalid = invalidText && get__default.default(touched, key);
|
|
613
|
+
const { typeProps = () => { }, additionalTypeProps = () => { } } = determineTypeProps(type, otherProps);
|
|
614
|
+
return (React__default.default.createElement(DataDrivenInput.default, { key: key, customComponent: input.customComponent, formikProps: formikProps, id: `['${key}']`, invalid: invalid, invalidText: invalidText, name: `['${key}']`, onBlur: handleBlur, type: type, value: inputValue, ...typeProps(formikProps, input, finalInputs, useCSVforArrays), ...otherInputsProps, ...inputProps, ...additionalTypeProps({ formikProps, input }), ...dataDrivenInputProps }));
|
|
615
|
+
});
|
|
616
|
+
return (React__default.default.createElement("div", { className: `${settings.prefix}--bmrg-dynamic-formik` }, children({ inputs: dataDrivenInputs, formikProps })));
|
|
617
|
+
}));
|
|
618
618
|
}
|
|
619
619
|
|
|
620
620
|
exports.default = DynamicFormik;
|