@wise/dynamic-flow-client 5.21.0 → 5.22.1

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 (38) hide show
  1. package/build/main.css +9 -0
  2. package/build/main.js +502 -105
  3. package/build/main.mjs +502 -105
  4. package/build/tsconfig.types.tsbuildinfo +1 -1
  5. package/build/types/domain/components/AlertComponent.d.ts +6 -2
  6. package/build/types/domain/components/AlertComponent.d.ts.map +1 -1
  7. package/build/types/domain/components/SectionComponent.d.ts +2 -1
  8. package/build/types/domain/components/SectionComponent.d.ts.map +1 -1
  9. package/build/types/domain/components/collectionComponent/CollectionComponent.d.ts +7 -0
  10. package/build/types/domain/components/collectionComponent/CollectionComponent.d.ts.map +1 -0
  11. package/build/types/domain/components/collectionComponent/types.d.ts +71 -0
  12. package/build/types/domain/components/collectionComponent/types.d.ts.map +1 -0
  13. package/build/types/domain/features/collection/getPerformCollectionQuery.d.ts +14 -0
  14. package/build/types/domain/features/collection/getPerformCollectionQuery.d.ts.map +1 -0
  15. package/build/types/domain/handlers/dismissHandler.d.ts +5 -0
  16. package/build/types/domain/handlers/dismissHandler.d.ts.map +1 -0
  17. package/build/types/domain/mappers/layout/alertLayoutToComponent.d.ts +1 -1
  18. package/build/types/domain/mappers/layout/alertLayoutToComponent.d.ts.map +1 -1
  19. package/build/types/domain/mappers/layout/collectionLayoutToComponent.d.ts +7 -0
  20. package/build/types/domain/mappers/layout/collectionLayoutToComponent.d.ts.map +1 -0
  21. package/build/types/domain/mappers/layout/sectionLayoutToComponent.d.ts +1 -1
  22. package/build/types/domain/mappers/layout/sectionLayoutToComponent.d.ts.map +1 -1
  23. package/build/types/domain/mappers/layout/upsellLayoutToComponent.d.ts.map +1 -1
  24. package/build/types/domain/mappers/mapLayoutToComponent.d.ts.map +1 -1
  25. package/build/types/domain/mappers/mapStepToComponent.d.ts.map +1 -1
  26. package/build/types/domain/mappers/utils/behavior-utils.d.ts.map +1 -1
  27. package/build/types/domain/types.d.ts +2 -1
  28. package/build/types/domain/types.d.ts.map +1 -1
  29. package/build/types/renderers/mappers/alertComponentToProps.d.ts.map +1 -1
  30. package/build/types/renderers/mappers/collectionComponentToProps.d.ts +5 -0
  31. package/build/types/renderers/mappers/collectionComponentToProps.d.ts.map +1 -0
  32. package/build/types/renderers/mappers/componentToRendererProps.d.ts.map +1 -1
  33. package/build/types/renderers/mappers/sectionComponentToProps.d.ts.map +1 -1
  34. package/build/types/test-utils/getMergedTestRenderers.d.ts +1 -1
  35. package/build/types/test-utils/getMergedTestRenderers.d.ts.map +1 -1
  36. package/build/types/utils/safe-parse-link.d.ts +2 -0
  37. package/build/types/utils/safe-parse-link.d.ts.map +1 -0
  38. package/package.json +4 -4
package/build/main.js CHANGED
@@ -883,6 +883,7 @@ var getChildren = (node) => {
883
883
  return node.tabs.flatMap((c) => c.childrenProps);
884
884
  case "alert":
885
885
  case "button":
886
+ case "collection":
886
887
  case "input-checkbox":
887
888
  case "input-date":
888
889
  case "decision":
@@ -1301,6 +1302,26 @@ var createAlertComponent = (props) => __spreadValues({
1301
1302
  kind: "layout"
1302
1303
  }, props);
1303
1304
 
1305
+ // src/domain/handlers/dismissHandler.ts
1306
+ var makeDismissHandler = (onDismiss, mapperProps) => () => {
1307
+ const { url, method, body, headers } = onDismiss;
1308
+ void mapperProps.httpClient(url, {
1309
+ method,
1310
+ body: method === "GET" ? void 0 : JSON.stringify(body),
1311
+ headers
1312
+ }).catch(() => {
1313
+ });
1314
+ };
1315
+
1316
+ // src/utils/safe-parse-link.ts
1317
+ var safeParseLink = (url) => {
1318
+ const parsed = URL.parse(url);
1319
+ if ((parsed == null ? void 0 : parsed.protocol) === "javascript:") {
1320
+ throw new Error("Javascript URLs are not allowed");
1321
+ }
1322
+ return url;
1323
+ };
1324
+
1304
1325
  // src/domain/mappers/utils/behavior-utils.ts
1305
1326
  var getDomainLayerBehavior = ({ action, behavior: specBehavior }, stepActions, registerSubmissionBehavior) => {
1306
1327
  if (specBehavior) {
@@ -1324,13 +1345,32 @@ var normaliseBehavior = (behavior, stepActions) => {
1324
1345
  onError: behavior.onError ? normaliseBehavior(behavior.onError, stepActions) : void 0
1325
1346
  });
1326
1347
  }
1348
+ if (behavior.type === "delay") {
1349
+ return {
1350
+ type: "none",
1351
+ track: false
1352
+ };
1353
+ }
1354
+ if (behavior.type === "dispatch-event") {
1355
+ return {
1356
+ type: "none",
1357
+ track: false
1358
+ };
1359
+ }
1360
+ if (behavior.type === "link") {
1361
+ return __spreadProps(__spreadValues({}, behavior), {
1362
+ type: "link",
1363
+ url: safeParseLink(behavior.url),
1364
+ track: true
1365
+ });
1366
+ }
1327
1367
  return __spreadProps(__spreadValues({}, behavior), { track: true });
1328
1368
  }
