@transferwise/components 0.0.0-experimental-b67d30b → 0.0.0-experimental-3b13cb3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -5,22 +5,22 @@ var reactId = require('@radix-ui/react-id');
5
5
  var classNames = require('classnames');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var icons = require('@transferwise/icons');
8
- var reactIntl = require('react-intl');
9
- var PropTypes = require('prop-types');
10
- var commonmark = require('commonmark');
8
+ var reactPopper = require('react-popper');
11
9
  var componentsTheming = require('@wise/components-theming');
12
10
  var reactTransitionGroup = require('react-transition-group');
13
11
  var focus = require('@react-aria/focus');
14
12
  var reactDom = require('react-dom');
13
+ var reactIntl = require('react-intl');
14
+ var PropTypes = require('prop-types');
15
+ var art = require('@wise/art');
15
16
  var index_js = require('use-sync-external-store/shim/index.js');
16
17
  var neptuneValidation = require('@transferwise/neptune-validation');
18
+ var commonmark = require('commonmark');
17
19
  var formatting = require('@transferwise/formatting');
18
20
  var react$1 = require('@headlessui/react');
19
21
  var mergeProps = require('merge-props');
20
22
  var react = require('@floating-ui/react');
21
23
  var overlays = require('@react-aria/overlays');
22
- var reactPopper = require('react-popper');
23
- var art = require('@wise/art');
24
24
  var clamp$2 = require('lodash.clamp');
25
25
  var debounce = require('lodash.debounce');
26
26
  var requiredIf = require('react-required-if');
@@ -700,565 +700,358 @@ const ActionOption = ({
700
700
  });
701
701
  };
702
702
 
