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

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/build/main.css CHANGED
@@ -176,6 +176,10 @@
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
+ }
179
183
  .chips-container {
180
184
  overflow-x: auto;
181
185
  }
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,
61
60
  findRendererPropsByType: () => findRendererPropsByType,
62
61
  makeHttpClient: () => makeHttpClient,
63
- translations: () => i18n_default
62
+ translations: () => i18n_default,
63
+ useDynamicFlow: () => useDynamicFlow
64
64
  });
65
65
  module.exports = __toCommonJS(index_exports);
66
66
 
@@ -778,7 +778,81 @@ var translations = {
778
778
  };
779
779
  var i18n_default = translations;
780
780
 
781
- // src/DynamicFlowCore.tsx
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
782
856
  var import_react4 = require("react");
783
857
 
784
858
  // src/common/errorBoundary/ErrorBoundary.tsx
@@ -882,80 +956,6 @@ var CoreContainerRenderer = {
882
956
  render: ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children })
883
957
  };
884
958
 
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
-
897
- // src/renderers/utils.ts
898
- function findRendererPropsByType(root, type, predicate = () => true) {
899
- if (isArray(root)) {
900
- return root.flatMap((child) => findRendererPropsByType(child, type, predicate));
901
- }
902
- return [
903
- ...isType(root, type) && predicate(root) ? [root] : [],
904
- ...getChildren(root).flatMap((child) => findRendererPropsByType(child, type, predicate))
905
- ];
906
- }
907
- var isType = (node, type) => node.type === type;
908
- var getChildren = (node) => {
909
- switch (node.type) {
910
- case "root":
911
- case "box":
912
- case "container":
913
- case "form":
914
- case "form-section":
915
- case "step":
916
- case "modal":
917
- case "section":
918
- return node.childrenProps;
919
- case "columns":
920
- return [...node.startChildrenProps, ...node.endChildrenProps];
921
- case "modal-layout":
922
- return node.content.childrenProps;
923
- case "repeatable":
924
- return node.editableItemProps ? [node.editableItemProps] : [];
925
- case "input-select":
926
- return node.childrenProps ? [node.childrenProps] : [];
927
- case "tabs":
928
- return node.tabs.flatMap((c) => c.childrenProps);
929
- case "alert":
930
- case "button":
931
- case "input-checkbox":
932
- case "input-date":
933
- case "decision":
934
- case "divider":
935
- case "heading":
936
- case "hidden":
937
- case "image":
938
- case "instructions":
939
- case "input-integer":
940
- case "list":
941
- case "loading-indicator":
942
- case "markdown":
943
- case "input-multi-select":
944
- case "input-upload-multi":
945
- case "input-number":
946
- case "money-input":
947
- case "paragraph":
948
- case "progress":
949
- case "review":
950
- case "search":
951
- case "status-list":
952
- case "input-text":
953
- case "input-upload":
954
- case "external-confirmation":
955
- return [];
956
- }
957
- };
958
-
959
959
  // src/renderers/CoreRootRenderer.tsx
960
960
  var import_jsx_runtime4 = require("react/jsx-runtime");
961
961
  var CoreRootRenderer = {
@@ -1979,7 +1979,7 @@ var getComponentAlertProps = (component, rendererMapperProps) => "alert" in comp
1979
1979
  markdown: component.alert.content
1980
1980
  }, rendererMapperProps) : null;
1981
1981
 
1982
- // src/useDynamicFlowCore.tsx
1982
+ // src/useDynamicFlowController.tsx
1983
1983
  var import_react3 = require("react");
1984
1984
  var import_react_intl7 = require("react-intl");
1985
1985
 
@@ -2000,8 +2000,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2000
2000
  uid: "root",
2001
2001
  stepComponent: null,
2002
2002
  stepStack: [],
2003
- isNativeBackEnabled: backConfig.isNativeBackEnabled,
2004
- isFlowCancellable: backConfig.isFlowCancellable,
2003
+ backConfig,
2005
2004
  _update(updateFn) {
2006
2005
  update(this, updateFn);
2007
2006
  },
@@ -2135,7 +2134,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2135
2134
  var _a, _b;
