@transferwise/components 46.31.0 → 46.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/build/index.js +764 -474
  2. package/build/index.js.map +1 -1
  3. package/build/index.mjs +763 -474
  4. package/build/index.mjs.map +1 -1
  5. package/build/main.css +135 -0
  6. package/build/styles/carousel/Carousel.css +135 -0
  7. package/build/styles/main.css +135 -0
  8. package/build/types/carousel/Carousel.d.ts +26 -0
  9. package/build/types/carousel/Carousel.d.ts.map +1 -0
  10. package/build/types/carousel/index.d.ts +3 -0
  11. package/build/types/carousel/index.d.ts.map +1 -0
  12. package/build/types/common/card/Card.d.ts +2 -2
  13. package/build/types/common/card/Card.d.ts.map +1 -1
  14. package/build/types/common/domHelpers/documentIosClick.d.ts +0 -1
  15. package/build/types/common/domHelpers/documentIosClick.d.ts.map +1 -1
  16. package/build/types/common/domHelpers/index.d.ts +1 -1
  17. package/build/types/common/domHelpers/index.d.ts.map +1 -1
  18. package/build/types/dateLookup/DateLookup.d.ts.map +1 -1
  19. package/build/types/index.d.ts +2 -0
  20. package/build/types/index.d.ts.map +1 -1
  21. package/build/types/moneyInput/MoneyInput.d.ts +4 -2
  22. package/build/types/moneyInput/MoneyInput.d.ts.map +1 -1
  23. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts +1 -1
  24. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
  25. package/build/types/promoCard/PromoCard.d.ts +16 -5
  26. package/build/types/promoCard/PromoCard.d.ts.map +1 -1
  27. package/build/types/select/Select.d.ts +7 -7
  28. package/build/types/select/Select.d.ts.map +1 -1
  29. package/build/types/typeahead/Typeahead.d.ts +4 -55
  30. package/build/types/typeahead/Typeahead.d.ts.map +1 -1
  31. package/package.json +1 -1
  32. package/src/carousel/Carousel.css +135 -0
  33. package/src/carousel/Carousel.less +133 -0
  34. package/src/carousel/Carousel.spec.tsx +221 -0
  35. package/src/carousel/Carousel.story.tsx +63 -0
  36. package/src/carousel/Carousel.tsx +345 -0
  37. package/src/carousel/index.ts +3 -0
  38. package/src/common/card/Card.tsx +51 -43
  39. package/src/common/domHelpers/documentIosClick.ts +0 -5
  40. package/src/common/domHelpers/index.ts +0 -1
  41. package/src/dateLookup/DateLookup.rtl.spec.tsx +2 -3
  42. package/src/dateLookup/DateLookup.tsx +1 -3
  43. package/src/index.ts +2 -0
  44. package/src/inputs/SelectInput.spec.tsx +1 -1
  45. package/src/main.css +135 -0
  46. package/src/main.less +1 -0
  47. package/src/moneyInput/MoneyInput.rtl.spec.tsx +10 -0
  48. package/src/moneyInput/MoneyInput.spec.js +10 -5
  49. package/src/moneyInput/MoneyInput.tsx +21 -14
  50. package/src/phoneNumberInput/PhoneNumberInput.rtl.spec.tsx +10 -0
  51. package/src/phoneNumberInput/PhoneNumberInput.tsx +11 -2
  52. package/src/promoCard/PromoCard.story.tsx +2 -2
  53. package/src/promoCard/PromoCard.tsx +30 -9
  54. package/src/select/Select.js +18 -15
  55. package/src/select/Select.rtl.spec.tsx +17 -0
  56. package/src/select/Select.spec.js +2 -7
  57. package/src/typeahead/Typeahead.rtl.spec.tsx +16 -0
  58. package/src/typeahead/Typeahead.tsx +21 -7
package/build/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as React from 'react';
2
- import React__default, { forwardRef, cloneElement, useState, useEffect, useRef, useMemo, Component, useCallback, createContext, useContext, useImperativeHandle, createElement, PureComponent, createRef, isValidElement, Children, Fragment as Fragment$1 } from 'react';
2
+ import React__default, { forwardRef, cloneElement, useState, useEffect, useRef, useMemo, Component, createContext, useContext, useCallback, useImperativeHandle, createElement, PureComponent, createRef, isValidElement, Children, Fragment as Fragment$1 } from 'react';
3
3
  import { useId } from '@radix-ui/react-id';
4
4
  import classNames from 'classnames';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
- import { ChevronUp, CrossCircleFill, Cross, NavigateAway, Check, Info as Info$1, Alert as Alert$1, ClockBorderless, Briefcase, Person, AlertCircleFill, ArrowLeft, AlertCircle, QuestionMarkCircle, Search, CrossCircle, ChevronDown, CheckCircleFill, ArrowRight, Download, ClockFill, Upload as Upload$2, Document, Plus, PlusCircle } from '@transferwise/icons';
6
+ import { ChevronUp, CrossCircleFill, Cross, NavigateAway, Check, Info as Info$1, Alert as Alert$1, ClockBorderless, Briefcase, Person, ArrowRight, Download, ChevronLeft, ChevronRight, AlertCircleFill, ArrowLeft, AlertCircle, QuestionMarkCircle, Search, CrossCircle, ChevronDown, CheckCircleFill, ClockFill, Upload as Upload$2, Document, Plus, PlusCircle } from '@transferwise/icons';
7
7
  import { defineMessages, useIntl, injectIntl, IntlProvider } from 'react-intl';
8
8
  import PropTypes from 'prop-types';
9
9
  import commonmark from 'commonmark';
@@ -136,10 +136,6 @@ function stopPropagation$1(event) {
136
136
  event.nativeEvent.stopImmediatePropagation();
137
137
  }
138
138
  }
139
- function getSimpleRandomId(prefix) {
140
- const random = Math.ceil(Math.random() * 999999);
141
- return `${prefix}${random}`;
142
- }
143
139
 
144
140
  /**
145
141
  * Defined in `Dimmer.less`
@@ -1478,9 +1474,719 @@ const Button = /*#__PURE__*/forwardRef(({
1478
1474
  className: "btn-loader"
1479
1475
  })]
1480
1476
  });
