@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.js CHANGED
@@ -1204,6 +1204,15 @@ var createRootDomainComponent = (onComponentUpdate, scrollToTop, backConfig, req
1204
1204
  const navigation = (_a = component.getStep()) == null ? void 0 : _a.step.navigation;
1205
1205
  const stepHasBehavior = Boolean((_b = navigation == null ? void 0 : navigation.back) != null ? _b : navigation == null ? void 0 : navigation.backButton);
1206
1206
  return component.backConfig.isFlowCancellable || component.stepStack.length > 1 && component.backConfig.isNativeBackEnabled || stepHasBehavior;
1207
+ },
1208
+ startDelay(delay) {
1209
+ var _a, _b;
1210
+ return (_b = (_a = component.getStep()) == null ? void 0 : _a.startDelay(delay)) != null ? _b : { abort: () => {
1211
+ } };
1212
+ },
1213
+ setExternalConfirmation(external) {
1214
+ var _a;
1215
+ (_a = component.getStep()) == null ? void 0 : _a.setExternalConfirmation(external);
1207
1216
  }
1208
1217
  };
1209
1218
  return component;
@@ -1346,10 +1355,10 @@ var normaliseBehavior = (behavior, stepActions) => {
1346
1355
  });
1347
1356
  }
1348
1357
  if (behavior.type === "delay") {
1349
- return {
1350
- type: "none",
1358
+ return __spreadProps(__spreadValues({}, behavior), {
1359
+ behavior: normaliseBehavior(behavior.behavior, stepActions),
1351
1360
  track: false
1352
- };
1361
+ });
1353
1362
  }
1354
1363
  if (behavior.type === "dispatch-event") {
1355
1364
  return {
@@ -1545,11 +1554,36 @@ var boxLayoutToComponent = (uid, { border = false, components, control, margin,
1545
1554
  )
1546
1555
  });
1547
1556
 
1557
+ // src/domain/mappers/utils/image.ts
1558
+ var mapSpecImage = (image) => {
1559
+ var _a, _b, _c;
1560
+ return image ? {
1561
+ uri: (_b = (_a = image.uri) != null ? _a : image.url) != null ? _b : "",
1562
+ accessibilityDescription: (_c = image.accessibilityDescription) != null ? _c : image.text
1563
+ } : void 0;
1564
+ };
1565
+
1566
+ // src/domain/mappers/utils/media-utils.ts
1567
+ var getDomainLayerMedia = ({ icon, image, media }) => {
1568
+ if (media) {
1569
+ return media;
1570
+ }
1571
+ if (icon || image) {
1572
+ return {
1573
+ type: "legacy",
1574
+ icon,
1575
+ image: mapSpecImage(image)
1576
+ };
1577
+ }
1578
+ return void 0;
1579
+ };
1580
+
1548
1581
  // src/domain/mappers/utils/utils.ts
1549
1582
  var mapInlineAlert = (alert) => {
1550
1583
  return alert ? {
1551
1584
  content: alert.content,
1552
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1585
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral",
1586
+ media: getDomainLayerMedia({ media: alert.media })
1553
1587
  } : void 0;
1554
1588
  };
1555
1589
  var mapAdditionalInfo = (info, mapperProps) => {
@@ -1576,7 +1610,8 @@ var mapAdditionalInfo = (info, mapperProps) => {
1576
1610
  var mapSchemaAlert = (alert) => {
1577
1611
  return alert ? {
1578
1612
  content: alert.markdown,
1579
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1613
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral",
1614
+ media: getDomainLayerMedia({ media: alert.media })
1580
1615
  } : void 0;
1581
1616
  };
1582
1617
 
@@ -1654,13 +1689,17 @@ var createCollectionComponent = (props, onComponentUpdate, queryFunction) => {
1654
1689
  });
1655
1690
  }).catch(() => {
1656
1691
  if (!signal.aborted) {
1692
+ const retry = () => {
1693
+ update(component, (draft) => {
1694
+ draft.status = { type: "loading", reason: mode };
1695
+ });
1696
+ query(mode);
1697
+ };
1657
1698
  update(component, (draft) => {
1658
- draft.state = {
1659
- filters: component.state.filters,
1660
- search: component.state.search,
1661
- sections: []
1662
- };
1663
- draft.status = { type: "error", reason: mode, retry: () => query(mode) };
1699
+ if (mode === "search") {
1700
+ draft.state.sections = [];
1701
+ }
1702
+ draft.status = { type: "error", reason: mode, retry };
1664
1703
  });
1665
1704
  }
1666
1705
  });