2136
2135
  const navigation = (_a = this.getStep()) == null ? void 0 : _a.step.navigation;
2137
2136
  const stepHasBehavior = Boolean((_b = navigation == null ? void 0 : navigation.back) != null ? _b : navigation == null ? void 0 : navigation.backButton);
2138
- return this.isFlowCancellable || this.stepStack.length > 1 && this.isNativeBackEnabled || stepHasBehavior;
2137
+ return this.backConfig.isFlowCancellable || this.stepStack.length > 1 && this.backConfig.isNativeBackEnabled || stepHasBehavior;
2139
2138
  }
2140
2139
  };
2141
2140
  return rootComponent;
@@ -7325,8 +7324,8 @@ function useStableCallback(handler) {
7325
7324
  return (0, import_react2.useCallback)((...args) => ref.current ? ref.current(...args) : null, []);
7326
7325
  }
7327
7326
 
7328
- // src/useDynamicFlowCore.tsx
7329
- function useDynamicFlowCore(props) {
7327
+ // src/useDynamicFlowController.tsx
7328
+ function useDynamicFlowController(props) {
7330
7329
  const _a = props, { flowId, initialAction, initialStep, features } = _a, rest = __objRest(_a, ["flowId", "initialAction", "initialStep", "features"]);
7331
7330
  const httpClient = useStableCallback(rest.httpClient);
7332
7331
  const onCancellation = useStableCallback(rest.onCancellation);
@@ -7725,20 +7724,29 @@ function useDynamicFlowCore(props) {
7725
7724
  trackCoreEvent("Step Shown", { isFirstStep: true });
7726
7725
  hasMappedInitialStep.current = true;
7727
7726
  }
7728
- return { rootComponent: rootComponentRef.current };
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
+ };
7729
7740
  }
7730
7741
  var useRerender = () => {
7731
7742
  const [, setState] = (0, import_react3.useState)({});
7732
7743
  return (0, import_react3.useCallback)(() => setState({}), []);
7733
7744
  };
7734
7745
 
7735
- // src/utils/normalise-flow-id.ts
7736
- var normaliseFlowId = (flowId) => flowId.toLowerCase().replace(/[^a-z-]/g, "-");
7737
-
7738
- // src/utils/scrollToTop.ts
7739
- var getScrollToTop = (normalisedFlowId, className3) => (behavior) => {
7746
+ // src/utils/getScrollToTop.ts
7747
+ var getScrollToTop = (normalisedFlowId, className2) => (behavior) => {
7740
7748
  var _a;
7741
- const element = document.querySelector(`div#${normalisedFlowId}.${className3}`);
7749
+ const element = document.querySelector(`div#${normalisedFlowId}.${className2}`);
7742
7750
  if (!element || !window) {
7743
7751
  return;
7744
7752
  }
@@ -7749,11 +7757,14 @@ var getScrollToTop = (normalisedFlowId, className3) => (behavior) => {
7749
7757
  }
7750
7758
  };
7751
7759
 
7752
- // src/DynamicFlowCore.tsx
7760
+ // src/utils/normalise-flow-id.ts
7761
+ var normaliseFlowId = (flowId) => flowId.toLowerCase().replace(/[^a-z-]/g, "-");
7762
+
7763
+ // src/useDynamicFlow.tsx
7753
7764
  var import_jsx_runtime6 = require("react/jsx-runtime");
7754
7765
  var className = "dynamic-flow";
7755
- function DynamicFlowCore(props) {
7756
- var _a;
7766
+ function useDynamicFlow(props) {
7767
+ var _a, _b, _c;
7757
7768
  const { flowId, renderers, httpClient, onEvent, onError, onLog } = props;
7758
7769
  const normalisedFlowId = normaliseFlowId(flowId);
7759
7770
  const scrollToTop = (0, import_react4.useMemo)(
@@ -7764,7 +7775,10 @@ function DynamicFlowCore(props) {
7764
7775
  var _a2;
7765
7776
  return new FeatureFlags((_a2 = props.features) != null ? _a2 : {});
7766
7777
  }, []);
7767
- const { rootComponent } = useDynamicFlowCore(__spreadProps(__spreadValues({}, props), { features, scrollToTop }));
7778
+ const { rootComponent, cancelFlow, navigateBack } = useDynamicFlowController(__spreadProps(__spreadValues({}, props), {
7779
+ features,
7780
+ scrollToTop
7781
+ }));
7768
7782
  const render = (0, import_react4.useMemo)(
7769
7783
  () => getRenderFunction([CoreRootRenderer, CoreContainerRenderer, ...renderers]),
7770
7784
  [renderers]
@@ -7777,95 +7791,31 @@ function DynamicFlowCore(props) {
7777
7791
  }),
7778
7792
  stepLoadingState: rootComponent.getLoadingState()
7779
7793
  });
7780
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
7781
- ErrorBoundary_default,
7782
- {
7783
- onError: (error) => {
7784
- onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed", { error });
7785
- onError == null ? void 0 : onError(error);
7786
- onLog == null ? void 0 : onLog("error", "Dynamic Flow - ErrorBoundary", { errorMessage: getErrorMessage(error) });
7787
- },
7788
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { id: normalisedFlowId, className, children: render(tree) })
7789
- }
7790
- );
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
+ };
7791
7815
  }