1481
- });
1477
+ });
1478
+
1479
+ const Card$2 = /*#__PURE__*/forwardRef(({
1480
+ className,
1481
+ children = null,
1482
+ id,
1483
+ isDisabled = false,
1484
+ isSmall = false,
1485
+ onDismiss,
1486
+ testId,
1487
+ ...props
1488
+ }, ref) => {
1489
+ const closeButtonReference = useRef(null);
1490
+ return /*#__PURE__*/jsxs("div", {
1491
+ ref: ref,
1492
+ className: classNames('np-Card', {
1493
+ 'np-Card--small': !!isSmall,
1494
+ 'is-disabled': !!isDisabled
1495
+ }, className),
1496
+ id: id,
1497
+ "data-testid": testId,
1498
+ ...props,
1499
+ children: [onDismiss && /*#__PURE__*/jsx(CloseButton, {
1500
+ ref: closeButtonReference,
1501
+ className: "np-Card-closeButton",
1502
+ size: isSmall ? 'sm' : 'md',
1503
+ isDisabled: isDisabled,
1504
+ testId: "close-button",
1505
+ onClick: e => {
1506
+ stopPropagation$1(e);
1507
+ onDismiss();
1508
+ }
1509
+ }), children]
1510
+ });
1511
+ });
1512
+ Card$2.displayName = 'Card';
1513
+
1514
+ function Display({
1515
+ as: Heading = 'h1',
1516
+ type = Typography.DISPLAY_LARGE,
1517
+ children,
1518
+ className,
1519
+ id
1520
+ }) {
1521
+ return /*#__PURE__*/jsx(Heading, {
1522
+ id: id,
1523
+ className: classNames(`np-text-${type}`, 'text-primary', className),
1524
+ children: children
1525
+ });
1526
+ }
1527
+
1528
+ const useConditionalListener = ({
1529
+ attachListener,
1530
+ callback,
1531
+ eventType,
1532
+ parent
1533
+ }) => {
1534
+ useEffect(() => {
1535
+ if (attachListener && !isUndefined(parent)) {
1536
+ parent.addEventListener(eventType, callback, true);
1537
+ }
1538
+ return () => {
1539
+ if (!isUndefined(parent)) {
1540
+ parent.removeEventListener(eventType, callback, true);
1541
+ }
1542
+ };
1543
+ }, [attachListener, callback, eventType, parent]);
1544
+ };
1545
+
1546
+ const DirectionContext = /*#__PURE__*/createContext(Direction.LTR);
1547
+ const DirectionProvider = ({
1548
+ direction,
1549
+ children
1550
+ }) => {
1551
+ return /*#__PURE__*/jsx(DirectionContext.Provider, {
1552
+ value: direction,
1553
+ children: children
1554
+ });
1555
+ };
1556
+
1557
+ const useDirection = () => {
1558
+ const direction = useContext(DirectionContext);
1559
+ return {
1560
+ direction,
1561
+ isRTL: direction === 'rtl'
1562
+ };
1563
+ };
1564
+
1565
+ const ObserverParams = {
1566
+ threshold: 0.1
1567
+ };
1568
+
1569
+ /**
1570
+ * useHasIntersected.
1571
+ * Use this custom hook to detect when an element has became visible inside the viewport. This hook checks only if the intersection happend.
1572
+ * Once the intersection has happened the hook will not return false even if the element gets out of the viewport.
1573
+ *
1574
+ * @param elRef.elRef
1575
+ * @param {object} [elRef] - node object that contains a react reference to the element that needs to be observed.
1576
+ * @param {strimng} [loading = 'eager'] - string that contains the type of loading.
1577
+ * @param elRef.loading
1578
+ * @usage `const [hasIntersected] = useHasIntersected({imageRef,loading});`
1579
+ */
1580
+ const useHasIntersected = ({
1581
+ elRef,
1582
+ loading
1583
+ }) => {
1584
+ const [hasIntersected, setHasIntersected] = useState(false);
1585
+ const {
1586
+ current
1587
+ } = elRef || {};
1588
+ const isValidReference = () => {
1589
+ return elRef && current;
1590
+ };
1591
+ const handleOnIntersect = (entries, observer) => {
1592
+ entries.forEach(entry => {
1593
+ if (entry.isIntersecting) {
1594
+ setHasIntersected(true);
1595
+ observer.unobserve(current);
1596
+ }
1597
+ });
1598
+ };
1599
+ useEffect(() => {
1600
+ let observer;
1601
+ let didCancel = false;
1602
+
1603
+ // Check if window is define for SSR and Old browsers fallback
1604
+ if (typeof window === 'undefined' || !window.IntersectionObserver || !isValidReference()) {
1605
+ setHasIntersected(true);
1606
+ } else if (!didCancel) {
1607
+ observer = new IntersectionObserver(handleOnIntersect, ObserverParams);
1608
+ observer.observe(current);
1609
+ }
1610
+ return () => {
1611
+ didCancel = true;
1612
+ if (observer) {
1613
+ observer.unobserve(current);
1614
+ }
1615
+ };
1616
+ }, [elRef]);
1617
+ if (loading === 'eager') {
1618
+ return [false];
1619
+ }
1620
+ return [hasIntersected];
1621
+ };
1622
+
1623
+ // eslint-disable-next-line import/extensions
1624
+ function useMedia(query) {
1625
+ return useSyncExternalStore(onStoreChange => {
1626
+ const mediaQueryList = window.matchMedia(query);
1627
+ mediaQueryList.addEventListener('change', onStoreChange);
1628
+ return () => {
1629
+ mediaQueryList.removeEventListener('change', onStoreChange);
1630
+ };
1631
+ }, () => typeof window !== 'undefined' ? window.matchMedia(query).matches : undefined, () => undefined);
1632
+ }
1633
+
1634
+ function useScreenSize(size) {
1635
+ return useMedia(`(min-width: ${size}px)`);
1636
+ }
1637
+
1638
+ /**
1639
+ * @deprecated Prefer `useScreenSize` instead.
1640
+ */
1641
+ const useLayout = () => {
1642
+ const screenXs = useScreenSize(Breakpoint.EXTRA_SMALL);
1643
+ const screenSm = useScreenSize(Breakpoint.SMALL);
1644
+ const screenMd = useScreenSize(Breakpoint.MEDIUM);
1645
+ const screenLg = useScreenSize(Breakpoint.LARGE);
1646
+ const screenXl = useScreenSize(Breakpoint.EXTRA_LARGE);
1647
+ return {
1648
+ isMobile: screenSm != null ? !screenSm : undefined,
1649
+ isExtraSmall: screenXs,
1650
+ isSmall: screenSm,
1651
+ isMedium: screenMd,
1652
+ isLarge: screenLg,
1653
+ isExtraLarge: screenXl
1654
+ };
1655
+ };
1656
+
1657
+ const EmptyTransparentImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
1658
+ const Image = ({
1659
+ id,
1660
+ src,
1661
+ alt,
1662
+ onLoad,
1663
+ onError,
1664
+ className,
1665
+ loading,
1666
+ stretch = true,
1667
+ role,
1668
+ shrink = true
1669
+ }) => {
1670
+ const elementReference = useRef(null);
1671
+ const [hasIntersected] = useHasIntersected({
1672
+ elRef: elementReference,
1673
+ loading
1674
+ });
1675
+ let imageSource = src;
1676
+ let imageOnLoad = onLoad;
1677
+ if (loading === 'lazy' && !hasIntersected) {
1678
+ imageSource = EmptyTransparentImage;
1679
+ imageOnLoad = undefined;
1680
+ }
1681
+ return /*#__PURE__*/jsx("img", {
1682
+ ref: elementReference,
1683
+ id: id,
1684
+ alt: alt,
1685
+ src: imageSource,
1686
+ className: classNames(['tw-image', {
1687
+ 'tw-image__stretch': stretch,
1688
+ 'tw-image__shrink': shrink
1689
+ }, className]),
1690
+ role: role,
1691
+ onLoad: imageOnLoad,
1692
+ onError: onError
1693
+ });
1694
+ };
1695
+
1696
+ const defaultPromoCardContext = {
1697
+ state: '',
1698
+ isDisabled: false,
1699
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1700
+ onChange: () => {}
1701
+ };
1702
+ /**
1703
+ * The PromoCard context object.
1704
+ */
1705
+ const PromoCardContext = /*#__PURE__*/createContext(defaultPromoCardContext);
1706
+ /**
1707
+ * A custom hook for accessing the PromoCard context object.
1708
+ *
1709
+ * The `usePromoCardContext` hook is used to access the PromoCard context object
1710
+ * from within a child PromoCard component. It throws an error if the context
1711
+ * object is not available, which can help with debugging and development.
1712
+ *
1713
+ * @returns {PromoCardContextType} - The PromoCard context object.
1714
+ */
1715
+ const usePromoCardContext = () => {
1716
+ return useContext(PromoCardContext);
1717
+ };
1718
+
1719
+ const PromoCardIndicator = ({
1720
+ className,
1721
+ children,
1722
+ label,
1723
+ icon,
1724
+ isSmall = false,
1725
+ testid,
1726
+ ...rest
1727
+ }) => {
1728
+ const isIconString = icon && typeof icon === 'string';
1729
+ const IconComponent = isIconString && {
1730
+ check: Check,
1731
+ arrow: ArrowRight,
1732
+ download: Download
1733
+ }[icon];
1734
+ return /*#__PURE__*/jsxs("div", {
1735
+ className: classNames('np-Card-indicator', className),
1736
+ "data-testid": testid,
1737
+ ...rest,
1738
+ children: [label && /*#__PURE__*/jsx(Body, {
1739
+ as: "span",
1740
+ type: Typography.BODY_LARGE_BOLD,
1741
+ className: "np-Card-indicatorText",
1742
+ children: label
1743
+ }), icon && /*#__PURE__*/jsx(Avatar, {
1744
+ type: AvatarType.ICON,
1745
+ size: isSmall ? 40 : 56,
1746
+ backgroundColor: "var(--Card-indicator-icon-background-color)",
1747
+ className: "np-Card-indicatorIcon",
1748
+ children: IconComponent ? /*#__PURE__*/jsx(IconComponent, {
1749
+ size: 24,
1750
+ "aria-hidden": "true"
1751
+ }) : icon
1752
+ }), children]
1753
+ });
1754
+ };
1755
+
1756
+ const PromoCard = /*#__PURE__*/forwardRef(({
1757
+ className,
1758
+ description,
1759
+ defaultChecked,
1760
+ download,
1761
+ href,
1762
+ hrefLang,
1763
+ id,
1764
+ headingLevel = 'h3',
1765
+ imageAlt,
1766
+ imageClass,
1767
+ imageSource,
1768
+ indicatorLabel,
1769
+ indicatorIcon,
1770
+ isChecked,
1771
+ isDisabled,
1772
+ onClick,
1773
+ onKeyDown,
1774
+ rel,
1775
+ tabIndex,
1776
+ target,
1777
+ testId,
1778
+ title,
1779
+ type,
1780
+ value,
1781
+ isSmall,
1782
+ useDisplayFont = true,
1783
+ anchorRef,
1784
+ anchorId,
1785
+ ...props
1786
+ }, ref) => {
1787
+ // Set the `checked` state to the value of `defaultChecked` if it is truthy,
1788
+ // or the value of `isChecked` if it is truthy, or `false` if neither
1789
+ // is truthy.
1790
+ const {
1791
+ state,
1792
+ onChange,
1793
+ isDisabled: contextIsDisabled
1794
+ } = usePromoCardContext();
1795
+ const [checked, setChecked] = useState(type === 'checkbox' ? defaultChecked ?? isChecked ?? false : false);
1796
+ const handleClick = () => {
1797
+ if (type === 'radio') {
1798
+ onChange(value || ''); // Update the context state for radio
1799
+ } else if (type === 'checkbox') {
1800
+ setChecked(!checked); // Update local state for checkbox
1801
+ }
1802
+ };
1803
+ const fallbackId = useId();
1804
+ const componentId = id || fallbackId;
1805
+ // Set the icon to `'arrow'` if `href` is truthy and `type` is falsy, or
1806
+ // `'download'` if `download` is truthy. If neither condition is true, set
1807
+ // `icon` to `undefined`.
1808
+ // Create a function to get icon type
1809
+ const getIconType = () => {
1810
+ if (indicatorIcon) {
1811
+ return indicatorIcon;
1812
+ }
1813
+ if (download) {
1814
+ return 'download';
1815
+ }
1816
+ if (href && !type) {
1817
+ return 'arrow';
1818
+ }
1819
+ return undefined;
1820
+ };
1821
+ // Define all class names string based on the values of the `href`, `type`,
1822
+ // `checked`, and `className` props.
1823
+ const commonClasses = classNames({
1824
+ 'np-Card--promoCard': true,
1825
+ 'np-Card--checked': !href && type,
1826
+ 'np-Card--link': href && !type,
1827
+ 'is-checked': type === 'radio' ? value === state : type === 'checkbox' ? checked : undefined
1828
+ }, className);
1829
+ // Object with common props that will be passed to the `Card` components
1830
+ const commonProps = {
1831
+ className: commonClasses,
1832
+ id: componentId,
1833
+ isDisabled: isDisabled || contextIsDisabled,
1834
+ onClick,
1835
+ onKeyDown,
1836
+ ref,
1837
+ 'data-testid': testId,
1838
+ isSmall
1839
+ };
1840
+ // Object with Anchor props that will be passed to the `a` element. These
1841
+ // won't be refurned if set to `isDisabled`
1842
+ const anchorProps = href && !isDisabled ? {
1843
+ download,
1844
+ href: href || undefined,
1845
+ hrefLang,
1846
+ rel,
1847
+ target,
1848
+ ref: anchorRef,
1849
+ id: anchorId
1850
+ } : {};
1851
+ // Object of all Checked props that will be passed to the root `Card` component
1852
+ const checkedProps = (type === 'checkbox' || type === 'radio') && !href ? {
1853
+ ...commonProps,
1854
+ 'aria-checked': type === 'radio' ? value === state : type === 'checkbox' ? checked : undefined,
1855
+ 'aria-describedby': `${componentId}-title`,
1856
+ 'aria-disabled': isDisabled,
1857
+ 'data-value': value ?? undefined,
1858
+ role: type === 'checkbox' || type === 'radio' ? type : undefined,
1859
+ onClick: handleClick,
1860
+ onKeyDown: event => {
1861
+ if (event.key === 'Enter' || event.key === ' ') {
1862
+ handleClick();
1863
+ }
1864
+ },
1865
+ ref,
1866
+ tabIndex: 0
1867
+ } : {};
1868
+ const getTitle = () => {
1869
+ const titleContent = href && !type ? /*#__PURE__*/jsx("a", {
1870
+ className: "np-Card-titleLink",
1871
+ ...anchorProps,
1872
+ children: title
1873
+ }) : title;
1874
+ const titleProps = {
1875
+ id: `${componentId}-title`,
1876
+ as: headingLevel,
1877
+ className: 'np-Card-title'
1878
+ };
1879
+ return useDisplayFont ? /*#__PURE__*/jsx(Display, {
1880
+ type: Typography.DISPLAY_SMALL,
1881
+ ...titleProps,
1882
+ children: titleContent
1883
+ }) : /*#__PURE__*/jsx(Title, {
1884
+ type: Typography.TITLE_SUBSECTION,
1885
+ ...titleProps,
1886
+ children: titleContent
1887
+ });
1888
+ };
1889
+ useEffect(() => {
1890
+ setChecked(defaultChecked ?? isChecked ?? false);
1891
+ }, [defaultChecked, isChecked]);
1892
+ return /*#__PURE__*/jsxs(Card$2, {
1893
+ ...commonProps,
1894
+ ...checkedProps,
1895
+ ...props,
1896
+ children: [(value === state || checked) && /*#__PURE__*/jsx("span", {
1897
+ className: "np-Card-check",
1898
+ children: /*#__PURE__*/jsx(Check, {
1899
+ size: 24,
1900
+ "aria-hidden": "true"
1901
+ })
1902
+ }), getTitle(), /*#__PURE__*/jsx(Body, {
1903
+ className: "np-Card-description",
1904
+ children: description
1905
+ }), imageSource && /*#__PURE__*/jsx("div", {
1906
+ className: classNames('np-Card-image', {
1907
+ imageClass
1908
+ }),
1909
+ children: /*#__PURE__*/jsx(Image, {
1910
+ src: imageSource,
1911
+ alt: imageAlt || '',
1912
+ loading: "lazy"
1913
+ })
1914
+ }), /*#__PURE__*/jsx(PromoCardIndicator, {
1915
+ label: indicatorLabel,
1916
+ icon: getIconType(),
1917
+ isSmall: isSmall
1918
+ })]
1919
+ });
1920
+ });
1921
+ var PromoCard$1 = /*#__PURE__*/React__default.memo(PromoCard);
1922
+
1923
+ const LEFT_SCROLL_OFFSET = 8;
1924
+ const Carousel = ({
1925
+ header,
1926
+ className,
1927
+ cards,
1928
+ onClick
1929
+ }) => {
1930
+ const [scrollPosition, setScrollPosition] = useState(0);
1931
+ const [previousScrollPosition, setPreviousScrollPosition] = useState(0);
1932
+ const [scrollIsAtEnd, setScrollIsAtEnd] = useState(false);
1933
+ const [visibleCardOnMobileView, setVisibleCardOnMobileView] = useState('');
1934
+ const carouselElementRef = useRef(null);
1935
+ const carouselCardsRef = useRef([]);
1936
+ const isLeftActionButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;
1937
+ const areActionButtonsEnabled = isLeftActionButtonEnabled || !scrollIsAtEnd;
1938
+ const [focusedCard, setFocusedCard] = useState(cards?.[0]?.id);
1939
+ const updateScrollButtonsState = () => {
1940
+ if (carouselElementRef.current) {
1941
+ const {
1942
+ scrollWidth,
1943
+ offsetWidth
1944
+ } = carouselElementRef.current;
1945
+ const scrollAtEnd = scrollWidth - offsetWidth <= scrollPosition + LEFT_SCROLL_OFFSET;
1946
+ setScrollIsAtEnd(scrollAtEnd);
1947
+ }
1948
+ const scrollDirecton = scrollPosition > previousScrollPosition ? 'right' : 'left';
1949
+ const cardsInFullViewIds = [];
1950
+ carouselCardsRef.current.forEach(card => {
1951
+ if (isVisible(carouselElementRef.current, card.cardElement)) {
1952
+ // eslint-disable-next-line functional/immutable-data
1953
+ cardsInFullViewIds.push(card.cardElement.getAttribute('id') ?? '');
1954
+ }
1955
+ });
1956
+ if (cardsInFullViewIds.length >= 1) {
1957
+ const visibleCardIndex = scrollDirecton === 'right' ? cardsInFullViewIds.length - 1 : 0;
1958
+ const visibleCardId = cardsInFullViewIds[visibleCardIndex];
1959
+ setVisibleCardOnMobileView(visibleCardId);
1960
+ setFocusedCard(visibleCardId);
1961
+ }
1962
+ setPreviousScrollPosition(scrollPosition);
1963
+ };
1964
+ const scrollCarousel = (direction = 'right') => {
1965
+ if (carouselElementRef.current) {
1966
+ const {
1967
+ scrollWidth
1968
+ } = carouselElementRef.current;
1969
+ const cardWidth = scrollWidth / carouselCardsRef.current.length;
1970
+ const res = Math.floor(cardWidth - cardWidth * 0.05);
1971
+ carouselElementRef.current.scrollBy({
1972
+ left: direction === 'right' ? res : -res,
1973
+ behavior: 'smooth'
1974
+ });
1975
+ }
1976
+ };
1977
+ const handleOnKeyDown = (event, index) => {
1978
+ if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
1979
+ const nextIndex = event.key === 'ArrowRight' ? index + 1 : index - 1;
1980
+ const nextCard = cards[nextIndex];
1981
+ if (nextCard) {
1982
+ const ref = carouselCardsRef.current[nextIndex];
1983
+ if (ref.type === 'promo') {
1984
+ ref.anchorElement?.focus();
1985
+ } else {
1986
+ ref.cardElement?.focus();
1987
+ }
1988
+ scrollCardIntoView(carouselCardsRef.current[nextIndex].cardElement, nextCard);
1989
+ event.preventDefault();
1990
+ }
1991
+ }
1992
+ if (event.key === 'Enter' || event.key === ' ') {
1993
+ event.currentTarget.click();
1994
+ }
1995
+ };
1996
+ const scrollCardIntoView = (element, card) => {
1997
+ element.scrollIntoView({
1998
+ behavior: 'smooth',
1999
+ block: 'nearest',
2000
+ inline: 'center'
2001
+ });
2002
+ setFocusedCard(card.id);
2003
+ };
2004
+ useEffect(() => {
2005
+ updateScrollButtonsState();
2006
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2007
+ }, [scrollPosition]);
2008
+ useEffect(() => {
2009
+ window.addEventListener('resize', updateScrollButtonsState);
2010
+ return () => {
2011
+ window.removeEventListener('resize', updateScrollButtonsState);
2012
+ };
2013
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2014
+ }, []);
2015
+ const addElementToCardsRefArray = (index, ref) => {
2016
+ if (ref) {
2017
+ // eslint-disable-next-line functional/immutable-data
2018
+ carouselCardsRef.current[index] = {
2019
+ type: ref.type ?? carouselCardsRef.current?.[index]?.type,
2020
+ cardElement: ref.cardElement ?? carouselCardsRef.current?.[index]?.cardElement,
2021
+ anchorElement: ref.anchorElement ?? carouselCardsRef.current?.[index]?.anchorElement
2022
+ };
2023
+ }
2024
+ };
2025
+ return /*#__PURE__*/jsxs("div", {
2026
+ className: classNames('carousel-wrapper', className),
2027
+ children: [/*#__PURE__*/jsxs("div", {
2028
+ className: "d-flex justify-content-between carousel__header",
2029
+ children: [typeof header === 'string' ? /*#__PURE__*/jsx(Title, {
2030
+ as: "span",
2031
+ type: "title-body",
2032
+ children: header
2033
+ }) : header, areActionButtonsEnabled ? /*#__PURE__*/jsxs("div", {
2034
+ className: "hidden-xs",
2035
+ children: [/*#__PURE__*/jsx(ActionButton, {
2036
+ className: "carousel__scroll-button",
2037
+ tabIndex: -1,
2038
+ priority: "secondary",
2039
+ disabled: !isLeftActionButtonEnabled,
2040
+ "aria-hidden": "true",
2041
+ "data-testid": "scroll-carousel-left",
2042
+ onClick: () => scrollCarousel('left'),
2043
+ children: /*#__PURE__*/jsx(ChevronLeft, {})
2044
+ }), /*#__PURE__*/jsx(ActionButton, {
2045
+ tabIndex: -1,
2046
+ className: "carousel__scroll-button m-l-1",
2047
+ priority: "secondary",
2048
+ "aria-hidden": "true",
2049
+ "data-testid": "scroll-carousel-right",
2050
+ disabled: scrollIsAtEnd,
2051
+ onClick: () => scrollCarousel(),
2052
+ children: /*#__PURE__*/jsx(ChevronRight, {})
2053
+ })]
2054
+ }) : null]
2055
+ }), /*#__PURE__*/jsx("div", {
2056
+ ref: carouselElementRef,
2057
+ tabIndex: -1,
2058
+ role: "list",
2059
+ className: "carousel",
2060
+ onScroll: event => {
2061
+ const target = event.target;
2062
+ setScrollPosition(target.scrollLeft);
2063
+ },
2064
+ children: cards?.map((card, index) => {
2065
+ const sharedProps = {
2066
+ id: card.id,
2067
+ className: classNames('carousel__card', {
2068
+ 'carousel__card--focused': card.id === focusedCard
2069
+ }),
2070
+ onClick: () => {
2071
+ card.onClick?.();
2072
+ onClick?.(card.id);
2073
+ },
2074
+ onFocus: event => {
2075
+ scrollCardIntoView(event.currentTarget, card);
2076
+ }
2077
+ };
2078
+ const cardContent = card.type !== 'promo' ? /*#__PURE__*/jsx("div", {
2079
+ id: `${card.id}-content`,
2080
+ className: classNames('carousel__card-content', {
2081
+ [card.className ?? '']: !!card.className
2082
+ })
2083
+ // eslint-disable-next-line react/forbid-dom-props
2084
+ ,
2085
+ style: card.styles,
2086
+ children: card.content
2087
+ }) : null;
2088
+ if (card.type === 'button') {
2089
+ return /*#__PURE__*/jsx("div", {
2090
+ "aria-labelledby": `${card.id}-content`,
2091
+ role: "listitem",
2092
+ children: /*#__PURE__*/jsx("div", {
2093
+ ...sharedProps,
2094
+ ref: el => {
2095
+ if (el) {
2096
+ // eslint-disable-next-line functional/immutable-data
2097
+ carouselCardsRef.current[index] = {
2098
+ type: 'default',
2099
+ cardElement: el
2100
+ };
2101
+ }
2102
+ },
2103
+ role: "button",
2104
+ tabIndex: 0,
2105
+ onKeyDown: event => handleOnKeyDown(event, index),
2106
+ children: cardContent
2107
+ })
2108
+ }, card.id);
2109
+ }
2110
+ if (card.type === 'promo') {
2111
+ return /*#__PURE__*/jsx("div", {
2112
+ id: card.id,
2113
+ role: "listitem",
2114
+ "aria-labelledby": `${card.id}-anchor`,
2115
+ children: /*#__PURE__*/jsx(PromoCard$1, {
2116
+ ...card,
2117
+ type: undefined,
2118
+ ...sharedProps,
2119
+ ref: el => {
2120
+ if (el) {
2121
+ addElementToCardsRefArray(index, {
2122
+ type: 'promo',
2123
+ cardElement: el
2124
+ });
2125
+ }
2126
+ },
2127
+ anchorRef: el => {
2128
+ if (el) {
2129
+ addElementToCardsRefArray(index, {
2130
+ type: 'promo',
2131
+ anchorElement: el
2132
+ });
2133
+ }
2134
+ },
2135
+ anchorId: `${card.id}-anchor`,
2136
+ onKeyDown: event => handleOnKeyDown(event, index)
2137
+ })
2138
+ }, card.id);
2139
+ }
2140
+ return /*#__PURE__*/jsx("div", {
2141
+ "aria-labelledby": `${card.id}-content`,
2142
+ role: "listitem",
2143
+ children: /*#__PURE__*/jsx("a", {
2144
+ ...sharedProps,
2145
+ ref: el => {
2146
+ if (el) {
2147
+ // eslint-disable-next-line functional/immutable-data
2148
+ carouselCardsRef.current[index] = {
2149
+ type: 'default',
2150
+ cardElement: el
2151
+ };
2152
+ }
2153
+ },
2154
+ href: card.href,
2155
+ rel: "noreferrer",
2156
+ onKeyDown: event => handleOnKeyDown(event, index),
2157
+ children: cardContent
2158
+ })
2159
+ }, card.id);
2160
+ })
2161
+ }), /*#__PURE__*/jsx("div", {
2162
+ className: "visible-xs",
2163
+ children: /*#__PURE__*/jsx("div", {
2164
+ className: "carousel__indicators",
2165
+ children: cards?.map((card, index) => /*#__PURE__*/jsx("button", {
2166
+ "data-testid": `${card.id}-indicator`,
2167
+ tabIndex: -1,
2168
+ "aria-hidden": true,
2169
+ type: "button",
2170
+ className: classNames('carousel__indicator', {
2171
+ 'carousel__indicator--selected': card.id === visibleCardOnMobileView
2172
+ }),
2173
+ onClick: () => {
2174
+ scrollCardIntoView(carouselCardsRef.current[index].cardElement, card);
2175
+ }
2176
+ }, `${card.id}-indicator`))
2177
+ })
2178
+ })]
2179
+ });
2180
+ };
2181
+ const isVisible = (container, el) => {
2182
+ const cWidth = container.offsetWidth;
2183
+ const cScrollOffset = container.scrollLeft;
2184
+ const elemLeft = el.offsetLeft - container.offsetLeft;
2185
+ const elemRight = elemLeft + el.offsetWidth;
2186
+ return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;
2187
+ };
1482
2188
 
