@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.js CHANGED
@@ -57,10 +57,13 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
57
57
  var index_exports = {};
58
58
  __export(index_exports, {
59
59
  DynamicFlow: () => DynamicFlowCore,
60
+ eventNames: () => eventNames,
60
61
  findRendererPropsByType: () => findRendererPropsByType,
61
62
  makeHttpClient: () => makeHttpClient,
63
+ makeRequestCache: () => makeRequestCache,
62
64
  translations: () => i18n_default,
63
- useDynamicFlow: () => useDynamicFlow
65
+ useDynamicFlow: () => useDynamicFlow,
66
+ useDynamicFlowModal: () => useDynamicFlowModal
64
67
  });
65
68
  module.exports = __toCommonJS(index_exports);
66
69
 
@@ -850,6 +853,7 @@ var getChildren = (node) => {
850
853
  case "input-text":
851
854
  case "input-upload":
852
855
  case "external-confirmation":
856
+ case "subflow":
853
857
  return [];
854
858
  }
855
859
  };
@@ -962,9 +966,15 @@ var CoreContainerRenderer = {
962
966
  var import_jsx_runtime4 = require("react/jsx-runtime");
963
967
  var CoreRootRenderer = {
964
968
  canRenderType: "root",
965
- render: ({ children, childrenProps }) => {
969
+ render: ({ children, childrenProps, subflow }) => {
970
+ if ((subflow == null ? void 0 : subflow.presentation.type) === "push") {
971
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: subflow.children });
972
+ }
966
973
  const [stepProps] = findRendererPropsByType(childrenProps, "step");
967
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { id: stepProps == null ? void 0 : stepProps.id, className: "dynamic-flow-step", children });
974
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { id: stepProps == null ? void 0 : stepProps.id, className: "dynamic-flow-step", children: [
975
+ children,
976
+ (subflow == null ? void 0 : subflow.presentation.type) === "modal" ? subflow.children : void 0
977
+ ] });
968
978
  }
969
979
  };
970
980
 
@@ -1712,11 +1722,18 @@ var rootComponentToProps = (rootComponent, rendererMapperProps) => {
1712
1722
  }
1713
1723
  return componentToRendererProps(child, rendererMapperProps);
1714
1724
  });
1725
+ const subflow = rootComponent.subflow ? {
1726
+ presentation: rootComponent.subflow.presentation,
1727
+ children: rendererMapperProps.render(
1728
+ componentToRendererProps(rootComponent.subflow, rendererMapperProps)
1729
+ )
1730
+ } : void 0;
1715
1731
  return __spreadValues({
1716
1732
  type: "root",
1717
1733
  uid: rootComponent.uid,
1718
1734
  children: childrenProps.map(rendererMapperProps.render),
1719
- childrenProps
1735
+ childrenProps,
1736
+ subflow
1720
1737
  }, rendererMapperProps);
1721
1738
  };
1722
1739
 
@@ -1907,6 +1924,19 @@ var uploadInputComponentToProps = (component, rendererMapperProps) => {
1907
1924
  });
1908
1925
  };
1909
1926
 
1927
+ // src/renderers/mappers/subflowComponentToRendererProps.ts
1928
+ var subflowComponentToRendererProps = (component, rendererMapperProps) => {
1929
+ return __spreadValues(__spreadProps(__spreadValues({
1930
+ uid: "subflow",
1931
+ type: "subflow"
1932
+ }, pick(component, "requestCache", "presentation", "initialRequest")), {
1933
+ onCancellation: component.onCancellation.bind(component),
1934
+ onCompletion: component.onCompletion.bind(component),
1935
+ onError: component.onError.bind(component),
1936
+ onEvent: component.onEvent.bind(component)
1937
+ }), rendererMapperProps);
1938
+ };
1939
+
1910
1940
  // src/renderers/mappers/componentToRendererProps.ts