7792
7816
 
7793
- // src/DynamicFormCore.tsx
7794
- var import_react5 = require("react");
7795
-
7796
- // src/utils/openLinkInNewTab.tsx
7797
- var openLinkInNewTab = (url) => {
7798
- var _a;
7799
- try {
7800
- const w = (_a = window == null ? void 0 : window.open) == null ? void 0 : _a.call(window, url, "_blank");
7801
- return Boolean(w);
7802
- } catch (e) {
7803
- return false;
7804
- }
7805
- };
7806
-
7807
- // src/DynamicFormCore.tsx
7808
- var import_jsx_runtime7 = require("react/jsx-runtime");
7809
- var className2 = "dynamic-flow";
7810
- var DynamicFormCore = (0, import_react5.forwardRef)(function DynamicFormCore2(props, ref) {
7811
- var _a;
7812
- const {
7813
- onCompletion = () => {
7814
- },
7815
- httpClient,
7816
- onEvent,
7817
- onError,
7818
- onLink = openLinkInNewTab,
7819
- renderers
7820
- } = props;
7821
- const normalisedFlowId = normaliseFlowId(props.flowId);
7822
- const scrollToTop = (0, import_react5.useMemo)(
7823
- () => getScrollToTop(normalisedFlowId, className2),
7824
- [normalisedFlowId]
7825
- );
7826
- const features = (0, import_react5.useMemo)(() => {
7827
- var _a2;
7828
- return new FeatureFlags((_a2 = props.features) != null ? _a2 : {});
7829
- }, []);
7830
- const { rootComponent } = useDynamicFlowCore(__spreadProps(__spreadValues({
7831
- onCompletion
7832
- }, props), {
7833
- features,
7834
- scrollToTop,
7835
- onLink
7836
- }));
7837
- (0, import_react5.useImperativeHandle)(
7838
- ref,
7839
- () => ({
7840
- getValue: async () => {
7841
- var _a2;
7842
- return (_a2 = await rootComponent.getSubmittableValue()) != null ? _a2 : null;
7843
- },
7844
- validate: () => rootComponent.validate()
7845
- }),
7846
- // eslint-disable-next-line react-hooks/exhaustive-deps
7847
- []
7848
- );
7849
- const render = (0, import_react5.useMemo)(
7850
- () => getRenderFunction([CoreRootRenderer, CoreContainerRenderer, ...renderers]),
7851
- [renderers]
7852
- );
7853
- const tree = componentToRendererProps(rootComponent, {
7854
- features,
7855
- render,
7856
- httpClient,
7857
- trackEvent: (_a = rootComponent.getTrackEvent()) != null ? _a : (() => {
7858
- }),
7859
- stepLoadingState: rootComponent.getLoadingState()
7860
- });
7861
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
7862
- ErrorBoundary_default,
7863
- {
7864
- onError: (error) => {
7865
- onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed");
7866
- onError(error);
7867
- },
7868
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { id: normalisedFlowId, className: className2, children: render(tree) })
7869
- }
7870
- );
7871
- });
7817
+ // src/DynamicFlowCore.tsx
7818
+ function DynamicFlowCore(props) {
7819
+ const df = useDynamicFlow(props);
7820
+ return df.component;
7821
+ }
package/build/main.mjs CHANGED
@@ -751,7 +751,81 @@ var translations = {
751
751
  };
