@wise/dynamic-flow-client 5.22.2 → 5.24.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 (26) hide show
  1. package/build/main.js +165 -66
  2. package/build/main.mjs +165 -66
  3. package/build/tsconfig.types.tsbuildinfo +1 -1
  4. package/build/types/controller/FlowController.d.ts.map +1 -1
  5. package/build/types/domain/components/RootDomainComponent.d.ts +7 -1
  6. package/build/types/domain/components/RootDomainComponent.d.ts.map +1 -1
  7. package/build/types/domain/components/collectionComponent/CollectionComponent.d.ts.map +1 -1
  8. package/build/types/domain/components/collectionComponent/types.d.ts +2 -0
  9. package/build/types/domain/components/collectionComponent/types.d.ts.map +1 -1
  10. package/build/types/domain/components/step/StepDomainComponent.d.ts +6 -1
  11. package/build/types/domain/components/step/StepDomainComponent.d.ts.map +1 -1
  12. package/build/types/domain/features/delay/getStepDelays.d.ts +10 -0
  13. package/build/types/domain/features/delay/getStepDelays.d.ts.map +1 -0
  14. package/build/types/domain/mappers/layout/collectionLayoutToComponent.d.ts.map +1 -1
  15. package/build/types/domain/mappers/utils/behavior-utils.d.ts.map +1 -1
  16. package/build/types/domain/mappers/utils/utils.d.ts.map +1 -1
  17. package/build/types/domain/types.d.ts +8 -2
  18. package/build/types/domain/types.d.ts.map +1 -1
  19. package/build/types/renderers/mappers/collectionComponentToProps.d.ts.map +1 -1
  20. package/build/types/renderers/mappers/componentToRendererProps.d.ts +3 -2
  21. package/build/types/renderers/mappers/componentToRendererProps.d.ts.map +1 -1
  22. package/build/types/renderers/mappers/constComponentToProps.d.ts +1 -1
  23. package/build/types/renderers/mappers/utils/mapRendererLoadingState.d.ts +4 -0
  24. package/build/types/renderers/mappers/utils/mapRendererLoadingState.d.ts.map +1 -0
  25. package/build/types/useDynamicFlow.d.ts.map +1 -1
  26. package/package.json +4 -4
package/build/main.mjs CHANGED
@@ -1173,6 +1173,15 @@ var createRootDomainComponent = (onComponentUpdate, scrollToTop, backConfig, req
1173
1173
  const navigation = (_a = component.getStep()) == null ? void 0 : _a.step.navigation;
1174
1174
  const stepHasBehavior = Boolean((_b = navigation == null ? void 0 : navigation.back) != null ? _b : navigation == null ? void 0 : navigation.backButton);
1175
1175
  return component.backConfig.isFlowCancellable || component.stepStack.length > 1 && component.backConfig.isNativeBackEnabled || stepHasBehavior;
1176
+ },
1177
+ startDelay(delay) {
1178
+ var _a, _b;
1179
+ return (_b = (_a = component.getStep()) == null ? void 0 : _a.startDelay(delay)) != null ? _b : { abort: () => {
1180
+ } };
1181
+ },
1182
+ setExternalConfirmation(external) {
1183
+ var _a;
1184
+ (_a = component.getStep()) == null ? void 0 : _a.setExternalConfirmation(external);
1176
1185
  }
1177
1186
  };
1178
1187
  return component;
@@ -1315,10 +1324,10 @@ var normaliseBehavior = (behavior, stepActions) => {
1315
1324
  });
1316
1325
  }
1317
1326
  if (behavior.type === "delay") {
1318
- return {
1319
- type: "none",
1327
+ return __spreadProps(__spreadValues({}, behavior), {
1328
+ behavior: normaliseBehavior(behavior.behavior, stepActions),
1320
1329
  track: false
1321
- };
1330
+ });
1322
1331
  }
