@wise/dynamic-flow-client 5.2.0-exp-bits-29346f3 → 5.2.0

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "dynamicFlows.ArraySchema.addItem": "Зберегти",
3
- "dynamicFlows.ArraySchema.addItemTitle": "Add Item",
3
+ "dynamicFlows.ArraySchema.addItemTitle": "Додати позицію",
4
4
  "dynamicFlows.ArraySchema.editItem": "Зберегти",
5
5
  "dynamicFlows.ArraySchema.maxItemsError": "Додайте {maxItems} або менше.",
6
6
  "dynamicFlows.ArraySchema.minItemsError": "Додайте принаймні {minItems}.",
@@ -24,7 +24,7 @@
24
24
  "dynamicFlows.ExternalConfirmation.open": "Відкрити в новій вкладці",
25
25
  "dynamicFlows.ExternalConfirmation.title": "Підтвердьте",
26
26
  "dynamicFlows.FileUploadSchema.maxFileSizeError": "Вибачте, але цей файл завеликий. Завантажте менший файл.",
27
- "dynamicFlows.FileUploadSchema.wrongFileTypeError": "Sorry, that file format is not supported. Please upload a different file.",
27
+ "dynamicFlows.FileUploadSchema.wrongFileTypeError": "Цей формат файлу не підтримується. Завантажте інший файл.",
28
28
  "dynamicFlows.Help.ariaLabel": "Натисніть тут, щоб дізнатися більше.",
29
29
  "dynamicFlows.MultiSelect.summary": "{first} і ще {count}",
30
30
  "dynamicFlows.MultipleFileUploadSchema.maxFileSizeError": "Вибачте, але цей файл завеликий. Завантажте менший файл.",
package/build/main.css CHANGED
@@ -176,10 +176,6 @@
176
176
  .tw-modal-body--scrollable .df-step-fixed__footer {
177
177
  bottom: -24px;
178
178
  }
179
- .df-modal .df-back-button {
180
- position: fixed;
181
- top: 24px;
182
- }
183
179
  .chips-container {
184
180
  overflow-x: auto;
185
181
  }
package/build/main.js CHANGED
@@ -57,10 +57,10 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
57
57
  var index_exports = {};
58
58
  __export(index_exports, {
59
59
  DynamicFlow: () => DynamicFlowCore,
60
+ DynamicForm: () => DynamicFormCore,
60
61
  findRendererPropsByType: () => findRendererPropsByType,
61
62
  makeHttpClient: () => makeHttpClient,
62
- translations: () => i18n_default,
63
- useDynamicFlow: () => useDynamicFlow
63
+ translations: () => i18n_default
64
64
  });
65
65
  module.exports = __toCommonJS(index_exports);
66
66
 
@@ -778,81 +778,7 @@ var translations = {
778
778
  };
779
779
  var i18n_default = translations;
780
780
 
781
- // src/utils/type-validators.ts
782
- var isString = (value) => typeof value === "string";
783
- var isNumber = (value) => typeof value === "number" && !Number.isNaN(value);
784
- var isInteger = (value) => isNumber(value) && Math.floor(value) === value;
785
- var isBoolean = (value) => typeof value === "boolean";
786
- var isObject = (value) => !isNullish(value) && (value == null ? void 0 : value.constructor) === Object;
787
- var isArray = (value) => Array.isArray(value);
788
- var isNull = (value) => value === null;
789
- var isUndefined = (value) => typeof value === "undefined";
790
- var isNullish = (v) => isNull(v) || isUndefined(v);
791
- var isFile = (value) => value instanceof File;
792
-
793
- // src/renderers/utils.ts
794
- function findRendererPropsByType(root, type, predicate = () => true) {
795
- if (isArray(root)) {
796
- return root.flatMap((child) => findRendererPropsByType(child, type, predicate));
797
- }
798
- return [
799
- ...isType(root, type) && predicate(root) ? [root] : [],
800
- ...getChildren(root).flatMap((child) => findRendererPropsByType(child, type, predicate))
801
- ];
802
- }
803
- var isType = (node, type) => node.type === type;
804
- var getChildren = (node) => {
805
- switch (node.type) {
806
- case "root":
807
- case "box":
808
- case "container":
809
- case "form":
810
- case "form-section":
811
- case "step":
812
- case "modal":
813
- case "section":
814
- return node.childrenProps;
815
- case "columns":
816
- return [...node.startChildrenProps, ...node.endChildrenProps];
817
- case "modal-layout":
818
- return node.content.childrenProps;
819
- case "repeatable":
820
- return node.editableItemProps ? [node.editableItemProps] : [];
821
- case "input-select":
822
- return node.childrenProps ? [node.childrenProps] : [];
823
- case "tabs":
824
- return node.tabs.flatMap((c) => c.childrenProps);
825
- case "alert":
826
- case "button":
827
- case "input-checkbox":
828
- case "input-date":
829
- case "decision":
830
- case "divider":
831
- case "heading":
832
- case "hidden":
833
- case "image":
834
- case "instructions":
835
- case "input-integer":
836
- case "list":
837
- case "loading-indicator":
838
- case "markdown":
839
- case "input-multi-select":
840
- case "input-upload-multi":
841
- case "input-number":
842
- case "money-input":
843
- case "paragraph":
844
- case "progress":
845
- case "review":
846
- case "search":
847
- case "status-list":
848
- case "input-text":
849
- case "input-upload":
850
- case "external-confirmation":
851
- return [];
852
- }
853
- };
854
-
855
- // src/useDynamicFlow.tsx
781
+ // src/DynamicFlowCore.tsx
856
782
  var import_react4 = require("react");
857
783
 
858
784
  // src/common/errorBoundary/ErrorBoundary.tsx
@@ -956,6 +882,81 @@ var CoreContainerRenderer = {
956
882
  render: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children })
957
883
  };
958
884
 