752
752
  var i18n_default = translations;
753
753
 
754
- // src/DynamicFlowCore.tsx
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
755
829
  import { useMemo as useMemo2 } from "react";
756
830
 
757
831
  // src/common/errorBoundary/ErrorBoundary.tsx
@@ -855,80 +929,6 @@ var CoreContainerRenderer = {
855
929
  render: ({ children }) => /* @__PURE__ */ jsx3(Fragment2, { children })
856
930
  };
857
931
 
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
-
870
- // src/renderers/utils.ts
871
- function findRendererPropsByType(root, type, predicate = () => true) {
872
- if (isArray(root)) {
873
- return root.flatMap((child) => findRendererPropsByType(child, type, predicate));
874
- }
875
- return [
876
- ...isType(root, type) && predicate(root) ? [root] : [],
877
- ...getChildren(root).flatMap((child) => findRendererPropsByType(child, type, predicate))
878
- ];
879
- }
880
- var isType = (node, type) => node.type === type;
881
- var getChildren = (node) => {
882
- switch (node.type) {
883
- case "root":
884
- case "box":
885
- case "container":
886
- case "form":
887
- case "form-section":
888
- case "step":
889
- case "modal":
890
- case "section":
891
- return node.childrenProps;
892
- case "columns":
893
- return [...node.startChildrenProps, ...node.endChildrenProps];
894
- case "modal-layout":
895
- return node.content.childrenProps;
896
- case "repeatable":
897
- return node.editableItemProps ? [node.editableItemProps] : [];
898
- case "input-select":
899
- return node.childrenProps ? [node.childrenProps] : [];
900
- case "tabs":
901
- return node.tabs.flatMap((c) => c.childrenProps);
902
- case "alert":
903
- case "button":
904
- case "input-checkbox":
905
- case "input-date":
906
- case "decision":
907
- case "divider":
908
- case "heading":
909
- case "hidden":
910
- case "image":
911
- case "instructions":
912
- case "input-integer":
913
- case "list":
914
- case "loading-indicator":
915
- case "markdown":
916
- case "input-multi-select":
917
- case "input-upload-multi":
918
- case "input-number":
919
- case "money-input":
920
- case "paragraph":
921
- case "progress":
922
- case "review":
923
- case "search":
924
- case "status-list":
925
- case "input-text":
926
- case "input-upload":
927
- case "external-confirmation":
928
- return [];
929
- }
930
- };
931
-
932
932
  // src/renderers/CoreRootRenderer.tsx
933
933
  import { jsx as jsx4 } from "react/jsx-runtime";
934
934
  var CoreRootRenderer = {
@@ -1952,7 +1952,7 @@ var getComponentAlertProps = (component, rendererMapperProps) => "alert" in comp
1952
1952
  markdown: component.alert.content
1953
1953
  }, rendererMapperProps) : null;
1954
1954
 
1955
- // src/useDynamicFlowCore.tsx
1955
+ // src/useDynamicFlowController.tsx
1956
1956
  import { useCallback as useCallback2, useEffect, useMemo, useRef as useRef2, useState } from "react";
1957
1957
  import { useIntl as useIntl2 } from "react-intl";
1958
1958
 
@@ -1973,8 +1973,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
1973
1973
  uid: "root",
1974
1974
  stepComponent: null,
1975
1975
  stepStack: [],
1976
- isNativeBackEnabled: backConfig.isNativeBackEnabled,
1977
- isFlowCancellable: backConfig.isFlowCancellable,
1976
+ backConfig,
1978
1977
  _update(updateFn) {
1979
1978
  update(this, updateFn);
1980
1979
  },
@@ -2108,7 +2107,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2108
2107
  var _a, _b;
2109
2108
  const navigation = (_a = this.getStep()) == null ? void 0 : _a.step.navigation;
2110
2109
  const stepHasBehavior = Boolean((_b = navigation == null ? void 0 : navigation.back) != null ? _b : navigation == null ? void 0 : navigation.backButton);