703
- var messages$d = reactIntl.defineMessages({
704
- ariaLabel: {
705
- id: "neptune.CloseButton.ariaLabel"
706
- }
707
- });
708
-
709
- const CloseButton = /*#__PURE__*/React.forwardRef(function CloseButton({
710
- 'aria-label': ariaLabel,
711
- size = exports.Size.MEDIUM,
712
- filled = false,
713
- className,
714
- onClick,
715
- isDisabled,
716
- testId
717
- }, reference) {
718
- const intl = reactIntl.useIntl();
719
- ariaLabel ??= intl.formatMessage(messages$d.ariaLabel);
720
- const Icon = filled ? icons.CrossCircleFill : icons.Cross;
721
- return /*#__PURE__*/jsxRuntime.jsx("button", {
722
- ref: reference,
723
- type: "button",
724
- className: classNames__default.default('np-close-button', 'close btn-link', 'text-no-decoration', {
725
- 'np-close-button--large': size === exports.Size.MEDIUM,
726
- 'np-close-button--x-large': size === exports.Size.LARGE
727
- }, className),
728
- "aria-label": ariaLabel,
729
- "aria-disabled": isDisabled,
730
- disabled: isDisabled,
731
- "data-testid": testId,
732
- onClick: onClick,
733
- children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
734
- size: size === exports.Size.SMALL ? 16 : 24
735
- })
736
- });
737
- });
738
-
739
- var messages$c = reactIntl.defineMessages({
740
- opensInNewTab: {
741
- id: "neptune.Link.opensInNewTab"
742
- }
743
- });
744
-
745
- const Link = ({
746
- className,
747
- children,
748
- href,
749
- target,
750
- type,
751
- 'aria-label': ariaLabel,
752
- onClick,
753
- ...props
754
- }) => {
755
- const isBlank = target === '_blank';
756
- const {
757
- formatMessage
758
- } = reactIntl.useIntl();
759
- return /*#__PURE__*/jsxRuntime.jsxs("a", {
760
- href: href,
761
- target: target,
762
- className: classNames__default.default('np-link', type ? `np-text-${type}` : undefined, 'd-inline-flex', className),
763
- "aria-label": ariaLabel,
764
- rel: isBlank ? 'noreferrer' : undefined,
765
- onClick: onClick,
766
- ...props,
767
- children: [children, " ", isBlank && /*#__PURE__*/jsxRuntime.jsx(icons.NavigateAway, {
768
- title: formatMessage(messages$c.opensInNewTab)
769
- })]
770
- });
771
- };
772
-
773
- const iconTypeMap = {
774
- positive: icons.Check,
775
- neutral: icons.Info,
776
- warning: icons.Alert,
777
- negative: icons.Cross,
778
- pending: icons.ClockBorderless,
779
- info: icons.Info,
780
- error: icons.Cross,
781
- success: icons.Check
782
- };
783
- const StatusIcon = ({
784
- sentiment = 'neutral',
785
- size = 'md'
703
+ const FocusBoundary = ({
704
+ children
786
705
  }) => {
787
- const Icon = iconTypeMap[sentiment];
788
- const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
789
- return /*#__PURE__*/jsxRuntime.jsx("span", {
790
- "data-testid": "status-icon",
791
- className: classNames__default.default('status-circle', 'status-circle-' + size, sentiment),
792
- children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
793
- className: classNames__default.default('status-icon', iconColor)
706
+ const wrapperReference = React.useRef(null);
707
+ React.useEffect(() => {
708
+ wrapperReference.current?.focus({
709
+ preventScroll: true
710
+ });
711
+ }, []);
712
+ return /*#__PURE__*/jsxRuntime.jsx(focus.FocusScope, {
713
+ contain: true,
714
+ restoreFocus: true,
715
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
716
+ ref: wrapperReference,
717
+ tabIndex: -1,
718
+ children: children
794
719
  })
795
720
  });
796
721
  };
797
722
 
798
- const DEFAULT_TYPE = exports.Typography.TITLE_GROUP;
799
- const titleTypeMapping = {
800
- [exports.Typography.TITLE_SCREEN]: 'h1',
801
- [exports.Typography.TITLE_SECTION]: 'h2',
802
- [exports.Typography.TITLE_SUBSECTION]: 'h3',
803
- [exports.Typography.TITLE_BODY]: 'h4',
804
- [exports.Typography.TITLE_GROUP]: 'h5'
805
- };
806
- function Title({
807
- as,
808
- type = DEFAULT_TYPE,
809
- className,
810
- ...props
811
- }) {
812
- const mapping = titleTypeMapping[type];
813
- const isTypeSupported = mapping !== undefined;
814
- if (isTypeSupported) {
815
- const HeaderTag = as ?? mapping;
816
- return /*#__PURE__*/jsxRuntime.jsx(HeaderTag, {
817
- ...props,
818
- className: classNames__default.default(`np-text-${type}`, className)
819
- });
820
- }
821
- const HeaderTag = as ?? titleTypeMapping[DEFAULT_TYPE];
822
- return /*#__PURE__*/jsxRuntime.jsx(HeaderTag, {
823
- ...props,
824
- className: classNames__default.default(`np-text-${DEFAULT_TYPE}`, className)
825
- });
826
- }
827
-
828
- function logActionRequired(message) {
829
- if (['development', 'test'].includes(process?.env?.NODE_ENV)) {
830
- // eslint-disable-next-line no-console
831
- console.warn(message);
832
- }
833
- }
834
- function logActionRequiredIf(message, conditional) {
835
- if (conditional) {
836
- logActionRequired(message);
837
- }
723
+ function withNextPortalWrapper(Component) {
724
+ return function (props) {
725
+ const [mounted, setMounted] = React.useState(false);
726
+ React.useEffect(() => {
727
+ setMounted(true);
728
+ }, [setMounted]);
729
+ return mounted ? /*#__PURE__*/reactDom.createPortal( /*#__PURE__*/jsxRuntime.jsx(Component, {
730
+ ...props
731
+ }), document.body) : null;
732
+ };
838
733
  }
839
734
 
840
- const reader = new commonmark__default.default.Parser();
841
- const writer = new commonmark__default.default.HtmlRenderer({
842
- safe: true
843
- });
844
- const NODE_TYPE_LIST = Object.values(exports.MarkdownNodeType);
845
- function Markdown({
846
- as: Element = 'div',
847
- allowList,
848
- blockList,
849
- config,
850
- className,
851
- children
852
- }) {
853
- if (!children) {
854
- return null;
855
- }
856
- const linkTarget = config?.link?.target ?? '_self';
857
- const paragraphClass = config?.paragraph?.className ?? '';
858
- if (allowList != null && blockList != null) {
859
- logActionRequired('Markdown supports only one of `allowList` or `blockList` to be used at a time. `blockList` will be ignored.');
735
+ /**
736
+ * Dimmer state management inspired by Material UI's ModalManager (https://github.com/mui-org/material-ui)
737
+ */
738
+ class DimmerManager {
739
+ /**
740
+ * Dimmer refs
741
+ */
742
+ dimmers;
743
+ constructor() {
744
+ this.dimmers = [];
860
745
  }
861
- const parser = nodes => {
862
- const parsed = reader.parse(nodes);
863
- const toExclude = allowList != null ? NODE_TYPE_LIST.filter(type => !allowList.includes(type)) : blockList;
864
- return toExclude != null ? stripNodes({
865
- parsed,
866
- blockList: toExclude
867
- }) : parsed;
868
- };
869
- const createMarkup = () => {
870
- const parsed = parser(children);
871
- return writer.render(parsed).replace(/<a href="/g, `<a target="${linkTarget}" href="`).replace(/<p>/g, `<p class="${paragraphClass}">`);
872
- };
873
- return /*#__PURE__*/jsxRuntime.jsx(Element, {
874
- className: className,
875
- dangerouslySetInnerHTML: {
876
- __html: createMarkup()
746
+ add(dimmer) {
747
+ let dimmerIndex = this.dimmers.indexOf(dimmer);
748
+ if (dimmerIndex !== -1) {
749
+ return dimmerIndex;
877
750
  }
878
- });
879
- }
880
- function stripNodes({
881
- blockList,
882
- parsed
883
- }) {
884
- if (!parsed) {
885
- return parsed;
751
+ dimmerIndex = this.dimmers.length;
752
+ this.dimmers.push(dimmer);
753
+ return dimmerIndex;
886
754
  }
887
- const walker = parsed.walker();
888
- for (let event = walker.next(); event != null; event = walker.next()) {
889
- const {
890
- node
891
- } = event;
892
- if (blockList.includes(node.type) && !event.entering) {
893
- while (node.firstChild != null) {
894
- node.insertBefore(node.firstChild);
895
- }
896
- node.unlink();
755
+ remove(dimmer) {
756
+ const dimmerIndex = this.dimmers.indexOf(dimmer);
757
+ if (dimmerIndex !== -1) {
758
+ this.dimmers.splice(dimmerIndex, 1);
897
759
  }
760
+ return dimmerIndex;
761
+ }
762
+ isTop(dimmer) {
763
+ return this.dimmers.length > 0 && this.dimmers[this.dimmers.length - 1] === dimmer;
898
764
  }
899
- return parsed;
900
765
  }
901
766
 
902
- const allowList = [exports.MarkdownNodeType.STRONG];
903
- const InlineMarkdown = props => {
904
- return /*#__PURE__*/jsxRuntime.jsx(Markdown, {
905
- ...props,
906
- as: "span",
907
- allowList: allowList,
908
- blockList: undefined
909
- });
910
- };
911
- InlineMarkdown.propTypes = {
912
- children: PropTypes__default.default.string.isRequired,
913
- className: PropTypes__default.default.string
914
- };
915
- InlineMarkdown.defaultProps = {
916
- className: undefined
917
- };
918
-
919
- exports.AlertArrowPosition = void 0;
920
- (function (AlertArrowPosition) {
921
- AlertArrowPosition["TOP_LEFT"] = "up-left";
922
- AlertArrowPosition["TOP"] = "up-center";
923
- AlertArrowPosition["TOP_RIGHT"] = "up-right";
924
- AlertArrowPosition["BOTTOM_LEFT"] = "down-left";
925
- AlertArrowPosition["BOTTOM"] = "down-center";
926
- AlertArrowPosition["BOTTOM_RIGHT"] = "down-right";
927
- })(exports.AlertArrowPosition || (exports.AlertArrowPosition = {}));
928
- function resolveType(type) {
929
- switch (type) {
930
- case 'success':
931
- return 'positive';
932
- case 'info':
933
- return 'neutral';
934
- case 'error':
935
- return 'negative';
936
- default:
937
- return type;
767
+ const EXIT_ANIMATION$1 = 350;
768
+ const dimmerManager = new DimmerManager();
769
+ const handleTouchMove = event => {
770
+ const isTouchedElementDimmer = event.target.classList.contains('dimmer');
771
+ // disable scroll on iOS devices for Dimmer area
772
+ // this is because of bug in WebKit https://bugs.webkit.org/show_bug.cgi?id=220908
773
+ // note: scrolling still works for children(s) as expected
774
+ if (isIosDevice() && isTouchedElementDimmer) {
775
+ event.stopPropagation();
776
+ event.preventDefault();
938
777
  }
939
- }
940
- function Alert({
941
- arrow,
942
- action,
778
+ };
779
+ const Dimmer = ({
943
780
  children,
944
781
  className,
945
- dismissible,
946
- icon,
947
- onDismiss,
948
- message,
949
- size,
950
- title,
951
- type = 'neutral',
952
- variant = 'desktop'
953
- }) {
954
- React.useEffect(() => {
955
- if (arrow !== undefined) {
956
- logActionRequired("Alert component doesn't support 'arrow' anymore, use 'InlineAlert' instead.");
782
+ disableClickToClose = false,
783
+ contentPosition,
784
+ fadeContentOnEnter = false,
785
+ fadeContentOnExit = false,
786
+ open = false,
787
+ scrollable = false,
788
+ transparent = false,
789
+ onClose
790
+ }) => {
791
+ const [hasNotExited, setHasNotExited] = React.useState(false);
792
+ const dimmerReference = React.useRef(null);
793
+ const closeOnClick = event => {
794
+ if (event.target === dimmerReference.current) {
795
+ onClose?.(event);
957
796
  }
958
- }, [arrow]);
959
- React.useEffect(() => {
960
- if (children !== undefined) {
961
- logActionRequired("Alert component doesn't support 'children' anymore, use 'message' instead.");
797
+ };
798
+ const handleClick = event => {
799
+ if (disableClickToClose || !onClose) {
800
+ return;
962
801
  }
963
- }, [children]);
964
- React.useEffect(() => {
965
- if (dismissible !== undefined) {
966
- logActionRequired("Alert component doesn't support 'dismissible' anymore, use 'onDismiss' instead.");
802
+ closeOnClick(event);
803
+ };
804
+ const handleKeyDown = React.useCallback(event => {
805
+ if (event.key !== 'Escape') {
806
+ return;
967
807
  }
968
- }, [dismissible]);
969
- React.useEffect(() => {
970
- if (size !== undefined) {
971
- logActionRequired("Alert component doesn't support 'size' anymore, please remove that prop.");
808
+ event.stopPropagation();
809
+ if (onClose && dimmerReference.current && dimmerManager.isTop(dimmerReference.current)) {
810
+ onClose(event);
972
811
  }
973
- }, [size]);
974
- const resolvedType = resolveType(type);
812
+ }, [onClose]);
813
+ const onEnter = () => {
814
+ setHasNotExited(true);
815
+ if (dimmerReference.current) {
816
+ dimmerManager.add(dimmerReference.current);
817
+ }
818
+ };
819
+ const onExited = () => {
820
+ setHasNotExited(false);
821
+ if (dimmerReference.current) {
822
+ dimmerManager.remove(dimmerReference.current);
823
+ }
824
+ };
975
825
  React.useEffect(() => {
976
- if (resolvedType !== type) {
977
- logActionRequired(`Alert component has deprecated '${type}' value for the 'type' prop. Please use '${resolvedType}' instead.`);
826
+ const localReferenceCopy = dimmerReference.current;
827
+ if (open) {
828
+ document.addEventListener('keydown', handleKeyDown);
829
+ localReferenceCopy?.addEventListener('touchmove', handleTouchMove, {
830
+ passive: true
831
+ });
978
832
  }
979
- }, [resolvedType, type]);
980
- const [shouldFire, setShouldFire] = React.useState(false);
981
- const closeButtonReference = React.useRef(null);
982
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
983
- className: classNames__default.default('alert d-flex', `alert-${resolvedType}`, arrow != null && alertArrowClassNames(arrow), className),
984
- "data-testid": "alert",
985
- onTouchStart: () => setShouldFire(true),
986
- onTouchEnd: event => {
987
- if (shouldFire && action &&
988
- // Check if current event is triggered from closeButton
989
- event.target instanceof Node && closeButtonReference.current && !closeButtonReference.current.contains(event.target)) {
990
- if (action.target === '_blank') {
991
- window.top?.open(action.href);
992
- } else {
993
- window.top?.location.assign(action.href);
994
- }
995
- }
996
- setShouldFire(false);
997
- },
998
- onTouchMove: () => setShouldFire(false),
999
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1000
- className: classNames__default.default('alert__content', 'd-flex', 'flex-grow-1', variant),
1001
- "data-testid": variant,
1002
- children: [icon ? /*#__PURE__*/jsxRuntime.jsx("div", {
1003
- className: "alert__icon",
1004
- children: icon
1005
- }) : /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
1006
- size: exports.Size.LARGE,
1007
- sentiment: resolvedType
1008
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
1009
- className: "alert__message",
1010
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1011
- role: exports.Sentiment.NEGATIVE === resolvedType ? 'alert' : 'status',
1012
- children: [title && /*#__PURE__*/jsxRuntime.jsx(Title, {
1013
- className: "m-b-1",
1014
- type: exports.Typography.TITLE_BODY,
1015
- children: title
1016
- }), /*#__PURE__*/jsxRuntime.jsx(Body, {
1017
- as: "span",
1018
- className: "d-block",
1019
- type: exports.Typography.BODY_LARGE,
1020
- children: children || /*#__PURE__*/jsxRuntime.jsx(InlineMarkdown, {
1021
- children: message
833
+ return () => {
834
+ document.removeEventListener('keydown', handleKeyDown);
835
+ localReferenceCopy?.removeEventListener('touchmove', handleTouchMove);
836
+ };
837
+ }, [handleKeyDown, open]);
838
+ return /*#__PURE__*/jsxRuntime.jsx(DimmerWrapper, {
839
+ open: open,
840
+ hasNotExited: hasNotExited,
841
+ children: /*#__PURE__*/jsxRuntime.jsx(reactTransitionGroup.CSSTransition, {
842
+ nodeRef: dimmerReference,
843
+ in: open,
844
+ appear: true
845
+ // Wait for animation to finish before unmount.
846
+ ,
847
+ timeout: {
848
+ enter: 0,
849
+ exit: EXIT_ANIMATION$1
850
+ },
851
+ classNames: {
852
+ enter: classNames__default.default({
853
+ 'dimmer--enter-fade': fadeContentOnEnter
854
+ }),
855
+ enterDone: classNames__default.default('dimmer--enter-done', {
856
+ 'dimmer--enter-fade': fadeContentOnEnter
857
+ }),
858
+ exit: classNames__default.default('dimmer--exit', {
859
+ 'dimmer--exit-fade': fadeContentOnExit
860
+ })
861
+ },
862
+ unmountOnExit: true,
863
+ onEnter: onEnter,
864
+ onExited: onExited,
865
+ children: /*#__PURE__*/jsxRuntime.jsx(DimmerContentWrapper, {
866
+ scrollBody: !transparent,
867
+ children: /*#__PURE__*/jsxRuntime.jsx(FocusBoundary, {
868
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
869
+ ref: dimmerReference,
870
+ className: classNames__default.default('dimmer', {
871
+ 'dimmer--scrollable': scrollable,
872
+ 'dimmer--transparent': transparent
873
+ }, className),
874
+ role: "presentation",
875
+ onClick: handleClick,
876
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
877
+ className: classNames__default.default('dimmer-content-positioner', contentPosition != null && ['d-flex justify-content-center', {
878
+ 'align-items-start': contentPosition === 'top',
879
+ 'align-items-center': contentPosition === 'center',
880
+ 'align-items-end': contentPosition === 'bottom'
881
+ }]),
882
+ children: children
1022
883
  })
1023
- })]
1024
- }), action && /*#__PURE__*/jsxRuntime.jsx(Link, {
1025
- href: action.href,
1026
- className: "m-t-1",
1027
- "aria-label": action['aria-label'],
1028
- target: action.target,
1029
- type: exports.Typography.LINK_LARGE,
1030
- children: action.text
1031
- })]
1032
- })]
1033
- }), onDismiss && /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1034
- ref: closeButtonReference,
1035
- className: "m-l-2",
1036
- onClick: onDismiss
1037
- })]
884
+ })
885
+ })
886
+ })
887
+ })
1038
888
  });
1039
- }
1040
- function alertArrowClassNames(arrow) {
1041
- switch (arrow) {
1042
- case 'down-center':
1043
- return 'arrow arrow-bottom arrow-center';
1044
- case 'down-left':
1045
- return 'arrow arrow-bottom arrow-left';
1046
- case 'down-right':
1047
- return 'arrow arrow-bottom arrow-right';
1048
- case 'up-center':
1049
- return 'arrow arrow-center';
1050
- case 'up-right':
1051
- return 'arrow arrow-right';
1052
- case 'up-left':
1053
- default:
1054
- return 'arrow';
1055
- }
1056
- }
1057
-
1058
- // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
1059
- exports.AvatarType = void 0;
1060
- (function (AvatarType) {
1061
- AvatarType["THUMBNAIL"] = "thumbnail";
1062
- AvatarType["ICON"] = "icon";
1063
- AvatarType["EMOJI"] = "emoji";
1064
- AvatarType["INITIALS"] = "initials";
1065
- })(exports.AvatarType || (exports.AvatarType = {}));
1066
-
1067
- /*
1068
- * The colors we support generating an Avatar background color from a "seed" for.
1069
- * Changing this array will change the assignment between seeds.
1070
- * Do not change this array.
1071
- */
1072
- const avatarColors = ['--color-bright-blue', '--color-bright-yellow', '--color-bright-pink', '--color-bright-orange'];
1073
- /*
1074
- * Takes in a "seed" string and spits out an index for the color we should use.
1075
- * This implementation has been synced across all three clients so that we consistently
1076
- * generate branded avatar colors when rendering a list of Avatars.
1077
- * Do not change this implementation.
1078
- */
1079
- const hashSeed = seed => {
1080
- const base = 31;
1081
- const modulo = avatarColors.length;
1082
- let hashValue = 0;
1083
- let basePow = 1;
1084
- for (let i = 0; i < seed.length; i += 1) {
1085
- hashValue = (hashValue + seed.charCodeAt(i) * basePow) % modulo;
1086
- basePow = basePow * base % modulo;
1087
- }
1088
- return hashValue;
1089
- };
1090
- const getAvatarColorFromSeed = seed => {
1091
- return avatarColors[hashSeed(seed)];
1092
- };
1093
-
1094
- const backwardsCompatibleSize = size => {
1095
- switch (size) {
1096
- case 'sm':
1097
- return 24;
1098
- case 'md':
1099
- return 48;
1100
- case 'lg':
1101
- return 72;
1102
- default:
1103
- return size;
1104
- }
1105
889
  };
1106
- const Avatar = ({
1107
- backgroundColor = null,
1108
- backgroundColorSeed = null,
1109
- children = null,
1110
- className,
1111
- outlined = false,
1112
- size: sizeFromProps = 48,
1113
- theme = exports.Theme.LIGHT,
1114
- type = 'thumbnail'
890
+ const DimmerWrapper = ({
891
+ open,
892
+ hasNotExited,
893
+ children
1115
894
  }) => {
1116
- const backgroundColorFromSeed = React.useMemo(() => !backgroundColor && backgroundColorSeed ? `var(${getAvatarColorFromSeed(backgroundColorSeed)})` : undefined, [backgroundColor, backgroundColorSeed]);
1117
- const size = backwardsCompatibleSize(sizeFromProps);
1118
- return /*#__PURE__*/jsxRuntime.jsx("div", {
1119
- className: classNames__default.default('tw-avatar', className, `tw-avatar--${size}`, `tw-avatar--${type}`, {
1120
- 'tw-avatar--outlined': outlined,
1121
- 'tw-avatar--branded': Boolean(backgroundColorFromSeed),
1122
- 'np-text-title-body': type === 'initials'
1123
- }),
1124
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
1125
- className: "tw-avatar__content",
1126
- style: {
1127
- backgroundColor: backgroundColor || backgroundColorFromSeed
1128
- },
1129
- children: children
1130
- })
895
+ const {
896
+ screenMode,
897
+ theme
898
+ } = componentsTheming.useTheme();
899
+ return open || hasNotExited ? /*#__PURE__*/jsxRuntime.jsx(componentsTheming.ThemeProvider, {
900
+ theme: "personal",
901
+ screenMode: theme === 'personal' ? screenMode : 'light',
902
+ isNotRootProvider: true,
903
+ children: children
904
+ }) : /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
905
+ children: children
1131
906
  });
1132
907
  };
1133
-
1134
- const Badge = ({
1135
- badge,
1136
- className = undefined,
1137
- size = exports.Size.SMALL,
1138
- border = exports.Theme.LIGHT,
1139
- children
908
+ const DimmerContentWrapper = ({
909
+ children,
910
+ scrollBody
1140
911
  }) => {
1141
- const classes = classNames__default.default('tw-badge', {
1142
- [`tw-badge-border-${border}`]: border,
1143
- [`tw-badge-${size}`]: size
1144
- }, className);
1145
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
1146
- className: classes,
1147
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1148
- className: "tw-badge__children",
1149
- children: children
1150
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
1151
- className: "tw-badge__content",
1152
- children: badge
1153
- })]
1154
- });
912
+ React.useEffect(() => {
913
+ if (scrollBody) {
914
+ addNoScrollClass();
915
+ }
916
+ return () => {
917
+ if (scrollBody) {
918
+ removeNoScrollClass();
919
+ }
920
+ };
921
+ }, [scrollBody]);
922
+ return children;
1155
923
  };
924
+ var Dimmer$1 = withNextPortalWrapper(Dimmer);
1156
925
 
1157
- const OptionalBadge = ({
1158
- url,
1159
- altText,
1160
- statusIcon,
926
+ const POPOVER_OFFSET = [0, 16];
927
+ // By default the flip positioning explores only the opposite alternative. So if left is passed and there's no enough space
928
+ // the right one gets chosen. If there's no space on both sides popover goes back to the initially chosen one left.
929
+ // This mapping forces popover to try the four available positions before going back to the initial chosen one.
930
+ const fallbackPlacements = {
931
+ [exports.Position.TOP]: [exports.Position.BOTTOM, exports.Position.RIGHT, exports.Position.LEFT],
932
+ [exports.Position.BOTTOM]: [exports.Position.TOP, exports.Position.RIGHT, exports.Position.LEFT],
933
+ [exports.Position.LEFT]: [exports.Position.RIGHT, exports.Position.TOP, exports.Position.BOTTOM],
934
+ [exports.Position.RIGHT]: [exports.Position.LEFT, exports.Position.TOP, exports.Position.BOTTOM]
935
+ };
936
+ const Panel = /*#__PURE__*/React.forwardRef(({
937
+ arrow = false,
938
+ flip = true,
939
+ altAxis = false,
1161
940
  children,
941
+ open = false,
942
+ onClose,
943
+ position = exports.Position.BOTTOM,
944
+ anchorRef,
945
+ anchorWidth = false,
1162
946
  ...rest
1163
- }) => {
1164
- if (url) {
1165
- return /*#__PURE__*/jsxRuntime.jsx(Badge, {
1166
- badge: /*#__PURE__*/jsxRuntime.jsx("img", {
1167
- src: url,
1168
- alt: altText
1169
- }),
1170
- ...rest,
1171
- children: children
947
+ }, reference) => {
948
+ const [arrowElement, setArrowElement] = React.useState(null);
949
+ const [popperElement, setPopperElement] = React.useState(null);
950
+ const modifiers = [];
951
+ if (altAxis) {
952
+ modifiers.push({
953
+ // https://popper.js.org/docs/v2/modifiers/prevent-overflow
954
+ name: 'preventOverflow',
955
+ options: {
956
+ altAxis: true,
957
+ tether: false
958
+ }
1172
959
  });
1173
960
  }
1174
- if (statusIcon) {
1175
- return /*#__PURE__*/jsxRuntime.jsx(Badge, {
1176
- badge: /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
1177
- sentiment: statusIcon,
1178
- size: exports.Size.SMALL
1179
- }),
1180
- ...rest,
1181
- children: children
961
+ if (arrow) {
962
+ modifiers.push({
963
+ name: 'arrow',
964
+ options: {
965
+ element: arrowElement,
966
+ options: {
967
+ padding: 8 // 8px from the edges of the popper
968
+ }
969
+ }
970
+ });
971
+ // This lets you displace a popper element from its reference element.
972
+ modifiers.push({
973
+ name: 'offset',
974
+ options: {
975
+ offset: POPOVER_OFFSET
976
+ }
1182
977
  });
1183
978
  }
1184
- return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
979
+ if (flip && fallbackPlacements[position]) {
980
+ modifiers.push({
981
+ name: 'flip',
982
+ options: {
983
+ fallbackPlacements: fallbackPlacements[position]
984
+ }
985
+ });
986
+ }
987
+ const {
988
+ styles,
989
+ attributes,
990
+ forceUpdate
991
+ } = reactPopper.usePopper(anchorRef.current, popperElement, {
992
+ placement: position,
993
+ modifiers
994
+ });
995
+ // If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),
996
+ // it is most simple just to always position before opening
997
+ React.useEffect(() => {
998
+ if (open && forceUpdate) {
999
+ forceUpdate();
1000
+ }
1001
+ }, [open]);
1002
+ const contentStyle = {
1003
+ ...(anchorWidth ? {
1004
+ width: anchorRef.current?.clientWidth
1005
+ } : undefined)
1006
+ };
1007
+ return /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
1008
+ open: open,
1009
+ transparent: true,
1010
+ fadeContentOnEnter: true,
1011
+ fadeContentOnExit: true,
1012
+ onClose: onClose,
1013
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
1014
+ ...rest,
1015
+ ref: setPopperElement,
1016
+ role: "dialog"
1017
+ // eslint-disable-next-line react/forbid-dom-props
1018
+ ,
1019
+ style: {
1020
+ ...styles.popper
1021
+ },
1022
+ ...attributes.popper,
1023
+ className: classNames__default.default('np-panel', {
1024
+ 'np-panel--open': open
1025
+ }, rest['className']),
1026
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
1027
+ ref: reference
1028
+ /* eslint-disable-next-line react/forbid-dom-props */,
1029
+ style: contentStyle,
1030
+ className: classNames__default.default('np-panel__content'),
1031
+ children: [children, arrow && /*#__PURE__*/jsxRuntime.jsx("div", {
1032
+ ref: setArrowElement,
1033
+ className: classNames__default.default('np-panel__arrow')
1034
+ // eslint-disable-next-line react/forbid-dom-props
1035
+ ,
1036
+ style: styles.arrow
1037
+ })]
1038
+ })
1039
+ })
1040
+ });
1041
+ });
1042
+
1043
+ const Section = ({
1044
+ children,
1045
+ className,
1046
+ withHorizontalPadding = false
1047
+ }) => {
1048
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
1049
+ className: classNames__default.default('np-section', className, {
1050
+ 'np-section--with-horizontal-padding': withHorizontalPadding
1051
+ }),
1185
1052
  children: children
1186
1053
  });
1187
1054
  };
1188
- const AvatarWrapper = ({
1189
- url,
1190
- profileType,
1191
- profileId,
1192
- badgeUrl,
1193
- badgeAltText,
1194
- badgeStatusIcon,
1195
- name,
1196
- avatarProps,
1197
- badgeProps
1198
- }) => {
1199
- const [hasImageLoadError, setImageLoadError] = React.useState(false);
1200
- const isBusinessProfile = profileType === exports.ProfileType.BUSINESS;
1201
- // Reset the errored state when url changes
1202
- React.useEffect(() => setImageLoadError(false), [url]);
1203
- const getAvatarProps = () => {
1204
- if (url && !hasImageLoadError) {
1205
- return {
1206
- type: exports.AvatarType.THUMBNAIL,
1207
- children: /*#__PURE__*/jsxRuntime.jsx("img", {
1208
- src: url,
1209
- alt: "",
1210
- onError: () => setImageLoadError(true)
1211
- }),
1212
- ...avatarProps
1213
- };
1214
- }
1215
- if (profileType) {
1216
- return {
1217
- type: exports.AvatarType.ICON,
1218
- children: isBusinessProfile ? /*#__PURE__*/jsxRuntime.jsx(icons.Briefcase, {
1219
- size: "24"
1220
- }) : /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
1221
- size: "24"
1222
- }),
1223
- ...avatarProps
1224
- };
1225
- }
1226
- if (name) {
1227
- return {
1228
- type: exports.AvatarType.INITIALS,
1229
- children: /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
1230
- children: getInitials(name)
1231
- }),
1232
- backgroundColorSeed: profileId?.toString(),
1233
- ...avatarProps
1234
- };
1235
- }
1236
- return {
1237
- type: exports.AvatarType.ICON,
1238
- children: /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
1239
- size: "24"
1240
- }),
1241
- ...avatarProps
1242
- };
1243
- };
1244
- return /*#__PURE__*/jsxRuntime.jsx(OptionalBadge, {
1245
- url: badgeUrl,
1246
- altText: badgeAltText,
1247
- statusIcon: badgeStatusIcon,
1248
- ...badgeProps,
1249
- children: /*#__PURE__*/jsxRuntime.jsx(Avatar, {
1250
- size: exports.Size.MEDIUM,
1251
- ...getAvatarProps()
1252
- })
1253
- });
1254
- };
1255
- function getInitials(name) {
1256
- const allInitials = name.split(' ').map(part => part[0]).join('').toUpperCase();
1257
- if (allInitials.length === 1) {
1258
- return allInitials[0];
1259
- }
1260
- return allInitials[0] + allInitials.slice(-1);
1261
- }
1262
1055
 
1263
1056
  const radius = {
1264
1057
  xxs: 6,
@@ -1383,7 +1176,7 @@ ProcessIndicator.defaultProps = {
1383
1176
  };
1384
1177
  var ProcessIndicator$1 = ProcessIndicator;
1385
1178
 
1386
- var messages$b = reactIntl.defineMessages({
1179
+ var messages$d = reactIntl.defineMessages({
1387
1180
  loadingAriaLabel: {
1388
1181
  id: "neptune.Button.loadingAriaLabel"
1389
1182
  }
@@ -1400,6 +1193,18 @@ const priorityClassMap = {
1400
1193
  [exports.Priority.TERTIARY]: 'btn-priority-3'
1401
1194
  };
1402
1195
 
1196
+ function logActionRequired(message) {
1197
+ if (['development', 'test'].includes(process?.env?.NODE_ENV)) {
1198
+ // eslint-disable-next-line no-console
1199
+ console.warn(message);
1200
+ }
1201
+ }
1202
+ function logActionRequiredIf(message, conditional) {
1203
+ if (conditional) {
1204
+ logActionRequired(message);
1205
+ }
1206
+ }
1207
+
1403
1208
  const deprecatedTypeMap = {
1404
1209
  [exports.Type.PRIMARY]: exports.ControlType.ACCENT,
1405
1210
  [exports.Type.SECONDARY]: exports.ControlType.ACCENT,
@@ -1502,7 +1307,7 @@ const Button = /*#__PURE__*/React.forwardRef(({
1502
1307
  className: classes,
1503
1308
  ...props,
1504
1309
  "aria-live": loading ? 'polite' : 'off',
1505
- "aria-label": loading ? intl.formatMessage(messages$b.loadingAriaLabel) : rest['aria-label'],
1310
+ "aria-label": loading ? intl.formatMessage(messages$d.loadingAriaLabel) : rest['aria-label'],
1506
1311
  children: [children, loading && /*#__PURE__*/jsxRuntime.jsx(ProcessIndicator$1, {
1507
1312
  size: processIndicatorSize(),
1508
1313
  className: "btn-loader"
@@ -1510,806 +1315,415 @@ const Button = /*#__PURE__*/React.forwardRef(({
1510
1315
  });
1511
1316
  });
1512
1317
 
1513
- const Card$1 = /*#__PURE__*/React.forwardRef((props, reference) => {
1318
+ var messages$c = reactIntl.defineMessages({
1319
+ opensInNewTab: {
1320
+ id: "neptune.Link.opensInNewTab"
1321
+ }
1322
+ });
1323
+
1324
+ const Link = ({
1325
+ className,
1326
+ children,
1327
+ href,
1328
+ target,
1329
+ type,
1330
+ 'aria-label': ariaLabel,
1331
+ onClick,
1332
+ ...props
1333
+ }) => {
1334
+ const isBlank = target === '_blank';
1514
1335
  const {
1515
- 'aria-label': ariaLabel,
1516
- as: Element,
1517
- isExpanded,
1518
- title,
1519
- details,
1520
- children,
1521
- onClick,
1522
- icon,
1523
- id,
1524
- className,
1525
- ...rest
1526
- } = props;
1527
- const isOpen = !!(isExpanded && children);
1528
- return /*#__PURE__*/jsxRuntime.jsxs(Element, {
1529
- ref: reference,
1530
- className: classNames__default.default('np-card', className, {
1531
- 'np-card--expanded': isOpen,
1532
- 'np-card--inactive': !children,
1533
- 'np-card--has-icon': !!icon
1534
- }),
1535
- id: id,
1536
- "data-testid": rest['data-testid'],
1537
- children: [/*#__PURE__*/jsxRuntime.jsx(Option$2, {
1538
- "aria-label": ariaLabel,
1539
- as: children ? 'button' : 'div',
1540
- className: classNames__default.default('np-card__button'),
1541
- media: icon,
1542
- title: title,
1543
- content: details,
1544
- showMediaAtAllSizes: true,
1545
- button: children && /*#__PURE__*/jsxRuntime.jsx(Chevron, {
1546
- orientation: isOpen ? exports.Position.TOP : exports.Position.BOTTOM
1547
- }),
1548
- onClick: () => children && onClick(!isExpanded)
1549
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
1550
- className: classNames__default.default('np-card__divider', {
1551
- 'np-card__divider--expanded': isOpen
1552
- })
1553
- }), isOpen && /*#__PURE__*/jsxRuntime.jsx(Body, {
1554
- as: "span",
1555
- type: exports.Typography.BODY_LARGE,
1556
- className: "np-card__content d-block",
1557
- children: children
1336
+ formatMessage
1337
+ } = reactIntl.useIntl();
1338
+ return /*#__PURE__*/jsxRuntime.jsxs("a", {
1339
+ href: href,
1340
+ target: target,
1341
+ className: classNames__default.default('np-link', type ? `np-text-${type}` : undefined, 'd-inline-flex', className),
1342
+ "aria-label": ariaLabel,
1343
+ rel: isBlank ? 'noreferrer' : undefined,
1344
+ onClick: onClick,
1345
+ ...props,
1346
+ children: [children, " ", isBlank && /*#__PURE__*/jsxRuntime.jsx(icons.NavigateAway, {
1347
+ title: formatMessage(messages$c.opensInNewTab)
1558
1348
  })]
1559
1349
  });
1560
- });
1561
- const hasChildren = ({
1562
- children
1563
- }) => children;
1564
- Card$1.propTypes = {
1565
- 'aria-label': PropTypes__default.default.string,
1566
- as: PropTypes__default.default.string,
1567
- isExpanded: requiredIf__default.default(PropTypes__default.default.bool, hasChildren),
1568
- title: PropTypes__default.default.node.isRequired,
1569
- details: PropTypes__default.default.node.isRequired,
1570
- onClick: requiredIf__default.default(PropTypes__default.default.func, hasChildren),
1571
- icon: PropTypes__default.default.node,
1572
- children: PropTypes__default.default.node,
1573
- id: PropTypes__default.default.string,
1574
- className: PropTypes__default.default.string,
1575
- 'data-testid': PropTypes__default.default.string
1576
- };
1577
- Card$1.defaultProps = {
1578
- 'aria-label': undefined,
1579
- as: 'div',
1580
- children: null,
1581
- id: null,
1582
- className: null,
1583
- 'data-testid': null
1584
1350
  };
1585
- var Card$2 = Card$1;
1586
1351
 
1587
- const CheckboxButton = /*#__PURE__*/React.forwardRef(({
1588
- checked,
1352
+ const DEFAULT_TYPE = exports.Typography.TITLE_GROUP;
1353
+ const titleTypeMapping = {
1354
+ [exports.Typography.TITLE_SCREEN]: 'h1',
1355
+ [exports.Typography.TITLE_SECTION]: 'h2',
1356
+ [exports.Typography.TITLE_SUBSECTION]: 'h3',
1357
+ [exports.Typography.TITLE_BODY]: 'h4',
1358
+ [exports.Typography.TITLE_GROUP]: 'h5'
1359
+ };
1360
+ function Title({
1361
+ as,
1362
+ type = DEFAULT_TYPE,
1589
1363
  className,
1590
- disabled,
1591
- onChange,
1592
- ...rest
1593
- }, reference) => /*#__PURE__*/jsxRuntime.jsxs("span", {
1594
- className: classNames__default.default('np-checkbox-button', className, disabled && 'disabled'),
1595
- children: [/*#__PURE__*/jsxRuntime.jsx("input", {
1596
- ...rest,
1597
- ref: reference,
1598
- type: "checkbox",
1599
- disabled: disabled,
1600
- checked: checked,
1601
- onChange: onChange
1602
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
1603
- className: "tw-checkbox-button",
1604
- children: /*#__PURE__*/jsxRuntime.jsx("span", {
1605
- className: "tw-checkbox-check"
1606
- })
1607
- })]
1608
- }));
1609
- var CheckboxButton$1 = CheckboxButton;
1364
+ ...props
1365
+ }) {
1366
+ const mapping = titleTypeMapping[type];
1367
+ const isTypeSupported = mapping !== undefined;
1368
+ if (isTypeSupported) {
1369
+ const HeaderTag = as ?? mapping;
1370
+ return /*#__PURE__*/jsxRuntime.jsx(HeaderTag, {
1371
+ ...props,
1372
+ className: classNames__default.default(`np-text-${type}`, className)
1373
+ });
1374
+ }
1375
+ const HeaderTag = as ?? titleTypeMapping[DEFAULT_TYPE];
1376
+ return /*#__PURE__*/jsxRuntime.jsx(HeaderTag, {
1377
+ ...props,
1378
+ className: classNames__default.default(`np-text-${DEFAULT_TYPE}`, className)
1379
+ });
1380
+ }
1610
1381
 
1611
- const Checkbox = ({
1612
- id,
1613
- checked,
1614
- required,
1615
- disabled,
1616
- readOnly,
1617
- label,
1618
- className,
1619
- secondary,
1620
- onChange,
1621
- onFocus,
1622
- onBlur
1382
+ const HeaderAction = ({
1383
+ action
1623
1384
  }) => {
1624
1385
  const {
1625
1386
  isModern
1626
1387
  } = componentsTheming.useTheme();
1627
- const classList = classNames__default.default('np-checkbox', {
1628
- checkbox: true,
1629
- 'checkbox-lg': secondary,
1630
- disabled: isModern && disabled
1631
- }, className);
1632
- const innerDisabled = disabled || readOnly;
1633
- return /*#__PURE__*/jsxRuntime.jsx("div", {
1634
- id: id,
1635
- className: classList,
1636
- children: /*#__PURE__*/jsxRuntime.jsxs("label", {
1637
- className: classNames__default.default({
1638
- disabled
1639
- }),
1640
- children: [/*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
1641
- className: "p-r-2",
1642
- checked: checked,
1643
- disabled: innerDisabled,
1644
- required: !innerDisabled && required,
1645
- onFocus: onFocus,
1646
- onChange: () => onChange(!checked),
1647
- onBlur: onBlur
1648
- }), /*#__PURE__*/jsxRuntime.jsxs(Body, {
1649
- as: "span",
1650
- className: "np-checkbox__text",
1651
- type: secondary ? exports.Typography.BODY_LARGE_BOLD : exports.Typography.BODY_LARGE,
1652
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1653
- className: required ? 'has-required' : undefined,
1654
- children: label
1655
- }), secondary && /*#__PURE__*/jsxRuntime.jsx(Body, {
1656
- as: "span",
1657
- className: classNames__default.default({
1658
- secondary: !isModern
1659
- }),
1660
- children: secondary
1661
- })]
1662
- })]
1663
- })
1388
+ const props = {
1389
+ 'aria-label': action['aria-label']
1390
+ };
1391
+ if ('href' in action) {
1392
+ return /*#__PURE__*/jsxRuntime.jsx(Link, {
1393
+ href: action.href,
1394
+ target: action.target,
1395
+ onClick: action.onClick,
1396
+ ...props,
1397
+ children: action.text
1398
+ });
1399
+ }
1400
+ return isModern ? /*#__PURE__*/jsxRuntime.jsx(Button, {
1401
+ className: "np-header__button",
1402
+ priority: "tertiary",
1403
+ size: "sm",
1404
+ onClick: action.onClick,
1405
+ ...props,
1406
+ children: action.text
1407
+ }) : /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
1408
+ onClick: action.onClick,
1409
+ ...props,
1410
+ children: action.text
1664
1411
  });
1665
1412
  };
1666
- Checkbox.propTypes = {
1667
- id: PropTypes__default.default.string,
1668
- checked: PropTypes__default.default.bool,
1669
- required: PropTypes__default.default.bool,
1670
- disabled: PropTypes__default.default.bool,
1671
- readOnly: PropTypes__default.default.bool,
1672
- label: PropTypes__default.default.node.isRequired,
1673
- secondary: PropTypes__default.default.string,
1674
- onFocus: PropTypes__default.default.func,
1675
- onChange: PropTypes__default.default.func.isRequired,
1676
- onBlur: PropTypes__default.default.func,
1677
- className: PropTypes__default.default.string
1678
- };
1679
- Checkbox.defaultProps = {
1680
- id: null,
1681
- checked: false,
1682
- required: false,
1683
- disabled: false,
1684
- readOnly: false,
1685
- secondary: null,
1686
- onFocus: null,
1687
- onBlur: null,
1688
- className: undefined
1689
- };
1690
-
1691
- const CheckboxOption = /*#__PURE__*/React.forwardRef(({
1692
- checked,
1693
- disabled,
1694
- onChange,
1695
- ...rest
1696
- }, reference) => {
1697
- return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1698
- ...rest,
1699
- ref: reference,
1700
- disabled: disabled,
1701
- button: /*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
1702
- checked: checked,
1703
- disabled: disabled,
1704
- onChange: () => onChange?.(!checked)
1705
- })
1413
+ /**
1414
+ *
1415
+ * Neptune Web: https://transferwise.github.io/neptune-web/components/content/Header
1416
+ *
1417
+ */
1418
+ const Header = ({
1419
+ action,
1420
+ as = 'h5',
1421
+ title,
1422
+ className
1423
+ }) => {
1424
+ if (!action) {
1425
+ return /*#__PURE__*/jsxRuntime.jsx(Title, {
1426
+ as: as,
1427
+ type: exports.Typography.TITLE_GROUP,
1428
+ className: classNames__default.default('np-header', 'np-header__title', className),
1429
+ children: title
1430
+ });
1431
+ }
1432
+ if (as === 'legend') {
1433
+ // eslint-disable-next-line no-console
1434
+ console.warn('Legends should be the first child in a fieldset, and this is not possible when including an action');
1435
+ }
1436
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
1437
+ className: classNames__default.default('np-header', className),
1438
+ children: [/*#__PURE__*/jsxRuntime.jsx(Title, {
1439
+ as: as,
1440
+ type: exports.Typography.TITLE_GROUP,
1441
+ className: "np-header__title",
1442
+ children: title
1443
+ }), /*#__PURE__*/jsxRuntime.jsx(HeaderAction, {
1444
+ action: action
1445
+ })]
1706
1446
  });
1707
- });
1447
+ };
1708
1448
 
1709
- const Chip = ({
1710
- label,
1711
- value,
1712
- onRemove,
1713
- onClick,
1714
- onKeyPress,
1715
- className = undefined,
1716
- 'aria-label': ariaLabel,
1717
- 'aria-checked': ariaChecked,
1718
- role,
1719
- closeButton
1449
+ const useConditionalListener = ({
1450
+ attachListener,
1451
+ callback,
1452
+ eventType,
1453
+ parent
1720
1454
  }) => {
1721
- const isActionable = onClick || onKeyPress;
1722
- const defaultRole = isActionable ? 'button' : undefined;
1723
- const tabIndex = isActionable ? 0 : -1;
1724
- const {
1725
- isModern
1726
- } = componentsTheming.useTheme();
1727
- const closeButtonReference = React.useRef(null);
1728
- const previousCloseButtonShown = React.useRef();
1729
1455
  React.useEffect(() => {
1730
- if (closeButtonReference.current != null && previousCloseButtonShown.current === false) {
1731
- closeButtonReference.current?.focus();
1456
+ if (attachListener && !neptuneValidation.isUndefined(parent)) {
1457
+ parent.addEventListener(eventType, callback, true);
1732
1458
  }
1733
- previousCloseButtonShown.current = closeButtonReference.current != null;
1734
- }, [onRemove]);
1735
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
1736
- role: role ?? defaultRole,
1737
- tabIndex: tabIndex,
1738
- "aria-label": ariaLabel,
1739
- "aria-checked": ariaChecked,
1740
- className: classNames__default.default('np-chip', 'd-flex', 'align-items-center', 'justify-content-between', onRemove ? 'np-chip--removable' : '', className),
1741
- ...(isActionable && {
1742
- onClick,
1743
- onKeyPress
1744
- }),
1745
- children: [isModern ? /*#__PURE__*/jsxRuntime.jsx(Body, {
1746
- "aria-hidden": !!onRemove,
1747
- type: exports.Typography.BODY_DEFAULT_BOLD,
1748
- children: label
1749
- }) : /*#__PURE__*/jsxRuntime.jsx("span", {
1750
- "aria-hidden": "false",
1751
- className: "np-chip-label",
1752
- children: label
1753
- }), onRemove ? /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1754
- ref: closeButtonReference,
1755
- className: isModern ? `btn-unstyled` : `btn-unstyled m-l-1`,
1756
- "aria-label": closeButton && closeButton['aria-label'],
1757
- size: "sm",
1758
- filled: isModern,
1759
- onClick: onRemove
1760
- }) : null]
1761
- }, value);
1459
+ return () => {
1460
+ if (!neptuneValidation.isUndefined(parent)) {
1461
+ parent.removeEventListener(eventType, callback, true);
1462
+ }
1463
+ };
1464
+ }, [attachListener, callback, eventType, parent]);
1762
1465
  };
1763
1466
 
1764
- var messages$a = reactIntl.defineMessages({
1765
- ariaLabel: {
1766
- id: "neptune.Chips.ariaLabel"
1767
- }
1768
- });
1769
-
1770
- const Chips = ({
1771
- chips,
1772
- onChange,
1773
- selected,
1774
- 'aria-label': ariaLabel,
1775
- className,
1776
- multiple
1467
+ const DirectionContext = /*#__PURE__*/React.createContext(exports.Direction.LTR);
1468
+ const DirectionProvider = ({
1469
+ direction,
1470
+ children
1777
1471
  }) => {
1778
- const intl = reactIntl.useIntl();
1779
- const isSelected = value => Array.isArray(selected) ? selected.includes(value) : selected === value;
1780
- const handleOnChange = (selectedValue, isCurrentlyEnabled) => {
1781
- onChange({
1782
- isEnabled: !isCurrentlyEnabled,
1783
- selectedValue
1784
- });
1785
- };
1786
- return /*#__PURE__*/jsxRuntime.jsx("div", {
1787
- className: classNames__default.default('np-chips d-flex', className),
1788
- "aria-label": ariaLabel,
1789
- role: !multiple ? 'radiogroup' : undefined,
1790
- children: chips.map(chip => {
1791
- const chipSelected = isSelected(chip.value);
1792
- return /*#__PURE__*/jsxRuntime.jsx(Chip, {
1793
- value: chip.value,
1794
- label: chip.label,
1795
- closeButton: {
1796
- 'aria-label': intl.formatMessage(messages$a.ariaLabel, {
1797
- choice: chip.label
1798
- })
1799
- },
1800
- className: classNames__default.default('text-xs-nowrap', {
1801
- 'np-chip--selected': chipSelected,
1802
- 'p-r-1': multiple && chipSelected
1803
- }),
1804
- ...(multiple && chipSelected ? {
1805
- onRemove: () => handleOnChange(chip.value, chipSelected),
1806
- 'aria-label': chip.label
1807
- } : {
1808
- onClick: () => handleOnChange(chip.value, chipSelected),
1809
- onKeyPress: () => handleOnChange(chip.value, chipSelected),
1810
- role: !multiple ? 'radio' : undefined,
1811
- 'aria-checked': chipSelected
1812
- })
1813
- }, chip.value);
1814
- })
1472
+ return /*#__PURE__*/jsxRuntime.jsx(DirectionContext.Provider, {
1473
+ value: direction,
1474
+ children: children
1815
1475
  });
1816
1476
  };
1817
1477
 
1818
- const CircularButton = ({
1819
- className,
1820
- children,
1821
- disabled,
1822
- icon,
1823
- priority = exports.Priority.PRIMARY,
1824
- type = exports.ControlType.ACCENT,
1825
- ...rest
1826
- }) => {
1827
- const classes = classNames__default.default('btn np-btn', typeClassMap[type], priorityClassMap[priority]);
1828
- const iconElement = Number(icon.props.size) !== 24 ? /*#__PURE__*/React.cloneElement(icon, {
1829
- size: 24
1830
- }) : icon;
1831
- return /*#__PURE__*/jsxRuntime.jsxs("label", {
1832
- className: classNames__default.default('np-circular-btn', priority, type, disabled && 'disabled', className),
1833
- children: [/*#__PURE__*/jsxRuntime.jsx("input", {
1834
- type: "button",
1835
- "aria-label": children,
1836
- className: classes,
1837
- disabled: disabled,
1838
- ...rest
1839
- }), iconElement, /*#__PURE__*/jsxRuntime.jsx(Body, {
1840
- as: "span",
1841
- className: "np-circular-btn__label",
1842
- type: exports.Typography.BODY_DEFAULT_BOLD,
1843
- children: children
1844
- })]
1845
- });
1478
+ const useDirection = () => {
1479
+ const direction = React.useContext(DirectionContext);
1480
+ return {
1481
+ direction,
1482
+ isRTL: direction === 'rtl'
1483
+ };
1846
1484
  };
1847
1485
 
1848
- const FocusBoundary = ({
1849
- children
1486
+ const ObserverParams = {
1487
+ threshold: 0.1
1488
+ };
1489
+
1490
+ /**
1491
+ * useHasIntersected.
1492
+ * Use this custom hook to detect when an element has became visible inside the viewport. This hook checks only if the intersection happend.
1493
+ * Once the intersection has happened the hook will not return false even if the element gets out of the viewport.
1494
+ *
1495
+ * @param elRef.elRef
1496
+ * @param {object} [elRef] - node object that contains a react reference to the element that needs to be observed.
1497
+ * @param {strimng} [loading = 'eager'] - string that contains the type of loading.
1498
+ * @param elRef.loading
1499
+ * @usage `const [hasIntersected] = useHasIntersected({imageRef,loading});`
1500
+ */
1501
+ const useHasIntersected = ({
1502
+ elRef,
1503
+ loading
1850
1504
  }) => {
1851
- const wrapperReference = React.useRef(null);
1852
- React.useEffect(() => {
1853
- wrapperReference.current?.focus({
1854
- preventScroll: true
1505
+ const [hasIntersected, setHasIntersected] = React.useState(false);
1506
+ const {
1507
+ current
1508
+ } = elRef || {};
1509
+ const isValidReference = () => {
1510
+ return elRef && current;
1511
+ };
1512
+ const handleOnIntersect = (entries, observer) => {
1513
+ entries.forEach(entry => {
1514
+ if (entry.isIntersecting) {
1515
+ setHasIntersected(true);
1516
+ observer.unobserve(current);
1517
+ }
1855
1518
  });
1856
- }, []);
1857
- return /*#__PURE__*/jsxRuntime.jsx(focus.FocusScope, {
1858
- contain: true,
1859
- restoreFocus: true,
1860
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
1861
- ref: wrapperReference,
1862
- tabIndex: -1,
1863
- children: children
1864
- })
1865
- });
1519
+ };
1520
+ React.useEffect(() => {
1521
+ let observer;
1522
+ let didCancel = false;
1523
+
1524
+ // Check if window is define for SSR and Old browsers fallback
1525
+ if (typeof window === 'undefined' || !window.IntersectionObserver || !isValidReference()) {
1526
+ setHasIntersected(true);
1527
+ } else if (!didCancel) {
1528
+ observer = new IntersectionObserver(handleOnIntersect, ObserverParams);
1529
+ observer.observe(current);
1530
+ }
1531
+ return () => {
1532
+ didCancel = true;
1533
+ if (observer) {
1534
+ observer.unobserve(current);
1535
+ }
1536
+ };
1537
+ }, [elRef]);
1538
+ if (loading === 'eager') {
1539
+ return [false];
1540
+ }
1541
+ return [hasIntersected];
1866
1542
  };
1867
1543
 
1868
- function withNextPortalWrapper(Component) {
1869
- return function (props) {
1870
- const [mounted, setMounted] = React.useState(false);
1871
- React.useEffect(() => {
1872
- setMounted(true);
1873
- }, [setMounted]);
1874
- return mounted ? /*#__PURE__*/reactDom.createPortal( /*#__PURE__*/jsxRuntime.jsx(Component, {
1875
- ...props
1876
- }), document.body) : null;
1877
- };
1544
+ // eslint-disable-next-line import/extensions
1545
+ function useMedia(query) {
1546
+ return index_js.useSyncExternalStore(onStoreChange => {
1547
+ const mediaQueryList = window.matchMedia(query);
1548
+ mediaQueryList.addEventListener('change', onStoreChange);
1549
+ return () => {
1550
+ mediaQueryList.removeEventListener('change', onStoreChange);
1551
+ };
1552
+ }, () => typeof window !== 'undefined' ? window.matchMedia(query).matches : undefined, () => undefined);
1553
+ }
1554
+
1555
+ function useScreenSize(size) {
1556
+ return useMedia(`(min-width: ${size}px)`);
1878
1557
  }
1879
1558
 
1880
1559
  /**
1881
- * Dimmer state management inspired by Material UI's ModalManager (https://github.com/mui-org/material-ui)
1560
+ * @deprecated Prefer `useScreenSize` instead.
1882
1561
  */
1883
- class DimmerManager {
1884
- /**
1885
- * Dimmer refs
1886
- */
1887
- dimmers;
1888
- constructor() {
1889
- this.dimmers = [];
1890
- }
1891
- add(dimmer) {
1892
- let dimmerIndex = this.dimmers.indexOf(dimmer);
1893
- if (dimmerIndex !== -1) {
1894
- return dimmerIndex;
1895
- }
1896
- dimmerIndex = this.dimmers.length;
1897
- this.dimmers.push(dimmer);
1898
- return dimmerIndex;
1899
- }
1900
- remove(dimmer) {
1901
- const dimmerIndex = this.dimmers.indexOf(dimmer);
1902
- if (dimmerIndex !== -1) {
1903
- this.dimmers.splice(dimmerIndex, 1);
1904
- }
1905
- return dimmerIndex;
1906
- }
1907
- isTop(dimmer) {
1908
- return this.dimmers.length > 0 && this.dimmers[this.dimmers.length - 1] === dimmer;
1909
- }
1910
- }
1562
+ const useLayout = () => {
1563
+ const screenXs = useScreenSize(exports.Breakpoint.EXTRA_SMALL);
1564
+ const screenSm = useScreenSize(exports.Breakpoint.SMALL);
1565
+ const screenMd = useScreenSize(exports.Breakpoint.MEDIUM);
1566
+ const screenLg = useScreenSize(exports.Breakpoint.LARGE);
1567
+ const screenXl = useScreenSize(exports.Breakpoint.EXTRA_LARGE);
1568
+ return {
1569
+ isMobile: screenSm != null ? !screenSm : undefined,
1570
+ isExtraSmall: screenXs,
1571
+ isSmall: screenSm,
1572
+ isMedium: screenMd,
1573
+ isLarge: screenLg,
1574
+ isExtraLarge: screenXl
1575
+ };
1576
+ };
1911
1577
 
1912
- const EXIT_ANIMATION$1 = 350;
1913
- const dimmerManager = new DimmerManager();
1914
- const handleTouchMove = event => {
1915
- const isTouchedElementDimmer = event.target.classList.contains('dimmer');
1916
- // disable scroll on iOS devices for Dimmer area
1917
- // this is because of bug in WebKit https://bugs.webkit.org/show_bug.cgi?id=220908
1918
- // note: scrolling still works for children(s) as expected
1919
- if (isIosDevice() && isTouchedElementDimmer) {
1920
- event.stopPropagation();
1921
- event.preventDefault();
1578
+ var messages$b = reactIntl.defineMessages({
1579
+ ariaLabel: {
1580
+ id: "neptune.CloseButton.ariaLabel"
1922
1581
  }
1923
- };
1924
- const Dimmer = ({
1582
+ });
1583
+
1584
+ const CloseButton = /*#__PURE__*/React.forwardRef(function CloseButton({
1585
+ 'aria-label': ariaLabel,
1586
+ size = exports.Size.MEDIUM,
1587
+ filled = false,
1588
+ className,
1589
+ onClick,
1590
+ isDisabled,
1591
+ testId
1592
+ }, reference) {
1593
+ const intl = reactIntl.useIntl();
1594
+ ariaLabel ??= intl.formatMessage(messages$b.ariaLabel);
1595
+ const Icon = filled ? icons.CrossCircleFill : icons.Cross;
1596
+ return /*#__PURE__*/jsxRuntime.jsx("button", {
1597
+ ref: reference,
1598
+ type: "button",
1599
+ className: classNames__default.default('np-close-button', 'close btn-link', 'text-no-decoration', {
1600
+ 'np-close-button--large': size === exports.Size.MEDIUM,
1601
+ 'np-close-button--x-large': size === exports.Size.LARGE
1602
+ }, className),
1603
+ "aria-label": ariaLabel,
1604
+ "aria-disabled": isDisabled,
1605
+ disabled: isDisabled,
1606
+ "data-testid": testId,
1607
+ onClick: onClick,
1608
+ children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
1609
+ size: size === exports.Size.SMALL ? 16 : 24
1610
+ })
1611
+ });
1612
+ });
1613
+
1614
+ const EXIT_ANIMATION = 350;
1615
+ const SlidingPanel = /*#__PURE__*/React.forwardRef(({
1616
+ position = 'left',
1617
+ open,
1618
+ showSlidingPanelBorder,
1619
+ slidingPanelPositionFixed,
1620
+ className,
1621
+ children,
1622
+ ...rest
1623
+ }, reference) => {
1624
+ const localReference = React.useRef(null);
1625
+ React.useImperativeHandle(reference, () => localReference.current, []);
1626
+ return /*#__PURE__*/React.createElement(reactTransitionGroup.CSSTransition, {
1627
+ ...rest,
1628
+ key: `sliding-panel--open-${position}`,
1629
+ nodeRef: localReference,
1630
+ in: open
1631
+ // Wait for animation to finish before unmount.
1632
+ ,
1633
+ timeout: {
1634
+ enter: 0,
1635
+ exit: EXIT_ANIMATION
1636
+ },
1637
+ classNames: "sliding-panel",
1638
+ appear: true,
1639
+ unmountOnExit: true
1640
+ }, /*#__PURE__*/jsxRuntime.jsx("div", {
1641
+ ref: localReference,
1642
+ className: classNames__default.default('sliding-panel', `sliding-panel--open-${position}`, showSlidingPanelBorder && `sliding-panel--border-${position}`, slidingPanelPositionFixed && 'sliding-panel--fixed', className),
1643
+ children: children
1644
+ }));
1645
+ });
1646
+
1647
+ const Drawer = ({
1925
1648
  children,
1926
1649
  className,
1927
- disableClickToClose = false,
1928
- contentPosition,
1929
- fadeContentOnEnter = false,
1930
- fadeContentOnExit = false,
1931
- open = false,
1932
- scrollable = false,
1933
- transparent = false,
1934
- onClose
1650
+ footerContent,
1651
+ headerTitle,
1652
+ onClose,
1653
+ open,
1654
+ position
1935
1655
  }) => {
1936
- const [hasNotExited, setHasNotExited] = React.useState(false);
1937
- const dimmerReference = React.useRef(null);
1938
- const closeOnClick = event => {
1939
- if (event.target === dimmerReference.current) {
1940
- onClose?.(event);
1941
- }
1942
- };
1943
- const handleClick = event => {
1944
- if (disableClickToClose || !onClose) {
1945
- return;
1946
- }
1947
- closeOnClick(event);
1948
- };
1949
- const handleKeyDown = React.useCallback(event => {
1950
- if (event.key !== 'Escape') {
1951
- return;
1952
- }
1953
- event.stopPropagation();
1954
- if (onClose && dimmerReference.current && dimmerManager.isTop(dimmerReference.current)) {
1955
- onClose(event);
1956
- }
1957
- }, [onClose]);
1958
- const onEnter = () => {
1959
- setHasNotExited(true);
1960
- if (dimmerReference.current) {
1961
- dimmerManager.add(dimmerReference.current);
1962
- }
1963
- };
1964
- const onExited = () => {
1965
- setHasNotExited(false);
1966
- if (dimmerReference.current) {
1967
- dimmerManager.remove(dimmerReference.current);
1968
- }
1969
- };
1970
- React.useEffect(() => {
1971
- const localReferenceCopy = dimmerReference.current;
1972
- if (open) {
1973
- document.addEventListener('keydown', handleKeyDown);
1974
- localReferenceCopy?.addEventListener('touchmove', handleTouchMove, {
1975
- passive: true
1976
- });
1977
- }
1978
- return () => {
1979
- document.removeEventListener('keydown', handleKeyDown);
1980
- localReferenceCopy?.removeEventListener('touchmove', handleTouchMove);
1981
- };
1982
- }, [handleKeyDown, open]);
1983
- return /*#__PURE__*/jsxRuntime.jsx(DimmerWrapper, {
1656
+ logActionRequiredIf('Drawer now expects `onClose`, and will soon make this prop required. Please update your usage to provide it.', !onClose);
1657
+ const {
1658
+ isMobile
1659
+ } = useLayout();
1660
+ const titleId = reactId.useId();
1661
+ return /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
1984
1662
  open: open,
1985
- hasNotExited: hasNotExited,
1986
- children: /*#__PURE__*/jsxRuntime.jsx(reactTransitionGroup.CSSTransition, {
1987
- nodeRef: dimmerReference,
1988
- in: open,
1989
- appear: true
1990
- // Wait for animation to finish before unmount.
1991
- ,
1992
- timeout: {
1993
- enter: 0,
1994
- exit: EXIT_ANIMATION$1
1995
- },
1996
- classNames: {
1997
- enter: classNames__default.default({
1998
- 'dimmer--enter-fade': fadeContentOnEnter
1999
- }),
2000
- enterDone: classNames__default.default('dimmer--enter-done', {
2001
- 'dimmer--enter-fade': fadeContentOnEnter
2002
- }),
2003
- exit: classNames__default.default('dimmer--exit', {
2004
- 'dimmer--exit-fade': fadeContentOnExit
2005
- })
2006
- },
2007
- unmountOnExit: true,
2008
- onEnter: onEnter,
2009
- onExited: onExited,
2010
- children: /*#__PURE__*/jsxRuntime.jsx(DimmerContentWrapper, {
2011
- scrollBody: !transparent,
2012
- children: /*#__PURE__*/jsxRuntime.jsx(FocusBoundary, {
2013
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
2014
- ref: dimmerReference,
2015
- className: classNames__default.default('dimmer', {
2016
- 'dimmer--scrollable': scrollable,
2017
- 'dimmer--transparent': transparent
2018
- }, className),
2019
- role: "presentation",
2020
- onClick: handleClick,
2021
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
2022
- className: classNames__default.default('dimmer-content-positioner', contentPosition != null && ['d-flex justify-content-center', {
2023
- 'align-items-start': contentPosition === 'top',
2024
- 'align-items-center': contentPosition === 'center',
2025
- 'align-items-end': contentPosition === 'bottom'
2026
- }]),
2027
- children: children
2028
- })
2029
- })
2030
- })
1663
+ onClose: onClose,
1664
+ children: /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
1665
+ open: open,
1666
+ position: isMobile ? exports.Position.BOTTOM : position,
1667
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
1668
+ role: "dialog",
1669
+ "aria-modal": true,
1670
+ "aria-labelledby": headerTitle ? titleId : undefined,
1671
+ className: classNames__default.default('np-drawer', className),
1672
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1673
+ className: classNames__default.default('np-drawer-header', {
1674
+ 'np-drawer-header--withborder': headerTitle
1675
+ }),
1676
+ children: [headerTitle && /*#__PURE__*/jsxRuntime.jsx(Title, {
1677
+ id: titleId,
1678
+ type: exports.Typography.TITLE_BODY,
1679
+ children: headerTitle
1680
+ }), /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1681
+ onClick: onClose
1682
+ })]
1683
+ }), children && /*#__PURE__*/jsxRuntime.jsx("div", {
1684
+ className: classNames__default.default('np-drawer-content'),
1685
+ children: children
1686
+ }), footerContent && /*#__PURE__*/jsxRuntime.jsx("div", {
1687
+ className: classNames__default.default('np-drawer-footer'),
1688
+ children: footerContent
1689
+ })]
2031
1690
  })
2032
1691
  })
2033
1692
  });
2034
1693
  };
2035
- const DimmerWrapper = ({
2036
- open,
2037
- hasNotExited,
2038
- children
2039
- }) => {
2040
- const {
2041
- screenMode,
2042
- theme
2043
- } = componentsTheming.useTheme();
2044
- return open || hasNotExited ? /*#__PURE__*/jsxRuntime.jsx(componentsTheming.ThemeProvider, {
2045
- theme: "personal",
2046
- screenMode: theme === 'personal' ? screenMode : 'light',
2047
- isNotRootProvider: true,
2048
- children: children
2049
- }) : /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
2050
- children: children
2051
- });
2052
- };
2053
- const DimmerContentWrapper = ({
2054
- children,
2055
- scrollBody
2056
- }) => {
2057
- React.useEffect(() => {
2058
- if (scrollBody) {
2059
- addNoScrollClass();
2060
- }
2061
- return () => {
2062
- if (scrollBody) {
2063
- removeNoScrollClass();
2064
- }
2065
- };
2066
- }, [scrollBody]);
2067
- return children;
2068
- };
2069
- var Dimmer$1 = withNextPortalWrapper(Dimmer);
2070
-
2071
- const useConditionalListener = ({
2072
- attachListener,
2073
- callback,
2074
- eventType,
2075
- parent
2076
- }) => {
2077
- React.useEffect(() => {
2078
- if (attachListener && !neptuneValidation.isUndefined(parent)) {
2079
- parent.addEventListener(eventType, callback, true);
2080
- }
2081
- return () => {
2082
- if (!neptuneValidation.isUndefined(parent)) {
2083
- parent.removeEventListener(eventType, callback, true);
2084
- }
2085
- };
2086
- }, [attachListener, callback, eventType, parent]);
2087
- };
2088
-
2089
- const DirectionContext = /*#__PURE__*/React.createContext(exports.Direction.LTR);
2090
- const DirectionProvider = ({
2091
- direction,
2092
- children
2093
- }) => {
2094
- return /*#__PURE__*/jsxRuntime.jsx(DirectionContext.Provider, {
2095
- value: direction,
2096
- children: children
2097
- });
2098
- };
2099
-
2100
- const useDirection = () => {
2101
- const direction = React.useContext(DirectionContext);
2102
- return {
2103
- direction,
2104
- isRTL: direction === 'rtl'
2105
- };
1694
+ Drawer.propTypes = {
1695
+ /** The content to appear in the drawer body. */
1696
+ children: PropTypes__default.default.node,
1697
+ className: PropTypes__default.default.string,
1698
+ /** The content to appear in the drawer footer. */
1699
+ footerContent: PropTypes__default.default.node,
1700
+ /** The content to appear in the drawer header. */
1701
+ headerTitle: PropTypes__default.default.node,
1702
+ /** The action to perform on close click. */
1703
+ onClose: PropTypes__default.default.func,
1704
+ /** The status of Drawer either open or not. */
1705
+ open: PropTypes__default.default.bool,
1706
+ /** The placement of Drawer on the screen either left or right. On mobile it will default to bottom. */
1707
+ position: PropTypes__default.default.oneOf(['left', 'right', 'bottom'])
2106
1708
  };
2107
-
2108
- const ObserverParams = {
2109
- threshold: 0.1
1709
+ Drawer.defaultProps = {
1710
+ children: null,
1711
+ className: undefined,
1712
+ footerContent: null,
1713
+ headerTitle: null,
1714
+ onClose: null,
1715
+ open: false,
1716
+ position: exports.Position.RIGHT
2110
1717
  };
1718
+ var Drawer$1 = Drawer;
2111
1719
 
1720
+ const INITIAL_Y_POSITION = 0;
1721
+ const CONTENT_SCROLL_THRESHOLD = 1;
1722
+ const MOVE_OFFSET_THRESHOLD = 50;
2112
1723
  /**
2113
- * useHasIntersected.
2114
- * Use this custom hook to detect when an element has became visible inside the viewport. This hook checks only if the intersection happend.
2115
- * Once the intersection has happened the hook will not return false even if the element gets out of the viewport.
2116
- *
2117
- * @param elRef.elRef
2118
- * @param {object} [elRef] - node object that contains a react reference to the element that needs to be observed.
2119
- * @param {strimng} [loading = 'eager'] - string that contains the type of loading.
2120
- * @param elRef.loading
2121
- * @usage `const [hasIntersected] = useHasIntersected({imageRef,loading});`
2122
- */
2123
- const useHasIntersected = ({
2124
- elRef,
2125
- loading
2126
- }) => {
2127
- const [hasIntersected, setHasIntersected] = React.useState(false);
2128
- const {
2129
- current
2130
- } = elRef || {};
2131
- const isValidReference = () => {
2132
- return elRef && current;
2133
- };
2134
- const handleOnIntersect = (entries, observer) => {
2135
- entries.forEach(entry => {
2136
- if (entry.isIntersecting) {
2137
- setHasIntersected(true);
2138
- observer.unobserve(current);
2139
- }
2140
- });
2141
- };
2142
- React.useEffect(() => {
2143
- let observer;
2144
- let didCancel = false;
2145
-
2146
- // Check if window is define for SSR and Old browsers fallback
2147
- if (typeof window === 'undefined' || !window.IntersectionObserver || !isValidReference()) {
2148
- setHasIntersected(true);
2149
- } else if (!didCancel) {
2150
- observer = new IntersectionObserver(handleOnIntersect, ObserverParams);
2151
- observer.observe(current);
2152
- }
2153
- return () => {
2154
- didCancel = true;
2155
- if (observer) {
2156
- observer.unobserve(current);
2157
- }
2158
- };
2159
- }, [elRef]);
2160
- if (loading === 'eager') {
2161
- return [false];
2162
- }
2163
- return [hasIntersected];
2164
- };
2165
-
2166
- // eslint-disable-next-line import/extensions
2167
- function useMedia(query) {
2168
- return index_js.useSyncExternalStore(onStoreChange => {
2169
- const mediaQueryList = window.matchMedia(query);
2170
- mediaQueryList.addEventListener('change', onStoreChange);
2171
- return () => {
2172
- mediaQueryList.removeEventListener('change', onStoreChange);
2173
- };
2174
- }, () => typeof window !== 'undefined' ? window.matchMedia(query).matches : undefined, () => undefined);
2175
- }
2176
-
2177
- function useScreenSize(size) {
2178
- return useMedia(`(min-width: ${size}px)`);
2179
- }
2180
-
2181
- /**
2182
- * @deprecated Prefer `useScreenSize` instead.
2183
- */
2184
- const useLayout = () => {
2185
- const screenXs = useScreenSize(exports.Breakpoint.EXTRA_SMALL);
2186
- const screenSm = useScreenSize(exports.Breakpoint.SMALL);
2187
- const screenMd = useScreenSize(exports.Breakpoint.MEDIUM);
2188
- const screenLg = useScreenSize(exports.Breakpoint.LARGE);
2189
- const screenXl = useScreenSize(exports.Breakpoint.EXTRA_LARGE);
2190
- return {
2191
- isMobile: screenSm != null ? !screenSm : undefined,
2192
- isExtraSmall: screenXs,
2193
- isSmall: screenSm,
2194
- isMedium: screenMd,
2195
- isLarge: screenLg,
2196
- isExtraLarge: screenXl
2197
- };
2198
- };
2199
-
2200
- const EXIT_ANIMATION = 350;
2201
- const SlidingPanel = /*#__PURE__*/React.forwardRef(({
2202
- position = 'left',
2203
- open,
2204
- showSlidingPanelBorder,
2205
- slidingPanelPositionFixed,
2206
- className,
2207
- children,
2208
- ...rest
2209
- }, reference) => {
2210
- const localReference = React.useRef(null);
2211
- React.useImperativeHandle(reference, () => localReference.current, []);
2212
- return /*#__PURE__*/React.createElement(reactTransitionGroup.CSSTransition, {
2213
- ...rest,
2214
- key: `sliding-panel--open-${position}`,
2215
- nodeRef: localReference,
2216
- in: open
2217
- // Wait for animation to finish before unmount.
2218
- ,
2219
- timeout: {
2220
- enter: 0,
2221
- exit: EXIT_ANIMATION
2222
- },
2223
- classNames: "sliding-panel",
2224
- appear: true,
2225
- unmountOnExit: true
2226
- }, /*#__PURE__*/jsxRuntime.jsx("div", {
2227
- ref: localReference,
2228
- className: classNames__default.default('sliding-panel', `sliding-panel--open-${position}`, showSlidingPanelBorder && `sliding-panel--border-${position}`, slidingPanelPositionFixed && 'sliding-panel--fixed', className),
2229
- children: children
2230
- }));
2231
- });
2232
-
2233
- const Drawer = ({
2234
- children,
2235
- className,
2236
- footerContent,
2237
- headerTitle,
2238
- onClose,
2239
- open,
2240
- position
2241
- }) => {
2242
- logActionRequiredIf('Drawer now expects `onClose`, and will soon make this prop required. Please update your usage to provide it.', !onClose);
2243
- const {
2244
- isMobile
2245
- } = useLayout();
2246
- const titleId = reactId.useId();
2247
- return /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
2248
- open: open,
2249
- onClose: onClose,
2250
- children: /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
2251
- open: open,
2252
- position: isMobile ? exports.Position.BOTTOM : position,
2253
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
2254
- role: "dialog",
2255
- "aria-modal": true,
2256
- "aria-labelledby": headerTitle ? titleId : undefined,
2257
- className: classNames__default.default('np-drawer', className),
2258
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2259
- className: classNames__default.default('np-drawer-header', {
2260
- 'np-drawer-header--withborder': headerTitle
2261
- }),
2262
- children: [headerTitle && /*#__PURE__*/jsxRuntime.jsx(Title, {
2263
- id: titleId,
2264
- type: exports.Typography.TITLE_BODY,
2265
- children: headerTitle
2266
- }), /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2267
- onClick: onClose
2268
- })]
2269
- }), children && /*#__PURE__*/jsxRuntime.jsx("div", {
2270
- className: classNames__default.default('np-drawer-content'),
2271
- children: children
2272
- }), footerContent && /*#__PURE__*/jsxRuntime.jsx("div", {
2273
- className: classNames__default.default('np-drawer-footer'),
2274
- children: footerContent
2275
- })]
2276
- })
2277
- })
2278
- });
2279
- };
2280
- Drawer.propTypes = {
2281
- /** The content to appear in the drawer body. */
2282
- children: PropTypes__default.default.node,
2283
- className: PropTypes__default.default.string,
2284
- /** The content to appear in the drawer footer. */
2285
- footerContent: PropTypes__default.default.node,
2286
- /** The content to appear in the drawer header. */
2287
- headerTitle: PropTypes__default.default.node,
2288
- /** The action to perform on close click. */
2289
- onClose: PropTypes__default.default.func,
2290
- /** The status of Drawer either open or not. */
2291
- open: PropTypes__default.default.bool,
2292
- /** The placement of Drawer on the screen either left or right. On mobile it will default to bottom. */
2293
- position: PropTypes__default.default.oneOf(['left', 'right', 'bottom'])
2294
- };
2295
- Drawer.defaultProps = {
2296
- children: null,
2297
- className: undefined,
2298
- footerContent: null,
2299
- headerTitle: null,
2300
- onClose: null,
2301
- open: false,
2302
- position: exports.Position.RIGHT
2303
- };
2304
- var Drawer$1 = Drawer;
2305
-
2306
- const INITIAL_Y_POSITION = 0;
2307
- const CONTENT_SCROLL_THRESHOLD = 1;
2308
- const MOVE_OFFSET_THRESHOLD = 50;
2309
- /**
2310
- * Neptune: https://transferwise.github.io/neptune/components/bottom-sheet/
2311
- *
2312
- * Neptune Web: https://transferwise.github.io/neptune-web/components/overlays/BottomSheet
1724
+ * Neptune: https://transferwise.github.io/neptune/components/bottom-sheet/
1725
+ *
1726
+ * Neptune Web: https://transferwise.github.io/neptune-web/components/overlays/BottomSheet
2313
1727
  *
2314
1728
  */
2315
1729
  const BottomSheet$1 = props => {
@@ -2476,6 +1890,928 @@ const BottomSheet$1 = props => {
2476
1890
  });
2477
1891
  };
2478
1892
 
1893
+ function SelectOption({
1894
+ selected: selectedValueProp = undefined,
1895
+ ...props
1896
+ }) {
1897
+ const rootRef = React.useRef(null);
1898
+ const [selected, setSelected] = React.useState(selectedValueProp);
1899
+ const [showMenu, setShowMenu] = React.useState(false);
1900
+ function handleOnClick(status) {
1901
+ return () => {
1902
+ console.log('handleOnClick', status);
1903
+ setShowMenu(status);
1904
+ };
1905
+ }
1906
+ function handleOnSelect(data) {
1907
+ return () => {
1908
+ setShowMenu(false);
1909
+ setSelected(data);
1910
+ };
1911
+ }
1912
+ const isSelected = selected !== undefined;
1913
+ const {
1914
+ isMobile
1915
+ } = useLayout();
1916
+ const options = /*#__PURE__*/jsxRuntime.jsxs(Section, {
1917
+ children: [/*#__PURE__*/jsxRuntime.jsx(Header, {
1918
+ title: "Payment Methods"
1919
+ }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1920
+ media: /*#__PURE__*/jsxRuntime.jsx(art.Flag, {
1921
+ code: "gbp"
1922
+ }),
1923
+ title: "Wise GBP balance",
1924
+ content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1925
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1926
+ children: "300 GBP available"
1927
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
1928
+ children: "0 GBP in fees, should arrive in seconds"
1929
+ })]
1930
+ }),
1931
+ onClick: handleOnSelect({
1932
+ media: /*#__PURE__*/jsxRuntime.jsx(art.Flag, {
1933
+ code: "gbp"
1934
+ }),
1935
+ title: 'Wise GBP balance'
1936
+ })
1937
+ }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1938
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1939
+ title: "Credit card",
1940
+ content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1941
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1942
+ children: "Transfer the money to Wise using your bank account."
1943
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
1944
+ children: "0.32 GBP in fees, should arrive in seconds"
1945
+ })]
1946
+ }),
1947
+ onClick: handleOnSelect({
1948
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1949
+ title: 'Credit card',
1950
+ content: 'Pay with your credit card'
1951
+ })
1952
+ }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1953
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1954
+ title: "Debit card",
1955
+ content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1956
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1957
+ children: "Send from your Visa or Mastercard."
1958
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
1959
+ children: "0.74 GBP in fees, should arrive in seconds"
1960
+ })]
1961
+ }),
1962
+ onClick: handleOnSelect({
1963
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1964
+ title: 'Debit card',
1965
+ content: 'Pay with your debit card'
1966
+ })
1967
+ }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1968
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.Bank, {}),
1969
+ title: "Swift Transfer",
1970
+ content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1971
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1972
+ children: "Send money internationally. Your bank will charge you extra fees."
1973
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
1974
+ children: "0.32 GBP in fees, should arrive by Thursday"
1975
+ })]
1976
+ })
1977
+ }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1978
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.BankTransfer, {}),
1979
+ title: "Bank Transfer",
1980
+ content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1981
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1982
+ children: "Transfer the money to Wise using your bank account."
1983
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
1984
+ children: "0.32 GBP in fees, should arrive in seconds"
1985
+ })]
1986
+ })
1987
+ }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1988
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1989
+ title: "Debit card"
1990
+ }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1991
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.Bank, {}),
1992
+ title: "Swift"
1993
+ }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1994
+ media: /*#__PURE__*/jsxRuntime.jsx(icons.BankTransfer, {}),
1995
+ title: "Bank Transfer"
1996
+ })]
1997
+ });
1998
+ return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1999
+ children: [/*#__PURE__*/jsxRuntime.jsx(Option$2, {
2000
+ ref: rootRef,
2001
+ media: isSelected ? selected.media : props.media,
2002
+ title: isSelected ? selected.title : props.title,
2003
+ content: isSelected ? selected.content : props.content,
2004
+ className: classNames__default.default('np-select-option', {
2005
+ 'np-select-option-selected': isSelected
2006
+ }, props.className),
2007
+ button: isSelected ? /*#__PURE__*/jsxRuntime.jsx(Chevron, {}) : /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
2008
+ onClick: handleOnClick(true),
2009
+ children: "Choose"
2010
+ }),
2011
+ onClick: isSelected ? handleOnClick(true) : undefined
2012
+ }), isMobile ? /*#__PURE__*/jsxRuntime.jsx(BottomSheet$1, {
2013
+ open: showMenu,
2014
+ onClose: handleOnClick(false),
2015
+ children: options
2016
+ }) : /*#__PURE__*/jsxRuntime.jsx(Panel, {
2017
+ open: showMenu,
2018
+ flip: false,
2019
+ altAxis: true,
2020
+ anchorRef: rootRef,
2021
+ anchorWidth: false,
2022
+ position: exports.Position.BOTTOM,
2023
+ onClose: handleOnClick(false),
2024
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
2025
+ className: "np-select-option-list p-a-2",
2026
+ children: options
2027
+ })
2028
+ })]
2029
+ });
2030
+ }
2031
+
2032
+ const iconTypeMap = {
2033
+ positive: icons.Check,
2034
+ neutral: icons.Info,
2035
+ warning: icons.Alert,
2036
+ negative: icons.Cross,
2037
+ pending: icons.ClockBorderless,
2038
+ info: icons.Info,
2039
+ error: icons.Cross,
2040
+ success: icons.Check
2041
+ };
2042
+ const StatusIcon = ({
2043
+ sentiment = 'neutral',
2044
+ size = 'md'
2045
+ }) => {
2046
+ const Icon = iconTypeMap[sentiment];
2047
+ const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
2048
+ return /*#__PURE__*/jsxRuntime.jsx("span", {
2049
+ "data-testid": "status-icon",
2050
+ className: classNames__default.default('status-circle', 'status-circle-' + size, sentiment),
2051
+ children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
2052
+ className: classNames__default.default('status-icon', iconColor)
2053
+ })
2054
+ });
2055
+ };
2056
+
2057
+ const reader = new commonmark__default.default.Parser();
2058
+ const writer = new commonmark__default.default.HtmlRenderer({
2059
+ safe: true
2060
+ });
2061
+ const NODE_TYPE_LIST = Object.values(exports.MarkdownNodeType);
2062
+ function Markdown({
2063
+ as: Element = 'div',
2064
+ allowList,
2065
+ blockList,
2066
+ config,
2067
+ className,
2068
+ children
2069
+ }) {
2070
+ if (!children) {
2071
+ return null;
2072
+ }
2073
+ const linkTarget = config?.link?.target ?? '_self';
2074
+ const paragraphClass = config?.paragraph?.className ?? '';
2075
+ if (allowList != null && blockList != null) {
2076
+ logActionRequired('Markdown supports only one of `allowList` or `blockList` to be used at a time. `blockList` will be ignored.');
2077
+ }
2078
+ const parser = nodes => {
2079
+ const parsed = reader.parse(nodes);
2080
+ const toExclude = allowList != null ? NODE_TYPE_LIST.filter(type => !allowList.includes(type)) : blockList;
2081
+ return toExclude != null ? stripNodes({
2082
+ parsed,
2083
+ blockList: toExclude
2084
+ }) : parsed;
2085
+ };
2086
+ const createMarkup = () => {
2087
+ const parsed = parser(children);
2088
+ return writer.render(parsed).replace(/<a href="/g, `<a target="${linkTarget}" href="`).replace(/<p>/g, `<p class="${paragraphClass}">`);
2089
+ };
2090
+ return /*#__PURE__*/jsxRuntime.jsx(Element, {
2091
+ className: className,
2092
+ dangerouslySetInnerHTML: {
2093
+ __html: createMarkup()
2094
+ }
2095
+ });
2096
+ }
2097
+ function stripNodes({
2098
+ blockList,
2099
+ parsed
2100
+ }) {
2101
+ if (!parsed) {
2102
+ return parsed;
2103
+ }
2104
+ const walker = parsed.walker();
2105
+ for (let event = walker.next(); event != null; event = walker.next()) {
2106
+ const {
2107
+ node
2108
+ } = event;
2109
+ if (blockList.includes(node.type) && !event.entering) {
2110
+ while (node.firstChild != null) {
2111
+ node.insertBefore(node.firstChild);
2112
+ }
2113
+ node.unlink();
2114
+ }
2115
+ }
2116
+ return parsed;
2117
+ }
2118
+
2119
+ const allowList = [exports.MarkdownNodeType.STRONG];
2120
+ const InlineMarkdown = props => {
2121
+ return /*#__PURE__*/jsxRuntime.jsx(Markdown, {
2122
+ ...props,
2123
+ as: "span",
2124
+ allowList: allowList,
2125
+ blockList: undefined
2126
+ });
2127
+ };
2128
+ InlineMarkdown.propTypes = {
2129
+ children: PropTypes__default.default.string.isRequired,
2130
+ className: PropTypes__default.default.string
2131
+ };
2132
+ InlineMarkdown.defaultProps = {
2133
+ className: undefined
2134
+ };
2135
+
2136
+ exports.AlertArrowPosition = void 0;
2137
+ (function (AlertArrowPosition) {
2138
+ AlertArrowPosition["TOP_LEFT"] = "up-left";
2139
+ AlertArrowPosition["TOP"] = "up-center";
2140
+ AlertArrowPosition["TOP_RIGHT"] = "up-right";
2141
+ AlertArrowPosition["BOTTOM_LEFT"] = "down-left";
2142
+ AlertArrowPosition["BOTTOM"] = "down-center";
2143
+ AlertArrowPosition["BOTTOM_RIGHT"] = "down-right";
2144
+ })(exports.AlertArrowPosition || (exports.AlertArrowPosition = {}));
2145
+ function resolveType(type) {
2146
+ switch (type) {
2147
+ case 'success':
2148
+ return 'positive';
2149
+ case 'info':
2150
+ return 'neutral';
2151
+ case 'error':
2152
+ return 'negative';
2153
+ default:
2154
+ return type;
2155
+ }
2156
+ }
2157
+ function Alert({
2158
+ arrow,
2159
+ action,
2160
+ children,
2161
+ className,
2162
+ dismissible,
2163
+ icon,
2164
+ onDismiss,
2165
+ message,
2166
+ size,
2167
+ title,
2168
+ type = 'neutral',
2169
+ variant = 'desktop'
2170
+ }) {
2171
+ React.useEffect(() => {
2172
+ if (arrow !== undefined) {
2173
+ logActionRequired("Alert component doesn't support 'arrow' anymore, use 'InlineAlert' instead.");
2174
+ }
2175
+ }, [arrow]);
2176
+ React.useEffect(() => {
2177
+ if (children !== undefined) {
2178
+ logActionRequired("Alert component doesn't support 'children' anymore, use 'message' instead.");
2179
+ }
2180
+ }, [children]);
2181
+ React.useEffect(() => {
2182
+ if (dismissible !== undefined) {
2183
+ logActionRequired("Alert component doesn't support 'dismissible' anymore, use 'onDismiss' instead.");
2184
+ }
2185
+ }, [dismissible]);
2186
+ React.useEffect(() => {
2187
+ if (size !== undefined) {
2188
+ logActionRequired("Alert component doesn't support 'size' anymore, please remove that prop.");
2189
+ }
2190
+ }, [size]);
2191
+ const resolvedType = resolveType(type);
2192
+ React.useEffect(() => {
2193
+ if (resolvedType !== type) {
2194
+ logActionRequired(`Alert component has deprecated '${type}' value for the 'type' prop. Please use '${resolvedType}' instead.`);
2195
+ }
2196
+ }, [resolvedType, type]);
2197
+ const [shouldFire, setShouldFire] = React.useState(false);
2198
+ const closeButtonReference = React.useRef(null);
2199
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2200
+ className: classNames__default.default('alert d-flex', `alert-${resolvedType}`, arrow != null && alertArrowClassNames(arrow), className),
2201
+ "data-testid": "alert",
2202
+ onTouchStart: () => setShouldFire(true),
2203
+ onTouchEnd: event => {
2204
+ if (shouldFire && action &&
2205
+ // Check if current event is triggered from closeButton
2206
+ event.target instanceof Node && closeButtonReference.current && !closeButtonReference.current.contains(event.target)) {
2207
+ if (action.target === '_blank') {
2208
+ window.top?.open(action.href);
2209
+ } else {
2210
+ window.top?.location.assign(action.href);
2211
+ }
2212
+ }
2213
+ setShouldFire(false);
2214
+ },
2215
+ onTouchMove: () => setShouldFire(false),
2216
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2217
+ className: classNames__default.default('alert__content', 'd-flex', 'flex-grow-1', variant),
2218
+ "data-testid": variant,
2219
+ children: [icon ? /*#__PURE__*/jsxRuntime.jsx("div", {
2220
+ className: "alert__icon",
2221
+ children: icon
2222
+ }) : /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
2223
+ size: exports.Size.LARGE,
2224
+ sentiment: resolvedType
2225
+ }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2226
+ className: "alert__message",
2227
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2228
+ role: exports.Sentiment.NEGATIVE === resolvedType ? 'alert' : 'status',
2229
+ children: [title && /*#__PURE__*/jsxRuntime.jsx(Title, {
2230
+ className: "m-b-1",
2231
+ type: exports.Typography.TITLE_BODY,
2232
+ children: title
2233
+ }), /*#__PURE__*/jsxRuntime.jsx(Body, {
2234
+ as: "span",
2235
+ className: "d-block",
2236
+ type: exports.Typography.BODY_LARGE,
2237
+ children: children || /*#__PURE__*/jsxRuntime.jsx(InlineMarkdown, {
2238
+ children: message
2239
+ })
2240
+ })]
2241
+ }), action && /*#__PURE__*/jsxRuntime.jsx(Link, {
2242
+ href: action.href,
2243
+ className: "m-t-1",
2244
+ "aria-label": action['aria-label'],
2245
+ target: action.target,
2246
+ type: exports.Typography.LINK_LARGE,
2247
+ children: action.text
2248
+ })]
2249
+ })]
2250
+ }), onDismiss && /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2251
+ ref: closeButtonReference,
2252
+ className: "m-l-2",
2253
+ onClick: onDismiss
2254
+ })]
2255
+ });
2256
+ }
2257
+ function alertArrowClassNames(arrow) {
2258
+ switch (arrow) {
2259
+ case 'down-center':
2260
+ return 'arrow arrow-bottom arrow-center';
2261
+ case 'down-left':
2262
+ return 'arrow arrow-bottom arrow-left';
2263
+ case 'down-right':
2264
+ return 'arrow arrow-bottom arrow-right';
2265
+ case 'up-center':
2266
+ return 'arrow arrow-center';
2267
+ case 'up-right':
2268
+ return 'arrow arrow-right';
2269
+ case 'up-left':
2270
+ default:
2271
+ return 'arrow';
2272
+ }
2273
+ }
2274
+
2275
+ // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
2276
+ exports.AvatarType = void 0;
2277
+ (function (AvatarType) {
2278
+ AvatarType["THUMBNAIL"] = "thumbnail";
2279
+ AvatarType["ICON"] = "icon";
2280
+ AvatarType["EMOJI"] = "emoji";
2281
+ AvatarType["INITIALS"] = "initials";
2282
+ })(exports.AvatarType || (exports.AvatarType = {}));
2283
+
2284
+ /*
2285
+ * The colors we support generating an Avatar background color from a "seed" for.
2286
+ * Changing this array will change the assignment between seeds.
2287
+ * Do not change this array.
2288
+ */
2289
+ const avatarColors = ['--color-bright-blue', '--color-bright-yellow', '--color-bright-pink', '--color-bright-orange'];
2290
+ /*
2291
+ * Takes in a "seed" string and spits out an index for the color we should use.
2292
+ * This implementation has been synced across all three clients so that we consistently
2293
+ * generate branded avatar colors when rendering a list of Avatars.
2294
+ * Do not change this implementation.
2295
+ */
2296
+ const hashSeed = seed => {
2297
+ const base = 31;
2298
+ const modulo = avatarColors.length;
2299
+ let hashValue = 0;
2300
+ let basePow = 1;
2301
+ for (let i = 0; i < seed.length; i += 1) {
2302
+ hashValue = (hashValue + seed.charCodeAt(i) * basePow) % modulo;
2303
+ basePow = basePow * base % modulo;
2304
+ }
2305
+ return hashValue;
2306
+ };
2307
+ const getAvatarColorFromSeed = seed => {
2308
+ return avatarColors[hashSeed(seed)];
2309
+ };
2310
+
2311
+ const backwardsCompatibleSize = size => {
2312
+ switch (size) {
2313
+ case 'sm':
2314
+ return 24;
2315
+ case 'md':
2316
+ return 48;
2317
+ case 'lg':
2318
+ return 72;
2319
+ default:
2320
+ return size;
2321
+ }
2322
+ };
2323
+ const Avatar = ({
2324
+ backgroundColor = null,
2325
+ backgroundColorSeed = null,
2326
+ children = null,
2327
+ className,
2328
+ outlined = false,
2329
+ size: sizeFromProps = 48,
2330
+ theme = exports.Theme.LIGHT,
2331
+ type = 'thumbnail'
2332
+ }) => {
2333
+ const backgroundColorFromSeed = React.useMemo(() => !backgroundColor && backgroundColorSeed ? `var(${getAvatarColorFromSeed(backgroundColorSeed)})` : undefined, [backgroundColor, backgroundColorSeed]);
2334
+ const size = backwardsCompatibleSize(sizeFromProps);
2335
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
2336
+ className: classNames__default.default('tw-avatar', className, `tw-avatar--${size}`, `tw-avatar--${type}`, {
2337
+ 'tw-avatar--outlined': outlined,
2338
+ 'tw-avatar--branded': Boolean(backgroundColorFromSeed),
2339
+ 'np-text-title-body': type === 'initials'
2340
+ }),
2341
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
2342
+ className: "tw-avatar__content",
2343
+ style: {
2344
+ backgroundColor: backgroundColor || backgroundColorFromSeed
2345
+ },
2346
+ children: children
2347
+ })
2348
+ });
2349
+ };
2350
+
2351
+ const Badge = ({
2352
+ badge,
2353
+ className = undefined,
2354
+ size = exports.Size.SMALL,
2355
+ border = exports.Theme.LIGHT,
2356
+ children
2357
+ }) => {
2358
+ const classes = classNames__default.default('tw-badge', {
2359
+ [`tw-badge-border-${border}`]: border,
2360
+ [`tw-badge-${size}`]: size
2361
+ }, className);
2362
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2363
+ className: classes,
2364
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2365
+ className: "tw-badge__children",
2366
+ children: children
2367
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2368
+ className: "tw-badge__content",
2369
+ children: badge
2370
+ })]
2371
+ });
2372
+ };
2373
+
2374
+ const OptionalBadge = ({
2375
+ url,
2376
+ altText,
2377
+ statusIcon,
2378
+ children,
2379
+ ...rest
2380
+ }) => {
2381
+ if (url) {
2382
+ return /*#__PURE__*/jsxRuntime.jsx(Badge, {
2383
+ badge: /*#__PURE__*/jsxRuntime.jsx("img", {
2384
+ src: url,
2385
+ alt: altText
2386
+ }),
2387
+ ...rest,
2388
+ children: children
2389
+ });
2390
+ }
2391
+ if (statusIcon) {
2392
+ return /*#__PURE__*/jsxRuntime.jsx(Badge, {
2393
+ badge: /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
2394
+ sentiment: statusIcon,
2395
+ size: exports.Size.SMALL
2396
+ }),
2397
+ ...rest,
2398
+ children: children
2399
+ });
2400
+ }
2401
+ return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
2402
+ children: children
2403
+ });
2404
+ };
2405
+ const AvatarWrapper = ({
2406
+ url,
2407
+ profileType,
2408
+ profileId,
2409
+ badgeUrl,
2410
+ badgeAltText,
2411
+ badgeStatusIcon,
2412
+ name,
2413
+ avatarProps,
2414
+ badgeProps
2415
+ }) => {
2416
+ const [hasImageLoadError, setImageLoadError] = React.useState(false);
2417
+ const isBusinessProfile = profileType === exports.ProfileType.BUSINESS;
2418
+ // Reset the errored state when url changes
2419
+ React.useEffect(() => setImageLoadError(false), [url]);
2420
+ const getAvatarProps = () => {
2421
+ if (url && !hasImageLoadError) {
2422
+ return {
2423
+ type: exports.AvatarType.THUMBNAIL,
2424
+ children: /*#__PURE__*/jsxRuntime.jsx("img", {
2425
+ src: url,
2426
+ alt: "",
2427
+ onError: () => setImageLoadError(true)
2428
+ }),
2429
+ ...avatarProps
2430
+ };
2431
+ }
2432
+ if (profileType) {
2433
+ return {
2434
+ type: exports.AvatarType.ICON,
2435
+ children: isBusinessProfile ? /*#__PURE__*/jsxRuntime.jsx(icons.Briefcase, {
2436
+ size: "24"
2437
+ }) : /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
2438
+ size: "24"
2439
+ }),
2440
+ ...avatarProps
2441
+ };
2442
+ }
2443
+ if (name) {
2444
+ return {
2445
+ type: exports.AvatarType.INITIALS,
2446
+ children: /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
2447
+ children: getInitials(name)
2448
+ }),
2449
+ backgroundColorSeed: profileId?.toString(),
2450
+ ...avatarProps
2451
+ };
2452
+ }
2453
+ return {
2454
+ type: exports.AvatarType.ICON,
2455
+ children: /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
2456
+ size: "24"
2457
+ }),
2458
+ ...avatarProps
2459
+ };
2460
+ };
2461
+ return /*#__PURE__*/jsxRuntime.jsx(OptionalBadge, {
2462
+ url: badgeUrl,
2463
+ altText: badgeAltText,
2464
+ statusIcon: badgeStatusIcon,
2465
+ ...badgeProps,
2466
+ children: /*#__PURE__*/jsxRuntime.jsx(Avatar, {
2467
+ size: exports.Size.MEDIUM,
2468
+ ...getAvatarProps()
2469
+ })
2470
+ });
2471
+ };
2472
+ function getInitials(name) {
2473
+ const allInitials = name.split(' ').map(part => part[0]).join('').toUpperCase();
2474
+ if (allInitials.length === 1) {
2475
+ return allInitials[0];
2476
+ }
2477
+ return allInitials[0] + allInitials.slice(-1);
2478
+ }
2479
+
2480
+ const Card$1 = /*#__PURE__*/React.forwardRef((props, reference) => {
2481
+ const {
2482
+ 'aria-label': ariaLabel,
2483
+ as: Element,
2484
+ isExpanded,
2485
+ title,
2486
+ details,
2487
+ children,
2488
+ onClick,
2489
+ icon,
2490
+ id,
2491
+ className,
2492
+ ...rest
2493
+ } = props;
2494
+ const isOpen = !!(isExpanded && children);
2495
+ return /*#__PURE__*/jsxRuntime.jsxs(Element, {
2496
+ ref: reference,
2497
+ className: classNames__default.default('np-card', className, {
2498
+ 'np-card--expanded': isOpen,
2499
+ 'np-card--inactive': !children,
2500
+ 'np-card--has-icon': !!icon
2501
+ }),
2502
+ id: id,
2503
+ "data-testid": rest['data-testid'],
2504
+ children: [/*#__PURE__*/jsxRuntime.jsx(Option$2, {
2505
+ "aria-label": ariaLabel,
2506
+ as: children ? 'button' : 'div',
2507
+ className: classNames__default.default('np-card__button'),
2508
+ media: icon,
2509
+ title: title,
2510
+ content: details,
2511
+ showMediaAtAllSizes: true,
2512
+ button: children && /*#__PURE__*/jsxRuntime.jsx(Chevron, {
2513
+ orientation: isOpen ? exports.Position.TOP : exports.Position.BOTTOM
2514
+ }),
2515
+ onClick: () => children && onClick(!isExpanded)
2516
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2517
+ className: classNames__default.default('np-card__divider', {
2518
+ 'np-card__divider--expanded': isOpen
2519
+ })
2520
+ }), isOpen && /*#__PURE__*/jsxRuntime.jsx(Body, {
2521
+ as: "span",
2522
+ type: exports.Typography.BODY_LARGE,
2523
+ className: "np-card__content d-block",
2524
+ children: children
2525
+ })]
2526
+ });
2527
+ });
2528
+ const hasChildren = ({
2529
+ children
2530
+ }) => children;
2531
+ Card$1.propTypes = {
2532
+ 'aria-label': PropTypes__default.default.string,
2533
+ as: PropTypes__default.default.string,
2534
+ isExpanded: requiredIf__default.default(PropTypes__default.default.bool, hasChildren),
2535
+ title: PropTypes__default.default.node.isRequired,
2536
+ details: PropTypes__default.default.node.isRequired,
2537
+ onClick: requiredIf__default.default(PropTypes__default.default.func, hasChildren),
2538
+ icon: PropTypes__default.default.node,
2539
+ children: PropTypes__default.default.node,
2540
+ id: PropTypes__default.default.string,
2541
+ className: PropTypes__default.default.string,
2542
+ 'data-testid': PropTypes__default.default.string
2543
+ };
2544
+ Card$1.defaultProps = {
2545
+ 'aria-label': undefined,
2546
+ as: 'div',
2547
+ children: null,
2548
+ id: null,
2549
+ className: null,
2550
+ 'data-testid': null
2551
+ };
2552
+ var Card$2 = Card$1;
2553
+
2554
+ const CheckboxButton = /*#__PURE__*/React.forwardRef(({
2555
+ checked,
2556
+ className,
2557
+ disabled,
2558
+ onChange,
2559
+ ...rest
2560
+ }, reference) => /*#__PURE__*/jsxRuntime.jsxs("span", {
2561
+ className: classNames__default.default('np-checkbox-button', className, disabled && 'disabled'),
2562
+ children: [/*#__PURE__*/jsxRuntime.jsx("input", {
2563
+ ...rest,
2564
+ ref: reference,
2565
+ type: "checkbox",
2566
+ disabled: disabled,
2567
+ checked: checked,
2568
+ onChange: onChange
2569
+ }), /*#__PURE__*/jsxRuntime.jsx("span", {
2570
+ className: "tw-checkbox-button",
2571
+ children: /*#__PURE__*/jsxRuntime.jsx("span", {
2572
+ className: "tw-checkbox-check"
2573
+ })
2574
+ })]
2575
+ }));
2576
+ var CheckboxButton$1 = CheckboxButton;
2577
+
2578
+ const Checkbox = ({
2579
+ id,
2580
+ checked,
2581
+ required,
2582
+ disabled,
2583
+ readOnly,
2584
+ label,
2585
+ className,
2586
+ secondary,
2587
+ onChange,
2588
+ onFocus,
2589
+ onBlur
2590
+ }) => {
2591
+ const {
2592
+ isModern
2593
+ } = componentsTheming.useTheme();
2594
+ const classList = classNames__default.default('np-checkbox', {
2595
+ checkbox: true,
2596
+ 'checkbox-lg': secondary,
2597
+ disabled: isModern && disabled
2598
+ }, className);
2599
+ const innerDisabled = disabled || readOnly;
2600
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
2601
+ id: id,
2602
+ className: classList,
2603
+ children: /*#__PURE__*/jsxRuntime.jsxs("label", {
2604
+ className: classNames__default.default({
2605
+ disabled
2606
+ }),
2607
+ children: [/*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
2608
+ className: "p-r-2",
2609
+ checked: checked,
2610
+ disabled: innerDisabled,
2611
+ required: !innerDisabled && required,
2612
+ onFocus: onFocus,
2613
+ onChange: () => onChange(!checked),
2614
+ onBlur: onBlur
2615
+ }), /*#__PURE__*/jsxRuntime.jsxs(Body, {
2616
+ as: "span",
2617
+ className: "np-checkbox__text",
2618
+ type: secondary ? exports.Typography.BODY_LARGE_BOLD : exports.Typography.BODY_LARGE,
2619
+ children: [/*#__PURE__*/jsxRuntime.jsx("span", {
2620
+ className: required ? 'has-required' : undefined,
2621
+ children: label
2622
+ }), secondary && /*#__PURE__*/jsxRuntime.jsx(Body, {
2623
+ as: "span",
2624
+ className: classNames__default.default({
2625
+ secondary: !isModern
2626
+ }),
2627
+ children: secondary
2628
+ })]
2629
+ })]
2630
+ })
2631
+ });
2632
+ };
2633
+ Checkbox.propTypes = {
2634
+ id: PropTypes__default.default.string,
2635
+ checked: PropTypes__default.default.bool,
2636
+ required: PropTypes__default.default.bool,
2637
+ disabled: PropTypes__default.default.bool,
2638
+ readOnly: PropTypes__default.default.bool,
2639
+ label: PropTypes__default.default.node.isRequired,
2640
+ secondary: PropTypes__default.default.string,
2641
+ onFocus: PropTypes__default.default.func,
2642
+ onChange: PropTypes__default.default.func.isRequired,
2643
+ onBlur: PropTypes__default.default.func,
2644
+ className: PropTypes__default.default.string
2645
+ };
2646
+ Checkbox.defaultProps = {
2647
+ id: null,
2648
+ checked: false,
2649
+ required: false,
2650
+ disabled: false,
2651
+ readOnly: false,
2652
+ secondary: null,
2653
+ onFocus: null,
2654
+ onBlur: null,
2655
+ className: undefined
2656
+ };
2657
+
2658
+ const CheckboxOption = /*#__PURE__*/React.forwardRef(({
2659
+ checked,
2660
+ disabled,
2661
+ onChange,
2662
+ ...rest
2663
+ }, reference) => {
2664
+ return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
2665
+ ...rest,
2666
+ ref: reference,
2667
+ disabled: disabled,
2668
+ button: /*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
2669
+ checked: checked,
2670
+ disabled: disabled,
2671
+ onChange: () => onChange?.(!checked)
2672
+ })
2673
+ });
2674
+ });
2675
+
2676
+ const Chip = ({
2677
+ label,
2678
+ value,
2679
+ onRemove,
2680
+ onClick,
2681
+ onKeyPress,
2682
+ className = undefined,
2683
+ 'aria-label': ariaLabel,
2684
+ 'aria-checked': ariaChecked,
2685
+ role,
2686
+ closeButton
2687
+ }) => {
2688
+ const isActionable = onClick || onKeyPress;
2689
+ const defaultRole = isActionable ? 'button' : undefined;
2690
+ const tabIndex = isActionable ? 0 : -1;
2691
+ const {
2692
+ isModern
2693
+ } = componentsTheming.useTheme();
2694
+ const closeButtonReference = React.useRef(null);
2695
+ const previousCloseButtonShown = React.useRef();
2696
+ React.useEffect(() => {
2697
+ if (closeButtonReference.current != null && previousCloseButtonShown.current === false) {
2698
+ closeButtonReference.current?.focus();
2699
+ }
2700
+ previousCloseButtonShown.current = closeButtonReference.current != null;
2701
+ }, [onRemove]);
2702
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
2703
+ role: role ?? defaultRole,
2704
+ tabIndex: tabIndex,
2705
+ "aria-label": ariaLabel,
2706
+ "aria-checked": ariaChecked,
2707
+ className: classNames__default.default('np-chip', 'd-flex', 'align-items-center', 'justify-content-between', onRemove ? 'np-chip--removable' : '', className),
2708
+ ...(isActionable && {
2709
+ onClick,
2710
+ onKeyPress
2711
+ }),
2712
+ children: [isModern ? /*#__PURE__*/jsxRuntime.jsx(Body, {
2713
+ "aria-hidden": !!onRemove,
2714
+ type: exports.Typography.BODY_DEFAULT_BOLD,
2715
+ children: label
2716
+ }) : /*#__PURE__*/jsxRuntime.jsx("span", {
2717
+ "aria-hidden": "false",
2718
+ className: "np-chip-label",
2719
+ children: label
2720
+ }), onRemove ? /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2721
+ ref: closeButtonReference,
2722
+ className: isModern ? `btn-unstyled` : `btn-unstyled m-l-1`,
2723
+ "aria-label": closeButton && closeButton['aria-label'],
2724
+ size: "sm",
2725
+ filled: isModern,
2726
+ onClick: onRemove
2727
+ }) : null]
2728
+ }, value);
2729
+ };
2730
+
2731
+ var messages$a = reactIntl.defineMessages({
2732
+ ariaLabel: {
2733
+ id: "neptune.Chips.ariaLabel"
2734
+ }
2735
+ });
2736
+
2737
+ const Chips = ({
2738
+ chips,
2739
+ onChange,
2740
+ selected,
2741
+ 'aria-label': ariaLabel,
2742
+ className,
2743
+ multiple
2744
+ }) => {
2745
+ const intl = reactIntl.useIntl();
2746
+ const isSelected = value => Array.isArray(selected) ? selected.includes(value) : selected === value;
2747
+ const handleOnChange = (selectedValue, isCurrentlyEnabled) => {
2748
+ onChange({
2749
+ isEnabled: !isCurrentlyEnabled,
2750
+ selectedValue
2751
+ });
2752
+ };
2753
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
2754
+ className: classNames__default.default('np-chips d-flex', className),
2755
+ "aria-label": ariaLabel,
2756
+ role: !multiple ? 'radiogroup' : undefined,
2757
+ children: chips.map(chip => {
2758
+ const chipSelected = isSelected(chip.value);
2759
+ return /*#__PURE__*/jsxRuntime.jsx(Chip, {
2760
+ value: chip.value,
2761
+ label: chip.label,
2762
+ closeButton: {
2763
+ 'aria-label': intl.formatMessage(messages$a.ariaLabel, {
2764
+ choice: chip.label
2765
+ })
2766
+ },
2767
+ className: classNames__default.default('text-xs-nowrap', {
2768
+ 'np-chip--selected': chipSelected,
2769
+ 'p-r-1': multiple && chipSelected
2770
+ }),
2771
+ ...(multiple && chipSelected ? {
2772
+ onRemove: () => handleOnChange(chip.value, chipSelected),
2773
+ 'aria-label': chip.label
2774
+ } : {
2775
+ onClick: () => handleOnChange(chip.value, chipSelected),
2776
+ onKeyPress: () => handleOnChange(chip.value, chipSelected),
2777
+ role: !multiple ? 'radio' : undefined,
2778
+ 'aria-checked': chipSelected
2779
+ })
2780
+ }, chip.value);
2781
+ })
2782
+ });
2783
+ };
2784
+
2785
+ const CircularButton = ({
2786
+ className,
2787
+ children,
2788
+ disabled,
2789
+ icon,
2790
+ priority = exports.Priority.PRIMARY,
2791
+ type = exports.ControlType.ACCENT,
2792
+ ...rest
2793
+ }) => {
2794
+ const classes = classNames__default.default('btn np-btn', typeClassMap[type], priorityClassMap[priority]);
2795
+ const iconElement = Number(icon.props.size) !== 24 ? /*#__PURE__*/React.cloneElement(icon, {
2796
+ size: 24
2797
+ }) : icon;
2798
+ return /*#__PURE__*/jsxRuntime.jsxs("label", {
2799
+ className: classNames__default.default('np-circular-btn', priority, type, disabled && 'disabled', className),
2800
+ children: [/*#__PURE__*/jsxRuntime.jsx("input", {
2801
+ type: "button",
2802
+ "aria-label": children,
2803
+ className: classes,
2804
+ disabled: disabled,
2805
+ ...rest
2806
+ }), iconElement, /*#__PURE__*/jsxRuntime.jsx(Body, {
2807
+ as: "span",
2808
+ className: "np-circular-btn__label",
2809
+ type: exports.Typography.BODY_DEFAULT_BOLD,
2810
+ children: children
2811
+ })]
2812
+ });
2813
+ };
2814
+
2479
2815
  const Card = ({
2480
2816
  className,
2481
2817
  children = null,
@@ -2988,124 +3324,6 @@ function shouldPropagateOnBlur({
2988
3324
  return blurElementParent !== focusElementParent;
2989
3325
  }
2990
3326
 
2991
- const POPOVER_OFFSET = [0, 16];
2992
- // By default the flip positioning explores only the opposite alternative. So if left is passed and there's no enough space
2993
- // the right one gets chosen. If there's no space on both sides popover goes back to the initially chosen one left.
2994
- // This mapping forces popover to try the four available positions before going back to the initial chosen one.
2995
- const fallbackPlacements = {
2996
- [exports.Position.TOP]: [exports.Position.BOTTOM, exports.Position.RIGHT, exports.Position.LEFT],
2997
- [exports.Position.BOTTOM]: [exports.Position.TOP, exports.Position.RIGHT, exports.Position.LEFT],
2998
- [exports.Position.LEFT]: [exports.Position.RIGHT, exports.Position.TOP, exports.Position.BOTTOM],
2999
- [exports.Position.RIGHT]: [exports.Position.LEFT, exports.Position.TOP, exports.Position.BOTTOM]
3000
- };
3001
- const Panel = /*#__PURE__*/React.forwardRef(({
3002
- arrow = false,
3003
- flip = true,
3004
- altAxis = false,
3005
- children,
3006
- open = false,
3007
- onClose,
3008
- position = exports.Position.BOTTOM,
3009
- anchorRef,
3010
- anchorWidth = false,
3011
- ...rest
3012
- }, reference) => {
3013
- const [arrowElement, setArrowElement] = React.useState(null);
3014
- const [popperElement, setPopperElement] = React.useState(null);
3015
- const modifiers = [];
3016
- if (altAxis) {
3017
- modifiers.push({
3018
- // https://popper.js.org/docs/v2/modifiers/prevent-overflow
3019
- name: 'preventOverflow',
3020
- options: {
3021
- altAxis: true,
3022
- tether: false
3023
- }
3024
- });
3025
- }
3026
- if (arrow) {
3027
- modifiers.push({
3028
- name: 'arrow',
3029
- options: {
3030
- element: arrowElement,
3031
- options: {
3032
- padding: 8 // 8px from the edges of the popper
3033
- }
3034
- }
3035
- });
3036
- // This lets you displace a popper element from its reference element.
3037
- modifiers.push({
3038
- name: 'offset',
3039
- options: {
3040
- offset: POPOVER_OFFSET
3041
- }
3042
- });
3043
- }
3044
- if (flip && fallbackPlacements[position]) {
3045
- modifiers.push({
3046
- name: 'flip',
3047
- options: {
3048
- fallbackPlacements: fallbackPlacements[position]
3049
- }
3050
- });
3051
- }
3052
- const {
3053
- styles,
3054
- attributes,
3055
- forceUpdate
3056
- } = reactPopper.usePopper(anchorRef.current, popperElement, {
3057
- placement: position,
3058
- modifiers
3059
- });
3060
- // If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),
3061
- // it is most simple just to always position before opening
3062
- React.useEffect(() => {
3063
- if (open && forceUpdate) {
3064
- forceUpdate();
3065
- }
3066
- }, [open]);
3067
- const contentStyle = {
3068
- ...(anchorWidth ? {
3069
- width: anchorRef.current?.clientWidth
3070
- } : undefined)
3071
- };
3072
- return /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
3073
- open: open,
3074
- transparent: true,
3075
- fadeContentOnEnter: true,
3076
- fadeContentOnExit: true,
3077
- onClose: onClose,
3078
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
3079
- ...rest,
3080
- ref: setPopperElement,
3081
- role: "dialog"
3082
- // eslint-disable-next-line react/forbid-dom-props
3083
- ,
3084
- style: {
3085
- ...styles.popper
3086
- },
3087
- ...attributes.popper,
3088
- className: classNames__default.default('np-panel', {
3089
- 'np-panel--open': open
3090
- }, rest['className']),
3091
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
3092
- ref: reference
3093
- /* eslint-disable-next-line react/forbid-dom-props */,
3094
- style: contentStyle,
3095
- className: classNames__default.default('np-panel__content'),
3096
- children: [children, arrow && /*#__PURE__*/jsxRuntime.jsx("div", {
3097
- ref: setArrowElement,
3098
- className: classNames__default.default('np-panel__arrow')
3099
- // eslint-disable-next-line react/forbid-dom-props
3100
- ,
3101
- style: styles.arrow
3102
- })]
3103
- })
3104
- })
3105
- });
3106
- });
3107
- var Panel$1 = Panel;
3108
-
3109
3327
  const ResponsivePanel = /*#__PURE__*/React.forwardRef(({
3110
3328
  anchorRef,
3111
3329
  arrow = false,
@@ -3127,7 +3345,7 @@ const ResponsivePanel = /*#__PURE__*/React.forwardRef(({
3127
3345
  children: children
3128
3346
  }, "bottomSheet");
3129
3347
  }
3130
- return /*#__PURE__*/jsxRuntime.jsx(Panel$1, {
3348
+ return /*#__PURE__*/jsxRuntime.jsx(Panel, {
3131
3349
  ref: reference,
3132
3350
  flip: flip,
3133
3351
  arrow: arrow,
@@ -5025,73 +5243,6 @@ const Field = ({
5025
5243
  });
5026
5244
  };
5027
5245
 
5028
- const HeaderAction = ({
5029
- action
5030
- }) => {
5031
- const {
5032
- isModern
5033
- } = componentsTheming.useTheme();
5034
- const props = {
5035
- 'aria-label': action['aria-label']
5036
- };
5037
- if ('href' in action) {
5038
- return /*#__PURE__*/jsxRuntime.jsx(Link, {
5039
- href: action.href,
5040
- target: action.target,
5041
- onClick: action.onClick,
5042
- ...props,
5043
- children: action.text
5044
- });
5045
- }
5046
- return isModern ? /*#__PURE__*/jsxRuntime.jsx(Button, {
5047
- className: "np-header__button",
5048
- priority: "tertiary",
5049
- size: "sm",
5050
- onClick: action.onClick,
5051
- ...props,
5052
- children: action.text
5053
- }) : /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
5054
- onClick: action.onClick,
5055
- ...props,
5056
- children: action.text
5057
- });
5058
- };
5059
- /**
5060
- *
5061
- * Neptune Web: https://transferwise.github.io/neptune-web/components/content/Header
5062
- *
5063
- */
5064
- const Header = ({
5065
- action,
5066
- as = 'h5',
5067
- title,
5068
- className
5069
- }) => {
5070
- if (!action) {
5071
- return /*#__PURE__*/jsxRuntime.jsx(Title, {
5072
- as: as,
5073
- type: exports.Typography.TITLE_GROUP,
5074
- className: classNames__default.default('np-header', 'np-header__title', className),
5075
- children: title
5076
- });
5077
- }
5078
- if (as === 'legend') {
5079
- // eslint-disable-next-line no-console
5080
- console.warn('Legends should be the first child in a fieldset, and this is not possible when including an action');
5081
- }
5082
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
5083
- className: classNames__default.default('np-header', className),
5084
- children: [/*#__PURE__*/jsxRuntime.jsx(Title, {
5085
- as: as,
5086
- type: exports.Typography.TITLE_GROUP,
5087
- className: "np-header__title",
5088
- children: title
5089
- }), /*#__PURE__*/jsxRuntime.jsx(HeaderAction, {
5090
- action: action
5091
- })]
5092
- });
5093
- };
5094
-
5095
5246
  const EmptyTransparentImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
5096
5247
  const Image = ({
5097
5248
  id,
@@ -8847,12 +8998,6 @@ const PhoneNumberInput = ({
8847
8998
  return explodeNumberModel(cleanValue);
8848
8999
  });
8849
9000
  const [broadcastedValue, setBroadcastedValue] = React.useState(null);
8850
- const [suffixDirty, setSuffixDirty] = React.useState(false);
8851
- React.useEffect(() => {
8852
- if (internalValue.suffix) {
8853
- setSuffixDirty(true);
8854
- }
8855
- }, [internalValue.suffix]);
8856
9001
  const countriesByPrefix = React.useMemo(() => groupCountriesByPrefix(sortArrayByProperty(excludeCountries(countries, disabledCountries), 'iso3')), [disabledCountries]);
8857
9002
  const onSuffixChange = event => {
8858
9003
  const suffix = event.target.value;
@@ -8916,11 +9061,6 @@ const PhoneNumberInput = ({
8916
9061
  format: country?.phoneFormat
8917
9062
  }));
8918
9063
  },
8919
- onClose: () => {
8920
- if (suffixDirty) {
8921
- onBlur?.();
8922
- }
8923
- },
8924
9064
  ...selectProps
8925
9065
  })
8926
9066
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
@@ -8940,7 +9080,7 @@ const PhoneNumberInput = ({
8940
9080
  onChange: onSuffixChange,
8941
9081
  onPaste: onPaste,
8942
9082
  onFocus: onFocus,
8943
- onBlur: () => onBlur?.()
9083
+ onBlur: onBlur
8944
9084
  })
8945
9085
  })