1483
- const Card$1 = /*#__PURE__*/forwardRef((props, reference) => {
2189
+ const Card = /*#__PURE__*/forwardRef((props, reference) => {
1484
2190
  const {
1485
2191
  'aria-label': ariaLabel,
1486
2192
  as: Element,
@@ -1531,7 +2237,7 @@ const Card$1 = /*#__PURE__*/forwardRef((props, reference) => {
1531
2237
  const hasChildren = ({
1532
2238
  children
1533
2239
  }) => children;
1534
- Card$1.propTypes = {
2240
+ Card.propTypes = {
1535
2241
  'aria-label': PropTypes.string,
1536
2242
  as: PropTypes.string,
1537
2243
  isExpanded: requiredIf(PropTypes.bool, hasChildren),
@@ -1544,7 +2250,7 @@ Card$1.propTypes = {
1544
2250
  className: PropTypes.string,
1545
2251
  'data-testid': PropTypes.string
1546
2252
  };
1547
- Card$1.defaultProps = {
2253
+ Card.defaultProps = {
1548
2254
  'aria-label': undefined,
1549
2255
  as: 'div',
1550
2256
  children: null,
@@ -1552,7 +2258,7 @@ Card$1.defaultProps = {
1552
2258
  className: null,
1553
2259
  'data-testid': null
1554
2260
  };
1555
- var Card$2 = Card$1;
2261
+ var Card$1 = Card;
1556
2262
 
1557
2263
  const CheckboxButton = /*#__PURE__*/forwardRef(({
1558
2264
  checked,
@@ -2038,135 +2744,6 @@ const DimmerContentWrapper = ({
2038
2744
  };
2039
2745
  var Dimmer$1 = withNextPortalWrapper(Dimmer);
2040
2746
 
2041
- const useConditionalListener = ({
2042
- attachListener,
2043
- callback,
2044
- eventType,
2045
- parent
2046
- }) => {
2047
- useEffect(() => {
2048
- if (attachListener && !isUndefined(parent)) {
2049
- parent.addEventListener(eventType, callback, true);
2050
- }
2051
- return () => {
2052
- if (!isUndefined(parent)) {
2053
- parent.removeEventListener(eventType, callback, true);
2054
- }
2055
- };
2056
- }, [attachListener, callback, eventType, parent]);
2057
- };
2058
-
2059
- const DirectionContext = /*#__PURE__*/createContext(Direction.LTR);
2060
- const DirectionProvider = ({
2061
- direction,
2062
- children
2063
- }) => {
2064
- return /*#__PURE__*/jsx(DirectionContext.Provider, {
2065
- value: direction,
2066
- children: children
2067
- });
2068
- };
2069
-
2070
- const useDirection = () => {
2071
- const direction = useContext(DirectionContext);
2072
- return {
2073
- direction,
2074
- isRTL: direction === 'rtl'
2075
- };
2076
- };
2077
-
2078
- const ObserverParams = {
2079
- threshold: 0.1
2080
- };
2081
-
2082
- /**
2083
- * useHasIntersected.
2084
- * Use this custom hook to detect when an element has became visible inside the viewport. This hook checks only if the intersection happend.
2085
- * Once the intersection has happened the hook will not return false even if the element gets out of the viewport.
2086
- *
2087
- * @param elRef.elRef
2088
- * @param {object} [elRef] - node object that contains a react reference to the element that needs to be observed.
2089
- * @param {strimng} [loading = 'eager'] - string that contains the type of loading.
2090
- * @param elRef.loading
2091
- * @usage `const [hasIntersected] = useHasIntersected({imageRef,loading});`
2092
- */
2093
- const useHasIntersected = ({
2094
- elRef,
2095
- loading
2096
- }) => {
2097
- const [hasIntersected, setHasIntersected] = useState(false);
2098
- const {
2099
- current
2100
- } = elRef || {};
2101
- const isValidReference = () => {
2102
- return elRef && current;
2103
- };
2104
- const handleOnIntersect = (entries, observer) => {
2105
- entries.forEach(entry => {
2106
- if (entry.isIntersecting) {
2107
- setHasIntersected(true);
2108
- observer.unobserve(current);
2109
- }
2110
- });
2111
- };
2112
- useEffect(() => {
2113
- let observer;
2114
- let didCancel = false;
2115
-
2116
- // Check if window is define for SSR and Old browsers fallback
2117
- if (typeof window === 'undefined' || !window.IntersectionObserver || !isValidReference()) {
2118
- setHasIntersected(true);
2119
- } else if (!didCancel) {
2120
- observer = new IntersectionObserver(handleOnIntersect, ObserverParams);
2121
- observer.observe(current);
2122
- }
2123
- return () => {
2124
- didCancel = true;
2125
- if (observer) {
2126
- observer.unobserve(current);
2127
- }
2128
- };
2129
- }, [elRef]);
2130
- if (loading === 'eager') {
2131
- return [false];
2132
- }
2133
- return [hasIntersected];
2134
- };
2135
-
2136
- // eslint-disable-next-line import/extensions
2137
- function useMedia(query) {
2138
- return useSyncExternalStore(onStoreChange => {
2139
- const mediaQueryList = window.matchMedia(query);
2140
- mediaQueryList.addEventListener('change', onStoreChange);
2141
- return () => {
2142
- mediaQueryList.removeEventListener('change', onStoreChange);
2143
- };
2144
- }, () => typeof window !== 'undefined' ? window.matchMedia(query).matches : undefined, () => undefined);
2145
- }
2146
-
2147
- function useScreenSize(size) {
2148
- return useMedia(`(min-width: ${size}px)`);
2149
- }
2150
-
2151
- /**
2152
- * @deprecated Prefer `useScreenSize` instead.
2153
- */
2154
- const useLayout = () => {
2155
- const screenXs = useScreenSize(Breakpoint.EXTRA_SMALL);
2156
- const screenSm = useScreenSize(Breakpoint.SMALL);
2157
- const screenMd = useScreenSize(Breakpoint.MEDIUM);
2158
- const screenLg = useScreenSize(Breakpoint.LARGE);
2159
- const screenXl = useScreenSize(Breakpoint.EXTRA_LARGE);
2160
- return {
2161
- isMobile: screenSm != null ? !screenSm : undefined,
2162
- isExtraSmall: screenXs,
2163
- isSmall: screenSm,
2164
- isMedium: screenMd,
2165
- isLarge: screenLg,
2166
- isExtraLarge: screenXl
2167
- };
2168
- };
2169
-
2170
2747
  const EXIT_ANIMATION = 350;
2171
2748
  const SlidingPanel = /*#__PURE__*/forwardRef(({
2172
2749
  position = 'left',
@@ -2446,39 +3023,6 @@ const BottomSheet$1 = props => {
2446
3023
  });
2447
3024
  };
2448
3025
 
2449
- const Card = ({
2450
- className,
2451
- children = null,
2452
- id,
2453
- isDisabled = false,
2454
- isSmall = false,
2455
- onDismiss,
2456
- testId,
2457
- ...props
2458
- }) => {
2459
- const closeButtonReference = useRef(null);
2460
- return /*#__PURE__*/jsxs("div", {
2461
- className: classNames('np-Card', {
2462
- 'np-Card--small': !!isSmall,
2463
- 'is-disabled': !!isDisabled
2464
- }, className),
2465
- id: id,
2466
- "data-testid": testId,
2467
- ...props,
2468
- children: [onDismiss && /*#__PURE__*/jsx(CloseButton, {
2469
- ref: closeButtonReference,
2470
- className: "np-Card-closeButton",
2471
- size: isSmall ? 'sm' : 'md',
2472
- isDisabled: isDisabled,
2473
- testId: "close-button",
2474
- onClick: e => {
2475
- stopPropagation$1(e);
2476
- onDismiss();
2477
- }
2478
- }), children]
2479
- });
2480
- };
2481
-
2482
3026
  function CriticalCommsBanner({
2483
3027
  title,
2484
3028
  subtitle,
@@ -4336,20 +4880,6 @@ DefinitionList.defaultProps = {
4336
4880
  };
4337
4881
  var DefinitionList$1 = DefinitionList;
4338
4882
 
4339
- function Display({
4340
- as: Heading = 'h1',
4341
- type = Typography.DISPLAY_LARGE,
4342
- children,
4343
- className,
4344
- id
4345
- }) {
4346
- return /*#__PURE__*/jsx(Heading, {
4347
- id: id,
4348
- className: classNames(`np-text-${type}`, 'text-primary', className),
4349
- children: children
4350
- });
4351
- }
4352
-
4353
4883
  const DropFade = ({
4354
4884
  children,
4355
4885
  show
@@ -5062,45 +5592,6 @@ const Header = ({
5062
5592
  });
5063
5593
  };
5064
5594
 
5065
- const EmptyTransparentImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
5066
- const Image = ({
5067
- id,
5068
- src,
5069
- alt,
5070
- onLoad,
5071
- onError,
5072
- className,
5073
- loading,
5074
- stretch = true,
5075
- role,
5076
- shrink = true
5077
- }) => {
5078
- const elementReference = useRef(null);
5079
- const [hasIntersected] = useHasIntersected({
5080
- elRef: elementReference,
5081
- loading
5082
- });
5083
- let imageSource = src;
5084
- let imageOnLoad = onLoad;
5085
- if (loading === 'lazy' && !hasIntersected) {
5086
- imageSource = EmptyTransparentImage;
5087
- imageOnLoad = undefined;
5088
- }
5089
- return /*#__PURE__*/jsx("img", {
5090
- ref: elementReference,
5091
- id: id,
5092
- alt: alt,
5093
- src: imageSource,
5094
- className: classNames(['tw-image', {
5095
- 'tw-image__stretch': stretch,
5096
- 'tw-image__shrink': shrink
5097
- }, className]),
5098
- role: role,
5099
- onLoad: imageOnLoad,
5100
- onError: onError
5101
- });
5102
- };
5103
-
5104
5595
  // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
5105
5596
  var InfoPresentation;
5106
5597
  (function (InfoPresentation) {
@@ -6935,9 +7426,8 @@ const formatAmountIfSet = ({
6935
7426
  }) => {
6936
7427
  if (maxLengthOverride) {
6937
7428
  return amount != null ? String(amount) : '';
6938
- } else {
6939
- return typeof amount === 'number' ? formatAmount(amount, currency, locale) : '';
6940
7429
  }
7430
+ return typeof amount === 'number' ? formatAmount(amount, currency, locale) : '';
6941
7431
  };
6942
7432
  const parseNumber = ({
6943
7433
  amount,
@@ -6995,7 +7485,7 @@ class MoneyInput extends Component {
6995
7485
  key,
6996
7486
  ctrlKey
6997
7487
  } = event;
6998
- const isNumberKey = isNumber(parseInt(key, 10));
7488
+ const isNumberKey = isNumber(Number.parseInt(key, 10));
6999
7489
  return isNumberKey || metaKey || ctrlKey || allowedInputKeys.has(key);
7000
7490
  };
7001
7491
  handleKeyDown = event => {
@@ -7011,7 +7501,7 @@ class MoneyInput extends Component {
7011
7501
  const parsed = isEmpty(paste) ? null : parseNumber({
7012
7502
  amount: paste,
7013
7503
  currency: this.props.selectedCurrency.currency,
7014
- locale: locale,
7504
+ locale,
7015
7505
  maxLengthOverride: this.props.maxLengthOverride
7016
7506
  });
7017
7507
  if (isNumberOrNull(parsed)) {
@@ -7019,7 +7509,7 @@ class MoneyInput extends Component {
7019
7509
  formattedAmount: formatAmountIfSet({
7020
7510
  amount: parsed,
7021
7511
  currency: this.props.selectedCurrency.currency,
7022
- locale: locale,
7512
+ locale,
7023
7513
  maxLengthOverride: this.props.maxLengthOverride
7024
7514
  })
7025
7515
  });
@@ -7116,15 +7606,17 @@ class MoneyInput extends Component {
7116
7606
  style = className => this.props.classNames[className] || className;
7117
7607
  render() {
7118
7608
  const {
7609
+ inputAttributes,
7610
+ id: amountInputId,
7611
+ 'aria-labelledby': ariaLabelledByProp,
7119
7612
  selectedCurrency,
7120
7613
  onCurrencyChange,
7121
7614
  size,
7122
7615
  addon,
7123
- id,
7124
- 'aria-labelledby': ariaLabelledBy,
7125
7616
  selectProps,
7126
7617
  maxLengthOverride
7127
7618
  } = this.props;
7619
+ const ariaLabelledBy = ariaLabelledByProp ?? inputAttributes?.['aria-labelledby'];
7128
7620
  const selectOptions = this.getSelectOptions();
7129
7621
  const hasSingleCurrency = () => {
7130
7622
  if (selectOptions.length !== 0) {
@@ -7145,10 +7637,12 @@ class MoneyInput extends Component {
7145
7637
  const isFixedCurrency = !this.state.searchQuery && hasSingleCurrency() || !onCurrencyChange;
7146
7638
  const disabled = !this.props.onAmountChange;
7147
7639
  return /*#__PURE__*/jsxs("div", {
7640
+ role: "group",
7641
+ ...inputAttributes,
7148
7642
  "aria-labelledby": ariaLabelledBy,
7149
7643
  className: classNames(this.style('tw-money-input'), this.style('input-group'), this.style(`input-group-${size}`)),
7150
7644
  children: [/*#__PURE__*/jsx(Input, {
7151
- id: id,
7645
+ id: amountInputId,
7152
7646
  value: this.state.formattedAmount,
7153
7647
  inputMode: "decimal",
7154
7648
  disabled: disabled,
@@ -7249,7 +7743,7 @@ function currencyOptionFitsQuery(option, query) {
7249
7743
  return contains(option.label, query) || contains(option.searchable, query) || contains(option.note, query);
7250
7744
  }
7251
7745
  function contains(property, query) {
7252
- return property && property.toLowerCase().includes(query.toLowerCase());
7746
+ return property?.toLowerCase().includes(query.toLowerCase());
7253
7747
  }
7254
7748
  function sortOptionsLabelsToFirst(options, query) {
7255
7749
  return [...options].sort((first, second) => {
@@ -7267,7 +7761,9 @@ function sortOptionsLabelsToFirst(options, query) {
7267
7761
  return 0;
7268
7762
  });
7269
7763
  }
7270
- var MoneyInput$1 = injectIntl(MoneyInput);
7764
+ var MoneyInput$1 = injectIntl(withInputAttributes(MoneyInput, {
7765
+ nonLabelable: true
7766
+ }));
7271
7767
 
7272
7768
  const NavigationOptionList = ({
7273
7769
  children
@@ -8788,7 +9284,7 @@ const defaultSelectProps = {};
8788
9284
  const defaultDisabledCountries = [];
8789
9285
  const PhoneNumberInput = ({
8790
9286
  id,
8791
- 'aria-labelledby': ariaLabelledBy,
9287
+ 'aria-labelledby': ariaLabelledByProp,
8792
9288
  required,
8793
9289
  disabled,
8794
9290
  initialValue,
@@ -8802,6 +9298,10 @@ const PhoneNumberInput = ({
8802
9298
  selectProps = defaultSelectProps,
8803
9299
  disabledCountries = defaultDisabledCountries
8804
9300
  }) => {
9301
+ const inputAttributes = useInputAttributes({
9302
+ nonLabelable: true
9303
+ });
9304
+ const ariaLabelledBy = ariaLabelledByProp ?? inputAttributes['aria-labelledby'];
8805
9305
  const {
8806
9306
  locale,
8807
9307
  formatMessage
@@ -8858,6 +9358,8 @@ const PhoneNumberInput = ({
8858
9358
  setBroadcastedValue(internalValue);
8859
9359
  }, [onChange, broadcastedValue, internalValue]);
8860
9360
  return /*#__PURE__*/jsxs("div", {
9361
+ role: "group",
9362
+ ...inputAttributes,
8861
9363
  "aria-labelledby": ariaLabelledBy,
8862
9364
  className: "tw-telephone",
8863
9365
  children: [/*#__PURE__*/jsx("div", {
@@ -8970,227 +9472,6 @@ const ProgressBar = ({
8970
9472
  });
8971
9473
  };
8972
9474
 
8973
- const defaultPromoCardContext = {
8974
- state: '',
8975
- isDisabled: false,
8976
- // eslint-disable-next-line @typescript-eslint/no-empty-function
8977
- onChange: () => {}
8978
- };
8979
- /**
8980
- * The PromoCard context object.
8981
- */
8982
- const PromoCardContext = /*#__PURE__*/createContext(defaultPromoCardContext);
8983
- /**
8984
- * A custom hook for accessing the PromoCard context object.
8985
- *
8986
- * The `usePromoCardContext` hook is used to access the PromoCard context object
8987
- * from within a child PromoCard component. It throws an error if the context
8988
- * object is not available, which can help with debugging and development.
8989
- *
8990
- * @returns {PromoCardContextType} - The PromoCard context object.
8991
- */
8992
- const usePromoCardContext = () => {
8993
- return useContext(PromoCardContext);
8994
- };
8995
-
8996
- const PromoCardIndicator = ({
8997
- className,
8998
- children,
8999
- label,
9000
- icon,
9001
- isSmall = false,
9002
- testid,
9003
- ...rest
9004
- }) => {
9005
- const isIconString = icon && typeof icon === 'string';
9006
- const IconComponent = isIconString && {
9007
- check: Check,
9008
- arrow: ArrowRight,
9009
- download: Download
9010
- }[icon];
9011
- return /*#__PURE__*/jsxs("div", {
9012
- className: classNames('np-Card-indicator', className),
9013
- "data-testid": testid,
9014
- ...rest,
9015
- children: [label && /*#__PURE__*/jsx(Body, {
9016
- as: "span",
9017
- type: Typography.BODY_LARGE_BOLD,
9018
- className: "np-Card-indicatorText",
9019
- children: label
9020
- }), icon && /*#__PURE__*/jsx(Avatar, {
9021
- type: AvatarType.ICON,
9022
- size: isSmall ? 40 : 56,
9023
- backgroundColor: "var(--Card-indicator-icon-background-color)",
9024
- className: "np-Card-indicatorIcon",
9025
- children: IconComponent ? /*#__PURE__*/jsx(IconComponent, {
9026
- size: 24,
9027
- "aria-hidden": "true"
9028
- }) : icon
9029
- }), children]
9030
- });
9031
- };
9032
-
9033
- const PromoCard = /*#__PURE__*/forwardRef(({
9034
- className,
9035
- description,
9036
- defaultChecked,
9037
- download,
9038
- href,
9039
- hrefLang,
9040
- id,
9041
- headingLevel = 'h3',
9042
- imageAlt,
9043
- imageClass,
9044
- imageSource,
9045
- indicatorLabel,
9046
- indicatorIcon,
9047
- isChecked,
9048
- isDisabled,
9049
- onClick,
9050
- rel,
9051
- tabIndex,
9052
- target,
9053
- testId,
9054
- title,
9055
- type,
9056
- value,
9057
- isSmall,
9058
- useDisplayFont = true,
9059
- ...props
9060
- }, reference) => {
9061
- // Set the `checked` state to the value of `defaultChecked` if it is truthy,
9062
- // or the value of `isChecked` if it is truthy, or `false` if neither
9063
- // is truthy.
9064
- const {
9065
- state,
9066
- onChange,
9067
- isDisabled: contextIsDisabled
9068
- } = usePromoCardContext();
9069
- const [checked, setChecked] = useState(type === 'checkbox' ? defaultChecked ?? isChecked ?? false : false);
9070
- const handleClick = () => {
9071
- if (type === 'radio') {
9072
- onChange(value || ''); // Update the context state for radio
9073
- } else if (type === 'checkbox') {
9074
- setChecked(!checked); // Update local state for checkbox
9075
- }
9076
- };
9077
- const fallbackId = useId();
9078
- const componentId = id || fallbackId;
9079
- // Set the icon to `'arrow'` if `href` is truthy and `type` is falsy, or
9080
- // `'download'` if `download` is truthy. If neither condition is true, set
9081
- // `icon` to `undefined`.
9082
- // Create a function to get icon type
9083
- const getIconType = () => {
9084
- if (indicatorIcon) {
9085
- return indicatorIcon;
9086
- }
9087
- if (download) {
9088
- return 'download';
9089
- }
9090
- if (href && !type) {
9091
- return 'arrow';
9092
- }
9093
- return undefined;
9094
- };
9095
- // Define all class names string based on the values of the `href`, `type`,
9096
- // `checked`, and `className` props.
9097
- const commonClasses = classNames({
9098
- 'np-Card--promoCard': true,
9099
- 'np-Card--checked': !href && type,
9100
- 'np-Card--link': href && !type,
9101
- 'is-checked': type === 'radio' ? value === state : type === 'checkbox' ? checked : undefined
9102
- }, className);
9103
- // Object with common props that will be passed to the `Card` components
9104
- const commonProps = {
9105
- className: commonClasses,
9106
- id: componentId,
9107
- isDisabled: isDisabled || contextIsDisabled,
9108
- onClick,
9109
- ref: reference,
9110
- 'data-testid': testId,
9111
- isSmall
9112
- };
9113
- // Object with Anchor props that will be passed to the `a` element. These
9114
- // won't be refurned if set to `isDisabled`
9115
- const anchorProps = href && !isDisabled ? {
9116
- download,
9117
- href: href || undefined,
9118
- hrefLang,
9119
- rel,
9120
- target
9121
- } : {};
9122
- // Object of all Checked props that will be passed to the root `Card` component
9123
- const checkedProps = (type === 'checkbox' || type === 'radio') && !href ? {
9124
- ...commonProps,
9125
- 'aria-checked': type === 'radio' ? value === state : type === 'checkbox' ? checked : undefined,
9126
- 'aria-describedby': `${componentId}-title`,
9127
- 'aria-disabled': isDisabled,
9128
- 'data-value': value ?? undefined,
9129
- role: type === 'checkbox' || type === 'radio' ? type : undefined,
9130
- onClick: handleClick,
9131
- onKeyDown: event => {
9132
- if (event.key === 'Enter' || event.key === ' ') {
9133
- handleClick();
9134
- }
9135
- },
9136
- ref: reference,
9137
- tabIndex: 0
9138
- } : {};
9139
- const getTitle = () => {
9140
- const titleContent = href && !type ? /*#__PURE__*/jsx("a", {
9141
- className: "np-Card-titleLink",
9142
- ...anchorProps,
9143
- children: title
9144
- }) : title;
9145
- const titleProps = {
9146
- id: `${componentId}-title`,
9147
- as: headingLevel,
9148
- className: 'np-Card-title'
9149
- };
9150
- return useDisplayFont ? /*#__PURE__*/jsx(Display, {
9151
- type: Typography.DISPLAY_SMALL,
9152
- ...titleProps,
9153
- children: titleContent
9154
- }) : /*#__PURE__*/jsx(Title, {
9155
- type: Typography.TITLE_SUBSECTION,
9156
- ...titleProps,
9157
- children: titleContent
9158
- });
9159
- };
9160
- useEffect(() => {
9161
- setChecked(defaultChecked ?? isChecked ?? false);
9162
- }, [defaultChecked, isChecked]);
9163
- return /*#__PURE__*/jsxs(Card, {
9164
- ...commonProps,
9165
- ...checkedProps,
9166
- ...props,
9167
- children: [(value === state || checked) && /*#__PURE__*/jsx("span", {
9168
- className: "np-Card-check",
9169
- children: /*#__PURE__*/jsx(Check, {
9170
- size: 24,
9171
- "aria-hidden": "true"
9172
- })
9173
- }), getTitle(), /*#__PURE__*/jsx(Body, {
9174
- className: "np-Card-description",
9175
- children: description
9176
- }), imageSource && /*#__PURE__*/jsx("div", {
9177
- className: classNames('np-Card-image', {
9178
- imageClass
9179
- }),
9180
- children: /*#__PURE__*/jsx(Image, {
9181
- src: imageSource,
9182
- alt: imageAlt || '',
9183
- loading: "lazy"
9184
- })
9185
- }), /*#__PURE__*/jsx(PromoCardIndicator, {
9186
- label: indicatorLabel,
9187
- icon: getIconType(),
9188
- isSmall: isSmall
9189
- })]
9190
- });
9191
- });
9192
- var PromoCard$1 = /*#__PURE__*/React__default.memo(PromoCard);
9193
-
9194
9475
  const PromoCardGroup = ({
9195
9476
  children,
9196
9477
  className,
@@ -9811,6 +10092,7 @@ function Select({
9811
10092
  dropdownProps,
9812
10093
  buttonProps
9813
10094
  }) {
10095
+ const inputAttributes = useInputAttributes();
9814
10096
  const {
9815
10097
  formatMessage
9816
10098
  } = useIntl();
@@ -9830,7 +10112,6 @@ function Select({
9830
10112
  const optionsListReference = useRef(null);
9831
10113
  const isSearchEnabled = !!onSearchChange || !!search;
9832
10114
  const isDropdownAutoWidth = dropdownWidth == null;
9833
- const fallbackButtonId = useMemo(() => getSimpleRandomId('np-select-'), []);
9834
10115
  const options = useMemo(() => {
9835
10116
  if (!search || !searchValue) {
9836
10117
  return defaultOptions;
@@ -9838,14 +10119,14 @@ function Select({
9838
10119
  return defaultOptions.filter(isSearchableOption).filter(option => {
9839
10120
  if (typeof search === 'function') {
9840
10121
  return search(option, searchValue);
9841
- } else {
9842
- return defaultFilterFunction(option, searchValue);
9843
10122
  }
10123
+ return defaultFilterFunction(option, searchValue);
9844
10124
  });
9845
10125
  }, [defaultOptions, search, searchValue]);
9846
10126
  const selectableOptions = useMemo(() => options.filter(isActionableOption), [options]);
9847
10127
  const focusedOption = selectableOptions[keyboardFocusedOptionIndex];
9848
- const computedId = id || fallbackButtonId;
10128
+ const fallbackButtonId = useId();
10129
+ const computedId = id || inputAttributes.id || fallbackButtonId;
9849
10130
  const listboxId = `${computedId}-listbox`;
9850
10131
  const searchBoxId = `${computedId}-searchbox`;
9851
10132
  const {
@@ -9976,7 +10257,7 @@ function Select({
9976
10257
  useEffect(() => {
9977
10258
  if (open) {
9978
10259
  if (!isMobile || searchValue) {
9979
- if (isSearchEnabled && !!searchBoxReference.current) {
10260
+ if (isSearchEnabled && searchBoxReference.current) {
9980
10261
  searchBoxReference.current.focus();
9981
10262
  }
9982
10263
  if (!isSearchEnabled && optionsListReference.current && (previousKeyboardFocusedOptionIndex.current == null || Number.isNaN(previousKeyboardFocusedOptionIndex.current))) {
@@ -10162,6 +10443,7 @@ function Select({
10162
10443
  onBlur: handleOnBlur,
10163
10444
  children: [/*#__PURE__*/jsxs(Button, {
10164
10445
  ref: dropdownButtonReference,
10446
+ ...inputAttributes,
10165
10447
  id: computedId,
10166
10448
  block: block,
10167
10449
  size: size,
@@ -10237,9 +10519,6 @@ Select.propTypes = {
10237
10519
  * if `function` you can define your own search function to implement custom search experience. This search function used while filtering the options array. The custom search function takes two parameters. First is the option the second is the keyword.
10238
10520
  */
10239
10521
  search: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
10240
- onChange: PropTypes.func.isRequired,
10241
- onFocus: PropTypes.func,
10242
- onBlur: PropTypes.func,
10243
10522
  options: PropTypes.arrayOf(PropTypes.shape({
10244
10523
  value: PropTypes.any,
10245
10524
  label: PropTypes.node,
@@ -10252,17 +10531,20 @@ Select.propTypes = {
10252
10531
  disabled: PropTypes.bool,
10253
10532
  searchStrings: PropTypes.arrayOf(PropTypes.string)
10254
10533
  })).isRequired,
10255
- /**
10256
- * To have full control of your search value and response use `onSearchChange` function combined with `searchValue` and custom filtering on the options array.
10257
- * DO NOT USE TOGETHER WITH `search` PROPERTY
10258
- */
10259
- onSearchChange: PropTypes.func,
10260
10534
  searchValue: PropTypes.string,
10261
10535
  searchPlaceholder: PropTypes.string,
10262
10536
  classNames: PropTypes.objectOf(PropTypes.string),
10263
10537
  dropdownUp: PropTypes.bool,
10264
10538
  buttonProps: PropTypes.object,
10265
- dropdownProps: PropTypes.object
10539
+ dropdownProps: PropTypes.object,
10540
+ onChange: PropTypes.func.isRequired,
10541
+ onFocus: PropTypes.func,
10542
+ onBlur: PropTypes.func,
10543
+ /**
10544
+ * To have full control of your search value and response use `onSearchChange` function combined with `searchValue` and custom filtering on the options array.
10545
+ * DO NOT USE TOGETHER WITH `search` PROPERTY
10546
+ */
10547
+ onSearchChange: PropTypes.func
10266
10548
  };
10267
10549
  Select.defaultProps = {
10268
10550
  id: undefined,
@@ -11858,7 +12140,8 @@ class Typeahead extends Component {
11858
12140
  };
11859
12141
  render() {
11860
12142
  const {
11861
- id,
12143
+ inputAttributes,
12144
+ id: idProp,
11862
12145
  placeholder,
11863
12146
  multiple,
11864
12147
  size,
@@ -11876,6 +12159,7 @@ class Typeahead extends Component {
11876
12159
  alert,
11877
12160
  inputAutoComplete
11878
12161
  } = this.props;
12162
+ const id = idProp ?? inputAttributes?.id;
11879
12163
  const {
11880
12164
  errorState,
11881
12165
  query,
@@ -11901,6 +12185,8 @@ class Typeahead extends Component {
11901
12185
  const hasWarning = displayAlert && alertType === Sentiment.WARNING;
11902
12186
  const hasInfo = displayAlert && alertType === Sentiment.NEUTRAL;
11903
12187
  return /*#__PURE__*/jsx("div", {
12188
+ role: "group",
12189
+ ...inputAttributes,
11904
12190
  id: id,
11905
12191
  className: classNames('typeahead', `typeahead-${size}`, {
11906
12192
  'typeahead--has-value': selected.length > 0,
@@ -11956,6 +12242,9 @@ class Typeahead extends Component {
11956
12242
  });
11957
12243
  }
11958
12244
  }
12245
+ var Typeahead$1 = withInputAttributes(Typeahead, {
12246
+ nonLabelable: true
12247
+ });
11959
12248
 
11960
12249
  // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
11961
12250
  var UploadStep;
@@ -14484,5 +14773,5 @@ const translations = {
14484
14773
  'zh-HK': zhHK
14485
14774
  };
14486
14775
 
14487
- export { Accordion, ActionButton, ActionOption, Alert, AlertArrowPosition, Avatar, AvatarType, AvatarWrapper, Badge, Card as BaseCard, Body, BottomSheet$1 as BottomSheet, Breakpoint, Button, Card$2 as Card, Checkbox, CheckboxButton$1 as CheckboxButton, CheckboxOption, Chevron, Chip, Chips, CircularButton, ControlType, CriticalCommsBanner, DEFAULT_LANG, DEFAULT_LOCALE, DateInput, DateLookup$1 as DateLookup, DateMode, Decision, DecisionPresentation, DecisionType, DefinitionList$1 as DefinitionList, Dimmer$1 as Dimmer, Direction, DirectionProvider, Display, Drawer$1 as Drawer, DropFade, Emphasis, Field, FileType, FlowNavigation, Header, Image, Info, InfoPresentation, InlineAlert, Input, InputGroup, InputWithDisplayFormat, InstructionsList, Label, LanguageProvider, Layout, Link, ListItem$1 as ListItem, Loader, Logo$1 as Logo, LogoType, Markdown, MarkdownNodeType, Modal, Money, MoneyInput$1 as MoneyInput, MonthFormat, NavigationOption, NavigationOptionList as NavigationOptionsList, Nudge, Option$2 as Option, OverlayHeader$1 as OverlayHeader, PhoneNumberInput, Popover$1 as Popover, Position, Priority, ProcessIndicator$1 as ProcessIndicator, ProfileType, Progress, ProgressBar, PromoCard$1 as PromoCard, PromoCardGroup$1 as PromoCardGroup, Provider, RTL_LANGUAGES, Radio, RadioGroup, RadioOption, SUPPORTED_LANGUAGES, Scroll, SearchInput, Section, SegmentedControl, Select, SelectInput, SelectInputOptionContent, SelectInputTriggerButton, Sentiment, Size, SlidingPanel, SnackbarConsumer, SnackbarContext, SnackbarPortal, SnackbarProvider, Status, StatusIcon, Stepper, Sticky, Summary, Switch, SwitchOption, Tabs$1 as Tabs, TextArea, TextareaWithDisplayFormat, Theme, Title, Tooltip, Type, Typeahead, Typography, Upload$1 as Upload, UploadInput, UploadStep, Variant, Width, adjustLocale, getCountryFromLocale, getDirectionFromLocale, getLangFromLocale, isBrowser, isServerSide, translations, useDirection, useLayout, useScreenSize, useSnackbar };
14776
+ export { Accordion, ActionButton, ActionOption, Alert, AlertArrowPosition, Avatar, AvatarType, AvatarWrapper, Badge, Card$2 as BaseCard, Body, BottomSheet$1 as BottomSheet, Breakpoint, Button, Card$1 as Card, Carousel, Checkbox, CheckboxButton$1 as CheckboxButton, CheckboxOption, Chevron, Chip, Chips, CircularButton, ControlType, CriticalCommsBanner, DEFAULT_LANG, DEFAULT_LOCALE, DateInput, DateLookup$1 as DateLookup, DateMode, Decision, DecisionPresentation, DecisionType, DefinitionList$1 as DefinitionList, Dimmer$1 as Dimmer, Direction, DirectionProvider, Display, Drawer$1 as Drawer, DropFade, Emphasis, Field, FileType, FlowNavigation, Header, Image, Info, InfoPresentation, InlineAlert, Input, InputGroup, InputWithDisplayFormat, InstructionsList, Label, LanguageProvider, Layout, Link, ListItem$1 as ListItem, Loader, Logo$1 as Logo, LogoType, Markdown, MarkdownNodeType, Modal, Money, MoneyInput$1 as MoneyInput, MonthFormat, NavigationOption, NavigationOptionList as NavigationOptionsList, Nudge, Option$2 as Option, OverlayHeader$1 as OverlayHeader, PhoneNumberInput, Popover$1 as Popover, Position, Priority, ProcessIndicator$1 as ProcessIndicator, ProfileType, Progress, ProgressBar, PromoCard$1 as PromoCard, PromoCardGroup$1 as PromoCardGroup, Provider, RTL_LANGUAGES, Radio, RadioGroup, RadioOption, SUPPORTED_LANGUAGES, Scroll, SearchInput, Section, SegmentedControl, Select, SelectInput, SelectInputOptionContent, SelectInputTriggerButton, Sentiment, Size, SlidingPanel, SnackbarConsumer, SnackbarContext, SnackbarPortal, SnackbarProvider, Status, StatusIcon, Stepper, Sticky, Summary, Switch, SwitchOption, Tabs$1 as Tabs, TextArea, TextareaWithDisplayFormat, Theme, Title, Tooltip, Type, Typeahead$1 as Typeahead, Typography, Upload$1 as Upload, UploadInput, UploadStep, Variant, Width, adjustLocale, getCountryFromLocale, getDirectionFromLocale, getLangFromLocale, isBrowser, isServerSide, translations, useDirection, useLayout, useScreenSize, useSnackbar };
14488
14777
  //# sourceMappingURL=index.mjs.map