2111
- return this.isFlowCancellable || this.stepStack.length > 1 && this.isNativeBackEnabled || stepHasBehavior;
2110
+ return this.backConfig.isFlowCancellable || this.stepStack.length > 1 && this.backConfig.isNativeBackEnabled || stepHasBehavior;
2112
2111
  }
2113
2112
  };
2114
2113
  return rootComponent;
@@ -7298,8 +7297,8 @@ function useStableCallback(handler) {
7298
7297
  return useCallback((...args) => ref.current ? ref.current(...args) : null, []);
7299
7298
  }
7300
7299
 
7301
- // src/useDynamicFlowCore.tsx
7302
- function useDynamicFlowCore(props) {
7300
+ // src/useDynamicFlowController.tsx
7301
+ function useDynamicFlowController(props) {
7303
7302
  const _a = props, { flowId, initialAction, initialStep, features } = _a, rest = __objRest(_a, ["flowId", "initialAction", "initialStep", "features"]);
7304
7303
  const httpClient = useStableCallback(rest.httpClient);
7305
7304
  const onCancellation = useStableCallback(rest.onCancellation);
@@ -7698,20 +7697,29 @@ function useDynamicFlowCore(props) {
7698
7697
  trackCoreEvent("Step Shown", { isFirstStep: true });
7699
7698
  hasMappedInitialStep.current = true;
7700
7699
  }
7701
- return { rootComponent: rootComponentRef.current };
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
+ };
7702
7713
  }
7703
7714
  var useRerender = () => {
7704
7715
  const [, setState] = useState({});
7705
7716
  return useCallback2(() => setState({}), []);
7706
7717
  };
7707
7718
 
7708
- // src/utils/normalise-flow-id.ts
7709
- var normaliseFlowId = (flowId) => flowId.toLowerCase().replace(/[^a-z-]/g, "-");
7710
-
7711
- // src/utils/scrollToTop.ts
7712
- var getScrollToTop = (normalisedFlowId, className3) => (behavior) => {
7719
+ // src/utils/getScrollToTop.ts
7720
+ var getScrollToTop = (normalisedFlowId, className2) => (behavior) => {
7713
7721
  var _a;
7714
- const element = document.querySelector(`div#${normalisedFlowId}.${className3}`);
7722
+ const element = document.querySelector(`div#${normalisedFlowId}.${className2}`);
7715
7723
  if (!element || !window) {
7716
7724
  return;
7717
7725
  }
@@ -7722,11 +7730,14 @@ var getScrollToTop = (normalisedFlowId, className3) => (behavior) => {
7722
7730
  }
7723
7731
  };
7724
7732
 
7725
- // src/DynamicFlowCore.tsx
7733
+ // src/utils/normalise-flow-id.ts
7734
+ var normaliseFlowId = (flowId) => flowId.toLowerCase().replace(/[^a-z-]/g, "-");
7735
+
7736
+ // src/useDynamicFlow.tsx
7726
7737
  import { jsx as jsx6 } from "react/jsx-runtime";
7727
7738
  var className = "dynamic-flow";
7728
- function DynamicFlowCore(props) {
7729
- var _a;
7739
+ function useDynamicFlow(props) {
7740
+ var _a, _b, _c;
7730
7741
  const { flowId, renderers, httpClient, onEvent, onError, onLog } = props;
7731
7742
  const normalisedFlowId = normaliseFlowId(flowId);
7732
7743
  const scrollToTop = useMemo2(
@@ -7737,7 +7748,10 @@ function DynamicFlowCore(props) {
7737
7748
  var _a2;
7738
7749
  return new FeatureFlags((_a2 = props.features) != null ? _a2 : {});
7739
7750
  }, []);
7740
- const { rootComponent } = useDynamicFlowCore(__spreadProps(__spreadValues({}, props), { features, scrollToTop }));
7751
+ const { rootComponent, cancelFlow, navigateBack } = useDynamicFlowController(__spreadProps(__spreadValues({}, props), {
7752
+ features,
7753
+ scrollToTop
7754
+ }));
7741
7755
  const render = useMemo2(
7742
7756
  () => getRenderFunction([CoreRootRenderer, CoreContainerRenderer, ...renderers]),
7743
7757
  [renderers]
@@ -7750,102 +7764,38 @@ function DynamicFlowCore(props) {
7750
7764
  }),
7751
7765
  stepLoadingState: rootComponent.getLoadingState()
7752
7766
  });
7753
- return /* @__PURE__ */ jsx6(
7754
- ErrorBoundary_default,
7755
- {
7756
- onError: (error) => {
7757
- onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed", { error });
7758
- onError == null ? void 0 : onError(error);
7759
- onLog == null ? void 0 : onLog("error", "Dynamic Flow - ErrorBoundary", { errorMessage: getErrorMessage(error) });
7760
- },
7761
- children: /* @__PURE__ */ jsx6("div", { id: normalisedFlowId, className, children: render(tree) })
7762
- }
7763
- );
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
+ };
7764
7788
  }