1323
1332
  if (behavior.type === "dispatch-event") {
1324
1333
  return {
@@ -1514,11 +1523,36 @@ var boxLayoutToComponent = (uid, { border = false, components, control, margin,
1514
1523
  )
1515
1524
  });
1516
1525
 
1526
+ // src/domain/mappers/utils/image.ts
1527
+ var mapSpecImage = (image) => {
1528
+ var _a, _b, _c;
1529
+ return image ? {
1530
+ uri: (_b = (_a = image.uri) != null ? _a : image.url) != null ? _b : "",
1531
+ accessibilityDescription: (_c = image.accessibilityDescription) != null ? _c : image.text
1532
+ } : void 0;
1533
+ };
1534
+
1535
+ // src/domain/mappers/utils/media-utils.ts
1536
+ var getDomainLayerMedia = ({ icon, image, media }) => {
1537
+ if (media) {
1538
+ return media;
1539
+ }
1540
+ if (icon || image) {
1541
+ return {
1542
+ type: "legacy",
1543
+ icon,
1544
+ image: mapSpecImage(image)
1545
+ };
1546
+ }
1547
+ return void 0;
1548
+ };
1549
+
1517
1550
  // src/domain/mappers/utils/utils.ts
1518
1551
  var mapInlineAlert = (alert) => {
1519
1552
  return alert ? {
1520
1553
  content: alert.content,
1521
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1554
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral",
1555
+ media: getDomainLayerMedia({ media: alert.media })
1522
1556
  } : void 0;
1523
1557
  };
1524
1558
  var mapAdditionalInfo = (info, mapperProps) => {
@@ -1545,7 +1579,8 @@ var mapAdditionalInfo = (info, mapperProps) => {
1545
1579
  var mapSchemaAlert = (alert) => {
1546
1580
  return alert ? {
1547
1581
  content: alert.markdown,
1548
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1582
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral",
1583
+ media: getDomainLayerMedia({ media: alert.media })
1549
1584
  } : void 0;
1550
1585
  };
1551
1586
 
@@ -1623,13 +1658,17 @@ var createCollectionComponent = (props, onComponentUpdate, queryFunction) => {
1623
1658
  });
1624
1659
  }).catch(() => {
1625
1660
  if (!signal.aborted) {
1661
+ const retry = () => {
1662
+ update(component, (draft) => {
1663
+ draft.status = { type: "loading", reason: mode };
1664
+ });
1665
+ query(mode);
1666
+ };
1626
1667
  update(component, (draft) => {
1627
- draft.state = {
1628
- filters: component.state.filters,
1629
- search: component.state.search,
1630
- sections: []
1631
- };
1632
- draft.status = { type: "error", reason: mode, retry: () => query(mode) };
1668
+ if (mode === "search") {
1669
+ draft.state.sections = [];
1670
+ }
1671
+ draft.status = { type: "error", reason: mode, retry };
1633
1672
  });
1634
1673
  }
1635
1674
  });