1329
1369
  if ("action" in behavior && behavior.action) {
1330
1370
  return actionToBehavior(behavior.action, stepActions);
1331
1371
  }
1332
1372
  if ("link" in behavior && behavior.link) {
1333
- return { type: "link", url: behavior.link.url, track: true };
1373
+ return { type: "link", url: safeParseLink(behavior.link.url), track: true };
1334
1374
  }
1335
1375
  return { type: "none", track: false };
1336
1376
  };
@@ -1454,20 +1494,25 @@ var alertLayoutToComponent = (uid, {
1454
1494
  context,
1455
1495
  callToAction,
1456
1496
  analyticsId,
1457
- tags
1458
- }, mapperProps) => {
1459
- const cta = callToAction ? getDomainLayerCallToAction(callToAction, mapperProps) : void 0;
1460
- return createAlertComponent({
1461
- uid,
1462
- analyticsId,
1463
- control,
1464
- markdown,
1465
- margin: margin != null ? margin : "md",
1466
- callToAction: cta,
1467
- context: mapLegacyContext(context != null ? context : "neutral"),
1468
- tags
1469
- });
1470
- };
1497
+ tags,
1498
+ title,
1499
+ media,
1500
+ onDismiss,
1501
+ secondaryCallToAction
1502
+ }, mapperProps) => createAlertComponent({
1503
+ uid,
1504
+ analyticsId,
1505
+ control,
1506
+ markdown,
1507
+ margin: margin != null ? margin : "md",
1508
+ callToAction: getDomainLayerCallToAction(callToAction, mapperProps),
1509
+ context: mapLegacyContext(context != null ? context : "neutral"),
1510
+ tags,
1511
+ title,
1512
+ media,
1513
+ dismiss: onDismiss ? makeDismissHandler(onDismiss, mapperProps) : void 0,
1514
+ secondaryCallToAction: getDomainLayerCallToAction(secondaryCallToAction, mapperProps)
1515
+ });
1471
1516
 
1472
1517
  // src/domain/components/BoxComponent.ts
