@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.mjs CHANGED
@@ -852,6 +852,7 @@ var getChildren = (node) => {
852
852
  return node.tabs.flatMap((c) => c.childrenProps);
853
853
  case "alert":
854
854
  case "button":
855
+ case "collection":
855
856
  case "input-checkbox":
856
857
  case "input-date":
857
858
  case "decision":
@@ -1270,6 +1271,26 @@ var createAlertComponent = (props) => __spreadValues({
1270
1271
  kind: "layout"
1271
1272
  }, props);
1272
1273
 
1274
+ // src/domain/handlers/dismissHandler.ts
1275
+ var makeDismissHandler = (onDismiss, mapperProps) => () => {
1276
+ const { url, method, body, headers } = onDismiss;
1277
+ void mapperProps.httpClient(url, {
1278
+ method,
1279
+ body: method === "GET" ? void 0 : JSON.stringify(body),
1280
+ headers
1281
+ }).catch(() => {
1282
+ });
1283
+ };
1284
+
1285
+ // src/utils/safe-parse-link.ts
1286
+ var safeParseLink = (url) => {
1287
+ const parsed = URL.parse(url);
1288
+ if ((parsed == null ? void 0 : parsed.protocol) === "javascript:") {
1289
+ throw new Error("Javascript URLs are not allowed");
1290
+ }
1291
+ return url;
1292
+ };
1293
+
1273
1294
  // src/domain/mappers/utils/behavior-utils.ts
1274
1295
  var getDomainLayerBehavior = ({ action, behavior: specBehavior }, stepActions, registerSubmissionBehavior) => {
1275
1296
  if (specBehavior) {
@@ -1293,13 +1314,32 @@ var normaliseBehavior = (behavior, stepActions) => {
1293
1314
  onError: behavior.onError ? normaliseBehavior(behavior.onError, stepActions) : void 0
1294
1315
  });
1295
1316
  }
1317
+ if (behavior.type === "delay") {
1318
+ return {
1319
+ type: "none",
1320
+ track: false
1321
+ };
1322
+ }
1323
+ if (behavior.type === "dispatch-event") {
1324
+ return {
1325
+ type: "none",
1326
+ track: false
1327
+ };
1328
+ }
1329
+ if (behavior.type === "link") {
1330
+ return __spreadProps(__spreadValues({}, behavior), {
1331
+ type: "link",
1332
+ url: safeParseLink(behavior.url),
1333
+ track: true
1334
+ });
1335
+ }
1296
1336
  return __spreadProps(__spreadValues({}, behavior), { track: true });
1297
1337
  }
1298
1338
  if ("action" in behavior && behavior.action) {
1299
1339
  return actionToBehavior(behavior.action, stepActions);
1300
1340
  }
1301
1341
  if ("link" in behavior && behavior.link) {
1302
- return { type: "link", url: behavior.link.url, track: true };
1342
+ return { type: "link", url: safeParseLink(behavior.link.url), track: true };
1303
1343
  }
1304
1344
  return { type: "none", track: false };
1305
1345
  };
@@ -1423,20 +1463,25 @@ var alertLayoutToComponent = (uid, {
1423
1463
  context,
1424
1464
  callToAction,
1425
1465
  analyticsId,
1426
- tags
1427
- }, mapperProps) => {
1428
- const cta = callToAction ? getDomainLayerCallToAction(callToAction, mapperProps) : void 0;
1429
- return createAlertComponent({
1430
- uid,
1431
- analyticsId,
1432
- control,
1433
- markdown,
1434
- margin: margin != null ? margin : "md",
1435
- callToAction: cta,
1436
- context: mapLegacyContext(context != null ? context : "neutral"),
1437
- tags
1438
- });
1439
- };
1466
+ tags,
1467
+ title,
1468
+ media,
1469
+ onDismiss,
1470
+ secondaryCallToAction
1471
+ }, mapperProps) => createAlertComponent({
1472
+ uid,
1473
+ analyticsId,
1474
+ control,
1475
+ markdown,
1476
+ margin: margin != null ? margin : "md",
1477
+ callToAction: getDomainLayerCallToAction(callToAction, mapperProps),
1478
+ context: mapLegacyContext(context != null ? context : "neutral"),
1479
+ tags,
1480
+ title,
1481
+ media,
1482
+ dismiss: onDismiss ? makeDismissHandler(onDismiss, mapperProps) : void 0,
1483
+ secondaryCallToAction: getDomainLayerCallToAction(secondaryCallToAction, mapperProps)
1484
+ });
1440
1485
 
