@transferwise/components 0.0.0-experimental-693e956 → 0.0.0-experimental-d729abf

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 (46) hide show
  1. package/build/i18n/en.json +1 -0
  2. package/build/index.js +2320 -2234
  3. package/build/index.js.map +1 -1
  4. package/build/index.mjs +2322 -2237
  5. package/build/index.mjs.map +1 -1
  6. package/build/main.css +31 -10
  7. package/build/styles/main.css +31 -10
  8. package/build/styles/selectOption/SelectOption.css +31 -0
  9. package/build/styles/uploadInput/UploadInput.css +0 -10
  10. package/build/types/index.d.ts +2 -0
  11. package/build/types/index.d.ts.map +1 -1
  12. package/build/types/selectOption/SelectOption.d.ts +20 -0
  13. package/build/types/selectOption/SelectOption.d.ts.map +1 -0
  14. package/build/types/selectOption/SelectOption.messages.d.ts +8 -0
  15. package/build/types/selectOption/SelectOption.messages.d.ts.map +1 -0
  16. package/build/types/selectOption/index.d.ts +3 -0
  17. package/build/types/selectOption/index.d.ts.map +1 -0
  18. package/build/types/slidingPanel/SlidingPanel.d.ts +1 -0
  19. package/build/types/slidingPanel/SlidingPanel.d.ts.map +1 -1
  20. package/build/types/sticky/Sticky.d.ts +31 -3
  21. package/build/types/sticky/Sticky.d.ts.map +1 -1
  22. package/build/types/uploadInput/types.d.ts +1 -9
  23. package/build/types/uploadInput/types.d.ts.map +1 -1
  24. package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
  25. package/package.json +2 -2
  26. package/src/i18n/en.json +1 -0
  27. package/src/index.ts +2 -0
  28. package/src/main.css +31 -10
  29. package/src/main.less +1 -0
  30. package/src/selectOption/SelectOption.css +31 -0
  31. package/src/selectOption/SelectOption.less +27 -0
  32. package/src/selectOption/SelectOption.messages.ts +8 -0
  33. package/src/selectOption/SelectOption.story.tsx +167 -0
  34. package/src/selectOption/SelectOption.tsx +134 -0
  35. package/src/selectOption/index.ts +2 -0
  36. package/src/slidingPanel/SlidingPanel.spec.js +2 -1
  37. package/src/slidingPanel/SlidingPanel.tsx +3 -0
  38. package/src/sticky/Sticky.spec.tsx +71 -0
  39. package/src/sticky/Sticky.story.tsx +46 -13
  40. package/src/sticky/Sticky.tsx +48 -4
  41. package/src/uploadInput/UploadInput.css +0 -10
  42. package/src/uploadInput/UploadInput.less +0 -11
  43. package/src/uploadInput/UploadInput.story.tsx +7 -50
  44. package/src/uploadInput/types.ts +1 -11
  45. package/src/uploadInput/uploadItem/UploadItem.tsx +6 -25
  46. package/src/sticky/Sticky.spec.js +0 -34
package/build/index.js CHANGED
@@ -4,20 +4,20 @@ var React = require('react');
4
4
  var classNames = require('classnames');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var icons = require('@transferwise/icons');
7
- var reactIntl = require('react-intl');
8
- var PropTypes = require('prop-types');
9
- var commonmark = require('commonmark');
7
+ var reactPopper = require('react-popper');
10
8
  var componentsTheming = require('@wise/components-theming');
11
9
  var reactTransitionGroup = require('react-transition-group');
12
10
  var focus = require('@react-aria/focus');
13
11
  var reactDom = require('react-dom');
12
+ var reactIntl = require('react-intl');
14
13
  var neptuneValidation = require('@transferwise/neptune-validation');
14
+ var PropTypes = require('prop-types');
15
+ var commonmark = require('commonmark');
15
16
  var formatting = require('@transferwise/formatting');
16
17
  var react$1 = require('@headlessui/react');
17
18
  var mergeProps = require('merge-props');
18
19
  var react = require('@floating-ui/react');
19
20
  var overlays = require('@react-aria/overlays');
20
- var reactPopper = require('react-popper');
21
21
  var art = require('@wise/art');
22
22
  var clamp$2 = require('lodash.clamp');
23
23
  var debounce = require('lodash.debounce');
@@ -694,585 +694,358 @@ const ActionOption = ({
694
694
  });
695
695
  };
696
696
 