885
+ // src/utils/type-validators.ts
886
+ var isString = (value) => typeof value === "string";
887
+ var isNumber = (value) => typeof value === "number" && !Number.isNaN(value);
888
+ var isInteger = (value) => isNumber(value) && Math.floor(value) === value;
889
+ var isBoolean = (value) => typeof value === "boolean";
890
+ var isObject = (value) => !isNullish(value) && (value == null ? void 0 : value.constructor) === Object;
891
+ var isArray = (value) => Array.isArray(value);
892
+ var isNull = (value) => value === null;
893
+ var isUndefined = (value) => typeof value === "undefined";
894
+ var isNullish = (v) => isNull(v) || isUndefined(v);
895
+ var isFile = (value) => value instanceof File;
896
+ var isValidDate = (value) => isString(value) && /^\d{4}-\d{2}-\d{2}$/.test(value);
897
+
898
+ // src/renderers/utils.ts
899
+ function findRendererPropsByType(root, type, predicate = () => true) {
900
+ if (isArray(root)) {
901
+ return root.flatMap((child) => findRendererPropsByType(child, type, predicate));
902
+ }
903
+ return [
904
+ ...isType(root, type) && predicate(root) ? [root] : [],
905
+ ...getChildren(root).flatMap((child) => findRendererPropsByType(child, type, predicate))
906
+ ];
907
+ }
908
+ var isType = (node, type) => node.type === type;
909
+ var getChildren = (node) => {
910
+ switch (node.type) {
911
+ case "root":
912
+ case "box":
913
+ case "container":
914
+ case "form":
915
+ case "form-section":
916
+ case "step":
917
+ case "modal":
918
+ case "section":
919
+ return node.childrenProps;
920
+ case "columns":
921
+ return [...node.startChildrenProps, ...node.endChildrenProps];
922
+ case "modal-layout":
923
+ return node.content.childrenProps;
924
+ case "repeatable":
925
+ return node.editableItemProps ? [node.editableItemProps] : [];
926
+ case "input-select":
927
+ return node.childrenProps ? [node.childrenProps] : [];
928
+ case "tabs":
929
+ return node.tabs.flatMap((c) => c.childrenProps);
930
+ case "alert":
931
+ case "button":
932
+ case "input-checkbox":
933
+ case "input-date":
934
+ case "decision":
935
+ case "divider":
936
+ case "heading":
937
+ case "hidden":
938
+ case "image":
939
+ case "instructions":
940
+ case "input-integer":
941
+ case "list":
942
+ case "loading-indicator":
943
+ case "markdown":
944
+ case "input-multi-select":
945
+ case "input-upload-multi":
946
+ case "input-number":
947
+ case "money-input":
948
+ case "paragraph":
949
+ case "progress":
950
+ case "review":
951
+ case "search":
952
+ case "status-list":
953
+ case "input-text":
954
+ case "input-upload":
955
+ case "external-confirmation":
956
+ return [];
957
+ }
958
+ };
959
+
959
960
  // src/renderers/CoreRootRenderer.tsx
960
961
  var import_jsx_runtime4 = require("react/jsx-runtime");
