@wise/dynamic-flow-client 5.3.0 → 5.4.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.
Files changed (28) hide show
  1. package/build/main.css +6 -0
  2. package/build/main.js +577 -251
  3. package/build/main.mjs +581 -255
  4. package/build/types/domain/components/RootDomainComponent.d.ts +7 -1
  5. package/build/types/domain/components/SelectInputComponent.d.ts +1 -2
  6. package/build/types/domain/components/SubflowDomainComponent.d.ts +16 -0
  7. package/build/types/domain/components/step/StepDomainComponent.d.ts +3 -3
  8. package/build/types/domain/features/eventNames.d.ts +1 -0
  9. package/build/types/domain/features/events.d.ts +2 -1
  10. package/build/types/domain/mappers/mapStepToComponent.d.ts +2 -0
  11. package/build/types/domain/prefetching/request-cache.d.ts +7 -7
  12. package/build/types/domain/types.d.ts +17 -3
  13. package/build/types/flow/executeRequest.d.ts +39 -0
  14. package/build/types/flow/executeSubmission.d.ts +6 -33
  15. package/build/types/flow/getResponseType.d.ts +1 -1
  16. package/build/types/flow/getSafeHttpClient.d.ts +1 -0
  17. package/build/types/flow/handleErrorResponse.d.ts +3 -0
  18. package/build/types/flow/response-utils.d.ts +2 -1
  19. package/build/types/getSubflowCallbacks.d.ts +14 -0
  20. package/build/types/index.d.ts +4 -0
  21. package/build/types/renderers/mappers/subflowComponentToRendererProps.d.ts +4 -0
  22. package/build/types/test-utils/DynamicFlowWiseModal.d.ts +12 -0
  23. package/build/types/test-utils/getMergedTestRenderers.d.ts +2 -0
  24. package/build/types/types.d.ts +2 -0
  25. package/build/types/useDynamicFlowController.d.ts +1 -1
  26. package/build/types/useDynamicFlowModal.d.ts +16 -0
  27. package/package.json +16 -16
  28. package/build/types/flow/makeSubmissionRequest.d.ts +0 -3
package/build/main.mjs CHANGED
@@ -823,6 +823,7 @@ var getChildren = (node) => {
823
823
  case "input-text":
824
824
  case "input-upload":
825
825
  case "external-confirmation":
826
+ case "subflow":
826
827
  return [];
827
828
  }
828
829
  };
@@ -932,17 +933,23 @@ var CoreContainerRenderer = {
932
933
  };
933
934
 
934
935
  // src/renderers/CoreRootRenderer.tsx
935
- import { jsx as jsx4 } from "react/jsx-runtime";
936
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
936
937
  var CoreRootRenderer = {
937
938
  canRenderType: "root",
938
- render: ({ children, childrenProps }) => {
939
+ render: ({ children, childrenProps, subflow }) => {
940
+ if ((subflow == null ? void 0 : subflow.presentation.type) === "push") {
941
+ return /* @__PURE__ */ jsx4(Fragment3, { children: subflow.children });
942
+ }
939
943
  const [stepProps] = findRendererPropsByType(childrenProps, "step");
940
- return /* @__PURE__ */ jsx4("div", { id: stepProps == null ? void 0 : stepProps.id, className: "dynamic-flow-step", children });
944
+ return /* @__PURE__ */ jsxs2("div", { id: stepProps == null ? void 0 : stepProps.id, className: "dynamic-flow-step", children: [
945
+ children,
946
+ (subflow == null ? void 0 : subflow.presentation.type) === "modal" ? subflow.children : void 0
947
+ ] });
941
948
  }
942
949
  };
943
950
 
944
951
  // src/renderers/getRenderFunction.tsx
945
- import { Fragment as Fragment3, jsx as jsx5 } from "react/jsx-runtime";
952
+ import { Fragment as Fragment4, jsx as jsx5 } from "react/jsx-runtime";
946
953
  var getRenderFunction = (renderers) => {
947
954
  function ComponentRenderer(props) {
948
955
  const { type } = props;
@@ -962,7 +969,7 @@ var getRenderFunction = (renderers) => {
962
969
  }
963
970
  const render = (props) => {
964
971
  if (!props) {
965
- return /* @__PURE__ */ jsx5(Fragment3, {});
972
+ return /* @__PURE__ */ jsx5(Fragment4, {});
966
973
  }
967
974
  return /* @__PURE__ */ jsx5(ComponentRenderer, __spreadValues({}, props), props.uid);
968
975
  };
@@ -1685,11 +1692,18 @@ var rootComponentToProps = (rootComponent, rendererMapperProps) => {
1685
1692
  }
1686
1693
  return componentToRendererProps(child, rendererMapperProps);
1687
1694
  });
1695
+ const subflow = rootComponent.subflow ? {
1696
+ presentation: rootComponent.subflow.presentation,
1697
+ children: rendererMapperProps.render(
1698
+ componentToRendererProps(rootComponent.subflow, rendererMapperProps)
1699
+ )
1700
+ } : void 0;
1688
1701
  return __spreadValues({
1689
1702
  type: "root",
1690
1703
  uid: rootComponent.uid,
1691
1704
  children: childrenProps.map(rendererMapperProps.render),
1692
- childrenProps
1705
+ childrenProps,
1706
+ subflow
1693
1707
  }, rendererMapperProps);
1694
1708
  };
1695
1709
 
@@ -1880,6 +1894,19 @@ var uploadInputComponentToProps = (component, rendererMapperProps) => {
1880
1894
  });
1881
1895
  };
1882
1896
 
1897
+ // src/renderers/mappers/subflowComponentToRendererProps.ts
1898
+ var subflowComponentToRendererProps = (component, rendererMapperProps) => {
1899
+ return __spreadValues(__spreadProps(__spreadValues({
1900
+ uid: "subflow",
1901
+ type: "subflow"
1902
+ }, pick(component, "requestCache", "presentation", "initialRequest")), {
1903
+ onCancellation: component.onCancellation.bind(component),
1904
+ onCompletion: component.onCompletion.bind(component),
1905
+ onError: component.onError.bind(component),
1906
+ onEvent: component.onEvent.bind(component)
1907
+ }), rendererMapperProps);
1908
+ };
1909
+
1883
1910
  // src/renderers/mappers/componentToRendererProps.ts