697
- var messages$d = reactIntl.defineMessages({
698
- ariaLabel: {
699
- id: "neptune.CloseButton.ariaLabel"
700
- }
701
- });
702
-
703
- const CloseButton = /*#__PURE__*/React.forwardRef(function CloseButton({
704
- 'aria-label': ariaLabel,
705
- size = exports.Size.MEDIUM,
706
- filled = false,
707
- className,
708
- onClick,
709
- isDisabled,
710
- testId
711
- }, reference) {
712
- const intl = reactIntl.useIntl();
713
- ariaLabel ??= intl.formatMessage(messages$d.ariaLabel);
714
- const Icon = filled ? icons.CrossCircleFill : icons.Cross;
715
- return /*#__PURE__*/jsxRuntime.jsx("button", {
716
- ref: reference,
717
- type: "button",
718
- className: classNames__default.default('np-close-button', 'close btn-link', 'text-no-decoration', {
719
- 'np-close-button--large': size === exports.Size.MEDIUM,
720
- 'np-close-button--x-large': size === exports.Size.LARGE
721
- }, className),
722
- "aria-label": ariaLabel,
723
- "aria-disabled": isDisabled,
724
- disabled: isDisabled,
725
- "data-testid": testId,
726
- onClick: onClick,
727
- children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
728
- size: size === exports.Size.SMALL ? 16 : 24
729
- })
730
- });
731
- });
732
-
733
- const iconTypeMap = {
734
- positive: icons.Check,
735
- neutral: icons.Info,
736
- warning: icons.Alert,
737
- negative: icons.Cross,
738
- pending: icons.ClockBorderless,
739
- info: icons.Info,
740
- error: icons.Cross,
741
- success: icons.Check
742
- };
743
- const StatusIcon = ({
744
- sentiment = 'neutral',
745
- size = 'md'
697
+ const FocusBoundary = ({
698
+ children
746
699
  }) => {
747
- const Icon = iconTypeMap[sentiment];
748
- const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
749
- return /*#__PURE__*/jsxRuntime.jsx("span", {
750
- "data-testid": "status-icon",
751
- className: classNames__default.default('status-circle', 'status-circle-' + size, sentiment),
752
- children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
753
- className: classNames__default.default('status-icon', iconColor)
700
+ const wrapperReference = React.useRef(null);
701
+ React.useEffect(() => {
702
+ wrapperReference.current?.focus({
703
+ preventScroll: true
704
+ });
705
+ }, []);
706
+ return /*#__PURE__*/jsxRuntime.jsx(focus.FocusScope, {
707
+ contain: true,
708
+ restoreFocus: true,
709
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
710
+ ref: wrapperReference,
711
+ tabIndex: -1,
712
+ children: children
754
713
  })
755
714
  });
756
715
  };
757
716
 
758
- const DEFAULT_TYPE = exports.Typography.TITLE_GROUP;
759
- const titleTypeMapping = {
760
- [exports.Typography.TITLE_SCREEN]: 'h1',
761
- [exports.Typography.TITLE_SECTION]: 'h2',
762
- [exports.Typography.TITLE_SUBSECTION]: 'h3',
763
- [exports.Typography.TITLE_BODY]: 'h4',
764
- [exports.Typography.TITLE_GROUP]: 'h5'
765
- };
766
- function Title({
767
- as,
768
- type = DEFAULT_TYPE,
769
- className,
770
- ...props
771
- }) {
772
- const mapping = titleTypeMapping[type];
773
- const isTypeSupported = mapping !== undefined;
774
- if (isTypeSupported) {
775
- const HeaderTag = as ?? mapping;
776
- return /*#__PURE__*/jsxRuntime.jsx(HeaderTag, {
777
- ...props,
778
- className: classNames__default.default(`np-text-${type}`, className)
779
- });
780
- }
781
- const HeaderTag = as ?? titleTypeMapping[DEFAULT_TYPE];
782
- return /*#__PURE__*/jsxRuntime.jsx(HeaderTag, {
783
- ...props,
784
- className: classNames__default.default(`np-text-${DEFAULT_TYPE}`, className)
785
- });
786
- }
787
-
788
- function logActionRequired(message) {
789
- if (typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production') {
790
- // eslint-disable-next-line no-console
791
- console.warn(message);
792
- }
793
- }
794
- function logActionRequiredIf(message, conditional) {
795
- if (conditional) {
796
- logActionRequired(message);
797
- }
717
+ function withNextPortalWrapper(Component) {
718
+ return function (props) {
719
+ const [mounted, setMounted] = React.useState(false);
720
+ React.useEffect(() => {
721
+ setMounted(true);
722
+ }, [setMounted]);
723
+ return mounted ? /*#__PURE__*/reactDom.createPortal( /*#__PURE__*/jsxRuntime.jsx(Component, {
724
+ ...props
725
+ }), document.body) : null;
726
+ };
798
727
  }
799
728
 
800
- const reader = new commonmark__default.default.Parser();
801
- const writer = new commonmark__default.default.HtmlRenderer({
802
- safe: true
803
- });
804
- const NODE_TYPE_LIST = Object.values(exports.MarkdownNodeType);
805
- function Markdown({
806
- as: Element = 'div',
807
- allowList,
808
- blockList,
809
- config,
810
- className,
811
- children
812
- }) {
813
- if (!children) {
814
- return null;
815
- }
816
- const linkTarget = config?.link?.target ?? '_self';
817
- const paragraphClass = config?.paragraph?.className ?? '';
818
- if (allowList != null && blockList != null) {
819
- logActionRequired('Markdown supports only one of `allowList` or `blockList` to be used at a time. `blockList` will be ignored.');
729
+ /**
730
+ * Dimmer state management inspired by Material UI's ModalManager (https://github.com/mui-org/material-ui)
731
+ */
732
+ class DimmerManager {
733
+ /**
734
+ * Dimmer refs
735
+ */
736
+ dimmers;
737
+ constructor() {
738
+ this.dimmers = [];
820
739
  }
821
- const parser = nodes => {
822
- const parsed = reader.parse(nodes);
823
- const toExclude = allowList != null ? NODE_TYPE_LIST.filter(type => !allowList.includes(type)) : blockList;
824
- return toExclude != null ? stripNodes({
825
- parsed,
826
- blockList: toExclude
827
- }) : parsed;
828
- };
829
- const createMarkup = () => {
830
- const parsed = parser(children);
831
- return writer.render(parsed).replace(/<a href="/g, `<a target="${linkTarget}" href="`).replace(/<p>/g, `<p class="${paragraphClass}">`);
832
- };
833
- return /*#__PURE__*/jsxRuntime.jsx(Element, {
834
- className: className,
835
- dangerouslySetInnerHTML: {
836
- __html: createMarkup()
740
+ add(dimmer) {
741
+ let dimmerIndex = this.dimmers.indexOf(dimmer);
742
+ if (dimmerIndex !== -1) {
743
+ return dimmerIndex;
837
744
  }
838
- });
839
- }
840
- function stripNodes({
841
- blockList,
842
- parsed
843
- }) {
844
- if (!parsed) {
845
- return parsed;
745
+ dimmerIndex = this.dimmers.length;
746
+ this.dimmers.push(dimmer);
747
+ return dimmerIndex;
846
748
  }
847
- const walker = parsed.walker();
848
- for (let event = walker.next(); event != null; event = walker.next()) {
849
- const {
850
- node
851
- } = event;
852
- if (blockList.includes(node.type) && !event.entering) {
853
- while (node.firstChild != null) {
854
- node.insertBefore(node.firstChild);
855
- }
856
- node.unlink();
749
+ remove(dimmer) {
750
+ const dimmerIndex = this.dimmers.indexOf(dimmer);
751
+ if (dimmerIndex !== -1) {
752
+ this.dimmers.splice(dimmerIndex, 1);
857
753
  }
754
+ return dimmerIndex;
755
+ }
756
+ isTop(dimmer) {
757
+ return this.dimmers.length > 0 && this.dimmers[this.dimmers.length - 1] === dimmer;
858
758
  }
859
- return parsed;
860
759
  }
861
760
 
862
- const allowList = [exports.MarkdownNodeType.STRONG];
863
- const InlineMarkdown = props => {
864
- return /*#__PURE__*/jsxRuntime.jsx(Markdown, {
865
- ...props,
866
- as: "span",
867
- allowList: allowList,
868
- blockList: undefined
869
- });
870
- };
871
- InlineMarkdown.propTypes = {
872
- children: PropTypes__default.default.string.isRequired,
873
- className: PropTypes__default.default.string
874
- };
875
- InlineMarkdown.defaultProps = {
876
- className: undefined
877
- };
878
-
879
- var messages$c = reactIntl.defineMessages({
880
- opensInNewTab: {
881
- id: "neptune.Link.opensInNewTab"
761
+ const EXIT_ANIMATION$1 = 350;
762
+ const dimmerManager = new DimmerManager();
763
+ const handleTouchMove = event => {
764
+ const isTouchedElementDimmer = event.target.classList.contains('dimmer');
765
+ // disable scroll on iOS devices for Dimmer area
766
+ // this is because of bug in WebKit https://bugs.webkit.org/show_bug.cgi?id=220908
767
+ // note: scrolling still works for children(s) as expected
768
+ if (isIosDevice() && isTouchedElementDimmer) {
769
+ event.stopPropagation();
770
+ event.preventDefault();
882
771
  }
883
- });
884
-
885
- const Link = ({
886
- className,
887
- children,
888
- href,
889
- target,
890
- type,
891
- 'aria-label': ariaLabel,
892
- onClick,
893
- ...props
894
- }) => {
895
- const isBlank = target === '_blank';
896
- const {
897
- formatMessage
898
- } = reactIntl.useIntl();
899
- return /*#__PURE__*/jsxRuntime.jsxs("a", {
900
- href: href,
901
- target: target,
902
- className: classNames__default.default('np-link', type ? `np-text-${type}` : undefined, 'd-inline-flex', className),
903
- "aria-label": ariaLabel,
904
- rel: isBlank ? 'noreferrer' : undefined,
905
- onClick: onClick,
906
- ...props,
907
- children: [children, " ", isBlank && /*#__PURE__*/jsxRuntime.jsx(icons.NavigateAway, {
908
- title: formatMessage(messages$c.opensInNewTab)
909
- })]
910
- });
911
- };
912
-
913
- function Action({
914
- action,
915
- className
916
- }) {
917
- if ('href' in action) {
918
- return /*#__PURE__*/jsxRuntime.jsx(Link, {
919
- href: action.href,
920
- className: className,
921
- "aria-label": action['aria-label'],
922
- target: action.target,
923
- type: exports.Typography.LINK_LARGE,
924
- onClick: action.onClick,
925
- children: action.text
926
- });
927
- }
928
- return /*#__PURE__*/jsxRuntime.jsx("button", {
929
- type: "button",
930
- "aria-label": action['aria-label'],
931
- className: classNames__default.default('btn-unstyled np-text-link-large', className),
932
- onClick: action.onClick,
933
- children: action.text
934
- });
935
- }
936
-
937
- exports.AlertArrowPosition = void 0;
938
- (function (AlertArrowPosition) {
939
- AlertArrowPosition["TOP_LEFT"] = "up-left";
940
- AlertArrowPosition["TOP"] = "up-center";
941
- AlertArrowPosition["TOP_RIGHT"] = "up-right";
942
- AlertArrowPosition["BOTTOM_LEFT"] = "down-left";
943
- AlertArrowPosition["BOTTOM"] = "down-center";
944
- AlertArrowPosition["BOTTOM_RIGHT"] = "down-right";
945
- })(exports.AlertArrowPosition || (exports.AlertArrowPosition = {}));
946
- function resolveType(type) {
947
- switch (type) {
948
- case 'success':
949
- return 'positive';
950
- case 'info':
951
- return 'neutral';
952
- case 'error':
953
- return 'negative';
954
- default:
955
- return type;
956
- }
957
- }
958
- function Alert({
959
- arrow,
960
- action,
772
+ };
773
+ const Dimmer = ({
961
774
  children,
962
775
  className,
963
- dismissible,
964
- icon,
965
- onDismiss,
966
- message,
967
- size,
968
- title,
969
- type = 'neutral',
970
- variant = 'desktop'
971
- }) {
972
- React.useEffect(() => {
973
- if (arrow !== undefined) {
974
- logActionRequired("Alert component doesn't support 'arrow' anymore, use 'InlineAlert' instead.");
776
+ disableClickToClose = false,
777
+ contentPosition,
778
+ fadeContentOnEnter = false,
779
+ fadeContentOnExit = false,
780
+ open = false,
781
+ scrollable = false,
782
+ transparent = false,
783
+ onClose
784
+ }) => {
785
+ const [hasNotExited, setHasNotExited] = React.useState(false);
786
+ const dimmerReference = React.useRef(null);
787
+ const closeOnClick = event => {
788
+ if (event.target === dimmerReference.current) {
789
+ onClose?.(event);
975
790
  }
976
- }, [arrow]);
977
- React.useEffect(() => {
978
- if (children !== undefined) {
979
- logActionRequired("Alert component doesn't support 'children' anymore, use 'message' instead.");
791
+ };
792
+ const handleClick = event => {
793
+ if (disableClickToClose || !onClose) {
794
+ return;
980
795
  }
981
- }, [children]);
982
- React.useEffect(() => {
983
- if (dismissible !== undefined) {
984
- logActionRequired("Alert component doesn't support 'dismissible' anymore, use 'onDismiss' instead.");
796
+ closeOnClick(event);
797
+ };
798
+ const handleKeyDown = React.useCallback(event => {
799
+ if (event.key !== 'Escape') {
800
+ return;
985
801
  }
986
- }, [dismissible]);
987
- React.useEffect(() => {
988
- if (size !== undefined) {
989
- logActionRequired("Alert component doesn't support 'size' anymore, please remove that prop.");
802
+ event.stopPropagation();
803
+ if (onClose && dimmerReference.current && dimmerManager.isTop(dimmerReference.current)) {
804
+ onClose(event);
990
805
  }
991
- }, [size]);
992
- const resolvedType = resolveType(type);
806
+ }, [onClose]);
807
+ const onEnter = () => {
808
+ setHasNotExited(true);
809
+ if (dimmerReference.current) {
810
+ dimmerManager.add(dimmerReference.current);
811
+ }
812
+ };
813
+ const onExited = () => {
814
+ setHasNotExited(false);
815
+ if (dimmerReference.current) {
816
+ dimmerManager.remove(dimmerReference.current);
817
+ }
818
+ };
993
819
  React.useEffect(() => {
994
- if (resolvedType !== type) {
995
- logActionRequired(`Alert component has deprecated '${type}' value for the 'type' prop. Please use '${resolvedType}' instead.`);
820
+ const localReferenceCopy = dimmerReference.current;
821
+ if (open) {
822
+ document.addEventListener('keydown', handleKeyDown);
823
+ localReferenceCopy?.addEventListener('touchmove', handleTouchMove, {
824
+ passive: true
825
+ });
996
826
  }
997
- }, [resolvedType, type]);
998
- const [shouldFire, setShouldFire] = React.useState(false);
999
- const closeButtonReference = React.useRef(null);
1000
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
1001
- className: classNames__default.default('alert d-flex', `alert-${resolvedType}`, arrow != null && alertArrowClassNames(arrow), className),
1002
- "data-testid": "alert",
1003
- onTouchStart: () => setShouldFire(true),
1004
- onTouchEnd: event => {
1005
- if (shouldFire && action?.href &&
1006
- // Check if current event is triggered from closeButton
1007
- event.target instanceof Node && closeButtonReference.current && !closeButtonReference.current.contains(event.target)) {
1008
- if (action.target === '_blank') {
1009
- window.top?.open(action.href);
1010
- } else {
1011
- window.top?.location.assign(action.href);
1012
- }
1013
- }
1014
- setShouldFire(false);
1015
- },
1016
- onTouchMove: () => setShouldFire(false),
1017
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1018
- className: classNames__default.default('alert__content', 'd-flex', 'flex-grow-1', variant),
1019
- "data-testid": variant,
1020
- children: [icon ? /*#__PURE__*/jsxRuntime.jsx("div", {
1021
- className: "alert__icon",
1022
- children: icon
1023
- }) : /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
1024
- size: exports.Size.LARGE,
1025
- sentiment: resolvedType
1026
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1027
- className: "alert__message",
1028
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1029
- role: exports.Sentiment.NEGATIVE === resolvedType ? 'alert' : 'status',
1030
- children: [title && /*#__PURE__*/jsxRuntime.jsx(Title, {
1031
- className: "m-b-1",
1032
- type: exports.Typography.TITLE_BODY,
1033
- children: title
1034
- }), /*#__PURE__*/jsxRuntime.jsx(Body, {
1035
- as: "span",
1036
- className: "d-block",
1037
- type: exports.Typography.BODY_LARGE,
1038
- children: children || /*#__PURE__*/jsxRuntime.jsx(InlineMarkdown, {
1039
- children: message
827
+ return () => {
828
+ document.removeEventListener('keydown', handleKeyDown);
829
+ localReferenceCopy?.removeEventListener('touchmove', handleTouchMove);
830
+ };
831
+ }, [handleKeyDown, open]);
832
+ return /*#__PURE__*/jsxRuntime.jsx(DimmerWrapper, {
833
+ open: open,
834
+ hasNotExited: hasNotExited,
835
+ children: /*#__PURE__*/jsxRuntime.jsx(reactTransitionGroup.CSSTransition, {
836
+ nodeRef: dimmerReference,
837
+ in: open,
838
+ appear: true
839
+ // Wait for animation to finish before unmount.
840
+ ,
841
+ timeout: {
842
+ enter: 0,
843
+ exit: EXIT_ANIMATION$1
844
+ },
845
+ classNames: {
846
+ enter: classNames__default.default({
847
+ 'dimmer--enter-fade': fadeContentOnEnter
848
+ }),
849
+ enterDone: classNames__default.default('dimmer--enter-done', {
850
+ 'dimmer--enter-fade': fadeContentOnEnter
851
+ }),
852
+ exit: classNames__default.default('dimmer--exit', {
853
+ 'dimmer--exit-fade': fadeContentOnExit
854
+ })
855
+ },
856
+ unmountOnExit: true,
857
+ onEnter: onEnter,
858
+ onExited: onExited,
859
+ children: /*#__PURE__*/jsxRuntime.jsx(DimmerContentWrapper, {
860
+ scrollBody: !transparent,
861
+ children: /*#__PURE__*/jsxRuntime.jsx(FocusBoundary, {
862
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
863
+ ref: dimmerReference,
864
+ className: classNames__default.default('dimmer', {
865
+ 'dimmer--scrollable': scrollable,
866
+ 'dimmer--transparent': transparent
867
+ }, className),
868
+ role: "presentation",
869
+ onClick: handleClick,
870
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
871
+ className: classNames__default.default('dimmer-content-positioner', contentPosition != null && ['d-flex justify-content-center', {
872
+ 'align-items-start': contentPosition === 'top',
873
+ 'align-items-center': contentPosition === 'center',
874
+ 'align-items-end': contentPosition === 'bottom'
875
+ }]),
876
+ children: children
1040
877
  })
1041
- })]
1042
- }), action && /*#__PURE__*/jsxRuntime.jsx(Action, {
1043
- action: action,
1044
- className: "m-t-1"
1045
- })]
1046
- })]
1047
- }), onDismiss && /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1048
- ref: closeButtonReference,
1049
- className: "m-l-2",
1050
- onClick: onDismiss
1051
- })]
878
+ })
879
+ })
880
+ })
881
+ })
1052
882
  });
1053
- }
1054
- function alertArrowClassNames(arrow) {
1055
- switch (arrow) {
1056
- case 'down-center':
1057
- return 'arrow arrow-bottom arrow-center';
1058
- case 'down-left':
1059
- return 'arrow arrow-bottom arrow-left';
1060
- case 'down-right':
1061
- return 'arrow arrow-bottom arrow-right';
1062
- case 'up-center':
1063
- return 'arrow arrow-center';
1064
- case 'up-right':
1065
- return 'arrow arrow-right';
1066
- case 'up-left':
1067
- default:
1068
- return 'arrow';
1069
- }
1070
- }
1071
-
1072
- // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
1073
- exports.AvatarType = void 0;
1074
- (function (AvatarType) {
1075
- AvatarType["THUMBNAIL"] = "thumbnail";
1076
- AvatarType["ICON"] = "icon";
1077
- AvatarType["EMOJI"] = "emoji";
1078
- AvatarType["INITIALS"] = "initials";
1079
- })(exports.AvatarType || (exports.AvatarType = {}));
1080
-
1081
- /*
1082
- * The colors we support generating an Avatar background color from a "seed" for.
1083
- * Changing this array will change the assignment between seeds.
1084
- * Do not change this array.
1085
- */
1086
- const avatarColors = ['--color-bright-blue', '--color-bright-yellow', '--color-bright-pink', '--color-bright-orange'];
1087
- /*
1088
- * Takes in a "seed" string and spits out an index for the color we should use.
1089
- * This implementation has been synced across all three clients so that we consistently
1090
- * generate branded avatar colors when rendering a list of Avatars.
1091
- * Do not change this implementation.
1092
- */
1093
- const hashSeed = seed => {
1094
- const base = 31;
1095
- const modulo = avatarColors.length;
1096
- let hashValue = 0;
1097
- let basePow = 1;
1098
- for (let i = 0; i < seed.length; i += 1) {
1099
- hashValue = (hashValue + seed.charCodeAt(i) * basePow) % modulo;
1100
- basePow = basePow * base % modulo;
1101
- }
1102
- return hashValue;
1103
- };
1104
- const getAvatarColorFromSeed = seed => {
1105
- return avatarColors[hashSeed(seed)];
1106
- };
1107
-
1108
- const backwardsCompatibleSize = size => {
1109
- switch (size) {
1110
- case 'sm':
1111
- return 24;
1112
- case 'md':
1113
- return 48;
1114
- case 'lg':
1115
- return 72;
1116
- default:
1117
- return size;
1118
- }
1119
883
  };
1120
- const Avatar = ({
1121
- backgroundColor = null,
1122
- backgroundColorSeed = null,
1123
- children = null,
1124
- className,
1125
- outlined = false,
1126
- size: sizeFromProps = 48,
1127
- theme = exports.Theme.LIGHT,
1128
- type = 'thumbnail'
884
+ const DimmerWrapper = ({
885
+ open,
886
+ hasNotExited,
887
+ children
1129
888
  }) => {
1130
- const backgroundColorFromSeed = React.useMemo(() => !backgroundColor && backgroundColorSeed ? `var(${getAvatarColorFromSeed(backgroundColorSeed)})` : undefined, [backgroundColor, backgroundColorSeed]);
1131
- const size = backwardsCompatibleSize(sizeFromProps);
1132
- return /*#__PURE__*/jsxRuntime.jsx("div", {
1133
- className: classNames__default.default('tw-avatar', className, `tw-avatar--${size}`, `tw-avatar--${type}`, {
1134
- 'tw-avatar--outlined': outlined,
1135
- 'tw-avatar--branded': Boolean(backgroundColorFromSeed),
1136
- 'np-text-title-body': type === 'initials'
1137
- }),
1138
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
1139
- className: "tw-avatar__content",
1140
- style: {
1141
- backgroundColor: backgroundColor || backgroundColorFromSeed
1142
- },
1143
- children: children
1144
- })
889
+ const {
890
+ screenMode,
891
+ theme
892
+ } = componentsTheming.useTheme();
893
+ return open || hasNotExited ? /*#__PURE__*/jsxRuntime.jsx(componentsTheming.ThemeProvider, {
894
+ theme: "personal",
895
+ screenMode: theme === 'personal' ? screenMode : 'light',
896
+ isNotRootProvider: true,
897
+ children: children
898
+ }) : /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
899
+ children: children
1145
900
  });
1146
901
  };
1147
-
1148
- const Badge = ({
1149
- badge,
1150
- className = undefined,
1151
- size = exports.Size.SMALL,
1152
- border = exports.Theme.LIGHT,
1153
- children
902
+ const DimmerContentWrapper = ({
903
+ children,
904
+ scrollBody
1154
905
  }) => {
1155
- const classes = classNames__default.default('tw-badge', {
1156
- [`tw-badge-border-${border}`]: border,
1157
- [`tw-badge-${size}`]: size
1158
- }, className);
1159
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
1160
- className: classes,
1161
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1162
- className: "tw-badge__children",
1163
- children: children
1164
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
1165
- className: "tw-badge__content",
1166
- children: badge
1167
- })]
1168
- });
906
+ React.useEffect(() => {
907
+ if (scrollBody) {
908
+ addNoScrollClass();
909
+ }
910
+ return () => {
911
+ if (scrollBody) {
912
+ removeNoScrollClass();
913
+ }
914
+ };
915
+ }, [scrollBody]);
916
+ return children;
1169
917
  };
918
+ var Dimmer$1 = withNextPortalWrapper(Dimmer);
1170
919
 
1171
- const OptionalBadge = ({
1172
- url,
1173
- altText,
1174
- statusIcon,
920
+ const POPOVER_OFFSET = [0, 16];
921
+ // By default the flip positioning explores only the opposite alternative. So if left is passed and there's no enough space
922
+ // the right one gets chosen. If there's no space on both sides popover goes back to the initially chosen one left.
923
+ // This mapping forces popover to try the four available positions before going back to the initial chosen one.
924
+ const fallbackPlacements = {
925
+ [exports.Position.TOP]: [exports.Position.BOTTOM, exports.Position.RIGHT, exports.Position.LEFT],
926
+ [exports.Position.BOTTOM]: [exports.Position.TOP, exports.Position.RIGHT, exports.Position.LEFT],
927
+ [exports.Position.LEFT]: [exports.Position.RIGHT, exports.Position.TOP, exports.Position.BOTTOM],
928
+ [exports.Position.RIGHT]: [exports.Position.LEFT, exports.Position.TOP, exports.Position.BOTTOM]
929
+ };
930
+ const Panel = /*#__PURE__*/React.forwardRef(function Panel({
931
+ arrow = false,
932
+ flip = true,
933
+ altAxis = false,
1175
934
  children,
935
+ open = false,
936
+ onClose,
937
+ position = exports.Position.BOTTOM,
938
+ anchorRef,
939
+ anchorWidth = false,
1176
940
  ...rest
1177
- }) => {
1178
- if (url) {
1179
- return /*#__PURE__*/jsxRuntime.jsx(Badge, {
1180
- badge: /*#__PURE__*/jsxRuntime.jsx("img", {
1181
- src: url,
1182
- alt: altText
1183
- }),
1184
- ...rest,
1185
- children: children
941
+ }, reference) {
942
+ const [arrowElement, setArrowElement] = React.useState(null);
943
+ const [popperElement, setPopperElement] = React.useState(null);
944
+ const modifiers = [];
945
+ if (altAxis) {
946
+ modifiers.push({
947
+ // https://popper.js.org/docs/v2/modifiers/prevent-overflow
948
+ name: 'preventOverflow',
949
+ options: {
950
+ altAxis: true,
951
+ tether: false
952
+ }
1186
953
  });
1187
954
  }
1188
- if (statusIcon) {
1189
- return /*#__PURE__*/jsxRuntime.jsx(Badge, {
1190
- badge: /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
1191
- sentiment: statusIcon,
1192
- size: exports.Size.SMALL
1193
- }),
1194
- ...rest,
1195
- children: children
955
+ if (arrow) {
956
+ modifiers.push({
957
+ name: 'arrow',
958
+ options: {
959
+ element: arrowElement,
960
+ options: {
961
+ padding: 8 // 8px from the edges of the popper
962
+ }
963
+ }
964
+ });
965
+ // This lets you displace a popper element from its reference element.
966
+ modifiers.push({
967
+ name: 'offset',
968
+ options: {
969
+ offset: POPOVER_OFFSET
970
+ }
1196
971
  });
1197
972
  }
1198
- return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
1199
- children: children
973
+ if (flip && fallbackPlacements[position]) {
974
+ modifiers.push({
975
+ name: 'flip',
976
+ options: {
977
+ fallbackPlacements: fallbackPlacements[position]
978
+ }
979
+ });
980
+ }
981
+ const {
982
+ styles,
983
+ attributes,
984
+ forceUpdate
985
+ } = reactPopper.usePopper(anchorRef.current, popperElement, {
986
+ placement: position,
987
+ modifiers
1200
988
  });
1201
- };
1202
- const AvatarWrapper = ({
1203
- url,
1204
- profileType,
1205
- profileId,
1206
- badgeUrl,
1207
- badgeAltText,
1208
- badgeStatusIcon,
1209
- name,
1210
- avatarProps,
1211
- badgeProps
1212
- }) => {
1213
- const [hasImageLoadError, setImageLoadError] = React.useState(false);
1214
- const isBusinessProfile = profileType === exports.ProfileType.BUSINESS;
1215
- // Reset the errored state when url changes
1216
- React.useEffect(() => setImageLoadError(false), [url]);
1217
- const getAvatarProps = () => {
1218
- if (url && !hasImageLoadError) {
1219
- return {
1220
- type: exports.AvatarType.THUMBNAIL,
1221
- children: /*#__PURE__*/jsxRuntime.jsx("img", {
1222
- src: url,
1223
- alt: "",
1224
- onError: () => setImageLoadError(true)
1225
- }),
1226
- ...avatarProps
1227
- };
1228
- }
1229
- if (profileType) {
1230
- return {
1231
- type: exports.AvatarType.ICON,
1232
- children: isBusinessProfile ? /*#__PURE__*/jsxRuntime.jsx(icons.Briefcase, {
1233
- size: "24"
1234
- }) : /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
1235
- size: "24"
1236
- }),
1237
- ...avatarProps
1238
- };
989
+ // If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),
990
+ // it is most simple just to always position before opening
991
+ React.useEffect(() => {
992
+ if (open && forceUpdate) {
993
+ forceUpdate();
1239
994
  }
1240
- if (name) {
1241
- return {
1242
- type: exports.AvatarType.INITIALS,
1243
- children: /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
1244
- children: getInitials(name)
1245
- }),
1246
- backgroundColorSeed: profileId?.toString(),
1247
- ...avatarProps
1248
- };
1249
- }
1250
- return {
1251
- type: exports.AvatarType.ICON,
1252
- children: /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
1253
- size: "24"
1254
- }),
1255
- ...avatarProps
1256
- };
995
+ }, [open]);
996
+ const contentStyle = {
997
+ ...(anchorWidth ? {
998
+ width: anchorRef.current?.clientWidth
999
+ } : undefined)
1257
1000
  };
1258
- return /*#__PURE__*/jsxRuntime.jsx(OptionalBadge, {
1259
- url: badgeUrl,
1260
- altText: badgeAltText,
1261
- statusIcon: badgeStatusIcon,
1262
- ...badgeProps,
1263
- children: /*#__PURE__*/jsxRuntime.jsx(Avatar, {
1264
- size: exports.Size.MEDIUM,
1265
- ...getAvatarProps()
1001
+ return /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
1002
+ open: open,
1003
+ transparent: true,
1004
+ fadeContentOnEnter: true,
1005
+ fadeContentOnExit: true,
1006
+ onClose: onClose,
1007
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
1008
+ ...rest,
1009
+ ref: setPopperElement,
1010
+ role: "dialog"
1011
+ // eslint-disable-next-line react/forbid-dom-props
1012
+ ,
1013
+ style: {
1014
+ ...styles.popper
1015
+ },
1016
+ ...attributes.popper,
1017
+ className: classNames__default.default('np-panel', {
1018
+ 'np-panel--open': open
1019
+ }, rest.className),
1020
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
1021
+ ref: reference
1022
+ /* eslint-disable-next-line react/forbid-dom-props */,
1023
+ style: contentStyle,
1024
+ className: classNames__default.default('np-panel__content'),
1025
+ children: [children, arrow && /*#__PURE__*/jsxRuntime.jsx("div", {
1026
+ ref: setArrowElement,
1027
+ className: classNames__default.default('np-panel__arrow')
1028
+ // eslint-disable-next-line react/forbid-dom-props
1029
+ ,
1030
+ style: styles.arrow
1031
+ })]
1032
+ })
1266
1033
  })
1267
1034
  });
1035
+ });
1036
+
1037
+ const Section = ({
1038
+ children,
1039
+ className,
1040
+ withHorizontalPadding = false
1041
+ }) => {
1042
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
1043
+ className: classNames__default.default('np-section', className, {
1044
+ 'np-section--with-horizontal-padding': withHorizontalPadding
1045
+ }),
1046
+ children: children
1047
+ });
1268
1048
  };
1269
- function getInitials(name) {
1270
- const allInitials = name.split(' ').map(part => part[0]).join('').toUpperCase();
1271
- if (allInitials.length === 1) {
1272
- return allInitials[0];
1273
- }
1274
- return allInitials[0] + allInitials.slice(-1);
1275
- }
1276
1049
 
1277
1050
  const radius = {
1278
1051
  xxs: 6,
@@ -1381,7 +1154,7 @@ class ProcessIndicator extends React.Component {
1381
1154
  }
1382
1155
  }
1383
1156
 
1384
- var messages$b = reactIntl.defineMessages({
1157
+ var messages$e = reactIntl.defineMessages({
1385
1158
  loadingAriaLabel: {
1386
1159
  id: "neptune.Button.loadingAriaLabel"
1387
1160
  }
@@ -1398,6 +1171,18 @@ const priorityClassMap = {
1398
1171
  [exports.Priority.TERTIARY]: 'btn-priority-3'
1399
1172
  };
1400
1173
 
1174
+ function logActionRequired(message) {
1175
+ if (typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production') {
1176
+ // eslint-disable-next-line no-console
1177
+ console.warn(message);
1178
+ }
1179
+ }
1180
+ function logActionRequiredIf(message, conditional) {
1181
+ if (conditional) {
1182
+ logActionRequired(message);
1183
+ }
1184
+ }
1185
+
1401
1186
  const deprecatedTypeMap = {
1402
1187
  [exports.Type.PRIMARY]: exports.ControlType.ACCENT,
1403
1188
  [exports.Type.SECONDARY]: exports.ControlType.ACCENT,
@@ -1500,7 +1285,7 @@ const Button = /*#__PURE__*/React.forwardRef(({
1500
1285
  className: classes,
1501
1286
  ...props,
1502
1287
  "aria-live": loading ? 'polite' : 'off',
1503
- "aria-label": loading ? intl.formatMessage(messages$b.loadingAriaLabel) : rest['aria-label'],
1288
+ "aria-label": loading ? intl.formatMessage(messages$e.loadingAriaLabel) : rest['aria-label'],
1504
1289
  children: [children, loading && /*#__PURE__*/jsxRuntime.jsx(ProcessIndicator, {
1505
1290
  size: processIndicatorSize(),
1506
1291
  className: "btn-loader"
@@ -1508,55 +1293,137 @@ const Button = /*#__PURE__*/React.forwardRef(({
1508
1293
  });
1509
1294
  });
1510
1295
 
1511
- const Card$2 = /*#__PURE__*/React.forwardRef(({
1296
+ var messages$d = reactIntl.defineMessages({
1297
+ opensInNewTab: {
1298
+ id: "neptune.Link.opensInNewTab"
1299
+ }
1300
+ });
1301
+
1302
+ const Link = ({
1512
1303
  className,
1513
- children = null,
1514
- id,
1515
- isDisabled = false,
1516
- isSmall = false,
1517
- onDismiss,
1518
- testId,
1304
+ children,
1305
+ href,
1306
+ target,
1307
+ type,
1308
+ 'aria-label': ariaLabel,
1309
+ onClick,
1519
1310
  ...props
1520
- }, ref) => {
1521
- const closeButtonReference = React.useRef(null);
1522
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
1523
- ref: ref,
1524
- className: classNames__default.default('np-Card', {
1525
- 'np-Card--small': !!isSmall,
1526
- 'is-disabled': !!isDisabled
1527
- }, className),
1528
- id: id,
1529
- "data-testid": testId,
1311
+ }) => {
1312
+ const isBlank = target === '_blank';
1313
+ const {
1314
+ formatMessage
1315
+ } = reactIntl.useIntl();
1316
+ return /*#__PURE__*/jsxRuntime.jsxs("a", {
1317
+ href: href,
1318
+ target: target,
1319
+ className: classNames__default.default('np-link', type ? `np-text-${type}` : undefined, 'd-inline-flex', className),
1320
+ "aria-label": ariaLabel,
1321
+ rel: isBlank ? 'noreferrer' : undefined,
1322
+ onClick: onClick,
1530
1323
  ...props,
1531
- children: [onDismiss && /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1532
- ref: closeButtonReference,
1533
- className: "np-Card-closeButton",
1534
- size: isSmall ? 'sm' : 'md',
1535
- isDisabled: isDisabled,
1536
- testId: "close-button",
1537
- onClick: e => {
1538
- stopPropagation$1(e);
1539
- onDismiss();
1540
- }
1541
- }), children]
1324
+ children: [children, " ", isBlank && /*#__PURE__*/jsxRuntime.jsx(icons.NavigateAway, {
1325
+ title: formatMessage(messages$d.opensInNewTab)
1326
+ })]
1542
1327
  });
1543
- });
1544
- Card$2.displayName = 'Card';
1328
+ };
1545
1329
 
1546
- function Display({
1547
- as: Heading = 'h1',
1548
- type = exports.Typography.DISPLAY_LARGE,
1549
- children,
1330
+ const DEFAULT_TYPE = exports.Typography.TITLE_GROUP;
1331
+ const titleTypeMapping = {
1332
+ [exports.Typography.TITLE_SCREEN]: 'h1',
1333
+ [exports.Typography.TITLE_SECTION]: 'h2',
1334
+ [exports.Typography.TITLE_SUBSECTION]: 'h3',
1335
+ [exports.Typography.TITLE_BODY]: 'h4',
1336
+ [exports.Typography.TITLE_GROUP]: 'h5'
1337
+ };
1338
+ function Title({
1339
+ as,
1340
+ type = DEFAULT_TYPE,
1550
1341
  className,
1551
- id
1342
+ ...props
1552
1343
  }) {
1553
- return /*#__PURE__*/jsxRuntime.jsx(Heading, {
1554
- id: id,
1555
- className: classNames__default.default(`np-text-${type}`, 'text-primary', className),
1556
- children: children
1344
+ const mapping = titleTypeMapping[type];
1345
+ const isTypeSupported = mapping !== undefined;
1346
+ if (isTypeSupported) {
1347
+ const HeaderTag = as ?? mapping;
1348
+ return /*#__PURE__*/jsxRuntime.jsx(HeaderTag, {
1349
+ ...props,
1350
+ className: classNames__default.default(`np-text-${type}`, className)
1351
+ });
1352
+ }
1353
+ const HeaderTag = as ?? titleTypeMapping[DEFAULT_TYPE];
1354
+ return /*#__PURE__*/jsxRuntime.jsx(HeaderTag, {
1355
+ ...props,
1356
+ className: classNames__default.default(`np-text-${DEFAULT_TYPE}`, className)
1557
1357
  });
1558
1358
  }
1559
1359
 
1360
+ const HeaderAction = ({
1361
+ action
1362
+ }) => {
1363
+ const {
1364
+ isModern
1365
+ } = componentsTheming.useTheme();
1366
+ const props = {
1367
+ 'aria-label': action['aria-label']
1368
+ };
1369
+ if ('href' in action) {
1370
+ return /*#__PURE__*/jsxRuntime.jsx(Link, {
1371
+ href: action.href,
1372
+ target: action.target,
1373
+ onClick: action.onClick,
1374
+ ...props,
1375
+ children: action.text
1376
+ });
1377
+ }
1378
+ return isModern ? /*#__PURE__*/jsxRuntime.jsx(Button, {
1379
+ className: "np-header__button",
1380
+ priority: "tertiary",
1381
+ size: "sm",
1382
+ onClick: action.onClick,
1383
+ ...props,
1384
+ children: action.text
1385
+ }) : /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
1386
+ onClick: action.onClick,
1387
+ ...props,
1388
+ children: action.text
1389
+ });
1390
+ };
1391
+ /**
1392
+ *
1393
+ * Neptune Web: https://transferwise.github.io/neptune-web/components/content/Header
1394
+ *
1395
+ */
1396
+ const Header = ({
1397
+ action,
1398
+ as = 'h5',
1399
+ title,
1400
+ className
1401
+ }) => {
1402
+ if (!action) {
1403
+ return /*#__PURE__*/jsxRuntime.jsx(Title, {
1404
+ as: as,
1405
+ type: exports.Typography.TITLE_GROUP,
1406
+ className: classNames__default.default('np-header', 'np-header__title', className),
1407
+ children: title
1408
+ });
1409
+ }
1410
+ if (as === 'legend') {
1411
+ // eslint-disable-next-line no-console
1412
+ console.warn('Legends should be the first child in a fieldset, and this is not possible when including an action');
1413
+ }
1414
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1415
+ className: classNames__default.default('np-header', className),
1416
+ children: [/*#__PURE__*/jsxRuntime.jsx(Title, {
1417
+ as: as,
1418
+ type: exports.Typography.TITLE_GROUP,
1419
+ className: "np-header__title",
1420
+ children: title
1421
+ }), /*#__PURE__*/jsxRuntime.jsx(HeaderAction, {
1422
+ action: action
1423
+ })]
1424
+ });
1425
+ };
1426
+
1560
1427
  const useConditionalListener = ({
1561
1428
  attachListener,
1562
1429
  callback,
@@ -1685,1375 +1552,1881 @@ const useLayout = () => {
1685
1552
  };
1686
1553
  };
1687
1554
 
1688
- const EmptyTransparentImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
1689
- const Image = ({
1690
- id,
1691
- src,
1692
- alt,
1693
- onLoad,
1694
- onError,
1695
- className,
1696
- loading,
1697
- stretch = true,
1698
- role,
1699
- shrink = true
1700
- }) => {
1701
- const elementReference = React.useRef(null);
1702
- const [hasIntersected] = useHasIntersected({
1703
- elRef: elementReference,
1704
- loading
1705
- });
1706
- let imageSource = src;
1707
- let imageOnLoad = onLoad;
1708
- if (loading === 'lazy' && !hasIntersected) {
1709
- imageSource = EmptyTransparentImage;
1710
- imageOnLoad = undefined;
1555
+ var messages$c = reactIntl.defineMessages({
1556
+ ariaLabel: {
1557
+ id: "neptune.CloseButton.ariaLabel"
1711
1558
  }
1712
- return /*#__PURE__*/jsxRuntime.jsx("img", {
1713
- ref: elementReference,
1714
- id: id,
1715
- alt: alt,
1716
- src: imageSource,
1717
- className: classNames__default.default(['tw-image', {
1718
- 'tw-image__stretch': stretch,
1719
- 'tw-image__shrink': shrink
1720
- }, className]),
1721
- role: role,
1722
- onLoad: imageOnLoad,
1723
- onError: onError
1724
- });
1725
- };
1559
+ });
1726
1560
 
1727
- const defaultPromoCardContext = {
1728
- state: '',
1729
- isDisabled: false,
1730
- // eslint-disable-next-line @typescript-eslint/no-empty-function
1731
- onChange: () => {}
1732
- };
1733
- /**
1734
- * The PromoCard context object.
1735
- */
1736
- const PromoCardContext = /*#__PURE__*/React.createContext(defaultPromoCardContext);
1737
- /**
1738
- * A custom hook for accessing the PromoCard context object.
1739
- *
1740
- * The `usePromoCardContext` hook is used to access the PromoCard context object
1741
- * from within a child PromoCard component. It throws an error if the context
1742
- * object is not available, which can help with debugging and development.
1743
- *
1744
- * @returns {PromoCardContextType} - The PromoCard context object.
1745
- */
1746
- const usePromoCardContext = () => {
1747
- return React.useContext(PromoCardContext);
1748
- };
1561
+ const CloseButton = /*#__PURE__*/React.forwardRef(function CloseButton({
1562
+ 'aria-label': ariaLabel,
1563
+ size = exports.Size.MEDIUM,
1564
+ filled = false,
1565
+ className,
1566
+ onClick,
1567
+ isDisabled,
1568
+ testId
1569
+ }, reference) {
1570
+ const intl = reactIntl.useIntl();
1571
+ ariaLabel ??= intl.formatMessage(messages$c.ariaLabel);
1572
+ const Icon = filled ? icons.CrossCircleFill : icons.Cross;
1573
+ return /*#__PURE__*/jsxRuntime.jsx("button", {
1574
+ ref: reference,
1575
+ type: "button",
1576
+ className: classNames__default.default('np-close-button', 'close btn-link', 'text-no-decoration', {
1577
+ 'np-close-button--large': size === exports.Size.MEDIUM,
1578
+ 'np-close-button--x-large': size === exports.Size.LARGE
1579
+ }, className),
1580
+ "aria-label": ariaLabel,
1581
+ "aria-disabled": isDisabled,
1582
+ disabled: isDisabled,
1583
+ "data-testid": testId,
1584
+ onClick: onClick,
1585
+ children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
1586
+ size: size === exports.Size.SMALL ? 16 : 24
1587
+ })
1588
+ });
1589
+ });
1749
1590
 
1750
- const PromoCardIndicator = ({
1591
+ const EXIT_ANIMATION = 350;
1592
+ const SlidingPanel = /*#__PURE__*/React.forwardRef(({
1593
+ position = 'left',
1594
+ open,
1595
+ showSlidingPanelBorder,
1596
+ slidingPanelPositionFixed,
1751
1597
  className,
1752
1598
  children,
1753
- label,
1754
- icon,
1755
- isSmall = false,
1756
- testid,
1599
+ testId,
1757
1600
  ...rest
1758
- }) => {
1759
- const isIconString = icon && typeof icon === 'string';
1760
- const IconComponent = isIconString && {
1761
- check: icons.Check,
1762
- arrow: icons.ArrowRight,
1763
- download: icons.Download
1764
- }[icon];
1765
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
1766
- className: classNames__default.default('np-Card-indicator', className),
1767
- "data-testid": testid,
1601
+ }, reference) => {
1602
+ const localReference = React.useRef(null);
1603
+ React.useImperativeHandle(reference, () => localReference.current, []);
1604
+ return /*#__PURE__*/React.createElement(reactTransitionGroup.CSSTransition, {
1768
1605
  ...rest,
1769
- children: [label && /*#__PURE__*/jsxRuntime.jsx(Body, {
1770
- as: "span",
1771
- type: exports.Typography.BODY_LARGE_BOLD,
1772
- className: "np-Card-indicatorText",
1773
- children: label
1774
- }), icon && /*#__PURE__*/jsxRuntime.jsx(Avatar, {
1775
- type: exports.AvatarType.ICON,
1776
- size: isSmall ? 40 : 56,
1777
- backgroundColor: "var(--Card-indicator-icon-background-color)",
1778
- className: "np-Card-indicatorIcon",
1779
- children: IconComponent ? /*#__PURE__*/jsxRuntime.jsx(IconComponent, {
1780
- size: 24,
1781
- "aria-hidden": "true"
1782
- }) : icon
1783
- }), children]
1784
- });
1785
- };
1606
+ key: `sliding-panel--open-${position}`,
1607
+ nodeRef: localReference,
1608
+ in: open
1609
+ // Wait for animation to finish before unmount.
1610
+ ,
1611
+ timeout: {
1612
+ enter: 0,
1613
+ exit: EXIT_ANIMATION
1614
+ },
1615
+ classNames: "sliding-panel",
1616
+ appear: true,
1617
+ unmountOnExit: true
1618
+ }, /*#__PURE__*/jsxRuntime.jsx("div", {
1619
+ ref: localReference,
1620
+ "data-testid": testId,
1621
+ className: classNames__default.default('sliding-panel', `sliding-panel--open-${position}`, showSlidingPanelBorder && `sliding-panel--border-${position}`, slidingPanelPositionFixed && 'sliding-panel--fixed', className),
1622
+ children: children
1623
+ }));
1624
+ });
1786
1625
 
1787
- const PromoCard = /*#__PURE__*/React.forwardRef(({
1626
+ const Drawer = ({
1627
+ children,
1788
1628
  className,
1789
- description,
1790
- defaultChecked,
1791
- download,
1792
- href,
1793
- hrefLang,
1794
- id,
1795
- headingLevel = 'h3',
1796
- imageAlt,
1797
- imageClass,
1798
- imageSource,
1799
- indicatorLabel,
1800
- indicatorIcon,
1801
- isChecked,
1802
- isDisabled,
1803
- onClick,
1804
- onKeyDown,
1805
- rel,
1806
- tabIndex,
1807
- target,
1808
- testId,
1809
- title,
1810
- type,
1811
- value,
1812
- isSmall,
1813
- useDisplayFont = true,
1814
- anchorRef,
1815
- anchorId,
1816
- ...props
1817
- }, ref) => {
1818
- // Set the `checked` state to the value of `defaultChecked` if it is truthy,
1819
- // or the value of `isChecked` if it is truthy, or `false` if neither
1820
- // is truthy.
1629
+ footerContent,
1630
+ headerTitle,
1631
+ onClose,
1632
+ open,
1633
+ position
1634
+ }) => {
1635
+ logActionRequiredIf('Drawer now expects `onClose`, and will soon make this prop required. Please update your usage to provide it.', !onClose);
1821
1636
  const {
1822
- state,
1823
- onChange,
1824
- isDisabled: contextIsDisabled
1825
- } = usePromoCardContext();
1826
- const [checked, setChecked] = React.useState(type === 'checkbox' ? defaultChecked ?? isChecked ?? false : false);
1827
- const handleClick = () => {
1828
- if (type === 'radio') {
1829
- onChange(value || ''); // Update the context state for radio
1830
- } else if (type === 'checkbox') {
1831
- setChecked(!checked); // Update local state for checkbox
1832
- }
1833
- };
1834
- const fallbackId = React.useId();
1835
- const componentId = id || fallbackId;
1836
- // Set the icon to `'arrow'` if `href` is truthy and `type` is falsy, or
1837
- // `'download'` if `download` is truthy. If neither condition is true, set
1838
- // `icon` to `undefined`.
1839
- // Create a function to get icon type
1840
- const getIconType = () => {
1841
- if (indicatorIcon) {
1842
- return indicatorIcon;
1843
- }
1844
- if (download) {
1845
- return 'download';
1846
- }
1847
- if (href && !type) {
1848
- return 'arrow';
1849
- }
1850
- return undefined;
1851
- };
1852
- // Define all class names string based on the values of the `href`, `type`,
1853
- // `checked`, and `className` props.
1854
- const commonClasses = classNames__default.default({
1855
- 'np-Card--promoCard': true,
1856
- 'np-Card--checked': !href && type,
1857
- 'np-Card--link': href && !type,
1858
- 'is-checked': type === 'radio' ? value === state : type === 'checkbox' ? checked : undefined
1859
- }, className);
1860
- // Object with common props that will be passed to the `Card` components
1861
- const commonProps = {
1862
- className: commonClasses,
1863
- id: componentId,
1864
- isDisabled: isDisabled || contextIsDisabled,
1865
- onClick,
1866
- onKeyDown,
1867
- ref,
1868
- 'data-testid': testId,
1869
- isSmall
1870
- };
1871
- // Object with Anchor props that will be passed to the `a` element. These
1872
- // won't be refurned if set to `isDisabled`
1873
- const anchorProps = href && !isDisabled ? {
1874
- download,
1875
- href: href || undefined,
1876
- hrefLang,
1877
- rel,
1878
- target,
1879
- ref: anchorRef,
1880
- id: anchorId
1881
- } : {};
1882
- // Object of all Checked props that will be passed to the root `Card` component
1883
- const checkedProps = (type === 'checkbox' || type === 'radio') && !href ? {
1884
- ...commonProps,
1885
- 'aria-checked': type === 'radio' ? value === state : type === 'checkbox' ? checked : undefined,
1886
- 'aria-describedby': `${componentId}-title`,
1887
- 'aria-disabled': isDisabled,
1888
- 'data-value': value ?? undefined,
1889
- role: type === 'checkbox' || type === 'radio' ? type : undefined,
1890
- onClick: handleClick,
1891
- onKeyDown: event => {
1892
- if (event.key === 'Enter' || event.key === ' ') {
1893
- handleClick();
1894
- }
1895
- },
1896
- ref,
1897
- tabIndex: 0
1898
- } : {};
1899
- const getTitle = () => {
1900
- const titleContent = href && !type ? /*#__PURE__*/jsxRuntime.jsx("a", {
1901
- className: "np-Card-titleLink",
1902
- ...anchorProps,
1903
- children: title
1904
- }) : title;
1905
- const titleProps = {
1906
- id: `${componentId}-title`,
1907
- as: headingLevel,
1908
- className: 'np-Card-title'
1909
- };
1910
- return useDisplayFont ? /*#__PURE__*/jsxRuntime.jsx(Display, {
1911
- type: exports.Typography.DISPLAY_SMALL,
1912
- ...titleProps,
1913
- children: titleContent
1914
- }) : /*#__PURE__*/jsxRuntime.jsx(Title, {
1915
- type: exports.Typography.TITLE_SUBSECTION,
1916
- ...titleProps,
1917
- children: titleContent
1918
- });
1919
- };
1920
- React.useEffect(() => {
1921
- setChecked(defaultChecked ?? isChecked ?? false);
1922
- }, [defaultChecked, isChecked]);
1923
- return /*#__PURE__*/jsxRuntime.jsxs(Card$2, {
1924
- ...commonProps,
1925
- ...checkedProps,
1926
- ...props,
1927
- children: [(value === state || checked) && /*#__PURE__*/jsxRuntime.jsx("span", {
1928
- className: "np-Card-check",
1929
- children: /*#__PURE__*/jsxRuntime.jsx(icons.Check, {
1930
- size: 24,
1931
- "aria-hidden": "true"
1932
- })
1933
- }), getTitle(), /*#__PURE__*/jsxRuntime.jsx(Body, {
1934
- className: "np-Card-description",
1935
- children: description
1936
- }), imageSource && /*#__PURE__*/jsxRuntime.jsx("div", {
1937
- className: classNames__default.default('np-Card-image', {
1938
- imageClass
1939
- }),
1940
- children: /*#__PURE__*/jsxRuntime.jsx(Image, {
1941
- src: imageSource,
1942
- alt: imageAlt || '',
1943
- loading: "lazy"
1637
+ isMobile
1638
+ } = useLayout();
1639
+ const titleId = React.useId();
1640
+ return /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
1641
+ open: open,
1642
+ onClose: onClose,
1643
+ children: /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
1644
+ open: open,
1645
+ position: isMobile ? exports.Position.BOTTOM : position,
1646
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
1647
+ role: "dialog",
1648
+ "aria-modal": true,
1649
+ "aria-labelledby": headerTitle ? titleId : undefined,
1650
+ className: classNames__default.default('np-drawer', className),
1651
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1652
+ className: classNames__default.default('np-drawer-header', {
1653
+ 'np-drawer-header--withborder': headerTitle
1654
+ }),
1655
+ children: [headerTitle && /*#__PURE__*/jsxRuntime.jsx(Title, {
1656
+ id: titleId,
1657
+ type: exports.Typography.TITLE_BODY,
1658
+ children: headerTitle
1659
+ }), /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1660
+ onClick: onClose
1661
+ })]
1662
+ }), children && /*#__PURE__*/jsxRuntime.jsx("div", {
1663
+ className: classNames__default.default('np-drawer-content'),
1664
+ children: children
1665
+ }), footerContent && /*#__PURE__*/jsxRuntime.jsx("div", {
1666
+ className: classNames__default.default('np-drawer-footer'),
1667
+ children: footerContent
1668
+ })]
1944
1669
  })
1945
- }), /*#__PURE__*/jsxRuntime.jsx(PromoCardIndicator, {
1946
- label: indicatorLabel,
1947
- icon: getIconType(),
1948
- isSmall: isSmall
1949
- })]
1670
+ })
1950
1671
  });
1951
- });
1952
- var PromoCard$1 = /*#__PURE__*/React__namespace.default.memo(PromoCard);
1672
+ };
1673
+ Drawer.propTypes = {
1674
+ /** The content to appear in the drawer body. */
1675
+ children: PropTypes__default.default.node,
1676
+ className: PropTypes__default.default.string,
1677
+ /** The content to appear in the drawer footer. */
1678
+ footerContent: PropTypes__default.default.node,
1679
+ /** The content to appear in the drawer header. */
1680
+ headerTitle: PropTypes__default.default.node,
1681
+ /** The status of Drawer either open or not. */
1682
+ open: PropTypes__default.default.bool,
1683
+ /** The placement of Drawer on the screen either left or right. On mobile it will default to bottom. */
1684
+ position: PropTypes__default.default.oneOf(['left', 'right', 'bottom']),
1685
+ /** The action to perform on close click. */
1686
+ onClose: PropTypes__default.default.func
1687
+ };
1688
+ Drawer.defaultProps = {
1689
+ children: null,
1690
+ className: undefined,
1691
+ footerContent: null,
1692
+ headerTitle: null,
1693
+ onClose: null,
1694
+ open: false,
1695
+ position: exports.Position.RIGHT
1696
+ };
1697
+ var Drawer$1 = Drawer;
1953
1698
 
1954
- const LEFT_SCROLL_OFFSET = 8;
1955
- const Carousel = ({
1956
- header,
1957
- className,
1958
- cards,
1959
- onClick
1960
- }) => {
1961
- const [scrollPosition, setScrollPosition] = React.useState(0);
1962
- const [previousScrollPosition, setPreviousScrollPosition] = React.useState(0);
1963
- const [scrollIsAtEnd, setScrollIsAtEnd] = React.useState(false);
1964
- const [visibleCardOnMobileView, setVisibleCardOnMobileView] = React.useState('');
1965
- const carouselElementRef = React.useRef(null);
1966
- const carouselCardsRef = React.useRef([]);
1967
- const isLeftActionButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;
1968
- const areActionButtonsEnabled = isLeftActionButtonEnabled || !scrollIsAtEnd;
1969
- const [focusedCard, setFocusedCard] = React.useState(cards?.[0]?.id);
1970
- const updateScrollButtonsState = () => {
1971
- if (carouselElementRef.current) {
1972
- const {
1973
- scrollWidth,
1974
- offsetWidth
1975
- } = carouselElementRef.current;
1976
- const scrollAtEnd = scrollWidth - offsetWidth <= scrollPosition + LEFT_SCROLL_OFFSET;
1977
- setScrollIsAtEnd(scrollAtEnd);
1978
- }
1979
- const scrollDirecton = scrollPosition > previousScrollPosition ? 'right' : 'left';
1980
- const cardsInFullViewIds = [];
1981
- carouselCardsRef.current.forEach(card => {
1982
- if (isVisible(carouselElementRef.current, card.cardElement)) {
1983
- // eslint-disable-next-line functional/immutable-data
1984
- cardsInFullViewIds.push(card.cardElement.getAttribute('id') ?? '');
1985
- }
1986
- });
1987
- if (cardsInFullViewIds.length >= 1) {
1988
- const visibleCardIndex = scrollDirecton === 'right' ? cardsInFullViewIds.length - 1 : 0;
1989
- const visibleCardId = cardsInFullViewIds[visibleCardIndex];
1990
- setVisibleCardOnMobileView(visibleCardId);
1991
- setFocusedCard(visibleCardId);
1992
- }
1993
- setPreviousScrollPosition(scrollPosition);
1994
- };
1995
- const scrollCarousel = (direction = 'right') => {
1996
- if (carouselElementRef.current) {
1997
- const {
1998
- scrollWidth
1999
- } = carouselElementRef.current;
2000
- const cardWidth = scrollWidth / carouselCardsRef.current.length;
2001
- const res = Math.floor(cardWidth - cardWidth * 0.05);
2002
- carouselElementRef.current.scrollBy({
2003
- left: direction === 'right' ? res : -res,
2004
- behavior: 'smooth'
2005
- });
2006
- }
2007
- };
2008
- const handleOnKeyDown = (event, index) => {
2009
- if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
2010
- const nextIndex = event.key === 'ArrowRight' ? index + 1 : index - 1;
2011
- const nextCard = cards[nextIndex];
2012
- if (nextCard) {
2013
- const ref = carouselCardsRef.current[nextIndex];
2014
- if (ref.type === 'promo') {
2015
- ref.anchorElement?.focus();
1699
+ const INITIAL_Y_POSITION = 0;
1700
+ const CONTENT_SCROLL_THRESHOLD = 1;
1701
+ const MOVE_OFFSET_THRESHOLD = 50;
1702
+ /**
1703
+ * Neptune: https://transferwise.github.io/neptune/components/bottom-sheet/
1704
+ *
1705
+ * Neptune Web: https://transferwise.github.io/neptune-web/components/overlays/BottomSheet
1706
+ *
1707
+ */
1708
+ const BottomSheet$1 = props => {
1709
+ const bottomSheetReference = React.useRef(null);
1710
+ const topBarReference = React.useRef(null);
1711
+ const contentReference = React.useRef(null);
1712
+ const [pressed, setPressed] = React.useState(false);
1713
+ /**
1714
+ * Used to track `requestAnimationFrame` requests
1715
+ *
1716
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame#return_value
1717
+ */
1718
+ const animationId = React.useRef(0);
1719
+ /**
1720
+ * Difference between initial coordinate ({@link initialYCoordinate})
1721
+ * and new position (when user moves component), it's get calculated on `onTouchMove` and `onMouseMove` events
1722
+ *
1723
+ * @see {@link calculateOffsetAfterMove}
1724
+ */
1725
+ const moveOffset = React.useRef(0);
1726
+ const initialYCoordinate = React.useRef(0);
1727
+ // apply shadow to the bottom of top-bar when scroll over content
1728
+ useConditionalListener({
1729
+ attachListener: props.open && !isServerSide(),
1730
+ callback: () => {
1731
+ if (topBarReference.current !== null) {
1732
+ const {
1733
+ classList
1734
+ } = topBarReference.current;
1735
+ if (!isContentScrollPositionAtTop()) {
1736
+ classList.add('np-bottom-sheet--top-bar--shadow');
2016
1737
  } else {
2017
- ref.cardElement?.focus();
1738
+ classList.remove('np-bottom-sheet--top-bar--shadow');
2018
1739
  }
2019
- scrollCardIntoView(carouselCardsRef.current[nextIndex].cardElement, nextCard);
2020
- event.preventDefault();
2021
1740
  }
1741
+ },
1742
+ eventType: 'scroll',
1743
+ parent: isServerSide() ? undefined : document
1744
+ });
1745
+ function move(newHeight) {
1746
+ if (bottomSheetReference.current !== null) {
1747
+ bottomSheetReference.current.style.transform = `translateY(${newHeight}px)`;
2022
1748
  }
2023
- if (event.key === 'Enter' || event.key === ' ') {
2024
- event.currentTarget.click();
1749
+ }
1750
+ function close(event) {
1751
+ setPressed(false);
1752
+ moveOffset.current = INITIAL_Y_POSITION;
1753
+ if (bottomSheetReference.current !== null) {
1754
+ bottomSheetReference.current.style.removeProperty('transform');
1755
+ }
1756
+ if (props.onClose) {
1757
+ props.onClose(event);
2025
1758
  }
1759
+ }
1760
+ const onSwipeStart = event => {
1761
+ initialYCoordinate.current = ('touches' in event ? event.touches[0] : event).clientY;
1762
+ setPressed(true);
2026
1763
  };
2027
- const scrollCardIntoView = (element, card) => {
2028
- element.scrollIntoView({
2029
- behavior: 'smooth',
2030
- block: 'nearest',
2031
- inline: 'center'
2032
- });
2033
- setFocusedCard(card.id);
1764
+ const onSwipeMove = event => {
1765
+ if (pressed) {
1766
+ const {
1767
+ clientY
1768
+ } = 'touches' in event ? event.touches[0] : event;
1769
+ const offset = calculateOffsetAfterMove(clientY);
1770
+ // check whether move is to the bottom only and content scroll position is at the top
1771
+ if (offset > INITIAL_Y_POSITION && isContentScrollPositionAtTop()) {
1772
+ moveOffset.current = offset;
1773
+ animationId.current = requestAnimationFrame(() => {
1774
+ if (animationId.current !== undefined && bottomSheetReference.current !== null) {
1775
+ move(offset);
1776
+ }
1777
+ });
1778
+ }
1779
+ }
2034
1780
  };
1781
+ function onSwipeEnd(event) {
1782
+ // stop moving component
1783
+ cancelAnimationFrame(animationId.current);
1784
+ setPressed(false);
1785
+ // check whether move down is strong enough
1786
+ // and content scroll position is at the top to close the component
1787
+ if (moveOffset.current > MOVE_OFFSET_THRESHOLD && isContentScrollPositionAtTop()) {
1788
+ close(event);
1789
+ }
1790
+ // otherwise move component back to default (initial) position
1791
+ else {
1792
+ move(INITIAL_Y_POSITION);
1793
+ }
1794
+ moveOffset.current = INITIAL_Y_POSITION;
1795
+ }
1796
+ function isContentScrollPositionAtTop() {
1797
+ return contentReference?.current?.scrollTop !== undefined && contentReference.current.scrollTop <= CONTENT_SCROLL_THRESHOLD;
1798
+ }
1799
+ /**
1800
+ * Calculates how hard user moves component,
1801
+ * result value used to determine whether to hide component or re-position to default state
1802
+ *
1803
+ * @param afterMoveYCoordinate
1804
+ */
1805
+ function calculateOffsetAfterMove(afterMoveYCoordinate) {
1806
+ return afterMoveYCoordinate - initialYCoordinate.current;
1807
+ }
1808
+ /**
1809
+ * Set `max-height` for content part (in order to keep it scrollable for content overflow cases) of the component
1810
+ * and ensures space for safe zone (32px) at the top.
1811
+ */
1812
+ function setContentMaxHeight() {
1813
+ const safeZoneHeight = '64px';
1814
+ const topbarHeight = '32px';
1815
+ const windowHight = isServerSide() ? 0 : window.innerHeight;
1816
+ /**
1817
+ * Calculate _real_ height of the screen (taking into account parts of browser interface).
1818
+ *
1819
+ * See https://css-tricks.com/the-trick-to-viewport-units-on-mobile for more details.
1820
+ */
1821
+ const screenHeight = `${windowHight * 0.01 * 100}px`;
1822
+ return {
1823
+ maxHeight: `calc(${screenHeight} - ${safeZoneHeight} - ${topbarHeight})`
1824
+ };
1825
+ }
1826
+ const is400Zoom = useMedia(`(max-width: ${exports.Breakpoint.ZOOM_400}px)`);
1827
+ return is400Zoom ? /*#__PURE__*/jsxRuntime.jsx(Drawer$1, {
1828
+ open: props.open,
1829
+ className: props.className,
1830
+ onClose: close,
1831
+ children: props.children
1832
+ }) : /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
1833
+ open: props.open,
1834
+ fadeContentOnEnter: true,
1835
+ fadeContentOnExit: true,
1836
+ onClose: close,
1837
+ children: /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
1838
+ ref: bottomSheetReference,
1839
+ open: props.open,
1840
+ position: exports.Position.BOTTOM,
1841
+ className: classNames__default.default('np-bottom-sheet', props.className),
1842
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
1843
+ role: "dialog",
1844
+ "aria-modal": true,
1845
+ onTouchStart: onSwipeStart,
1846
+ onTouchMove: onSwipeMove,
1847
+ onTouchEnd: onSwipeEnd,
1848
+ onMouseDown: onSwipeStart,
1849
+ onMouseMove: onSwipeMove,
1850
+ onMouseUp: onSwipeEnd,
1851
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1852
+ ref: topBarReference,
1853
+ className: "np-bottom-sheet--top-bar",
1854
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1855
+ className: "np-bottom-sheet--handler"
1856
+ }), /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1857
+ size: "sm",
1858
+ className: "sr-only np-bottom-sheet--close-btn",
1859
+ onClick: close
1860
+ })]
1861
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1862
+ ref: contentReference,
1863
+ style: setContentMaxHeight(),
1864
+ className: "np-bottom-sheet--content",
1865
+ children: props.children
1866
+ })]
1867
+ })
1868
+ })
1869
+ });
1870
+ };
1871
+
1872
+ const NavigationOption = /*#__PURE__*/React.forwardRef(({
1873
+ as: component = 'button',
1874
+ disabled = false,
1875
+ onClick,
1876
+ className,
1877
+ ...rest
1878
+ }, reference) => {
1879
+ if ('href' in rest && rest.href) {
1880
+ component = 'a';
1881
+ }
1882
+ return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1883
+ ...rest,
1884
+ ref: reference,
1885
+ as: component,
1886
+ className: classNames__default.default('np-navigation-option', className),
1887
+ button: /*#__PURE__*/jsxRuntime.jsx(Chevron, {
1888
+ orientation: exports.Position.RIGHT,
1889
+ disabled: disabled,
1890
+ className: "d-block"
1891
+ }),
1892
+ disabled: disabled,
1893
+ onClick: event => {
1894
+ if (disabled) {
1895
+ event.preventDefault();
1896
+ return;
1897
+ }
1898
+ if (onClick) {
1899
+ onClick(event);
1900
+ }
1901
+ }
1902
+ });
1903
+ });
1904
+
1905
+ const NavigationOptionList = ({
1906
+ children
1907
+ }) => {
1908
+ return /*#__PURE__*/jsxRuntime.jsx("ul", {
1909
+ className: "np-navigation-options-list",
1910
+ children: React.Children.map(children, child => /*#__PURE__*/jsxRuntime.jsx("li", {
1911
+ className: "np-navigation-options-list__item",
1912
+ children: child
1913
+ }, child?.toString()))
1914
+ });
1915
+ };
1916
+
1917
+ const FieldLabelIdContext = /*#__PURE__*/React.createContext(undefined);
1918
+ const FieldLabelIdContextProvider = FieldLabelIdContext.Provider;
1919
+ const InputIdContext = /*#__PURE__*/React.createContext(undefined);
1920
+ const InputIdContextProvider = InputIdContext.Provider;
1921
+ const InputDescribedByContext = /*#__PURE__*/React.createContext(undefined);
1922
+ const InputDescribedByProvider = InputDescribedByContext.Provider;
1923
+ const InputInvalidContext = /*#__PURE__*/React.createContext(undefined);
1924
+ const InputInvalidProvider = InputInvalidContext.Provider;
1925
+ function useInputAttributes({
1926
+ nonLabelable
1927
+ } = {}) {
1928
+ const labelId = React.useContext(FieldLabelIdContext);
1929
+ return {
1930
+ id: React.useContext(InputIdContext),
1931
+ 'aria-labelledby': nonLabelable ? labelId : undefined,
1932
+ 'aria-describedby': React.useContext(InputDescribedByContext),
1933
+ 'aria-invalid': React.useContext(InputInvalidContext)
1934
+ };
1935
+ }
1936
+ function withInputAttributes(Component, args) {
1937
+ function ComponentWithInputAttributes(props) {
1938
+ return /*#__PURE__*/jsxRuntime.jsx(Component, {
1939
+ inputAttributes: useInputAttributes(args),
1940
+ ...props
1941
+ });
1942
+ }
1943
+ ComponentWithInputAttributes.displayName = `withInputAttributes(${Component.displayName || Component.name || 'Component'})`;
1944
+ return ComponentWithInputAttributes;
1945
+ }
1946
+
1947
+ var messages$b = reactIntl.defineMessages({
1948
+ actionLabel: {
1949
+ id: "neptune.SelectOption.action.label"
1950
+ }
1951
+ });
1952
+
1953
+ function SelectOption({
1954
+ selected: selectedValueProp = undefined,
1955
+ optionsTitle,
1956
+ options,
1957
+ onChange,
1958
+ action,
1959
+ ...props
1960
+ }) {
1961
+ const intl = reactIntl.useIntl();
1962
+ const rootRef = React.useRef(null);
1963
+ const [selected, setSelected] = React.useState(selectedValueProp);
1964
+ const [showOptions, setShowOptions] = React.useState(false);
1965
+ const inputAttributes = useInputAttributes();
1966
+ function handleOnClick(showOptionsStatus) {
1967
+ return () => {
1968
+ setShowOptions(showOptionsStatus);
1969
+ };
1970
+ }
1971
+ function handleOnChange(data) {
1972
+ return () => {
1973
+ setShowOptions(false);
1974
+ setSelected(data);
1975
+ onChange(data);
1976
+ };
1977
+ }
1978
+ const isSelected = selected !== undefined;
1979
+ const {
1980
+ isMobile
1981
+ } = useLayout();
1982
+ function getOptionsContent(isMobileView = false) {
1983
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
1984
+ className: classNames__default.default('np-select-option-list'),
1985
+ children: options.map(optionsGroup =>
1986
+ /*#__PURE__*/
1987
+ // eslint-disable-next-line react/jsx-key
1988
+ jsxRuntime.jsxs(Section, {
1989
+ className: classNames__default.default('np-select-option-group', {
1990
+ 'p-a-2': !isMobileView
1991
+ }),
1992
+ children: [optionsGroup.title && /*#__PURE__*/jsxRuntime.jsx(Header, {
1993
+ title: optionsGroup.title
1994
+ }), /*#__PURE__*/jsxRuntime.jsx(NavigationOptionList, {
1995
+ children: optionsGroup.options.map(option =>
1996
+ /*#__PURE__*/
1997
+ // eslint-disable-next-line react/jsx-key
1998
+ jsxRuntime.jsx(NavigationOption, {
1999
+ isContainerAligned: isMobileView,
2000
+ showMediaCircle: true,
2001
+ showMediaAtAllSizes: true,
2002
+ media: option.media,
2003
+ title: option.title,
2004
+ content: option.content,
2005
+ onClick: handleOnChange(option)
2006
+ }))
2007
+ })]
2008
+ }))
2009
+ });
2010
+ }
2011
+ return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
2012
+ children: [/*#__PURE__*/jsxRuntime.jsx(Option$2, {
2013
+ ref: rootRef,
2014
+ ...props,
2015
+ ...inputAttributes,
2016
+ showMediaAtAllSizes: true,
2017
+ media: (isSelected ? selected : props).media,
2018
+ title: (isSelected ? selected : props).title,
2019
+ content: (isSelected ? selected : props).content,
2020
+ className: classNames__default.default('np-select-option', {
2021
+ 'np-select-option-selected': isSelected
2022
+ }, props.className),
2023
+ button: isSelected ? /*#__PURE__*/jsxRuntime.jsx(Chevron, {}) : /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
2024
+ disabled: props.disabled,
2025
+ onClick: handleOnClick(true),
2026
+ children: action?.label || intl.formatMessage(messages$b.actionLabel)
2027
+ }),
2028
+ onClick: isSelected ? handleOnClick(true) : undefined
2029
+ }), isMobile ? /*#__PURE__*/jsxRuntime.jsx(BottomSheet$1, {
2030
+ open: showOptions,
2031
+ onClose: handleOnClick(false),
2032
+ children: getOptionsContent(true)
2033
+ }) : /*#__PURE__*/jsxRuntime.jsx(Panel, {
2034
+ anchorWidth: true,
2035
+ open: showOptions,
2036
+ flip: false,
2037
+ altAxis: false,
2038
+ anchorRef: rootRef,
2039
+ position: exports.Position.BOTTOM,
2040
+ onClose: handleOnClick(false),
2041
+ children: getOptionsContent(false)
2042
+ })]
2043
+ });
2044
+ }
2045
+
2046
+ const iconTypeMap = {
2047
+ positive: icons.Check,
2048
+ neutral: icons.Info,
2049
+ warning: icons.Alert,
2050
+ negative: icons.Cross,
2051
+ pending: icons.ClockBorderless,
2052
+ info: icons.Info,
2053
+ error: icons.Cross,
2054
+ success: icons.Check
2055
+ };
2056
+ const StatusIcon = ({
2057
+ sentiment = 'neutral',
2058
+ size = 'md'
2059
+ }) => {
2060
+ const Icon = iconTypeMap[sentiment];
2061
+ const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
2062
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
2063
+ "data-testid": "status-icon",
2064
+ className: classNames__default.default('status-circle', 'status-circle-' + size, sentiment),
2065
+ children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
2066
+ className: classNames__default.default('status-icon', iconColor)
2067
+ })
2068
+ });
2069
+ };
2070
+
2071
+ const reader = new commonmark__default.default.Parser();
2072
+ const writer = new commonmark__default.default.HtmlRenderer({
2073
+ safe: true
2074
+ });
2075
+ const NODE_TYPE_LIST = Object.values(exports.MarkdownNodeType);
2076
+ function Markdown({
2077
+ as: Element = 'div',
2078
+ allowList,
2079
+ blockList,
2080
+ config,
2081
+ className,
2082
+ children
2083
+ }) {
2084
+ if (!children) {
2085
+ return null;
2086
+ }
2087
+ const linkTarget = config?.link?.target ?? '_self';
2088
+ const paragraphClass = config?.paragraph?.className ?? '';
2089
+ if (allowList != null && blockList != null) {
2090
+ logActionRequired('Markdown supports only one of `allowList` or `blockList` to be used at a time. `blockList` will be ignored.');
2091
+ }
2092
+ const parser = nodes => {
2093
+ const parsed = reader.parse(nodes);
2094
+ const toExclude = allowList != null ? NODE_TYPE_LIST.filter(type => !allowList.includes(type)) : blockList;
2095
+ return toExclude != null ? stripNodes({
2096
+ parsed,
2097
+ blockList: toExclude
2098
+ }) : parsed;
2099
+ };
2100
+ const createMarkup = () => {
2101
+ const parsed = parser(children);
2102
+ return writer.render(parsed).replace(/<a href="/g, `<a target="${linkTarget}" href="`).replace(/<p>/g, `<p class="${paragraphClass}">`);
2103
+ };
2104
+ return /*#__PURE__*/jsxRuntime.jsx(Element, {
2105
+ className: className,
2106
+ dangerouslySetInnerHTML: {
2107
+ __html: createMarkup()
2108
+ }
2109
+ });
2110
+ }
2111
+ function stripNodes({
2112
+ blockList,
2113
+ parsed
2114
+ }) {
2115
+ if (!parsed) {
2116
+ return parsed;
2117
+ }
2118
+ const walker = parsed.walker();
2119
+ for (let event = walker.next(); event != null; event = walker.next()) {
2120
+ const {
2121
+ node
2122
+ } = event;
2123
+ if (blockList.includes(node.type) && !event.entering) {
2124
+ while (node.firstChild != null) {
2125
+ node.insertBefore(node.firstChild);
2126
+ }
2127
+ node.unlink();
2128
+ }
2129
+ }
2130
+ return parsed;
2131
+ }
2132
+
2133
+ const allowList = [exports.MarkdownNodeType.STRONG];
2134
+ const InlineMarkdown = props => {
2135
+ return /*#__PURE__*/jsxRuntime.jsx(Markdown, {
2136
+ ...props,
2137
+ as: "span",
2138
+ allowList: allowList,
2139
+ blockList: undefined
2140
+ });
2141
+ };
2142
+ InlineMarkdown.propTypes = {
2143
+ children: PropTypes__default.default.string.isRequired,
2144
+ className: PropTypes__default.default.string
2145
+ };
2146
+ InlineMarkdown.defaultProps = {
2147
+ className: undefined
2148
+ };
2149
+
2150
+ function Action({
2151
+ action,
2152
+ className
2153
+ }) {
2154
+ if ('href' in action) {
2155
+ return /*#__PURE__*/jsxRuntime.jsx(Link, {
2156
+ href: action.href,
2157
+ className: className,
2158
+ "aria-label": action['aria-label'],
2159
+ target: action.target,
2160
+ type: exports.Typography.LINK_LARGE,
2161
+ onClick: action.onClick,
2162
+ children: action.text
2163
+ });
2164
+ }
2165
+ return /*#__PURE__*/jsxRuntime.jsx("button", {
2166
+ type: "button",
2167
+ "aria-label": action['aria-label'],
2168
+ className: classNames__default.default('btn-unstyled np-text-link-large', className),
2169
+ onClick: action.onClick,
2170
+ children: action.text
2171
+ });
2172
+ }
2173
+
2174
+ exports.AlertArrowPosition = void 0;
2175
+ (function (AlertArrowPosition) {
2176
+ AlertArrowPosition["TOP_LEFT"] = "up-left";
2177
+ AlertArrowPosition["TOP"] = "up-center";
2178
+ AlertArrowPosition["TOP_RIGHT"] = "up-right";
2179
+ AlertArrowPosition["BOTTOM_LEFT"] = "down-left";
2180
+ AlertArrowPosition["BOTTOM"] = "down-center";
2181
+ AlertArrowPosition["BOTTOM_RIGHT"] = "down-right";
2182
+ })(exports.AlertArrowPosition || (exports.AlertArrowPosition = {}));
2183
+ function resolveType(type) {
2184
+ switch (type) {
2185
+ case 'success':
2186
+ return 'positive';
2187
+ case 'info':
2188
+ return 'neutral';
2189
+ case 'error':
2190
+ return 'negative';
2191
+ default:
2192
+ return type;
2193
+ }
2194
+ }
2195
+ function Alert({
2196
+ arrow,
2197
+ action,
2198
+ children,
2199
+ className,
2200
+ dismissible,
2201
+ icon,
2202
+ onDismiss,
2203
+ message,
2204
+ size,
2205
+ title,
2206
+ type = 'neutral',
2207
+ variant = 'desktop'
2208
+ }) {
2035
2209
  React.useEffect(() => {
2036
- updateScrollButtonsState();
2037
- // eslint-disable-next-line react-hooks/exhaustive-deps
2038
- }, [scrollPosition]);
2210
+ if (arrow !== undefined) {
2211
+ logActionRequired("Alert component doesn't support 'arrow' anymore, use 'InlineAlert' instead.");
2212
+ }
2213
+ }, [arrow]);
2039
2214
  React.useEffect(() => {
2040
- window.addEventListener('resize', updateScrollButtonsState);
2041
- return () => {
2042
- window.removeEventListener('resize', updateScrollButtonsState);
2043
- };
2044
- // eslint-disable-next-line react-hooks/exhaustive-deps
2045
- }, []);
2046
- const addElementToCardsRefArray = (index, ref) => {
2047
- if (ref) {
2048
- // eslint-disable-next-line functional/immutable-data
2049
- carouselCardsRef.current[index] = {
2050
- type: ref.type ?? carouselCardsRef.current?.[index]?.type,
2051
- cardElement: ref.cardElement ?? carouselCardsRef.current?.[index]?.cardElement,
2052
- anchorElement: ref.anchorElement ?? carouselCardsRef.current?.[index]?.anchorElement
2053
- };
2215
+ if (children !== undefined) {
2216
+ logActionRequired("Alert component doesn't support 'children' anymore, use 'message' instead.");
2054
2217
  }
2055
- };
2218
+ }, [children]);
2219
+ React.useEffect(() => {
2220
+ if (dismissible !== undefined) {
2221
+ logActionRequired("Alert component doesn't support 'dismissible' anymore, use 'onDismiss' instead.");
2222
+ }
2223
+ }, [dismissible]);
2224
+ React.useEffect(() => {
2225
+ if (size !== undefined) {
2226
+ logActionRequired("Alert component doesn't support 'size' anymore, please remove that prop.");
2227
+ }
2228
+ }, [size]);
2229
+ const resolvedType = resolveType(type);
2230
+ React.useEffect(() => {
2231
+ if (resolvedType !== type) {
2232
+ logActionRequired(`Alert component has deprecated '${type}' value for the 'type' prop. Please use '${resolvedType}' instead.`);
2233
+ }
2234
+ }, [resolvedType, type]);
2235
+ const [shouldFire, setShouldFire] = React.useState(false);
2236
+ const closeButtonReference = React.useRef(null);
2056
2237
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
2057
- className: classNames__default.default('carousel-wrapper', className),
2058
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2059
- className: "d-flex justify-content-between carousel__header",
2060
- children: [typeof header === 'string' ? /*#__PURE__*/jsxRuntime.jsx(Title, {
2061
- as: "span",
2062
- type: "title-body",
2063
- children: header
2064
- }) : header, areActionButtonsEnabled ? /*#__PURE__*/jsxRuntime.jsxs("div", {
2065
- className: "hidden-xs",
2066
- children: [/*#__PURE__*/jsxRuntime.jsx(ActionButton, {
2067
- className: "carousel__scroll-button",
2068
- tabIndex: -1,
2069
- priority: "secondary",
2070
- disabled: !isLeftActionButtonEnabled,
2071
- "aria-hidden": "true",
2072
- "data-testid": "scroll-carousel-left",
2073
- onClick: () => scrollCarousel('left'),
2074
- children: /*#__PURE__*/jsxRuntime.jsx(icons.ChevronLeft, {})
2075
- }), /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
2076
- tabIndex: -1,
2077
- className: "carousel__scroll-button m-l-1",
2078
- priority: "secondary",
2079
- "aria-hidden": "true",
2080
- "data-testid": "scroll-carousel-right",
2081
- disabled: scrollIsAtEnd,
2082
- onClick: () => scrollCarousel(),
2083
- children: /*#__PURE__*/jsxRuntime.jsx(icons.ChevronRight, {})
2084
- })]
2085
- }) : null]
2086
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
2087
- ref: carouselElementRef,
2088
- tabIndex: -1,
2089
- role: "list",
2090
- className: "carousel",
2091
- onScroll: event => {
2092
- const target = event.target;
2093
- setScrollPosition(target.scrollLeft);
2094
- },
2095
- children: cards?.map((card, index) => {
2096
- const sharedProps = {
2097
- id: card.id,
2098
- className: classNames__default.default('carousel__card', {
2099
- 'carousel__card--focused': card.id === focusedCard
2100
- }),
2101
- onClick: () => {
2102
- card.onClick?.();
2103
- onClick?.(card.id);
2104
- },
2105
- onFocus: event => {
2106
- scrollCardIntoView(event.currentTarget, card);
2107
- }
2108
- };
2109
- const cardContent = card.type !== 'promo' ? /*#__PURE__*/jsxRuntime.jsx("div", {
2110
- id: `${card.id}-content`,
2111
- className: classNames__default.default('carousel__card-content', {
2112
- [card.className ?? '']: !!card.className
2113
- })
2114
- // eslint-disable-next-line react/forbid-dom-props
2115
- ,
2116
- style: card.styles,
2117
- children: card.content
2118
- }) : null;
2119
- if (card.type === 'button') {
2120
- return /*#__PURE__*/jsxRuntime.jsx("div", {
2121
- "aria-labelledby": `${card.id}-content`,
2122
- role: "listitem",
2123
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
2124
- ...sharedProps,
2125
- ref: el => {
2126
- if (el) {
2127
- // eslint-disable-next-line functional/immutable-data
2128
- carouselCardsRef.current[index] = {
2129
- type: 'default',
2130
- cardElement: el
2131
- };
2132
- }
2133
- },
2134
- role: "button",
2135
- tabIndex: 0,
2136
- onKeyDown: event => handleOnKeyDown(event, index),
2137
- children: cardContent
2138
- })
2139
- }, card.id);
2238
+ className: classNames__default.default('alert d-flex', `alert-${resolvedType}`, arrow != null && alertArrowClassNames(arrow), className),
2239
+ "data-testid": "alert",
2240
+ onTouchStart: () => setShouldFire(true),
2241
+ onTouchEnd: event => {
2242
+ if (shouldFire && action?.href &&
2243
+ // Check if current event is triggered from closeButton
2244
+ event.target instanceof Node && closeButtonReference.current && !closeButtonReference.current.contains(event.target)) {
2245
+ if (action.target === '_blank') {
2246
+ window.top?.open(action.href);
2247
+ } else {
2248
+ window.top?.location.assign(action.href);
2140
2249
  }
2141
- if (card.type === 'promo') {
2142
- return /*#__PURE__*/jsxRuntime.jsx("div", {
2143
- id: card.id,
2144
- role: "listitem",
2145
- "aria-labelledby": `${card.id}-anchor`,
2146
- children: /*#__PURE__*/jsxRuntime.jsx(PromoCard$1, {
2147
- ...card,
2148
- type: undefined,
2149
- ...sharedProps,
2150
- ref: el => {
2151
- if (el) {
2152
- addElementToCardsRefArray(index, {
2153
- type: 'promo',
2154
- cardElement: el
2155
- });
2156
- }
2157
- },
2158
- anchorRef: el => {
2159
- if (el) {
2160
- addElementToCardsRefArray(index, {
2161
- type: 'promo',
2162
- anchorElement: el
2163
- });
2164
- }
2165
- },
2166
- anchorId: `${card.id}-anchor`,
2167
- onKeyDown: event => handleOnKeyDown(event, index)
2250
+ }
2251
+ setShouldFire(false);
2252
+ },
2253
+ onTouchMove: () => setShouldFire(false),
2254
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2255
+ className: classNames__default.default('alert__content', 'd-flex', 'flex-grow-1', variant),
2256
+ "data-testid": variant,
2257
+ children: [icon ? /*#__PURE__*/jsxRuntime.jsx("div", {
2258
+ className: "alert__icon",
2259
+ children: icon
2260
+ }) : /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
2261
+ size: exports.Size.LARGE,
2262
+ sentiment: resolvedType
2263
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2264
+ className: "alert__message",
2265
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2266
+ role: exports.Sentiment.NEGATIVE === resolvedType ? 'alert' : 'status',
2267
+ children: [title && /*#__PURE__*/jsxRuntime.jsx(Title, {
2268
+ className: "m-b-1",
2269
+ type: exports.Typography.TITLE_BODY,
2270
+ children: title
2271
+ }), /*#__PURE__*/jsxRuntime.jsx(Body, {
2272
+ as: "span",
2273
+ className: "d-block",
2274
+ type: exports.Typography.BODY_LARGE,
2275
+ children: children || /*#__PURE__*/jsxRuntime.jsx(InlineMarkdown, {
2276
+ children: message
2168
2277
  })
2169
- }, card.id);
2170
- }
2171
- return /*#__PURE__*/jsxRuntime.jsx("div", {
2172
- "aria-labelledby": `${card.id}-content`,
2173
- role: "listitem",
2174
- children: /*#__PURE__*/jsxRuntime.jsx("a", {
2175
- ...sharedProps,
2176
- ref: el => {
2177
- if (el) {
2178
- // eslint-disable-next-line functional/immutable-data
2179
- carouselCardsRef.current[index] = {
2180
- type: 'default',
2181
- cardElement: el
2182
- };
2183
- }
2184
- },
2185
- href: card.href,
2186
- rel: "noreferrer",
2187
- onKeyDown: event => handleOnKeyDown(event, index),
2188
- children: cardContent
2189
- })
2190
- }, card.id);
2191
- })
2192
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
2193
- className: "visible-xs",
2194
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
2195
- className: "carousel__indicators",
2196
- children: cards?.map((card, index) => /*#__PURE__*/jsxRuntime.jsx("button", {
2197
- "data-testid": `${card.id}-indicator`,
2198
- tabIndex: -1,
2199
- "aria-hidden": true,
2200
- type: "button",
2201
- className: classNames__default.default('carousel__indicator', {
2202
- 'carousel__indicator--selected': card.id === visibleCardOnMobileView
2203
- }),
2204
- onClick: () => {
2205
- scrollCardIntoView(carouselCardsRef.current[index].cardElement, card);
2206
- }
2207
- }, `${card.id}-indicator`))
2208
- })
2278
+ })]
2279
+ }), action && /*#__PURE__*/jsxRuntime.jsx(Action, {
2280
+ action: action,
2281
+ className: "m-t-1"
2282
+ })]
2283
+ })]
2284
+ }), onDismiss && /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2285
+ ref: closeButtonReference,
2286
+ className: "m-l-2",
2287
+ onClick: onDismiss
2209
2288
  })]
