@wise/dynamic-flow-client 5.29.0 → 5.30.0-experimental-7a76ef5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/build/main.css +97 -0
  2. package/build/main.js +539 -326
  3. package/build/main.mjs +539 -326
  4. package/build/tsconfig.types.tsbuildinfo +1 -1
  5. package/build/types/controller/getRequestAbortController.d.ts +4 -3
  6. package/build/types/controller/getRequestAbortController.d.ts.map +1 -1
  7. package/build/types/domain/components/collectionComponent/CollectionComponent.d.ts +6 -7
  8. package/build/types/domain/components/collectionComponent/CollectionComponent.d.ts.map +1 -1
  9. package/build/types/domain/components/collectionComponent/CollectionController.d.ts +18 -0
  10. package/build/types/domain/components/collectionComponent/CollectionController.d.ts.map +1 -0
  11. package/build/types/domain/components/collectionComponent/CollectionStack.d.ts +12 -0
  12. package/build/types/domain/components/collectionComponent/CollectionStack.d.ts.map +1 -0
  13. package/build/types/domain/components/collectionComponent/CollectionState.d.ts +20 -0
  14. package/build/types/domain/components/collectionComponent/CollectionState.d.ts.map +1 -0
  15. package/build/types/domain/components/collectionComponent/applyCollectionResponse.d.ts +7 -0
  16. package/build/types/domain/components/collectionComponent/applyCollectionResponse.d.ts.map +1 -0
  17. package/build/types/domain/components/collectionComponent/mergeSections.d.ts +3 -0
  18. package/build/types/domain/components/collectionComponent/mergeSections.d.ts.map +1 -0
  19. package/build/types/domain/components/collectionComponent/toggleFilterOption.d.ts +3 -0
  20. package/build/types/domain/components/collectionComponent/toggleFilterOption.d.ts.map +1 -0
  21. package/build/types/domain/components/collectionComponent/types.d.ts +42 -18
  22. package/build/types/domain/components/collectionComponent/types.d.ts.map +1 -1
  23. package/build/types/domain/features/collection/getPerformCollectionQuery.d.ts +2 -2
  24. package/build/types/domain/features/collection/getPerformCollectionQuery.d.ts.map +1 -1
  25. package/build/types/domain/mappers/layout/collectionLayoutToComponent.d.ts +3 -3
  26. package/build/types/domain/mappers/layout/collectionLayoutToComponent.d.ts.map +1 -1
  27. package/build/types/renderers/mappers/collectionComponentToProps.d.ts.map +1 -1
  28. package/package.json +2 -2
package/build/main.mjs CHANGED
@@ -830,6 +830,7 @@ function findRendererPropsByType(root, type, predicate = () => true) {
830
830
  }
831
831
  var isType = (node, type) => node.type === type;