1884
1911
  var componentToRendererProps = (component, mapperProps) => {
1885
1912
  if (isHiddenComponent(component)) {
@@ -1978,6 +2005,8 @@ var getComponentProps = (component, rendererMapperProps) => {
1978
2005
  return selectInputComponentToProps(component, rendererMapperProps);
1979
2006
  case "status-list":
1980
2007
  return statusListComponentToProps(component, rendererMapperProps);
2008
+ case "subflow":
2009
+ return subflowComponentToRendererProps(component, rendererMapperProps);
1981
2010
  case "tabs":
1982
2011
  return tabsComponentToProps(component, rendererMapperProps);
1983
2012
  case "text":
@@ -2015,15 +2044,17 @@ var getInputUpdateFunction = (updateComponent) => {
2015
2044
  };
2016
2045
 
2017
2046
  // src/domain/components/RootDomainComponent.ts
2018
- var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2047
+ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig, requestCache) => {
2019
2048
  const update = getInputUpdateFunction(updateComponent);
2020
2049
  const rootComponent = {
2021
2050
  type: "root",
2022
2051
  kind: "step",
2023
2052
  uid: "root",
2024
2053
  stepComponent: null,
2054
+ subflow: null,
2025
2055
  stepStack: [],
2026
2056
  backConfig,
2057
+ requestCache,
2027
2058
  _update(updateFn) {
2028
2059
  update(this, updateFn);
2029
2060
  },
@@ -2086,6 +2117,16 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2086
2117
  var _a;
2087
2118
  return (_a = this.stepStack[this.stepStack.length - 1]) != null ? _a : null;
2088
2119
  },
2120
+ addSubflow(subflow) {
2121
+ this._update((draft) => {
2122
+ draft.subflow = subflow;
2123
+ });
2124
+ },
2125
+ closeSubflow() {
2126
+ this._update((draft) => {
2127
+ draft.subflow = null;
2128
+ });
2129
+ },
2089
2130
  start() {
2090
2131
  var _a;
2091
2132
  (_a = this.getStep()) == null ? void 0 : _a.start();
@@ -2096,6 +2137,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2096
2137
  },
2097
2138
  updateStep(stepComponent) {
2098
2139
  var _a;
2140
+ this.closeSubflow();
2099
2141
  const shouldScroll = shouldScrollOnStepUpdate(stepComponent, this.getStep());
2100
2142
  this._update((draft) => {
2101
2143
  draft.stepStack = draft.stepStack.slice(0, -1);
@@ -2107,10 +2149,11 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2107
2149
  (_a = this.getStep()) == null ? void 0 : _a.start();
2108
2150
  },
2109
2151
  pushStep(stepComponent) {
2152
+ var _a;
2153
+ this.closeSubflow();
2110
2154
  const previousStep = this.getStep();
2111
2155
  const previousStepHasPolling = previousStep == null ? void 0 : previousStep.step.polling;
2112
2156
  this._update((draft) => {
2113
- var _a;
2114
2157
  switch (stepComponent.stackBehavior) {
2115
2158
  case "remove-previous":
2116
2159
  case "replace-current":
@@ -2125,9 +2168,9 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2125
2168
  }
2126
2169
  draft.stepStack.push(stepComponent);
2127
2170
  }
2128
- (_a = this.getStep()) == null ? void 0 : _a.start();
2129
2171
  });
2130
2172
  if (previousStep != null) {
2173
+ (_a = this.getStep()) == null ? void 0 : _a.start();
2131
2174
  scrollToTop == null ? void 0 : scrollToTop("instant");
2132
2175
  }
2133
2176
  },
@@ -2145,6 +2188,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2145
2188
  },
2146
2189
  navigateBack() {
2147
2190
  var _a;
2191
+ this.closeSubflow();
2148
2192
  if (this.stepStack.length === 1) {
2149
2193
  return;
2150
2194
  }
@@ -2169,6 +2213,24 @@ var shouldScrollOnStepUpdate = (newStep, currentStep) => {
2169
2213
  return newStep.error != null && newStep.error !== currentStep.error;
2170
2214
  };
2171
2215
 
2216
+ // src/domain/components/utils/getRandomId.ts
2217
+ var getRandomId = () => Math.random().toString(36).substring(2);
2218
+
2219
+ // src/domain/components/SubflowDomainComponent.ts
2220
+ var createSubflowDomainComponent = (subflowProps, updateComponent) => {
2221
+ const update = getInputUpdateFunction(updateComponent);
2222
+ const subflowComponent = __spreadProps(__spreadValues({
2223
+ uid: `subflow-${getRandomId()}`,
2224
+ type: "subflow",
2225
+ kind: "layout"
2226
+ }, subflowProps), {
2227
+ _update(updateFn) {
2228
+ update(this, updateFn);
2229
+ }
2230
+ });
2231
+ return subflowComponent;
2232
+ };
2233
+
2172
2234
  // src/domain/components/ModalComponent.ts
2173
2235
  var createModalContentComponent = (modalProps, updateComponent) => {
2174
2236
  const update = getInputUpdateFunction(updateComponent);
@@ -2192,9 +2254,6 @@ var createModalContentComponent = (modalProps, updateComponent) => {
2192
2254
  return modalContentComponent;
2193
2255
  };
2194
2256
 
2195
- // src/domain/components/utils/getRandomId.ts
2196
- var getRandomId = () => Math.random().toString(36).substring(2);
2197
-
2198
2257
  // src/domain/components/AlertComponent.ts
2199
2258
  var createAlertComponent = (alertProps) => __spreadValues({
2200
2259
  type: "alert",
@@ -2217,6 +2276,12 @@ var getDomainLayerBehavior = ({ action, behavior: specBehavior }, stepActions, r
2217
2276
  };
2218
2277
  var normaliseBehavior = (behavior, stepActions) => {
2219
2278
  if ("type" in behavior) {
2279
+ if (behavior.type === "subflow") {
2280
+ return __spreadProps(__spreadValues({}, behavior), {
2281
+ onCompletion: behavior.onCompletion ? normaliseBehavior(behavior.onCompletion, stepActions) : void 0,
2282
+ onError: behavior.onError ? normaliseBehavior(behavior.onError, stepActions) : void 0
2283
+ });
2284
+ }
2220
2285
  return behavior;
2221
2286
  }
2222
2287
  if ("action" in behavior && behavior.action) {
@@ -3338,6 +3403,35 @@ var modalToComponent = (uid, { content, title }, mapperProps, schemaComponents)
3338
3403
  mapperProps.updateComponent
3339
3404
  );
3340
3405
 
3406
+ // src/domain/components/step/ExternalConfirmationComponent.ts
3407
+ var createExternalConfirmation = (uid, url, updateComponent) => {
3408
+ const update = getInputUpdateFunction(updateComponent);
3409
+ return {
3410
+ type: "external-confirmation",
3411
+ kind: "layout",
3412
+ uid,
3413
+ url,
3414
+ status: "initial",
3415
+ onSuccess() {
3416
+ update(this, (draft) => {
3417
+ draft.status = "success";
3418
+ });
3419
+ },
3420
+ onFailure() {
3421
+ if (this.status === "initial") {
3422
+ update(this, (draft) => {
3423
+ draft.status = "failure";
3424
+ });
3425
+ }
3426
+ },
3427
+ onCancel() {
3428
+ update(this, (draft) => {
3429
+ draft.status = "dismissed";
3430
+ });
3431
+ }
3432
+ };
3433
+ };
3434
+
3341
3435
  // src/utils/recursiveMerge.ts
3342
3436
  function recursiveMerge(valueA, valueB) {
3343
3437
  if (valueA === null) {
@@ -3377,57 +3471,6 @@ function mergeArrays(valueA, valueB) {
3377
3471
  );
3378
3472
  }
3379
3473
 
3380
- // src/flow/makeSubmissionRequest.ts
3381
- var makeSubmissionRequest = (action, model) => {
3382
- var _a, _b;
3383
- return [
3384
- (_a = action.url) != null ? _a : "",
3385
- {
3386
- method: (_b = action.method) != null ? _b : "POST",
3387
- body: makeRequestBody(action, model),
3388
- headers: { "Content-Type": "application/json" }
3389
- }
3390
- ];
3391
- };
3392
- var makeRequestBody = (action, model) => {
3393
- var _a, _b;
3394
- const method = (_a = action.method) != null ? _a : "POST";
3395
- if (method === "GET") {
3396
- return void 0;
3397
- }
3398
- const payload = recursiveMerge(model, (_b = action.data) != null ? _b : null);
3399
- return payload !== null ? JSON.stringify(payload) : null;
3400
- };
3401
-
3402
- // src/domain/components/step/ExternalConfirmationComponent.ts
3403
- var createExternalConfirmation = (uid, url, updateComponent) => {
3404
- const update = getInputUpdateFunction(updateComponent);
3405
- return {
3406
- type: "external-confirmation",
3407
- kind: "layout",
3408
- uid,
3409
- url,
3410
- status: "initial",
3411
- onSuccess() {
3412
- update(this, (draft) => {
3413
- draft.status = "success";
3414
- });
3415
- },
3416
- onFailure() {
3417
- if (this.status === "initial") {
3418
- update(this, (draft) => {
3419
- draft.status = "failure";
3420
- });
3421
- }
3422
- },
3423
- onCancel() {
3424
- update(this, (draft) => {
3425
- draft.status = "dismissed";
3426
- });
3427
- }
3428
- };
3429
- };
3430
-
3431
3474
  // src/utils/component-utils.ts
3432
3475
  var getSubmittableData = async (components) => Promise.all(components.map(async (component) => component.getSubmittableValue())).then(
3433
3476
  (values) => values.reduce((acc, value) => recursiveMerge(acc, value), null)
@@ -3582,27 +3625,42 @@ var getStepRefreshAfter = ({
3582
3625
  };
3583
3626
 
3584
3627
  // src/domain/prefetching/request-cache.ts
3585
- var makeRequestCache = () => {
3586
- const cache = /* @__PURE__ */ new Map();
3587
- return {
3588
- has: (...requestParams) => {
3589
- return cache.has(makeKey(...requestParams));
3590
- },
3591
- get: (...requestParams) => {
3592
- return cache.get(makeKey(...requestParams));
3593
- },
3594
- delete: (...requestParams) => {
3595
- return cache.delete(makeKey(...requestParams));
3596
- },
3597
- set: (...[input, init, response]) => {
3598
- return cache.set(makeKey(input, init), response);
3628
+ var makeRequestCacheWithParent = (parent) => {
3629
+ const map = /* @__PURE__ */ new Map();
3630
+ const cache = {
3631
+ get: (requestParams) => {
3632
+ var _a;
3633
+ const key = makeKey(requestParams);
3634
+ const promise = (_a = map.get(key)) != null ? _a : parent == null ? void 0 : parent.get(requestParams);
3635
+ map.delete(key);
3636
+ return promise;
3599
3637
  },
3600
- clear: () => {
3601
- cache.clear();
3638
+ set: (requestParams, responsePromise) => {
3639
+ return map.set(makeKey(requestParams), responsePromise);
3602
3640
  }
3603
3641
  };
3642
+ return cache;
3643
+ };
3644
+ var makeRequestCache = (initialValues = []) => {
3645
+ const cache = makeRequestCacheWithParent(void 0);
3646
+ initialValues.forEach(([requestParams, responsePromise]) => {
3647
+ cache.set(requestParams, responsePromise);
3648
+ });
3649
+ return cache;
3650
+ };
3651
+ var normaliseRequestCache = (cache) => {
3652
+ if (cache === void 0) {
3653
+ return makeRequestCache();
3654
+ }
3655
+ if (isRequestCacheInstance(cache)) {
3656
+ return cache;
3657
+ }
3658
+ return makeRequestCache(cache);
3659
+ };
3660
+ var isRequestCacheInstance = (cache) => {
3661
+ return !cache || !Array.isArray(cache);
3604
3662
  };
3605
- var makeKey = (...requestParams) => {
3663
+ var makeKey = (requestParams) => {
3606
3664
  var _a, _b;
3607
3665
  const [input, init] = requestParams;
3608
3666
  const url = typeof input === "string" || input instanceof URL ? input.toString() : input.url;
@@ -4094,7 +4152,7 @@ var getInitialValidationAsyncState = () => ({
4094
4152
  });
4095
4153
 
4096
4154
  // src/flow/response-utils.ts
4097
- import { validateActionResponse } from "@wise/dynamic-flow-types/spec";
4155
+ import { validateActionResponse, validateSubflowResponse } from "@wise/dynamic-flow-types/spec";
4098
4156
  var assertResponseIsValid = (response) => {
4099
4157
  if (!isResponse(response)) {
4100
4158
  throw new Error("Incorrect type of response from fetch. Expected object of type Response.");
@@ -4140,6 +4198,13 @@ function assertModalResponseBody(body) {
4140
4198
  "Incorrect response body in modal response. Expected an object satisfying the type { title?: string, components: Layout[] }."
4141
4199
  );
4142
4200
  }
4201
+ function assertSubflowResponseBody(body) {
4202
+ const { valid } = validateSubflowResponse(body);
4203
+ if (valid) {
4204
+ return;
4205
+ }
4206
+ throw new Error("Incorrect response body in subflow response.");
4207
+ }
4143
4208
  function isErrorResponseBody(body) {
4144
4209
  return Boolean(
4145
4210
  isObject(body) && (body.refreshFormUrl || body.refreshUrl || body.validation || body.error || body.analytics)
@@ -6088,11 +6153,17 @@ var createSelectInputComponent = (selectProps, updateComponent) => {
6088
6153
  if (updatedIndex === this.selectedIndex) {
6089
6154
  return;
6090
6155
  }
6091
- if (updatedIndex !== null && this.analyticsId) {
6092
- selectProps.trackEvent("OneOf Selected", {
6093
- oneOfId: this.analyticsId,
6094
- schemaId: this.children[updatedIndex].analyticsId
6156
+ if (updatedIndex !== null) {
6157
+ selectProps.trackEvent("OneOf Option Selected", {
6158
+ schema: this.analyticsId,
6159
+ selectedOption: this.children[updatedIndex].analyticsId
6095
6160
  });
6161
+ if (this.analyticsId) {
6162
+ selectProps.trackEvent("OneOf Selected", {
6163
+ oneOfId: this.analyticsId,
6164
+ schemaId: this.children[updatedIndex].analyticsId
6165
+ });
6166
+ }
6096
6167
  }
6097
6168
  this._update((draft) => {
6098
6169
  draft.errors = [];
@@ -6829,6 +6900,227 @@ var groupLayout = (acc, layout) => {
6829
6900
  var hasChildren = (component) => "components" in component;
6830
6901
  var hasColumns = (component) => "right" in component && "left" in component;
6831
6902
 
6903
+ // src/flow/handleErrorResponse.ts
6904
+ var handleErrorResponse = async (response, actionId, trackEvent) => {
6905
+ const body = await parseResponseBodyAsJsonElement(response.clone());
6906
+ if (isErrorResponseBody(body)) {
6907
+ const refreshUrl = body.refreshUrl || body.refreshFormUrl;
6908
+ const { error, validation, analytics } = body;
6909
+ trackEvent("Action Failed", __spreadProps(__spreadValues({}, analytics), { actionId, statusCode: response.status }));
6910
+ const errors = { error, validation };
6911
+ return refreshUrl ? { type: "refresh", body: { refreshUrl, errors } } : {
6912
+ type: "error",
6913
+ body: { errors, analytics },
6914
+ httpError: { statusCode: response.status }
6915
+ };
6916
+ }
6917
+ trackEvent("Action Failed", { actionId, statusCode: response.status });
6918
+ const errorMessage = await parseResponseBodyAsText(response);
6919
+ return {
6920
+ type: "error",
6921
+ httpError: {
6922
+ message: errorMessage || void 0,
6923
+ statusCode: response.status
6924
+ }
6925
+ };
6926
+ };
6927
+
6928
+ // src/flow/getResponseType.ts
6929
+ var responseTypes = ["step", "action", "exit", "modal", "subflow"];
6930
+ var getResponseType = async (response) => {
6931
+ assertResponseIsValid(response);
6932
+ const headerResponseType = getResponseTypeFromHeader(response);
6933
+ if (headerResponseType) {
6934
+ return headerResponseType;
6935
+ }
6936
+ const jsonBody = await parseResponseBodyAsJsonElement(response.clone());
6937
+ if (isObject(jsonBody) && jsonBody.action) {
6938
+ return "action";
6939
+ }
6940
+ return "step";
6941
+ };
6942
+ var getResponseTypeFromHeader = (response) => {
6943
+ var _a, _b;
6944
+ if ((_a = response.headers) == null ? void 0 : _a.has("X-Df-Response-Type")) {
6945
+ const type = response.headers.get("X-Df-Response-Type");
6946
+ assertDFResponseType(type);
6947
+ return type;
6948
+ }
6949
+ if ((_b = response.headers) == null ? void 0 : _b.has("X-Df-Exit")) {
6950
+ return "exit";
6951
+ }
6952
+ return void 0;
6953
+ };
6954
+ function assertDFResponseType(type) {
6955
+ if (!responseTypes.includes(type)) {
6956
+ throw new Error(
6957
+ "Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'error', 'modal', 'subflow'."
6958
+ );
6959
+ }
6960
+ }
6961
+
6962
+ // src/flow/makeSafeHttpClient.ts
6963
+ var makeSafeHttpClient = (httpClient) => async (...props) => {
6964
+ try {
6965
+ return await httpClient(...props);
6966
+ } catch (e) {
6967
+ return null;
6968
+ }
6969
+ };
6970
+
6971
+ // src/flow/executeRequest.ts
6972
+ var executeRequest = async (props) => {
6973
+ const { exit, request, requestCache, httpClient, trackEvent, logEvent } = props;
6974
+ const { url, method, body } = request;
6975
+ const response = await getCachedOrFetch(
6976
+ [
6977
+ url,
6978
+ {
6979
+ method,
6980
+ body: body ? JSON.stringify(body) : void 0,
6981
+ headers: { "Content-Type": "application/json" }
6982
+ }
6983
+ ],
6984
+ requestCache,
6985
+ httpClient
6986
+ );
6987
+ if (!response) {
6988
+ const extra = { errorMessage: "Network Error" };
6989
+ trackEvent("Request Failed", extra);
6990
+ logEvent("error", "Dynamic Flow - Request Failed Unexpectedly", extra);
6991
+ return { type: "error" };
6992
+ }
6993
+ if (!response.ok) {
6994
+ return handleErrorResponse(response, void 0, trackEvent);
6995
+ }
6996
+ const responseType = await getResponseType(response);
6997
+ const responseBody = await parseResponseBodyAsJsonElement(response.clone());
6998
+ if (exit) {
6999
+ return { type: "complete", result: responseBody };
7000
+ }
7001
+ switch (responseType) {
7002
+ case "step": {
7003
+ const etag = response.headers.get("etag") || null;
7004
+ assertStepResponseBody(responseBody);
7005
+ return { type: "replace-step", step: responseBody, etag };
7006
+ }
7007
+ case "exit": {
7008
+ return { type: "complete", result: responseBody };
7009
+ }
7010
+ case "action": {
7011
+ assertActionResponseBody(responseBody);
7012
+ return {
7013
+ type: "behavior",
7014
+ behavior: {
7015
+ type: "action",
7016
+ action: responseBody.action
7017
+ }
7018
+ };
7019
+ }
7020
+ case "subflow": {
7021
+ assertSubflowResponseBody(responseBody);
7022
+ return {
7023
+ type: "behavior",
7024
+ behavior: __spreadProps(__spreadValues({}, responseBody), {
7025
+ type: "subflow",
7026
+ onCompletion: responseBody.onCompletion ? normaliseBehavior(responseBody.onCompletion, []) : void 0,
7027
+ onError: responseBody.onError ? normaliseBehavior(responseBody.onError, []) : void 0
7028
+ })
7029
+ };
7030
+ }
7031
+ case "modal": {
7032
+ assertModalResponseBody(responseBody);
7033
+ return { type: "behavior", behavior: __spreadProps(__spreadValues({}, responseBody), { type: "modal" }) };
7034
+ }
7035
+ default: {
7036
+ throw new Error(`Unsupported response type: ${String(responseType)}`);
7037
+ }
7038
+ }
7039
+ };
7040
+ var getCachedOrFetch = async (requestParams, requestCache, httpClient) => {
7041
+ const cachedPromise = requestCache.get(requestParams);
7042
+ if (cachedPromise) {
7043
+ const cachedResponse = await cachedPromise;
7044
+ if (cachedResponse == null ? void 0 : cachedResponse.ok) {
7045
+ return cachedResponse;
7046
+ }
7047
+ }
7048
+ return makeSafeHttpClient(httpClient)(...requestParams);
7049
+ };
7050
+
7051
+ // src/flow/executeSubmission.ts
7052
+ var executeSubmission = async (props) => {
7053
+ const { httpClient, requestCache, trackEvent, logEvent } = props;
7054
+ const triggerAction = async (action, model, isInitial) => {
7055
+ var _a, _b;
7056
+ const { exit, url, result = null, id: actionId } = action;
7057
+ const trackSubmissionEvent = !isInitial ? trackEvent : () => {
7058
+ };
7059
+ trackSubmissionEvent("Action Triggered", { actionId });
7060
+ if (exit && !url) {
7061
+ trackSubmissionEvent("Action Succeeded", { actionId });
7062
+ return { type: "complete", result };
7063
+ }
7064
+ try {
7065
+ const command = await executeRequest({
7066
+ exit,
7067
+ request: createRequestFromAction(action, model),
7068
+ requestCache,
7069
+ httpClient,
7070
+ trackEvent: (name, properties) => {
7071
+ trackSubmissionEvent(name, __spreadProps(__spreadValues({}, properties), { actionId }));
7072
+ },
7073
+ logEvent
7074
+ });
7075
+ switch (command.type) {
7076
+ case "error": {
7077
+ trackSubmissionEvent("Action Failed", __spreadValues({
7078
+ actionId,
7079
+ statusCode: (_a = command.httpError) == null ? void 0 : _a.statusCode
7080
+ }, (_b = command.body) == null ? void 0 : _b.analytics));
7081
+ return command;
7082
+ }
7083
+ case "behavior": {
7084
+ if (command.behavior.type === "action") {
7085
+ trackSubmissionEvent("Action Succeeded", { actionId });
7086
+ return await executeRequest({
7087
+ request: createRequestFromAction(command.behavior.action, null),
7088
+ requestCache,
7089
+ httpClient,
7090
+ trackEvent,
7091
+ logEvent
7092
+ });
7093
+ }
7094
+ trackSubmissionEvent("Action Succeeded", { actionId });
7095
+ return command;
7096
+ }
7097
+ case "complete": {
7098
+ trackSubmissionEvent("Action Succeeded", { actionId });
7099
+ return __spreadProps(__spreadValues({}, command), { result: recursiveMerge(command.result, result) });
7100
+ }
7101
+ default: {
7102
+ trackSubmissionEvent("Action Succeeded", { actionId });
7103
+ return command;
7104
+ }
7105
+ }
7106
+ } catch (error) {
7107
+ const errorMessage = getErrorMessage(error);
7108
+ trackSubmissionEvent("Action Failed", { actionId, errorMessage });
7109
+ logEvent("error", "Dynamic Flow - Action Failed Unexpectedly", { actionId, errorMessage });
7110
+ throw error;
7111
+ }
7112
+ };
7113
+ return triggerAction(props.action, props.model, props.isInitial);
7114
+ };
7115
+ var createRequestFromAction = (action, model) => {
7116
+ var _a, _b, _c;
7117
+ return __spreadProps(__spreadValues({}, action), {
7118
+ url: (_a = action.url) != null ? _a : "",
7119
+ method: (_b = action.method) != null ? _b : "POST",
7120
+ body: action.method === "GET" ? void 0 : recursiveMerge(model, (_c = action.data) != null ? _c : null)
7121
+ });
7122
+ };
7123
+
6832
7124
  // src/domain/mappers/mapStepToComponent.ts
6833
7125
  var mapStepToComponent = (_a) => {
6834
7126
  var _b = _a, {
@@ -6847,7 +7139,7 @@ var mapStepToComponent = (_a) => {
6847
7139
  "onBehavior"
6848
7140
  ]);
6849
7141
  var _a2;
6850
- const { etag, step, stepLocalValue, logEvent, updateComponent } = restProps;
7142
+ const { etag, step, stepLocalValue, flowRequestCache, logEvent, updateComponent } = restProps;
6851
7143
  const {
6852
7144
  id,
6853
7145
  control,
@@ -6862,12 +7154,15 @@ var mapStepToComponent = (_a) => {
6862
7154
  title,
6863
7155
  tags
6864
7156
  } = step;
6865
- const submissionRequestsCache = makeRequestCache();
7157
+ const requestCache = makeRequestCacheWithParent(flowRequestCache);
6866
7158
  const submissionBehaviors = [];
6867
7159
  const registerSubmissionBehavior = (behavior) => {
6868
7160
  if (behavior.type === "action" && behavior.action.prefetch) {
6869
7161
  submissionBehaviors.push(behavior);
6870
7162
  }
7163
+ if (behavior.type === "subflow" && behavior.launchConfig.type === "dynamic" && behavior.launchConfig.request.prefetch) {
7164
+ submissionBehaviors.push(behavior);
7165
+ }
6871
7166
  };
6872
7167
  const back = mapBackNavigation(navigation, onBehavior, features.isEnabled("nativeBack"));
6873
7168
  const stepId = id || key;
@@ -6928,7 +7223,7 @@ var mapStepToComponent = (_a) => {
6928
7223
  title,
6929
7224
  tags,
6930
7225
  stackBehavior: (_a2 = navigation == null ? void 0 : navigation.stackBehavior) != null ? _a2 : "default",
6931
- submissionRequestsCache,
7226
+ requestCache,
6932
7227
  step,
6933
7228
  updateComponent,
6934
7229
  trackEvent,
@@ -6938,7 +7233,7 @@ var mapStepToComponent = (_a) => {
6938
7233
  httpClient: mapperProps.httpClient,
6939
7234
  model: stepComponent.getSubmittableValueSync(),
6940
7235
  behaviors: submissionBehaviors,
6941
- requestsCache: submissionRequestsCache
7236
+ requestCache
6942
7237
  });
6943
7238
  return stepComponent;
6944
7239
  };
@@ -6961,56 +7256,25 @@ var mapBackNavigation = (navigation, onBehavior, isNativeBackEnabled) => {
6961
7256
  } : void 0;
6962
7257
  };
6963
7258
  var executePrefetch = (props) => {
6964
- const {
6965
- httpClient,
6966
- behaviors: submissionBehaviors,
6967
- model,
6968
- requestsCache: submissionRequestsCache
6969
- } = props;
7259
+ const { httpClient, behaviors: submissionBehaviors, model, requestCache } = props;
6970
7260
  submissionBehaviors.forEach((behavior) => {
6971
- const requestParams = makeSubmissionRequest(behavior.action, model);
7261
+ const request = behavior.type === "action" ? createRequestFromAction(behavior.action, model) : behavior.launchConfig.request;
7262
+ const requestParams = [
7263
+ request.url,
7264
+ {
7265
+ body: JSON.stringify(request.body),
7266
+ method: request.method,
7267
+ headers: { "Content-Type": "application/json" }
7268
+ }
7269
+ ];
6972
7270
  try {
6973
7271
  const responsePromise = httpClient(...requestParams).catch(() => null);
6974
- submissionRequestsCache.set(...requestParams, responsePromise);
7272
+ requestCache.set(requestParams, responsePromise);
6975
7273
  } catch (e) {
6976
7274
  }
6977
7275
  });
6978
7276
  };
6979
7277
 
6980
- // src/flow/getResponseType.ts
6981
- var responseTypes = ["step", "action", "exit", "modal"];
6982
- var getResponseType = async (response) => {
6983
- assertResponseIsValid(response);
6984
- const headerResponseType = getResponseTypeFromHeader(response);
6985
- if (headerResponseType) {
6986
- return headerResponseType;
6987
- }
6988
- const jsonBody = await parseResponseBodyAsJsonElement(response.clone());
6989
- if (isObject(jsonBody) && jsonBody.action) {
6990
- return "action";
6991
- }
6992
- return "step";
6993
- };
6994
- var getResponseTypeFromHeader = (response) => {
6995
- var _a, _b;
6996
- if ((_a = response.headers) == null ? void 0 : _a.has("X-Df-Response-Type")) {
6997
- const type = response.headers.get("X-Df-Response-Type");
6998
- assertDFResponseType(type);
6999
- return type;
7000
- }
7001
- if ((_b = response.headers) == null ? void 0 : _b.has("X-Df-Exit")) {
7002
- return "exit";
7003
- }
7004
- return void 0;
7005
- };
7006
- function assertDFResponseType(type) {
7007
- if (!responseTypes.includes(type)) {
7008
- throw new Error(
7009
- "Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'error', 'modal'."
7010
- );
7011
- }
7012
- }
7013
-
7014
7278
  // src/flow/executePoll.ts
7015
7279
  var executePoll = async (props) => {
7016
7280
  const { errorBehavior, signal, url, httpClient, trackEvent } = props;
@@ -7104,113 +7368,62 @@ var executeRefresh = async (props) => {
7104
7368
  }
7105
7369
  };
7106
7370
 
7107
- // src/flow/makeSafeHttpClient.ts
7108
- var makeSafeHttpClient = (httpClient) => async (...props) => {
7109
- try {
7110
- return await httpClient(...props);
7111
- } catch (e) {
7112
- return null;
7113
- }
7114
- };
7115
-
7116
- // src/flow/executeSubmission.ts
7117
- var executeSubmission = async (props) => {
7118
- const { httpClient, requestCache, trackEvent, logEvent } = props;
7119
- const triggerAction = async (action, model, isInitial) => {
7120
- const { exit, url, result = null, id: actionId } = action;
7121
- const trackSubmissionEvent = !isInitial ? trackEvent : () => {
7122
- };
7123
- trackSubmissionEvent("Action Triggered", { actionId });
7124
- if (exit && !url) {
7125
- trackSubmissionEvent("Action Succeeded", { actionId });
7126
- return { type: "complete", result };
7127
- }
7128
- const requestParams = makeSubmissionRequest(action, model);
7129
- const response = await getCachedOrFetch(requestParams, requestCache, httpClient);
7130
- if (!response) {
7131
- const extra = { actionId, errorMessage: "Network Error" };
7132
- trackEvent("Action Failed", extra);
7133
- logEvent("error", "Dynamic Flow - Action Failed Unexpectedly", extra);
7134
- return { type: "error" };
7135
- }
7136
- if (!response.ok) {
7137
- return handleErrorResponse(response, actionId);
7138
- }
7139
- try {
7140
- const responseType = await getResponseType(response);
7141
- const body = await parseResponseBodyAsJsonElement(response);
7142
- if (exit) {
7143
- return { type: "complete", result: recursiveMerge(body, result) };
7144
- }
7145
- switch (responseType) {
7146
- case "step": {
7147
- const etag = response.headers.get("etag") || null;
7148
- assertStepResponseBody(body);
7149
- trackSubmissionEvent("Action Succeeded", { actionId });
7150
- return { type: "replace-step", step: body, etag };
7151
- }
7152
- case "exit": {
7153
- trackSubmissionEvent("Action Succeeded", { actionId });
7154
- return { type: "complete", result: recursiveMerge(body, result) };
7155
- }
7156
- case "action": {
7157
- assertActionResponseBody(body);
7158
- trackSubmissionEvent("Action Succeeded", { actionId });
7159
- return await triggerAction(body.action, null, false);
7160
- }
7161
- case "modal": {
7162
- assertModalResponseBody(body);
7163
- trackSubmissionEvent("Action Succeeded", { actionId });
7164
- return { type: "behavior", behavior: __spreadProps(__spreadValues({}, body), { type: "modal" }) };
7165
- }
7166
- default: {
7167
- throw new Error(`Unsupported response type: ${String(responseType)}`);
7168
- }
7371
+ // src/getSubflowCallbacks.ts
7372
+ var getSubflowCallbacks = ({
7373
+ behavior,
7374
+ close,
7375
+ restart,
7376
+ onBehavior,
7377
+ onError,
7378
+ onEvent
7379
+ }) => {
7380
+ const {
7381
+ onCompletion: onCompletionBehavior,
7382
+ onError: onErrorBehavior,
7383
+ referrerId,
7384
+ resultKey
7385
+ } = behavior;
7386
+ return {
7387
+ onCompletion: (result) => {
7388
+ var _a;
7389
+ restart();
7390
+ if (!onCompletionBehavior) {
7391
+ close();
7392
+ return;
7169
7393
  }
7170
- } catch (error) {
7171
- const errorMessage = getErrorMessage(error);
7172
- trackSubmissionEvent("Action Failed", { actionId, errorMessage });
7173
- logEvent("error", "Dynamic Flow - Action Failed Unexpectedly", { actionId, errorMessage });
7174
- throw error;
7175
- }
7176
- };
7177
- const handleErrorResponse = async (response, actionId) => {
7178
- const body = await parseResponseBodyAsJsonElement(response.clone());
7179
- if (isErrorResponseBody(body)) {
7180
- const refreshUrl = body.refreshUrl || body.refreshFormUrl;
7181
- const { error, validation, analytics } = body;
7182
- trackEvent("Action Failed", __spreadProps(__spreadValues({}, analytics), { actionId, statusCode: response.status }));
7183
- const errors = { error, validation };
7184
- return refreshUrl ? { type: "refresh", body: { refreshUrl, errors } } : {
7185
- type: "error",
7186
- body: { errors, analytics },
7187
- httpError: { statusCode: response.status }
7188
- };
7189
- }
7190
- trackEvent("Action Failed", { actionId, statusCode: response.status });
7191
- const errorMessage = await parseResponseBodyAsText(response);
7192
- return {
7193
- type: "error",
7194
- httpError: {
7195
- message: errorMessage || void 0,
7196
- statusCode: response.status
7394
+ if (onCompletionBehavior.type === "action") {
7395
+ const newActionData = recursiveMerge(
7396
+ (_a = onCompletionBehavior.action.data) != null ? _a : null,
7397
+ resultKey ? { [resultKey]: result } : result
7398
+ );
7399
+ void onBehavior(__spreadProps(__spreadValues({}, onCompletionBehavior), {
7400
+ action: __spreadProps(__spreadValues({}, onCompletionBehavior.action), { data: newActionData })
7401
+ }));
7402
+ return;
7197
7403
  }
7198
- };
7199
- };
7200
- return triggerAction(props.action, props.model, props.isInitial);
7201
- };
7202
- var getCachedOrFetch = async (requestParams, requestCache, httpClient) => {
7203
- if (requestCache == null ? void 0 : requestCache.has(...requestParams)) {
7204
- const cachedPromise = requestCache.get(...requestParams);
7205
- requestCache.delete(...requestParams);
7206
- if (cachedPromise) {
7207
- const cachedResponse = await cachedPromise;
7208
- if (cachedResponse == null ? void 0 : cachedResponse.ok) {
7209
- return cachedResponse;
7404
+ void onBehavior(onCompletionBehavior);
7405
+ close();
7406
+ },
7407
+ onError: (error, status) => {
7408
+ if (!onErrorBehavior) {
7409
+ onError(error, {}, status);
7410
+ close();
7411
+ return;
7210
7412
  }
7413
+ restart();
7414
+ void onBehavior(onErrorBehavior);
7415
+ close();
7416
+ },
7417
+ onEvent: (name, properties) => {
7418
+ onEvent(name, __spreadValues({
7419
+ referrerId
7420
+ }, properties));
7421
+ },
7422
+ onCancellation: () => {
7423
+ restart();
7424
+ close();
7211
7425
  }
7212
- }
7213
- return makeSafeHttpClient(httpClient)(...requestParams);
7426
+ };
7214
7427
  };
7215
7428
 
7216
7429
  // src/renderers/getSchemaErrorMessageFunction.ts
@@ -7442,17 +7655,16 @@ function useStableCallback(handler) {
7442
7655
 
7443
7656
  // src/useDynamicFlowController.tsx
7444
7657
  function useDynamicFlowController(props) {
7445
- const _a = props, { flowId, initialAction, initialStep, features } = _a, rest = __objRest(_a, ["flowId", "initialAction", "initialStep", "features"]);
7658
+ const _a = props, { flowId, initialAction, initialStep, features, scrollToTop } = _a, rest = __objRest(_a, ["flowId", "initialAction", "initialStep", "features", "scrollToTop"]);
7446
7659
  const httpClient = useStableCallback(rest.httpClient);
7447
7660
  const onCancellation = useStableCallback(rest.onCancellation);
7448
7661
  const onCompletion = useStableCallback(rest.onCompletion);
7449
- const onCopy = useStableCallback(props.onCopy);
7450
- const onValueChange = useStableCallback(props.onValueChange);
7451
- const onLink = useStableCallback(props.onLink);
7662
+ const onCopy = useStableCallback(rest.onCopy);
7663
+ const onLink = useStableCallback(rest.onLink);
7452
7664
  const onError = useStableCallback(rest.onError);
7453
7665
  const onEvent = useStableCallback(rest.onEvent);
7454
7666
  const onLog = useStableCallback(rest.onLog);
7455
- const scrollToTop = useStableCallback(props.scrollToTop);
7667
+ const onValueChange = useStableCallback(rest.onValueChange);
7456
7668
  const { formatMessage, locale } = useIntl2();
7457
7669
  const getErrorMessageFunctions = useMemo(
7458
7670
  () => getSchemaErrorMessageFunction(formatMessage, locale),
@@ -7460,10 +7672,15 @@ function useDynamicFlowController(props) {
7460
7672
  );
7461
7673
  const rerender = useRerender();
7462
7674
  const rootComponentRef = useRef2(
7463
- createRootDomainComponent(rerender, scrollToTop, {
7464
- isNativeBackEnabled: features.isEnabled("nativeBack"),
7465
- isFlowCancellable: Boolean(rest.onCancellation)
7466
- })
7675
+ createRootDomainComponent(
7676
+ rerender,
7677
+ scrollToTop,
7678
+ {
7679
+ isNativeBackEnabled: features.isEnabled("nativeBack"),
7680
+ isFlowCancellable: Boolean(rest.onCancellation)
7681
+ },
7682
+ normaliseRequestCache(rest.requestCache)
7683
+ )
7467
7684
  );
7468
7685
  const stepCount = useRef2(0);
7469
7686
  const abortControllerRef = useRef2(new AbortController());
@@ -7472,12 +7689,15 @@ function useDynamicFlowController(props) {
7472
7689
  abortControllerRef.current = new AbortController();
7473
7690
  return abortControllerRef.current.signal;
7474
7691
  };
7692
+ const hasTriggeredInitialAction = useRef2(false);
7475
7693
  useEffect(() => {
7476
7694
  trackCoreEvent("Initiated");
7477
- if (!initialStep && initialAction) {
7695
+ if (!hasTriggeredInitialAction.current && !initialStep && initialAction) {
7478
7696
  rootComponentRef.current.setLoadingState("submitting");
7697
+ hasTriggeredInitialAction.current = true;
7479
7698
  void onAction(__spreadValues({ method: "GET" }, initialAction), null);
7480
7699
  }
7700
+ rootComponentRef.current.start();
7481
7701
  return () => {
7482
7702
  rootComponentRef.current.stop();
7483
7703
  };
@@ -7490,6 +7710,7 @@ function useDynamicFlowController(props) {
7490
7710
  const component = createStepComponent2(newStep, etag, null);
7491
7711
  if (component) {
7492
7712
  rootComponentRef.current.pushStep(component);
7713
+ rootComponentRef.current.setLoadingState("idle");
7493
7714
  }
7494
7715
  },
7495
7716
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -7504,12 +7725,14 @@ function useDynamicFlowController(props) {
7504
7725
  );
7505
7726
  if (component) {
7506
7727
  rootComponentRef.current.updateStep(component);
7728
+ rootComponentRef.current.setLoadingState("idle");
7507
7729
  }
7508
7730
  }, []);
7509
7731
  const getMapperProps = () => ({
7510
7732
  uid: `${rootComponentRef.current.uid}:${stepCount.current}`,
7511
7733
  loadingState: "idle",
7512
7734
  updateComponent: () => rerender(),
7735
+ flowRequestCache: rootComponentRef.current.requestCache,
7513
7736
  getErrorMessageFunctions,
7514
7737
  trackEvent,
7515
7738
  logEvent,
@@ -7548,7 +7771,8 @@ function useDynamicFlowController(props) {
7548
7771
  const stepId = (_b = (_a2 = step == null ? void 0 : step.id) != null ? _a2 : step == null ? void 0 : step.key) != null ? _b : null;
7549
7772
  const analytics = step == null ? void 0 : step.analytics;
7550
7773
  const metadata = __spreadValues(__spreadValues(__spreadValues(__spreadValues({
7551
- flowId
7774
+ flowId,
7775
+ integrationId: flowId
7552
7776
  }, step ? { stepCount: stepCount.current } : {}), stepId !== null ? { stepId } : {}), analytics), properties);
7553
7777
  try {
7554
7778
  onEvent == null ? void 0 : onEvent(`Dynamic Flow - ${eventName}`, __spreadValues({}, metadata));
@@ -7589,7 +7813,7 @@ function useDynamicFlowController(props) {
7589
7813
  onCancellation();
7590
7814
  }, []);
7591
7815
  const onBehavior = useCallback2(async (behavior) => {
7592
- var _a2;
7816
+ var _a2, _b, _c;
7593
7817
  switch (behavior.type) {
7594
7818
  case "back": {
7595
7819
  if (behavior.action) {
@@ -7680,6 +7904,33 @@ function useDynamicFlowController(props) {
7680
7904
  case "dismiss":
7681
7905
  rootComponentRef.current.dismissModal();
7682
7906
  break;
7907
+ case "subflow": {
7908
+ rootComponentRef.current.setLoadingState("submitting");
7909
+ const { launchConfig } = behavior;
7910
+ const { request, presentation } = launchConfig;
7911
+ const callbacks = getSubflowCallbacks({
7912
+ behavior,
7913
+ close: () => rootComponentRef.current.closeSubflow(),
7914
+ onBehavior,
7915
+ onError: closeWithError,
7916
+ onEvent,
7917
+ restart: () => {
7918
+ rootComponentRef.current.setLoadingState("idle");
7919
+ rootComponentRef.current.start();
7920
+ }
7921
+ });
7922
+ const component = createSubflowDomainComponent(
7923
+ __spreadProps(__spreadValues({}, callbacks), {
7924
+ initialRequest: request,
7925
+ requestCache: (_c = (_b = rootComponentRef.current.getStep()) == null ? void 0 : _b.requestCache) != null ? _c : rootComponentRef.current.requestCache,
7926
+ presentation
7927
+ }),
7928
+ rerender
7929
+ );
7930
+ rootComponentRef.current.stop();
7931
+ rootComponentRef.current.addSubflow(component);
7932
+ break;
7933
+ }
7683
7934
  case "none":
7684
7935
  break;
7685
7936
  }
@@ -7688,16 +7939,16 @@ function useDynamicFlowController(props) {
7688
7939
  }, []);
7689
7940
  const onAction = useCallback2(
7690
7941
  async (action, model) => {
7691
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
7942
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
7692
7943
  try {
7693
7944
  rootComponentRef.current.setLoadingState("submitting");
7694
7945
  const command = await executeSubmission({
7695
7946
  action,
7696
7947
  model,
7697
7948
  isInitial: !rootComponentRef.current.hasStep(),
7698
- requestCache: (_a2 = rootComponentRef.current.getStep()) == null ? void 0 : _a2.submissionRequestsCache,
7949
+ requestCache: (_b = (_a2 = rootComponentRef.current.getStep()) == null ? void 0 : _a2.requestCache) != null ? _b : rootComponentRef.current.requestCache,
7699
7950
  httpClient,
7700
- trackEvent: trackCoreEvent,
7951
+ trackEvent,
7701
7952
  logEvent
7702
7953
  });
7703
7954
  switch (command.type) {
@@ -7709,6 +7960,7 @@ function useDynamicFlowController(props) {
7709
7960
  }
7710
7961
  case "replace-step": {
7711
7962
  const isFirstStep = !rootComponentRef.current.hasStep();
7963
+ rootComponentRef.current.closeSubflow();
7712
7964
  createStep(command.step, command.etag);
7713
7965
  trackCoreEvent("Step Shown", { isFirstStep });
7714
7966
  break;
@@ -7716,7 +7968,7 @@ function useDynamicFlowController(props) {
7716
7968
  case "error": {
7717
7969
  rootComponentRef.current.setLoadingState("idle");
7718
7970
  const genericErrorMessage = getErrorMessageFunctions().genericErrorWithRetry();
7719
- const errors = (_c = (_b = command.body) == null ? void 0 : _b.errors) != null ? _c : { error: genericErrorMessage };
7971
+ const errors = (_d = (_c = command.body) == null ? void 0 : _c.errors) != null ? _d : { error: genericErrorMessage };
7720
7972
  const currentStep = rootComponentRef.current.getStep();
7721
7973
  if (currentStep) {
7722
7974
  updateStep(
@@ -7730,16 +7982,16 @@ function useDynamicFlowController(props) {
7730
7982
  external: void 0
7731
7983
  // and no external, to avoid retriggering it
7732
7984
  }),
7733
- (_e = (_d = rootComponentRef.current.getStep()) == null ? void 0 : _d.etag) != null ? _e : null
7985
+ (_f = (_e = rootComponentRef.current.getStep()) == null ? void 0 : _e.etag) != null ? _f : null
7734
7986
  );
7735
7987
  } else {
7736
- const errorMessage = ((_g = (_f = command.body) == null ? void 0 : _f.errors) == null ? void 0 : _g.error) || ((_h = command.httpError) == null ? void 0 : _h.message) || "Initial request failed";
7988
+ const errorMessage = ((_h = (_g = command.body) == null ? void 0 : _g.errors) == null ? void 0 : _h.error) || ((_i = command.httpError) == null ? void 0 : _i.message) || "Initial request failed";
7737
7989
  closeWithError(
7738
7990
  new Error(errorMessage, {
7739
7991
  cause: `method: ${action.method}, url: ${action.url}`
7740
7992
  }),
7741
7993
  {},
7742
- (_i = command.httpError) == null ? void 0 : _i.statusCode
7994
+ (_j = command.httpError) == null ? void 0 : _j.statusCode
7743
7995
  );
7744
7996
  }
7745
7997
  break;
@@ -7835,7 +8087,7 @@ function useDynamicFlowController(props) {
7835
8087
  []
7836
8088
  );
7837
8089
  const hasMappedInitialStep = useRef2(false);
7838
- if (!hasMappedInitialStep.current && initialStep && !initialAction) {
8090
+ if (!hasMappedInitialStep.current && initialStep) {
7839
8091
  createStep(initialStep, null);
7840
8092
  trackCoreEvent("Step Shown", { isFirstStep: true });
7841
8093
  hasMappedInitialStep.current = true;
@@ -7920,15 +8172,89 @@ function useDynamicFlow(props) {
7920
8172
  };
7921
8173
  }
7922
8174
 
8175
+ // src/useDynamicFlowModal.tsx
8176
+ import { useState as useState2 } from "react";
8177
+ var useDynamicFlowModal = (props) => {
8178
+ const _a = props, { renderers, onCompletion, onError, onCancellation, onEvent, onLink } = _a, rest = __objRest(_a, ["renderers", "onCompletion", "onError", "onCancellation", "onEvent", "onLink"]);
8179
+ const [state, setState] = useState2({ type: "initial" });
8180
+ const df = useDynamicFlow(__spreadProps(__spreadValues({}, rest), {
8181
+ onCompletion: (result) => {
8182
+ setState({ type: "completed", result });
8183
+ },
8184
+ onError: (error, status) => {
8185
+ setState({ type: "error", error, status });
8186
+ },
8187
+ onEvent: (name, properties) => {
8188
+ if (name === "Dynamic Flow - Step Shown") {
8189
+ setState({ type: "in-progress" });
8190
+ }
8191
+ onEvent == null ? void 0 : onEvent(name, properties);
8192
+ },
8193
+ renderers,
8194
+ onLink: onLink != null ? onLink : (() => true)
8195
+ }));
8196
+ const onUnmount = () => {
8197
+ switch (state.type) {
8198
+ case "completed":
8199
+ onCompletion(state.result);
8200
+ break;
8201
+ case "error":
8202
+ onError(state.error, state.status);
8203
+ break;
8204
+ case "initial":
8205
+ case "in-progress":
8206
+ case "cancelled": {
8207
+ df.controller.cancel();
8208
+ onCancellation == null ? void 0 : onCancellation();
8209
+ }
8210
+ }
8211
+ };
8212
+ const onClose = () => {
8213
+ setState({ type: "cancelled" });
8214
+ };
8215
+ return __spreadProps(__spreadValues({}, df), {
8216
+ modal: { body: df.view, open: state.type === "in-progress", onClose, onUnmount }
8217
+ });
8218
+ };
8219
+
7923
8220
  // src/DynamicFlowCore.tsx
7924
8221
  function DynamicFlowCore(props) {
7925
8222
  const df = useDynamicFlow(props);
7926
8223
  return df.view;
7927
8224
  }
8225
+
8226
+ // src/domain/features/eventNames.ts
8227
+ var eventNames = [
8228
+ "Initiated",
8229
+ "Succeeded",
8230
+ "Failed",
8231
+ "Cancelled",
8232
+ "Step Shown",
8233
+ "Action Triggered",
8234
+ "Action Succeeded",
8235
+ "Action Aborted",
8236
+ "Action Failed",
8237
+ "Refresh Triggered",
8238
+ "Refresh Succeeded",
8239
+ "Refresh Aborted",
8240
+ "Refresh Failed",
8241
+ "OneOf Selected",
8242
+ "OneOf Option Selected",
8243
+ "PersistAsync Triggered",
8244
+ "PersistAsync Succeeded",
8245
+ "PersistAsync Failed",
8246
+ "Polling Failed",
8247
+ "ValidationAsync Triggered",
8248
+ "ValidationAsync Succeeded",
8249
+ "ValidationAsync Failed"
8250
+ ];
7928
8251
  export {
7929
8252
  DynamicFlowCore as DynamicFlow,
8253
+ eventNames,
7930
8254
  findRendererPropsByType,
7931
8255
  makeHttpClient,
8256
+ makeRequestCache,
7932
8257
  i18n_default as translations,
7933
- useDynamicFlow
8258
+ useDynamicFlow,
8259
+ useDynamicFlowModal
7934
8260
  };