2210
2289
  });
2211
- };
2212
- const isVisible = (container, el) => {
2213
- const cWidth = container.offsetWidth;
2214
- const cScrollOffset = container.scrollLeft;
2215
- const elemLeft = el.offsetLeft - container.offsetLeft;
2216
- const elemRight = elemLeft + el.offsetWidth;
2217
- return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;
2218
- };
2290
+ }
2291
+ function alertArrowClassNames(arrow) {
2292
+ switch (arrow) {
2293
+ case 'down-center':
2294
+ return 'arrow arrow-bottom arrow-center';
2295
+ case 'down-left':
2296
+ return 'arrow arrow-bottom arrow-left';
2297
+ case 'down-right':
2298
+ return 'arrow arrow-bottom arrow-right';
2299
+ case 'up-center':
2300
+ return 'arrow arrow-center';
2301
+ case 'up-right':
2302
+ return 'arrow arrow-right';
2303
+ case 'up-left':
2304
+ default:
2305
+ return 'arrow';
2306
+ }
2307
+ }
2219
2308
 
2220
- const Card = /*#__PURE__*/React.forwardRef((props, reference) => {
2221
- const {
2222
- 'aria-label': ariaLabel,
2223
- as: Element,
2224
- isExpanded,
2225
- title,
2226
- details,
2227
- children,
2228
- onClick,
2229
- icon,
2230
- id,
2231
- className,
2232
- ...rest
2233
- } = props;
2234
- const isOpen = !!(isExpanded && children);
2235
- return /*#__PURE__*/jsxRuntime.jsxs(Element, {
2236
- ref: reference,
2237
- className: classNames__default.default('np-card', className, {
2238
- 'np-card--expanded': isOpen,
2239
- 'np-card--inactive': !children,
2240
- 'np-card--has-icon': !!icon
2241
- }),
2242
- id: id,
2243
- "data-testid": rest['data-testid'],
2244
- children: [/*#__PURE__*/jsxRuntime.jsx(Option$2, {
2245
- "aria-label": ariaLabel,
2246
- as: children ? 'button' : 'div',
2247
- className: classNames__default.default('np-card__button'),
2248
- media: icon,
2249
- title: title,
2250
- content: details,
2251
- showMediaAtAllSizes: true,
2252
- button: children && /*#__PURE__*/jsxRuntime.jsx(Chevron, {
2253
- orientation: isOpen ? exports.Position.TOP : exports.Position.BOTTOM
2254
- }),
2255
- onClick: () => children && onClick(!isExpanded)
2256
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
2257
- className: classNames__default.default('np-card__divider', {
2258
- 'np-card__divider--expanded': isOpen
2259
- })
2260
- }), isOpen && /*#__PURE__*/jsxRuntime.jsx(Body, {
2261
- as: "span",
2262
- type: exports.Typography.BODY_LARGE,
2263
- className: "np-card__content d-block",
2264
- children: children
2265
- })]
2266
- });
2267
- });
2268
- const hasChildren = ({
2269
- children
2270
- }) => children;
2271
- Card.propTypes = {
2272
- 'aria-label': PropTypes__default.default.string,
2273
- as: PropTypes__default.default.string,
2274
- isExpanded: requiredIf__default.default(PropTypes__default.default.bool, hasChildren),
2275
- title: PropTypes__default.default.node.isRequired,
2276
- details: PropTypes__default.default.node.isRequired,
2277
- onClick: requiredIf__default.default(PropTypes__default.default.func, hasChildren),
2278
- icon: PropTypes__default.default.node,
2279
- children: PropTypes__default.default.node,
2280
- id: PropTypes__default.default.string,
2281
- className: PropTypes__default.default.string,
2282
- 'data-testid': PropTypes__default.default.string
2309
+ // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
2310
+ exports.AvatarType = void 0;
2311
+ (function (AvatarType) {
2312
+ AvatarType["THUMBNAIL"] = "thumbnail";
2313
+ AvatarType["ICON"] = "icon";
2314
+ AvatarType["EMOJI"] = "emoji";
2315
+ AvatarType["INITIALS"] = "initials";
2316
+ })(exports.AvatarType || (exports.AvatarType = {}));
2317
+
2318
+ /*
2319
+ * The colors we support generating an Avatar background color from a "seed" for.
2320
+ * Changing this array will change the assignment between seeds.
2321
+ * Do not change this array.
2322
+ */
2323
+ const avatarColors = ['--color-bright-blue', '--color-bright-yellow', '--color-bright-pink', '--color-bright-orange'];
2324
+ /*
2325
+ * Takes in a "seed" string and spits out an index for the color we should use.
2326
+ * This implementation has been synced across all three clients so that we consistently
2327
+ * generate branded avatar colors when rendering a list of Avatars.
2328
+ * Do not change this implementation.
2329
+ */
2330
+ const hashSeed = seed => {
2331
+ const base = 31;
2332
+ const modulo = avatarColors.length;
2333
+ let hashValue = 0;
2334
+ let basePow = 1;
2335
+ for (let i = 0; i < seed.length; i += 1) {
2336
+ hashValue = (hashValue + seed.charCodeAt(i) * basePow) % modulo;
2337
+ basePow = basePow * base % modulo;
2338
+ }
2339
+ return hashValue;
2283
2340
  };
2284
- Card.defaultProps = {
2285
- 'aria-label': undefined,
2286
- as: 'div',
2287
- children: null,
2288
- id: null,
2289
- className: null,
2290
- 'data-testid': null
2341
+ const getAvatarColorFromSeed = seed => {
2342
+ return avatarColors[hashSeed(seed)];
2291
2343
  };
2292
- var Card$1 = Card;
2293
-
2294
- const CheckboxButton = /*#__PURE__*/React.forwardRef(({
2295
- checked,
2296
- className,
2297
- disabled,
2298
- onChange,
2299
- ...rest
2300
- }, reference) => /*#__PURE__*/jsxRuntime.jsxs("span", {
2301
- className: classNames__default.default('np-checkbox-button', className, disabled && 'disabled'),
2302
- children: [/*#__PURE__*/jsxRuntime.jsx("input", {
2303
- ...rest,
2304
- ref: reference,
2305
- type: "checkbox",
2306
- disabled: disabled,
2307
- checked: checked,
2308
- onChange: onChange
2309
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
2310
- className: "tw-checkbox-button",
2311
- children: /*#__PURE__*/jsxRuntime.jsx("span", {
2312
- className: "tw-checkbox-check"
2313
- })
2314
- })]
2315
- }));
2316
- var CheckboxButton$1 = CheckboxButton;
2317
2344
 
2318
- const Checkbox = ({
2319
- id,
2320
- checked,
2321
- required,
2322
- disabled,
2323
- readOnly,
2324
- label,
2345
+ const backwardsCompatibleSize = size => {
2346
+ switch (size) {
2347
+ case 'sm':
2348
+ return 24;
2349
+ case 'md':
2350
+ return 48;
2351
+ case 'lg':
2352
+ return 72;
2353
+ default:
2354
+ return size;
2355
+ }
2356
+ };
2357
+ const Avatar = ({
2358
+ backgroundColor = null,
2359
+ backgroundColorSeed = null,
2360
+ children = null,
2325
2361
  className,
2326
- secondary,
2327
- onChange,
2328
- onFocus,
2329
- onBlur
2362
+ outlined = false,
2363
+ size: sizeFromProps = 48,
2364
+ theme = exports.Theme.LIGHT,
2365
+ type = 'thumbnail'
2330
2366
  }) => {
2331
- const {
2332
- isModern
2333
- } = componentsTheming.useTheme();
2334
- const classList = classNames__default.default('np-checkbox', {
2335
- checkbox: true,
2336
- 'checkbox-lg': secondary,
2337
- disabled: isModern && disabled
2338
- }, className);
2339
- const innerDisabled = disabled || readOnly;
2367
+ const backgroundColorFromSeed = React.useMemo(() => !backgroundColor && backgroundColorSeed ? `var(${getAvatarColorFromSeed(backgroundColorSeed)})` : undefined, [backgroundColor, backgroundColorSeed]);
2368
+ const size = backwardsCompatibleSize(sizeFromProps);
2340
2369
  return /*#__PURE__*/jsxRuntime.jsx("div", {
2341
- id: id,
2342
- className: classList,
2343
- children: /*#__PURE__*/jsxRuntime.jsxs("label", {
2344
- className: classNames__default.default({
2345
- disabled
2346
- }),
2347
- children: [/*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
2348
- className: "p-r-2",
2349
- checked: checked,
2350
- disabled: innerDisabled,
2351
- required: !innerDisabled && required,
2352
- onFocus: onFocus,
2353
- onChange: () => onChange(!checked),
2354
- onBlur: onBlur
2355
- }), /*#__PURE__*/jsxRuntime.jsxs(Body, {
2356
- as: "span",
2357
- className: "np-checkbox__text",
2358
- type: secondary ? exports.Typography.BODY_LARGE_BOLD : exports.Typography.BODY_LARGE,
2359
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
2360
- className: required ? 'has-required' : undefined,
2361
- children: label
2362
- }), secondary && /*#__PURE__*/jsxRuntime.jsx(Body, {
2363
- as: "span",
2364
- className: classNames__default.default({
2365
- secondary: !isModern
2366
- }),
2367
- children: secondary
2368
- })]
2369
- })]
2370
- })
2371
- });
2372
- };
2373
- Checkbox.propTypes = {
2374
- id: PropTypes__default.default.string,
2375
- checked: PropTypes__default.default.bool,
2376
- required: PropTypes__default.default.bool,
2377
- disabled: PropTypes__default.default.bool,
2378
- readOnly: PropTypes__default.default.bool,
2379
- label: PropTypes__default.default.node.isRequired,
2380
- secondary: PropTypes__default.default.string,
2381
- onFocus: PropTypes__default.default.func,
2382
- onChange: PropTypes__default.default.func.isRequired,
2383
- onBlur: PropTypes__default.default.func,
2384
- className: PropTypes__default.default.string
2370
+ className: classNames__default.default('tw-avatar', className, `tw-avatar--${size}`, `tw-avatar--${type}`, {
2371
+ 'tw-avatar--outlined': outlined,
2372
+ 'tw-avatar--branded': Boolean(backgroundColorFromSeed),
2373
+ 'np-text-title-body': type === 'initials'
2374
+ }),
2375
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
2376
+ className: "tw-avatar__content",
2377
+ style: {
2378
+ backgroundColor: backgroundColor || backgroundColorFromSeed
2379
+ },
2380
+ children: children
2381
+ })
2382
+ });
2385
2383
  };