7765
7789
 
7766
- // src/DynamicFormCore.tsx
7767
- import { forwardRef, useImperativeHandle, useMemo as useMemo3 } from "react";
7768
-
7769
- // src/utils/openLinkInNewTab.tsx
7770
- var openLinkInNewTab = (url) => {
7771
- var _a;
7772
- try {
7773
- const w = (_a = window == null ? void 0 : window.open) == null ? void 0 : _a.call(window, url, "_blank");
7774
- return Boolean(w);
7775
- } catch (e) {
7776
- return false;
7777
- }
7778
- };
7779
-
7780
- // src/DynamicFormCore.tsx
7781
- import { jsx as jsx7 } from "react/jsx-runtime";
7782
- var className2 = "dynamic-flow";
7783
- var DynamicFormCore = forwardRef(function DynamicFormCore2(props, ref) {
7784
- var _a;
7785
- const {
7786
- onCompletion = () => {
7787
- },
7788
- httpClient,
7789
- onEvent,
7790
- onError,
7791
- onLink = openLinkInNewTab,
7792
- renderers
7793
- } = props;
7794
- const normalisedFlowId = normaliseFlowId(props.flowId);
7795
- const scrollToTop = useMemo3(
7796
- () => getScrollToTop(normalisedFlowId, className2),
7797
- [normalisedFlowId]
7798
- );
7799
- const features = useMemo3(() => {
7800
- var _a2;
7801
- return new FeatureFlags((_a2 = props.features) != null ? _a2 : {});
7802
- }, []);
7803
- const { rootComponent } = useDynamicFlowCore(__spreadProps(__spreadValues({
7804
- onCompletion
7805
- }, props), {
7806
- features,
7807
- scrollToTop,
7808
- onLink
7809
- }));
7810
- useImperativeHandle(
7811
- ref,
7812
- () => ({
7813
- getValue: async () => {
7814
- var _a2;
7815
- return (_a2 = await rootComponent.getSubmittableValue()) != null ? _a2 : null;
7816
- },
7817
- validate: () => rootComponent.validate()
7818
- }),
7819
- // eslint-disable-next-line react-hooks/exhaustive-deps
7820
- []
7821
- );
7822
- const render = useMemo3(
7823
- () => getRenderFunction([CoreRootRenderer, CoreContainerRenderer, ...renderers]),
7824
- [renderers]
7825
- );
7826
- const tree = componentToRendererProps(rootComponent, {
7827
- features,
7828
- render,
7829
- httpClient,
7830
- trackEvent: (_a = rootComponent.getTrackEvent()) != null ? _a : (() => {
7831
- }),
7832
- stepLoadingState: rootComponent.getLoadingState()
7833
- });
7834
- return /* @__PURE__ */ jsx7(
7835
- ErrorBoundary_default,
7836
- {
7837
- onError: (error) => {
7838
- onEvent == null ? void 0 : onEvent("Dynamic Flow - Failed");
7839
- onError(error);
7840
- },
7841
- children: /* @__PURE__ */ jsx7("div", { id: normalisedFlowId, className: className2, children: render(tree) })
7842
- }
7843
- );
7844
- });
7790
+ // src/DynamicFlowCore.tsx
7791
+ function DynamicFlowCore(props) {
7792
+ const df = useDynamicFlow(props);
7793
+ return df.component;
7794
+ }
7845
7795
  export {
7846
7796
  DynamicFlowCore as DynamicFlow,
7847
- DynamicFormCore as DynamicForm,
7848
7797
  findRendererPropsByType,
7849
7798
  makeHttpClient,
7850
- i18n_default as translations
7799
+ i18n_default as translations,
7800
+ useDynamicFlow
7851
7801
  };