961
962
  var CoreRootRenderer = {
@@ -1438,10 +1439,28 @@ var pickValidationState = (states) => {
1438
1439
  return definedStates[0];
1439
1440
  };
1440
1441
 
1442
+ // src/renderers/mappers/utils/selectInputOptionsToProps.ts
1443
+ var selectInputOptionsToProps = (options, children, rendererMapperProps) => {
1444
+ return options.map((option, index) => {
1445
+ const child = children[index];
1446
+ const optionChildrenProps = child ? componentToRendererProps(child, rendererMapperProps) : null;
1447
+ const optionChildren = optionChildrenProps ? rendererMapperProps.render(optionChildrenProps) : null;
1448
+ return __spreadProps(__spreadValues({}, option), {
1449
+ children: optionChildren,
1450
+ childrenProps: optionChildrenProps
1451
+ });
1452
+ });
1453
+ };
1454
+
1441
1455
  // src/renderers/mappers/multiSelectComponentToProps.ts
1442
1456
  var multiSelectInputComponentToProps = (component, rendererMapperProps) => {
1443
- const { autoComplete, maxItems, minItems, options, selectedIndices, onSelect } = component;
1457
+ const { autoComplete, maxItems, minItems, selectedIndices, onSelect } = component;
1444
1458
  const _a = inputComponentToProps(component, "input-multi-select"), { required, value } = _a, props = __objRest(_a, ["required", "value"]);
1459
+ const options = selectInputOptionsToProps(
1460
+ component.options,
1461
+ component.getChildren(),
1462
+ rendererMapperProps
1463
+ );
1445
1464
  return __spreadProps(__spreadValues(__spreadValues({}, props), rendererMapperProps), {
1446
1465
  autoComplete,
1447
1466
  maxItems,
@@ -1782,10 +1801,15 @@ var sectionComponentToProps = (component, rendererMapperProps) => {
1782
1801
 
1783
1802
  // src/renderers/mappers/selectInputComponentToProps.ts
1784
1803
  var selectInputComponentToProps = (component, rendererMapperProps) => {
1785
- const { autoComplete, options, selectedIndex, onSelect } = component;
1804
+ const { autoComplete, selectedIndex, onSelect } = component;
1786
1805
  const selectedChild = component.getSelectedChild();
1787
1806
  const childrenProps = selectedChild ? componentToRendererProps(selectedChild, rendererMapperProps) : null;
1788
1807
  const _a = inputComponentToProps(component, "input-select"), { value } = _a, props = __objRest(_a, ["value"]);
1808
+ const options = selectInputOptionsToProps(
1809
+ component.options,
1810
+ component.getChildren(),
1811
+ rendererMapperProps
1812
+ );
1789
1813
  return __spreadProps(__spreadValues(__spreadValues({}, props), rendererMapperProps), {
1790
1814
  autoComplete,
1791
1815
  options,
@@ -1979,7 +2003,7 @@ var getComponentAlertProps = (component, rendererMapperProps) => "alert" in comp
1979
2003
  markdown: component.alert.content
1980
2004
  }, rendererMapperProps) : null;
1981
2005
 
1982
- // src/useDynamicFlowController.tsx
2006
+ // src/useDynamicFlowCore.tsx
1983
2007
  var import_react3 = require("react");
1984
2008
  var import_react_intl7 = require("react-intl");
1985
2009
 
@@ -2000,7 +2024,8 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2000
2024
  uid: "root",
2001
2025
  stepComponent: null,
2002
2026
  stepStack: [],
2003
- backConfig,
2027
+ isNativeBackEnabled: backConfig.isNativeBackEnabled,
2028
+ isFlowCancellable: backConfig.isFlowCancellable,
2004
2029
  _update(updateFn) {
2005
2030
  update(this, updateFn);
2006
2031
  },
@@ -2134,7 +2159,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2134
2159
  var _a, _b;
2135
2160
  const navigation = (_a = this.getStep()) == null ? void 0 : _a.step.navigation;
2136
2161
  const stepHasBehavior = Boolean((_b = navigation == null ? void 0 : navigation.back) != null ? _b : navigation == null ? void 0 : navigation.backButton);
2137
- return this.backConfig.isFlowCancellable || this.stepStack.length > 1 && this.backConfig.isNativeBackEnabled || stepHasBehavior;
2162
+ return this.isFlowCancellable || this.stepStack.length > 1 && this.isNativeBackEnabled || stepHasBehavior;
2138
2163
  }
2139
2164
  };
2140
2165
  return rootComponent;
@@ -3978,6 +4003,12 @@ var getRequiredCheck = (required, messageFunctions) => (value) => {
3978
4003
  }
3979
4004
  return isNullish(value) ? messageFunctions.required() : null;
3980
4005
  };
4006
+ var getValidDateCheck = (required, messageFunctions) => (value) => {
4007
+ if (required && !isValidDate(value)) {
4008
+ return messageFunctions.required();
4009
+ }
4010
+ return null;
4011
+ };
3981
4012
 
3982
4013
  // src/domain/mappers/utils/getAutocompleteString.ts
3983
4014
  var getAutocompleteString = (hints) => {
@@ -6196,7 +6227,7 @@ var createPersistAsyncComponent = (props, performPersistAsync, schemaOnChange, u
6196
6227
  };
6197
6228
 
6198
6229
  // src/domain/mappers/schema/persistAsyncSchemaToComponent.ts
6199
- var isSupported = (type) => ["boolean", "text", "date", "integer", "number", "upload"].includes(type);
6230
+ var isSupported = (type) => ["const", "boolean", "text", "date", "integer", "number", "upload"].includes(type);
6200
6231
  var persistAsyncSchemaToComponent = (schemaMapperProps, mapperProps) => {
6201
6232
  const { uid, schema, model, localValue } = schemaMapperProps;
6202
6233
  const { persistAsync, tags } = schema;
@@ -6295,8 +6326,10 @@ var createDateInputComponent = (textInputProps, updateComponent) => {
6295
6326
  return this.getSubmittableValueSync();
6296
6327
  },
6297
6328
  getSubmittableValueSync() {
6298
- var _a2;
6299
- return (_a2 = this.getLocalValue()) != null ? _a2 : null;
6329
+ if (isValidDate(this.getLocalValue())) {
6330
+ return this.getLocalValue();
6331
+ }
6332
+ return null;
6300
6333
  },
6301
6334
  getSummary() {
6302
6335
  return summariser(this.getLocalValue());
@@ -6360,6 +6393,7 @@ var stringSchemaToDateInputComponent = (schemaMapperProps, mapperProps) => {
6360
6393
  autoComplete: getAutocompleteString(autocompleteHint),
6361
6394
  checks: schema.hidden ? [] : [
6362
6395
  getRequiredCheck(required, errorMessageFunctions),
6396
+ getValidDateCheck(required, errorMessageFunctions),
6363
6397
  getAboveMaximumDateCheck(schema, errorMessageFunctions),
6364
6398
  getBelowMinimumDateCheck(schema, errorMessageFunctions)
6365
6399
  ],
@@ -7324,8 +7358,8 @@ function useStableCallback(handler) {
7324
7358
  return (0, import_react2.useCallback)((...args) => ref.current ? ref.current(...args) : null, []);
7325
7359
  }
7326
7360
 
7327
- // src/useDynamicFlowController.tsx
7328
- function useDynamicFlowController(props) {
7361
+ // src/useDynamicFlowCore.tsx
7362
+ function useDynamicFlowCore(props) {
7329
7363
  const _a = props, { flowId, initialAction, initialStep, features } = _a, rest = __objRest(_a, ["flowId", "initialAction", "initialStep", "features"]);
7330
7364
  const httpClient = useStableCallback(rest.httpClient);
7331
7365
  const onCancellation = useStableCallback(rest.onCancellation);
@@ -7724,29 +7758,20 @@ function useDynamicFlowController(props) {
7724
7758
  trackCoreEvent("Step Shown", { isFirstStep: true });
7725
7759
  hasMappedInitialStep.current = true;
7726
7760
  }
7727
- return {
7728
- rootComponent: rootComponentRef.current,
7729
- cancelFlow: closeWithCancellation,
7730
- navigateBack: () => {
7731
- var _a2;
7732
- if (((_a2 = rootComponentRef.current.stepStack) == null ? void 0 : _a2.length) > 1) {
7733
- rootComponentRef.current.navigateBack();
7734
- } else {
7735
- closeWithCancellation();
7736
- }
7737
- rootComponentRef.current.setLoadingState("idle");
7738
- }
7739
- };
7761
+ return { rootComponent: rootComponentRef.current };
7740
7762
  }
7741
7763
  var useRerender = () => {
7742
7764
  const [, setState] = (0, import_react3.useState)({});
7743
7765
  return (0, import_react3.useCallback)(() => setState({}), []);
7744
7766
  };
7745
7767
 
7746
- // src/utils/getScrollToTop.ts
7747
- var getScrollToTop = (normalisedFlowId, className2) => (behavior) => {
7768
+ // src/utils/normalise-flow-id.ts
7769
+ var normaliseFlowId = (flowId) => flowId.toLowerCase().replace(/[^a-z-]/g, "-");
7770
+
7771
+ // src/utils/scrollToTop.ts
7772
+ var getScrollToTop = (normalisedFlowId, className3) => (behavior) => {
7748
7773
  var _a;
7749
- const element = document.querySelector(`div#${normalisedFlowId}.${className2}`);
7774
+ const element = document.querySelector(`div#${normalisedFlowId}.${className3}`);
7750
7775
  if (!element || !window) {
7751
7776
  return;
7752
7777
  }
@@ -7757,14 +7782,11 @@ var getScrollToTop = (normalisedFlowId, className2) => (behavior) => {
7757
7782
  }
7758
7783
  };
7759
7784
 
7760
- // src/utils/normalise-flow-id.ts
7761
- var normaliseFlowId = (flowId) => flowId.toLowerCase().replace(/[^a-z-]/g, "-");
7762
-
7763
- // src/useDynamicFlow.tsx
7785
+ // src/DynamicFlowCore.tsx
7764
7786
  var import_jsx_runtime6 = require("react/jsx-runtime");
7765
7787
  var className = "dynamic-flow";
7766
- function useDynamicFlow(props) {
7767
- var _a, _b, _c;
7788
+ function DynamicFlowCore(props) {
7789
+ var _a;
7768
7790
  const { flowId, renderers, httpClient, onEvent, onError, onLog } = props;
7769
7791
  const normalisedFlowId = normaliseFlowId(flowId);
7770
7792
  const scrollToTop = (0, import_react4.useMemo)(
@@ -7775,10 +7797,7 @@ function useDynamicFlow(props) {
7775
7797
  var _a2;
7776
7798
  return new FeatureFlags((_a2 = props.features) != null ? _a2 : {});
7777
7799
  }, []);
7778
- const { rootComponent, cancelFlow, navigateBack } = useDynamicFlowController(__spreadProps(__spreadValues({}, props), {
7779
- features,
7780
- scrollToTop
7781
- }));
7800
+ const { rootComponent } = useDynamicFlowCore(__spreadProps(__spreadValues({}, props), { features, scrollToTop }));
7782
7801
  const render = (0, import_react4.useMemo)(
7783
7802
  () => getRenderFunction([CoreRootRenderer, CoreContainerRenderer, ...renderers]),
7784
7803
  [renderers]
@@ -7791,31 +7810,95 @@ function useDynamicFlow(props) {
7791
7810
  }),
7792
7811
  stepLoadingState: rootComponent.getLoadingState()
7793
7812
  });
7794
- return {
7795
- title: (_c = (_b = rootComponent.getStep()) == null ? void 0 : _b.title) != null ? _c : "",
7796
- getSubmittableValue: async () => rootComponent.getSubmittableValue(),
7797
- validate: () => rootComponent.validate(),
7798
- rootComponent,
7799
- cancelFlow,
7800
- navigateBack,
7801
- component: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
7802
- ErrorBoundary_default,
7803
- {
7804
- onError: (error) => {
7805
- onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed", { error });
7806
- onError == null ? void 0 : onError(error);
7807
- onLog == null ? void 0 : onLog("error", "Dynamic Flow - ErrorBoundary", {
7808
- errorMessage: getErrorMessage(error)
7809
- });
7810
- },
7811
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { id: normalisedFlowId, className, children: render(tree) })
7812
- }
7813
- )
7814
- };
7813
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
7814
+ ErrorBoundary_default,
7815
+ {
7816
+ onError: (error) => {
7817
+ onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed", { error });
7818
+ onError == null ? void 0 : onError(error);
7819
+ onLog == null ? void 0 : onLog("error", "Dynamic Flow - ErrorBoundary", { errorMessage: getErrorMessage(error) });
7820
+ },
7821
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { id: normalisedFlowId, className, children: render(tree) })
7822
+ }
7823
+ );
7815
7824
  }
7816
7825
 
7817
- // src/DynamicFlowCore.tsx
7818
- function DynamicFlowCore(props) {
7819
- const df = useDynamicFlow(props);
7820
- return df.component;
7821
- }
7826
+ // src/DynamicFormCore.tsx
7827
+ var import_react5 = require("react");
7828
+
7829
+ // src/utils/openLinkInNewTab.tsx
7830
+ var openLinkInNewTab = (url) => {
7831
+ var _a;
7832
+ try {
7833
+ const w = (_a = window == null ? void 0 : window.open) == null ? void 0 : _a.call(window, url, "_blank");
7834
+ return Boolean(w);
7835
+ } catch (e) {
7836
+ return false;
7837
+ }
7838
+ };
7839
+
7840
+ // src/DynamicFormCore.tsx
7841
+ var import_jsx_runtime7 = require("react/jsx-runtime");
7842
+ var className2 = "dynamic-flow";
7843
+ var DynamicFormCore = (0, import_react5.forwardRef)(function DynamicFormCore2(props, ref) {
7844
+ var _a;
7845
+ const {
7846
+ onCompletion = () => {
7847
+ },
7848
+ httpClient,
7849
+ onEvent,
7850
+ onError,
7851
+ onLink = openLinkInNewTab,
7852
+ renderers
7853
+ } = props;
7854
+ const normalisedFlowId = normaliseFlowId(props.flowId);
7855
+ const scrollToTop = (0, import_react5.useMemo)(
7856
+ () => getScrollToTop(normalisedFlowId, className2),
7857
+ [normalisedFlowId]
7858
+ );
7859
+ const features = (0, import_react5.useMemo)(() => {
7860
+ var _a2;
7861
+ return new FeatureFlags((_a2 = props.features) != null ? _a2 : {});
7862
+ }, []);
7863
+ const { rootComponent } = useDynamicFlowCore(__spreadProps(__spreadValues({
7864
+ onCompletion
7865
+ }, props), {
7866
+ features,
7867
+ scrollToTop,
7868
+ onLink
7869
+ }));
7870
+ (0, import_react5.useImperativeHandle)(
7871
+ ref,
7872
+ () => ({
7873
+ getValue: async () => {
7874
+ var _a2;
7875
+ return (_a2 = await rootComponent.getSubmittableValue()) != null ? _a2 : null;
7876
+ },
7877
+ validate: () => rootComponent.validate()
7878
+ }),
7879
+ // eslint-disable-next-line react-hooks/exhaustive-deps
7880
+ []
7881
+ );
7882
+ const render = (0, import_react5.useMemo)(
7883
+ () => getRenderFunction([CoreRootRenderer, CoreContainerRenderer, ...renderers]),
7884
+ [renderers]
7885
+ );
7886
+ const tree = componentToRendererProps(rootComponent, {
7887
+ features,
7888
+ render,
7889
+ httpClient,
7890
+ trackEvent: (_a = rootComponent.getTrackEvent()) != null ? _a : (() => {
7891
+ }),
7892
+ stepLoadingState: rootComponent.getLoadingState()
7893
+ });
7894
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7895
+ ErrorBoundary_default,
7896
+ {
7897
+ onError: (error) => {
7898
+ onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed");
7899
+ onError(error);
7900
+ },
7901
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { id: normalisedFlowId, className: className2, children: render(tree) })
7902
+ }
7903
+ );
7904
+ });
package/build/main.mjs CHANGED
@@ -751,81 +751,7 @@ var translations = {
751
751
  };
752
752
  var i18n_default = translations;
753
753
 
754
- // src/utils/type-validators.ts
755
- var isString = (value) => typeof value === "string";
756
- var isNumber = (value) => typeof value === "number" && !Number.isNaN(value);
757
- var isInteger = (value) => isNumber(value) && Math.floor(value) === value;
758
- var isBoolean = (value) => typeof value === "boolean";
759
- var isObject = (value) => !isNullish(value) && (value == null ? void 0 : value.constructor) === Object;
760
- var isArray = (value) => Array.isArray(value);
761
- var isNull = (value) => value === null;
762
- var isUndefined = (value) => typeof value === "undefined";
763
- var isNullish = (v) => isNull(v) || isUndefined(v);
764
- var isFile = (value) => value instanceof File;
765
-
766
- // src/renderers/utils.ts
767
- function findRendererPropsByType(root, type, predicate = () => true) {
768
- if (isArray(root)) {
769
- return root.flatMap((child) => findRendererPropsByType(child, type, predicate));
770
- }
771
- return [
772
- ...isType(root, type) && predicate(root) ? [root] : [],
773
- ...getChildren(root).flatMap((child) => findRendererPropsByType(child, type, predicate))
774
- ];
775
- }
776
- var isType = (node, type) => node.type === type;
777
- var getChildren = (node) => {
778
- switch (node.type) {
779
- case "root":
780
- case "box":
781
- case "container":
782
- case "form":
783
- case "form-section":
784
- case "step":
785
- case "modal":
786
- case "section":
787
- return node.childrenProps;
788
- case "columns":
789
- return [...node.startChildrenProps, ...node.endChildrenProps];
790
- case "modal-layout":
791
- return node.content.childrenProps;
792
- case "repeatable":
793
- return node.editableItemProps ? [node.editableItemProps] : [];
794
- case "input-select":
795
- return node.childrenProps ? [node.childrenProps] : [];
796
- case "tabs":
797
- return node.tabs.flatMap((c) => c.childrenProps);
798
- case "alert":
799
- case "button":
800
- case "input-checkbox":
801
- case "input-date":
802
- case "decision":
803
- case "divider":
804
- case "heading":
805
- case "hidden":
806
- case "image":
807
- case "instructions":
808
- case "input-integer":
809
- case "list":
810
- case "loading-indicator":
811
- case "markdown":
812
- case "input-multi-select":
813
- case "input-upload-multi":
814
- case "input-number":
815
- case "money-input":
816
- case "paragraph":
817
- case "progress":
818
- case "review":
819
- case "search":
820
- case "status-list":
821
- case "input-text":
822
- case "input-upload":
823
- case "external-confirmation":
824
- return [];
825
- }
826
- };
827
-
828
- // src/useDynamicFlow.tsx
754
+ // src/DynamicFlowCore.tsx
829
755
  import { useMemo as useMemo2 } from "react";
830
756
 
831
757
  // src/common/errorBoundary/ErrorBoundary.tsx
@@ -929,6 +855,81 @@ var CoreContainerRenderer = {
929
855
  render: ({ children }) => /* @__PURE__ */ jsx3(Fragment2, { children })
930
856
  };
931
857
 
858
+ // src/utils/type-validators.ts
859
+ var isString = (value) => typeof value === "string";
860
+ var isNumber = (value) => typeof value === "number" && !Number.isNaN(value);
861
+ var isInteger = (value) => isNumber(value) && Math.floor(value) === value;
862
+ var isBoolean = (value) => typeof value === "boolean";
863
+ var isObject = (value) => !isNullish(value) && (value == null ? void 0 : value.constructor) === Object;
864
+ var isArray = (value) => Array.isArray(value);
865
+ var isNull = (value) => value === null;
866
+ var isUndefined = (value) => typeof value === "undefined";
867
+ var isNullish = (v) => isNull(v) || isUndefined(v);
868
+ var isFile = (value) => value instanceof File;
869
+ var isValidDate = (value) => isString(value) && /^\d{4}-\d{2}-\d{2}$/.test(value);
870
+
871
+ // src/renderers/utils.ts
872
+ function findRendererPropsByType(root, type, predicate = () => true) {
873
+ if (isArray(root)) {
874
+ return root.flatMap((child) => findRendererPropsByType(child, type, predicate));
875
+ }
876
+ return [
877
+ ...isType(root, type) && predicate(root) ? [root] : [],
878
+ ...getChildren(root).flatMap((child) => findRendererPropsByType(child, type, predicate))
879
+ ];
880
+ }
881
+ var isType = (node, type) => node.type === type;
882
+ var getChildren = (node) => {
883
+ switch (node.type) {
884
+ case "root":
885
+ case "box":
886
+ case "container":
887
+ case "form":
888
+ case "form-section":
889
+ case "step":
890
+ case "modal":
891
+ case "section":
892
+ return node.childrenProps;
893
+ case "columns":
894
+ return [...node.startChildrenProps, ...node.endChildrenProps];
895
+ case "modal-layout":
896
+ return node.content.childrenProps;
897
+ case "repeatable":
898
+ return node.editableItemProps ? [node.editableItemProps] : [];
899
+ case "input-select":
900
+ return node.childrenProps ? [node.childrenProps] : [];
901
+ case "tabs":
902
+ return node.tabs.flatMap((c) => c.childrenProps);
903
+ case "alert":
904
+ case "button":
905
+ case "input-checkbox":
906
+ case "input-date":
907
+ case "decision":
908
+ case "divider":
909
+ case "heading":
910
+ case "hidden":
911
+ case "image":
912
+ case "instructions":
913
+ case "input-integer":
914
+ case "list":
915
+ case "loading-indicator":
916
+ case "markdown":
917
+ case "input-multi-select":
918
+ case "input-upload-multi":
919
+ case "input-number":
920
+ case "money-input":
921
+ case "paragraph":
922
+ case "progress":
923
+ case "review":
924
+ case "search":
925
+ case "status-list":
926
+ case "input-text":
927
+ case "input-upload":
928
+ case "external-confirmation":
929
+ return [];
930
+ }
931
+ };
932
+
932
933
  // src/renderers/CoreRootRenderer.tsx
933
934
  import { jsx as jsx4 } from "react/jsx-runtime";
934
935
  var CoreRootRenderer = {
@@ -1411,10 +1412,28 @@ var pickValidationState = (states) => {
1411
1412
  return definedStates[0];
1412
1413
  };
1413
1414
 
1415
+ // src/renderers/mappers/utils/selectInputOptionsToProps.ts
1416
+ var selectInputOptionsToProps = (options, children, rendererMapperProps) => {
1417
+ return options.map((option, index) => {
1418
+ const child = children[index];
1419
+ const optionChildrenProps = child ? componentToRendererProps(child, rendererMapperProps) : null;
1420
+ const optionChildren = optionChildrenProps ? rendererMapperProps.render(optionChildrenProps) : null;
1421
+ return __spreadProps(__spreadValues({}, option), {
1422
+ children: optionChildren,
1423
+ childrenProps: optionChildrenProps
1424
+ });
1425
+ });
1426
+ };
1427
+
1414
1428
  // src/renderers/mappers/multiSelectComponentToProps.ts
1415
1429
  var multiSelectInputComponentToProps = (component, rendererMapperProps) => {
1416
- const { autoComplete, maxItems, minItems, options, selectedIndices, onSelect } = component;
1430
+ const { autoComplete, maxItems, minItems, selectedIndices, onSelect } = component;
1417
1431
  const _a = inputComponentToProps(component, "input-multi-select"), { required, value } = _a, props = __objRest(_a, ["required", "value"]);
1432
+ const options = selectInputOptionsToProps(
1433
+ component.options,
1434
+ component.getChildren(),
1435
+ rendererMapperProps
1436
+ );
1418
1437
  return __spreadProps(__spreadValues(__spreadValues({}, props), rendererMapperProps), {
1419
1438
  autoComplete,
1420
1439
  maxItems,
@@ -1755,10 +1774,15 @@ var sectionComponentToProps = (component, rendererMapperProps) => {
1755
1774
 
1756
1775
  // src/renderers/mappers/selectInputComponentToProps.ts
1757
1776
  var selectInputComponentToProps = (component, rendererMapperProps) => {
1758
- const { autoComplete, options, selectedIndex, onSelect } = component;
1777
+ const { autoComplete, selectedIndex, onSelect } = component;
1759
1778
  const selectedChild = component.getSelectedChild();
1760
1779
  const childrenProps = selectedChild ? componentToRendererProps(selectedChild, rendererMapperProps) : null;
1761
1780
  const _a = inputComponentToProps(component, "input-select"), { value } = _a, props = __objRest(_a, ["value"]);
1781
+ const options = selectInputOptionsToProps(
1782
+ component.options,
1783
+ component.getChildren(),
1784
+ rendererMapperProps
1785
+ );
1762
1786
  return __spreadProps(__spreadValues(__spreadValues({}, props), rendererMapperProps), {
1763
1787
  autoComplete,
1764
1788
  options,
@@ -1952,7 +1976,7 @@ var getComponentAlertProps = (component, rendererMapperProps) => "alert" in comp
1952
1976
  markdown: component.alert.content
1953
1977
  }, rendererMapperProps) : null;
1954
1978
 
1955
- // src/useDynamicFlowController.tsx
1979
+ // src/useDynamicFlowCore.tsx
1956
1980
  import { useCallback as useCallback2, useEffect, useMemo, useRef as useRef2, useState } from "react";
1957
1981
  import { useIntl as useIntl2 } from "react-intl";
1958
1982
 
@@ -1973,7 +1997,8 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
1973
1997
  uid: "root",
1974
1998
  stepComponent: null,
1975
1999
  stepStack: [],
1976
- backConfig,
2000
+ isNativeBackEnabled: backConfig.isNativeBackEnabled,
2001
+ isFlowCancellable: backConfig.isFlowCancellable,
1977
2002
  _update(updateFn) {
1978
2003
  update(this, updateFn);
1979
2004
  },
@@ -2107,7 +2132,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2107
2132
  var _a, _b;
2108
2133
  const navigation = (_a = this.getStep()) == null ? void 0 : _a.step.navigation;
2109
2134
  const stepHasBehavior = Boolean((_b = navigation == null ? void 0 : navigation.back) != null ? _b : navigation == null ? void 0 : navigation.backButton);
2110
- return this.backConfig.isFlowCancellable || this.stepStack.length > 1 && this.backConfig.isNativeBackEnabled || stepHasBehavior;
2135
+ return this.isFlowCancellable || this.stepStack.length > 1 && this.isNativeBackEnabled || stepHasBehavior;
2111
2136
  }
2112
2137
  };
2113
2138
  return rootComponent;
@@ -3951,6 +3976,12 @@ var getRequiredCheck = (required, messageFunctions) => (value) => {
3951
3976
  }
3952
3977
  return isNullish(value) ? messageFunctions.required() : null;
3953
3978
  };
3979
+ var getValidDateCheck = (required, messageFunctions) => (value) => {
3980
+ if (required && !isValidDate(value)) {
3981
+ return messageFunctions.required();
3982
+ }
3983
+ return null;
3984
+ };
3954
3985
 
3955
3986
  // src/domain/mappers/utils/getAutocompleteString.ts
3956
3987
  var getAutocompleteString = (hints) => {
@@ -6169,7 +6200,7 @@ var createPersistAsyncComponent = (props, performPersistAsync, schemaOnChange, u
6169
6200
  };
6170
6201
 
6171
6202
  // src/domain/mappers/schema/persistAsyncSchemaToComponent.ts
6172
- var isSupported = (type) => ["boolean", "text", "date", "integer", "number", "upload"].includes(type);
6203
+ var isSupported = (type) => ["const", "boolean", "text", "date", "integer", "number", "upload"].includes(type);
6173
6204
  var persistAsyncSchemaToComponent = (schemaMapperProps, mapperProps) => {
6174
6205
  const { uid, schema, model, localValue } = schemaMapperProps;
6175
6206
  const { persistAsync, tags } = schema;
@@ -6268,8 +6299,10 @@ var createDateInputComponent = (textInputProps, updateComponent) => {
6268
6299
  return this.getSubmittableValueSync();
6269
6300
  },
6270
6301
  getSubmittableValueSync() {
6271
- var _a2;
6272
- return (_a2 = this.getLocalValue()) != null ? _a2 : null;
6302
+ if (isValidDate(this.getLocalValue())) {
6303
+ return this.getLocalValue();
6304
+ }
6305
+ return null;
6273
6306
  },
6274
6307
  getSummary() {
6275
6308
  return summariser(this.getLocalValue());
@@ -6333,6 +6366,7 @@ var stringSchemaToDateInputComponent = (schemaMapperProps, mapperProps) => {
6333
6366
  autoComplete: getAutocompleteString(autocompleteHint),
6334
6367
  checks: schema.hidden ? [] : [
6335
6368
  getRequiredCheck(required, errorMessageFunctions),
6369
+ getValidDateCheck(required, errorMessageFunctions),
6336
6370
  getAboveMaximumDateCheck(schema, errorMessageFunctions),
6337
6371
  getBelowMinimumDateCheck(schema, errorMessageFunctions)
6338
6372
  ],
@@ -7297,8 +7331,8 @@ function useStableCallback(handler) {
7297
7331
  return useCallback((...args) => ref.current ? ref.current(...args) : null, []);
7298
7332
  }
7299
7333
 
7300
- // src/useDynamicFlowController.tsx
7301
- function useDynamicFlowController(props) {
7334
+ // src/useDynamicFlowCore.tsx
7335
+ function useDynamicFlowCore(props) {
7302
7336
  const _a = props, { flowId, initialAction, initialStep, features } = _a, rest = __objRest(_a, ["flowId", "initialAction", "initialStep", "features"]);
7303
7337
  const httpClient = useStableCallback(rest.httpClient);
7304
7338
  const onCancellation = useStableCallback(rest.onCancellation);
@@ -7697,29 +7731,20 @@ function useDynamicFlowController(props) {
7697
7731
  trackCoreEvent("Step Shown", { isFirstStep: true });
7698
7732
  hasMappedInitialStep.current = true;
7699
7733
  }
7700
- return {
7701
- rootComponent: rootComponentRef.current,
7702
- cancelFlow: closeWithCancellation,
7703
- navigateBack: () => {
7704
- var _a2;
7705
- if (((_a2 = rootComponentRef.current.stepStack) == null ? void 0 : _a2.length) > 1) {
7706
- rootComponentRef.current.navigateBack();
7707
- } else {
7708
- closeWithCancellation();
7709
- }
7710
- rootComponentRef.current.setLoadingState("idle");
7711
- }
7712
- };
7734
+ return { rootComponent: rootComponentRef.current };
7713
7735
  }
7714
7736
  var useRerender = () => {
7715
7737
  const [, setState] = useState({});
7716
7738
  return useCallback2(() => setState({}), []);
7717
7739
  };
7718
7740
 
7719
- // src/utils/getScrollToTop.ts
7720
- var getScrollToTop = (normalisedFlowId, className2) => (behavior) => {
7741
+ // src/utils/normalise-flow-id.ts
7742
+ var normaliseFlowId = (flowId) => flowId.toLowerCase().replace(/[^a-z-]/g, "-");
7743
+
7744
+ // src/utils/scrollToTop.ts
7745
+ var getScrollToTop = (normalisedFlowId, className3) => (behavior) => {
7721
7746
  var _a;
7722
- const element = document.querySelector(`div#${normalisedFlowId}.${className2}`);
7747
+ const element = document.querySelector(`div#${normalisedFlowId}.${className3}`);
7723
7748
  if (!element || !window) {
7724
7749
  return;
7725
7750
  }
@@ -7730,14 +7755,11 @@ var getScrollToTop = (normalisedFlowId, className2) => (behavior) => {
7730
7755
  }
7731
7756
  };
7732
7757
 
7733
- // src/utils/normalise-flow-id.ts
7734
- var normaliseFlowId = (flowId) => flowId.toLowerCase().replace(/[^a-z-]/g, "-");
7735
-
7736
- // src/useDynamicFlow.tsx
7758
+ // src/DynamicFlowCore.tsx
7737
7759
  import { jsx as jsx6 } from "react/jsx-runtime";
7738
7760
  var className = "dynamic-flow";
7739
- function useDynamicFlow(props) {
7740
- var _a, _b, _c;
7761
+ function DynamicFlowCore(props) {
7762
+ var _a;
7741
7763
  const { flowId, renderers, httpClient, onEvent, onError, onLog } = props;
7742
7764
  const normalisedFlowId = normaliseFlowId(flowId);
7743
7765
  const scrollToTop = useMemo2(
@@ -7748,10 +7770,7 @@ function useDynamicFlow(props) {
7748
7770
  var _a2;
7749
7771
  return new FeatureFlags((_a2 = props.features) != null ? _a2 : {});
7750
7772
  }, []);
7751
- const { rootComponent, cancelFlow, navigateBack } = useDynamicFlowController(__spreadProps(__spreadValues({}, props), {
7752
- features,
7753
- scrollToTop
7754
- }));
7773
+ const { rootComponent } = useDynamicFlowCore(__spreadProps(__spreadValues({}, props), { features, scrollToTop }));
7755
7774
  const render = useMemo2(
7756
7775
  () => getRenderFunction([CoreRootRenderer, CoreContainerRenderer, ...renderers]),
7757
7776
  [renderers]
@@ -7764,38 +7783,102 @@ function useDynamicFlow(props) {
7764
7783
  }),
7765
7784
  stepLoadingState: rootComponent.getLoadingState()
7766
7785
  });
7767
- return {
7768
- title: (_c = (_b = rootComponent.getStep()) == null ? void 0 : _b.title) != null ? _c : "",
7769
- getSubmittableValue: async () => rootComponent.getSubmittableValue(),
7770
- validate: () => rootComponent.validate(),
7771
- rootComponent,
7772
- cancelFlow,
7773
- navigateBack,
7774
- component: /* @__PURE__ */ jsx6(
7775
- ErrorBoundary_default,
7776
- {
7777
- onError: (error) => {
7778
- onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed", { error });
7779
- onError == null ? void 0 : onError(error);
7780
- onLog == null ? void 0 : onLog("error", "Dynamic Flow - ErrorBoundary", {
7781
- errorMessage: getErrorMessage(error)
7782
- });
7783
- },
7784
- children: /* @__PURE__ */ jsx6("div", { id: normalisedFlowId, className, children: render(tree) })
7785
- }
7786
- )
7787
- };
7786
+ return /* @__PURE__ */ jsx6(
7787
+ ErrorBoundary_default,
7788
+ {
7789
+ onError: (error) => {
7790
+ onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed", { error });
7791
+ onError == null ? void 0 : onError(error);
7792
+ onLog == null ? void 0 : onLog("error", "Dynamic Flow - ErrorBoundary", { errorMessage: getErrorMessage(error) });
7793
+ },
7794
+ children: /* @__PURE__ */ jsx6("div", { id: normalisedFlowId, className, children: render(tree) })
7795
+ }
7796
+ );
7788
7797
  }
7789
7798
 
7790
- // src/DynamicFlowCore.tsx
7791
- function DynamicFlowCore(props) {
7792
- const df = useDynamicFlow(props);
7793
- return df.component;
7794
- }
7799
+ // src/DynamicFormCore.tsx
7800
+ import { forwardRef, useImperativeHandle, useMemo as useMemo3 } from "react";
7801
+
7802
+ // src/utils/openLinkInNewTab.tsx
7803
+ var openLinkInNewTab = (url) => {
7804
+ var _a;
7805
+ try {
7806
+ const w = (_a = window == null ? void 0 : window.open) == null ? void 0 : _a.call(window, url, "_blank");
7807
+ return Boolean(w);
7808
+ } catch (e) {
7809
+ return false;
7810
+ }
7811
+ };
7812
+
7813
+ // src/DynamicFormCore.tsx
7814
+ import { jsx as jsx7 } from "react/jsx-runtime";
7815
+ var className2 = "dynamic-flow";
7816
+ var DynamicFormCore = forwardRef(function DynamicFormCore2(props, ref) {
7817
+ var _a;
7818
+ const {
7819
+ onCompletion = () => {
7820
+ },
7821
+ httpClient,
7822
+ onEvent,
7823
+ onError,
7824
+ onLink = openLinkInNewTab,
7825
+ renderers
7826
+ } = props;
7827
+ const normalisedFlowId = normaliseFlowId(props.flowId);
7828
+ const scrollToTop = useMemo3(
7829
+ () => getScrollToTop(normalisedFlowId, className2),
7830
+ [normalisedFlowId]
7831
+ );
7832
+ const features = useMemo3(() => {
7833
+ var _a2;
7834
+ return new FeatureFlags((_a2 = props.features) != null ? _a2 : {});
7835
+ }, []);
7836
+ const { rootComponent } = useDynamicFlowCore(__spreadProps(__spreadValues({
7837
+ onCompletion
7838
+ }, props), {
7839
+ features,
7840
+ scrollToTop,
7841
+ onLink
7842
+ }));
7843
+ useImperativeHandle(
7844
+ ref,
7845
+ () => ({
7846
+ getValue: async () => {
7847
+ var _a2;
7848
+ return (_a2 = await rootComponent.getSubmittableValue()) != null ? _a2 : null;
7849
+ },
7850
+ validate: () => rootComponent.validate()
7851
+ }),
7852
+ // eslint-disable-next-line react-hooks/exhaustive-deps
7853
+ []
7854
+ );
7855
+ const render = useMemo3(
7856
+ () => getRenderFunction([CoreRootRenderer, CoreContainerRenderer, ...renderers]),
7857
+ [renderers]
7858
+ );
7859
+ const tree = componentToRendererProps(rootComponent, {
7860
+ features,
7861
+ render,
7862
+ httpClient,
7863
+ trackEvent: (_a = rootComponent.getTrackEvent()) != null ? _a : (() => {
7864
+ }),
7865
+ stepLoadingState: rootComponent.getLoadingState()
7866
+ });
7867
+ return /* @__PURE__ */ jsx7(
7868
+ ErrorBoundary_default,
7869
+ {
7870
+ onError: (error) => {
7871
+ onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed");
7872
+ onError(error);
7873
+ },
7874
+ children: /* @__PURE__ */ jsx7("div", { id: normalisedFlowId, className: className2, children: render(tree) })
7875
+ }
7876
+ );
7877
+ });
7795
7878
  export {
7796
7879
  DynamicFlowCore as DynamicFlow,
7880
+ DynamicFormCore as DynamicForm,
7797
7881
  findRendererPropsByType,
7798
7882
  makeHttpClient,
7799
- i18n_default as translations,
7800
- useDynamicFlow
7883
+ i18n_default as translations
7801
7884
  };
@@ -1,5 +1,2 @@
1
1
  import type { DynamicFlowCoreProps } from './types';
2
- /**
3
- * @deprecated Use `useDynamicFlow` hook instead.
4
- */
5
2
  export declare function DynamicFlowCore(props: DynamicFlowCoreProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import type { DynamicFlowCoreProps, DynamicFormController } from './types';
2
+ import type { OnValueChange } from './domain/types';
3
+ /**
4
+ * DynamicFormCore is like DynamicFlowCore, but it also accepts a ForwardedRef.
5
+ * This ref conforms to the DynamicFormController type, containing two functions: `getValue` and `validate`.
6
+ * @experimental This component may be changed in the future without notice.
7
+ */
8
+ export declare const DynamicFormCore: import("react").ForwardRefExoticComponent<Omit<DynamicFlowCoreProps, "onCompletion"> & {
9
+ onValueChange?: OnValueChange;
10
+ onCompletion?: DynamicFlowCoreProps["onCompletion"];
11
+ } & import("react").RefAttributes<DynamicFormController>>;
@@ -8,10 +8,8 @@ export type RootDomainComponent = BaseComponent & {
8
8
  kind: 'step';
9
9
  stepComponent: StepDomainComponent | null;
10
10
  stepStack: StepDomainComponent[];
11
- backConfig: {
12
- isNativeBackEnabled: boolean;
13
- isFlowCancellable: boolean;
14
- };
11
+ isNativeBackEnabled: boolean;
12
+ isFlowCancellable: boolean;
15
13
  canPerformBack: () => boolean;
16
14
  dismissAllModals: () => void;
17
15
  dismissModal: () => void;
@@ -23,4 +23,5 @@ export declare const getAboveMaximumDateCheck: GetIsInvalidCheck<StringSchema, s
23
23
  export declare const getBelowMinimumDateCheck: GetIsInvalidCheck<StringSchema, string | null>;
24
24
  export declare const getNotAdheringToPatternCheck: GetIsInvalidCheck<StringSchema, string | null>;
25
25
  export declare const getRequiredCheck: (required: boolean, messageFunctions: ErrorMessageFunctions) => IsInvalidCheck<LocalValue | null>;
26
+ export declare const getValidDateCheck: (required: boolean, messageFunctions: ErrorMessageFunctions) => IsInvalidCheck<string | null>;
26
27
  export {};
@@ -1,6 +1,6 @@
1
1
  export { makeHttpClient } from './common/makeHttpClient';
2
2
  export { default as translations } from './i18n';
3
- export type { DynamicFlowCoreProps as DynamicFlowProps } from './types';
4
- export { findRendererPropsByType } from './renderers/utils';
5
- export { useDynamicFlow } from './useDynamicFlow';
3
+ export type { DynamicFlowCoreProps as DynamicFlowProps, DynamicFormController } from './types';
6
4
  export { DynamicFlowCore as DynamicFlow } from './DynamicFlowCore';
5
+ export { DynamicFormCore as DynamicForm } from './DynamicFormCore';
6
+ export { findRendererPropsByType } from './renderers/utils';
@@ -1,4 +1,4 @@
1
- import type { MultiSelectComponent } from '../../domain/components/MultiSelectInputComponent';
2
1
  import type { MultiSelectInputRendererProps } from '@wise/dynamic-flow-types/renderers';
2
+ import type { MultiSelectComponent } from '../../domain/components/MultiSelectInputComponent';
3
3
  import { RendererMapperProps } from './componentToRendererProps';
4
4
  export declare const multiSelectInputComponentToProps: (component: MultiSelectComponent, rendererMapperProps: RendererMapperProps) => MultiSelectInputRendererProps;
@@ -1,4 +1,4 @@
1
- import type { SelectInputComponent } from '../../domain/components/SelectInputComponent';
2
1
  import type { SelectInputRendererProps } from '@wise/dynamic-flow-types/renderers';
2
+ import type { SelectInputComponent } from '../../domain/components/SelectInputComponent';
3
3
  import { type RendererMapperProps } from './componentToRendererProps';
4
4
  export declare const selectInputComponentToProps: (component: SelectInputComponent, rendererMapperProps: RendererMapperProps) => SelectInputRendererProps;
@@ -0,0 +1,5 @@
1
+ import type { SelectInputRendererOption } from '@wise/dynamic-flow-types/renderers';
2
+ import { SelectInputOption } from '../../../domain/components/SelectInputComponent';
3
+ import { SchemaComponent } from '../../../domain/types';
4
+ import { RendererMapperProps } from '../componentToRendererProps';
5
+ export declare const selectInputOptionsToProps: (options: SelectInputOption[], children: SchemaComponent[], rendererMapperProps: RendererMapperProps) => SelectInputRendererOption[];
@@ -1,5 +1,5 @@
1
1
  import type { Renderers } from '@wise/dynamic-flow-types/renderers';
2
- import type { Model, Step } from '@wise/dynamic-flow-types/spec';
2
+ import type { JsonElement, Model, Step } from '@wise/dynamic-flow-types/spec';
3
3
  import type { AnalyticsEventHandler, LoggingEventHandler } from './domain/features/events';
4
4
  export type DynamicFlowCoreProps = {
5
5
  flowId: string;
@@ -16,6 +16,16 @@ export type DynamicFlowCoreProps = {
16
16
  onLog?: LoggingEventHandler;
17
17
  onLink: (url: string) => boolean;
18
18
  };
19
+ export type DynamicFormController = {
20
+ /**
21
+ * Returns the current value of the form, even if it doesn't pass validation.
22
+ */
23
+ getValue: () => Promise<JsonElement>;
24
+ /**
25
+ * triggers validation in every UI component and returns whether or not the current value is valid.
26
+ */
27
+ validate: () => boolean;
28
+ };
19
29
  export type InitialAction = {
20
30
  id?: string;
21
31
  url: string;
@@ -8,9 +8,7 @@ type UseDynamicFlowCoreProps = Omit<DynamicFlowCoreProps, 'renderers' | 'feature
8
8
  scrollToTop?: ScrollToTop;
9
9
  onLink: (url: string) => boolean;
10
10
  };
11
- export declare function useDynamicFlowController(props: UseDynamicFlowCoreProps): {
11
+ export declare function useDynamicFlowCore(props: UseDynamicFlowCoreProps): {
12
12
  rootComponent: RootDomainComponent;
13
- cancelFlow: () => void;
14
- navigateBack: () => void;
15
13
  };
16
14
  export {};
@@ -1,2 +1,2 @@
1
- import type { ScrollToTop } from '../domain/types';
1
+ import { ScrollToTop } from '../domain/types';
2
2
  export declare const getScrollToTop: (normalisedFlowId: string, className: string) => ScrollToTop;
@@ -8,3 +8,4 @@ export declare const isNull: (value: unknown) => value is null;
8
8
  export declare const isUndefined: (value: unknown) => value is undefined;
9
9
  export declare const isNullish: (v: unknown) => v is null | undefined;
10
10
  export declare const isFile: (value: unknown) => value is File;
11
+ export declare const isValidDate: (value: string | null) => boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wise/dynamic-flow-client",
3
- "version": "5.2.0-exp-bits-29346f3",
3
+ "version": "5.2.0",
4
4
  "description": "Dynamic Flow web client",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./build/main.js",
@@ -72,8 +72,8 @@
72
72
  "typescript": "5.9.3",
73
73
  "vitest": "4.0.16",
74
74
  "vitest-fetch-mock": "0.4.5",
75
- "@wise/dynamic-flow-renderers": "0.0.0",
76
- "@wise/dynamic-flow-fixtures": "0.0.1"
75
+ "@wise/dynamic-flow-fixtures": "0.0.1",
76
+ "@wise/dynamic-flow-renderers": "0.0.0"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "@transferwise/components": "^46.104.0",
@@ -86,7 +86,7 @@
86
86
  "react-intl": "^6"
87
87
  },
88
88
  "dependencies": {
89
- "@wise/dynamic-flow-types": "4.2.0-exp-bits-29346f3"
89
+ "@wise/dynamic-flow-types": "4.3.0"
90
90
  },
91
91
  "scripts": {
92
92
  "dev": "EXCLUDE_VISUAL_TESTS=true pnpm storybook dev -p 3003",
@@ -1,13 +0,0 @@
1
- import type { DynamicFlowCoreProps } from './types';
2
- /**
3
- * @experimental This hook may be changed or removed in the future without notice.
4
- */
5
- export declare function useDynamicFlow(props: DynamicFlowCoreProps): {
6
- title: string;
7
- getSubmittableValue: () => Promise<import("@wise/dynamic-flow-types/spec").JsonElement>;
8
- validate: () => boolean;
9
- rootComponent: import("./domain/components/RootDomainComponent").RootDomainComponent;
10
- cancelFlow: () => void;
11
- navigateBack: () => void;
12
- component: import("react/jsx-runtime").JSX.Element;
13
- };
@@ -1,2 +0,0 @@
1
- import { FeatureFlags } from '../domain/mappers/utils/FeatureFlags';
2
- export declare const useFeatureFlags: (features: Record<string, unknown> | undefined) => FeatureFlags;