2386
- Checkbox.defaultProps = {
2387
- id: null,
2388
- checked: false,
2389
- required: false,
2390
- disabled: false,
2391
- readOnly: false,
2392
- secondary: null,
2393
- onFocus: null,
2394
- onBlur: null,
2395
- className: undefined
2384
+
2385
+ const Badge = ({
2386
+ badge,
2387
+ className = undefined,
2388
+ size = exports.Size.SMALL,
2389
+ border = exports.Theme.LIGHT,
2390
+ children
2391
+ }) => {
2392
+ const classes = classNames__default.default('tw-badge', {
2393
+ [`tw-badge-border-${border}`]: border,
2394
+ [`tw-badge-${size}`]: size
2395
+ }, className);
2396
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2397
+ className: classes,
2398
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2399
+ className: "tw-badge__children",
2400
+ children: children
2401
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2402
+ className: "tw-badge__content",
2403
+ children: badge
2404
+ })]
2405
+ });
2396
2406
  };
2397
2407
 
2398
- const CheckboxOption = /*#__PURE__*/React.forwardRef(({
2399
- checked,
2400
- disabled,
2401
- onChange,
2408
+ const OptionalBadge = ({
2409
+ url,
2410
+ altText,
2411
+ statusIcon,
2412
+ children,
2402
2413
  ...rest
2403
- }, reference) => {
2404
- return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
2405
- ...rest,
2406
- ref: reference,
2407
- disabled: disabled,
2408
- button: /*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
2409
- checked: checked,
2410
- disabled: disabled,
2411
- onChange: () => onChange?.(!checked)
2414
+ }) => {
2415
+ if (url) {
2416
+ return /*#__PURE__*/jsxRuntime.jsx(Badge, {
2417
+ badge: /*#__PURE__*/jsxRuntime.jsx("img", {
2418
+ src: url,
2419
+ alt: altText
2420
+ }),
2421
+ ...rest,
2422
+ children: children
2423
+ });
2424
+ }
2425
+ if (statusIcon) {
2426
+ return /*#__PURE__*/jsxRuntime.jsx(Badge, {
2427
+ badge: /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
2428
+ sentiment: statusIcon,
2429
+ size: exports.Size.SMALL
2430
+ }),
2431
+ ...rest,
2432
+ children: children
2433
+ });
2434
+ }
2435
+ return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
2436
+ children: children
2437
+ });
2438
+ };
2439
+ const AvatarWrapper = ({
2440
+ url,
2441
+ profileType,
2442
+ profileId,
2443
+ badgeUrl,
2444
+ badgeAltText,
2445
+ badgeStatusIcon,
2446
+ name,
2447
+ avatarProps,
2448
+ badgeProps
2449
+ }) => {
2450
+ const [hasImageLoadError, setImageLoadError] = React.useState(false);
2451
+ const isBusinessProfile = profileType === exports.ProfileType.BUSINESS;
2452
+ // Reset the errored state when url changes
2453
+ React.useEffect(() => setImageLoadError(false), [url]);
2454
+ const getAvatarProps = () => {
2455
+ if (url && !hasImageLoadError) {
2456
+ return {
2457
+ type: exports.AvatarType.THUMBNAIL,
2458
+ children: /*#__PURE__*/jsxRuntime.jsx("img", {
2459
+ src: url,
2460
+ alt: "",
2461
+ onError: () => setImageLoadError(true)
2462
+ }),
2463
+ ...avatarProps
2464
+ };
2465
+ }
2466
+ if (profileType) {
2467
+ return {
2468
+ type: exports.AvatarType.ICON,
2469
+ children: isBusinessProfile ? /*#__PURE__*/jsxRuntime.jsx(icons.Briefcase, {
2470
+ size: "24"
2471
+ }) : /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
2472
+ size: "24"
2473
+ }),
2474
+ ...avatarProps
2475
+ };
2476
+ }
2477
+ if (name) {
2478
+ return {
2479
+ type: exports.AvatarType.INITIALS,
2480
+ children: /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
2481
+ children: getInitials(name)
2482
+ }),
2483
+ backgroundColorSeed: profileId?.toString(),
2484
+ ...avatarProps
2485
+ };
2486
+ }
2487
+ return {
2488
+ type: exports.AvatarType.ICON,
2489
+ children: /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
2490
+ size: "24"
2491
+ }),
2492
+ ...avatarProps
2493
+ };
2494
+ };
2495
+ return /*#__PURE__*/jsxRuntime.jsx(OptionalBadge, {
2496
+ url: badgeUrl,
2497
+ altText: badgeAltText,
2498
+ statusIcon: badgeStatusIcon,
2499
+ ...badgeProps,
2500
+ children: /*#__PURE__*/jsxRuntime.jsx(Avatar, {
2501
+ size: exports.Size.MEDIUM,
2502
+ ...getAvatarProps()
2412
2503
  })
2413
2504
  });