@@ -1,2 +1,5 @@
1
1
  import type { DynamicFlowCoreProps } from './types';
2
+ /**
3
+ * @deprecated Use `useDynamicFlow` hook instead.
4
+ */
2
5
  export declare function DynamicFlowCore(props: DynamicFlowCoreProps): import("react/jsx-runtime").JSX.Element;
@@ -8,8 +8,10 @@ export type RootDomainComponent = BaseComponent & {
8
8
  kind: 'step';
9
9
  stepComponent: StepDomainComponent | null;
10
10
  stepStack: StepDomainComponent[];
11
- isNativeBackEnabled: boolean;
12
- isFlowCancellable: boolean;
11
+ backConfig: {
12
+ isNativeBackEnabled: boolean;
13
+ isFlowCancellable: boolean;
14
+ };
13
15
  canPerformBack: () => boolean;
14
16
  dismissAllModals: () => void;
15
17
  dismissModal: () => void;
@@ -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, DynamicFormController } from './types';
4
- export { DynamicFlowCore as DynamicFlow } from './DynamicFlowCore';
5
- export { DynamicFormCore as DynamicForm } from './DynamicFormCore';
3
+ export type { DynamicFlowCoreProps as DynamicFlowProps } from './types';
6
4
  export { findRendererPropsByType } from './renderers/utils';
5
+ export { useDynamicFlow } from './useDynamicFlow';
6
+ export { DynamicFlowCore as DynamicFlow } from './DynamicFlowCore';
@@ -1,5 +1,5 @@
1
1
  import type { Renderers } from '@wise/dynamic-flow-types/renderers';
2
- import type { JsonElement, Model, Step } from '@wise/dynamic-flow-types/spec';
2
+ import type { 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,16 +16,6 @@ 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
- };
29
19
  export type InitialAction = {
30
20
  id?: string;
31
21
  url: string;
@@ -0,0 +1,13 @@
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
+ };
@@ -8,7 +8,9 @@ type UseDynamicFlowCoreProps = Omit<DynamicFlowCoreProps, 'renderers' | 'feature
8
8
  scrollToTop?: ScrollToTop;
9
9
  onLink: (url: string) => boolean;
10
10
  };
11
- export declare function useDynamicFlowCore(props: UseDynamicFlowCoreProps): {
11
+ export declare function useDynamicFlowController(props: UseDynamicFlowCoreProps): {
12
12
  rootComponent: RootDomainComponent;
13
+ cancelFlow: () => void;
14
+ navigateBack: () => void;
13
15
  };
14
16
  export {};
@@ -1,2 +1,2 @@
1
- import { ScrollToTop } from '../domain/types';
1
+ import type { ScrollToTop } from '../domain/types';
2
2
  export declare const getScrollToTop: (normalisedFlowId: string, className: string) => ScrollToTop;
@@ -0,0 +1,2 @@
1
+ import { FeatureFlags } from '../domain/mappers/utils/FeatureFlags';
2
+ export declare const useFeatureFlags: (features: Record<string, unknown> | undefined) => FeatureFlags;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wise/dynamic-flow-client",
3
- "version": "5.1.3",
3
+ "version": "5.2.0-exp-bits-29346f3",
4
4
  "description": "Dynamic Flow web client",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./build/main.js",
@@ -86,7 +86,7 @@
86
86
  "react-intl": "^6"
87
87
  },
88
88
  "dependencies": {
89
- "@wise/dynamic-flow-types": "4.2.0"
89
+ "@wise/dynamic-flow-types": "4.2.0-exp-bits-29346f3"
90
90
  },
91
91
  "scripts": {
92
92
  "dev": "EXCLUDE_VISUAL_TESTS=true pnpm storybook dev -p 3003",
@@ -1,11 +0,0 @@
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>>;