1473
1518
  var createBoxComponent = (props) => __spreadProps(__spreadValues({}, props), {
@@ -1500,6 +1545,367 @@ var boxLayoutToComponent = (uid, { border = false, components, control, margin,
1500
1545
  )
1501
1546
  });
1502
1547
 
1548
+ // src/domain/mappers/utils/utils.ts
1549
+ var mapInlineAlert = (alert) => {
1550
+ return alert ? {
1551
+ content: alert.content,
1552
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1553
+ } : void 0;
1554
+ };
1555
+ var mapAdditionalInfo = (info, mapperProps) => {
1556
+ const { onBehavior, trackEvent, registerSubmissionBehavior } = mapperProps;
1557
+ if (info) {
1558
+ const behavior = getDomainLayerBehavior(info, [], registerSubmissionBehavior);
1559
+ const isLink = behavior.type === "link";
1560
+ return {
1561
+ text: info.text,
1562
+ href: isLink ? behavior.url : void 0,
1563
+ hrefWithTracking: getHrefWithTracking({
1564
+ behavior,
1565
+ onBehavior,
1566
+ trackEvent
1567
+ }),
1568
+ accessibilityDescription: info.accessibilityDescription,
1569
+ onClick: behavior.type === "none" ? void 0 : () => {
1570
+ void onBehavior(behavior);
1571
+ }
1572
+ };
1573
+ }
1574
+ return void 0;
1575
+ };
1576
+ var mapSchemaAlert = (alert) => {
1577
+ return alert ? {
1578
+ content: alert.markdown,
1579
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1580
+ } : void 0;
1581
+ };
1582
+
1583
+ // src/domain/components/utils/debounce.ts
1584
+ var debounce = (callback, waitMs) => {
1585
+ let timeoutId = null;
1586
+ let lastArgs = null;
1587
+ const clearTimer = () => {
1588
+ if (timeoutId !== null) {
1589
+ clearTimeout(timeoutId);
1590
+ timeoutId = null;
1591
+ }
1592
+ lastArgs = null;
1593
+ };
1594
+ const debouncedFn = (...args) => {
1595
+ lastArgs = args;
1596
+ if (timeoutId !== null) {
1597
+ clearTimeout(timeoutId);
1598
+ }
1599
+ timeoutId = setTimeout(() => {
1600
+ callback(...lastArgs);
1601
+ timeoutId = null;
1602
+ lastArgs = null;
1603
+ }, waitMs);
1604
+ };
1605
+ debouncedFn.cancel = () => {
1606
+ if (timeoutId !== null) {
1607
+ clearTimer();
1608
+ }
1609
+ };
1610
+ debouncedFn.flush = () => {
1611
+ if (timeoutId !== null) {
1612
+ callback(...lastArgs);
1613
+ clearTimer();
1614
+ }
1615
+ };
1616
+ return debouncedFn;
1617
+ };
1618
+
1619
+ // src/domain/components/collectionComponent/CollectionComponent.ts
1620
+ var DEBOUNCE_TIME = 800;
1621
+ var createCollectionComponent = (props, onComponentUpdate, queryFunction) => {
1622
+ const { uid, analyticsId, control, margin, tags, state } = props;
1623
+ const update = getInputUpdateFunction(onComponentUpdate);
1624
+ let abortController = new AbortController();
1625
+ const query = (mode) => {
1626
+ var _a, _b;
1627
+ abortController.abort();
1628
+ abortController = new AbortController();
1629
+ const { signal } = abortController;
1630
+ queryFunction({
1631
+ searchParam: (_a = component.state.search) == null ? void 0 : _a.param,
1632
+ query: (_b = component.state.search) == null ? void 0 : _b.query,
1633
+ cursor: mode === "pagination" ? component.state.nextCursor : void 0,
1634
+ signal,
1635
+ filters: component.state.filters
1636
+ }).then((response) => {
1637
+ if (!response) {
1638
+ return;
1639
+ }
1640
+ update(component, (draft) => {
1641
+ var _a2, _b2;
1642
+ draft.state = {
1643
+ sections: mode === "pagination" ? mergeSections(component.state.sections, response.sections) : response.sections,
1644
+ nextCursor: response.nextCursor,
1645
+ filters: response.filters ? mapFilters(response.filters) : component.state.filters,
1646
+ search: response.search ? mapSearch(response.search) : component.state.search,
1647
+ beforeSections: (_a2 = response.beforeSections) != null ? _a2 : component.state.beforeSections,
1648
+ afterSections: (_b2 = response.afterSections) != null ? _b2 : component.state.afterSections
1649
+ };
1650
+ draft.status = {
1651
+ type: "idle",
1652
+ loadMore: response.nextCursor ? paginate : void 0
1653
+ };
1654
+ });
1655
+ }).catch(() => {
1656
+ if (!signal.aborted) {
1657
+ 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) };
1664
+ });
1665
+ }
1666
+ });
1667
+ };
1668
+ const debouncedQuery = debounce(query, DEBOUNCE_TIME);
1669
+ const search = () => {
1670
+ abortController.abort();
1671
+ debouncedQuery("search");
1672
+ };
1673
+ const filter = () => {
1674
+ debouncedQuery("search");
1675
+ debouncedQuery.flush();
1676
+ };
1677
+ const paginate = () => query("pagination");
1678
+ const selectFilter = (filterIndex, optionIndex) => {
1679
+ var _a;
1680
+ const selected = (_a = component.state.filters) == null ? void 0 : _a[filterIndex];
1681
+ if (!selected) {
1682
+ return;
1683
+ }
1684
+ const currentValue = selected.options[optionIndex].selected;
1685
+ update(component, (draft) => {
1686
+ if (!draft.state.filters) {
1687
+ return;
1688
+ }
1689
+ const draftFilter = draft.state.filters[filterIndex];
1690
+ if (selected.multiSelect) {
1691
+ draftFilter.options[optionIndex].selected = !currentValue;
1692
+ } else {
1693
+ draftFilter.options.forEach((draftOption, index) => {
1694
+ draftOption.selected = index === optionIndex ? !currentValue : false;
1695
+ });
1696
+ }
1697
+ draft.status = { type: "loading", reason: "search" };
1698
+ });
1699
+ filter();
1700
+ };
1701
+ const mapFilters = (filters) => filters == null ? void 0 : filters.map((f, filterIndex) => {
1702
+ var _a;
1703
+ return __spreadProps(__spreadValues({}, f), {
1704
+ options: (_a = f.options) == null ? void 0 : _a.map((option, optionIndex) => {
1705
+ var _a2;
1706
+ return __spreadProps(__spreadValues({}, option), {
1707
+ selected: (_a2 = option.selected) != null ? _a2 : false,
1708
+ onSelect: () => selectFilter(filterIndex, optionIndex)
1709
+ });
1710
+ })
1711
+ });
1712
+ });
1713
+ const mapSearch = (searchConfig) => searchConfig ? __spreadProps(__spreadValues({
1714
+ query: ""
1715
+ }, searchConfig), {
1716
+ onChange(value) {
1717
+ update(component, (draft) => {
1718
+ if (draft.state.search) {
1719
+ draft.state.search.query = value;
1720
+ draft.status = { type: "loading", reason: "search" };
1721
+ }
1722
+ });
1723
+ search();
1724
+ }
1725
+ }) : void 0;
1726
+ const component = {
1727
+ type: "collection",
1728
+ kind: "layout",
1729
+ uid,
1730
+ analyticsId,
1731
+ control,
1732
+ margin,
1733
+ tags,
1734
+ status: {
1735
+ type: "idle",
1736
+ loadMore: state.nextCursor ? () => query("pagination") : void 0
1737
+ },
1738
+ state: __spreadProps(__spreadValues({}, state), {
1739
+ filters: mapFilters(state.filters),
1740
+ search: mapSearch(props.search)
1741
+ })
1742
+ };
1743
+ return component;
1744
+ };
1745
+ var mergeSections = (existing, incoming) => {
1746
+ const knownIds = new Set(existing.map((section) => section.id));
1747
+ const newSections = incoming.filter((section) => !knownIds.has(section.id));
1748
+ const merged = existing.map((section) => {
1749
+ const match = incoming.find((s) => s.id === section.id);
1750
+ if (!match) return section;
1751
+ return __spreadProps(__spreadValues({}, match), { items: [...section.items, ...match.items] });
1752
+ });
1753
+ return [...merged, ...newSections];
1754
+ };
1755
+
1756
+ // src/domain/features/collection/getPerformCollectionQuery.ts
1757
+ var getPerformCollectionQuery = (httpClient, baseRequest, mapState) => {
1758
+ let latestSuccessfulRequestHash = null;
1759
+ let latestSuccessfulResults = null;
1760
+ return async (props) => {
1761
+ const requestHash = hashRequest(props);
1762
+ if (requestHash !== latestSuccessfulRequestHash) {
1763
+ const response = await performRequest(baseRequest, props, httpClient);
1764
+ const results = await parseResponse(response);
1765
+ latestSuccessfulRequestHash = requestHash;
1766
+ const mappedState = mapState(results);
1767
+ latestSuccessfulResults = mappedState;
1768
+ return mappedState;
1769
+ }
1770
+ return latestSuccessfulResults;
1771
+ };
1772
+ };
1773
+ var performRequest = (request, queryProps, httpClient) => {
1774
+ const { url, method, body, headers } = request;
1775
+ if (method === "GET") {
1776
+ return httpClient(buildQueryURL(url, queryProps), {
1777
+ method,
1778
+ headers: __spreadProps(__spreadValues({}, headers), {
1779
+ "Content-Type": "application/json"
1780
+ }),
1781
+ signal: queryProps.signal
1782
+ });
1783
+ }
1784
+ return httpClient(url, {
1785
+ method,
1786
+ headers: __spreadProps(__spreadValues({}, headers), {
1787
+ "Content-Type": "application/json"
1788
+ }),
1789
+ signal: queryProps.signal,
1790
+ body: JSON.stringify(__spreadValues(__spreadValues({}, body && typeof body === "object" && !isArray(body) ? body : {}), buildRequestBody(queryProps)))
1791
+ });
1792
+ };
1793
+ var buildQueryURL = (url, { searchParam, query, cursor, filters = [] }) => {
1794
+ const [baseUrl, queryParams] = splitUrlAndParams(url);
1795
+ const params = new URLSearchParams(queryParams);
1796
+ if (searchParam && query) {
1797
+ params.append(searchParam, query);
1798
+ }
1799
+ if (cursor) {
1800
+ params.append("cursor", cursor);
1801
+ }
1802
+ getFilterValues(filters).forEach(([key, value]) => {
1803
+ if (typeof value === "string") {
1804
+ params.append(key, value);
1805
+ } else {
1806
+ value.forEach((v) => params.append(key, v));
1807
+ }
1808
+ });
1809
+ return `${baseUrl}?${params.toString()}`;
1810
+ };
1811
+ var splitUrlAndParams = (url) => {
1812
+ const [baseUrl, ...rest] = url.split("?");
1813
+ return [baseUrl, rest.join("")];
1814
+ };
1815
+ var buildRequestBody = ({
1816
+ searchParam,
1817
+ query,
1818
+ cursor,
1819
+ filters = []
1820
+ }) => __spreadProps(__spreadValues(__spreadValues({}, searchParam && query ? { [searchParam]: query } : {}), Object.fromEntries(getFilterValues(filters))), {
1821
+ cursor
1822
+ });
1823
+ var getFilterValues = (filters) => {
1824
+ return filters.map((filter) => {
1825
+ const { multiSelect, param } = filter;
1826
+ const values = filter.options.filter((option) => option.selected).map((option) => option.value);
1827
+ if (values.length === 0) {
1828
+ return void 0;
1829
+ }
1830
+ return [param, multiSelect ? values : values[0]];
1831
+ }).filter((value) => value !== void 0);
1832
+ };
1833
+ var parseResponse = async (response) => {
1834
+ if (response.ok) {
1835
+ const body = await response.json().catch(() => null);
1836
+ return body;
1837
+ }
1838
+ throw Error("error response");
1839
+ };
1840
+ var hashRequest = ({
1841
+ query,
1842
+ cursor,
1843
+ filters
1844
+ }) => JSON.stringify({ query, cursor, filters: getFilterValues(filters != null ? filters : []) });
1845
+
1846
+ // src/domain/mappers/layout/collectionLayoutToComponent.ts
1847
+ var collectionLayoutToComponent = (uid, { analyticsId, control, initialState, margin, search, tags, baseRequest }, mapperProps) => {
1848
+ const { httpClient, onComponentUpdate } = mapperProps;
1849
+ const mapLayout = (layout, index) => mapLayoutToComponent(`${uid}-collection-response-${index}`, layout, mapperProps, []);
1850
+ const mapState = (state) => mapCollectionSpecToDomainState(state, mapperProps, mapLayout);
1851
+ const queryFunction = getPerformCollectionQuery(httpClient, baseRequest, mapState);
1852
+ const component = createCollectionComponent(
1853
+ {
1854
+ uid,
1855
+ analyticsId,
1856
+ control,
1857
+ margin: margin != null ? margin : "md",
1858
+ tags,
1859
+ state: mapState(initialState),
1860
+ search
1861
+ },
1862
+ onComponentUpdate,
1863
+ queryFunction
1864
+ );
1865
+ return component;
1866
+ };
1867
+ var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
1868
+ var _a, _b, _c;
1869
+ return {
1870
+ sections: specState.sections.map((section) => {
1871
+ return {
1872
+ id: section.id,
1873
+ title: section.title,
1874
+ callToAction: getDomainLayerCallToAction(section.callToAction, mapperProps),
1875
+ items: section.items.map((item) => {
1876
+ const behavior = getDomainLayerBehavior(
1877
+ { behavior: item.primaryBehavior },
1878
+ [],
1879
+ mapperProps.registerSubmissionBehavior
1880
+ );
1881
+ return __spreadProps(__spreadValues({}, item), {
1882
+ id: item.entityId,
1883
+ onClick: item.primaryBehavior ? () => {
1884
+ void mapperProps.onBehavior(behavior);
1885
+ } : void 0,
1886
+ callToAction: getDomainLayerCallToAction(item.callToAction, mapperProps),
1887
+ inlineAlert: mapInlineAlert(item.inlineAlert)
1888
+ });
1889
+ })
1890
+ };
1891
+ }),
1892
+ filters: (_a = specState.filters) == null ? void 0 : _a.map((filter) => __spreadProps(__spreadValues({}, filter), {
1893
+ options: filter.options.map((option) => {
1894
+ var _a2;
1895
+ return __spreadProps(__spreadValues({}, option), {
1896
+ selected: (_a2 = option.selected) != null ? _a2 : false,
1897
+ onSelect: () => {
1898
+ }
1899
+ // noop - this gets added during mapping
1900
+ });
1901
+ })
1902
+ })),
1903
+ beforeSections: (_b = specState.beforeSections) == null ? void 0 : _b.map(mapLayout),
1904
+ afterSections: (_c = specState.afterSections) == null ? void 0 : _c.map(mapLayout),
1905
+ nextCursor: specState.nextCursor
1906
+ };
1907
+ };
1908
+
1503
1909
  // src/domain/components/ButtonComponent.ts