2414
- });
2505
+ };
2506
+ function getInitials(name) {
2507
+ const allInitials = name.split(' ').map(part => part[0]).join('').toUpperCase();
2508
+ if (allInitials.length === 1) {
2509
+ return allInitials[0];
2510
+ }
2511
+ return allInitials[0] + allInitials.slice(-1);
2512
+ }
2415
2513
 
2416
- const Chip = ({
2417
- label,
2418
- value,
2419
- onRemove,
2420
- onClick,
2421
- onKeyPress,
2422
- className = undefined,
2423
- 'aria-label': ariaLabel,
2424
- 'aria-checked': ariaChecked,
2425
- role,
2426
- closeButton
2427
- }) => {
2428
- const isActionable = onClick || onKeyPress;
2429
- const defaultRole = isActionable ? 'button' : undefined;
2430
- const tabIndex = isActionable ? 0 : -1;
2431
- const {
2432
- isModern
2433
- } = componentsTheming.useTheme();
2514
+ const Card$2 = /*#__PURE__*/React.forwardRef(({
2515
+ className,
2516
+ children = null,
2517
+ id,
2518
+ isDisabled = false,
2519
+ isSmall = false,
2520
+ onDismiss,
2521
+ testId,
2522
+ ...props
2523
+ }, ref) => {
2434
2524
  const closeButtonReference = React.useRef(null);
2435
- const previousCloseButtonShown = React.useRef(undefined);
2436
- React.useEffect(() => {
2437
- if (closeButtonReference.current != null && previousCloseButtonShown.current === false) {
2438
- closeButtonReference.current?.focus();
2439
- }
2440
- previousCloseButtonShown.current = closeButtonReference.current != null;
2441
- }, [onRemove]);
2442
2525
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
2443
- role: role ?? defaultRole,
2444
- tabIndex: tabIndex,
2445
- "aria-label": ariaLabel,
2446
- "aria-checked": ariaChecked,
2447
- className: classNames__default.default('np-chip', 'd-flex', 'align-items-center', 'justify-content-between', onRemove ? 'np-chip--removable' : '', className),
2448
- ...(isActionable && {
2449
- onClick,
2450
- onKeyPress
2451
- }),
2452
- children: [isModern ? /*#__PURE__*/jsxRuntime.jsx(Body, {
2453
- "aria-hidden": !!onRemove,
2454
- type: exports.Typography.BODY_DEFAULT_BOLD,
2455
- children: label
2456
- }) : /*#__PURE__*/jsxRuntime.jsx("span", {
2457
- "aria-hidden": "false",
2458
- className: "np-chip-label",
2459
- children: label
2460
- }), onRemove ? /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2526
+ ref: ref,
2527
+ className: classNames__default.default('np-Card', {
2528
+ 'np-Card--small': !!isSmall,
2529
+ 'is-disabled': !!isDisabled
2530
+ }, className),
2531
+ id: id,
2532
+ "data-testid": testId,
2533
+ ...props,
2534
+ children: [onDismiss && /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2461
2535
  ref: closeButtonReference,
2462
- className: isModern ? `btn-unstyled` : `btn-unstyled m-l-1`,
2463
- "aria-label": closeButton?.['aria-label'],
2464
- size: "sm",
2465
- filled: isModern,
2466
- onClick: onRemove
2467
- }) : null]
2468
- }, value);
2469
- };
2470
-
2471
- var messages$a = reactIntl.defineMessages({
2472
- ariaLabel: {
2473
- id: "neptune.Chips.ariaLabel"
2474
- }
2536
+ className: "np-Card-closeButton",
2537
+ size: isSmall ? 'sm' : 'md',
2538
+ isDisabled: isDisabled,
2539
+ testId: "close-button",
2540
+ onClick: e => {
2541
+ stopPropagation$1(e);
2542
+ onDismiss();
2543
+ }
2544
+ }), children]
2545
+ });
2475
2546
  });
2547
+ Card$2.displayName = 'Card';
2476
2548
 