8946
9086
  })]
@@ -9550,19 +9690,6 @@ function RadioOption({
9550
9690
  });
9551
9691
  }
9552
9692
 
9553
- const Section = ({
9554
- children,
9555
- className,
9556
- withHorizontalPadding = false
9557
- }) => {
9558
- return /*#__PURE__*/jsxRuntime.jsx("div", {
9559
- className: classNames__default.default('np-section', className, {
9560
- 'np-section--with-horizontal-padding': withHorizontalPadding
9561
- }),
9562
- children: children
9563
- });
9564
- };
9565
-
9566
9693
  const SegmentedControl = ({
9567
9694
  name,
9568
9695
  value,
@@ -10229,7 +10356,7 @@ function Select({
10229
10356
  children: renderOptionsList({
10230
10357
  className: isModern ? '' : 'p-a-1'
10231
10358
  })
10232
- }) : /*#__PURE__*/jsxRuntime.jsx(Panel$1, {
10359
+ }) : /*#__PURE__*/jsxRuntime.jsx(Panel, {
10233
10360
  open: open,
10234
10361
  flip: false,
10235
10362
  altAxis: true,
@@ -14591,6 +14718,7 @@ exports.Select = Select;
14591
14718
  exports.SelectInput = SelectInput;
14592
14719
  exports.SelectInputOptionContent = SelectInputOptionContent;
14593
14720
  exports.SelectInputTriggerButton = SelectInputTriggerButton;
14721
+ exports.SelectOption = SelectOption;
14594
14722
  exports.SlidingPanel = SlidingPanel;
14595
14723
  exports.SnackbarConsumer = SnackbarConsumer;
14596
14724
  exports.SnackbarContext = SnackbarContext;