1504
1910
  var createButtonComponent = (props) => __spreadValues({
1505
1911
  type: "button",
@@ -1668,41 +2074,6 @@ var createDecisionComponent = (props) => __spreadValues({
1668
2074
  // src/domain/mappers/utils/tags-utils.ts
1669
2075
  var mapTags = ({ tag, tags }) => tags != null ? tags : tag != null ? [tag] : void 0;
1670
2076
 
1671
- // src/domain/mappers/utils/utils.ts
1672
- var mapInlineAlert = (alert) => {
1673
- return alert ? {
1674
- content: alert.content,
1675
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1676
- } : void 0;
1677
- };
1678
- var mapAdditionalInfo = (info, mapperProps) => {
1679
- const { onBehavior, trackEvent, registerSubmissionBehavior } = mapperProps;
1680
- if (info) {
1681
- const behavior = getDomainLayerBehavior(info, [], registerSubmissionBehavior);
1682
- const isLink = behavior.type === "link";
1683
- return {
1684
- text: info.text,
1685
- href: isLink ? behavior.url : void 0,
1686
- hrefWithTracking: getHrefWithTracking({
1687
- behavior,
1688
- onBehavior,
1689
- trackEvent
1690
- }),
1691
- accessibilityDescription: info.accessibilityDescription,
1692
- onClick: behavior.type === "none" ? void 0 : () => {
1693
- void onBehavior(behavior);
1694
- }
1695
- };
1696
- }
1697
- return void 0;
1698
- };
1699
- var mapSchemaAlert = (alert) => {
1700
- return alert ? {
1701
- content: alert.markdown,
1702
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1703
- } : void 0;
1704
- };
1705
-
1706
2077
  // src/domain/mappers/layout/decisionLayoutToComponent.ts
1707
2078
  var decisionLayoutToComponent = (uid, {
1708
2079
  analyticsId,
@@ -2178,44 +2549,8 @@ var mapReviewField = (field, mapperProps) => {
2178
2549
  });
2179
2550
  };
2180
2551
 
2181
- // src/domain/components/utils/debounce.ts
2182
- var debounce = (callback, waitMs) => {
2183
- let timeoutId = null;
2184
- let lastArgs = null;
2185
- const clearTimer = () => {
2186
- if (timeoutId !== null) {
2187
- clearTimeout(timeoutId);
2188
- timeoutId = null;
2189
- }
2190
- lastArgs = null;
2191
- };
2192
- const debouncedFn = (...args) => {
2193
- lastArgs = args;
2194
- if (timeoutId !== null) {
2195
- clearTimeout(timeoutId);
2196
- }
2197
- timeoutId = setTimeout(() => {
2198
- callback(...lastArgs);
2199
- timeoutId = null;
2200
- lastArgs = null;
2201
- }, waitMs);
2202
- };
2203
- debouncedFn.cancel = () => {
2204
- if (timeoutId !== null) {
2205
- clearTimer();
2206
- }
2207
- };
2208
- debouncedFn.flush = () => {
2209
- if (timeoutId !== null) {
2210
- callback(...lastArgs);
2211
- clearTimer();
2212
- }
2213
- };
2214
- return debouncedFn;
2215
- };
2216
-
2217
2552
  // src/domain/components/searchComponent/SearchComponent.ts
2218
- var DEBOUNCE_TIME = 400;
2553
+ var DEBOUNCE_TIME2 = 400;
2219
2554
  var createSearchComponent = (props, performSearch, onBehavior, onComponentUpdate) => {
2220
2555
  const { uid, analyticsId, control, emptyMessage, initialState, hint, margin, tags, title } = props;
2221
2556
  const update = getInputUpdateFunction(onComponentUpdate);
@@ -2245,7 +2580,7 @@ var createSearchComponent = (props, performSearch, onBehavior, onComponentUpdate
2245
2580
  }
2246
2581
  });
2247
2582
  };
2248
- const debouncedSearch = debounce(search, DEBOUNCE_TIME);
2583
+ const debouncedSearch = debounce(search, DEBOUNCE_TIME2);
2249
2584
  const component = {
2250
2585
  type: "search",
2251
2586
  kind: "layout",
@@ -2300,10 +2635,10 @@ var createSearchComponent = (props, performSearch, onBehavior, onComponentUpdate
2300
2635
 
2301
2636
  // src/domain/features/search/getPerformSearchFunction.ts
2302
2637
  var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultConfig) => {
2303
- let latestSuccessfulRequestHash = hashRequest("", defaultConfig);
2638
+ let latestSuccessfulRequestHash = hashRequest2("", defaultConfig);
2304
2639
  let latestSuccessfulResults = null;
2305
2640
  return async ({ config = defaultConfig, query, signal }) => {
2306
- const requestHash = hashRequest(query, config);
2641
+ const requestHash = hashRequest2(query, config);
2307
2642
  if (requestHash !== latestSuccessfulRequestHash) {
2308
2643
  const { method, param, url } = config;
2309
2644
  const headers = { "Content-Type": "application/json" };
@@ -2317,7 +2652,7 @@ var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultC
2317
2652
  signal,
2318
2653
  body: JSON.stringify({ [param]: query })
2319
2654
  }));
2320
- const results = await parseResponse(response);
2655
+ const results = await parseResponse2(response);
2321
2656
  latestSuccessfulRequestHash = requestHash;
2322
2657
  if (results.type === "layout") {
2323
2658
  const mappedLayoutResult = {
@@ -2333,7 +2668,7 @@ var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultC
2333
2668
  return latestSuccessfulResults;
2334
2669
  };
2335
2670
  };
2336
- var parseResponse = async (response) => {
2671
+ var parseResponse2 = async (response) => {
2337
2672
  if (response.ok) {
2338
2673
  const body = await response.json().catch(() => null);
2339
2674
  if (isValidResponseBody(body)) {
@@ -2370,7 +2705,7 @@ var isValidResponseBody = (body) => {
2370
2705
  }
2371
2706
  return false;
2372
2707
  };
2373
- var hashRequest = (query, config) => JSON.stringify({ query, config });
2708
+ var hashRequest2 = (query, config) => JSON.stringify({ query, config });
2374
2709
 
2375
2710
  // src/domain/mappers/layout/searchLayoutToComponent.ts
2376
2711
  var searchLayoutToComponent = (uid, {
@@ -2447,12 +2782,22 @@ var createSectionComponent = (props) => __spreadProps(__spreadValues({}, props),
2447
2782
  });
2448
2783
 
2449
2784
  // src/domain/mappers/layout/sectionLayoutToComponent.ts
2450
- var sectionLayoutToComponent = (uid, { analyticsId, control, title, components, callToAction, margin, tags }, mapperProps, schemaComponents) => {
2785
+ var sectionLayoutToComponent = (uid, {
2786
+ analyticsId,
2787
+ control,
2788
+ shortTitle,
2789
+ title,
2790
+ components,
2791
+ callToAction,
2792
+ margin,
2793
+ tags
2794
+ }, mapperProps, schemaComponents) => {
2451
2795
  return createSectionComponent({
2452
2796
  uid,
2453
2797
  analyticsId,
2454
2798
  control,
2455
2799
  title,
2800
+ shortTitle,
2456
2801
  components: components.map(
2457
2802
  (component, index) => mapLayoutToComponent(`${uid}.section-${index}`, component, mapperProps, schemaComponents)
2458
2803
  ),
@@ -2536,12 +2881,7 @@ var upsellLayoutToComponent = (uid, { analyticsId, callToAction, control, margin
2536
2881
  media: getDomainLayerMedia({ media }),
2537
2882
  tags,
2538
2883
  text,
2539
- dismiss: onDismiss ? () => {
2540
- const { url, method } = onDismiss;
2541
- const body = method === "GET" ? void 0 : JSON.stringify(onDismiss.body);
2542
- void mapperProps.httpClient(url, { method, body }).catch(() => {
2543
- });
2544
- } : void 0
2884
+ dismiss: onDismiss ? makeDismissHandler(onDismiss, mapperProps) : void 0
2545
2885
  },
2546
2886
  onComponentUpdate
2547
2887
  );
@@ -2556,6 +2896,8 @@ var mapLayoutToComponent = (uid, layout, mapperProps, schemaComponents) => {
2556
2896
  return boxLayoutToComponent(uid, layout, mapperProps, schemaComponents);
2557
2897
  case "button":
2558
2898
  return buttonLayoutToComponent(uid, layout, mapperProps);
2899
+ case "collection":
2900
+ return collectionLayoutToComponent(uid, layout, mapperProps);
2559
2901
  case "columns":
2560
2902
  return columnsLayoutToComponent(uid, layout, mapperProps, schemaComponents);
2561
2903
  case "decision":
@@ -6610,7 +6952,7 @@ var getExternalConfiguration = (uid, external, onLoad, mapperProps) => {
6610
6952
  if (onLoad.type === "link") {
6611
6953
  return createExternalConfirmation(
6612
6954
  `${uid}-external-confirmation`,
6613
- onLoad == null ? void 0 : onLoad.url,
6955
+ safeParseLink(onLoad.url),
6614
6956
  mapperProps.onLink,
6615
6957
  mapperProps.onComponentUpdate
6616
6958
  );
@@ -6618,7 +6960,7 @@ var getExternalConfiguration = (uid, external, onLoad, mapperProps) => {
6618
6960
  if ((external == null ? void 0 : external.url) && onLoad.type === "none") {
6619
6961
  return createExternalConfirmation(
6620
6962
  `${uid}-external-confirmation`,
6621
- external == null ? void 0 : external.url,
6963
+ safeParseLink(external.url),
6622
6964
  mapperProps.onLink,
6623
6965
  mapperProps.onComponentUpdate
6624
6966
  );
@@ -7809,8 +8151,22 @@ function pick(obj, ...keys) {
7809
8151
  }
7810
8152
 
7811
8153
  // src/renderers/mappers/alertComponentToProps.ts
7812
- var alertComponentToProps = (component, rendererMapperProps) => __spreadValues(__spreadProps(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "context", "control", "margin", "markdown", "tags")), {
7813
- callToAction: mapCallToActionOptional(component.callToAction)
8154
+ var alertComponentToProps = (component, rendererMapperProps) => __spreadValues(__spreadProps(__spreadValues({}, pick(
8155
+ component,
8156
+ "uid",
8157
+ "analyticsId",
8158
+ "type",
8159
+ "context",
8160
+ "control",
8161
+ "margin",
8162
+ "markdown",
8163
+ "media",
8164
+ "tags",
8165
+ "title"
8166
+ )), {
8167
+ callToAction: mapCallToActionOptional(component.callToAction),
8168
+ onDismiss: component.dismiss,
8169
+ secondaryCallToAction: mapCallToActionOptional(component.secondaryCallToAction)
7814
8170
  }), rendererMapperProps);
7815
8171
 
7816
8172
  // src/renderers/mappers/allOfComponentToProps.ts
@@ -7929,6 +8285,35 @@ var mapBoxControl = ({
7929
8285
  return control;
7930
8286
  };
7931
8287
 
8288
+ // src/renderers/mappers/collectionComponentToProps.ts
8289
+ var collectionComponentToProps = (component, rendererMapperProps) => {
8290
+ var _a, _b, _c;
8291
+ const beforeSectionsProps = (_a = component.state.beforeSections) == null ? void 0 : _a.map(
8292
+ (child) => componentToRendererProps(child, rendererMapperProps)
8293
+ );
8294
+ const afterSectionsProps = (_b = component.state.afterSections) == null ? void 0 : _b.map(
8295
+ (child) => componentToRendererProps(child, rendererMapperProps)
8296
+ );
8297
+ return __spreadProps(__spreadValues(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "control", "margin", "tags")), rendererMapperProps), {
8298
+ status: component.status,
8299
+ state: __spreadProps(__spreadValues({}, component.state), {
8300
+ filters: (_c = component.state.filters) != null ? _c : [],
8301
+ sections: component.state.sections.map((section) => __spreadProps(__spreadValues({}, section), {
8302
+ callToAction: mapCallToActionOptional(section.callToAction),
8303
+ items: section.items.map((item) => __spreadProps(__spreadValues({}, item), {
8304
+ callToAction: mapCallToActionOptional(item.callToAction),
8305
+ additionalInfo: mapAdditionalInfo2(item.additionalInfo),
8306
+ disabled: rendererMapperProps.stepLoadingState !== "idle" || item.disabled
8307
+ }))
8308
+ })),
8309
+ beforeSectionsProps,
8310
+ beforeSections: beforeSectionsProps == null ? void 0 : beforeSectionsProps.map(rendererMapperProps.render),
8311
+ afterSectionsProps,
8312
+ afterSections: afterSectionsProps == null ? void 0 : afterSectionsProps.map(rendererMapperProps.render)
8313
+ })
8314
+ });
8315
+ };
8316
+
7932
8317
  // src/renderers/mappers/buttonComponentToProps.ts
7933
8318
  var buttonComponentToProps = (component, rendererMapperProps) => {
7934
8319
  return __spreadValues(__spreadProps(__spreadValues({
@@ -8416,7 +8801,17 @@ var sectionComponentToProps = (component, rendererMapperProps) => {
8416
8801
  const childrenProps = component.components.map(
8417
8802
  (c) => componentToRendererProps(c, rendererMapperProps)
8418
8803
  );
8419
- return __spreadProps(__spreadValues(__spreadProps(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "title", "margin", "control", "tags")), {
8804
+ return __spreadProps(__spreadValues(__spreadProps(__spreadValues({}, pick(
8805
+ component,
8806
+ "uid",
8807
+ "analyticsId",
8808
+ "type",
8809
+ "shortTitle",
8810
+ "title",
8811
+ "margin",
8812
+ "control",
8813
+ "tags"
8814
+ )), {
8420
8815
  callToAction: mapCallToActionOptional(component.callToAction)
8421
8816
  }), rendererMapperProps), {
8422
8817
  children: childrenProps.map(rendererMapperProps.render),
@@ -8558,6 +8953,8 @@ var getComponentProps = (component, rendererMapperProps) => {
8558
8953
  return boxComponentToProps(component, rendererMapperProps);
8559
8954
  case "button":
8560
8955
  return buttonComponentToProps(component, rendererMapperProps);
8956
+ case "collection":
8957
+ return collectionComponentToProps(component, rendererMapperProps);
8561
8958
  case "columns":
8562
8959
  return columnsComponentToProps(component, rendererMapperProps);
8563
8960
  case "container":