2477
- const Chips = ({
2478
- chips,
2479
- onChange,
2480
- selected,
2481
- 'aria-label': ariaLabel,
2549
+ function Display({
2550
+ as: Heading = 'h1',
2551
+ type = exports.Typography.DISPLAY_LARGE,
2552
+ children,
2553
+ className,
2554
+ id
2555
+ }) {
2556
+ return /*#__PURE__*/jsxRuntime.jsx(Heading, {
2557
+ id: id,
2558
+ className: classNames__default.default(`np-text-${type}`, 'text-primary', className),
2559
+ children: children
2560
+ });
2561
+ }
2562
+
2563
+ const EmptyTransparentImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
2564
+ const Image = ({
2565
+ id,
2566
+ src,
2567
+ alt,
2568
+ onLoad,
2569
+ onError,
2482
2570
  className,
2483
- multiple
2571
+ loading,
2572
+ stretch = true,
2573
+ role,
2574
+ shrink = true
2484
2575
  }) => {
2485
- const intl = reactIntl.useIntl();
2486
- const isSelected = value => Array.isArray(selected) ? selected.includes(value) : selected === value;
2487
- const handleOnChange = (selectedValue, isCurrentlyEnabled) => {
2488
- onChange({
2489
- isEnabled: !isCurrentlyEnabled,
2490
- selectedValue
2491
- });
2492
- };
2493
- return /*#__PURE__*/jsxRuntime.jsx("div", {
2494
- className: classNames__default.default('np-chips d-flex', className),
2495
- "aria-label": ariaLabel,
2496
- role: !multiple ? 'radiogroup' : undefined,
2497
- children: chips.map(chip => {
2498
- const chipSelected = isSelected(chip.value);
2499
- return /*#__PURE__*/jsxRuntime.jsx(Chip, {
2500
- value: chip.value,
2501
- label: chip.label,
2502
- closeButton: {
2503
- 'aria-label': intl.formatMessage(messages$a.ariaLabel, {
2504
- choice: chip.label
2505
- })
2506
- },
2507
- className: classNames__default.default('text-xs-nowrap', {
2508
- 'np-chip--selected': chipSelected,
2509
- 'p-r-1': multiple && chipSelected
2510
- }),
2511
- ...(multiple && chipSelected ? {
2512
- onRemove: () => handleOnChange(chip.value, chipSelected),
2513
- 'aria-label': chip.label
2514
- } : {
2515
- onClick: () => handleOnChange(chip.value, chipSelected),
2516
- onKeyPress: () => handleOnChange(chip.value, chipSelected),
2517
- role: !multiple ? 'radio' : undefined,
2518
- 'aria-checked': chipSelected
2519
- })
2520
- }, chip.value);
2521
- })
2576
+ const elementReference = React.useRef(null);
2577
+ const [hasIntersected] = useHasIntersected({
2578
+ elRef: elementReference,
2579
+ loading
2580
+ });
2581
+ let imageSource = src;
2582
+ let imageOnLoad = onLoad;
2583
+ if (loading === 'lazy' && !hasIntersected) {
2584
+ imageSource = EmptyTransparentImage;
2585
+ imageOnLoad = undefined;
2586
+ }
2587
+ return /*#__PURE__*/jsxRuntime.jsx("img", {
2588
+ ref: elementReference,
2589
+ id: id,
2590
+ alt: alt,
2591
+ src: imageSource,
2592
+ className: classNames__default.default(['tw-image', {
2593
+ 'tw-image__stretch': stretch,
2594
+ 'tw-image__shrink': shrink
2595
+ }, className]),
2596
+ role: role,
2597
+ onLoad: imageOnLoad,
2598
+ onError: onError
2522
2599
  });
2523
2600
  };
2524
2601
 
2525
- const CircularButton = ({
2602
+ const defaultPromoCardContext = {
2603
+ state: '',
2604
+ isDisabled: false,
2605
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
2606
+ onChange: () => {}
2607
+ };
2608
+ /**
2609
+ * The PromoCard context object.
2610
+ */
2611
+ const PromoCardContext = /*#__PURE__*/React.createContext(defaultPromoCardContext);
2612
+ /**
2613
+ * A custom hook for accessing the PromoCard context object.
2614
+ *
2615
+ * The `usePromoCardContext` hook is used to access the PromoCard context object
2616
+ * from within a child PromoCard component. It throws an error if the context
2617
+ * object is not available, which can help with debugging and development.
2618
+ *
2619
+ * @returns {PromoCardContextType} - The PromoCard context object.
2620
+ */
2621
+ const usePromoCardContext = () => {
2622
+ return React.useContext(PromoCardContext);
2623
+ };
2624
+
2625
+ const PromoCardIndicator = ({
2526
2626
  className,
2527
2627
  children,
2528
- disabled,
2628
+ label,
2529
2629
  icon,
2530
- priority = exports.Priority.PRIMARY,
2531
- type = exports.ControlType.ACCENT,
2630
+ isSmall = false,
2631
+ testid,
2532
2632
  ...rest
2533
2633
  }) => {
2534
- const classes = classNames__default.default('btn np-btn', typeClassMap[type], priorityClassMap[priority]);
2535
- const iconElement = Number(icon.props.size) !== 24 ? /*#__PURE__*/React.cloneElement(icon, {
2536
- size: 24
2537
- }) : icon;
2538
- return /*#__PURE__*/jsxRuntime.jsxs("label", {
2539
- className: classNames__default.default('np-circular-btn', priority, type, disabled && 'disabled', className),
2540
- children: [/*#__PURE__*/jsxRuntime.jsx("input", {
2541
- type: "button",
2542
- "aria-label": children,
2543
- className: classes,
2544
- disabled: disabled,
2545
- ...rest
2546
- }), iconElement, /*#__PURE__*/jsxRuntime.jsx(Body, {
2634
+ const isIconString = icon && typeof icon === 'string';
2635
+ const IconComponent = isIconString && {
2636
+ check: icons.Check,
2637
+ arrow: icons.ArrowRight,
2638
+ download: icons.Download
2639
+ }[icon];
2640
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2641
+ className: classNames__default.default('np-Card-indicator', className),
2642
+ "data-testid": testid,
2643
+ ...rest,
2644
+ children: [label && /*#__PURE__*/jsxRuntime.jsx(Body, {
2547
2645
  as: "span",
2548
- className: "np-circular-btn__label",
2549
- type: exports.Typography.BODY_DEFAULT_BOLD,
2550
- children: children
2551
- })]
2646
+ type: exports.Typography.BODY_LARGE_BOLD,
2647
+ className: "np-Card-indicatorText",
2648
+ children: label
2649
+ }), icon && /*#__PURE__*/jsxRuntime.jsx(Avatar, {
2650
+ type: exports.AvatarType.ICON,
2651
+ size: isSmall ? 40 : 56,
2652
+ backgroundColor: "var(--Card-indicator-icon-background-color)",
2653
+ className: "np-Card-indicatorIcon",
2654
+ children: IconComponent ? /*#__PURE__*/jsxRuntime.jsx(IconComponent, {
2655
+ size: 24,
2656
+ "aria-hidden": "true"
2657
+ }) : icon
2658
+ }), children]
2552
2659
  });
2553
2660
  };
2554
2661
 
2555
- const FocusBoundary = ({
2556
- children
2557
- }) => {
2558
- const wrapperReference = React.useRef(null);
2559
- React.useEffect(() => {
2560
- wrapperReference.current?.focus({
2561
- preventScroll: true
2662
+ const PromoCard = /*#__PURE__*/React.forwardRef(({
2663
+ className,
2664
+ description,
2665
+ defaultChecked,
2666
+ download,
2667
+ href,
2668
+ hrefLang,
2669
+ id,
2670
+ headingLevel = 'h3',
2671
+ imageAlt,
2672
+ imageClass,
2673
+ imageSource,
2674
+ indicatorLabel,
2675
+ indicatorIcon,
2676
+ isChecked,
2677
+ isDisabled,
2678
+ onClick,
2679
+ onKeyDown,
2680
+ rel,
2681
+ tabIndex,
2682
+ target,
2683
+ testId,
2684
+ title,
2685
+ type,
2686
+ value,
2687
+ isSmall,
2688
+ useDisplayFont = true,
2689
+ anchorRef,
2690
+ anchorId,
2691
+ ...props
2692
+ }, ref) => {
2693
+ // Set the `checked` state to the value of `defaultChecked` if it is truthy,
2694
+ // or the value of `isChecked` if it is truthy, or `false` if neither
2695
+ // is truthy.
2696
+ const {
2697
+ state,
2698
+ onChange,
2699
+ isDisabled: contextIsDisabled
2700
+ } = usePromoCardContext();
2701
+ const [checked, setChecked] = React.useState(type === 'checkbox' ? defaultChecked ?? isChecked ?? false : false);
2702
+ const handleClick = () => {
2703
+ if (type === 'radio') {
2704
+ onChange(value || ''); // Update the context state for radio
2705
+ } else if (type === 'checkbox') {
2706
+ setChecked(!checked); // Update local state for checkbox
2707
+ }
2708
+ };
2709
+ const fallbackId = React.useId();
2710
+ const componentId = id || fallbackId;
2711
+ // Set the icon to `'arrow'` if `href` is truthy and `type` is falsy, or
2712
+ // `'download'` if `download` is truthy. If neither condition is true, set
2713
+ // `icon` to `undefined`.
2714
+ // Create a function to get icon type
2715
+ const getIconType = () => {
2716
+ if (indicatorIcon) {
2717
+ return indicatorIcon;
2718
+ }
2719
+ if (download) {
2720
+ return 'download';
2721
+ }
2722
+ if (href && !type) {
2723
+ return 'arrow';
2724
+ }
2725
+ return undefined;
2726
+ };
2727
+ // Define all class names string based on the values of the `href`, `type`,
2728
+ // `checked`, and `className` props.
2729
+ const commonClasses = classNames__default.default({
2730
+ 'np-Card--promoCard': true,
2731
+ 'np-Card--checked': !href && type,
2732
+ 'np-Card--link': href && !type,
2733
+ 'is-checked': type === 'radio' ? value === state : type === 'checkbox' ? checked : undefined
2734
+ }, className);
2735
+ // Object with common props that will be passed to the `Card` components
2736
+ const commonProps = {
2737
+ className: commonClasses,
2738
+ id: componentId,
2739
+ isDisabled: isDisabled || contextIsDisabled,
2740
+ onClick,
2741
+ onKeyDown,
2742
+ ref,
2743
+ 'data-testid': testId,
2744
+ isSmall
2745
+ };
2746
+ // Object with Anchor props that will be passed to the `a` element. These
2747
+ // won't be refurned if set to `isDisabled`
2748
+ const anchorProps = href && !isDisabled ? {
2749
+ download,
2750
+ href: href || undefined,
2751
+ hrefLang,
2752
+ rel,
2753
+ target,
2754
+ ref: anchorRef,
2755
+ id: anchorId
2756
+ } : {};
2757
+ // Object of all Checked props that will be passed to the root `Card` component
2758
+ const checkedProps = (type === 'checkbox' || type === 'radio') && !href ? {
2759
+ ...commonProps,
2760
+ 'aria-checked': type === 'radio' ? value === state : type === 'checkbox' ? checked : undefined,
2761
+ 'aria-describedby': `${componentId}-title`,
2762
+ 'aria-disabled': isDisabled,
2763
+ 'data-value': value ?? undefined,
2764
+ role: type === 'checkbox' || type === 'radio' ? type : undefined,
2765
+ onClick: handleClick,
2766
+ onKeyDown: event => {
2767
+ if (event.key === 'Enter' || event.key === ' ') {
2768
+ handleClick();
2769
+ }
2770
+ },
2771
+ ref,
2772
+ tabIndex: 0
2773
+ } : {};
2774
+ const getTitle = () => {
2775
+ const titleContent = href && !type ? /*#__PURE__*/jsxRuntime.jsx("a", {
2776
+ className: "np-Card-titleLink",
2777
+ ...anchorProps,
2778
+ children: title
2779
+ }) : title;
2780
+ const titleProps = {
2781
+ id: `${componentId}-title`,
2782
+ as: headingLevel,
2783
+ className: 'np-Card-title'
2784
+ };
2785
+ return useDisplayFont ? /*#__PURE__*/jsxRuntime.jsx(Display, {
2786
+ type: exports.Typography.DISPLAY_SMALL,
2787
+ ...titleProps,
2788
+ children: titleContent
2789
+ }) : /*#__PURE__*/jsxRuntime.jsx(Title, {
2790
+ type: exports.Typography.TITLE_SUBSECTION,
2791
+ ...titleProps,
2792
+ children: titleContent
2562
2793
  });
2563
- }, []);
2564
- return /*#__PURE__*/jsxRuntime.jsx(focus.FocusScope, {
2565
- contain: true,
2566
- restoreFocus: true,
2567
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
2568
- ref: wrapperReference,
2569
- tabIndex: -1,
2570
- children: children
2571
- })
2572
- });
2573
- };
2574
-
2575
- function withNextPortalWrapper(Component) {
2576
- return function (props) {
2577
- const [mounted, setMounted] = React.useState(false);
2578
- React.useEffect(() => {
2579
- setMounted(true);
2580
- }, [setMounted]);
2581
- return mounted ? /*#__PURE__*/reactDom.createPortal( /*#__PURE__*/jsxRuntime.jsx(Component, {
2582
- ...props
2583
- }), document.body) : null;
2584
2794
  };
2585
- }
2586
-
2587
- /**
2588
- * Dimmer state management inspired by Material UI's ModalManager (https://github.com/mui-org/material-ui)
2589
- */
2590
- class DimmerManager {
2591
- /**
2592
- * Dimmer refs
2593
- */
2594
- dimmers;
2595
- constructor() {
2596
- this.dimmers = [];
2597
- }
2598
- add(dimmer) {
2599
- let dimmerIndex = this.dimmers.indexOf(dimmer);
2600
- if (dimmerIndex !== -1) {
2601
- return dimmerIndex;
2602
- }
2603
- dimmerIndex = this.dimmers.length;
2604
- this.dimmers.push(dimmer);
2605
- return dimmerIndex;
2606
- }
2607
- remove(dimmer) {
2608
- const dimmerIndex = this.dimmers.indexOf(dimmer);
2609
- if (dimmerIndex !== -1) {
2610
- this.dimmers.splice(dimmerIndex, 1);
2611
- }
2612
- return dimmerIndex;
2613
- }
2614
- isTop(dimmer) {
2615
- return this.dimmers.length > 0 && this.dimmers[this.dimmers.length - 1] === dimmer;
2616
- }
2617
- }
2795
+ React.useEffect(() => {
2796
+ setChecked(defaultChecked ?? isChecked ?? false);
2797
+ }, [defaultChecked, isChecked]);
2798
+ return /*#__PURE__*/jsxRuntime.jsxs(Card$2, {
2799
+ ...commonProps,
2800
+ ...checkedProps,
2801
+ ...props,
2802
+ children: [(value === state || checked) && /*#__PURE__*/jsxRuntime.jsx("span", {
2803
+ className: "np-Card-check",
2804
+ children: /*#__PURE__*/jsxRuntime.jsx(icons.Check, {
2805
+ size: 24,
2806
+ "aria-hidden": "true"
2807
+ })
2808
+ }), getTitle(), /*#__PURE__*/jsxRuntime.jsx(Body, {
2809
+ className: "np-Card-description",
2810
+ children: description
2811
+ }), imageSource && /*#__PURE__*/jsxRuntime.jsx("div", {
2812
+ className: classNames__default.default('np-Card-image', {
2813
+ imageClass
2814
+ }),
2815
+ children: /*#__PURE__*/jsxRuntime.jsx(Image, {
2816
+ src: imageSource,
2817
+ alt: imageAlt || '',
2818
+ loading: "lazy"
2819
+ })
2820
+ }), /*#__PURE__*/jsxRuntime.jsx(PromoCardIndicator, {
2821
+ label: indicatorLabel,
2822
+ icon: getIconType(),
2823
+ isSmall: isSmall
2824
+ })]
2825
+ });
2826
+ });
2827
+ var PromoCard$1 = /*#__PURE__*/React__namespace.default.memo(PromoCard);
2618
2828
 
2619
- const EXIT_ANIMATION$1 = 350;
2620
- const dimmerManager = new DimmerManager();
2621
- const handleTouchMove = event => {
2622
- const isTouchedElementDimmer = event.target.classList.contains('dimmer');
2623
- // disable scroll on iOS devices for Dimmer area
2624
- // this is because of bug in WebKit https://bugs.webkit.org/show_bug.cgi?id=220908
2625
- // note: scrolling still works for children(s) as expected
2626
- if (isIosDevice() && isTouchedElementDimmer) {
2627
- event.stopPropagation();
2628
- event.preventDefault();
2629
- }
2630
- };
2631
- const Dimmer = ({
2632
- children,
2829
+ const LEFT_SCROLL_OFFSET = 8;
2830
+ const Carousel = ({
2831
+ header,
2633
2832
  className,
2634
- disableClickToClose = false,
2635
- contentPosition,
2636
- fadeContentOnEnter = false,
2637
- fadeContentOnExit = false,
2638
- open = false,
2639
- scrollable = false,
2640
- transparent = false,
2641
- onClose
2833
+ cards,
2834
+ onClick
2642
2835
  }) => {
2643
- const [hasNotExited, setHasNotExited] = React.useState(false);
2644
- const dimmerReference = React.useRef(null);
2645
- const closeOnClick = event => {
2646
- if (event.target === dimmerReference.current) {
2647
- onClose?.(event);
2836
+ const [scrollPosition, setScrollPosition] = React.useState(0);
2837
+ const [previousScrollPosition, setPreviousScrollPosition] = React.useState(0);
2838
+ const [scrollIsAtEnd, setScrollIsAtEnd] = React.useState(false);
2839
+ const [visibleCardOnMobileView, setVisibleCardOnMobileView] = React.useState('');
2840
+ const carouselElementRef = React.useRef(null);
2841
+ const carouselCardsRef = React.useRef([]);
2842
+ const isLeftActionButtonEnabled = scrollPosition > LEFT_SCROLL_OFFSET;
2843
+ const areActionButtonsEnabled = isLeftActionButtonEnabled || !scrollIsAtEnd;
2844
+ const [focusedCard, setFocusedCard] = React.useState(cards?.[0]?.id);
2845
+ const updateScrollButtonsState = () => {
2846
+ if (carouselElementRef.current) {
2847
+ const {
2848
+ scrollWidth,
2849
+ offsetWidth
2850
+ } = carouselElementRef.current;
2851
+ const scrollAtEnd = scrollWidth - offsetWidth <= scrollPosition + LEFT_SCROLL_OFFSET;
2852
+ setScrollIsAtEnd(scrollAtEnd);
2648
2853
  }
2649
- };
2650
- const handleClick = event => {
2651
- if (disableClickToClose || !onClose) {
2652
- return;
2854
+ const scrollDirecton = scrollPosition > previousScrollPosition ? 'right' : 'left';
2855
+ const cardsInFullViewIds = [];
2856
+ carouselCardsRef.current.forEach(card => {
2857
+ if (isVisible(carouselElementRef.current, card.cardElement)) {
2858
+ // eslint-disable-next-line functional/immutable-data
2859
+ cardsInFullViewIds.push(card.cardElement.getAttribute('id') ?? '');
2860
+ }
2861
+ });
2862
+ if (cardsInFullViewIds.length >= 1) {
2863
+ const visibleCardIndex = scrollDirecton === 'right' ? cardsInFullViewIds.length - 1 : 0;
2864
+ const visibleCardId = cardsInFullViewIds[visibleCardIndex];
2865
+ setVisibleCardOnMobileView(visibleCardId);
2866
+ setFocusedCard(visibleCardId);
2653
2867
  }
2654
- closeOnClick(event);
2868
+ setPreviousScrollPosition(scrollPosition);
2655
2869
  };
2656
- const handleKeyDown = React.useCallback(event => {
2657
- if (event.key !== 'Escape') {
2658
- return;
2870
+ const scrollCarousel = (direction = 'right') => {
2871
+ if (carouselElementRef.current) {
2872
+ const {
2873
+ scrollWidth
2874
+ } = carouselElementRef.current;
2875
+ const cardWidth = scrollWidth / carouselCardsRef.current.length;
2876
+ const res = Math.floor(cardWidth - cardWidth * 0.05);
2877
+ carouselElementRef.current.scrollBy({
2878
+ left: direction === 'right' ? res : -res,
2879
+ behavior: 'smooth'
2880
+ });
2659
2881
  }
2660
- event.stopPropagation();
2661
- if (onClose && dimmerReference.current && dimmerManager.isTop(dimmerReference.current)) {
2662
- onClose(event);
2882
+ };
2883
+ const handleOnKeyDown = (event, index) => {
2884
+ if (event.key === 'ArrowRight' || event.key === 'ArrowLeft') {
2885
+ const nextIndex = event.key === 'ArrowRight' ? index + 1 : index - 1;
2886
+ const nextCard = cards[nextIndex];
2887
+ if (nextCard) {
2888
+ const ref = carouselCardsRef.current[nextIndex];
2889
+ if (ref.type === 'promo') {
2890
+ ref.anchorElement?.focus();
2891
+ } else {
2892
+ ref.cardElement?.focus();
2893
+ }
2894
+ scrollCardIntoView(carouselCardsRef.current[nextIndex].cardElement, nextCard);
2895
+ event.preventDefault();
2896
+ }
2663
2897
  }
2664
- }, [onClose]);
2665
- const onEnter = () => {
2666
- setHasNotExited(true);
2667
- if (dimmerReference.current) {
2668
- dimmerManager.add(dimmerReference.current);
2898
+ if (event.key === 'Enter' || event.key === ' ') {
2899
+ event.currentTarget.click();
2669
2900
  }
2670
2901
  };
2671
- const onExited = () => {
2672
- setHasNotExited(false);
2673
- if (dimmerReference.current) {
2674
- dimmerManager.remove(dimmerReference.current);
2675
- }
2902
+ const scrollCardIntoView = (element, card) => {
2903
+ element.scrollIntoView({
2904
+ behavior: 'smooth',
2905
+ block: 'nearest',
2906
+ inline: 'center'
2907
+ });
2908
+ setFocusedCard(card.id);
2676
2909
  };
2677
2910
  React.useEffect(() => {
2678
- const localReferenceCopy = dimmerReference.current;
2679
- if (open) {
2680
- document.addEventListener('keydown', handleKeyDown);
2681
- localReferenceCopy?.addEventListener('touchmove', handleTouchMove, {
2682
- passive: true
2683
- });
2911
+ updateScrollButtonsState();
2912
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2913
+ }, [scrollPosition]);
2914
+ React.useEffect(() => {
2915
+ window.addEventListener('resize', updateScrollButtonsState);
2916
+ return () => {
2917
+ window.removeEventListener('resize', updateScrollButtonsState);
2918
+ };
2919
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2920
+ }, []);
2921
+ const addElementToCardsRefArray = (index, ref) => {
2922
+ if (ref) {
2923
+ // eslint-disable-next-line functional/immutable-data
2924
+ carouselCardsRef.current[index] = {
2925
+ type: ref.type ?? carouselCardsRef.current?.[index]?.type,
2926
+ cardElement: ref.cardElement ?? carouselCardsRef.current?.[index]?.cardElement,
2927
+ anchorElement: ref.anchorElement ?? carouselCardsRef.current?.[index]?.anchorElement
2928
+ };
2684
2929
  }
2685
- return () => {
2686
- document.removeEventListener('keydown', handleKeyDown);
2687
- localReferenceCopy?.removeEventListener('touchmove', handleTouchMove);
2688
- };
2689
- }, [handleKeyDown, open]);
2690
- return /*#__PURE__*/jsxRuntime.jsx(DimmerWrapper, {
2691
- open: open,
2692
- hasNotExited: hasNotExited,
2693
- children: /*#__PURE__*/jsxRuntime.jsx(reactTransitionGroup.CSSTransition, {
2694
- nodeRef: dimmerReference,
2695
- in: open,
2696
- appear: true
2697
- // Wait for animation to finish before unmount.
2698
- ,
2699
- timeout: {
2700
- enter: 0,
2701
- exit: EXIT_ANIMATION$1
2702
- },
2703
- classNames: {
2704
- enter: classNames__default.default({
2705
- 'dimmer--enter-fade': fadeContentOnEnter
2706
- }),
2707
- enterDone: classNames__default.default('dimmer--enter-done', {
2708
- 'dimmer--enter-fade': fadeContentOnEnter
2709
- }),
2710
- exit: classNames__default.default('dimmer--exit', {
2711
- 'dimmer--exit-fade': fadeContentOnExit
2712
- })
2930
+ };
2931
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2932
+ className: classNames__default.default('carousel-wrapper', className),
2933
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2934
+ className: "d-flex justify-content-between carousel__header",
2935
+ children: [typeof header === 'string' ? /*#__PURE__*/jsxRuntime.jsx(Title, {
2936
+ as: "span",
2937
+ type: "title-body",
2938
+ children: header
2939
+ }) : header, areActionButtonsEnabled ? /*#__PURE__*/jsxRuntime.jsxs("div", {
2940
+ className: "hidden-xs",
2941
+ children: [/*#__PURE__*/jsxRuntime.jsx(ActionButton, {
2942
+ className: "carousel__scroll-button",
2943
+ tabIndex: -1,
2944
+ priority: "secondary",
2945
+ disabled: !isLeftActionButtonEnabled,
2946
+ "aria-hidden": "true",
2947
+ "data-testid": "scroll-carousel-left",
2948
+ onClick: () => scrollCarousel('left'),
2949
+ children: /*#__PURE__*/jsxRuntime.jsx(icons.ChevronLeft, {})
2950
+ }), /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
2951
+ tabIndex: -1,
2952
+ className: "carousel__scroll-button m-l-1",
2953
+ priority: "secondary",
2954
+ "aria-hidden": "true",
2955
+ "data-testid": "scroll-carousel-right",
2956
+ disabled: scrollIsAtEnd,
2957
+ onClick: () => scrollCarousel(),
2958
+ children: /*#__PURE__*/jsxRuntime.jsx(icons.ChevronRight, {})
2959
+ })]
2960
+ }) : null]
2961
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2962
+ ref: carouselElementRef,
2963
+ tabIndex: -1,
2964
+ role: "list",
2965
+ className: "carousel",
2966
+ onScroll: event => {
2967
+ const target = event.target;
2968
+ setScrollPosition(target.scrollLeft);
2713
2969
  },
2714
- unmountOnExit: true,
2715
- onEnter: onEnter,
2716
- onExited: onExited,
2717
- children: /*#__PURE__*/jsxRuntime.jsx(DimmerContentWrapper, {
2718
- scrollBody: !transparent,
2719
- children: /*#__PURE__*/jsxRuntime.jsx(FocusBoundary, {
2720
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
2721
- ref: dimmerReference,
2722
- className: classNames__default.default('dimmer', {
2723
- 'dimmer--scrollable': scrollable,
2724
- 'dimmer--transparent': transparent
2725
- }, className),
2726
- role: "presentation",
2727
- onClick: handleClick,
2970
+ children: cards?.map((card, index) => {
2971
+ const sharedProps = {
2972
+ id: card.id,
2973
+ className: classNames__default.default('carousel__card', {
2974
+ 'carousel__card--focused': card.id === focusedCard
2975
+ }),
2976
+ onClick: () => {
2977
+ card.onClick?.();
2978
+ onClick?.(card.id);
2979
+ },
2980
+ onFocus: event => {
2981
+ scrollCardIntoView(event.currentTarget, card);
2982
+ }
2983
+ };
2984
+ const cardContent = card.type !== 'promo' ? /*#__PURE__*/jsxRuntime.jsx("div", {
2985
+ id: `${card.id}-content`,
2986
+ className: classNames__default.default('carousel__card-content', {
2987
+ [card.className ?? '']: !!card.className
2988
+ })
2989
+ // eslint-disable-next-line react/forbid-dom-props
2990
+ ,
2991
+ style: card.styles,
2992
+ children: card.content
2993
+ }) : null;
2994
+ if (card.type === 'button') {
2995
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
2996
+ "aria-labelledby": `${card.id}-content`,
2997
+ role: "listitem",
2728
2998
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
2729
- className: classNames__default.default('dimmer-content-positioner', contentPosition != null && ['d-flex justify-content-center', {
2730
- 'align-items-start': contentPosition === 'top',
2731
- 'align-items-center': contentPosition === 'center',
2732
- 'align-items-end': contentPosition === 'bottom'
2733
- }]),
2734
- children: children
2999
+ ...sharedProps,
3000
+ ref: el => {
3001
+ if (el) {
3002
+ // eslint-disable-next-line functional/immutable-data
3003
+ carouselCardsRef.current[index] = {
3004
+ type: 'default',
3005
+ cardElement: el
3006
+ };
3007
+ }
3008
+ },
3009
+ role: "button",
3010
+ tabIndex: 0,
3011
+ onKeyDown: event => handleOnKeyDown(event, index),
3012
+ children: cardContent
3013
+ })
3014
+ }, card.id);
3015
+ }
3016
+ if (card.type === 'promo') {
3017
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
3018
+ id: card.id,
3019
+ role: "listitem",
3020
+ "aria-labelledby": `${card.id}-anchor`,
3021
+ children: /*#__PURE__*/jsxRuntime.jsx(PromoCard$1, {
3022
+ ...card,
3023
+ type: undefined,
3024
+ ...sharedProps,
3025
+ ref: el => {
3026
+ if (el) {
3027
+ addElementToCardsRefArray(index, {
3028
+ type: 'promo',
3029
+ cardElement: el
3030
+ });
3031
+ }
3032
+ },
3033
+ anchorRef: el => {
3034
+ if (el) {
3035
+ addElementToCardsRefArray(index, {
3036
+ type: 'promo',
3037
+ anchorElement: el
3038
+ });
3039
+ }
3040
+ },
3041
+ anchorId: `${card.id}-anchor`,
3042
+ onKeyDown: event => handleOnKeyDown(event, index)
2735
3043
  })
3044
+ }, card.id);
3045
+ }
3046
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
3047
+ "aria-labelledby": `${card.id}-content`,
3048
+ role: "listitem",
3049
+ children: /*#__PURE__*/jsxRuntime.jsx("a", {
3050
+ ...sharedProps,
3051
+ ref: el => {
3052
+ if (el) {
3053
+ // eslint-disable-next-line functional/immutable-data
3054
+ carouselCardsRef.current[index] = {
3055
+ type: 'default',
3056
+ cardElement: el
3057
+ };
3058
+ }
3059
+ },
3060
+ href: card.href,
3061
+ rel: "noreferrer",
3062
+ onKeyDown: event => handleOnKeyDown(event, index),
3063
+ children: cardContent
2736
3064
  })
2737
- })
3065
+ }, card.id);
2738
3066
  })
2739
- })
3067
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
3068
+ className: "visible-xs",
3069
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
3070
+ className: "carousel__indicators",
3071
+ children: cards?.map((card, index) => /*#__PURE__*/jsxRuntime.jsx("button", {
3072
+ "data-testid": `${card.id}-indicator`,
3073
+ tabIndex: -1,
3074
+ "aria-hidden": true,
3075
+ type: "button",
3076
+ className: classNames__default.default('carousel__indicator', {
3077
+ 'carousel__indicator--selected': card.id === visibleCardOnMobileView
3078
+ }),
3079
+ onClick: () => {
3080
+ scrollCardIntoView(carouselCardsRef.current[index].cardElement, card);
3081
+ }
3082
+ }, `${card.id}-indicator`))
3083
+ })
3084
+ })]
3085
+ });
3086
+ };
3087
+ const isVisible = (container, el) => {
3088
+ const cWidth = container.offsetWidth;
3089
+ const cScrollOffset = container.scrollLeft;
3090
+ const elemLeft = el.offsetLeft - container.offsetLeft;
3091
+ const elemRight = elemLeft + el.offsetWidth;
3092
+ return elemLeft >= cScrollOffset && elemRight <= cScrollOffset + cWidth;
3093
+ };
3094
+
3095
+ const Card = /*#__PURE__*/React.forwardRef((props, reference) => {
3096
+ const {
3097
+ 'aria-label': ariaLabel,
3098
+ as: Element,
3099
+ isExpanded,
3100
+ title,
3101
+ details,
3102
+ children,
3103
+ onClick,
3104
+ icon,
3105
+ id,
3106
+ className,
3107
+ ...rest
3108
+ } = props;
3109
+ const isOpen = !!(isExpanded && children);
3110
+ return /*#__PURE__*/jsxRuntime.jsxs(Element, {
3111
+ ref: reference,
3112
+ className: classNames__default.default('np-card', className, {
3113
+ 'np-card--expanded': isOpen,
3114
+ 'np-card--inactive': !children,
3115
+ 'np-card--has-icon': !!icon
3116
+ }),
3117
+ id: id,
3118
+ "data-testid": rest['data-testid'],
3119
+ children: [/*#__PURE__*/jsxRuntime.jsx(Option$2, {
3120
+ "aria-label": ariaLabel,
3121
+ as: children ? 'button' : 'div',
3122
+ className: classNames__default.default('np-card__button'),
3123
+ media: icon,
3124
+ title: title,
3125
+ content: details,
3126
+ showMediaAtAllSizes: true,
3127
+ button: children && /*#__PURE__*/jsxRuntime.jsx(Chevron, {
3128
+ orientation: isOpen ? exports.Position.TOP : exports.Position.BOTTOM
3129
+ }),
3130
+ onClick: () => children && onClick(!isExpanded)
3131
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
3132
+ className: classNames__default.default('np-card__divider', {
3133
+ 'np-card__divider--expanded': isOpen
3134
+ })
3135
+ }), isOpen && /*#__PURE__*/jsxRuntime.jsx(Body, {
3136
+ as: "span",
3137
+ type: exports.Typography.BODY_LARGE,
3138
+ className: "np-card__content d-block",
3139
+ children: children
3140
+ })]
2740
3141
  });
2741
- };
2742
- const DimmerWrapper = ({
2743
- open,
2744
- hasNotExited,
3142
+ });
3143
+ const hasChildren = ({
2745
3144
  children
3145
+ }) => children;
3146
+ Card.propTypes = {
3147
+ 'aria-label': PropTypes__default.default.string,
3148
+ as: PropTypes__default.default.string,
3149
+ isExpanded: requiredIf__default.default(PropTypes__default.default.bool, hasChildren),
3150
+ title: PropTypes__default.default.node.isRequired,
3151
+ details: PropTypes__default.default.node.isRequired,
3152
+ onClick: requiredIf__default.default(PropTypes__default.default.func, hasChildren),
3153
+ icon: PropTypes__default.default.node,
3154
+ children: PropTypes__default.default.node,
3155
+ id: PropTypes__default.default.string,
3156
+ className: PropTypes__default.default.string,
3157
+ 'data-testid': PropTypes__default.default.string
3158
+ };
3159
+ Card.defaultProps = {
3160
+ 'aria-label': undefined,
3161
+ as: 'div',
3162
+ children: null,
3163
+ id: null,
3164
+ className: null,
3165
+ 'data-testid': null
3166
+ };
3167
+ var Card$1 = Card;
3168
+
3169
+ const CheckboxButton = /*#__PURE__*/React.forwardRef(({
3170
+ checked,
3171
+ className,
3172
+ disabled,
3173
+ onChange,
3174
+ ...rest
3175
+ }, reference) => /*#__PURE__*/jsxRuntime.jsxs("span", {
3176
+ className: classNames__default.default('np-checkbox-button', className, disabled && 'disabled'),
3177
+ children: [/*#__PURE__*/jsxRuntime.jsx("input", {
3178
+ ...rest,
3179
+ ref: reference,
3180
+ type: "checkbox",
3181
+ disabled: disabled,
3182
+ checked: checked,
3183
+ onChange: onChange
3184
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
3185
+ className: "tw-checkbox-button",
3186
+ children: /*#__PURE__*/jsxRuntime.jsx("span", {
3187
+ className: "tw-checkbox-check"
3188
+ })
3189
+ })]
3190
+ }));
3191
+ var CheckboxButton$1 = CheckboxButton;
3192
+
3193
+ const Checkbox = ({
3194
+ id,
3195
+ checked,
3196
+ required,
3197
+ disabled,
3198
+ readOnly,
3199
+ label,
3200
+ className,
3201
+ secondary,
3202
+ onChange,
3203
+ onFocus,
3204
+ onBlur
2746
3205
  }) => {
2747
3206
  const {
2748
- screenMode,
2749
- theme
3207
+ isModern
2750
3208
  } = componentsTheming.useTheme();
2751
- return open || hasNotExited ? /*#__PURE__*/jsxRuntime.jsx(componentsTheming.ThemeProvider, {
2752
- theme: "personal",
2753
- screenMode: theme === 'personal' ? screenMode : 'light',
2754
- isNotRootProvider: true,
2755
- children: children
2756
- }) : /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
2757
- children: children
3209
+ const classList = classNames__default.default('np-checkbox', {
3210
+ checkbox: true,
3211
+ 'checkbox-lg': secondary,
3212
+ disabled: isModern && disabled
3213
+ }, className);
3214
+ const innerDisabled = disabled || readOnly;
3215
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
3216
+ id: id,
3217
+ className: classList,
3218
+ children: /*#__PURE__*/jsxRuntime.jsxs("label", {
3219
+ className: classNames__default.default({
3220
+ disabled
3221
+ }),
3222
+ children: [/*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
3223
+ className: "p-r-2",
3224
+ checked: checked,
3225
+ disabled: innerDisabled,
3226
+ required: !innerDisabled && required,
3227
+ onFocus: onFocus,
3228
+ onChange: () => onChange(!checked),
3229
+ onBlur: onBlur
3230
+ }), /*#__PURE__*/jsxRuntime.jsxs(Body, {
3231
+ as: "span",
3232
+ className: "np-checkbox__text",
3233
+ type: secondary ? exports.Typography.BODY_LARGE_BOLD : exports.Typography.BODY_LARGE,
3234
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
3235
+ className: required ? 'has-required' : undefined,
3236
+ children: label
3237
+ }), secondary && /*#__PURE__*/jsxRuntime.jsx(Body, {
3238
+ as: "span",
3239
+ className: classNames__default.default({
3240
+ secondary: !isModern
3241
+ }),
3242
+ children: secondary
3243
+ })]
3244
+ })]
3245
+ })
2758
3246
  });
2759
3247
  };