1441
1486
  // src/domain/components/BoxComponent.ts
1442
1487
  var createBoxComponent = (props) => __spreadProps(__spreadValues({}, props), {
@@ -1469,6 +1514,367 @@ var boxLayoutToComponent = (uid, { border = false, components, control, margin,
1469
1514
  )
1470
1515
  });
1471
1516
 
1517
+ // src/domain/mappers/utils/utils.ts
1518
+ var mapInlineAlert = (alert) => {
1519
+ return alert ? {
1520
+ content: alert.content,
1521
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1522
+ } : void 0;
1523
+ };
1524
+ var mapAdditionalInfo = (info, mapperProps) => {
1525
+ const { onBehavior, trackEvent, registerSubmissionBehavior } = mapperProps;
1526
+ if (info) {
1527
+ const behavior = getDomainLayerBehavior(info, [], registerSubmissionBehavior);
1528
+ const isLink = behavior.type === "link";
1529
+ return {
1530
+ text: info.text,
1531
+ href: isLink ? behavior.url : void 0,
1532
+ hrefWithTracking: getHrefWithTracking({
1533
+ behavior,
1534
+ onBehavior,
1535
+ trackEvent
1536
+ }),
1537
+ accessibilityDescription: info.accessibilityDescription,
1538
+ onClick: behavior.type === "none" ? void 0 : () => {
1539
+ void onBehavior(behavior);
1540
+ }
1541
+ };
1542
+ }
1543
+ return void 0;
1544
+ };
1545
+ var mapSchemaAlert = (alert) => {
1546
+ return alert ? {
1547
+ content: alert.markdown,
1548
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1549
+ } : void 0;
1550
+ };
1551
+
1552
+ // src/domain/components/utils/debounce.ts
1553
+ var debounce = (callback, waitMs) => {
1554
+ let timeoutId = null;
1555
+ let lastArgs = null;
1556
+ const clearTimer = () => {
1557
+ if (timeoutId !== null) {
1558
+ clearTimeout(timeoutId);
1559
+ timeoutId = null;
1560
+ }
1561
+ lastArgs = null;
1562
+ };
1563
+ const debouncedFn = (...args) => {
1564
+ lastArgs = args;
1565
+ if (timeoutId !== null) {
1566
+ clearTimeout(timeoutId);
1567
+ }
1568
+ timeoutId = setTimeout(() => {
1569
+ callback(...lastArgs);
1570
+ timeoutId = null;
1571
+ lastArgs = null;
1572
+ }, waitMs);
1573
+ };
1574
+ debouncedFn.cancel = () => {
1575
+ if (timeoutId !== null) {
1576
+ clearTimer();
1577
+ }
1578
+ };
1579
+ debouncedFn.flush = () => {
1580
+ if (timeoutId !== null) {
1581
+ callback(...lastArgs);
1582
+ clearTimer();
1583
+ }
1584
+ };
1585
+ return debouncedFn;
1586
+ };
1587
+
1588
+ // src/domain/components/collectionComponent/CollectionComponent.ts
1589
+ var DEBOUNCE_TIME = 800;
1590
+ var createCollectionComponent = (props, onComponentUpdate, queryFunction) => {
1591
+ const { uid, analyticsId, control, margin, tags, state } = props;
1592
+ const update = getInputUpdateFunction(onComponentUpdate);
1593
+ let abortController = new AbortController();
1594
+ const query = (mode) => {
1595
+ var _a, _b;
1596
+ abortController.abort();
1597
+ abortController = new AbortController();
1598
+ const { signal } = abortController;
1599
+ queryFunction({
1600
+ searchParam: (_a = component.state.search) == null ? void 0 : _a.param,
1601
+ query: (_b = component.state.search) == null ? void 0 : _b.query,
1602
+ cursor: mode === "pagination" ? component.state.nextCursor : void 0,
1603
+ signal,
1604
+ filters: component.state.filters
1605
+ }).then((response) => {
1606
+ if (!response) {
1607
+ return;
1608
+ }
1609
+ update(component, (draft) => {
1610
+ var _a2, _b2;
1611
+ draft.state = {
1612
+ sections: mode === "pagination" ? mergeSections(component.state.sections, response.sections) : response.sections,
1613
+ nextCursor: response.nextCursor,
1614
+ filters: response.filters ? mapFilters(response.filters) : component.state.filters,
1615
+ search: response.search ? mapSearch(response.search) : component.state.search,
1616
+ beforeSections: (_a2 = response.beforeSections) != null ? _a2 : component.state.beforeSections,
1617
+ afterSections: (_b2 = response.afterSections) != null ? _b2 : component.state.afterSections
1618
+ };
1619
+ draft.status = {
1620
+ type: "idle",
1621
+ loadMore: response.nextCursor ? paginate : void 0
1622
+ };
1623
+ });
1624
+ }).catch(() => {
1625
+ if (!signal.aborted) {
1626
+ 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) };
1633
+ });
1634
+ }
1635
+ });
1636
+ };
1637
+ const debouncedQuery = debounce(query, DEBOUNCE_TIME);
1638
+ const search = () => {
1639
+ abortController.abort();
1640
+ debouncedQuery("search");
1641
+ };
1642
+ const filter = () => {
1643
+ debouncedQuery("search");
1644
+ debouncedQuery.flush();
1645
+ };
1646
+ const paginate = () => query("pagination");
1647
+ const selectFilter = (filterIndex, optionIndex) => {
1648
+ var _a;
1649
+ const selected = (_a = component.state.filters) == null ? void 0 : _a[filterIndex];
1650
+ if (!selected) {
1651
+ return;
1652
+ }
1653
+ const currentValue = selected.options[optionIndex].selected;
1654
+ update(component, (draft) => {
1655
+ if (!draft.state.filters) {
1656
+ return;
1657
+ }
1658
+ const draftFilter = draft.state.filters[filterIndex];
1659
+ if (selected.multiSelect) {
1660
+ draftFilter.options[optionIndex].selected = !currentValue;
1661
+ } else {
1662
+ draftFilter.options.forEach((draftOption, index) => {
1663
+ draftOption.selected = index === optionIndex ? !currentValue : false;
1664
+ });
1665
+ }
1666
+ draft.status = { type: "loading", reason: "search" };
1667
+ });
1668
+ filter();
1669
+ };
1670
+ const mapFilters = (filters) => filters == null ? void 0 : filters.map((f, filterIndex) => {
1671
+ var _a;
1672
+ return __spreadProps(__spreadValues({}, f), {
1673
+ options: (_a = f.options) == null ? void 0 : _a.map((option, optionIndex) => {
1674
+ var _a2;
1675
+ return __spreadProps(__spreadValues({}, option), {
1676
+ selected: (_a2 = option.selected) != null ? _a2 : false,
1677
+ onSelect: () => selectFilter(filterIndex, optionIndex)
1678
+ });
1679
+ })
1680
+ });
1681
+ });
1682
+ const mapSearch = (searchConfig) => searchConfig ? __spreadProps(__spreadValues({
1683
+ query: ""
1684
+ }, searchConfig), {
1685
+ onChange(value) {
1686
+ update(component, (draft) => {
1687
+ if (draft.state.search) {
1688
+ draft.state.search.query = value;
1689
+ draft.status = { type: "loading", reason: "search" };
1690
+ }
1691
+ });
1692
+ search();
1693
+ }
1694
+ }) : void 0;
1695
+ const component = {
1696
+ type: "collection",
1697
+ kind: "layout",
1698
+ uid,
1699
+ analyticsId,
1700
+ control,
1701
+ margin,
1702
+ tags,
1703
+ status: {
1704
+ type: "idle",
1705
+ loadMore: state.nextCursor ? () => query("pagination") : void 0
1706
+ },
1707
+ state: __spreadProps(__spreadValues({}, state), {
1708
+ filters: mapFilters(state.filters),
1709
+ search: mapSearch(props.search)
1710
+ })
1711
+ };
1712
+ return component;
1713
+ };
1714
+ var mergeSections = (existing, incoming) => {
1715
+ const knownIds = new Set(existing.map((section) => section.id));
1716
+ const newSections = incoming.filter((section) => !knownIds.has(section.id));
1717
+ const merged = existing.map((section) => {
1718
+ const match = incoming.find((s) => s.id === section.id);
1719
+ if (!match) return section;
1720
+ return __spreadProps(__spreadValues({}, match), { items: [...section.items, ...match.items] });
1721
+ });
1722
+ return [...merged, ...newSections];
1723
+ };
1724
+
1725
+ // src/domain/features/collection/getPerformCollectionQuery.ts
1726
+ var getPerformCollectionQuery = (httpClient, baseRequest, mapState) => {
1727
+ let latestSuccessfulRequestHash = null;
1728
+ let latestSuccessfulResults = null;
1729
+ return async (props) => {
1730
+ const requestHash = hashRequest(props);
1731
+ if (requestHash !== latestSuccessfulRequestHash) {
1732
+ const response = await performRequest(baseRequest, props, httpClient);
1733
+ const results = await parseResponse(response);
1734
+ latestSuccessfulRequestHash = requestHash;
1735
+ const mappedState = mapState(results);
1736
+ latestSuccessfulResults = mappedState;
1737
+ return mappedState;
1738
+ }
1739
+ return latestSuccessfulResults;
1740
+ };
1741
+ };
1742
+ var performRequest = (request, queryProps, httpClient) => {
1743
+ const { url, method, body, headers } = request;
1744
+ if (method === "GET") {
1745
+ return httpClient(buildQueryURL(url, queryProps), {
1746
+ method,
1747
+ headers: __spreadProps(__spreadValues({}, headers), {
1748
+ "Content-Type": "application/json"
1749
+ }),
1750
+ signal: queryProps.signal
1751
+ });
1752
+ }
1753
+ return httpClient(url, {
1754
+ method,
1755
+ headers: __spreadProps(__spreadValues({}, headers), {
1756
+ "Content-Type": "application/json"
1757
+ }),
1758
+ signal: queryProps.signal,
1759
+ body: JSON.stringify(__spreadValues(__spreadValues({}, body && typeof body === "object" && !isArray(body) ? body : {}), buildRequestBody(queryProps)))
1760
+ });
1761
+ };
1762
+ var buildQueryURL = (url, { searchParam, query, cursor, filters = [] }) => {
1763
+ const [baseUrl, queryParams] = splitUrlAndParams(url);
1764
+ const params = new URLSearchParams(queryParams);
1765
+ if (searchParam && query) {
1766
+ params.append(searchParam, query);
1767
+ }
1768
+ if (cursor) {
1769
+ params.append("cursor", cursor);
1770
+ }
1771
+ getFilterValues(filters).forEach(([key, value]) => {
1772
+ if (typeof value === "string") {
1773
+ params.append(key, value);
1774
+ } else {
1775
+ value.forEach((v) => params.append(key, v));
1776
+ }
1777
+ });
1778
+ return `${baseUrl}?${params.toString()}`;
1779
+ };
1780
+ var splitUrlAndParams = (url) => {
1781
+ const [baseUrl, ...rest] = url.split("?");
1782
+ return [baseUrl, rest.join("")];
1783
+ };
1784
+ var buildRequestBody = ({
1785
+ searchParam,
1786
+ query,
1787
+ cursor,
1788
+ filters = []
1789
+ }) => __spreadProps(__spreadValues(__spreadValues({}, searchParam && query ? { [searchParam]: query } : {}), Object.fromEntries(getFilterValues(filters))), {
1790
+ cursor
1791
+ });
1792
+ var getFilterValues = (filters) => {
1793
+ return filters.map((filter) => {
1794
+ const { multiSelect, param } = filter;
1795
+ const values = filter.options.filter((option) => option.selected).map((option) => option.value);
1796
+ if (values.length === 0) {
1797
+ return void 0;
1798
+ }
1799
+ return [param, multiSelect ? values : values[0]];
1800
+ }).filter((value) => value !== void 0);
1801
+ };
1802
+ var parseResponse = async (response) => {
1803
+ if (response.ok) {
1804
+ const body = await response.json().catch(() => null);
1805
+ return body;
1806
+ }
1807
+ throw Error("error response");
1808
+ };
1809
+ var hashRequest = ({
1810
+ query,
1811
+ cursor,
1812
+ filters
1813
+ }) => JSON.stringify({ query, cursor, filters: getFilterValues(filters != null ? filters : []) });
1814
+
1815
+ // src/domain/mappers/layout/collectionLayoutToComponent.ts
1816
+ var collectionLayoutToComponent = (uid, { analyticsId, control, initialState, margin, search, tags, baseRequest }, mapperProps) => {
1817
+ const { httpClient, onComponentUpdate } = mapperProps;
1818
+ const mapLayout = (layout, index) => mapLayoutToComponent(`${uid}-collection-response-${index}`, layout, mapperProps, []);
1819
+ const mapState = (state) => mapCollectionSpecToDomainState(state, mapperProps, mapLayout);
1820
+ const queryFunction = getPerformCollectionQuery(httpClient, baseRequest, mapState);
1821
+ const component = createCollectionComponent(
1822
+ {
1823
+ uid,
1824
+ analyticsId,
1825
+ control,
1826
+ margin: margin != null ? margin : "md",
1827
+ tags,
1828
+ state: mapState(initialState),
1829
+ search
1830
+ },
1831
+ onComponentUpdate,
1832
+ queryFunction
1833
+ );
1834
+ return component;
1835
+ };
1836
+ var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
1837
+ var _a, _b, _c;
1838
+ return {
1839
+ sections: specState.sections.map((section) => {
1840
+ return {
1841
+ id: section.id,
1842
+ title: section.title,
1843
+ callToAction: getDomainLayerCallToAction(section.callToAction, mapperProps),
1844
+ items: section.items.map((item) => {
1845
+ const behavior = getDomainLayerBehavior(
1846
+ { behavior: item.primaryBehavior },
1847
+ [],
1848
+ mapperProps.registerSubmissionBehavior
1849
+ );
1850
+ return __spreadProps(__spreadValues({}, item), {
1851
+ id: item.entityId,
1852
+ onClick: item.primaryBehavior ? () => {
1853
+ void mapperProps.onBehavior(behavior);
1854
+ } : void 0,
1855
+ callToAction: getDomainLayerCallToAction(item.callToAction, mapperProps),
1856
+ inlineAlert: mapInlineAlert(item.inlineAlert)
1857
+ });
1858
+ })
1859
+ };
1860
+ }),
1861
+ filters: (_a = specState.filters) == null ? void 0 : _a.map((filter) => __spreadProps(__spreadValues({}, filter), {
1862
+ options: filter.options.map((option) => {
1863
+ var _a2;
1864
+ return __spreadProps(__spreadValues({}, option), {
1865
+ selected: (_a2 = option.selected) != null ? _a2 : false,
1866
+ onSelect: () => {
1867
+ }
1868
+ // noop - this gets added during mapping
1869
+ });
1870
+ })
1871
+ })),
1872
+ beforeSections: (_b = specState.beforeSections) == null ? void 0 : _b.map(mapLayout),
1873
+ afterSections: (_c = specState.afterSections) == null ? void 0 : _c.map(mapLayout),
1874
+ nextCursor: specState.nextCursor
1875
+ };
1876
+ };
1877
+
1472
1878
  // src/domain/components/ButtonComponent.ts
