@wise/dynamic-flow-client 5.13.4 → 5.14.0-experimental-76b77f2

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.
package/build/main.js CHANGED
@@ -828,6 +828,7 @@ var getChildren = (node) => {
828
828
  return node.tabs.flatMap((c) => c.childrenProps);
829
829
  case "alert":
830
830
  case "button":
831
+ case "collection":
831
832
  case "input-checkbox":
832
833
  case "input-date":
833
834
  case "decision":
@@ -1386,6 +1387,305 @@ var boxLayoutToComponent = (uid, { border = false, components, control, margin,
1386
1387
  )
1387
1388
  });
1388
1389
 
1390
+ // src/domain/components/utils/debounce.ts
1391
+ var debounce = (callback, waitMs) => {
1392
+ let timeoutId = null;
1393
+ let lastArgs = null;
1394
+ const clearTimer = () => {
1395
+ if (timeoutId) {
1396
+ clearTimeout(timeoutId);
1397
+ timeoutId = null;
1398
+ }
1399
+ lastArgs = null;
1400
+ };
1401
+ const debouncedFn = (...args) => {
1402
+ lastArgs = args;
1403
+ if (timeoutId !== null) {
1404
+ clearTimeout(timeoutId);
1405
+ }
1406
+ timeoutId = setTimeout(() => {
1407
+ callback(...lastArgs);
1408
+ timeoutId = null;
1409
+ lastArgs = null;
1410
+ }, waitMs);
1411
+ };
1412
+ debouncedFn.cancel = () => {
1413
+ if (timeoutId !== null) {
1414
+ clearTimer();
1415
+ }
1416
+ };
1417
+ debouncedFn.flush = () => {
1418
+ if (timeoutId !== null) {
1419
+ callback(...lastArgs);
1420
+ clearTimer();
1421
+ }
1422
+ };
1423
+ return debouncedFn;
1424
+ };
1425
+
1426
+ // src/domain/components/CollectionComponent.ts
1427
+ var createCollectionComponent = (props, onComponentUpdate, searchFunction) => {
1428
+ const { uid, analyticsId, control, margin, tags, url, method, state, search, filters } = props;
1429
+ const update = getInputUpdateFunction(onComponentUpdate);
1430
+ let abortController = new AbortController();
1431
+ const searchFn = (component2, query, searchFilters, cursor) => {
1432
+ abortController.abort();
1433
+ abortController = new AbortController();
1434
+ const { signal } = abortController;
1435
+ searchFunction({
1436
+ query,
1437
+ cursor,
1438
+ signal,
1439
+ filters: searchFilters
1440
+ }).then((response) => {
1441
+ if (!response) {
1442
+ return;
1443
+ }
1444
+ if (response.type === "collection-content") {
1445
+ if (cursor) {
1446
+ update(component2, (draft) => {
1447
+ if (draft.state.type === "empty") {
1448
+ return;
1449
+ }
1450
+ const updated = draft.state.sections.map((section) => {
1451
+ const m = response.sections.find((s) => s.id === section.id);
1452
+ if (m) {
1453
+ return __spreadProps(__spreadValues({}, section), {
1454
+ items: [...section.items, ...m.items]
1455
+ });
1456
+ }
1457
+ return section;
1458
+ });
1459
+ draft.state.sections = updated;
1460
+ draft.state.nextCursor = response.nextCursor;
1461
+ draft.cursorStale = false;
1462
+ });
1463
+ } else {
1464
+ update(component2, (draft) => {
1465
+ draft.state = __spreadValues({}, response);
1466
+ draft.cursorStale = false;
1467
+ });
1468
+ }
1469
+ } else {
1470
+ update(component2, (draft) => {
1471
+ draft.state = response;
1472
+ });
1473
+ }
1474
+ }).catch(() => {
1475
+ });
1476
+ };
1477
+ const debouncedSearch = debounce(searchFn, 800);
1478
+ const component = {
1479
+ type: "collection",
1480
+ kind: "layout",
1481
+ uid,
1482
+ analyticsId,
1483
+ control,
1484
+ cursorStale: false,
1485
+ margin,
1486
+ method,
1487
+ url,
1488
+ tags,
1489
+ state,
1490
+ search: __spreadProps(__spreadValues({}, search), {
1491
+ onChange(query) {
1492
+ component._update((draft) => {
1493
+ draft.search.query = query;
1494
+ });
1495
+ debouncedSearch(component, query, component.filters);
1496
+ }
1497
+ }),
1498
+ filters: filters.map((filter, i) => {
1499
+ var _a;
1500
+ return __spreadProps(__spreadValues({}, filter), {
1501
+ options: (_a = filter.options) == null ? void 0 : _a.map((value, j) => {
1502
+ var _a2;
1503
+ return __spreadProps(__spreadValues({}, value), {
1504
+ selected: (_a2 = value.selected) != null ? _a2 : false,
1505
+ onSelect() {
1506
+ const currentValue = component.filters[i].options[j].selected;
1507
+ component._update((draft) => {
1508
+ if (filter.multiSelection) {
1509
+ draft.filters[i].options[j].selected = !currentValue;
1510
+ } else {
1511
+ draft.filters[i].options = draft.filters[i].options.map((option, k) => __spreadProps(__spreadValues({}, option), {
1512
+ selected: k === j ? !currentValue : false
1513
+ }));
1514
+ }
1515
+ });
1516
+ searchFn(component, component.search.query, component.filters, void 0);
1517
+ }
1518
+ });
1519
+ })
1520
+ });
1521
+ }),
1522
+ _update(updateFn) {
1523
+ update(this, updateFn);
1524
+ },
1525
+ loadMore() {
1526
+ if (this.cursorStale || this.state.type === "empty") {
1527
+ return;
1528
+ }
1529
+ const cursor = this.state.nextCursor;
1530
+ this._update((draft) => {
1531
+ draft.cursorStale = true;
1532
+ });
1533
+ searchFn(this, this.search.query, this.filters, cursor);
1534
+ }
1535
+ };
1536
+ return component;
1537
+ };
1538
+
1539
+ // src/domain/mappers/utils/utils.ts
1540
+ var mapInlineAlert = (alert) => {
1541
+ return alert ? {
1542
+ content: alert.content,
1543
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1544
+ } : void 0;
1545
+ };
1546
+ var mapAdditionalInfo = (info, mapperProps) => {
1547
+ const { onBehavior, registerSubmissionBehavior } = mapperProps;
1548
+ if (info) {
1549
+ const behavior = getDomainLayerBehavior(info, [], registerSubmissionBehavior);
1550
+ return {
1551
+ text: info.text,
1552
+ href: behavior.type === "link" ? behavior.url : void 0,
1553
+ accessibilityDescription: info.accessibilityDescription,
1554
+ onClick: behavior.type === "none" ? void 0 : () => {
1555
+ void onBehavior(behavior);
1556
+ }
1557
+ };
1558
+ }
1559
+ return void 0;
1560
+ };
1561
+ var mapSchemaAlert = (alert) => {
1562
+ return alert ? {
1563
+ content: alert.markdown,
1564
+ context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1565
+ } : void 0;
1566
+ };
1567
+
1568
+ // src/domain/mappers/layout/collectionLayoutToComponent.ts
1569
+ var collectionLayoutToComponent = (uid, {
1570
+ analyticsId,
1571
+ control,
1572
+ filters,
1573
+ initialState,
1574
+ margin,
1575
+ method,
1576
+ search,
1577
+ tags,
1578
+ url
1579
+ }, mapperProps) => {
1580
+ const { httpClient, onComponentUpdate } = mapperProps;
1581
+ const searchFunction = getPerformCollectionSearchFunction(
1582
+ httpClient,
1583
+ url,
1584
+ method,
1585
+ search.param,
1586
+ mapperProps,
1587
+ (layout, index) => mapLayoutToComponent(`${uid}-collection-response-${index}`, layout, mapperProps, [])
1588
+ );
1589
+ const component = createCollectionComponent(
1590
+ {
1591
+ uid,
1592
+ analyticsId,
1593
+ control,
1594
+ margin: margin != null ? margin : "md",
1595
+ tags,
1596
+ url,
1597
+ method,
1598
+ state: {
1599
+ type: "collection-content",
1600
+ sections: initialState.sections.map((section) => {
1601
+ return {
1602
+ id: section.id,
1603
+ title: section.title,
1604
+ items: section.items.map((item) => {
1605
+ return __spreadProps(__spreadValues({}, item), {
1606
+ callToAction: getDomainLayerCallToAction(item.callToAction, mapperProps),
1607
+ inlineAlert: mapInlineAlert(item.inlineAlert)
1608
+ });
1609
+ })
1610
+ };
1611
+ }),
1612
+ nextCursor: initialState.nextCursor
1613
+ },
1614
+ search: {
1615
+ query: null,
1616
+ onChange(query) {
1617
+ }
1618
+ },
1619
+ filters: filters.filter((filter) => filter.options)
1620
+ },
1621
+ onComponentUpdate,
1622
+ searchFunction
1623
+ );
1624
+ return component;
1625
+ };
1626
+ var getPerformCollectionSearchFunction = (httpClient, url, method, searchParam, mapperProps, mapLayout) => {
1627
+ let latestSuccessfulRequestHash = "abc";
1628
+ let latestSuccessfulResults = null;
1629
+ return async ({ query, cursor, signal, filters }) => {
1630
+ const requestHash = query;
1631
+ const headers = { "Content-Type": "application/json" };
1632
+ const filterValues = filters.map(
1633
+ (f) => {
1634
+ var _a;
1635
+ return [f.param, (_a = f.options.find((option) => option.selected)) == null ? void 0 : _a.id];
1636
+ }
1637
+ );
1638
+ const response = await (method === "GET" ? httpClient(addQueryParameters(url, [[searchParam, query != null ? query : void 0], ...filterValues]), {
1639
+ method,
1640
+ headers,
1641
+ signal
1642
+ }) : httpClient(url, {
1643
+ method,
1644
+ headers,
1645
+ signal,
1646
+ body: JSON.stringify(__spreadValues(__spreadProps(__spreadValues({}, query ? { [searchParam]: query } : {}), {
1647
+ cursor
1648
+ }), filterValues.reduce((acc, [k, v]) => __spreadProps(__spreadValues({}, acc), { [k]: v }), {})))
1649
+ }));
1650
+ const results = await parseResponse(response);
1651
+ if (results.type === "collection-content") {
1652
+ return {
1653
+ type: "collection-content",
1654
+ sections: [
1655
+ ...results.sections.map((section) => __spreadProps(__spreadValues({}, section), {
1656
+ callToAction: getDomainLayerCallToAction(section.callToAction, mapperProps),
1657
+ items: section.items.map((item) => __spreadProps(__spreadValues({}, item), {
1658
+ callToAction: getDomainLayerCallToAction(item.callToAction, mapperProps),
1659
+ inlineAlert: mapInlineAlert(item.inlineAlert)
1660
+ }))
1661
+ }))
1662
+ ],
1663
+ nextCursor: results.nextCursor
1664
+ };
1665
+ }
1666
+ return {
1667
+ type: "empty",
1668
+ content: results.content.map(mapLayout)
1669
+ };
1670
+ };
1671
+ };
1672
+ var parseResponse = async (response) => {
1673
+ if (response.ok) {
1674
+ const body = await response.json().catch(() => null);
1675
+ return body;
1676
+ }
1677
+ throw Error("error response");
1678
+ };
1679
+ var addQueryParameters = (url, params) => {
1680
+ return params.reduce((u, [key, param]) => param ? addQueryParameter(u, key, param) : u, url);
1681
+ };
1682
+ var addQueryParameter = (url, key, value) => {
1683
+ const [urlBase, urlQuery] = url.split("?");
1684
+ const urlQueryParams = new URLSearchParams(urlQuery);
1685
+ urlQueryParams.set(key, value);
1686
+ return `${urlBase}?${urlQueryParams.toString()}`;
1687
+ };
1688
+
1389
1689
  // src/domain/components/ButtonComponent.ts