2760
- const DimmerContentWrapper = ({
2761
- children,
2762
- scrollBody
2763
- }) => {
2764
- React.useEffect(() => {
2765
- if (scrollBody) {
2766
- addNoScrollClass();
2767
- }
2768
- return () => {
2769
- if (scrollBody) {
2770
- removeNoScrollClass();
2771
- }
2772
- };
2773
- }, [scrollBody]);
2774
- return children;
3248
+ Checkbox.propTypes = {
3249
+ id: PropTypes__default.default.string,
3250
+ checked: PropTypes__default.default.bool,
3251
+ required: PropTypes__default.default.bool,
3252
+ disabled: PropTypes__default.default.bool,
3253
+ readOnly: PropTypes__default.default.bool,
3254
+ label: PropTypes__default.default.node.isRequired,
3255
+ secondary: PropTypes__default.default.string,
3256
+ onFocus: PropTypes__default.default.func,
3257
+ onChange: PropTypes__default.default.func.isRequired,
3258
+ onBlur: PropTypes__default.default.func,
3259
+ className: PropTypes__default.default.string
3260
+ };
3261
+ Checkbox.defaultProps = {
3262
+ id: null,
3263
+ checked: false,
3264
+ required: false,
3265
+ disabled: false,
3266
+ readOnly: false,
3267
+ secondary: null,
3268
+ onFocus: null,
3269
+ onBlur: null,
3270
+ className: undefined
2775
3271
  };
2776
- var Dimmer$1 = withNextPortalWrapper(Dimmer);
2777
3272
 
2778
- const EXIT_ANIMATION = 350;
2779
- const SlidingPanel = /*#__PURE__*/React.forwardRef(({
2780
- position = 'left',
2781
- open,
2782
- showSlidingPanelBorder,
2783
- slidingPanelPositionFixed,
2784
- className,
2785
- children,
3273
+ const CheckboxOption = /*#__PURE__*/React.forwardRef(({
3274
+ checked,
3275
+ disabled,
3276
+ onChange,
2786
3277
  ...rest
2787
3278
  }, reference) => {
2788
- const localReference = React.useRef(null);
2789
- React.useImperativeHandle(reference, () => localReference.current, []);
2790
- return /*#__PURE__*/React.createElement(reactTransitionGroup.CSSTransition, {
3279
+ return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
2791
3280
  ...rest,
2792
- key: `sliding-panel--open-${position}`,
2793
- nodeRef: localReference,
2794
- in: open
2795
- // Wait for animation to finish before unmount.
2796
- ,
2797
- timeout: {
2798
- enter: 0,
2799
- exit: EXIT_ANIMATION
2800
- },
2801
- classNames: "sliding-panel",
2802
- appear: true,
2803
- unmountOnExit: true
2804
- }, /*#__PURE__*/jsxRuntime.jsx("div", {
2805
- ref: localReference,
2806
- className: classNames__default.default('sliding-panel', `sliding-panel--open-${position}`, showSlidingPanelBorder && `sliding-panel--border-${position}`, slidingPanelPositionFixed && 'sliding-panel--fixed', className),
2807
- children: children
2808
- }));
3281
+ ref: reference,
3282
+ disabled: disabled,
3283
+ button: /*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
3284
+ checked: checked,
3285
+ disabled: disabled,
3286
+ onChange: () => onChange?.(!checked)
3287
+ })
3288
+ });
3289
+ });
3290
+
3291
+ const Chip = ({
3292
+ label,
3293
+ value,
3294
+ onRemove,
3295
+ onClick,
3296
+ onKeyPress,
3297
+ className = undefined,
3298
+ 'aria-label': ariaLabel,
3299
+ 'aria-checked': ariaChecked,
3300
+ role,
3301
+ closeButton
3302
+ }) => {
3303
+ const isActionable = onClick || onKeyPress;
3304
+ const defaultRole = isActionable ? 'button' : undefined;
3305
+ const tabIndex = isActionable ? 0 : -1;
3306
+ const {
3307
+ isModern
3308
+ } = componentsTheming.useTheme();
3309
+ const closeButtonReference = React.useRef(null);
3310
+ const previousCloseButtonShown = React.useRef(undefined);
3311
+ React.useEffect(() => {
3312
+ if (closeButtonReference.current != null && previousCloseButtonShown.current === false) {
3313
+ closeButtonReference.current?.focus();
3314
+ }
3315
+ previousCloseButtonShown.current = closeButtonReference.current != null;
3316
+ }, [onRemove]);
3317
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
3318
+ role: role ?? defaultRole,
3319
+ tabIndex: tabIndex,
3320
+ "aria-label": ariaLabel,
3321
+ "aria-checked": ariaChecked,
3322
+ className: classNames__default.default('np-chip', 'd-flex', 'align-items-center', 'justify-content-between', onRemove ? 'np-chip--removable' : '', className),
3323
+ ...(isActionable && {
3324
+ onClick,
3325
+ onKeyPress
3326
+ }),
3327
+ children: [isModern ? /*#__PURE__*/jsxRuntime.jsx(Body, {
3328
+ "aria-hidden": !!onRemove,
3329
+ type: exports.Typography.BODY_DEFAULT_BOLD,
3330
+ children: label
3331
+ }) : /*#__PURE__*/jsxRuntime.jsx("span", {
3332
+ "aria-hidden": "false",
3333
+ className: "np-chip-label",
3334
+ children: label
3335
+ }), onRemove ? /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
3336
+ ref: closeButtonReference,
3337
+ className: isModern ? `btn-unstyled` : `btn-unstyled m-l-1`,
3338
+ "aria-label": closeButton?.['aria-label'],
3339
+ size: "sm",
3340
+ filled: isModern,
3341
+ onClick: onRemove
3342
+ }) : null]
3343
+ }, value);
3344
+ };
3345
+
3346
+ var messages$a = reactIntl.defineMessages({
3347
+ ariaLabel: {
3348
+ id: "neptune.Chips.ariaLabel"
3349
+ }
2809
3350
  });
2810
3351
 
2811
- const Drawer = ({
2812
- children,
3352
+ const Chips = ({
3353
+ chips,
3354
+ onChange,
3355
+ selected,
3356
+ 'aria-label': ariaLabel,
2813
3357
  className,
2814
- footerContent,
2815
- headerTitle,
2816
- onClose,
2817
- open,
2818
- position
3358
+ multiple
2819
3359
  }) => {
2820
- logActionRequiredIf('Drawer now expects `onClose`, and will soon make this prop required. Please update your usage to provide it.', !onClose);
2821
- const {
2822
- isMobile
2823
- } = useLayout();
2824
- const titleId = React.useId();
2825
- return /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
2826
- open: open,
2827
- onClose: onClose,
2828
- children: /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
2829
- open: open,
2830
- position: isMobile ? exports.Position.BOTTOM : position,
2831
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
2832
- role: "dialog",
2833
- "aria-modal": true,
2834
- "aria-labelledby": headerTitle ? titleId : undefined,
2835
- className: classNames__default.default('np-drawer', className),
2836
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2837
- className: classNames__default.default('np-drawer-header', {
2838
- 'np-drawer-header--withborder': headerTitle
2839
- }),
2840
- children: [headerTitle && /*#__PURE__*/jsxRuntime.jsx(Title, {
2841
- id: titleId,
2842
- type: exports.Typography.TITLE_BODY,
2843
- children: headerTitle
2844
- }), /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2845
- onClick: onClose
2846
- })]
2847
- }), children && /*#__PURE__*/jsxRuntime.jsx("div", {
2848
- className: classNames__default.default('np-drawer-content'),
2849
- children: children
2850
- }), footerContent && /*#__PURE__*/jsxRuntime.jsx("div", {
2851
- className: classNames__default.default('np-drawer-footer'),
2852
- children: footerContent
2853
- })]
2854
- })
2855
- })
2856
- });
2857
- };
2858
- Drawer.propTypes = {
2859
- /** The content to appear in the drawer body. */
2860
- children: PropTypes__default.default.node,
2861
- className: PropTypes__default.default.string,
2862
- /** The content to appear in the drawer footer. */
2863
- footerContent: PropTypes__default.default.node,
2864
- /** The content to appear in the drawer header. */
2865
- headerTitle: PropTypes__default.default.node,
2866
- /** The status of Drawer either open or not. */
2867
- open: PropTypes__default.default.bool,
2868
- /** The placement of Drawer on the screen either left or right. On mobile it will default to bottom. */
2869
- position: PropTypes__default.default.oneOf(['left', 'right', 'bottom']),
2870
- /** The action to perform on close click. */
2871
- onClose: PropTypes__default.default.func
2872
- };
2873
- Drawer.defaultProps = {
2874
- children: null,
2875
- className: undefined,
2876
- footerContent: null,
2877
- headerTitle: null,
2878
- onClose: null,
2879
- open: false,
2880
- position: exports.Position.RIGHT
2881
- };
2882
- var Drawer$1 = Drawer;
2883
-
2884
- const INITIAL_Y_POSITION = 0;
2885
- const CONTENT_SCROLL_THRESHOLD = 1;
2886
- const MOVE_OFFSET_THRESHOLD = 50;
2887
- /**
2888
- * Neptune: https://transferwise.github.io/neptune/components/bottom-sheet/
2889
- *
2890
- * Neptune Web: https://transferwise.github.io/neptune-web/components/overlays/BottomSheet
2891
- *
2892
- */
2893
- const BottomSheet$1 = props => {
2894
- const bottomSheetReference = React.useRef(null);
2895
- const topBarReference = React.useRef(null);
2896
- const contentReference = React.useRef(null);
2897
- const [pressed, setPressed] = React.useState(false);
2898
- /**
2899
- * Used to track `requestAnimationFrame` requests
2900
- *
2901
- * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame#return_value
2902
- */
2903
- const animationId = React.useRef(0);
2904
- /**
2905
- * Difference between initial coordinate ({@link initialYCoordinate})
2906
- * and new position (when user moves component), it's get calculated on `onTouchMove` and `onMouseMove` events
2907
- *
2908
- * @see {@link calculateOffsetAfterMove}
2909
- */
2910
- const moveOffset = React.useRef(0);
2911
- const initialYCoordinate = React.useRef(0);
2912
- // apply shadow to the bottom of top-bar when scroll over content
2913
- useConditionalListener({
2914
- attachListener: props.open && !isServerSide(),
2915
- callback: () => {
2916
- if (topBarReference.current !== null) {
2917
- const {
2918
- classList
2919
- } = topBarReference.current;
2920
- if (!isContentScrollPositionAtTop()) {
2921
- classList.add('np-bottom-sheet--top-bar--shadow');
2922
- } else {
2923
- classList.remove('np-bottom-sheet--top-bar--shadow');
2924
- }
2925
- }
2926
- },
2927
- eventType: 'scroll',
2928
- parent: isServerSide() ? undefined : document
2929
- });
2930
- function move(newHeight) {
2931
- if (bottomSheetReference.current !== null) {
2932
- bottomSheetReference.current.style.transform = `translateY(${newHeight}px)`;
2933
- }
2934
- }
2935
- function close(event) {
2936
- setPressed(false);
2937
- moveOffset.current = INITIAL_Y_POSITION;
2938
- if (bottomSheetReference.current !== null) {
2939
- bottomSheetReference.current.style.removeProperty('transform');
2940
- }
2941
- if (props.onClose) {
2942
- props.onClose(event);
2943
- }
2944
- }
2945
- const onSwipeStart = event => {
2946
- initialYCoordinate.current = ('touches' in event ? event.touches[0] : event).clientY;
2947
- setPressed(true);
2948
- };
2949
- const onSwipeMove = event => {
2950
- if (pressed) {
2951
- const {
2952
- clientY
2953
- } = 'touches' in event ? event.touches[0] : event;
2954
- const offset = calculateOffsetAfterMove(clientY);
2955
- // check whether move is to the bottom only and content scroll position is at the top
2956
- if (offset > INITIAL_Y_POSITION && isContentScrollPositionAtTop()) {
2957
- moveOffset.current = offset;
2958
- animationId.current = requestAnimationFrame(() => {
2959
- if (animationId.current !== undefined && bottomSheetReference.current !== null) {
2960
- move(offset);
2961
- }
2962
- });
2963
- }
2964
- }
3360
+ const intl = reactIntl.useIntl();
3361
+ const isSelected = value => Array.isArray(selected) ? selected.includes(value) : selected === value;
3362
+ const handleOnChange = (selectedValue, isCurrentlyEnabled) => {
3363
+ onChange({
3364
+ isEnabled: !isCurrentlyEnabled,
3365
+ selectedValue
3366
+ });
2965
3367
  };
2966
- function onSwipeEnd(event) {
2967
- // stop moving component
2968
- cancelAnimationFrame(animationId.current);
2969
- setPressed(false);
2970
- // check whether move down is strong enough
2971
- // and content scroll position is at the top to close the component
2972
- if (moveOffset.current > MOVE_OFFSET_THRESHOLD && isContentScrollPositionAtTop()) {
2973
- close(event);
2974
- }
2975
- // otherwise move component back to default (initial) position
2976
- else {
2977
- move(INITIAL_Y_POSITION);
2978
- }
2979
- moveOffset.current = INITIAL_Y_POSITION;
2980
- }
2981
- function isContentScrollPositionAtTop() {
2982
- return contentReference?.current?.scrollTop !== undefined && contentReference.current.scrollTop <= CONTENT_SCROLL_THRESHOLD;
2983
- }
2984
- /**
2985
- * Calculates how hard user moves component,
2986
- * result value used to determine whether to hide component or re-position to default state
2987
- *
2988
- * @param afterMoveYCoordinate
2989
- */
2990
- function calculateOffsetAfterMove(afterMoveYCoordinate) {
2991
- return afterMoveYCoordinate - initialYCoordinate.current;
2992
- }
2993
- /**
2994
- * Set `max-height` for content part (in order to keep it scrollable for content overflow cases) of the component
2995
- * and ensures space for safe zone (32px) at the top.
2996
- */
2997
- function setContentMaxHeight() {
2998
- const safeZoneHeight = '64px';
2999
- const topbarHeight = '32px';
3000
- const windowHight = isServerSide() ? 0 : window.innerHeight;
3001
- /**
3002
- * Calculate _real_ height of the screen (taking into account parts of browser interface).
3003
- *
3004
- * See https://css-tricks.com/the-trick-to-viewport-units-on-mobile for more details.
3005
- */
3006
- const screenHeight = `${windowHight * 0.01 * 100}px`;
3007
- return {
3008
- maxHeight: `calc(${screenHeight} - ${safeZoneHeight} - ${topbarHeight})`
3009
- };
3010
- }
3011
- const is400Zoom = useMedia(`(max-width: ${exports.Breakpoint.ZOOM_400}px)`);
3012
- return is400Zoom ? /*#__PURE__*/jsxRuntime.jsx(Drawer$1, {
3013
- open: props.open,
3014
- className: props.className,
3015
- onClose: close,
3016
- children: props.children
3017
- }) : /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
3018
- open: props.open,
3019
- fadeContentOnEnter: true,
3020
- fadeContentOnExit: true,
3021
- onClose: close,
3022
- children: /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
3023
- ref: bottomSheetReference,
3024
- open: props.open,
3025
- position: exports.Position.BOTTOM,
3026
- className: classNames__default.default('np-bottom-sheet', props.className),
3027
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
3028
- role: "dialog",
3029
- "aria-modal": true,
3030
- onTouchStart: onSwipeStart,
3031
- onTouchMove: onSwipeMove,
3032
- onTouchEnd: onSwipeEnd,
3033
- onMouseDown: onSwipeStart,
3034
- onMouseMove: onSwipeMove,
3035
- onMouseUp: onSwipeEnd,
3036
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
3037
- ref: topBarReference,
3038
- className: "np-bottom-sheet--top-bar",
3039
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
3040
- className: "np-bottom-sheet--handler"
3041
- }), /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
3042
- size: "sm",
3043
- className: "sr-only np-bottom-sheet--close-btn",
3044
- onClick: close
3045
- })]
3046
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
3047
- ref: contentReference,
3048
- style: setContentMaxHeight(),
3049
- className: "np-bottom-sheet--content",
3050
- children: props.children
3051
- })]
3052
- })
3368
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
3369
+ className: classNames__default.default('np-chips d-flex', className),
3370
+ "aria-label": ariaLabel,
3371
+ role: !multiple ? 'radiogroup' : undefined,
3372
+ children: chips.map(chip => {
3373
+ const chipSelected = isSelected(chip.value);
3374
+ return /*#__PURE__*/jsxRuntime.jsx(Chip, {
3375
+ value: chip.value,
3376
+ label: chip.label,
3377
+ closeButton: {
3378
+ 'aria-label': intl.formatMessage(messages$a.ariaLabel, {
3379
+ choice: chip.label
3380
+ })
3381
+ },
3382
+ className: classNames__default.default('text-xs-nowrap', {
3383
+ 'np-chip--selected': chipSelected,
3384
+ 'p-r-1': multiple && chipSelected
3385
+ }),
3386
+ ...(multiple && chipSelected ? {
3387
+ onRemove: () => handleOnChange(chip.value, chipSelected),
3388
+ 'aria-label': chip.label
3389
+ } : {
3390
+ onClick: () => handleOnChange(chip.value, chipSelected),
3391
+ onKeyPress: () => handleOnChange(chip.value, chipSelected),
3392
+ role: !multiple ? 'radio' : undefined,
3393
+ 'aria-checked': chipSelected
3394
+ })
3395
+ }, chip.value);
3053
3396
  })
3054
3397
  });
3055
3398
  };
3056
3399
 