1473
1879
  var createButtonComponent = (props) => __spreadValues({
1474
1880
  type: "button",
@@ -1637,41 +2043,6 @@ var createDecisionComponent = (props) => __spreadValues({
1637
2043
  // src/domain/mappers/utils/tags-utils.ts
1638
2044
  var mapTags = ({ tag, tags }) => tags != null ? tags : tag != null ? [tag] : void 0;
1639
2045
 
1640
- // src/domain/mappers/utils/utils.ts
1641
- var mapInlineAlert = (alert) => {
1642
- return alert ? {
1643
- content: alert.content,
1644
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1645
- } : void 0;
1646
- };
1647
- var mapAdditionalInfo = (info, mapperProps) => {
1648
- const { onBehavior, trackEvent, registerSubmissionBehavior } = mapperProps;
1649
- if (info) {
1650
- const behavior = getDomainLayerBehavior(info, [], registerSubmissionBehavior);
1651
- const isLink = behavior.type === "link";
1652
- return {
1653
- text: info.text,
1654
- href: isLink ? behavior.url : void 0,
1655
- hrefWithTracking: getHrefWithTracking({
1656
- behavior,
1657
- onBehavior,
1658
- trackEvent
1659
- }),
1660
- accessibilityDescription: info.accessibilityDescription,
1661
- onClick: behavior.type === "none" ? void 0 : () => {
1662
- void onBehavior(behavior);
1663
- }
1664
- };
1665
- }
1666
- return void 0;
1667
- };
1668
- var mapSchemaAlert = (alert) => {
1669
- return alert ? {
1670
- content: alert.markdown,
1671
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1672
- } : void 0;
1673
- };
1674
-
1675
2046
  // src/domain/mappers/layout/decisionLayoutToComponent.ts
1676
2047
  var decisionLayoutToComponent = (uid, {
1677
2048
  analyticsId,
@@ -2147,44 +2518,8 @@ var mapReviewField = (field, mapperProps) => {
2147
2518
  });
2148
2519
  };
2149
2520
 
2150
- // src/domain/components/utils/debounce.ts
2151
- var debounce = (callback, waitMs) => {
2152
- let timeoutId = null;
2153
- let lastArgs = null;
2154
- const clearTimer = () => {
2155
- if (timeoutId !== null) {
2156
- clearTimeout(timeoutId);
2157
- timeoutId = null;
2158
- }
2159
- lastArgs = null;
2160
- };
2161
- const debouncedFn = (...args) => {
2162
- lastArgs = args;
2163
- if (timeoutId !== null) {
2164
- clearTimeout(timeoutId);
2165
- }
2166
- timeoutId = setTimeout(() => {
2167
- callback(...lastArgs);
2168
- timeoutId = null;
2169
- lastArgs = null;
2170
- }, waitMs);
2171
- };
2172
- debouncedFn.cancel = () => {
2173
- if (timeoutId !== null) {
2174
- clearTimer();
2175
- }
2176
- };
2177
- debouncedFn.flush = () => {
2178
- if (timeoutId !== null) {
2179
- callback(...lastArgs);
2180
- clearTimer();
2181
- }
2182
- };
2183
- return debouncedFn;
2184
- };
2185
-
2186
2521
  // src/domain/components/searchComponent/SearchComponent.ts
2187
- var DEBOUNCE_TIME = 400;
2522
+ var DEBOUNCE_TIME2 = 400;
2188
2523
  var createSearchComponent = (props, performSearch, onBehavior, onComponentUpdate) => {
2189
2524
  const { uid, analyticsId, control, emptyMessage, initialState, hint, margin, tags, title } = props;
2190
2525
  const update = getInputUpdateFunction(onComponentUpdate);
@@ -2214,7 +2549,7 @@ var createSearchComponent = (props, performSearch, onBehavior, onComponentUpdate
2214
2549
  }
2215
2550
  });
2216
2551
  };
2217
- const debouncedSearch = debounce(search, DEBOUNCE_TIME);
2552
+ const debouncedSearch = debounce(search, DEBOUNCE_TIME2);
2218
2553
  const component = {
2219
2554
  type: "search",
2220
2555
  kind: "layout",
@@ -2269,10 +2604,10 @@ var createSearchComponent = (props, performSearch, onBehavior, onComponentUpdate
2269
2604
 
2270
2605
  // src/domain/features/search/getPerformSearchFunction.ts
2271
2606
  var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultConfig) => {
2272
- let latestSuccessfulRequestHash = hashRequest("", defaultConfig);
2607
+ let latestSuccessfulRequestHash = hashRequest2("", defaultConfig);
2273
2608
  let latestSuccessfulResults = null;
2274
2609
  return async ({ config = defaultConfig, query, signal }) => {
2275
- const requestHash = hashRequest(query, config);
2610
+ const requestHash = hashRequest2(query, config);
2276
2611
  if (requestHash !== latestSuccessfulRequestHash) {
2277
2612
  const { method, param, url } = config;
2278
2613
  const headers = { "Content-Type": "application/json" };
@@ -2286,7 +2621,7 @@ var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultC
2286
2621
  signal,
2287
2622
  body: JSON.stringify({ [param]: query })
2288
2623
  }));
2289
- const results = await parseResponse(response);
2624
+ const results = await parseResponse2(response);
2290
2625
  latestSuccessfulRequestHash = requestHash;
2291
2626
  if (results.type === "layout") {
2292
2627
  const mappedLayoutResult = {
@@ -2302,7 +2637,7 @@ var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultC
2302
2637
  return latestSuccessfulResults;
2303
2638
  };
2304
2639
  };
2305
- var parseResponse = async (response) => {
2640
+ var parseResponse2 = async (response) => {
2306
2641
  if (response.ok) {
2307
2642
  const body = await response.json().catch(() => null);
2308
2643
  if (isValidResponseBody(body)) {
@@ -2339,7 +2674,7 @@ var isValidResponseBody = (body) => {
2339
2674
  }
2340
2675
  return false;
2341
2676
  };
2342
- var hashRequest = (query, config) => JSON.stringify({ query, config });
2677
+ var hashRequest2 = (query, config) => JSON.stringify({ query, config });
2343
2678
 
2344
2679
  // src/domain/mappers/layout/searchLayoutToComponent.ts
2345
2680
  var searchLayoutToComponent = (uid, {
@@ -2416,12 +2751,22 @@ var createSectionComponent = (props) => __spreadProps(__spreadValues({}, props),
2416
2751
  });
2417
2752
 
2418
2753
  // src/domain/mappers/layout/sectionLayoutToComponent.ts
2419
- var sectionLayoutToComponent = (uid, { analyticsId, control, title, components, callToAction, margin, tags }, mapperProps, schemaComponents) => {
2754
+ var sectionLayoutToComponent = (uid, {
2755
+ analyticsId,
2756
+ control,
2757
+ shortTitle,
2758
+ title,
2759
+ components,
2760
+ callToAction,
2761
+ margin,
2762
+ tags
2763
+ }, mapperProps, schemaComponents) => {
2420
2764
  return createSectionComponent({
2421
2765
  uid,
2422
2766
  analyticsId,
2423
2767
  control,
2424
2768
  title,
2769
+ shortTitle,
2425
2770
  components: components.map(
2426
2771
  (component, index) => mapLayoutToComponent(`${uid}.section-${index}`, component, mapperProps, schemaComponents)
2427
2772
  ),
@@ -2505,12 +2850,7 @@ var upsellLayoutToComponent = (uid, { analyticsId, callToAction, control, margin
2505
2850
  media: getDomainLayerMedia({ media }),
2506
2851
  tags,
2507
2852
  text,
2508
- dismiss: onDismiss ? () => {
2509
- const { url, method } = onDismiss;
2510
- const body = method === "GET" ? void 0 : JSON.stringify(onDismiss.body);
2511
- void mapperProps.httpClient(url, { method, body }).catch(() => {
2512
- });
2513
- } : void 0
2853
+ dismiss: onDismiss ? makeDismissHandler(onDismiss, mapperProps) : void 0
2514
2854
  },
2515
2855
  onComponentUpdate
2516
2856
  );
@@ -2525,6 +2865,8 @@ var mapLayoutToComponent = (uid, layout, mapperProps, schemaComponents) => {
2525
2865
  return boxLayoutToComponent(uid, layout, mapperProps, schemaComponents);
2526
2866
  case "button":
2527
2867
  return buttonLayoutToComponent(uid, layout, mapperProps);
2868
+ case "collection":
2869
+ return collectionLayoutToComponent(uid, layout, mapperProps);
2528
2870
  case "columns":
2529
2871
  return columnsLayoutToComponent(uid, layout, mapperProps, schemaComponents);
2530
2872
  case "decision":
@@ -6579,7 +6921,7 @@ var getExternalConfiguration = (uid, external, onLoad, mapperProps) => {
6579
6921
  if (onLoad.type === "link") {
6580
6922
  return createExternalConfirmation(
6581
6923
  `${uid}-external-confirmation`,
6582
- onLoad == null ? void 0 : onLoad.url,
6924
+ safeParseLink(onLoad.url),
6583
6925
  mapperProps.onLink,
6584
6926
  mapperProps.onComponentUpdate
6585
6927
  );
@@ -6587,7 +6929,7 @@ var getExternalConfiguration = (uid, external, onLoad, mapperProps) => {
6587
6929
  if ((external == null ? void 0 : external.url) && onLoad.type === "none") {
6588
6930
  return createExternalConfirmation(
6589
6931
  `${uid}-external-confirmation`,
6590
- external == null ? void 0 : external.url,
6932
+ safeParseLink(external.url),
6591
6933
  mapperProps.onLink,
6592
6934
  mapperProps.onComponentUpdate
6593
6935
  );
@@ -7778,8 +8120,22 @@ function pick(obj, ...keys) {
7778
8120
  }
7779
8121
 
7780
8122
  // src/renderers/mappers/alertComponentToProps.ts
7781
- var alertComponentToProps = (component, rendererMapperProps) => __spreadValues(__spreadProps(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "context", "control", "margin", "markdown", "tags")), {
7782
- callToAction: mapCallToActionOptional(component.callToAction)
8123
+ var alertComponentToProps = (component, rendererMapperProps) => __spreadValues(__spreadProps(__spreadValues({}, pick(
8124
+ component,
8125
+ "uid",
8126
+ "analyticsId",
8127
+ "type",
8128
+ "context",
8129
+ "control",
8130
+ "margin",
8131
+ "markdown",
8132
+ "media",
8133
+ "tags",
8134
+ "title"
8135
+ )), {
8136
+ callToAction: mapCallToActionOptional(component.callToAction),
8137
+ onDismiss: component.dismiss,
8138
+ secondaryCallToAction: mapCallToActionOptional(component.secondaryCallToAction)
7783
8139
  }), rendererMapperProps);
7784
8140
 
7785
8141
  // src/renderers/mappers/allOfComponentToProps.ts
@@ -7898,6 +8254,35 @@ var mapBoxControl = ({
7898
8254
  return control;
7899
8255
  };
7900
8256
 
8257
+ // src/renderers/mappers/collectionComponentToProps.ts
8258
+ var collectionComponentToProps = (component, rendererMapperProps) => {
8259
+ var _a, _b, _c;
8260
+ const beforeSectionsProps = (_a = component.state.beforeSections) == null ? void 0 : _a.map(
8261
+ (child) => componentToRendererProps(child, rendererMapperProps)
8262
+ );
8263
+ const afterSectionsProps = (_b = component.state.afterSections) == null ? void 0 : _b.map(
8264
+ (child) => componentToRendererProps(child, rendererMapperProps)
8265
+ );
8266
+ return __spreadProps(__spreadValues(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "control", "margin", "tags")), rendererMapperProps), {
8267
+ status: component.status,
8268
+ state: __spreadProps(__spreadValues({}, component.state), {
8269
+ filters: (_c = component.state.filters) != null ? _c : [],
8270
+ sections: component.state.sections.map((section) => __spreadProps(__spreadValues({}, section), {
8271
+ callToAction: mapCallToActionOptional(section.callToAction),
8272
+ items: section.items.map((item) => __spreadProps(__spreadValues({}, item), {
8273
+ callToAction: mapCallToActionOptional(item.callToAction),
8274
+ additionalInfo: mapAdditionalInfo2(item.additionalInfo),
8275
+ disabled: rendererMapperProps.stepLoadingState !== "idle" || item.disabled
8276
+ }))
8277
+ })),
8278
+ beforeSectionsProps,
8279
+ beforeSections: beforeSectionsProps == null ? void 0 : beforeSectionsProps.map(rendererMapperProps.render),
8280
+ afterSectionsProps,
8281
+ afterSections: afterSectionsProps == null ? void 0 : afterSectionsProps.map(rendererMapperProps.render)
8282
+ })
8283
+ });
8284
+ };
8285
+
7901
8286
  // src/renderers/mappers/buttonComponentToProps.ts
7902
8287
  var buttonComponentToProps = (component, rendererMapperProps) => {
7903
8288
  return __spreadValues(__spreadProps(__spreadValues({
@@ -8385,7 +8770,17 @@ var sectionComponentToProps = (component, rendererMapperProps) => {
8385
8770
  const childrenProps = component.components.map(
8386
8771
  (c) => componentToRendererProps(c, rendererMapperProps)
8387
8772
  );
8388
- return __spreadProps(__spreadValues(__spreadProps(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "title", "margin", "control", "tags")), {
8773
+ return __spreadProps(__spreadValues(__spreadProps(__spreadValues({}, pick(
8774
+ component,
8775
+ "uid",
8776
+ "analyticsId",
8777
+ "type",
8778
+ "shortTitle",
8779
+ "title",
8780
+ "margin",
8781
+ "control",
8782
+ "tags"
8783
+ )), {
8389
8784
  callToAction: mapCallToActionOptional(component.callToAction)
8390
8785
  }), rendererMapperProps), {
8391
8786
  children: childrenProps.map(rendererMapperProps.render),
@@ -8527,6 +8922,8 @@ var getComponentProps = (component, rendererMapperProps) => {
8527
8922
  return boxComponentToProps(component, rendererMapperProps);
8528
8923
  case "button":
8529
8924
  return buttonComponentToProps(component, rendererMapperProps);
8925
+ case "collection":
8926
+ return collectionComponentToProps(component, rendererMapperProps);
8530
8927
  case "columns":
8531
8928
  return columnsComponentToProps(component, rendererMapperProps);
8532
8929
  case "container":