1390
1690
  var createButtonComponent = (buttonProps) => __spreadValues({
1391
1691
  type: "button",
@@ -1554,35 +1854,6 @@ var createDecisionComponent = (decisionProps) => __spreadValues({
1554
1854
  // src/domain/mappers/utils/tags-utils.ts
1555
1855
  var mapTags = ({ tag, tags }) => tags != null ? tags : tag != null ? [tag] : void 0;
1556
1856
 
1557
- // src/domain/mappers/utils/utils.ts
1558
- var mapInlineAlert = (alert) => {
1559
- return alert ? {
1560
- content: alert.content,
1561
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1562
- } : void 0;
1563
- };
1564
- var mapAdditionalInfo = (info, mapperProps) => {
1565
- const { onBehavior, registerSubmissionBehavior } = mapperProps;
1566
- if (info) {
1567
- const behavior = getDomainLayerBehavior(info, [], registerSubmissionBehavior);
1568
- return {
1569
- text: info.text,
1570
- href: behavior.type === "link" ? behavior.url : void 0,
1571
- accessibilityDescription: info.accessibilityDescription,
1572
- onClick: behavior.type === "none" ? void 0 : () => {
1573
- void onBehavior(behavior);
1574
- }
1575
- };
1576
- }
1577
- return void 0;
1578
- };
1579
- var mapSchemaAlert = (alert) => {
1580
- return alert ? {
1581
- content: alert.markdown,
1582
- context: alert.context ? mapLegacyContext(alert.context) : "neutral"
1583
- } : void 0;
1584
- };
1585
-
1586
1857
  // src/domain/mappers/layout/decisionLayoutToComponent.ts
1587
1858
  var decisionLayoutToComponent = (uid, {
1588
1859
  analyticsId,
@@ -2053,42 +2324,6 @@ var mapReviewField = (field, mapperProps) => {
2053
2324
  });
2054
2325
  };
2055
2326
 
2056
- // src/domain/components/utils/debounce.ts
2057
- var debounce = (callback, waitMs) => {
2058
- let timeoutId = null;
2059
- let lastArgs = null;
2060
- const clearTimer = () => {
2061
- if (timeoutId) {
2062
- clearTimeout(timeoutId);
2063
- timeoutId = null;
2064
- }
2065
- lastArgs = null;
2066
- };
2067
- const debouncedFn = (...args) => {
2068
- lastArgs = args;
2069
- if (timeoutId !== null) {
2070
- clearTimeout(timeoutId);
2071
- }
2072
- timeoutId = setTimeout(() => {
2073
- callback(...lastArgs);
2074
- timeoutId = null;
2075
- lastArgs = null;
2076
- }, waitMs);
2077
- };
2078
- debouncedFn.cancel = () => {
2079
- if (timeoutId !== null) {
2080
- clearTimer();
2081
- }
2082
- };
2083
- debouncedFn.flush = () => {
2084
- if (timeoutId !== null) {
2085
- callback(...lastArgs);
2086
- clearTimer();
2087
- }
2088
- };
2089
- return debouncedFn;
2090
- };
2091
-
2092
2327
  // src/domain/components/searchComponent/SearchComponent.ts
2093
2328
  var DEBOUNCE_TIME = 400;
2094
2329
  var createSearchComponent = (searchProps, performSearch, onBehavior, onComponentUpdate) => {
@@ -2185,7 +2420,7 @@ var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultC
2185
2420
  if (requestHash !== latestSuccessfulRequestHash) {
2186
2421
  const { method, param, url } = config;
2187
2422
  const headers = { "Content-Type": "application/json" };
2188
- const response = await (method === "GET" ? httpClient(addQueryParameter(url, param, query), {
2423
+ const response = await (method === "GET" ? httpClient(addQueryParameter2(url, param, query), {
2189
2424
  method,
2190
2425
  headers,
2191
2426
  signal
@@ -2195,7 +2430,7 @@ var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultC
2195
2430
  signal,
2196
2431
  body: JSON.stringify({ [param]: query })
2197
2432
  }));
2198
- const results = await parseResponse(response);
2433
+ const results = await parseResponse2(response);
2199
2434
  latestSuccessfulRequestHash = requestHash;
2200
2435
  if (results.type === "layout") {
2201
2436
  const mappedLayoutResult = {
@@ -2211,7 +2446,7 @@ var getPerformSearchFunction = (httpClient, mapLayoutToDomainComponent, defaultC
2211
2446
  return latestSuccessfulResults;
2212
2447
  };
2213
2448
  };
2214
- var parseResponse = async (response) => {
2449
+ var parseResponse2 = async (response) => {
2215
2450
  if (response.ok) {
2216
2451
  const body = await response.json().catch(() => null);
2217
2452
  if (isValidResponseBody(body)) {
@@ -2228,7 +2463,7 @@ var parseResponse = async (response) => {
2228
2463
  }
2229
2464
  throw Error("error response");
2230
2465
  };
2231
- var addQueryParameter = (url, key, value) => {
2466
+ var addQueryParameter2 = (url, key, value) => {
2232
2467
  const [urlBase, urlQuery] = url.split("?");
2233
2468
  const urlQueryParams = new URLSearchParams(urlQuery);
2234
2469
  urlQueryParams.set(key, value);
@@ -2436,6 +2671,8 @@ var mapLayoutToComponent = (uid, layout, mapperProps, schemaComponents) => {
2436
2671
  return boxLayoutToComponent(uid, layout, mapperProps, schemaComponents);
2437
2672
  case "button":
2438
2673
  return buttonLayoutToComponent(uid, layout, mapperProps);
2674
+ case "collection":
2675
+ return collectionLayoutToComponent(uid, layout, mapperProps);
2439
2676
  case "columns":
2440
2677
  return columnsLayoutToComponent(uid, layout, mapperProps, schemaComponents);
2441
2678
  case "decision":
@@ -7451,6 +7688,34 @@ var mapBoxControl = ({
7451
7688
  return control;
7452
7689
  };
7453
7690
 
7691
+ // src/renderers/mappers/collectionComponentToProps.ts
7692
+ var collectionComponentToProps = (component, rendererMapperProps) => {
7693
+ var _a;
7694
+ return __spreadProps(__spreadValues(__spreadValues({}, pick(
7695
+ component,
7696
+ "uid",
7697
+ "analyticsId",
7698
+ "type",
7699
+ "control",
7700
+ "margin",
7701
+ "tags",
7702
+ "url",
7703
+ "method",
7704
+ "search",
7705
+ "filters"
7706
+ )), rendererMapperProps), {
7707
+ state: component.state.type === "empty" ? {
7708
+ type: "empty",
7709
+ children: component.state.content.map((child) => componentToRendererProps(child, rendererMapperProps)).map(rendererMapperProps.render)
7710
+ } : component.state,
7711
+ search: __spreadProps(__spreadValues({}, component.search), {
7712
+ query: (_a = component.search.query) != null ? _a : void 0
7713
+ }),
7714
+ filters: component.filters,
7715
+ loadMore: component.cursorStale ? void 0 : component.loadMore.bind(component)
7716
+ });
7717
+ };
7718
+
7454
7719
  // src/renderers/mappers/buttonComponentToProps.ts
7455
7720
  var buttonComponentToProps = (component, rendererMapperProps) => {
7456
7721
  return __spreadValues(__spreadProps(__spreadValues({
@@ -8275,6 +8540,8 @@ var getComponentProps = (component, rendererMapperProps) => {
8275
8540
  return boxComponentToProps(component, rendererMapperProps);
8276
8541
  case "button":
8277
8542
  return buttonComponentToProps(component, rendererMapperProps);
8543
+ case "collection":
8544
+ return collectionComponentToProps(component, rendererMapperProps);
8278
8545
  case "columns":
8279
8546
  return columnsComponentToProps(component, rendererMapperProps);
8280
8547
  case "container":