@@ -1746,13 +1785,15 @@ var mergeSections = (existing, incoming) => {
1746
1785
  const knownIds = new Set(existing.map((section) => section.id));
1747
1786
  const newSections = incoming.filter((section) => !knownIds.has(section.id));
1748
1787
  const merged = existing.map((section) => {
1749
- var _a, _b;
1788
+ var _a, _b, _c, _d;
1750
1789
  const match = incoming.find((s) => s.id === section.id);
1751
1790
  if (!match) return section;
1752
1791
  return {
1753
1792
  id: match.id,
1754
1793
  title: (_a = match.title) != null ? _a : section.title,
1755
1794
  callToAction: (_b = match.callToAction) != null ? _b : section.callToAction,
1795
+ help: (_c = match.help) != null ? _c : section.help,
1796
+ inlineAlert: (_d = match.inlineAlert) != null ? _d : section.inlineAlert,
1756
1797
  items: [...section.items, ...match.items]
1757
1798
  };
1758
1799
  });
@@ -1871,13 +1912,14 @@ var collectionLayoutToComponent = (uid, { analyticsId, control, initialState, ma
1871
1912
  return component;
1872
1913
  };
1873
1914
  var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
1874
- var _a, _b, _c;
1915
+ const { sections, filters, beforeSections, afterSections, nextCursor } = specState;
1875
1916
  return {
1876
- sections: specState.sections.map((section) => {
1877
- return {
1878
- id: section.id,
1879
- title: section.title,
1917
+ sections: sections.map((section) => {
1918
+ var _a;
1919
+ return __spreadProps(__spreadValues({}, section), {
1880
1920
  callToAction: getDomainLayerCallToAction(section.callToAction, mapperProps),
1921
+ help: (_a = section.help) == null ? void 0 : _a.markdown,
1922
+ inlineAlert: mapInlineAlert(section.inlineAlert),
1881
1923
  items: section.items.map((item) => {
1882
1924
  const behavior = getDomainLayerBehavior(
1883
1925
  { behavior: item.primaryBehavior },
@@ -1893,24 +1935,29 @@ var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
1893
1935
  inlineAlert: mapInlineAlert(item.inlineAlert)
1894
1936
  });
1895
1937
  })
1896
- };
1938
+ });
1897
1939
  }),
1898
- filters: (_a = specState.filters) == null ? void 0 : _a.map((filter) => __spreadProps(__spreadValues({}, filter), {
1899
- options: filter.options.map((option) => {
1900
- var _a2;
1901
- return __spreadProps(__spreadValues({}, option), {
1902
- selected: (_a2 = option.selected) != null ? _a2 : false,
1903
- onSelect: () => {
1904
- }
1905
- // noop - this gets added during mapping
1906
- });
1907
- })
1908
- })),
1909
- beforeSections: (_b = specState.beforeSections) == null ? void 0 : _b.map(mapLayout),
1910
- afterSections: (_c = specState.afterSections) == null ? void 0 : _c.map(mapLayout),
1911
- nextCursor: specState.nextCursor
1940
+ filters: filters == null ? void 0 : filters.map(mapFilter),
1941
+ beforeSections: beforeSections == null ? void 0 : beforeSections.map(mapLayout),
1942
+ afterSections: afterSections == null ? void 0 : afterSections.map(mapLayout),
1943
+ nextCursor
1912
1944
  };
1913
1945
  };
1946
+ var mapFilter = (filter) => {
1947
+ const anySelected = filter.options.some((option) => option.selected);
1948
+ return __spreadProps(__spreadValues({}, filter), {
1949
+ options: filter.options.map((option, index) => {
1950
+ var _a;
1951
+ return __spreadProps(__spreadValues({}, option), {
1952
+ // if a single select with no selection, we should default to selecting the first item
1953
+ selected: filter.multiSelect || anySelected ? (_a = option.selected) != null ? _a : false : index === 0,
1954
+ onSelect: () => {
1955
+ }
1956
+ // noop - this gets added during mapping in the component itself
1957
+ });
1958
+ })
1959
+ });
1960
+ };
1914
1961
 
1915
1962
  // src/domain/components/ButtonComponent.ts
1916
1963
  var createButtonComponent = (props) => __spreadValues({
@@ -1918,30 +1965,6 @@ var createButtonComponent = (props) => __spreadValues({
1918
1965
  kind: "layout"
1919
1966
  }, props);
1920
1967
 
1921
- // src/domain/mappers/utils/image.ts
1922
- var mapSpecImage = (image) => {
1923
- var _a, _b, _c;
1924
- return image ? {
1925
- uri: (_b = (_a = image.uri) != null ? _a : image.url) != null ? _b : "",
1926
- accessibilityDescription: (_c = image.accessibilityDescription) != null ? _c : image.text
1927
- } : void 0;
1928
- };
1929
-
1930
- // src/domain/mappers/utils/media-utils.ts
1931
- var getDomainLayerMedia = ({ icon, image, media }) => {
1932
- if (media) {
1933
- return media;
1934
- }
1935
- if (icon || image) {
1936
- return {
1937
- type: "legacy",
1938
- icon,
1939
- image: mapSpecImage(image)
1940
- };
1941
- }
1942
- return void 0;
1943
- };
1944
-
1945
1968
  // src/domain/mappers/layout/buttonLayoutToComponent.ts
1946
1969
  var buttonLayoutToComponent = (uid, button, mapperProps) => {
1947
1970
  if (!button.behavior && !button.action && mapperProps.features.isEnabled("strictButtonOperations")) {
@@ -3035,6 +3058,45 @@ var getSubmittableData = async (components) => Promise.all(components.map(async
3035
3058
  var getSubmittableDataSync = (components) => components.map((component) => component.getSubmittableValueSync()).reduce((acc, value) => recursiveMerge(acc, value), null);
3036
3059
  var getLocalValues = (components) => components.map((component) => component.getLocalValue()).reduce((acc, value) => recursiveMerge(acc, value), null);
3037
3060
 
3061
+ // src/domain/features/delay/getStepDelays.ts
3062
+ var getStepDelays = (onEmpty) => {
3063
+ let timeouts = [];
3064
+ const remove = (timeout) => {
3065
+ timeouts = timeouts.filter((pendingTimeout) => pendingTimeout !== timeout);
3066
+ };
3067
+ return {
3068
+ start({ duration, execute }) {
3069
+ const timeout = setTimeout(() => {
3070
+ if (timeouts.includes(timeout)) {
3071
+ remove(timeout);
3072
+ execute();
3073
+ }
3074
+ if (timeouts.length === 0) {
3075
+ onEmpty();
3076
+ }
3077
+ }, duration * 1e3);
3078
+ timeouts = [...timeouts, timeout];
3079
+ return {
3080
+ abort: () => {
3081
+ clearTimeout(timeout);
3082
+ remove(timeout);
3083
+ if (timeouts.length === 0) {
3084
+ onEmpty();
3085
+ }
3086
+ }
3087
+ };
3088
+ },
3089
+ stop() {
3090
+ if (timeouts.length === 0) {
3091
+ return;
3092
+ }
3093
+ timeouts.forEach(clearTimeout);
3094
+ timeouts = [];
3095
+ onEmpty();
3096
+ }
3097
+ };
3098
+ };
3099
+
3038
3100
  // src/domain/components/step/StepDomainComponent.ts
3039
3101
  var createStepComponent = (props) => {
3040
3102
  const _a = props, {
@@ -3057,6 +3119,14 @@ var createStepComponent = (props) => {
3057
3119
  "onLoad"
3058
3120
  ]);
3059
3121
  const update = getInputUpdateFunction(onComponentUpdate);
3122
+ const resetDelayState = () => {
3123
+ if (component.loadingState === "delay-pending") {
3124
+ update(component, (draft) => {
3125
+ draft.loadingState = "idle";
3126
+ });
3127
+ }
3128
+ };
3129
+ const stepDelays = getStepDelays(resetDelayState);
3060
3130
  const component = __spreadProps(__spreadValues({
3061
3131
  uid
3062
3132
  }, rest), {
@@ -3106,6 +3176,10 @@ var createStepComponent = (props) => {
3106
3176
  draft.loadingState = loadingState;
3107
3177
  });
3108
3178
  },
3179
+ startDelay(delay) {
3180
+ component.setLoadingState("delay-pending");
3181
+ return stepDelays.start(delay);
3182
+ },
3109
3183
  addSubflow(subflow) {
3110
3184
  update(component, (draft) => {
3111
3185
  draft.subflow = subflow;
@@ -3133,11 +3207,17 @@ var createStepComponent = (props) => {
3133
3207
  stop() {
3134
3208
  stepPolling == null ? void 0 : stepPolling.stop();
3135
3209
  stepRefreshAfter == null ? void 0 : stepRefreshAfter.stop();
3210
+ stepDelays.stop();
3136
3211
  stepPrefetch.stop();
3137
3212
  update(component, (draft) => {
3138
3213
  draft.state = "stopped";
3139
3214
  draft.modals = [];
3140
3215
  });
3216
+ },
3217
+ setExternalConfirmation(external) {
3218
+ update(component, (draft) => {
3219
+ draft.externalConfirmation = external;
3220
+ });
3141
3221
  }
3142
3222
  });
3143
3223
  return component;
@@ -7523,6 +7603,14 @@ var createFlowController = (props) => {
7523
7603
  var _a;
7524
7604
  trackBehaviorTriggered(trackEvent, behavior);
7525
7605
  switch (behavior.type) {
7606
+ case "delay": {
7607
+ return rootComponent.startDelay({
7608
+ duration: behavior.duration,
7609
+ execute: () => {
7610
+ void onBehavior(behavior.behavior);
7611
+ }
7612
+ });
7613
+ }
7526
7614
  case "download": {
7527
7615
  try {
7528
7616
  await executeDownload(behavior.request, httpClient);
@@ -7593,7 +7681,14 @@ var createFlowController = (props) => {
7593
7681
  };
7594
7682
  }
7595
7683
  case "link": {
7596
- onLink(behavior.url);
7684
+ rootComponent.setExternalConfirmation(
7685
+ createExternalConfirmation(
7686
+ `${rootComponent.uid}-external-confirmation`,
7687
+ behavior.url,
7688
+ onLink,
7689
+ onChange
7690
+ )
7691
+ );
7597
7692
  break;
7598
7693
  }
7599
7694
  case "modal": {
@@ -8293,17 +8388,18 @@ var mapBoxControl = ({
8293
8388
 
8294
8389
  // src/renderers/mappers/collectionComponentToProps.ts
8295
8390
  var collectionComponentToProps = (component, rendererMapperProps) => {
8296
- var _a, _b, _c;
8297
- const beforeSectionsProps = (_a = component.state.beforeSections) == null ? void 0 : _a.map(
8391
+ var _a, _b, _c, _d, _e;
8392
+ const { render } = rendererMapperProps;
8393
+ const beforeSectionsProps = (_b = (_a = component.state.beforeSections) == null ? void 0 : _a.map(
8298
8394
  (child) => componentToRendererProps(child, rendererMapperProps)
8299
- );
8300
- const afterSectionsProps = (_b = component.state.afterSections) == null ? void 0 : _b.map(
8395
+ )) != null ? _b : [];
8396
+ const afterSectionsProps = (_d = (_c = component.state.afterSections) == null ? void 0 : _c.map(
8301
8397
  (child) => componentToRendererProps(child, rendererMapperProps)
8302
- );
8398
+ )) != null ? _d : [];
8303
8399
  return __spreadProps(__spreadValues(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "control", "margin", "tags")), rendererMapperProps), {
8304
8400
  status: component.status,
8305
8401
  state: __spreadProps(__spreadValues({}, component.state), {
8306
- filters: (_c = component.state.filters) != null ? _c : [],
8402
+ filters: (_e = component.state.filters) != null ? _e : [],
8307
8403
  sections: component.state.sections.map((section) => __spreadProps(__spreadValues({}, section), {
8308
8404
  callToAction: mapCallToActionOptional(section.callToAction),
8309
8405
  items: section.items.map((item) => __spreadProps(__spreadValues({}, item), {
@@ -8313,9 +8409,9 @@ var collectionComponentToProps = (component, rendererMapperProps) => {
8313
8409
  }))
8314
8410
  })),
8315
8411
  beforeSectionsProps,
8316
- beforeSections: beforeSectionsProps == null ? void 0 : beforeSectionsProps.map(rendererMapperProps.render),
8412
+ beforeSections: beforeSectionsProps.map(render),
8317
8413
  afterSectionsProps,
8318
- afterSections: afterSectionsProps == null ? void 0 : afterSectionsProps.map(rendererMapperProps.render)
8414
+ afterSections: afterSectionsProps.map(render)
8319
8415
  })
8320
8416
  });
8321
8417
  };
@@ -9181,6 +9277,9 @@ var rootComponentToProps = (rootComponent, rendererMapperProps, nativeSubflowHan
9181
9277
  }, rendererMapperProps);
9182
9278
  };
9183
9279
 
9280
+ // src/renderers/mappers/utils/mapRendererLoadingState.ts
9281
+ var mapRendererLoadingState = (loadingState) => loadingState === "delay-pending" ? "submitting" : loadingState;
9282
+
9184
9283
  // src/renderers/subflow/getNativeSubflowRenderer.tsx
9185
9284
  var import_jsx_runtime7 = require("react/jsx-runtime");
9186
9285
  var getNativeSubflowRenderer = (handlers) => {
@@ -9297,7 +9396,7 @@ function useDynamicFlow(props) {
9297
9396
  httpClient,
9298
9397
  trackEvent: (_b = rootComponent.getTrackEvent()) != null ? _b : (() => {
9299
9398
  }),
9300
- stepLoadingState: rootComponent.getLoadingState()
9399
+ stepLoadingState: mapRendererLoadingState(rootComponent.getLoadingState())
9301
9400
  },
9302
9401
  (_c = props.nativeSubflowHandlers) != null ? _c : []
9303
9402
  );