3400
+ const CircularButton = ({
3401
+ className,
3402
+ children,
3403
+ disabled,
3404
+ icon,
3405
+ priority = exports.Priority.PRIMARY,
3406
+ type = exports.ControlType.ACCENT,
3407
+ ...rest
3408
+ }) => {
3409
+ const classes = classNames__default.default('btn np-btn', typeClassMap[type], priorityClassMap[priority]);
3410
+ const iconElement = Number(icon.props.size) !== 24 ? /*#__PURE__*/React.cloneElement(icon, {
3411
+ size: 24
3412
+ }) : icon;
3413
+ return /*#__PURE__*/jsxRuntime.jsxs("label", {
3414
+ className: classNames__default.default('np-circular-btn', priority, type, disabled && 'disabled', className),
3415
+ children: [/*#__PURE__*/jsxRuntime.jsx("input", {
3416
+ type: "button",
3417
+ "aria-label": children,
3418
+ className: classes,
3419
+ disabled: disabled,
3420
+ ...rest
3421
+ }), iconElement, /*#__PURE__*/jsxRuntime.jsx(Body, {
3422
+ as: "span",
3423
+ className: "np-circular-btn__label",
3424
+ type: exports.Typography.BODY_DEFAULT_BOLD,
3425
+ children: children
3426
+ })]
3427
+ });
3428
+ };
3429
+
3057
3430
  function CriticalCommsBanner({
3058
3431
  title,
3059
3432
  subtitle,
@@ -3167,36 +3540,6 @@ const isMonthAndYearFormat = dateString => validDateString(dateString) && dateSt
3167
3540
  const MDY = new Set(['en-US']);
3168
3541
  const YMD = new Set(['hu', 'hu-HU', 'zh-HK', 'zh-CN', 'ja', 'ja-JP']);
3169
3542
 
3170
- const FieldLabelIdContext = /*#__PURE__*/React.createContext(undefined);
3171
- const FieldLabelIdContextProvider = FieldLabelIdContext.Provider;
3172
- const InputIdContext = /*#__PURE__*/React.createContext(undefined);
3173
- const InputIdContextProvider = InputIdContext.Provider;
3174
- const InputDescribedByContext = /*#__PURE__*/React.createContext(undefined);
3175
- const InputDescribedByProvider = InputDescribedByContext.Provider;
3176
- const InputInvalidContext = /*#__PURE__*/React.createContext(undefined);
3177
- const InputInvalidProvider = InputInvalidContext.Provider;
3178
- function useInputAttributes({
3179
- nonLabelable
3180
- } = {}) {
3181
- const labelId = React.useContext(FieldLabelIdContext);
3182
- return {
3183
- id: React.useContext(InputIdContext),
3184
- 'aria-labelledby': nonLabelable ? labelId : undefined,
3185
- 'aria-describedby': React.useContext(InputDescribedByContext),
3186
- 'aria-invalid': React.useContext(InputInvalidContext)
3187
- };
3188
- }
3189
- function withInputAttributes(Component, args) {
3190
- function ComponentWithInputAttributes(props) {
3191
- return /*#__PURE__*/jsxRuntime.jsx(Component, {
3192
- inputAttributes: useInputAttributes(args),
3193
- ...props
3194
- });
3195
- }
3196
- ComponentWithInputAttributes.displayName = `withInputAttributes(${Component.displayName || Component.name || 'Component'})`;
3197
- return ComponentWithInputAttributes;
3198
- }
3199
-
3200
3543
  var messages$9 = reactIntl.defineMessages({
3201
3544
  monthLabel: {
3202
3545
  id: "neptune.DateInput.month.label"
@@ -3442,214 +3785,96 @@ const DateInput = ({
3442
3785
  onChange: event => handleDayChange(event)
3443
3786
  })
3444
3787
  })]
3445
- })
3446
- });
3447
- };
3448
- const getYear = () => {
3449
- return /*#__PURE__*/jsxRuntime.jsx("div", {
3450
- className: "col-sm-4",
3451
- children: /*#__PURE__*/jsxRuntime.jsxs("label", {
3452
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
3453
- className: "sr-only",
3454
- children: yearLabel
3455
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
3456
- className: `input-group input-group-${size}`,
3457
- children: /*#__PURE__*/jsxRuntime.jsx(Input, {
3458
- type: "text",
3459
- inputMode: "numeric",
3460
- pattern: "[0-9]*",
3461
- name: "year",
3462
- autoComplete: yearAutoComplete,
3463
- placeholder: placeholders?.year,
3464
- value: year || '',
3465
- disabled: disabled,
3466
- min: 1,
3467
- onChange: event => handleYearChange(event)
3468
- })
3469
- })]
3470
- })
3471
- });
3472
- };
3473
- const monthBeforeDay = MDY.has(locale);
3474
- const yearFirst = YMD.has(locale);
3475
- return /*#__PURE__*/jsxRuntime.jsx("div", {
3476
- className: "tw-date",
3477
- ...inputAttributes,
3478
- id: id,
3479
- "aria-labelledby": ariaLabelledBy,
3480
- "aria-label": ariaLabel,
3481
- role: "group" // Add role attribute to indicate container for interactive elements
3482
- ,
3483
- onFocus: event => shouldPropagateOnFocus(event) ? onFocus && onFocus(event) : event.stopPropagation(),
3484
- onBlur: event => shouldPropagateOnBlur(event) ? onBlur && onBlur(event) : event.stopPropagation(),
3485
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
3486
- className: "row",
3487
- children: (() => {
3488
- if (monthYearOnly) {
3489
- return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3490
- children: [!yearFirst && getMonth(), getYear(), yearFirst && getMonth()]
3491
- });
3492
- }
3493
- if (monthBeforeDay) {
3494
- return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3495
- children: [getMonth(), getDay(), getYear()]
3496
- });
3497
- }
3498
- if (yearFirst) {
3499
- return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3500
- children: [getYear(), getMonth(), getDay()]
3501
- });
3502
- }
3503
- return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3504
- children: [getDay(), getMonth(), getYear()]
3505
- });
3506
- })()
3507
- })
3508
- });
3509
- };
3510
- // Should only propagate if the relatedTarget is not part of this DateInput component.
3511
- function shouldPropagateOnFocus({
3512
- target,
3513
- relatedTarget
3514
- }) {
3515
- const targetParent = target.closest('.tw-date');
3516
- const relatedParent = relatedTarget && relatedTarget.closest('.tw-date');
3517
- return targetParent !== relatedParent;
3518
- }
3519
- // Should only propagate if the relatedTarget or the activeElement is not part of this DateInput component.
3520
- function shouldPropagateOnBlur({
3521
- target,
3522
- relatedTarget
3523
- }) {
3524
- const blurElementParent = target.closest('.tw-date');
3525
- // Even though FocusEvent.relatedTarget is supported by IE
3526
- // (https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/relatedTarget)
3527
- // "IE11 sets document.activeElement to the next focused element before the blur event is called."
3528
- // (https://stackoverflow.com/a/49325196/986241)
3529
- // Therefore if the relatedTarget is null, we try the document.activeElement,
3530
- // which may contain the HTML element that is gaining focus
3531
- const focusElement = relatedTarget || (document.activeElement !== target ? document.activeElement : null);
3532
- const focusElementParent = focusElement && focusElement.closest('.tw-date');
3533
- return blurElementParent !== focusElementParent;
3534
- }
3535
-
3536
- const POPOVER_OFFSET = [0, 16];
3537
- // By default the flip positioning explores only the opposite alternative. So if left is passed and there's no enough space
3538
- // the right one gets chosen. If there's no space on both sides popover goes back to the initially chosen one left.
3539
- // This mapping forces popover to try the four available positions before going back to the initial chosen one.
3540
- const fallbackPlacements = {
3541
- [exports.Position.TOP]: [exports.Position.BOTTOM, exports.Position.RIGHT, exports.Position.LEFT],
3542
- [exports.Position.BOTTOM]: [exports.Position.TOP, exports.Position.RIGHT, exports.Position.LEFT],
3543
- [exports.Position.LEFT]: [exports.Position.RIGHT, exports.Position.TOP, exports.Position.BOTTOM],
3544
- [exports.Position.RIGHT]: [exports.Position.LEFT, exports.Position.TOP, exports.Position.BOTTOM]
3545
- };
3546
- const Panel = /*#__PURE__*/React.forwardRef(function Panel({
3547
- arrow = false,
3548
- flip = true,
3549
- altAxis = false,
3550
- children,
3551
- open = false,
3552
- onClose,
3553
- position = exports.Position.BOTTOM,
3554
- anchorRef,
3555
- anchorWidth = false,
3556
- ...rest
3557
- }, reference) {
3558
- const [arrowElement, setArrowElement] = React.useState(null);
3559
- const [popperElement, setPopperElement] = React.useState(null);
3560
- const modifiers = [];
3561
- if (altAxis) {
3562
- modifiers.push({
3563
- // https://popper.js.org/docs/v2/modifiers/prevent-overflow
3564
- name: 'preventOverflow',
3565
- options: {
3566
- altAxis: true,
3567
- tether: false
3568
- }
3569
- });
3570
- }
3571
- if (arrow) {
3572
- modifiers.push({
3573
- name: 'arrow',
3574
- options: {
3575
- element: arrowElement,
3576
- options: {
3577
- padding: 8 // 8px from the edges of the popper
3578
- }
3579
- }
3580
- });
3581
- // This lets you displace a popper element from its reference element.
3582
- modifiers.push({
3583
- name: 'offset',
3584
- options: {
3585
- offset: POPOVER_OFFSET
3586
- }
3587
- });
3588
- }
3589
- if (flip && fallbackPlacements[position]) {
3590
- modifiers.push({
3591
- name: 'flip',
3592
- options: {
3593
- fallbackPlacements: fallbackPlacements[position]
3594
- }
3595
- });
3596
- }
3597
- const {
3598
- styles,
3599
- attributes,
3600
- forceUpdate
3601
- } = reactPopper.usePopper(anchorRef.current, popperElement, {
3602
- placement: position,
3603
- modifiers
3604
- });
3605
- // If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),
3606
- // it is most simple just to always position before opening
3607
- React.useEffect(() => {
3608
- if (open && forceUpdate) {
3609
- forceUpdate();
3610
- }
3611
- }, [open]);
3612
- const contentStyle = {
3613
- ...(anchorWidth ? {
3614
- width: anchorRef.current?.clientWidth
3615
- } : undefined)
3788
+ })
3789
+ });
3616
3790
  };
3617
- return /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
3618
- open: open,
3619
- transparent: true,
3620
- fadeContentOnEnter: true,
3621
- fadeContentOnExit: true,
3622
- onClose: onClose,
3623
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
3624
- ...rest,
3625
- ref: setPopperElement,
3626
- role: "dialog"
3627
- // eslint-disable-next-line react/forbid-dom-props
3628
- ,
3629
- style: {
3630
- ...styles.popper
3631
- },
3632
- ...attributes.popper,
3633
- className: classNames__default.default('np-panel', {
3634
- 'np-panel--open': open
3635
- }, rest.className),
3636
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
3637
- ref: reference
3638
- /* eslint-disable-next-line react/forbid-dom-props */,
3639
- style: contentStyle,
3640
- className: classNames__default.default('np-panel__content'),
3641
- children: [children, arrow && /*#__PURE__*/jsxRuntime.jsx("div", {
3642
- ref: setArrowElement,
3643
- className: classNames__default.default('np-panel__arrow')
3644
- // eslint-disable-next-line react/forbid-dom-props
3645
- ,
3646
- style: styles.arrow
3791
+ const getYear = () => {
3792
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
3793
+ className: "col-sm-4",
3794
+ children: /*#__PURE__*/jsxRuntime.jsxs("label", {
3795
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
3796
+ className: "sr-only",
3797
+ children: yearLabel
3798
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
3799
+ className: `input-group input-group-${size}`,
3800
+ children: /*#__PURE__*/jsxRuntime.jsx(Input, {
3801
+ type: "text",
3802
+ inputMode: "numeric",
3803
+ pattern: "[0-9]*",
3804
+ name: "year",
3805
+ autoComplete: yearAutoComplete,
3806
+ placeholder: placeholders?.year,
3807
+ value: year || '',
3808
+ disabled: disabled,
3809
+ min: 1,
3810
+ onChange: event => handleYearChange(event)
3811
+ })
3647
3812
  })]
3648
3813
  })
3814
+ });
3815
+ };
3816
+ const monthBeforeDay = MDY.has(locale);
3817
+ const yearFirst = YMD.has(locale);
3818
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
3819
+ className: "tw-date",
3820
+ ...inputAttributes,
3821
+ id: id,
3822
+ "aria-labelledby": ariaLabelledBy,
3823
+ "aria-label": ariaLabel,
3824
+ role: "group" // Add role attribute to indicate container for interactive elements
3825
+ ,
3826
+ onFocus: event => shouldPropagateOnFocus(event) ? onFocus && onFocus(event) : event.stopPropagation(),
3827
+ onBlur: event => shouldPropagateOnBlur(event) ? onBlur && onBlur(event) : event.stopPropagation(),
3828
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
3829
+ className: "row",
3830
+ children: (() => {
3831
+ if (monthYearOnly) {
3832
+ return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3833
+ children: [!yearFirst && getMonth(), getYear(), yearFirst && getMonth()]
3834
+ });
3835
+ }
3836
+ if (monthBeforeDay) {
3837
+ return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3838
+ children: [getMonth(), getDay(), getYear()]
3839
+ });
3840
+ }
3841
+ if (yearFirst) {
3842
+ return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3843
+ children: [getYear(), getMonth(), getDay()]
3844
+ });
3845
+ }
3846
+ return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
3847
+ children: [getDay(), getMonth(), getYear()]
3848
+ });
3849
+ })()
3649
3850
  })
3650
3851
  });
3651
- });
3652
- var Panel$1 = Panel;
3852
+ };
3853
+ // Should only propagate if the relatedTarget is not part of this DateInput component.
3854
+ function shouldPropagateOnFocus({
3855
+ target,
3856
+ relatedTarget
3857
+ }) {
3858
+ const targetParent = target.closest('.tw-date');
3859
+ const relatedParent = relatedTarget && relatedTarget.closest('.tw-date');
3860
+ return targetParent !== relatedParent;
3861
+ }
3862
+ // Should only propagate if the relatedTarget or the activeElement is not part of this DateInput component.
3863
+ function shouldPropagateOnBlur({
3864
+ target,
3865
+ relatedTarget
3866
+ }) {
3867
+ const blurElementParent = target.closest('.tw-date');
3868
+ // Even though FocusEvent.relatedTarget is supported by IE
3869
+ // (https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/relatedTarget)
3870
+ // "IE11 sets document.activeElement to the next focused element before the blur event is called."
3871
+ // (https://stackoverflow.com/a/49325196/986241)
3872
+ // Therefore if the relatedTarget is null, we try the document.activeElement,
3873
+ // which may contain the HTML element that is gaining focus
3874
+ const focusElement = relatedTarget || (document.activeElement !== target ? document.activeElement : null);
3875
+ const focusElementParent = focusElement && focusElement.closest('.tw-date');
3876
+ return blurElementParent !== focusElementParent;
3877
+ }
3653
3878
 
3654
3879
  const ResponsivePanel = /*#__PURE__*/React.forwardRef(function ResponsivePanel({
3655
3880
  anchorRef,
@@ -3672,7 +3897,7 @@ const ResponsivePanel = /*#__PURE__*/React.forwardRef(function ResponsivePanel({
3672
3897
  children: children
3673
3898
  }, "bottomSheet");
3674
3899
  }
3675
- return /*#__PURE__*/jsxRuntime.jsx(Panel$1, {
3900
+ return /*#__PURE__*/jsxRuntime.jsx(Panel, {
3676
3901
  ref: reference,
3677
3902
  flip: flip,
3678
3903
  arrow: arrow,
@@ -4647,39 +4872,6 @@ var DateLookup$1 = withInputAttributes(DateLookup, {
4647
4872
  nonLabelable: true
4648
4873
  });
4649
4874
 
4650
- const NavigationOption = /*#__PURE__*/React.forwardRef(({
4651
- as: component = 'button',
4652
- disabled = false,
4653
- onClick,
4654
- className,
4655
- ...rest
4656
- }, reference) => {
4657
- if ('href' in rest && rest.href) {
4658
- component = 'a';
4659
- }
4660
- return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
4661
- ...rest,
4662
- ref: reference,
4663
- as: component,
4664
- className: classNames__default.default('np-navigation-option', className),
4665
- button: /*#__PURE__*/jsxRuntime.jsx(Chevron, {
4666
- orientation: exports.Position.RIGHT,
4667
- disabled: disabled,
4668
- className: "d-block"
4669
- }),
4670
- disabled: disabled,
4671
- onClick: event => {
4672
- if (disabled) {
4673
- event.preventDefault();
4674
- return;
4675
- }
4676
- if (onClick) {
4677
- onClick(event);
4678
- }
4679
- }
4680
- });
4681
- });
4682
-
4683
4875
  const Tile = ({
4684
4876
  className,
4685
4877
  description,
@@ -5554,73 +5746,6 @@ const FlowNavigation = ({
5554
5746
  });
5555
5747
  };
5556
5748
 
5557
- const HeaderAction = ({
5558
- action
5559
- }) => {
5560
- const {
5561
- isModern
5562
- } = componentsTheming.useTheme();
5563
- const props = {
5564
- 'aria-label': action['aria-label']
5565
- };
5566
- if ('href' in action) {
5567
- return /*#__PURE__*/jsxRuntime.jsx(Link, {
5568
- href: action.href,
5569
- target: action.target,
5570
- onClick: action.onClick,
5571
- ...props,
5572
- children: action.text
5573
- });
5574
- }
5575
- return isModern ? /*#__PURE__*/jsxRuntime.jsx(Button, {
5576
- className: "np-header__button",
5577
- priority: "tertiary",
5578
- size: "sm",
5579
- onClick: action.onClick,
5580
- ...props,
5581
- children: action.text
5582
- }) : /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
5583
- onClick: action.onClick,
5584
- ...props,
5585
- children: action.text
5586
- });
5587
- };
5588
- /**
5589
- *
5590
- * Neptune Web: https://transferwise.github.io/neptune-web/components/content/Header
5591
- *
5592
- */
5593
- const Header = ({
5594
- action,
5595
- as = 'h5',
5596
- title,
5597
- className
5598
- }) => {
5599
- if (!action) {
5600
- return /*#__PURE__*/jsxRuntime.jsx(Title, {
5601
- as: as,
5602
- type: exports.Typography.TITLE_GROUP,
5603
- className: classNames__default.default('np-header', 'np-header__title', className),
5604
- children: title
5605
- });
5606
- }
5607
- if (as === 'legend') {
5608
- // eslint-disable-next-line no-console
5609
- console.warn('Legends should be the first child in a fieldset, and this is not possible when including an action');
5610
- }
5611
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
5612
- className: classNames__default.default('np-header', className),
5613
- children: [/*#__PURE__*/jsxRuntime.jsx(Title, {
5614
- as: as,
5615
- type: exports.Typography.TITLE_GROUP,
5616
- className: "np-header__title",
5617
- children: title
5618
- }), /*#__PURE__*/jsxRuntime.jsx(HeaderAction, {
5619
- action: action
5620
- })]
5621
- });
5622
- };
5623
-
5624
5749
  // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
5625
5750
  exports.InfoPresentation = void 0;
5626
5751
  (function (InfoPresentation) {
@@ -7789,18 +7914,6 @@ var MoneyInput$1 = reactIntl.injectIntl(withInputAttributes(MoneyInput, {
7789
7914
  nonLabelable: true
7790
7915
  }));
7791
7916
 
7792
- const NavigationOptionList = ({
7793
- children
7794
- }) => {
7795
- return /*#__PURE__*/jsxRuntime.jsx("ul", {
7796
- className: "np-navigation-options-list",
7797
- children: React.Children.map(children, child => /*#__PURE__*/jsxRuntime.jsx("li", {
7798
- className: "np-navigation-options-list__item",
7799
- children: child
7800
- }, child?.toString()))
7801
- });
7802
- };
7803
-
7804
7917
  const STORAGE_NAME = 'dismissedNudges';
7805
7918
  const getLocalStorage = () => {
7806
7919
  try {
@@ -9597,6 +9710,7 @@ var en = {
9597
9710
  "neptune.PhoneNumberInput.SelectInput.placeholder": "Select an option...",
9598
9711
  "neptune.Select.searchPlaceholder": "Search...",
9599
9712
  "neptune.SelectInput.noResultsFound": "No results found",
9713
+ "neptune.SelectOption.action.label": "Choose",
9600
9714
  "neptune.Summary.statusDone": "Item done",
9601
9715
  "neptune.Summary.statusNotDone": "Item to do",
9602
9716
  "neptune.Summary.statusPending": "Item pending",
@@ -9824,19 +9938,6 @@ function RadioOption({
9824
9938
  });
9825
9939
  }
9826
9940
 
9827
- const Section = ({
9828
- children,
9829
- className,
9830
- withHorizontalPadding = false
9831
- }) => {
9832
- return /*#__PURE__*/jsxRuntime.jsx("div", {
9833
- className: classNames__default.default('np-section', className, {
9834
- 'np-section--with-horizontal-padding': withHorizontalPadding
9835
- }),
9836
- children: children
9837
- });
9838
- };
9839
-
9840
9941
  const SegmentedControl = ({
9841
9942
  name,
9842
9943
  value,
@@ -10490,7 +10591,7 @@ function Select({
10490
10591
  children: renderOptionsList({
10491
10592
  className: isModern ? '' : 'p-a-1'
10492
10593
  })
10493
- }) : /*#__PURE__*/jsxRuntime.jsx(Panel$1, {
10594
+ }) : /*#__PURE__*/jsxRuntime.jsx(Panel, {
10494
10595
  open: open,
10495
10596
  flip: false,
10496
10597
  altAxis: true,
@@ -10740,19 +10841,21 @@ function SnackbarProvider({
10740
10841
  });
10741
10842
  }
10742
10843
 
10743
- function Sticky({
10844
+ const Sticky = ({
10744
10845
  open = true,
10745
- position = 'bottom',
10746
- children
10747
- }) {
10846
+ position = exports.Position.BOTTOM,
10847
+ children,
10848
+ testId
10849
+ }) => {
10748
10850
  return /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
10851
+ testId: testId,
10749
10852
  open: open,
10750
10853
  position: position,
10751
10854
  slidingPanelPositionFixed: true,
10752
10855
  showSlidingPanelBorder: true,
10753
10856
  children: children
10754
10857
  });
10755
- }
10858
+ };
10756
10859
 
10757
10860
  var messages$1 = reactIntl.defineMessages({
10758
10861
  statusNotDone: {
@@ -13393,7 +13496,6 @@ const UploadItem = ({
13393
13496
  status,
13394
13497
  filename,
13395
13498
  error,
13396
- errors,
13397
13499
  url
13398
13500
  } = file;
13399
13501
  const {
@@ -13401,7 +13503,7 @@ const UploadItem = ({
13401
13503
  } = componentsTheming.useTheme();
13402
13504
  const isSucceeded = [exports.Status.SUCCEEDED, undefined].includes(status) && !!url;
13403
13505
  const getIcon = () => {
13404
- if (error || errors?.length || status === exports.Status.FAILED) {
13506
+ if (error || status === exports.Status.FAILED) {
13405
13507
  return isModern ? /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
13406
13508
  size: exports.Size.SMALL,
13407
13509
  sentiment: exports.Sentiment.NEGATIVE
@@ -13440,30 +13542,13 @@ const UploadItem = ({
13440
13542
  children: processIndicator
13441
13543
  }); // Scale down ProcessIndicator to be 20px*20px to match `icons`
13442
13544
  };
13443
- const getErrorMessage = error => typeof error === 'object' ? error.message : error || formatMessage(MESSAGES.uploadingFailed);
13444
- const getMultipleErrors = errors => {
13445
- if (!errors?.length) {
13446
- return null;
13447
- }
13448
- if (errors?.length === 1) {
13449
- return getErrorMessage(errors[0]);
13450
- }
13451
- return /*#__PURE__*/jsxRuntime.jsx("ul", {
13452
- className: "np-upload-input-errors m-b-0",
13453
- children: errors.map((error, index) => {
13454
- // eslint-disable-next-line react/no-array-index-key
13455
- return /*#__PURE__*/jsxRuntime.jsx("li", {
13456
- children: getErrorMessage(error)
13457
- }, index);
13458
- })
13459
- });
13460
- };
13545
+ const getErrorMessage = () => typeof error === 'object' ? error.message : error || formatMessage(MESSAGES.uploadingFailed);
13461
13546
  const getDescription = () => {
13462
- if (error || errors?.length || status === exports.Status.FAILED) {
13547
+ if (error || status === exports.Status.FAILED) {
13463
13548
  return /*#__PURE__*/jsxRuntime.jsx(Body, {
13464
13549
  type: exports.Typography.BODY_DEFAULT_BOLD,
13465
13550
  className: "text-negative",
13466
- children: errors?.length ? getMultipleErrors(errors) : getErrorMessage(error)
13551
+ children: getErrorMessage()
13467
13552
  });
13468
13553
  }
13469
13554
  switch (status) {
@@ -14872,6 +14957,7 @@ exports.Select = Select;
14872
14957
  exports.SelectInput = SelectInput;
14873
14958
  exports.SelectInputOptionContent = SelectInputOptionContent;
14874
14959
  exports.SelectInputTriggerButton = SelectInputTriggerButton;
14960
+ exports.SelectOption = SelectOption;
14875
14961
  exports.SlidingPanel = SlidingPanel;
14876
14962
  exports.SnackbarConsumer = SnackbarConsumer;
14877
14963
  exports.SnackbarContext = SnackbarContext;