1911
1941
  var componentToRendererProps = (component, mapperProps) => {
1912
1942
  if (isHiddenComponent(component)) {
@@ -2005,6 +2035,8 @@ var getComponentProps = (component, rendererMapperProps) => {
2005
2035
  return selectInputComponentToProps(component, rendererMapperProps);
2006
2036
  case "status-list":
2007
2037
  return statusListComponentToProps(component, rendererMapperProps);
2038
+ case "subflow":
2039
+ return subflowComponentToRendererProps(component, rendererMapperProps);
2008
2040
  case "tabs":
2009
2041
  return tabsComponentToProps(component, rendererMapperProps);
2010
2042
  case "text":
@@ -2042,15 +2074,17 @@ var getInputUpdateFunction = (updateComponent) => {
2042
2074
  };
2043
2075
 
2044
2076
  // src/domain/components/RootDomainComponent.ts
2045
- var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2077
+ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig, requestCache) => {
2046
2078
  const update = getInputUpdateFunction(updateComponent);
2047
2079
  const rootComponent = {
2048
2080
  type: "root",
2049
2081
  kind: "step",
2050
2082
  uid: "root",
2051
2083
  stepComponent: null,
2084
+ subflow: null,
2052
2085
  stepStack: [],
2053
2086
  backConfig,
2087
+ requestCache,
2054
2088
  _update(updateFn) {
2055
2089
  update(this, updateFn);
2056
2090
  },
@@ -2113,6 +2147,16 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2113
2147
  var _a;
2114
2148
  return (_a = this.stepStack[this.stepStack.length - 1]) != null ? _a : null;
2115
2149
  },
2150
+ addSubflow(subflow) {
2151
+ this._update((draft) => {
2152
+ draft.subflow = subflow;
2153
+ });
2154
+ },
2155
+ closeSubflow() {
2156
+ this._update((draft) => {
2157
+ draft.subflow = null;
2158
+ });
2159
+ },
2116
2160
  start() {
2117
2161
  var _a;
2118
2162
  (_a = this.getStep()) == null ? void 0 : _a.start();
@@ -2123,6 +2167,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2123
2167
  },
2124
2168
  updateStep(stepComponent) {
2125
2169
  var _a;
2170
+ this.closeSubflow();
2126
2171
  const shouldScroll = shouldScrollOnStepUpdate(stepComponent, this.getStep());
2127
2172
  this._update((draft) => {
2128
2173
  draft.stepStack = draft.stepStack.slice(0, -1);
@@ -2134,10 +2179,11 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2134
2179
  (_a = this.getStep()) == null ? void 0 : _a.start();
2135
2180
  },
2136
2181
  pushStep(stepComponent) {
2182
+ var _a;
2183
+ this.closeSubflow();
2137
2184
  const previousStep = this.getStep();
2138
2185
  const previousStepHasPolling = previousStep == null ? void 0 : previousStep.step.polling;
2139
2186
  this._update((draft) => {
2140
- var _a;
2141
2187
  switch (stepComponent.stackBehavior) {
2142
2188
  case "remove-previous":
2143
2189
  case "replace-current":
@@ -2152,9 +2198,9 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2152
2198
  }
2153
2199
  draft.stepStack.push(stepComponent);
2154
2200
  }
2155
- (_a = this.getStep()) == null ? void 0 : _a.start();
2156
2201
  });
2157
2202
  if (previousStep != null) {
2203
+ (_a = this.getStep()) == null ? void 0 : _a.start();
2158
2204
  scrollToTop == null ? void 0 : scrollToTop("instant");
2159
2205
  }
2160
2206
  },
@@ -2172,6 +2218,7 @@ var createRootDomainComponent = (updateComponent, scrollToTop, backConfig) => {
2172
2218
  },
2173
2219
  navigateBack() {
2174
2220
  var _a;
2221
+ this.closeSubflow();
2175
2222
  if (this.stepStack.length === 1) {
2176
2223
  return;
2177
2224
  }
@@ -2196,6 +2243,24 @@ var shouldScrollOnStepUpdate = (newStep, currentStep) => {
2196
2243
  return newStep.error != null && newStep.error !== currentStep.error;
2197
2244
  };
2198
2245
 
2246
+ // src/domain/components/utils/getRandomId.ts
2247
+ var getRandomId = () => Math.random().toString(36).substring(2);
2248
+
2249
+ // src/domain/components/SubflowDomainComponent.ts
2250
+ var createSubflowDomainComponent = (subflowProps, updateComponent) => {
2251
+ const update = getInputUpdateFunction(updateComponent);
2252
+ const subflowComponent = __spreadProps(__spreadValues({
2253
+ uid: `subflow-${getRandomId()}`,
2254
+ type: "subflow",
2255
+ kind: "layout"
2256
+ }, subflowProps), {
2257
+ _update(updateFn) {
2258
+ update(this, updateFn);
2259
+ }
2260
+ });
2261
+ return subflowComponent;
2262
+ };
2263
+
2199
2264
  // src/domain/components/ModalComponent.ts
2200
2265
  var createModalContentComponent = (modalProps, updateComponent) => {
2201
2266
  const update = getInputUpdateFunction(updateComponent);
@@ -2219,9 +2284,6 @@ var createModalContentComponent = (modalProps, updateComponent) => {
2219
2284
  return modalContentComponent;
2220
2285
  };
2221
2286
 
2222
- // src/domain/components/utils/getRandomId.ts
2223
- var getRandomId = () => Math.random().toString(36).substring(2);
2224
-
2225
2287
  // src/domain/components/AlertComponent.ts
2226
2288
  var createAlertComponent = (alertProps) => __spreadValues({
2227
2289
  type: "alert",
@@ -2244,6 +2306,12 @@ var getDomainLayerBehavior = ({ action, behavior: specBehavior }, stepActions, r
2244
2306
  };
2245
2307
  var normaliseBehavior = (behavior, stepActions) => {
2246
2308
  if ("type" in behavior) {
2309
+ if (behavior.type === "subflow") {
2310
+ return __spreadProps(__spreadValues({}, behavior), {
2311
+ onCompletion: behavior.onCompletion ? normaliseBehavior(behavior.onCompletion, stepActions) : void 0,
2312
+ onError: behavior.onError ? normaliseBehavior(behavior.onError, stepActions) : void 0
2313
+ });
2314
+ }
2247
2315
  return behavior;
2248
2316
  }
2249
2317
  if ("action" in behavior && behavior.action) {
@@ -3365,6 +3433,35 @@ var modalToComponent = (uid, { content, title }, mapperProps, schemaComponents)
3365
3433
  mapperProps.updateComponent
3366
3434
  );
3367
3435
 
3436
+ // src/domain/components/step/ExternalConfirmationComponent.ts
3437
+ var createExternalConfirmation = (uid, url, updateComponent) => {
3438
+ const update = getInputUpdateFunction(updateComponent);
3439
+ return {
3440
+ type: "external-confirmation",
3441
+ kind: "layout",
3442
+ uid,
3443
+ url,
3444
+ status: "initial",
3445
+ onSuccess() {
3446
+ update(this, (draft) => {
3447
+ draft.status = "success";
3448
+ });
3449
+ },
3450
+ onFailure() {
3451
+ if (this.status === "initial") {
3452
+ update(this, (draft) => {
3453
+ draft.status = "failure";
3454
+ });
3455
+ }
3456
+ },
3457
+ onCancel() {
3458
+ update(this, (draft) => {
3459
+ draft.status = "dismissed";
3460
+ });
3461
+ }
3462
+ };
3463
+ };
3464
+
3368
3465
  // src/utils/recursiveMerge.ts
3369
3466
  function recursiveMerge(valueA, valueB) {
3370
3467
  if (valueA === null) {
@@ -3404,57 +3501,6 @@ function mergeArrays(valueA, valueB) {
3404
3501
  );
3405
3502
  }
3406
3503
 
3407
- // src/flow/makeSubmissionRequest.ts
3408
- var makeSubmissionRequest = (action, model) => {
3409
- var _a, _b;
3410
- return [
3411
- (_a = action.url) != null ? _a : "",
3412
- {
3413
- method: (_b = action.method) != null ? _b : "POST",
3414
- body: makeRequestBody(action, model),
3415
- headers: { "Content-Type": "application/json" }
3416
- }
3417
- ];
3418
- };
3419
- var makeRequestBody = (action, model) => {
3420
- var _a, _b;
3421
- const method = (_a = action.method) != null ? _a : "POST";
3422
- if (method === "GET") {
3423
- return void 0;
3424
- }
3425
- const payload = recursiveMerge(model, (_b = action.data) != null ? _b : null);
3426
- return payload !== null ? JSON.stringify(payload) : null;
3427
- };
3428
-
3429
- // src/domain/components/step/ExternalConfirmationComponent.ts
3430
- var createExternalConfirmation = (uid, url, updateComponent) => {
3431
- const update = getInputUpdateFunction(updateComponent);
3432
- return {
3433
- type: "external-confirmation",
3434
- kind: "layout",
3435
- uid,
3436
- url,
3437
- status: "initial",
3438
- onSuccess() {
3439
- update(this, (draft) => {
3440
- draft.status = "success";
3441
- });
3442
- },
3443
- onFailure() {
3444
- if (this.status === "initial") {
3445
- update(this, (draft) => {
3446
- draft.status = "failure";
3447
- });
3448
- }
3449
- },
3450
- onCancel() {
3451
- update(this, (draft) => {
3452
- draft.status = "dismissed";
3453
- });
3454
- }
3455
- };
3456
- };
3457
-
3458
3504
  // src/utils/component-utils.ts
3459
3505
  var getSubmittableData = async (components) => Promise.all(components.map(async (component) => component.getSubmittableValue())).then(
3460
3506
  (values) => values.reduce((acc, value) => recursiveMerge(acc, value), null)
@@ -3609,27 +3655,42 @@ var getStepRefreshAfter = ({
3609
3655
  };
3610
3656
 
3611
3657
  // src/domain/prefetching/request-cache.ts
3612
- var makeRequestCache = () => {
3613
- const cache = /* @__PURE__ */ new Map();
3614
- return {
3615
- has: (...requestParams) => {
3616
- return cache.has(makeKey(...requestParams));
3617
- },
3618
- get: (...requestParams) => {
3619
- return cache.get(makeKey(...requestParams));
3620
- },
3621
- delete: (...requestParams) => {
3622
- return cache.delete(makeKey(...requestParams));
3623
- },
3624
- set: (...[input, init, response]) => {
3625
- return cache.set(makeKey(input, init), response);
3658
+ var makeRequestCacheWithParent = (parent) => {
3659
+ const map = /* @__PURE__ */ new Map();
3660
+ const cache = {
3661
+ get: (requestParams) => {
3662
+ var _a;
3663
+ const key = makeKey(requestParams);
3664
+ const promise = (_a = map.get(key)) != null ? _a : parent == null ? void 0 : parent.get(requestParams);
3665
+ map.delete(key);
3666
+ return promise;
3626
3667
  },
3627
- clear: () => {
3628
- cache.clear();
3668
+ set: (requestParams, responsePromise) => {
3669
+ return map.set(makeKey(requestParams), responsePromise);
3629
3670
  }
3630
3671
  };
3672
+ return cache;
3673
+ };
3674
+ var makeRequestCache = (initialValues = []) => {
3675
+ const cache = makeRequestCacheWithParent(void 0);
3676
+ initialValues.forEach(([requestParams, responsePromise]) => {
3677
+ cache.set(requestParams, responsePromise);
3678
+ });
3679
+ return cache;
3680
+ };
3681
+ var normaliseRequestCache = (cache) => {
3682
+ if (cache === void 0) {
3683
+ return makeRequestCache();
3684
+ }
3685
+ if (isRequestCacheInstance(cache)) {
3686
+ return cache;
3687
+ }
3688
+ return makeRequestCache(cache);
3689
+ };
3690
+ var isRequestCacheInstance = (cache) => {
3691
+ return !cache || !Array.isArray(cache);
3631
3692
  };
3632
- var makeKey = (...requestParams) => {
3693
+ var makeKey = (requestParams) => {
3633
3694
  var _a, _b;
3634
3695
  const [input, init] = requestParams;
3635
3696
  const url = typeof input === "string" || input instanceof URL ? input.toString() : input.url;
@@ -4167,6 +4228,13 @@ function assertModalResponseBody(body) {
4167
4228
  "Incorrect response body in modal response. Expected an object satisfying the type { title?: string, components: Layout[] }."
4168
4229
  );
4169
4230
  }
4231
+ function assertSubflowResponseBody(body) {
4232
+ const { valid } = (0, import_spec.validateSubflowResponse)(body);
4233
+ if (valid) {
4234
+ return;
4235
+ }
4236
+ throw new Error("Incorrect response body in subflow response.");
4237
+ }
4170
4238
  function isErrorResponseBody(body) {
4171
4239
  return Boolean(
4172
4240
  isObject(body) && (body.refreshFormUrl || body.refreshUrl || body.validation || body.error || body.analytics)
@@ -6115,11 +6183,17 @@ var createSelectInputComponent = (selectProps, updateComponent) => {
6115
6183
  if (updatedIndex === this.selectedIndex) {
6116
6184
  return;
6117
6185
  }
6118
- if (updatedIndex !== null && this.analyticsId) {
6119
- selectProps.trackEvent("OneOf Selected", {
6120
- oneOfId: this.analyticsId,
6121
- schemaId: this.children[updatedIndex].analyticsId
6186
+ if (updatedIndex !== null) {
6187
+ selectProps.trackEvent("OneOf Option Selected", {
6188
+ schema: this.analyticsId,
6189
+ selectedOption: this.children[updatedIndex].analyticsId
6122
6190
  });
6191
+ if (this.analyticsId) {
6192
+ selectProps.trackEvent("OneOf Selected", {
6193
+ oneOfId: this.analyticsId,
6194
+ schemaId: this.children[updatedIndex].analyticsId
6195
+ });
6196
+ }
6123
6197
  }
6124
6198
  this._update((draft) => {
6125
6199
  draft.errors = [];
@@ -6856,6 +6930,227 @@ var groupLayout = (acc, layout) => {
6856
6930
  var hasChildren = (component) => "components" in component;
6857
6931
  var hasColumns = (component) => "right" in component && "left" in component;
6858
6932
 
6933
+ // src/flow/handleErrorResponse.ts
6934
+ var handleErrorResponse = async (response, actionId, trackEvent) => {
6935
+ const body = await parseResponseBodyAsJsonElement(response.clone());
6936
+ if (isErrorResponseBody(body)) {
6937
+ const refreshUrl = body.refreshUrl || body.refreshFormUrl;
6938
+ const { error, validation, analytics } = body;
6939
+ trackEvent("Action Failed", __spreadProps(__spreadValues({}, analytics), { actionId, statusCode: response.status }));
6940
+ const errors = { error, validation };
6941
+ return refreshUrl ? { type: "refresh", body: { refreshUrl, errors } } : {
6942
+ type: "error",
6943
+ body: { errors, analytics },
6944
+ httpError: { statusCode: response.status }
6945
+ };
6946
+ }
6947
+ trackEvent("Action Failed", { actionId, statusCode: response.status });
6948
+ const errorMessage = await parseResponseBodyAsText(response);
6949
+ return {
6950
+ type: "error",
6951
+ httpError: {
6952
+ message: errorMessage || void 0,
6953
+ statusCode: response.status
6954
+ }
6955
+ };
6956
+ };
6957
+
6958
+ // src/flow/getResponseType.ts
6959
+ var responseTypes = ["step", "action", "exit", "modal", "subflow"];
6960
+ var getResponseType = async (response) => {
6961
+ assertResponseIsValid(response);
6962
+ const headerResponseType = getResponseTypeFromHeader(response);
6963
+ if (headerResponseType) {
6964
+ return headerResponseType;
6965
+ }
6966
+ const jsonBody = await parseResponseBodyAsJsonElement(response.clone());
6967
+ if (isObject(jsonBody) && jsonBody.action) {
6968
+ return "action";
6969
+ }
6970
+ return "step";
6971
+ };
6972
+ var getResponseTypeFromHeader = (response) => {
6973
+ var _a, _b;
6974
+ if ((_a = response.headers) == null ? void 0 : _a.has("X-Df-Response-Type")) {
6975
+ const type = response.headers.get("X-Df-Response-Type");
6976
+ assertDFResponseType(type);
6977
+ return type;
6978
+ }
6979
+ if ((_b = response.headers) == null ? void 0 : _b.has("X-Df-Exit")) {
6980
+ return "exit";
6981
+ }
6982
+ return void 0;
6983
+ };
6984
+ function assertDFResponseType(type) {
6985
+ if (!responseTypes.includes(type)) {
6986
+ throw new Error(
6987
+ "Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'error', 'modal', 'subflow'."
6988
+ );
6989
+ }
6990
+ }
6991
+
6992
+ // src/flow/makeSafeHttpClient.ts
6993
+ var makeSafeHttpClient = (httpClient) => async (...props) => {
6994
+ try {
6995
+ return await httpClient(...props);
6996
+ } catch (e) {
6997
+ return null;
6998
+ }
6999
+ };
7000
+
7001
+ // src/flow/executeRequest.ts
7002
+ var executeRequest = async (props) => {
7003
+ const { exit, request, requestCache, httpClient, trackEvent, logEvent } = props;
7004
+ const { url, method, body } = request;
7005
+ const response = await getCachedOrFetch(
7006
+ [
7007
+ url,
7008
+ {
7009
+ method,
7010
+ body: body ? JSON.stringify(body) : void 0,
7011
+ headers: { "Content-Type": "application/json" }
7012
+ }
7013
+ ],
7014
+ requestCache,
7015
+ httpClient
7016
+ );
7017
+ if (!response) {
7018
+ const extra = { errorMessage: "Network Error" };
7019
+ trackEvent("Request Failed", extra);
7020
+ logEvent("error", "Dynamic Flow - Request Failed Unexpectedly", extra);
7021
+ return { type: "error" };
7022
+ }
7023
+ if (!response.ok) {
7024
+ return handleErrorResponse(response, void 0, trackEvent);
7025
+ }
7026
+ const responseType = await getResponseType(response);
7027
+ const responseBody = await parseResponseBodyAsJsonElement(response.clone());
7028
+ if (exit) {
7029
+ return { type: "complete", result: responseBody };
7030
+ }
7031
+ switch (responseType) {
7032
+ case "step": {
7033
+ const etag = response.headers.get("etag") || null;
7034
+ assertStepResponseBody(responseBody);
7035
+ return { type: "replace-step", step: responseBody, etag };
7036
+ }
7037
+ case "exit": {
7038
+ return { type: "complete", result: responseBody };
7039
+ }
7040
+ case "action": {
7041
+ assertActionResponseBody(responseBody);
7042
+ return {
7043
+ type: "behavior",
7044
+ behavior: {
7045
+ type: "action",
7046
+ action: responseBody.action
7047
+ }
7048
+ };
7049
+ }
7050
+ case "subflow": {
7051
+ assertSubflowResponseBody(responseBody);
7052
+ return {
7053
+ type: "behavior",
7054
+ behavior: __spreadProps(__spreadValues({}, responseBody), {
7055
+ type: "subflow",
7056
+ onCompletion: responseBody.onCompletion ? normaliseBehavior(responseBody.onCompletion, []) : void 0,
7057
+ onError: responseBody.onError ? normaliseBehavior(responseBody.onError, []) : void 0
7058
+ })
7059
+ };
7060
+ }
7061
+ case "modal": {
7062
+ assertModalResponseBody(responseBody);
7063
+ return { type: "behavior", behavior: __spreadProps(__spreadValues({}, responseBody), { type: "modal" }) };
7064
+ }
7065
+ default: {
7066
+ throw new Error(`Unsupported response type: ${String(responseType)}`);
7067
+ }
7068
+ }
7069
+ };
7070
+ var getCachedOrFetch = async (requestParams, requestCache, httpClient) => {
7071
+ const cachedPromise = requestCache.get(requestParams);
7072
+ if (cachedPromise) {
7073
+ const cachedResponse = await cachedPromise;
7074
+ if (cachedResponse == null ? void 0 : cachedResponse.ok) {
7075
+ return cachedResponse;
7076
+ }
7077
+ }
7078
+ return makeSafeHttpClient(httpClient)(...requestParams);
7079
+ };
7080
+
7081
+ // src/flow/executeSubmission.ts
7082
+ var executeSubmission = async (props) => {
7083
+ const { httpClient, requestCache, trackEvent, logEvent } = props;
7084
+ const triggerAction = async (action, model, isInitial) => {
7085
+ var _a, _b;
7086
+ const { exit, url, result = null, id: actionId } = action;
7087
+ const trackSubmissionEvent = !isInitial ? trackEvent : () => {
7088
+ };
7089
+ trackSubmissionEvent("Action Triggered", { actionId });
7090
+ if (exit && !url) {
7091
+ trackSubmissionEvent("Action Succeeded", { actionId });
7092
+ return { type: "complete", result };
7093
+ }
7094
+ try {
7095
+ const command = await executeRequest({
7096
+ exit,
7097
+ request: createRequestFromAction(action, model),
7098
+ requestCache,
7099
+ httpClient,
7100
+ trackEvent: (name, properties) => {
7101
+ trackSubmissionEvent(name, __spreadProps(__spreadValues({}, properties), { actionId }));
7102
+ },
7103
+ logEvent
7104
+ });
7105
+ switch (command.type) {
7106
+ case "error": {
7107
+ trackSubmissionEvent("Action Failed", __spreadValues({
7108
+ actionId,
7109
+ statusCode: (_a = command.httpError) == null ? void 0 : _a.statusCode
7110
+ }, (_b = command.body) == null ? void 0 : _b.analytics));
7111
+ return command;
7112
+ }
7113
+ case "behavior": {
7114
+ if (command.behavior.type === "action") {
7115
+ trackSubmissionEvent("Action Succeeded", { actionId });
7116
+ return await executeRequest({
7117
+ request: createRequestFromAction(command.behavior.action, null),
7118
+ requestCache,
7119
+ httpClient,
7120
+ trackEvent,
7121
+ logEvent
7122
+ });
7123
+ }
7124
+ trackSubmissionEvent("Action Succeeded", { actionId });
7125
+ return command;
7126
+ }
7127
+ case "complete": {
7128
+ trackSubmissionEvent("Action Succeeded", { actionId });
7129
+ return __spreadProps(__spreadValues({}, command), { result: recursiveMerge(command.result, result) });
7130
+ }
7131
+ default: {
7132
+ trackSubmissionEvent("Action Succeeded", { actionId });
7133
+ return command;
7134
+ }
7135
+ }
7136
+ } catch (error) {
7137
+ const errorMessage = getErrorMessage(error);
7138
+ trackSubmissionEvent("Action Failed", { actionId, errorMessage });
7139
+ logEvent("error", "Dynamic Flow - Action Failed Unexpectedly", { actionId, errorMessage });
7140
+ throw error;
7141
+ }
7142
+ };
7143
+ return triggerAction(props.action, props.model, props.isInitial);
7144
+ };
7145
+ var createRequestFromAction = (action, model) => {
7146
+ var _a, _b, _c;
7147
+ return __spreadProps(__spreadValues({}, action), {
7148
+ url: (_a = action.url) != null ? _a : "",
7149
+ method: (_b = action.method) != null ? _b : "POST",
7150
+ body: action.method === "GET" ? void 0 : recursiveMerge(model, (_c = action.data) != null ? _c : null)
7151
+ });
7152
+ };
7153
+
6859
7154
  // src/domain/mappers/mapStepToComponent.ts
6860
7155
  var mapStepToComponent = (_a) => {
6861
7156
  var _b = _a, {
@@ -6874,7 +7169,7 @@ var mapStepToComponent = (_a) => {
6874
7169
  "onBehavior"
6875
7170
  ]);
6876
7171
  var _a2;
6877
- const { etag, step, stepLocalValue, logEvent, updateComponent } = restProps;
7172
+ const { etag, step, stepLocalValue, flowRequestCache, logEvent, updateComponent } = restProps;
6878
7173
  const {
6879
7174
  id,
6880
7175
  control,
@@ -6889,12 +7184,15 @@ var mapStepToComponent = (_a) => {
6889
7184
  title,
6890
7185
  tags
6891
7186
  } = step;
6892
- const submissionRequestsCache = makeRequestCache();
7187
+ const requestCache = makeRequestCacheWithParent(flowRequestCache);
6893
7188
  const submissionBehaviors = [];
6894
7189
  const registerSubmissionBehavior = (behavior) => {
6895
7190
  if (behavior.type === "action" && behavior.action.prefetch) {
6896
7191
  submissionBehaviors.push(behavior);
6897
7192
  }
7193
+ if (behavior.type === "subflow" && behavior.launchConfig.type === "dynamic" && behavior.launchConfig.request.prefetch) {
7194
+ submissionBehaviors.push(behavior);
7195
+ }
6898
7196
  };
6899
7197
  const back = mapBackNavigation(navigation, onBehavior, features.isEnabled("nativeBack"));
6900
7198
  const stepId = id || key;
@@ -6955,7 +7253,7 @@ var mapStepToComponent = (_a) => {
6955
7253
  title,
6956
7254
  tags,
6957
7255
  stackBehavior: (_a2 = navigation == null ? void 0 : navigation.stackBehavior) != null ? _a2 : "default",
6958
- submissionRequestsCache,
7256
+ requestCache,
6959
7257
  step,
6960
7258
  updateComponent,
6961
7259
  trackEvent,
@@ -6965,7 +7263,7 @@ var mapStepToComponent = (_a) => {
6965
7263
  httpClient: mapperProps.httpClient,
6966
7264
  model: stepComponent.getSubmittableValueSync(),
6967
7265
  behaviors: submissionBehaviors,
6968
- requestsCache: submissionRequestsCache
7266
+ requestCache
6969
7267
  });
6970
7268
  return stepComponent;
6971
7269
  };
@@ -6988,56 +7286,25 @@ var mapBackNavigation = (navigation, onBehavior, isNativeBackEnabled) => {
6988
7286
  } : void 0;
6989
7287
  };
6990
7288
  var executePrefetch = (props) => {
6991
- const {
6992
- httpClient,
6993
- behaviors: submissionBehaviors,
6994
- model,
6995
- requestsCache: submissionRequestsCache
6996
- } = props;
7289
+ const { httpClient, behaviors: submissionBehaviors, model, requestCache } = props;
6997
7290
  submissionBehaviors.forEach((behavior) => {
6998
- const requestParams = makeSubmissionRequest(behavior.action, model);
7291
+ const request = behavior.type === "action" ? createRequestFromAction(behavior.action, model) : behavior.launchConfig.request;
7292
+ const requestParams = [
7293
+ request.url,
7294
+ {
7295
+ body: JSON.stringify(request.body),
7296
+ method: request.method,
7297
+ headers: { "Content-Type": "application/json" }
7298
+ }
7299
+ ];
6999
7300
  try {
7000
7301
  const responsePromise = httpClient(...requestParams).catch(() => null);
7001
- submissionRequestsCache.set(...requestParams, responsePromise);
7302
+ requestCache.set(requestParams, responsePromise);
7002
7303
  } catch (e) {
7003
7304
  }
7004
7305
  });
7005
7306
  };
7006
7307
 
7007
- // src/flow/getResponseType.ts
7008
- var responseTypes = ["step", "action", "exit", "modal"];
7009
- var getResponseType = async (response) => {
7010
- assertResponseIsValid(response);
7011
- const headerResponseType = getResponseTypeFromHeader(response);
7012
- if (headerResponseType) {
7013
- return headerResponseType;
7014
- }
7015
- const jsonBody = await parseResponseBodyAsJsonElement(response.clone());
7016
- if (isObject(jsonBody) && jsonBody.action) {
7017
- return "action";
7018
- }
7019
- return "step";
7020
- };
7021
- var getResponseTypeFromHeader = (response) => {
7022
- var _a, _b;
7023
- if ((_a = response.headers) == null ? void 0 : _a.has("X-Df-Response-Type")) {
7024
- const type = response.headers.get("X-Df-Response-Type");
7025
- assertDFResponseType(type);
7026
- return type;
7027
- }
7028
- if ((_b = response.headers) == null ? void 0 : _b.has("X-Df-Exit")) {
7029
- return "exit";
7030
- }
7031
- return void 0;
7032
- };
7033
- function assertDFResponseType(type) {
7034
- if (!responseTypes.includes(type)) {
7035
- throw new Error(
7036
- "Unsupported X-Df-Response-Type. Allowed values are 'step', 'action', 'exit', 'error', 'modal'."
7037
- );
7038
- }
7039
- }
7040
-
7041
7308
  // src/flow/executePoll.ts
7042
7309
  var executePoll = async (props) => {
7043
7310
  const { errorBehavior, signal, url, httpClient, trackEvent } = props;
@@ -7131,113 +7398,62 @@ var executeRefresh = async (props) => {
7131
7398
  }
7132
7399
  };
7133
7400
 
7134
- // src/flow/makeSafeHttpClient.ts
7135
- var makeSafeHttpClient = (httpClient) => async (...props) => {
7136
- try {
7137
- return await httpClient(...props);
7138
- } catch (e) {
7139
- return null;
7140
- }
7141
- };
7142
-
7143
- // src/flow/executeSubmission.ts
7144
- var executeSubmission = async (props) => {
7145
- const { httpClient, requestCache, trackEvent, logEvent } = props;
7146
- const triggerAction = async (action, model, isInitial) => {
7147
- const { exit, url, result = null, id: actionId } = action;
7148
- const trackSubmissionEvent = !isInitial ? trackEvent : () => {
7149
- };
7150
- trackSubmissionEvent("Action Triggered", { actionId });
7151
- if (exit && !url) {
7152
- trackSubmissionEvent("Action Succeeded", { actionId });
7153
- return { type: "complete", result };
7154
- }
7155
- const requestParams = makeSubmissionRequest(action, model);
7156
- const response = await getCachedOrFetch(requestParams, requestCache, httpClient);
7157
- if (!response) {
7158
- const extra = { actionId, errorMessage: "Network Error" };
7159
- trackEvent("Action Failed", extra);
7160
- logEvent("error", "Dynamic Flow - Action Failed Unexpectedly", extra);
7161
- return { type: "error" };
7162
- }
7163
- if (!response.ok) {
7164
- return handleErrorResponse(response, actionId);
7165
- }
7166
- try {
7167
- const responseType = await getResponseType(response);
7168
- const body = await parseResponseBodyAsJsonElement(response);
7169
- if (exit) {
7170
- return { type: "complete", result: recursiveMerge(body, result) };
7171
- }
7172
- switch (responseType) {
7173
- case "step": {
7174
- const etag = response.headers.get("etag") || null;
7175
- assertStepResponseBody(body);
7176
- trackSubmissionEvent("Action Succeeded", { actionId });
7177
- return { type: "replace-step", step: body, etag };
7178
- }
7179
- case "exit": {
7180
- trackSubmissionEvent("Action Succeeded", { actionId });
7181
- return { type: "complete", result: recursiveMerge(body, result) };
7182
- }
7183
- case "action": {
7184
- assertActionResponseBody(body);
7185
- trackSubmissionEvent("Action Succeeded", { actionId });
7186
- return await triggerAction(body.action, null, false);
7187
- }
7188
- case "modal": {
7189
- assertModalResponseBody(body);
7190
- trackSubmissionEvent("Action Succeeded", { actionId });
7191
- return { type: "behavior", behavior: __spreadProps(__spreadValues({}, body), { type: "modal" }) };
7192
- }
7193
- default: {
7194
- throw new Error(`Unsupported response type: ${String(responseType)}`);
7195
- }
7401
+ // src/getSubflowCallbacks.ts
7402
+ var getSubflowCallbacks = ({
7403
+ behavior,
7404
+ close,
7405
+ restart,
7406
+ onBehavior,
7407
+ onError,
7408
+ onEvent
7409
+ }) => {
7410
+ const {
7411
+ onCompletion: onCompletionBehavior,
7412
+ onError: onErrorBehavior,
7413
+ referrerId,
7414
+ resultKey
7415
+ } = behavior;
7416
+ return {
7417
+ onCompletion: (result) => {
7418
+ var _a;
7419
+ restart();
7420
+ if (!onCompletionBehavior) {
7421
+ close();
7422
+ return;
7196
7423
  }
7197
- } catch (error) {
7198
- const errorMessage = getErrorMessage(error);
7199
- trackSubmissionEvent("Action Failed", { actionId, errorMessage });
7200
- logEvent("error", "Dynamic Flow - Action Failed Unexpectedly", { actionId, errorMessage });
7201
- throw error;
7202
- }
7203
- };
7204
- const handleErrorResponse = async (response, actionId) => {
7205
- const body = await parseResponseBodyAsJsonElement(response.clone());
7206
- if (isErrorResponseBody(body)) {
7207
- const refreshUrl = body.refreshUrl || body.refreshFormUrl;
7208
- const { error, validation, analytics } = body;
7209
- trackEvent("Action Failed", __spreadProps(__spreadValues({}, analytics), { actionId, statusCode: response.status }));
7210
- const errors = { error, validation };
7211
- return refreshUrl ? { type: "refresh", body: { refreshUrl, errors } } : {
7212
- type: "error",
7213
- body: { errors, analytics },
7214
- httpError: { statusCode: response.status }
7215
- };
7216
- }
7217
- trackEvent("Action Failed", { actionId, statusCode: response.status });
7218
- const errorMessage = await parseResponseBodyAsText(response);
7219
- return {
7220
- type: "error",
7221
- httpError: {
7222
- message: errorMessage || void 0,
7223
- statusCode: response.status
7424
+ if (onCompletionBehavior.type === "action") {
7425
+ const newActionData = recursiveMerge(
7426
+ (_a = onCompletionBehavior.action.data) != null ? _a : null,
7427
+ resultKey ? { [resultKey]: result } : result
7428
+ );
7429
+ void onBehavior(__spreadProps(__spreadValues({}, onCompletionBehavior), {
7430
+ action: __spreadProps(__spreadValues({}, onCompletionBehavior.action), { data: newActionData })
7431
+ }));
7432
+ return;
7224
7433
  }
7225
- };
7226
- };
7227
- return triggerAction(props.action, props.model, props.isInitial);
7228
- };
7229
- var getCachedOrFetch = async (requestParams, requestCache, httpClient) => {
7230
- if (requestCache == null ? void 0 : requestCache.has(...requestParams)) {
7231
- const cachedPromise = requestCache.get(...requestParams);
7232
- requestCache.delete(...requestParams);
7233
- if (cachedPromise) {
7234
- const cachedResponse = await cachedPromise;
7235
- if (cachedResponse == null ? void 0 : cachedResponse.ok) {
7236
- return cachedResponse;
7434
+ void onBehavior(onCompletionBehavior);
7435
+ close();
7436
+ },
7437
+ onError: (error, status) => {
7438
+ if (!onErrorBehavior) {
7439
+ onError(error, {}, status);
7440
+ close();
7441
+ return;
7237
7442
  }
7443
+ restart();
7444
+ void onBehavior(onErrorBehavior);
7445
+ close();
7446
+ },
7447
+ onEvent: (name, properties) => {
7448
+ onEvent(name, __spreadValues({
7449
+ referrerId
7450
+ }, properties));
7451
+ },
7452
+ onCancellation: () => {
7453
+ restart();
7454
+ close();
7238
7455
  }
7239
- }
7240
- return makeSafeHttpClient(httpClient)(...requestParams);
7456
+ };
7241
7457
  };
7242
7458
 
7243
7459
  // src/renderers/getSchemaErrorMessageFunction.ts
@@ -7469,17 +7685,16 @@ function useStableCallback(handler) {
7469
7685
 
7470
7686
  // src/useDynamicFlowController.tsx
7471
7687
  function useDynamicFlowController(props) {
7472
- const _a = props, { flowId, initialAction, initialStep, features } = _a, rest = __objRest(_a, ["flowId", "initialAction", "initialStep", "features"]);
7688
+ const _a = props, { flowId, initialAction, initialStep, features, scrollToTop } = _a, rest = __objRest(_a, ["flowId", "initialAction", "initialStep", "features", "scrollToTop"]);
7473
7689
  const httpClient = useStableCallback(rest.httpClient);
7474
7690
  const onCancellation = useStableCallback(rest.onCancellation);
7475
7691
  const onCompletion = useStableCallback(rest.onCompletion);
7476
- const onCopy = useStableCallback(props.onCopy);
7477
- const onValueChange = useStableCallback(props.onValueChange);
7478
- const onLink = useStableCallback(props.onLink);
7692
+ const onCopy = useStableCallback(rest.onCopy);
7693
+ const onLink = useStableCallback(rest.onLink);
7479
7694
  const onError = useStableCallback(rest.onError);
7480
7695
  const onEvent = useStableCallback(rest.onEvent);
7481
7696
  const onLog = useStableCallback(rest.onLog);
7482
- const scrollToTop = useStableCallback(props.scrollToTop);
7697
+ const onValueChange = useStableCallback(rest.onValueChange);
7483
7698
  const { formatMessage, locale } = (0, import_react_intl7.useIntl)();
7484
7699
  const getErrorMessageFunctions = (0, import_react3.useMemo)(
7485
7700
  () => getSchemaErrorMessageFunction(formatMessage, locale),
@@ -7487,10 +7702,15 @@ function useDynamicFlowController(props) {
7487
7702
  );
7488
7703
  const rerender = useRerender();
7489
7704
  const rootComponentRef = (0, import_react3.useRef)(
7490
- createRootDomainComponent(rerender, scrollToTop, {
7491
- isNativeBackEnabled: features.isEnabled("nativeBack"),
7492
- isFlowCancellable: Boolean(rest.onCancellation)
7493
- })
7705
+ createRootDomainComponent(
7706
+ rerender,
7707
+ scrollToTop,
7708
+ {
7709
+ isNativeBackEnabled: features.isEnabled("nativeBack"),
7710
+ isFlowCancellable: Boolean(rest.onCancellation)
7711
+ },
7712
+ normaliseRequestCache(rest.requestCache)
7713
+ )
7494
7714
  );
7495
7715
  const stepCount = (0, import_react3.useRef)(0);
7496
7716
  const abortControllerRef = (0, import_react3.useRef)(new AbortController());
@@ -7499,12 +7719,15 @@ function useDynamicFlowController(props) {
7499
7719
  abortControllerRef.current = new AbortController();
7500
7720
  return abortControllerRef.current.signal;
7501
7721
  };
7722
+ const hasTriggeredInitialAction = (0, import_react3.useRef)(false);
7502
7723
  (0, import_react3.useEffect)(() => {
7503
7724
  trackCoreEvent("Initiated");
7504
- if (!initialStep && initialAction) {
7725
+ if (!hasTriggeredInitialAction.current && !initialStep && initialAction) {
7505
7726
  rootComponentRef.current.setLoadingState("submitting");
7727
+ hasTriggeredInitialAction.current = true;
7506
7728
  void onAction(__spreadValues({ method: "GET" }, initialAction), null);
7507
7729
  }
7730
+ rootComponentRef.current.start();
7508
7731
  return () => {
7509
7732
  rootComponentRef.current.stop();
7510
7733
  };
@@ -7517,6 +7740,7 @@ function useDynamicFlowController(props) {
7517
7740
  const component = createStepComponent2(newStep, etag, null);
7518
7741
  if (component) {
7519
7742
  rootComponentRef.current.pushStep(component);
7743
+ rootComponentRef.current.setLoadingState("idle");
7520
7744
  }
7521
7745
  },
7522
7746
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -7531,12 +7755,14 @@ function useDynamicFlowController(props) {
7531
7755
  );
7532
7756
  if (component) {
7533
7757
  rootComponentRef.current.updateStep(component);
7758
+ rootComponentRef.current.setLoadingState("idle");
7534
7759
  }
7535
7760
  }, []);
7536
7761
  const getMapperProps = () => ({
7537
7762
  uid: `${rootComponentRef.current.uid}:${stepCount.current}`,
7538
7763
  loadingState: "idle",
7539
7764
  updateComponent: () => rerender(),
7765
+ flowRequestCache: rootComponentRef.current.requestCache,
7540
7766
  getErrorMessageFunctions,
7541
7767
  trackEvent,
7542
7768
  logEvent,
@@ -7575,7 +7801,8 @@ function useDynamicFlowController(props) {
7575
7801
  const stepId = (_b = (_a2 = step == null ? void 0 : step.id) != null ? _a2 : step == null ? void 0 : step.key) != null ? _b : null;
7576
7802
  const analytics = step == null ? void 0 : step.analytics;
7577
7803
  const metadata = __spreadValues(__spreadValues(__spreadValues(__spreadValues({
7578
- flowId
7804
+ flowId,
7805
+ integrationId: flowId
7579
7806
  }, step ? { stepCount: stepCount.current } : {}), stepId !== null ? { stepId } : {}), analytics), properties);
7580
7807
  try {
7581
7808
  onEvent == null ? void 0 : onEvent(`Dynamic Flow - ${eventName}`, __spreadValues({}, metadata));
@@ -7616,7 +7843,7 @@ function useDynamicFlowController(props) {
7616
7843
  onCancellation();
7617
7844
  }, []);
7618
7845
  const onBehavior = (0, import_react3.useCallback)(async (behavior) => {
7619
- var _a2;
7846
+ var _a2, _b, _c;
7620
7847
  switch (behavior.type) {
7621
7848
  case "back": {
7622
7849
  if (behavior.action) {
@@ -7707,6 +7934,33 @@ function useDynamicFlowController(props) {
7707
7934
  case "dismiss":
7708
7935
  rootComponentRef.current.dismissModal();
7709
7936
  break;
7937
+ case "subflow": {
7938
+ rootComponentRef.current.setLoadingState("submitting");
7939
+ const { launchConfig } = behavior;
7940
+ const { request, presentation } = launchConfig;
7941
+ const callbacks = getSubflowCallbacks({
7942
+ behavior,
7943
+ close: () => rootComponentRef.current.closeSubflow(),
7944
+ onBehavior,
7945
+ onError: closeWithError,
7946
+ onEvent,
7947
+ restart: () => {
7948
+ rootComponentRef.current.setLoadingState("idle");
7949
+ rootComponentRef.current.start();
7950
+ }
7951
+ });
7952
+ const component = createSubflowDomainComponent(
7953
+ __spreadProps(__spreadValues({}, callbacks), {
7954
+ initialRequest: request,
7955
+ requestCache: (_c = (_b = rootComponentRef.current.getStep()) == null ? void 0 : _b.requestCache) != null ? _c : rootComponentRef.current.requestCache,
7956
+ presentation
7957
+ }),
7958
+ rerender
7959
+ );
7960
+ rootComponentRef.current.stop();
7961
+ rootComponentRef.current.addSubflow(component);
7962
+ break;
7963
+ }
7710
7964
  case "none":
7711
7965
  break;
7712
7966
  }
@@ -7715,16 +7969,16 @@ function useDynamicFlowController(props) {
7715
7969
  }, []);
7716
7970
  const onAction = (0, import_react3.useCallback)(
7717
7971
  async (action, model) => {
7718
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
7972
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
7719
7973
  try {
7720
7974
  rootComponentRef.current.setLoadingState("submitting");
7721
7975
  const command = await executeSubmission({
7722
7976
  action,
7723
7977
  model,
7724
7978
  isInitial: !rootComponentRef.current.hasStep(),
7725
- requestCache: (_a2 = rootComponentRef.current.getStep()) == null ? void 0 : _a2.submissionRequestsCache,
7979
+ requestCache: (_b = (_a2 = rootComponentRef.current.getStep()) == null ? void 0 : _a2.requestCache) != null ? _b : rootComponentRef.current.requestCache,
7726
7980
  httpClient,
7727
- trackEvent: trackCoreEvent,
7981
+ trackEvent,
7728
7982
  logEvent
7729
7983
  });
7730
7984
  switch (command.type) {
@@ -7736,6 +7990,7 @@ function useDynamicFlowController(props) {
7736
7990
  }
7737
7991
  case "replace-step": {
7738
7992
  const isFirstStep = !rootComponentRef.current.hasStep();
7993
+ rootComponentRef.current.closeSubflow();
7739
7994
  createStep(command.step, command.etag);
7740
7995
  trackCoreEvent("Step Shown", { isFirstStep });
7741
7996
  break;
@@ -7743,7 +7998,7 @@ function useDynamicFlowController(props) {
7743
7998
  case "error": {
7744
7999
  rootComponentRef.current.setLoadingState("idle");
7745
8000
  const genericErrorMessage = getErrorMessageFunctions().genericErrorWithRetry();
7746
- const errors = (_c = (_b = command.body) == null ? void 0 : _b.errors) != null ? _c : { error: genericErrorMessage };
8001
+ const errors = (_d = (_c = command.body) == null ? void 0 : _c.errors) != null ? _d : { error: genericErrorMessage };
7747
8002
  const currentStep = rootComponentRef.current.getStep();
7748
8003
  if (currentStep) {
7749
8004
  updateStep(
@@ -7757,16 +8012,16 @@ function useDynamicFlowController(props) {
7757
8012
  external: void 0
7758
8013
  // and no external, to avoid retriggering it
7759
8014
  }),
7760
- (_e = (_d = rootComponentRef.current.getStep()) == null ? void 0 : _d.etag) != null ? _e : null
8015
+ (_f = (_e = rootComponentRef.current.getStep()) == null ? void 0 : _e.etag) != null ? _f : null
7761
8016
  );
7762
8017
  } else {
7763
- 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";
8018
+ 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";
7764
8019
  closeWithError(
7765
8020
  new Error(errorMessage, {
7766
8021
  cause: `method: ${action.method}, url: ${action.url}`
7767
8022
  }),
7768
8023
  {},
7769
- (_i = command.httpError) == null ? void 0 : _i.statusCode
8024
+ (_j = command.httpError) == null ? void 0 : _j.statusCode
7770
8025
  );
7771
8026
  }
7772
8027
  break;
@@ -7862,7 +8117,7 @@ function useDynamicFlowController(props) {
7862
8117
  []
7863
8118
  );
7864
8119
  const hasMappedInitialStep = (0, import_react3.useRef)(false);
7865
- if (!hasMappedInitialStep.current && initialStep && !initialAction) {
8120
+ if (!hasMappedInitialStep.current && initialStep) {
7866
8121
  createStep(initialStep, null);
7867
8122
  trackCoreEvent("Step Shown", { isFirstStep: true });
7868
8123
  hasMappedInitialStep.current = true;
@@ -7947,8 +8202,79 @@ function useDynamicFlow(props) {
7947
8202
  };
7948
8203
  }
7949
8204
 
8205
+ // src/useDynamicFlowModal.tsx
8206
+ var import_react5 = require("react");
8207
+ var useDynamicFlowModal = (props) => {
8208
+ const _a = props, { renderers, onCompletion, onError, onCancellation, onEvent, onLink } = _a, rest = __objRest(_a, ["renderers", "onCompletion", "onError", "onCancellation", "onEvent", "onLink"]);
8209
+ const [state, setState] = (0, import_react5.useState)({ type: "initial" });
8210
+ const df = useDynamicFlow(__spreadProps(__spreadValues({}, rest), {
8211
+ onCompletion: (result) => {
8212
+ setState({ type: "completed", result });
8213
+ },
8214
+ onError: (error, status) => {
8215
+ setState({ type: "error", error, status });
8216
+ },
8217
+ onEvent: (name, properties) => {
8218
+ if (name === "Dynamic Flow - Step Shown") {
8219
+ setState({ type: "in-progress" });
8220
+ }
8221
+ onEvent == null ? void 0 : onEvent(name, properties);
8222
+ },
8223
+ renderers,
8224
+ onLink: onLink != null ? onLink : (() => true)
8225
+ }));
8226
+ const onUnmount = () => {
8227
+ switch (state.type) {
8228
+ case "completed":
8229
+ onCompletion(state.result);
8230
+ break;
8231
+ case "error":
8232
+ onError(state.error, state.status);
8233
+ break;
8234
+ case "initial":
8235
+ case "in-progress":
8236
+ case "cancelled": {
8237
+ df.controller.cancel();
8238
+ onCancellation == null ? void 0 : onCancellation();
8239
+ }
8240
+ }
8241
+ };
8242
+ const onClose = () => {
8243
+ setState({ type: "cancelled" });
8244
+ };
8245
+ return __spreadProps(__spreadValues({}, df), {
8246
+ modal: { body: df.view, open: state.type === "in-progress", onClose, onUnmount }
8247
+ });
8248
+ };
8249
+
7950
8250
  // src/DynamicFlowCore.tsx
7951
8251
  function DynamicFlowCore(props) {
7952
8252
  const df = useDynamicFlow(props);
7953
8253
  return df.view;
7954
8254
  }
8255
+
8256
+ // src/domain/features/eventNames.ts
8257
+ var eventNames = [
8258
+ "Initiated",
8259
+ "Succeeded",
8260
+ "Failed",
8261
+ "Cancelled",
8262
+ "Step Shown",
8263
+ "Action Triggered",
8264
+ "Action Succeeded",
8265
+ "Action Aborted",
8266
+ "Action Failed",
8267
+ "Refresh Triggered",
8268
+ "Refresh Succeeded",
8269
+ "Refresh Aborted",
8270
+ "Refresh Failed",
8271
+ "OneOf Selected",
8272
+ "OneOf Option Selected",
8273
+ "PersistAsync Triggered",
8274
+ "PersistAsync Succeeded",
8275
+ "PersistAsync Failed",
8276
+ "Polling Failed",
8277
+ "ValidationAsync Triggered",
8278
+ "ValidationAsync Succeeded",
8279
+ "ValidationAsync Failed"
8280
+ ];