832
832
  var getChildren = (node) => {
833
+ var _a;
833
834
  switch (node.type) {
834
835
  case "root":
835
836
  case "box":
@@ -851,9 +852,16 @@ var getChildren = (node) => {
851
852
  return node.childrenProps ? [node.childrenProps] : [];
852
853
  case "tabs":
853
854
  return node.tabs.flatMap((c) => c.childrenProps);
855
+ case "collection": {
856
+ const { beforeSectionsProps, afterSectionsProps, sections, search } = node.state;
857
+ return [
858
+ ...beforeSectionsProps,
859
+ ...afterSectionsProps,
860
+ ...[...sections, ...(_a = search == null ? void 0 : search.initialSections) != null ? _a : []].filter((section) => section.type === "layout").flatMap((section) => section.childrenProps)
861
+ ];
862
+ }
854
863
  case "alert":
855
864
  case "button":
856
- case "collection":
857
865
  case "input-checkbox":
858
866
  case "input-date":
859
867
  case "decision":
@@ -1546,101 +1554,78 @@ var boxLayoutToComponent = (uid, { border = false, components, control, margin,
1546
1554
  )
1547
1555
  });
1548
1556
 
1549
- // src/domain/mappers/utils/image.ts
1550
- var mapSpecImage = (image) => {
1551
- var _a, _b, _c;
1552
- return image ? {
1553
- uri: (_b = (_a = image.uri) != null ? _a : image.url) != null ? _b : "",
1554
- accessibilityDescription: (_c = image.accessibilityDescription) != null ? _c : image.text
1555
- } : void 0;
1557
+ // src/domain/components/collectionComponent/CollectionState.ts
1558
+ var createCollectionState = (id, _a, searchQuery) => {
1559
+ var _b = _a, { search } = _b, response = __objRest(_b, ["search"]);
1560
+ return __spreadProps(__spreadValues({}, response), {
1561
+ id,
1562
+ status: { type: "idle" },
1563
+ search: search ? __spreadProps(__spreadValues({}, search), { query: searchQuery }) : void 0
1564
+ });
1556
1565
  };
1557
-
1558
- // src/domain/mappers/utils/media-utils.ts
1559
- var getDomainLayerMedia = ({ icon, image, media }) => {
1560
- if (media) {
1561
- return media;
1562
- }
1563
- if (icon || image) {
1564
- return {
1565
- type: "legacy",
1566
- icon,
1567
- image: mapSpecImage(image)
1568
- };
1569
- }
1570
- return void 0;
1566
+ var forkCollectionState = (_a, forkedId) => {
1567
+ var _b = _a, { id, status } = _b, state = __objRest(_b, ["id", "status"]);
1568
+ var _a2, _b2;
1569
+ return createCollectionState(forkedId, state, (_b2 = (_a2 = state.search) == null ? void 0 : _a2.query) != null ? _b2 : "");
1571
1570
  };
1572
-
1573
- // src/domain/mappers/utils/utils.ts
1574
- var mapInlineAlert = (alert) => {
1575
- return alert ? {
1576
- content: alert.content,
1577
- context: alert.context ? mapLegacyContext(alert.context) : "neutral",
1578
- media: getDomainLayerMedia({ media: alert.media })
1579
- } : void 0;
1571
+ var getCollectionStateChildren = (state) => {
1572
+ var _a, _b, _c, _d;
1573
+ return [
1574
+ // TODO We should be calling the lifecycle stop/start methods on new layouts
1575
+ ...(_a = state.beforeSections) != null ? _a : [],
1576
+ ...getSectionsChildren(state.sections),
1577
+ ...getSectionsChildren((_c = (_b = state.search) == null ? void 0 : _b.initialSections) != null ? _c : []),
1578
+ ...(_d = state.afterSections) != null ? _d : []
1579
+ ];
1580
1580
  };
1581
- var mapAdditionalInfo = (info, mapperProps) => {
1582
- const { onBehavior, trackEvent, registerSubmissionBehavior } = mapperProps;
1583
- if (info) {
1584
- const behavior = getDomainLayerBehavior(info, [], registerSubmissionBehavior);
1585
- const isLink = behavior.type === "link";
1586
- return {
1587
- text: info.text,
1588
- href: isLink ? behavior.url : void 0,
1589
- hrefWithTracking: getHrefWithTracking({
1590
- behavior,
1591
- onBehavior,
1592
- trackEvent
1593
- }),
1594
- accessibilityDescription: info.accessibilityDescription,
1595
- onClick: behavior.type === "none" ? void 0 : () => {
1596
- void onBehavior(behavior);
1581
+ var setLoading = (state, reason) => __spreadProps(__spreadValues({}, state), { status: { type: "loading", reason } });
1582
+ var setError = (state, reason) => __spreadProps(__spreadValues({}, state), {
1583
+ sections: reason === "pagination" ? state.sections : [],
1584
+ status: { type: "error", reason }
1585
+ });
1586
+ var setQuery = (state, value) => state.search ? __spreadProps(__spreadValues({}, state), {
1587
+ search: __spreadProps(__spreadValues({}, state.search), { query: value })
1588
+ }) : state;
1589
+ var getSectionsChildren = (sections) => sections.filter((section) => section.type === "layout").flatMap((section) => section.components);
1590
+
1591
+ // src/domain/components/collectionComponent/CollectionStack.ts
1592
+ var createCollectionStack = (uid, initialState, onChange) => {
1593
+ let states = [createCollectionState(`${uid}-state-0`, initialState, "")];
1594
+ let forkCount = 0;
1595
+ return {
1596
+ getStates: () => states,
1597
+ getState: (id) => states.find((state) => state.id === id),
1598
+ getActiveState: () => states[states.length - 1],
1599
+ update(id, transform) {
1600
+ const state = states.find((current) => current.id === id);
1601
+ if (!state) {
1602
+ return;
1597
1603
  }
1598
- };
1599
- }
1600
- return void 0;
1601
- };
1602
- var mapSchemaAlert = (alert) => {
1603
- return alert ? {
1604
- content: alert.markdown,
1605
- context: alert.context ? mapLegacyContext(alert.context) : "neutral",
1606
- media: getDomainLayerMedia({ media: alert.media })
1607
- } : void 0;
1608
- };
1609
-
1610
- // src/domain/components/utils/debounce.ts
1611
- var debounce = (callback, waitMs) => {
1612
- let timeoutId = null;
1613
- let lastArgs = null;
1614
- const clearTimer = () => {
1615
- if (timeoutId !== null) {
1616
- clearTimeout(timeoutId);
1617
- timeoutId = null;
1618
- }
1619
- lastArgs = null;
1620
- };
1621
- const debouncedFn = (...args) => {
1622
- lastArgs = args;
1623
- if (timeoutId !== null) {
1624
- clearTimeout(timeoutId);
1625
- }
1626
- timeoutId = setTimeout(() => {
1627
- callback(...lastArgs);
1628
- timeoutId = null;
1629
- lastArgs = null;
1630
- }, waitMs);
1631
- };
1632
- debouncedFn.cancel = () => {
1633
- if (timeoutId !== null) {
1634
- clearTimer();
1635
- }
1636
- };
1637
- debouncedFn.flush = () => {
1638
- if (timeoutId !== null) {
1639
- callback(...lastArgs);
1640
- clearTimer();
1604
+ const updated = transform(state);
1605
+ if (updated === state) {
1606
+ return;
1607
+ }
1608
+ const replace = (current) => current.id === id ? updated : current;
1609
+ const [root, ...forks] = states;
1610
+ states = [replace(root), ...forks.map(replace)];
1611
+ onChange();
1612
+ },
1613
+ fork() {
1614
+ forkCount += 1;
1615
+ const state = forkCollectionState(states[states.length - 1], `${uid}-state-${forkCount}`);
1616
+ states = [...states, state];
1617
+ onChange();
1618
+ },
1619
+ pop() {
1620
+ const [root, ...forks] = states;
1621
+ const popped = forks.at(-1);
1622
+ if (popped) {
1623
+ states = [root, ...forks.slice(0, -1)];
1624
+ onChange();
1625
+ }
1626
+ return popped;
1641
1627
  }
1642
1628
  };
1643
- return debouncedFn;
1644
1629
  };
1645
1630
 
1646
1631
  // src/utils/recursiveMerge.ts
@@ -1682,176 +1667,251 @@ function mergeArrays(valueA, valueB) {
1682
1667
  );
1683
1668
  }
1684
1669
 
1685
- // src/domain/components/collectionComponent/CollectionComponent.ts
1686
- var DEBOUNCE_TIME = 800;
1687
- var createCollectionComponent = (props, onComponentUpdate, queryFunction, trackEvent) => {
1688
- const { uid, analyticsId, control, margin, tags, state } = props;
1689
- const update = getInputUpdateFunction(onComponentUpdate);
1690
- let abortController = new AbortController();
1691
- const trackCollectionEvent = (source, status) => trackEvent(getEventName(source, status), component.state.analytics);
1692
- const query = (mode, source) => {
1693
- var _a, _b;
1694
- abortController.abort();
1695
- abortController = new AbortController();
1696
- const { signal } = abortController;
1697
- trackCollectionEvent(source != null ? source : mode, "Triggered");
1698
- queryFunction({
1699
- searchParam: (_a = component.state.search) == null ? void 0 : _a.param,
1700
- query: (_b = component.state.search) == null ? void 0 : _b.query,
1701
- cursor: mode === "pagination" ? component.state.nextCursor : void 0,
1702
- signal,
1703
- filters: component.state.filters
1704
- }).then((response) => {
1705
- if (!response) {
1706
- return;
1707
- }
1708
- update(component, (draft) => {
1709
- draft.state = mergeState(mode, component.state, response);
1710
- draft.status = {
1711
- type: "idle",
1712
- loadMore: response.nextCursor ? paginate : void 0
1713
- };
1670
+ // src/domain/components/collectionComponent/mergeSections.ts
1671
+ var mergeSections = (existing, incoming) => {
1672
+ const knownIds = new Set(existing.map((section) => section.id));
1673
+ const newSections = incoming.filter((section) => !knownIds.has(section.id));
1674
+ const merged = existing.map((section) => {
1675
+ var _a, _b, _c, _d;
1676
+ const match = incoming.find((s) => s.id === section.id);
1677
+ if (!match) return section;
1678
+ if (section.type !== match.type) return section;
1679
+ const baseProps = {
1680
+ type: section.type,
1681
+ id: match.id,
1682
+ title: (_a = match.title) != null ? _a : section.title,
1683
+ callToAction: (_b = match.callToAction) != null ? _b : section.callToAction,
1684
+ help: (_c = match.help) != null ? _c : section.help,
1685
+ inlineAlert: (_d = match.inlineAlert) != null ? _d : section.inlineAlert
1686
+ };
1687
+ if (section.type === "layout" && match.type === "layout") {
1688
+ return __spreadProps(__spreadValues({}, baseProps), {
1689
+ type: "layout",
1690
+ components: [...section.components, ...match.components]
1714
1691
  });
1715
- trackCollectionEvent(source != null ? source : mode, "Succeeded");
1716
- }).catch(() => {
1717
- if (!signal.aborted) {
1718
- const retry = () => {
1719
- update(component, (draft) => {
1720
- draft.status = { type: "loading", reason: mode };
1721
- });
1722
- query(mode, source);
1723
- };
1724
- update(component, (draft) => {
1725
- if (mode === "search") {
1726
- draft.state.sections = [];
1727
- }
1728
- draft.status = { type: "error", reason: mode, retry };
1729
- });
1730
- trackCollectionEvent(source != null ? source : mode, "Failed");
1731
- }
1732
- });
1692
+ }
1693
+ if (section.type === "items" && match.type === "items") {
1694
+ return __spreadProps(__spreadValues({}, baseProps), {
1695
+ type: "items",
1696
+ items: [...section.items, ...match.items]
1697
+ });
1698
+ }
1699
+ return section;
1700
+ });
1701
+ return [...merged, ...newSections];
1702
+ };
1703
+
1704
+ // src/domain/components/collectionComponent/applyCollectionResponse.ts
1705
+ var applyCollectionResponse = (state, mode, incoming) => {
1706
+ var _a, _b, _c, _d, _e;
1707
+ return __spreadProps(__spreadValues({}, state), {
1708
+ sections: mode === "pagination" ? mergeSections(state.sections, incoming.sections) : incoming.sections,
1709
+ nextCursor: incoming.nextCursor,
1710
+ analytics: mode === "pagination" ? recursiveMerge(state.analytics, incoming.analytics) : incoming.analytics,
1711
+ filters: (_a = incoming.filters) != null ? _a : state.filters,
1712
+ search: incoming.search ? __spreadProps(__spreadValues({}, incoming.search), { query: (_c = (_b = state.search) == null ? void 0 : _b.query) != null ? _c : "" }) : state.search,
1713
+ beforeSections: (_d = incoming.beforeSections) != null ? _d : state.beforeSections,
1714
+ afterSections: (_e = incoming.afterSections) != null ? _e : state.afterSections,
1715
+ status: { type: "idle" }
1716
+ });
1717
+ };
1718
+
1719
+ // src/controller/getRequestAbortController.ts
1720
+ var getRequestAbortController = () => {
1721
+ let abortController = new AbortController();
1722
+ return {
1723
+ refresh() {
1724
+ abortController.abort();
1725
+ abortController = new AbortController();
1726
+ return abortController.signal;
1727
+ },
1728
+ abort() {
1729
+ abortController.abort();
1730
+ }
1733
1731
  };
1734
- const debouncedQuery = debounce(query, DEBOUNCE_TIME);
1735
- const search = () => {
1736
- abortController.abort();
1737
- debouncedQuery("search");
1732
+ };
1733
+
1734
+ // src/domain/components/utils/debounce.ts
1735
+ var debounce = (callback, waitMs) => {
1736
+ let timeoutId = null;
1737
+ let lastArgs = null;
1738
+ const clearTimer = () => {
1739
+ if (timeoutId !== null) {
1740
+ clearTimeout(timeoutId);
1741
+ timeoutId = null;
1742
+ }
1743
+ lastArgs = null;
1738
1744
  };
1739
- const filter = () => {
1740
- debouncedQuery("search", "filter");
1741
- debouncedQuery.flush();
1745
+ const debouncedFn = (...args) => {
1746
+ lastArgs = args;
1747
+ if (timeoutId !== null) {
1748
+ clearTimeout(timeoutId);
1749
+ }
1750
+ timeoutId = setTimeout(() => {
1751
+ callback(...lastArgs);
1752
+ timeoutId = null;
1753
+ lastArgs = null;
1754
+ }, waitMs);
1742
1755
  };
1743
- const paginate = () => query("pagination");
1744
- const mergeState = (mode, original, incoming) => {
1745
- var _a, _b;
1746
- return {
1747
- sections: mode === "pagination" ? mergeSections(original.sections, incoming.sections) : incoming.sections,
1748
- nextCursor: incoming.nextCursor,
1749
- filters: incoming.filters ? mapFilters(incoming.filters) : original.filters,
1750
- search: incoming.search ? mapSearch(incoming.search) : original.search,
1751
- beforeSections: (_a = incoming.beforeSections) != null ? _a : original.beforeSections,
1752
- afterSections: (_b = incoming.afterSections) != null ? _b : original.afterSections,
1753
- analytics: mode === "pagination" ? recursiveMerge(original.analytics, incoming.analytics) : incoming.analytics
1754
- };
1756
+ debouncedFn.cancel = () => {
1757
+ if (timeoutId !== null) {
1758
+ clearTimer();
1759
+ }
1755
1760
  };
1756
- const selectFilter = (filterIndex, optionIndex) => {
1757
- var _a;
1758
- const selected = (_a = component.state.filters) == null ? void 0 : _a[filterIndex];
1759
- if (!selected) {
1760
- return;
1761
+ debouncedFn.flush = () => {
1762
+ if (timeoutId !== null) {
1763
+ callback(...lastArgs);
1764
+ clearTimer();
1761
1765
  }
1762
- const currentValue = selected.options[optionIndex].selected;
1763
- update(component, (draft) => {
1764
- if (!draft.state.filters) {
1765
- return;
1766
- }
1767
- const draftFilter = draft.state.filters[filterIndex];
1768
- if (selected.multiSelect) {
1769
- draftFilter.options[optionIndex].selected = !currentValue;
1770
- } else {
1771
- draftFilter.options.forEach((draftOption, index) => {
1772
- draftOption.selected = index === optionIndex ? !currentValue : false;
1773
- });
1774
- }
1775
- draft.status = { type: "loading", reason: "search" };
1776
- });
1777
- filter();
1778
1766
  };
1779
- const mapFilters = (filters) => filters == null ? void 0 : filters.map((f, filterIndex) => {
1780
- var _a;
1781
- return __spreadProps(__spreadValues({}, f), {
1782
- options: (_a = f.options) == null ? void 0 : _a.map((option, optionIndex) => {
1783
- var _a2;
1784
- return __spreadProps(__spreadValues({}, option), {
1785
- selected: (_a2 = option.selected) != null ? _a2 : false,
1786
- onSelect: () => selectFilter(filterIndex, optionIndex)
1787
- });
1788
- })
1789
- });
1767
+ return debouncedFn;
1768
+ };
1769
+
1770
+ // src/domain/components/collectionComponent/toggleFilterOption.ts
1771
+ var toggleFilterOption = (state, filterIndex, optionIndex) => {
1772
+ var _a;
1773
+ const filter = (_a = state.filters) == null ? void 0 : _a[filterIndex];
1774
+ if (!state.filters || !filter) {
1775
+ return state;
1776
+ }
1777
+ const currentValue = filter.options[optionIndex].selected;
1778
+ const options = filter.options.map((option, index) => {
1779
+ if (index === optionIndex) {
1780
+ return __spreadProps(__spreadValues({}, option), { selected: !currentValue });
1781
+ }
1782
+ return filter.multiSelect ? option : __spreadProps(__spreadValues({}, option), { selected: false });
1790
1783
  });
1791
- const mapSearch = (searchConfig) => searchConfig ? __spreadProps(__spreadValues({
1792
- query: ""
1793
- }, searchConfig), {
1794
- onChange(value) {
1795
- update(component, (draft) => {
1796
- if (draft.state.search) {
1797
- draft.state.search.query = value;
1798
- draft.status = { type: "loading", reason: "search" };
1799
- }
1784
+ return __spreadProps(__spreadValues({}, state), {
1785
+ filters: state.filters.map(
1786
+ (current, index) => index === filterIndex ? __spreadProps(__spreadValues({}, current), { options }) : current
1787
+ )
1788
+ });
1789
+ };
1790
+
1791
+ // src/domain/components/collectionComponent/CollectionController.ts
1792
+ var createCollectionController = ({
1793
+ stack,
1794
+ collectionClient,
1795
+ trackEvent
1796
+ }) => {
1797
+ let requests = /* @__PURE__ */ new Map();
1798
+ const getRequest = (id) => {
1799
+ const existing = requests.get(id);
1800
+ if (existing) {
1801
+ return existing;
1802
+ }
1803
+ const request = createSchedulableRequest((mode, signal) => executeRequest2(id, mode, signal));
1804
+ requests = new Map([...requests, [id, request]]);
1805
+ return request;
1806
+ };
1807
+ const queueRequest = (id, mode, transform) => {
1808
+ if (!stack.getState(id)) {
1809
+ return;
1810
+ }
1811
+ stack.update(id, (state) => setLoading(transform(state), mode));
1812
+ getRequest(id).queue(mode);
1813
+ };
1814
+ const runRequest = (id, mode, transform = (state) => state) => {
1815
+ if (!stack.getState(id)) {
1816
+ return;
1817
+ }
1818
+ stack.update(id, (state) => setLoading(transform(state), mode));
1819
+ getRequest(id).run(mode);
1820
+ };
1821
+ const handleSuccess = (state, mode, response) => {
1822
+ trackEvent(
1823
+ getEventName(mode, "Succeeded"),
1824
+ mode === "pagination" ? recursiveMerge(state.analytics, response.analytics) : response.analytics
1825
+ );
1826
+ stack.update(state.id, (current) => applyCollectionResponse(current, mode, response));
1827
+ };
1828
+ const handleFailure = (state, mode) => {
1829
+ trackEvent(getEventName(mode, "Failed"), state.analytics);
1830
+ stack.update(state.id, (current) => setError(current, mode));
1831
+ };
1832
+ const executeRequest2 = async (id, mode, signal) => {
1833
+ const state = stack.getState(id);
1834
+ if (!state) {
1835
+ return;
1836
+ }
1837
+ const { analytics, filters, search } = state;
1838
+ trackEvent(getEventName(mode, "Triggered"), analytics);
1839
+ try {
1840
+ const response = await collectionClient({
1841
+ searchParam: search == null ? void 0 : search.param,
1842
+ query: search == null ? void 0 : search.query,
1843
+ cursor: mode === "pagination" ? state.nextCursor : void 0,
1844
+ signal,
1845
+ filters
1800
1846
  });
1801
- search();
1847
+ if (response && !signal.aborted) {
1848
+ handleSuccess(state, mode, response);
1849
+ }
1850
+ } catch (e) {
1851
+ if (!signal.aborted) {
1852
+ handleFailure(state, mode);
1853
+ }
1802
1854
  }
1803
- }) : void 0;
1804
- const component = {
1805
- type: "collection",
1806
- kind: "layout",
1807
- uid,
1808
- analyticsId,
1809
- control,
1810
- margin,
1811
- tags,
1812
- getChildren() {
1813
- var _a, _b, _c, _d;
1814
- return [
1815
- ...(_b = (_a = component.state) == null ? void 0 : _a.beforeSections) != null ? _b : [],
1816
- ...(_d = (_c = component.state) == null ? void 0 : _c.afterSections) != null ? _d : []
1817
- ];
1855
+ };
1856
+ return {
1857
+ search(id, value) {
1858
+ queueRequest(id, "search", (state) => setQuery(state, value));
1818
1859
  },
1819
- status: {
1820
- type: "idle",
1821
- loadMore: state.nextCursor ? () => query("pagination") : void 0
1860
+ selectFilter(id, filterIndex, optionIndex) {
1861
+ var _a, _b;
1862
+ if (!((_b = (_a = stack.getState(id)) == null ? void 0 : _a.filters) == null ? void 0 : _b[filterIndex])) {
1863
+ return;
1864
+ }
1865
+ runRequest(id, "filter", (state) => toggleFilterOption(state, filterIndex, optionIndex));
1822
1866
  },
1823
- state: __spreadProps(__spreadValues({}, state), {
1824
- filters: mapFilters(state.filters),
1825
- search: mapSearch(props.search)
1826
- }),
1827
- start() {
1828
- component.getChildren().forEach((child) => child.start());
1867
+ loadMore(id) {
1868
+ runRequest(id, "pagination");
1829
1869
  },
1830
- stop() {
1831
- component.getChildren().forEach((child) => child.stop());
1870
+ retry(id) {
1871
+ var _a;
1872
+ const status = (_a = stack.getState(id)) == null ? void 0 : _a.status;
1873
+ if ((status == null ? void 0 : status.type) !== "error") {
1874
+ return;
1875
+ }
1876
+ runRequest(id, status.reason);
1877
+ },
1878
+ fork: stack.fork,
1879
+ pop() {
1880
+ var _a;
1881
+ const states = stack.getStates();
1882
+ if (states.length === 1) {
1883
+ return;
1884
+ }
1885
+ const { id } = stack.getActiveState();
1886
+ (_a = requests.get(id)) == null ? void 0 : _a.abort();
1887
+ requests = new Map([...requests].filter(([stateId]) => stateId !== id));
1888
+ stack.pop();
1832
1889
  }
1833
1890
  };
1834
- return component;
1835
1891
  };
1836
- var mergeSections = (existing, incoming) => {
1837
- const knownIds = new Set(existing.map((section) => section.id));
1838
- const newSections = incoming.filter((section) => !knownIds.has(section.id));
1839
- const merged = existing.map((section) => {
1840
- var _a, _b, _c, _d;
1841
- const match = incoming.find((s) => s.id === section.id);
1842
- if (!match) return section;
1843
- return {
1844
- id: match.id,
1845
- title: (_a = match.title) != null ? _a : section.title,
1846
- callToAction: (_b = match.callToAction) != null ? _b : section.callToAction,
1847
- help: (_c = match.help) != null ? _c : section.help,
1848
- inlineAlert: (_d = match.inlineAlert) != null ? _d : section.inlineAlert,
1849
- items: [...section.items, ...match.items]
1850
- };
1851
- });
1852
- return [...merged, ...newSections];
1892
+ var DEBOUNCE_TIME = 800;
1893
+ var createSchedulableRequest = (execute) => {
1894
+ const { abort, refresh } = getRequestAbortController();
1895
+ const run = (mode) => {
1896
+ void execute(mode, refresh());
1897
+ };
1898
+ const debouncedRun = debounce(run, DEBOUNCE_TIME);
1899
+ return {
1900
+ run(mode) {
1901
+ debouncedRun.cancel();
1902
+ run(mode);
1903
+ },
1904
+ queue(mode) {
1905
+ abort();
1906
+ debouncedRun(mode);
1907
+ },
1908
+ abort() {
1909
+ debouncedRun.cancel();
1910
+ abort();
1911
+ }
1912
+ };
1853
1913
  };
1854
- var getEventName = (mode, state) => {
1914
+ var getEventName = (mode, status) => {
1855
1915
  const getMode = () => {
1856
1916
  switch (mode) {
1857
1917
  case "pagination":
@@ -1862,7 +1922,94 @@ var getEventName = (mode, state) => {
1862
1922
  return "Filter";
1863
1923
  }
1864
1924
  };
1865
- return `Collection ${getMode()} ${state}`;
1925
+ return `Collection ${getMode()} ${status}`;
1926
+ };
1927
+
1928
+ // src/domain/mappers/utils/image.ts
1929
+ var mapSpecImage = (image) => {
1930
+ var _a, _b, _c;
1931
+ return image ? {
1932
+ uri: (_b = (_a = image.uri) != null ? _a : image.url) != null ? _b : "",
1933
+ accessibilityDescription: (_c = image.accessibilityDescription) != null ? _c : image.text
1934
+ } : void 0;
1935
+ };
1936
+
1937
+ // src/domain/mappers/utils/media-utils.ts
1938
+ var getDomainLayerMedia = ({ icon, image, media }) => {
1939
+ if (media) {
1940
+ return media;
1941
+ }
1942
+ if (icon || image) {
1943
+ return {
1944
+ type: "legacy",
1945
+ icon,
1946
+ image: mapSpecImage(image)
1947
+ };
1948
+ }
1949
+ return void 0;
1950
+ };
1951
+
1952
+ // src/domain/mappers/utils/utils.ts
1953
+ var mapInlineAlert = (alert) => {
1954
+ return alert ? {
1955
+ content: alert.content,
1956
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral",
1957
+ media: getDomainLayerMedia({ media: alert.media })
1958
+ } : void 0;
1959
+ };
1960
+ var mapAdditionalInfo = (info, mapperProps) => {
1961
+ const { onBehavior, trackEvent, registerSubmissionBehavior } = mapperProps;
1962
+ if (info) {
1963
+ const behavior = getDomainLayerBehavior(info, [], registerSubmissionBehavior);
1964
+ const isLink = behavior.type === "link";
1965
+ return {
1966
+ text: info.text,
1967
+ href: isLink ? behavior.url : void 0,
1968
+ hrefWithTracking: getHrefWithTracking({
1969
+ behavior,
1970
+ onBehavior,
1971
+ trackEvent
1972
+ }),
1973
+ accessibilityDescription: info.accessibilityDescription,
1974
+ onClick: behavior.type === "none" ? void 0 : () => {
1975
+ void onBehavior(behavior);
1976
+ }
1977
+ };
1978
+ }
1979
+ return void 0;
1980
+ };
1981
+ var mapSchemaAlert = (alert) => {
1982
+ return alert ? {
1983
+ content: alert.markdown,
1984
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral",
1985
+ media: getDomainLayerMedia({ media: alert.media })
1986
+ } : void 0;
1987
+ };
1988
+
1989
+ // src/domain/components/collectionComponent/CollectionComponent.ts
1990
+ var createCollectionComponent = (props, stack, controller) => {
1991
+ const getChildren2 = () => getCollectionStateChildren(stack.getActiveState());
1992
+ return __spreadProps(__spreadValues({}, props), {
1993
+ type: "collection",
1994
+ kind: "layout",
1995
+ get stack() {
1996
+ return stack.getStates();
1997
+ },
1998
+ getActiveState: stack.getActiveState,
1999
+ fork: controller.fork,
2000
+ pop: controller.pop,
2001
+ search: ({ id }, value) => controller.search(id, value),
2002
+ selectFilter: ({ id }, filterIndex, optionIndex) => controller.selectFilter(id, filterIndex, optionIndex),
2003
+ loadMore: ({ id }) => controller.loadMore(id),
2004
+ retry: ({ id }) => controller.retry(id),
2005
+ getChildren: getChildren2,
2006
+ start() {
2007
+ getChildren2().forEach((child) => child.start());
2008
+ },
2009
+ stop() {
2010
+ getChildren2().forEach((child) => child.stop());
2011
+ }
2012
+ });
1866
2013
  };
1867
2014
 
1868
2015
  // src/domain/features/collection/getPerformCollectionQuery.ts
@@ -1956,29 +2103,45 @@ var hashRequest = ({
1956
2103
  }) => JSON.stringify({ query, cursor, filters: getFilterValues(filters != null ? filters : []) });
1957
2104
 
1958
2105
  // src/domain/mappers/layout/collectionLayoutToComponent.ts
1959
- var collectionLayoutToComponent = (uid, { analyticsId, control, initialState, margin, search, tags, baseRequest }, mapperProps) => {
2106
+ var collectionLayoutToComponent = (uid, { analyticsId, control, initialState, margin, search, tags, baseRequest }, mapperProps, schemaComponents) => {
2107
+ var _a;
1960
2108
  const { httpClient, onComponentUpdate, trackEvent } = mapperProps;
1961
- const mapLayout = (layout, index) => mapLayoutToComponent(`${uid}-collection-response-${index}`, layout, mapperProps, []);
2109
+ let layoutIndex = 0;
2110
+ const mapLayout = (layout) => {
2111
+ layoutIndex += 1;
2112
+ return mapLayoutToComponent(
2113
+ `${uid}-collection-response-${layoutIndex}`,
2114
+ layout,
2115
+ mapperProps,
2116
+ schemaComponents
2117
+ );
2118
+ };
1962
2119
  const mapState = (state) => mapCollectionSpecToDomainState(state, mapperProps, mapLayout);
1963
- const queryFunction = getPerformCollectionQuery(httpClient, baseRequest, mapState);
2120
+ const collectionClient = getPerformCollectionQuery(httpClient, baseRequest, mapState);
2121
+ const stack = createCollectionStack(
2122
+ uid,
2123
+ mapState(__spreadProps(__spreadValues({}, initialState), {
2124
+ search: (_a = initialState.search) != null ? _a : search
2125
+ })),
2126
+ onComponentUpdate
2127
+ );
2128
+ const controller = createCollectionController({ stack, collectionClient, trackEvent });
1964
2129
  const component = createCollectionComponent(
1965
2130
  {
1966
2131
  uid,
1967
2132
  analyticsId,
1968
2133
  control,
1969
2134
  margin: margin != null ? margin : "md",
1970
- tags,
1971
- state: mapState(initialState),
1972
- search
2135
+ tags
1973
2136
  },
1974
- onComponentUpdate,
1975
- queryFunction,
1976
- trackEvent
2137
+ stack,
2138
+ controller
1977
2139
  );
1978
2140
  return component;
1979
2141
  };
1980
2142
  var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
1981
2143
  const {
2144
+ search,
1982
2145
  sections,
1983
2146
  filters,
1984
2147
  beforeSections,
@@ -1987,29 +2150,8 @@ var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
1987
2150
  analytics = {}
1988
2151
  } = specState;
1989
2152
  return {
1990
- sections: sections.map((section) => {
1991
- var _a;
1992
- return __spreadProps(__spreadValues({}, section), {
1993
- callToAction: getDomainLayerCallToAction(section.callToAction, mapperProps),
1994
- help: (_a = section.help) == null ? void 0 : _a.markdown,
1995
- inlineAlert: mapInlineAlert(section.inlineAlert),
1996
- items: section.items.map((item) => {
1997
- const behavior = getDomainLayerBehavior(
1998
- { behavior: item.primaryBehavior },
1999
- [],
2000
- mapperProps.registerSubmissionBehavior
2001
- );
2002
- return __spreadProps(__spreadValues({}, item), {
2003
- id: item.entityId,
2004
- onClick: item.primaryBehavior ? () => {
2005
- void mapperProps.onBehavior(behavior);
2006
- } : void 0,
2007
- callToAction: getDomainLayerCallToAction(item.callToAction, mapperProps),
2008
- inlineAlert: mapInlineAlert(item.inlineAlert)
2009
- });
2010
- })
2011
- });
2012
- }),
2153
+ search: search ? mapSearch(search, mapperProps, mapLayout) : void 0,
2154
+ sections: sections.map((section) => mapSection(section, mapperProps, mapLayout)),
2013
2155
  filters: filters == null ? void 0 : filters.map(mapFilter),
2014
2156
  beforeSections: beforeSections == null ? void 0 : beforeSections.map(mapLayout),
2015
2157
  afterSections: afterSections == null ? void 0 : afterSections.map(mapLayout),
@@ -2017,6 +2159,49 @@ var mapCollectionSpecToDomainState = (specState, mapperProps, mapLayout) => {
2017
2159
  analytics
2018
2160
  };
2019
2161
  };
2162
+ var mapSearch = (search, mapperProps, mapLayout) => {
2163
+ var _a, _b, _c;
2164
+ return search ? __spreadProps(__spreadValues({}, search), {
2165
+ help: (_a = search.help) == null ? void 0 : _a.markdown,
2166
+ hints: (_b = search.hints) != null ? _b : search.hint ? [search.hint] : void 0,
2167
+ initialSections: (_c = search.initialSections) == null ? void 0 : _c.map(
2168
+ (section) => mapSection(section, mapperProps, mapLayout)
2169
+ )
2170
+ }) : void 0;
2171
+ };
2172
+ var mapSection = (section, mapperProps, mapLayout) => {
2173
+ var _a;
2174
+ const baseProps = __spreadProps(__spreadValues({}, section), {
2175
+ callToAction: getDomainLayerCallToAction(section.callToAction, mapperProps),
2176
+ help: (_a = section.help) == null ? void 0 : _a.markdown,
2177
+ inlineAlert: mapInlineAlert(section.inlineAlert)
2178
+ });
2179
+ if (section.type === "layout") {
2180
+ return __spreadProps(__spreadValues({}, baseProps), {
2181
+ type: "layout",
2182
+ components: section.components.map(mapLayout)
2183
+ });
2184
+ }
2185
+ return __spreadProps(__spreadValues({}, baseProps), {
2186
+ type: "items",
2187
+ items: section.items.map((item) => mapResultItem(item, mapperProps))
2188
+ });
2189
+ };
2190
+ var mapResultItem = (item, mapperProps) => {
2191
+ const behavior = getDomainLayerBehavior(
2192
+ { behavior: item.primaryBehavior },
2193
+ [],
2194
+ mapperProps.registerSubmissionBehavior
2195
+ );
2196
+ return __spreadProps(__spreadValues({}, item), {
2197
+ id: item.entityId,
2198
+ onClick: item.primaryBehavior ? () => {
2199
+ void mapperProps.onBehavior(behavior);
2200
+ } : void 0,
2201
+ callToAction: getDomainLayerCallToAction(item.callToAction, mapperProps),
2202
+ inlineAlert: mapInlineAlert(item.inlineAlert)
2203
+ });
2204
+ };
2020
2205
  var mapFilter = (filter) => {
2021
2206
  const anySelected = filter.options.some((option) => option.selected);
2022
2207
  return __spreadProps(__spreadValues({}, filter), {
@@ -2024,10 +2209,7 @@ var mapFilter = (filter) => {
2024
2209
  var _a;
2025
2210
  return __spreadProps(__spreadValues({}, option), {
2026
2211
  // if a single select with no selection, we should default to selecting the first item
2027
- selected: filter.multiSelect || anySelected ? (_a = option.selected) != null ? _a : false : index === 0,
2028
- onSelect: () => {
2029
- }
2030
- // noop - this gets added during mapping in the component itself
2212
+ selected: filter.multiSelect || anySelected ? (_a = option.selected) != null ? _a : false : index === 0
2031
2213
  });
2032
2214
  })
2033
2215
  });
@@ -3281,7 +3463,7 @@ var mapLayoutToComponent = (uid, layout, mapperProps, schemaComponents) => {
3281
3463
  case "button":
3282
3464
  return buttonLayoutToComponent(uid, layout, mapperProps);
3283
3465
  case "collection":
3284
- return collectionLayoutToComponent(uid, layout, mapperProps);
3466
+ return collectionLayoutToComponent(uid, layout, mapperProps, schemaComponents);
3285
3467
  case "columns":
3286
3468
  return columnsLayoutToComponent(uid, layout, mapperProps, schemaComponents);
3287
3469
  case "decision":
@@ -7991,21 +8173,6 @@ var executeSubflow = async ({
7991
8173
  });
7992
8174
  };
7993
8175
 
7994
- // src/controller/getRequestAbortController.ts
7995
- var getRequestAbortController = () => {
7996
- let abortController = new AbortController();
7997
- return {
7998
- abortAndGetNewSignal() {
7999
- abortController.abort();
8000
- abortController = new AbortController();
8001
- return abortController.signal;
8002
- },
8003
- abort() {
8004
- abortController.abort();
8005
- }
8006
- };
8007
- };
8008
-
8009
8176
  // src/controller/getStepCounter.ts
8010
8177
  var getStepCounter = () => {
8011
8178
  let count = 0;
@@ -8384,7 +8551,7 @@ var createFlowController = (props) => {
8384
8551
  rootComponent.setLoadingState("refreshing");
8385
8552
  const model = rootComponent.getSubmittableValueSync();
8386
8553
  const command = await executeRefresh({
8387
- abortSignal: refreshAbortController.abortAndGetNewSignal(),
8554
+ abortSignal: refreshAbortController.refresh(),
8388
8555
  url: (_a = refreshUrl != null ? refreshUrl : rootComponent.getRefreshUrl()) != null ? _a : "",
8389
8556
  model,
8390
8557
  etag: (_c = (_b = rootComponent.getStep()) == null ? void 0 : _b.etag) != null ? _c : null,
@@ -8942,31 +9109,77 @@ var mapBoxControl = ({
8942
9109
 
8943
9110
  // src/renderers/mappers/collectionComponentToProps.ts
8944
9111
  var collectionComponentToProps = (component, rendererMapperProps) => {
8945
- var _a, _b, _c, _d, _e;
9112
+ const { stack } = component;
9113
+ return __spreadProps(__spreadValues(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "control", "margin", "tags", "fork", "pop")), rendererMapperProps), {
9114
+ state: mapCollectionState(component, component.getActiveState(), rendererMapperProps),
9115
+ onSearchChange: (query) => component.search(component.getActiveState(), query),
9116
+ depth: stack.length - 1
9117
+ });
9118
+ };
9119
+ var mapCollectionState = (component, state, rendererMapperProps) => {
9120
+ var _a, _b, _c, _d;
8946
9121
  const { render } = rendererMapperProps;
8947
- const beforeSectionsProps = (_b = (_a = component.state.beforeSections) == null ? void 0 : _a.map(
8948
- (child) => componentToRendererProps(child, rendererMapperProps)
8949
- )) != null ? _b : [];
8950
- const afterSectionsProps = (_d = (_c = component.state.afterSections) == null ? void 0 : _c.map(
8951
- (child) => componentToRendererProps(child, rendererMapperProps)
8952
- )) != null ? _d : [];
8953
- return __spreadProps(__spreadValues(__spreadValues({}, pick(component, "uid", "analyticsId", "type", "control", "margin", "tags")), rendererMapperProps), {
8954
- status: component.status,
8955
- state: __spreadProps(__spreadValues({}, component.state), {
8956
- filters: (_e = component.state.filters) != null ? _e : [],
8957
- sections: component.state.sections.map((section) => __spreadProps(__spreadValues({}, section), {
8958
- callToAction: mapCallToActionOptional(section.callToAction),
8959
- items: section.items.map((item) => __spreadProps(__spreadValues({}, item), {
8960
- callToAction: mapCallToActionOptional(item.callToAction),
8961
- additionalInfo: mapAdditionalInfo2(item.additionalInfo),
8962
- disabled: rendererMapperProps.stepLoadingState !== "idle" || item.disabled
8963
- }))
8964
- })),
8965
- beforeSectionsProps,
8966
- beforeSections: beforeSectionsProps.map(render),
8967
- afterSectionsProps,
8968
- afterSections: afterSectionsProps.map(render)
8969
- })
9122
+ const { search } = state;
9123
+ const beforeSectionsProps = (_b = (_a = state.beforeSections) == null ? void 0 : _a.map((child) => componentToRendererProps(child, rendererMapperProps))) != null ? _b : [];
9124
+ const afterSectionsProps = (_d = (_c = state.afterSections) == null ? void 0 : _c.map((child) => componentToRendererProps(child, rendererMapperProps))) != null ? _d : [];
9125
+ return {
9126
+ id: state.id,
9127
+ status: mapStatus(component, state),
9128
+ sections: mapSections(state.sections, rendererMapperProps),
9129
+ filters: mapFilters(component, state),
9130
+ beforeSectionsProps,
9131
+ beforeSections: beforeSectionsProps.map(render),
9132
+ afterSectionsProps,
9133
+ afterSections: afterSectionsProps.map(render),
9134
+ search: search ? __spreadProps(__spreadValues({}, pick(search, "title", "hint", "hints", "query")), {
9135
+ initialSections: search.initialSections ? mapSections(search.initialSections, rendererMapperProps) : void 0
9136
+ }) : void 0
9137
+ };
9138
+ };
9139
+ var mapStatus = (component, state) => {
9140
+ const { status } = state;
9141
+ switch (status.type) {
9142
+ case "idle":
9143
+ return {
9144
+ type: "idle",
9145
+ loadMore: state.nextCursor ? () => component.loadMore(state) : void 0
9146
+ };
9147
+ case "loading":
9148
+ return status;
9149
+ case "error":
9150
+ return __spreadProps(__spreadValues({}, status), { retry: () => component.retry(state) });
9151
+ }
9152
+ };
9153
+ var mapFilters = (component, state) => {
9154
+ var _a;
9155
+ return ((_a = state.filters) != null ? _a : []).map((filter, filterIndex) => __spreadProps(__spreadValues({}, filter), {
9156
+ options: filter.options.map((option, optionIndex) => __spreadProps(__spreadValues({}, option), {
9157
+ onSelect: () => component.selectFilter(state, filterIndex, optionIndex)
9158
+ }))
9159
+ }));
9160
+ };
9161
+ var mapSections = (sections, rendererMapperProps) => sections.map((section) => mapSection2(section, rendererMapperProps));
9162
+ var mapSection2 = (section, rendererMapperProps) => {
9163
+ const baseProps = __spreadProps(__spreadValues({}, section), {
9164
+ callToAction: mapCallToActionOptional(section.callToAction)
9165
+ });
9166
+ if (section.type === "layout") {
9167
+ const childrenProps = section.components.map(
9168
+ (child) => componentToRendererProps(child, rendererMapperProps)
9169
+ );
9170
+ return __spreadProps(__spreadValues({}, baseProps), {
9171
+ type: "layout",
9172
+ childrenProps,
9173
+ children: childrenProps.map(rendererMapperProps.render)
9174
+ });
9175
+ }
9176
+ return __spreadProps(__spreadValues({}, baseProps), {
9177
+ type: "items",
9178
+ items: section.items.map((item) => __spreadProps(__spreadValues({}, item), {
9179
+ callToAction: mapCallToActionOptional(item.callToAction),
9180
+ additionalInfo: mapAdditionalInfo2(item.additionalInfo),
9181
+ disabled: rendererMapperProps.stepLoadingState !== "idle" || item.disabled
9182
+ }))
8970
9183
  });
8971
9184
  };
8972
9185
 
@@ -9387,7 +9600,7 @@ var reviewComponentToProps = (component, rendererMapperProps) => __spreadValues(
9387
9600
 
9388
9601
  // src/renderers/mappers/searchComponentToProps.ts
9389
9602
  var searchComponentToProps = (component, rendererMapperProps) => {
9390
- const { uid, emptyMessage, error, query, setQuery, selectResult } = component;
9603
+ const { uid, emptyMessage, error, query, setQuery: setQuery2, selectResult } = component;
9391
9604
  const state = getSearchState({
9392
9605
  emptyMessage,
9393
9606
  error,
@@ -9395,11 +9608,11 @@ var searchComponentToProps = (component, rendererMapperProps) => {
9395
9608
  query,
9396
9609
  state: component.state,
9397
9610
  rendererMapperProps,
9398
- setQuery,
9611
+ setQuery: setQuery2,
9399
9612
  selectResult
9400
9613
  });
9401
9614
  return __spreadValues(__spreadProps(__spreadValues({}, pick(component, "uid", "control", "hint", "isLoading", "margin", "query", "title", "tags")), {
9402
- onChange: setQuery,
9615
+ onChange: setQuery2,
9403
9616
  type: "search",
9404
9617
  id: uid,
9405
9618
  state
@@ -9412,14 +9625,14 @@ var getSearchState = ({
9412
9625
  query,
9413
9626
  state,
9414
9627
  rendererMapperProps,
9415
- setQuery,
9628
+ setQuery: setQuery2,
9416
9629
  selectResult
9417
9630
  }) => {
9418
9631
  if (isLoading) {
9419
9632
  return { type: "pending" };
9420
9633
  }
9421
9634
  if (error) {
9422
- return { type: "error", onRetry: () => setQuery(query) };
9635
+ return { type: "error", onRetry: () => setQuery2(query) };
9423
9636
  }
9424
9637
  if (!state) {
9425
9638
  return { type: "noResults", message: emptyMessage };