@@ -1715,13 +1754,15 @@ var mergeSections = (existing, incoming) => {
1715
1754
  const knownIds = new Set(existing.map((section) => section.id));
1716
1755
  const newSections = incoming.filter((section) => !knownIds.has(section.id));
1717
1756
  const merged = existing.map((section) => {
1718
- var _a, _b;
1757
+ var _a, _b, _c, _d;
1719
1758
  const match = incoming.find((s) => s.id === section.id);
1720
1759
  if (!match) return section;
1721
1760
  return {
1722
1761
  id: match.id,
1723
1762
  title: (_a = match.title) != null ? _a : section.title,
1724
1763
  callToAction: (_b = match.callToAction) != null ? _b : section.callToAction,
1764
+ help: (_c = match.help) != null ? _c : section.help,
1765
+ inlineAlert: (_d = match.inlineAlert) != null ? _d : section.inlineAlert,
1725
1766
  items: [...section.items, ...match.items]
1726
1767
  };
1727
1768
  });
@@ -1840,13 +1881,14 @@ var collectionLayoutToComponent = (uid, { analyticsId, control, initialState, ma
1840
1881
  return component;
1841
1882
  };
1842
1883
  var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
1843
- var _a, _b, _c;
1884
+ const { sections, filters, beforeSections, afterSections, nextCursor } = specState;
1844
1885
  return {
1845
- sections: specState.sections.map((section) => {
1846
- return {
1847
- id: section.id,
1848
- title: section.title,
1886
+ sections: sections.map((section) => {
1887
+ var _a;
1888
+ return __spreadProps(__spreadValues({}, section), {
1849
1889
  callToAction: getDomainLayerCallToAction(section.callToAction, mapperProps),
1890
+ help: (_a = section.help) == null ? void 0 : _a.markdown,
1891
+ inlineAlert: mapInlineAlert(section.inlineAlert),
1850
1892
  items: section.items.map((item) => {
1851
1893
  const behavior = getDomainLayerBehavior(
1852
1894
  { behavior: item.primaryBehavior },
@@ -1862,24 +1904,29 @@ var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
1862
1904
  inlineAlert: mapInlineAlert(item.inlineAlert)
1863
1905
  });
1864
1906
  })
1865
- };
1907
+ });
1866
1908
  }),
1867
- filters: (_a = specState.filters) == null ? void 0 : _a.map((filter) => __spreadProps(__spreadValues({}, filter), {
1868
- options: filter.options.map((option) => {
1869
- var _a2;
1870
- return __spreadProps(__spreadValues({}, option), {
1871
- selected: (_a2 = option.selected) != null ? _a2 : false,
1872
- onSelect: () => {
1873
- }
1874
- // noop - this gets added during mapping
1875
- });
1876
- })
1877
- })),
1878
- beforeSections: (_b = specState.beforeSections) == null ? void 0 : _b.map(mapLayout),
1879
- afterSections: (_c = specState.afterSections) == null ? void 0 : _c.map(mapLayout),
1880
- nextCursor: specState.nextCursor
1909
+ filters: filters == null ? void 0 : filters.map(mapFilter),
1910
+ beforeSections: beforeSections == null ? void 0 : beforeSections.map(mapLayout),
1911
+ afterSections: afterSections == null ? void 0 : afterSections.map(mapLayout),
1912
+ nextCursor
1881
1913
  };
1882
1914
  };
1915
+ var mapFilter = (filter) => {
1916
+ const anySelected = filter.options.some((option) => option.selected);
1917
+ return __spreadProps(__spreadValues({}, filter), {
1918
+ options: filter.options.map((option, index) => {
1919
+ var _a;
1920
+ return __spreadProps(__spreadValues({}, option), {
1921
+ // if a single select with no selection, we should default to selecting the first item
1922
+ selected: filter.multiSelect || anySelected ? (_a = option.selected) != null ? _a : false : index === 0,
1923
+ onSelect: () => {
1924
+ }
1925
+ // noop - this gets added during mapping in the component itself
1926
+ });
1927
+ })
1928
+ });
1929
+ };
1883
1930
 
1884
1931
  // src/domain/components/ButtonComponent.ts
1885
1932
  var createButtonComponent = (props) => __spreadValues({
@@ -1887,30 +1934,6 @@ var createButtonComponent = (props) => __spreadValues({
1887
1934
  kind: "layout"
1888
1935
  }, props);
1889
1936
 
1890
- // src/domain/mappers/utils/image.ts
1891
- var mapSpecImage = (image) => {
1892
- var _a, _b, _c;
1893
- return image ? {
1894
- uri: (_b = (_a = image.uri) != null ? _a : image.url) != null ? _b : "",
1895
- accessibilityDescription: (_c = image.accessibilityDescription) != null ? _c : image.text
1896
- } : void 0;
1897
- };
1898
-
1899
- // src/domain/mappers/utils/media-utils.ts
1900
- var getDomainLayerMedia = ({ icon, image, media }) => {
1901
- if (media) {
1902
- return media;
1903
- }
1904
- if (icon || image) {
1905
- return {
1906
- type: "legacy",
1907
- icon,
1908
- image: mapSpecImage(image)
1909
- };
1910
- }
1911
- return void 0;
1912
- };
1913
-
1914
1937
  // src/domain/mappers/layout/buttonLayoutToComponent.ts
1915
1938
  var buttonLayoutToComponent = (uid, button, mapperProps) => {
1916
1939
  if (!button.behavior && !button.action && mapperProps.features.isEnabled("strictButtonOperations")) {
@@ -3004,6 +3027,45 @@ var getSubmittableData = async (components) => Promise.all(components.map(async
3004
3027
  var getSubmittableDataSync = (components) => components.map((component) => component.getSubmittableValueSync()).reduce((acc, value) => recursiveMerge(acc, value), null);
3005
3028
  var getLocalValues = (components) => components.map((component) => component.getLocalValue()).reduce((acc, value) => recursiveMerge(acc, value), null);
3006
3029
 
3030
+ // src/domain/features/delay/getStepDelays.ts
3031
+ var getStepDelays = (onEmpty) => {
3032
+ let timeouts = [];
3033
+ const remove = (timeout) => {
3034
+ timeouts = timeouts.filter((pendingTimeout) => pendingTimeout !== timeout);
3035
+ };
3036
+ return {
3037
+ start({ duration, execute }) {
3038
+ const timeout = setTimeout(() => {
3039
+ if (timeouts.includes(timeout)) {
3040
+ remove(timeout);
3041
+ execute();
3042
+ }
3043
+ if (timeouts.length === 0) {
3044
+ onEmpty();
3045
+ }
3046
+ }, duration * 1e3);
3047
+ timeouts = [...timeouts, timeout];
3048
+ return {
3049
+ abort: () => {
3050
+ clearTimeout(timeout);
3051
+ remove(timeout);
3052
+ if (timeouts.length === 0) {
3053
+ onEmpty();
3054
+ }
3055
+ }
3056
+ };
3057
+ },
3058
+ stop() {
3059
+ if (timeouts.length === 0) {
3060
+ return;
3061
+ }
3062
+ timeouts.forEach(clearTimeout);
3063
+ timeouts = [];
3064
+ onEmpty();
3065
+ }
3066
+ };
3067
+ };
3068
+
3007
3069
  // src/domain/components/step/StepDomainComponent.ts
3008
3070
  var createStepComponent = (props) => {
3009
3071
  const _a = props, {
@@ -3026,6 +3088,14 @@ var createStepComponent = (props) => {
3026
3088
  "onLoad"
3027
3089
  ]);
3028
3090
  const update = getInputUpdateFunction(onComponentUpdate);
3091
+ const resetDelayState = () => {
3092
+ if (component.loadingState === "delay-pending") {
3093
+ update(component, (draft) => {
3094
+ draft.loadingState = "idle";
3095
+ });
3096
+ }
3097
+ };
3098
+ const stepDelays = getStepDelays(resetDelayState);
3029
3099
  const component = __spreadProps(__spreadValues({
3030
3100
  uid
3031
3101
  }, rest), {
@@ -3075,6 +3145,10 @@ var createStepComponent = (props) => {
3075
3145
  draft.loadingState = loadingState;
3076
3146
  });
3077
3147
  },
3148
+ startDelay(delay) {
3149
+ component.setLoadingState("delay-pending");
3150
+ return stepDelays.start(delay);
3151
+ },
3078
3152
  addSubflow(subflow) {
3079
3153
  update(component, (draft) => {
3080
3154
  draft.subflow = subflow;
@@ -3102,11 +3176,17 @@ var createStepComponent = (props) => {
3102
3176
  stop() {
3103
3177
  stepPolling == null ? void 0 : stepPolling.stop();
3104
3178
  stepRefreshAfter == null ? void 0 : stepRefreshAfter.stop();
3179
+ stepDelays.stop();
3105
3180
  stepPrefetch.stop();
3106
3181
  update(component, (draft) => {
3107
3182
  draft.state = "stopped";
3108
3183
  draft.modals = [];
3109
3184
  });
3185
+ },
3186
+ setExternalConfirmation(external) {
3187
+ update(component, (draft) => {
3188
+ draft.externalConfirmation = external;
3189
+ });
3110
3190
  }
3111
3191
  });
3112
3192
  return component;
@@ -7492,6 +7572,14 @@ var createFlowController = (props) => {
7492
7572
  var _a;
7493
7573
  trackBehaviorTriggered(trackEvent, behavior);
7494
7574
  switch (behavior.type) {
7575
+ case "delay": {
7576
+ return rootComponent.startDelay({
7577
+ duration: behavior.duration,
7578
+ execute: () => {
7579
+ void onBehavior(behavior.behavior);
7580
+ }
7581
+ });
7582
+ }
7495
7583
  case "download": {
7496
7584
  try {
7497
7585
  await executeDownload(behavior.request, httpClient);
@@ -7562,7 +7650,14 @@ var createFlowController = (props) => {
7562
7650
  };
7563
7651
  }
7564
7652
  case "link": {
7565
- onLink(behavior.url);
7653
+ rootComponent.setExternalConfirmation(
7654
+ createExternalConfirmation(
7655
+ `${rootComponent.uid}-external-confirmation`,
7656
+ behavior.url,
7657
+ onLink,
7658
+ onChange
7659
+ )
7660
+ );
7566
7661
  break;
7567
7662
  }
7568
7663
  case "modal": {
@@ -8262,17 +8357,18 @@ var mapBoxControl = ({
8262
8357
 
8263
8358
  // src/renderers/mappers/collectionComponentToProps.ts
8264
8359
  var collectionComponentToProps = (component, rendererMapperProps) => {
8265
- var _a, _b, _c;
8266
- const beforeSectionsProps = (_a = component.state.beforeSections) == null ? void 0 : _a.map(
8360
+ var _a, _b, _c, _d, _e;
8361
+ const { render } = rendererMapperProps;
8362
+ const beforeSectionsProps = (_b = (_a = component.state.beforeSections) == null ? void 0 : _a.map(
8267
8363
  (child) => componentToRendererProps(child, rendererMapperProps)
8268
- );
8269
- const afterSectionsProps = (_b = component.state.afterSections) == null ? void 0 : _b.map(
8364
+ )) != null ? _b : [];
8365
+ const afterSectionsProps = (_d = (_c = component.state.afterSections) == null ? void 0 : _c.map(
8270
8366
  (child) => componentToRendererProps(child, rendererMapperProps)
8271
- );
8367
+ )) != null ? _d : [];
8272
8368
  return __spreadProps(__spreadValues(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "control", "margin", "tags")), rendererMapperProps), {
8273
8369
  status: component.status,
8274
8370
  state: __spreadProps(__spreadValues({}, component.state), {
8275
- filters: (_c = component.state.filters) != null ? _c : [],
8371
+ filters: (_e = component.state.filters) != null ? _e : [],
8276
8372
  sections: component.state.sections.map((section) => __spreadProps(__spreadValues({}, section), {
8277
8373
  callToAction: mapCallToActionOptional(section.callToAction),
8278
8374
  items: section.items.map((item) => __spreadProps(__spreadValues({}, item), {
@@ -8282,9 +8378,9 @@ var collectionComponentToProps = (component, rendererMapperProps) => {
8282
8378
  }))
8283
8379
  })),
8284
8380
  beforeSectionsProps,
8285
- beforeSections: beforeSectionsProps == null ? void 0 : beforeSectionsProps.map(rendererMapperProps.render),
8381
+ beforeSections: beforeSectionsProps.map(render),
8286
8382
  afterSectionsProps,
8287
- afterSections: afterSectionsProps == null ? void 0 : afterSectionsProps.map(rendererMapperProps.render)
8383
+ afterSections: afterSectionsProps.map(render)
8288
8384
  })
8289
8385
  });
8290
8386
  };
@@ -9150,6 +9246,9 @@ var rootComponentToProps = (rootComponent, rendererMapperProps, nativeSubflowHan
9150
9246
  }, rendererMapperProps);
9151
9247
  };
9152
9248
 
9249
+ // src/renderers/mappers/utils/mapRendererLoadingState.ts
9250
+ var mapRendererLoadingState = (loadingState) => loadingState === "delay-pending" ? "submitting" : loadingState;
9251
+
9153
9252
  // src/renderers/subflow/getNativeSubflowRenderer.tsx
9154
9253
  import { Fragment as Fragment6, jsx as jsx7 } from "react/jsx-runtime";
9155
9254
  var getNativeSubflowRenderer = (handlers) => {
@@ -9266,7 +9365,7 @@ function useDynamicFlow(props) {
9266
9365
  httpClient,
9267
9366
  trackEvent: (_b = rootComponent.getTrackEvent()) != null ? _b : (() => {
9268
9367
  }),
9269
- stepLoadingState: rootComponent.getLoadingState()
9368
+ stepLoadingState: mapRendererLoadingState(rootComponent.getLoadingState())
9270
9369
  },
9271
9370
  (_c = props.nativeSubflowHandlers) != null ? _c : []
9272
9371
  );