@transferwise/components 0.0.0-experimental-a213c0c → 0.0.0-experimental-ac06ea4

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 reactPopper = require('react-popper');
8
+ var reactIntl = require('react-intl');
9
+ var PropTypes = require('prop-types');
10
+ var commonmark = require('commonmark');
9
11
  var componentsTheming = require('@wise/components-theming');
10
12
  var reactTransitionGroup = require('react-transition-group');
11
13
  var focus = require('@react-aria/focus');
12
14
  var reactDom = require('react-dom');
13
- var reactIntl = require('react-intl');
14
- var PropTypes = require('prop-types');
15
- var art = require('@wise/art');
16
15
  var index_js = require('use-sync-external-store/shim/index.js');
17
16
  var neptuneValidation = require('@transferwise/neptune-validation');
18
- var commonmark = require('commonmark');
19
17
  var formatting = require('@transferwise/formatting');
20
18
  var react$1 = require('@headlessui/react');
21
19
  var mergeProps = require('merge-props');
22
20
  var react = require('@floating-ui/react');
23
21
  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,383 +700,590 @@ const ActionOption = ({
700
700
  });
701
701
  };
702
702
 
703
- const FocusBoundary = ({
704
- children
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
705
754
  }) => {
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
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'
786
+ }) => {
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)
719
794
  })
720
795
  });
721
796
  };
722
797
 
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
- };
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
+ });
733
826
  }
734
827
 
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 = [];
745
- }
746
- add(dimmer) {
747
- let dimmerIndex = this.dimmers.indexOf(dimmer);
748
- if (dimmerIndex !== -1) {
749
- return dimmerIndex;
750
- }
751
- dimmerIndex = this.dimmers.length;
752
- this.dimmers.push(dimmer);
753
- return dimmerIndex;
754
- }
755
- remove(dimmer) {
756
- const dimmerIndex = this.dimmers.indexOf(dimmer);
757
- if (dimmerIndex !== -1) {
758
- this.dimmers.splice(dimmerIndex, 1);
759
- }
760
- return dimmerIndex;
828
+ function logActionRequired(message) {
829
+ if (['development', 'test'].includes(process?.env?.NODE_ENV)) {
830
+ // eslint-disable-next-line no-console
831
+ console.warn(message);
761
832
  }
762
- isTop(dimmer) {
763
- return this.dimmers.length > 0 && this.dimmers[this.dimmers.length - 1] === dimmer;
833
+ }
834
+ function logActionRequiredIf(message, conditional) {
835
+ if (conditional) {
836
+ logActionRequired(message);
764
837
  }
765
838
  }
766
839
 
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();
777
- }
778
- };
779
- const Dimmer = ({
780
- children,
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,
781
850
  className,
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);
796
- }
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.');
860
+ }
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;
797
868
  };
798
- const handleClick = event => {
799
- if (disableClickToClose || !onClose) {
800
- return;
801
- }
802
- closeOnClick(event);
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}">`);
803
872
  };
804
- const handleKeyDown = React.useCallback(event => {
805
- if (event.key !== 'Escape') {
806
- return;
807
- }
808
- event.stopPropagation();
809
- if (onClose && dimmerReference.current && dimmerManager.isTop(dimmerReference.current)) {
810
- onClose(event);
811
- }
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);
873
+ return /*#__PURE__*/jsxRuntime.jsx(Element, {
874
+ className: className,
875
+ dangerouslySetInnerHTML: {
876
+ __html: createMarkup()
823
877
  }
824
- };
825
- React.useEffect(() => {
826
- const localReferenceCopy = dimmerReference.current;
827
- if (open) {
828
- document.addEventListener('keydown', handleKeyDown);
829
- localReferenceCopy?.addEventListener('touchmove', handleTouchMove, {
830
- passive: true
831
- });
878
+ });
879
+ }
880
+ function stripNodes({
881
+ blockList,
882
+ parsed
883
+ }) {
884
+ if (!parsed) {
885
+ return parsed;
886
+ }
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();
832
897
  }
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
883
- })
884
- })
885
- })
886
- })
887
- })
898
+ }
899
+ return parsed;
900
+ }
901
+
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
888
909
  });
889
910
  };
890
- const DimmerWrapper = ({
891
- open,
892
- hasNotExited,
893
- children
894
- }) => {
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
906
- });
911
+ InlineMarkdown.propTypes = {
912
+ children: PropTypes__default.default.string.isRequired,
913
+ className: PropTypes__default.default.string
907
914
  };
908
- const DimmerContentWrapper = ({
909
- children,
910
- scrollBody
911
- }) => {
912
- React.useEffect(() => {
913
- if (scrollBody) {
914
- addNoScrollClass();
915
- }
916
- return () => {
917
- if (scrollBody) {
918
- removeNoScrollClass();
919
- }
920
- };
921
- }, [scrollBody]);
922
- return children;
915
+ InlineMarkdown.defaultProps = {
916
+ className: undefined
923
917
  };
924
- var Dimmer$1 = withNextPortalWrapper(Dimmer);
925
918
 
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,
940
- children,
941
- open = false,
942
- onClose,
943
- position = exports.Position.BOTTOM,
944
- anchorRef,
945
- anchorWidth = false,
946
- ...rest
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
- }
959
- });
960
- }
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
- }
977
- });
978
- }
979
- if (flip && fallbackPlacements[position]) {
980
- modifiers.push({
981
- name: 'flip',
982
- options: {
983
- fallbackPlacements: fallbackPlacements[position]
984
- }
985
- });
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;
986
938
  }
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
939
+ }
940
+ function Alert({
941
+ arrow,
942
+ action,
943
+ children,
944
+ className,
945
+ dismissible,
946
+ icon,
947
+ onDismiss,
948
+ message,
949
+ size,
950
+ title,
951
+ type = 'neutral',
952
+ variant = 'desktop'
953
+ }) {
997
954
  React.useEffect(() => {
998
- if (open && forceUpdate) {
999
- forceUpdate();
955
+ if (arrow !== undefined) {
956
+ logActionRequired("Alert component doesn't support 'arrow' anymore, use 'InlineAlert' instead.");
1000
957
  }
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
958
+ }, [arrow]);
959
+ React.useEffect(() => {
960
+ if (children !== undefined) {
961
+ logActionRequired("Alert component doesn't support 'children' anymore, use 'message' instead.");
962
+ }
963
+ }, [children]);
964
+ React.useEffect(() => {
965
+ if (dismissible !== undefined) {
966
+ logActionRequired("Alert component doesn't support 'dismissible' anymore, use 'onDismiss' instead.");
967
+ }
968
+ }, [dismissible]);
969
+ React.useEffect(() => {
970
+ if (size !== undefined) {
971
+ logActionRequired("Alert component doesn't support 'size' anymore, please remove that prop.");
972
+ }
973
+ }, [size]);
974
+ const resolvedType = resolveType(type);
975
+ React.useEffect(() => {
976
+ if (resolvedType !== type) {
977
+ logActionRequired(`Alert component has deprecated '${type}' value for the 'type' prop. Please use '${resolvedType}' instead.`);
978
+ }
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
1022
+ })
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
1037
1031
  })]
1038
- })
1039
- })
1032
+ })]
1033
+ }), onDismiss && /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1034
+ ref: closeButtonReference,
1035
+ className: "m-l-2",
1036
+ onClick: onDismiss
1037
+ })]
1040
1038
  });
1041
- });
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
+ }
1042
1057
 
1043
- const Section = ({
1044
- children,
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
+ };
1106
+ const Avatar = ({
1107
+ backgroundColor = null,
1108
+ backgroundColorSeed = null,
1109
+ children = null,
1045
1110
  className,
1046
- withHorizontalPadding = false
1111
+ outlined = false,
1112
+ size: sizeFromProps = 48,
1113
+ theme = exports.Theme.LIGHT,
1114
+ type = 'thumbnail'
1047
1115
  }) => {
1116
+ const backgroundColorFromSeed = React.useMemo(() => !backgroundColor && backgroundColorSeed ? `var(${getAvatarColorFromSeed(backgroundColorSeed)})` : undefined, [backgroundColor, backgroundColorSeed]);
1117
+ const size = backwardsCompatibleSize(sizeFromProps);
1048
1118
  return /*#__PURE__*/jsxRuntime.jsx("div", {
1049
- className: classNames__default.default('np-section', className, {
1050
- 'np-section--with-horizontal-padding': withHorizontalPadding
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'
1051
1123
  }),
1052
- children: children
1124
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
1125
+ className: "tw-avatar__content",
1126
+ style: {
1127
+ backgroundColor: backgroundColor || backgroundColorFromSeed
1128
+ },
1129
+ children: children
1130
+ })
1053
1131
  });
1054
1132
  };
1055
1133
 
1056
- const radius = {
1057
- xxs: 6,
1058
- xs: 11,
1059
- sm: 22,
1060
- xl: 61
1134
+ const Badge = ({
1135
+ badge,
1136
+ className = undefined,
1137
+ size = exports.Size.SMALL,
1138
+ border = exports.Theme.LIGHT,
1139
+ children
1140
+ }) => {
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
+ });
1061
1155
  };
1062
- const ANIMATION_DURATION_IN_MS = 1500;
1063
- class ProcessIndicator extends React.Component {
1064
- constructor(props) {
1065
- super(props);
1066
- this.state = {
1067
- status: props.status,
1068
- size: props.size
1069
- };
1070
- this.interval = null;
1071
- this.timeout = null;
1072
- }
1073
1156
 
1074
- /**
1075
- * Create interval for animation duration (1500ms)
1076
- * Update state only at the end of every interval
1077
- * (end of animation loop) if props changed before end of animation
1078
- */
1079
- componentDidMount() {
1157
+ const OptionalBadge = ({
1158
+ url,
1159
+ altText,
1160
+ statusIcon,
1161
+ children,
1162
+ ...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
1172
+ });
1173
+ }
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
1182
+ });
1183
+ }
1184
+ return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
1185
+ children: children
1186
+ });
1187
+ };
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
+
1263
+ const radius = {
1264
+ xxs: 6,
1265
+ xs: 11,
1266
+ sm: 22,
1267
+ xl: 61
1268
+ };
1269
+ const ANIMATION_DURATION_IN_MS = 1500;
1270
+ class ProcessIndicator extends React.Component {
1271
+ constructor(props) {
1272
+ super(props);
1273
+ this.state = {
1274
+ status: props.status,
1275
+ size: props.size
1276
+ };
1277
+ this.interval = null;
1278
+ this.timeout = null;
1279
+ }
1280
+
1281
+ /**
1282
+ * Create interval for animation duration (1500ms)
1283
+ * Update state only at the end of every interval
1284
+ * (end of animation loop) if props changed before end of animation
1285
+ */
1286
+ componentDidMount() {
1080
1287
  this.interval = setInterval(() => {
1081
1288
  const statusFromState = this.state.status;
1082
1289
  const sizeFromState = this.state.size;
@@ -1176,7 +1383,7 @@ ProcessIndicator.defaultProps = {
1176
1383
  };
1177
1384
  var ProcessIndicator$1 = ProcessIndicator;
1178
1385
 
1179
- var messages$d = reactIntl.defineMessages({
1386
+ var messages$b = reactIntl.defineMessages({
1180
1387
  loadingAriaLabel: {
1181
1388
  id: "neptune.Button.loadingAriaLabel"
1182
1389
  }
@@ -1193,18 +1400,6 @@ const priorityClassMap = {
1193
1400
  [exports.Priority.TERTIARY]: 'btn-priority-3'
1194
1401
  };
1195
1402
 
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
-
1208
1403
  const deprecatedTypeMap = {
1209
1404
  [exports.Type.PRIMARY]: exports.ControlType.ACCENT,
1210
1405
  [exports.Type.SECONDARY]: exports.ControlType.ACCENT,
@@ -1307,7 +1502,7 @@ const Button = /*#__PURE__*/React.forwardRef(({
1307
1502
  className: classes,
1308
1503
  ...props,
1309
1504
  "aria-live": loading ? 'polite' : 'off',
1310
- "aria-label": loading ? intl.formatMessage(messages$d.loadingAriaLabel) : rest['aria-label'],
1505
+ "aria-label": loading ? intl.formatMessage(messages$b.loadingAriaLabel) : rest['aria-label'],
1311
1506
  children: [children, loading && /*#__PURE__*/jsxRuntime.jsx(ProcessIndicator$1, {
1312
1507
  size: processIndicatorSize(),
1313
1508
  className: "btn-loader"
@@ -1315,1504 +1510,972 @@ const Button = /*#__PURE__*/React.forwardRef(({
1315
1510
  });
1316
1511
  });
1317
1512
 
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';
1513
+ const Card$1 = /*#__PURE__*/React.forwardRef((props, reference) => {
1335
1514
  const {
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)
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
1348
1558
  })]
1349
1559
  });
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
1350
1576
  };
1351
-
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'
1577
+ Card$1.defaultProps = {
1578
+ 'aria-label': undefined,
1579
+ as: 'div',
1580
+ children: null,
1581
+ id: null,
1582
+ className: null,
1583
+ 'data-testid': null
1359
1584
  };
1360
- function Title({
1361
- as,
1362
- type = DEFAULT_TYPE,
1585
+ var Card$2 = Card$1;
1586
+
1587
+ const CheckboxButton = /*#__PURE__*/React.forwardRef(({
1588
+ checked,
1363
1589
  className,
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
- }
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;
1381
1610
 
1382
- const HeaderAction = ({
1383
- action
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
1384
1623
  }) => {
1385
1624
  const {
1386
1625
  isModern
1387
1626
  } = componentsTheming.useTheme();
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
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
+ })
1411
1664
  });
1412
1665
  };
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
- })]
1446
- });
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
1447
1678
  };
1448
-
1449
- const useConditionalListener = ({
1450
- attachListener,
1451
- callback,
1452
- eventType,
1453
- parent
1454
- }) => {
1455
- React.useEffect(() => {
1456
- if (attachListener && !neptuneValidation.isUndefined(parent)) {
1457
- parent.addEventListener(eventType, callback, true);
1458
- }
1459
- return () => {
1460
- if (!neptuneValidation.isUndefined(parent)) {
1461
- parent.removeEventListener(eventType, callback, true);
1462
- }
1463
- };
1464
- }, [attachListener, callback, eventType, parent]);
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
1465
1689
  };
1466
1690
 
1467
- const DirectionContext = /*#__PURE__*/React.createContext(exports.Direction.LTR);
1468
- const DirectionProvider = ({
1469
- direction,
1470
- children
1471
- }) => {
1472
- return /*#__PURE__*/jsxRuntime.jsx(DirectionContext.Provider, {
1473
- value: direction,
1474
- children: children
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
+ })
1475
1706
  });
1476
- };
1477
-
1478
- const useDirection = () => {
1479
- const direction = React.useContext(DirectionContext);
1480
- return {
1481
- direction,
1482
- isRTL: direction === 'rtl'
1483
- };
1484
- };
1485
-
1486
- const ObserverParams = {
1487
- threshold: 0.1
1488
- };
1707
+ });
1489
1708
 
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
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
1504
1720
  }) => {
1505
- const [hasIntersected, setHasIntersected] = React.useState(false);
1721
+ const isActionable = onClick || onKeyPress;
1722
+ const defaultRole = isActionable ? 'button' : undefined;
1723
+ const tabIndex = isActionable ? 0 : -1;
1506
1724
  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
- }
1518
- });
1519
- };
1725
+ isModern
1726
+ } = componentsTheming.useTheme();
1727
+ const closeButtonReference = React.useRef(null);
1728
+ const previousCloseButtonShown = React.useRef();
1520
1729
  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);
1730
+ if (closeButtonReference.current != null && previousCloseButtonShown.current === false) {
1731
+ closeButtonReference.current?.focus();
1530
1732
  }
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];
1542
- };
1543
-
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)`);
1557
- }
1558
-
1559
- /**
1560
- * @deprecated Prefer `useScreenSize` instead.
1561
- */
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
- };
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);
1576
1762
  };
1577
1763
 
1578
- var messages$b = reactIntl.defineMessages({
1764
+ var messages$a = reactIntl.defineMessages({
1579
1765
  ariaLabel: {
1580
- id: "neptune.CloseButton.ariaLabel"
1766
+ id: "neptune.Chips.ariaLabel"
1581
1767
  }
1582
1768
  });
1583
1769
 
1584
- const CloseButton = /*#__PURE__*/React.forwardRef(function CloseButton({
1770
+ const Chips = ({
1771
+ chips,
1772
+ onChange,
1773
+ selected,
1585
1774
  'aria-label': ariaLabel,
1586
- size = exports.Size.MEDIUM,
1587
- filled = false,
1588
1775
  className,
1589
- onClick,
1590
- isDisabled,
1591
- testId
1592
- }, reference) {
1776
+ multiple
1777
+ }) => {
1593
1778
  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),
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),
1603
1788
  "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
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);
1610
1814
  })
1611
1815
  });
1612
- });
1816
+ };
1613
1817
 
1614
- const EXIT_ANIMATION = 350;
1615
- const SlidingPanel = /*#__PURE__*/React.forwardRef(({
1616
- position = 'left',
1617
- open,
1618
- showSlidingPanelBorder,
1619
- slidingPanelPositionFixed,
1818
+ const CircularButton = ({
1620
1819
  className,
1621
1820
  children,
1821
+ disabled,
1822
+ icon,
1823
+ priority = exports.Priority.PRIMARY,
1824
+ type = exports.ControlType.ACCENT,
1622
1825
  ...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
- });
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
+ });
1846
+ };
1646
1847
 
1647
- const Drawer = ({
1648
- children,
1649
- className,
1650
- footerContent,
1651
- headerTitle,
1652
- onClose,
1653
- open,
1654
- position
1848
+ const FocusBoundary = ({
1849
+ children
1655
1850
  }) => {
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, {
1662
- open: open,
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
- })]
1690
- })
1851
+ const wrapperReference = React.useRef(null);
1852
+ React.useEffect(() => {
1853
+ wrapperReference.current?.focus({
1854
+ preventScroll: true
1855
+ });
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
1691
1864
  })
1692
1865
  });
1693
1866
  };
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'])
1708
- };
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
1717
- };
1718
- var Drawer$1 = Drawer;
1719
1867
 
1720
- const INITIAL_Y_POSITION = 0;
1721
- const CONTENT_SCROLL_THRESHOLD = 1;
1722
- const MOVE_OFFSET_THRESHOLD = 50;
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
+ };
1878
+ }
1879
+
1723
1880
  /**
1724
- * Neptune: https://transferwise.github.io/neptune/components/bottom-sheet/
1725
- *
1726
- * Neptune Web: https://transferwise.github.io/neptune-web/components/overlays/BottomSheet
1727
- *
1881
+ * Dimmer state management inspired by Material UI's ModalManager (https://github.com/mui-org/material-ui)
1728
1882
  */
1729
- const BottomSheet$1 = props => {
1730
- const bottomSheetReference = React.useRef(null);
1731
- const topBarReference = React.useRef(null);
1732
- const contentReference = React.useRef(null);
1733
- const [pressed, setPressed] = React.useState(false);
1734
- /**
1735
- * Used to track `requestAnimationFrame` requests
1736
- *
1737
- * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame#return_value
1738
- */
1739
- const animationId = React.useRef(0);
1883
+ class DimmerManager {
1740
1884
  /**
1741
- * Difference between initial coordinate ({@link initialYCoordinate})
1742
- * and new position (when user moves component), it's get calculated on `onTouchMove` and `onMouseMove` events
1743
- *
1744
- * @see {@link calculateOffsetAfterMove}
1885
+ * Dimmer refs
1745
1886
  */
1746
- const moveOffset = React.useRef(0);
1747
- const initialYCoordinate = React.useRef(0);
1748
- // apply shadow to the bottom of top-bar when scroll over content
1749
- useConditionalListener({
1750
- attachListener: props.open && !isServerSide(),
1751
- callback: () => {
1752
- if (topBarReference.current !== null) {
1753
- const {
1754
- classList
1755
- } = topBarReference.current;
1756
- if (!isContentScrollPositionAtTop()) {
1757
- classList.add('np-bottom-sheet--top-bar--shadow');
1758
- } else {
1759
- classList.remove('np-bottom-sheet--top-bar--shadow');
1760
- }
1761
- }
1762
- },
1763
- eventType: 'scroll',
1764
- parent: isServerSide() ? undefined : document
1765
- });
1766
- function move(newHeight) {
1767
- if (bottomSheetReference.current !== null) {
1768
- bottomSheetReference.current.style.transform = `translateY(${newHeight}px)`;
1769
- }
1887
+ dimmers;
1888
+ constructor() {
1889
+ this.dimmers = [];
1770
1890
  }
1771
- function close(event) {
1772
- setPressed(false);
1773
- moveOffset.current = INITIAL_Y_POSITION;
1774
- if (bottomSheetReference.current !== null) {
1775
- bottomSheetReference.current.style.removeProperty('transform');
1891
+ add(dimmer) {
1892
+ let dimmerIndex = this.dimmers.indexOf(dimmer);
1893
+ if (dimmerIndex !== -1) {
1894
+ return dimmerIndex;
1776
1895
  }
1777
- if (props.onClose) {
1778
- props.onClose(event);
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);
1779
1904
  }
1905
+ return dimmerIndex;
1780
1906
  }
1781
- const onSwipeStart = event => {
1782
- initialYCoordinate.current = ('touches' in event ? event.touches[0] : event).clientY;
1783
- setPressed(true);
1907
+ isTop(dimmer) {
1908
+ return this.dimmers.length > 0 && this.dimmers[this.dimmers.length - 1] === dimmer;
1909
+ }
1910
+ }
1911
+
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();
1922
+ }
1923
+ };
1924
+ const Dimmer = ({
1925
+ children,
1926
+ className,
1927
+ disableClickToClose = false,
1928
+ contentPosition,
1929
+ fadeContentOnEnter = false,
1930
+ fadeContentOnExit = false,
1931
+ open = false,
1932
+ scrollable = false,
1933
+ transparent = false,
1934
+ onClose
1935
+ }) => {
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
+ }
1784
1942
  };
1785
- const onSwipeMove = event => {
1786
- if (pressed) {
1787
- const {
1788
- clientY
1789
- } = 'touches' in event ? event.touches[0] : event;
1790
- const offset = calculateOffsetAfterMove(clientY);
1791
- // check whether move is to the bottom only and content scroll position is at the top
1792
- if (offset > INITIAL_Y_POSITION && isContentScrollPositionAtTop()) {
1793
- moveOffset.current = offset;
1794
- animationId.current = requestAnimationFrame(() => {
1795
- if (animationId.current !== undefined && bottomSheetReference.current !== null) {
1796
- move(offset);
1797
- }
1798
- });
1799
- }
1943
+ const handleClick = event => {
1944
+ if (disableClickToClose || !onClose) {
1945
+ return;
1800
1946
  }
1947
+ closeOnClick(event);
1801
1948
  };
1802
- function onSwipeEnd(event) {
1803
- // stop moving component
1804
- cancelAnimationFrame(animationId.current);
1805
- setPressed(false);
1806
- // check whether move down is strong enough
1807
- // and content scroll position is at the top to close the component
1808
- if (moveOffset.current > MOVE_OFFSET_THRESHOLD && isContentScrollPositionAtTop()) {
1809
- close(event);
1949
+ const handleKeyDown = React.useCallback(event => {
1950
+ if (event.key !== 'Escape') {
1951
+ return;
1810
1952
  }
1811
- // otherwise move component back to default (initial) position
1812
- else {
1813
- move(INITIAL_Y_POSITION);
1953
+ event.stopPropagation();
1954
+ if (onClose && dimmerReference.current && dimmerManager.isTop(dimmerReference.current)) {
1955
+ onClose(event);
1814
1956
  }
1815
- moveOffset.current = INITIAL_Y_POSITION;
1816
- }
1817
- function isContentScrollPositionAtTop() {
1818
- return contentReference?.current?.scrollTop !== undefined && contentReference.current.scrollTop <= CONTENT_SCROLL_THRESHOLD;
1819
- }
1820
- /**
1821
- * Calculates how hard user moves component,
1822
- * result value used to determine whether to hide component or re-position to default state
1823
- *
1824
- * @param afterMoveYCoordinate
1825
- */
1826
- function calculateOffsetAfterMove(afterMoveYCoordinate) {
1827
- return afterMoveYCoordinate - initialYCoordinate.current;
1828
- }
1829
- /**
1830
- * Set `max-height` for content part (in order to keep it scrollable for content overflow cases) of the component
1831
- * and ensures space for safe zone (32px) at the top.
1832
- */
1833
- function setContentMaxHeight() {
1834
- const safeZoneHeight = '64px';
1835
- const topbarHeight = '32px';
1836
- const windowHight = isServerSide() ? 0 : window.innerHeight;
1837
- /**
1838
- * Calculate _real_ height of the screen (taking into account parts of browser interface).
1839
- *
1840
- * See https://css-tricks.com/the-trick-to-viewport-units-on-mobile for more details.
1841
- */
1842
- const screenHeight = `${windowHight * 0.01 * 100}px`;
1843
- return {
1844
- maxHeight: `calc(${screenHeight} - ${safeZoneHeight} - ${topbarHeight})`
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);
1845
1981
  };
1846
- }
1847
- const is400Zoom = useMedia(`(max-width: ${exports.Breakpoint.ZOOM_400}px)`);
1848
- return is400Zoom ? /*#__PURE__*/jsxRuntime.jsx(Drawer$1, {
1849
- open: props.open,
1850
- className: props.className,
1851
- onClose: close,
1852
- children: props.children
1853
- }) : /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
1854
- open: props.open,
1855
- fadeContentOnEnter: true,
1856
- fadeContentOnExit: true,
1857
- onClose: close,
1858
- children: /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
1859
- ref: bottomSheetReference,
1860
- open: props.open,
1861
- position: exports.Position.BOTTOM,
1862
- className: classNames__default.default('np-bottom-sheet', props.className),
1863
- children: /*#__PURE__*/jsxRuntime.jsxs("div", {
1864
- role: "dialog",
1865
- "aria-modal": true,
1866
- onTouchStart: onSwipeStart,
1867
- onTouchMove: onSwipeMove,
1868
- onTouchEnd: onSwipeEnd,
1869
- onMouseDown: onSwipeStart,
1870
- onMouseMove: onSwipeMove,
1871
- onMouseUp: onSwipeEnd,
1872
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
1873
- ref: topBarReference,
1874
- className: "np-bottom-sheet--top-bar",
1875
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1876
- className: "np-bottom-sheet--handler"
1877
- }), /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
1878
- size: "sm",
1879
- className: "sr-only np-bottom-sheet--close-btn",
1880
- onClick: close
1881
- })]
1882
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
1883
- ref: contentReference,
1884
- style: setContentMaxHeight(),
1885
- className: "np-bottom-sheet--content",
1886
- children: props.children
1887
- })]
1982
+ }, [handleKeyDown, open]);
1983
+ return /*#__PURE__*/jsxRuntime.jsx(DimmerWrapper, {
1984
+ 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
+ })
1888
2031
  })
1889
2032
  })
1890
2033
  });
1891
2034
  };
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) {
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
+ }
1901
2061
  return () => {
1902
- console.log('handleOnClick', status);
1903
- setShowMenu(status);
2062
+ if (scrollBody) {
2063
+ removeNoScrollClass();
2064
+ }
1904
2065
  };
1905
- }
1906
- function handleOnSelect(data) {
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
+ }
1907
2081
  return () => {
1908
- setShowMenu(false);
1909
- setSelected(data);
2082
+ if (!neptuneValidation.isUndefined(parent)) {
2083
+ parent.removeEventListener(eventType, callback, true);
2084
+ }
1910
2085
  };
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
- showMediaAtAllSizes: true,
1921
- media: /*#__PURE__*/jsxRuntime.jsx(art.Flag, {
1922
- code: "gbp"
1923
- }),
1924
- title: "Wise GBP balance",
1925
- content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1926
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1927
- children: "300 GBP available"
1928
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
1929
- children: "0 GBP in fees, should arrive in seconds"
1930
- })]
1931
- }),
1932
- onClick: handleOnSelect({
1933
- media: /*#__PURE__*/jsxRuntime.jsx(art.Flag, {
1934
- code: "gbp"
1935
- }),
1936
- title: 'Wise GBP balance'
1937
- })
1938
- }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1939
- media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1940
- title: "Credit card",
1941
- content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1942
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
1943
- children: "Transfer the money to Wise using your bank account."
1944
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
1945
- children: "0.32 GBP in fees, should arrive in seconds"
1946
- })]
1947
- }),
1948
- onClick: handleOnSelect({
1949
- media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1950
- title: 'Credit card',
1951
- content: 'Pay with your credit card'
1952
- })
1953
- }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1954
- media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1955
- title: "Debit card",
1956
- content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1957
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1958
- children: "Send from your Visa or Mastercard."
1959
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
1960
- children: "0.74 GBP in fees, should arrive in seconds"
1961
- })]
1962
- }),
1963
- onClick: handleOnSelect({
1964
- media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1965
- title: 'Debit card',
1966
- content: 'Pay with your debit card'
1967
- })
1968
- }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1969
- media: /*#__PURE__*/jsxRuntime.jsx(icons.Bank, {}),
1970
- title: "Swift Transfer",
1971
- content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1972
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1973
- children: "Send money internationally. Your bank will charge you extra fees."
1974
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
1975
- children: "0.32 GBP in fees, should arrive by Thursday"
1976
- })]
1977
- })
1978
- }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1979
- media: /*#__PURE__*/jsxRuntime.jsx(icons.BankTransfer, {}),
1980
- title: "Bank Transfer",
1981
- content: /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
1982
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
1983
- children: "Transfer the money to Wise using your bank account."
1984
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
1985
- children: "0.32 GBP in fees, should arrive in seconds"
1986
- })]
1987
- })
1988
- }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1989
- media: /*#__PURE__*/jsxRuntime.jsx(icons.Card, {}),
1990
- title: "Debit card"
1991
- }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1992
- media: /*#__PURE__*/jsxRuntime.jsx(icons.Bank, {}),
1993
- title: "Swift"
1994
- }), /*#__PURE__*/jsxRuntime.jsx(Option$2, {
1995
- media: /*#__PURE__*/jsxRuntime.jsx(icons.BankTransfer, {}),
1996
- title: "Bank Transfer"
1997
- })]
1998
- });
1999
- return /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
2000
- children: [/*#__PURE__*/jsxRuntime.jsx(Option$2, {
2001
- ref: rootRef,
2002
- media: isSelected ? selected.media : props.media,
2003
- title: isSelected ? selected.title : props.title,
2004
- content: isSelected ? selected.content : props.content,
2005
- className: classNames__default.default('np-select-option', {
2006
- 'np-select-option-selected': isSelected
2007
- }, props.className),
2008
- button: isSelected ? /*#__PURE__*/jsxRuntime.jsx(Chevron, {}) : /*#__PURE__*/jsxRuntime.jsx(ActionButton, {
2009
- onClick: handleOnClick(true),
2010
- children: "Choose"
2011
- }),
2012
- onClick: isSelected ? handleOnClick(true) : undefined
2013
- }), isMobile ? /*#__PURE__*/jsxRuntime.jsx(BottomSheet$1, {
2014
- open: showMenu,
2015
- onClose: handleOnClick(false),
2016
- children: options
2017
- }) : /*#__PURE__*/jsxRuntime.jsx(Panel, {
2018
- open: showMenu,
2019
- flip: false,
2020
- altAxis: true,
2021
- anchorRef: rootRef,
2022
- anchorWidth: false,
2023
- position: exports.Position.BOTTOM,
2024
- onClose: handleOnClick(false),
2025
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
2026
- className: "np-select-option-list p-a-2",
2027
- children: options
2028
- })
2029
- })]
2030
- });
2031
- }
2032
-
2033
- const iconTypeMap = {
2034
- positive: icons.Check,
2035
- neutral: icons.Info,
2036
- warning: icons.Alert,
2037
- negative: icons.Cross,
2038
- pending: icons.ClockBorderless,
2039
- info: icons.Info,
2040
- error: icons.Cross,
2041
- success: icons.Check
2086
+ }, [attachListener, callback, eventType, parent]);
2042
2087
  };
2043
- const StatusIcon = ({
2044
- sentiment = 'neutral',
2045
- size = 'md'
2088
+
2089
+ const DirectionContext = /*#__PURE__*/React.createContext(exports.Direction.LTR);
2090
+ const DirectionProvider = ({
2091
+ direction,
2092
+ children
2046
2093
  }) => {
2047
- const Icon = iconTypeMap[sentiment];
2048
- const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
2049
- return /*#__PURE__*/jsxRuntime.jsx("span", {
2050
- "data-testid": "status-icon",
2051
- className: classNames__default.default('status-circle', 'status-circle-' + size, sentiment),
2052
- children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
2053
- className: classNames__default.default('status-icon', iconColor)
2054
- })
2094
+ return /*#__PURE__*/jsxRuntime.jsx(DirectionContext.Provider, {
2095
+ value: direction,
2096
+ children: children
2055
2097
  });
2056
2098
  };
2057
2099
 
2058
- const reader = new commonmark__default.default.Parser();
2059
- const writer = new commonmark__default.default.HtmlRenderer({
2060
- safe: true
2061
- });
2062
- const NODE_TYPE_LIST = Object.values(exports.MarkdownNodeType);
2063
- function Markdown({
2064
- as: Element = 'div',
2065
- allowList,
2066
- blockList,
2067
- config,
2068
- className,
2069
- children
2070
- }) {
2071
- if (!children) {
2072
- return null;
2073
- }
2074
- const linkTarget = config?.link?.target ?? '_self';
2075
- const paragraphClass = config?.paragraph?.className ?? '';
2076
- if (allowList != null && blockList != null) {
2077
- logActionRequired('Markdown supports only one of `allowList` or `blockList` to be used at a time. `blockList` will be ignored.');
2078
- }
2079
- const parser = nodes => {
2080
- const parsed = reader.parse(nodes);
2081
- const toExclude = allowList != null ? NODE_TYPE_LIST.filter(type => !allowList.includes(type)) : blockList;
2082
- return toExclude != null ? stripNodes({
2083
- parsed,
2084
- blockList: toExclude
2085
- }) : parsed;
2086
- };
2087
- const createMarkup = () => {
2088
- const parsed = parser(children);
2089
- return writer.render(parsed).replace(/<a href="/g, `<a target="${linkTarget}" href="`).replace(/<p>/g, `<p class="${paragraphClass}">`);
2100
+ const useDirection = () => {
2101
+ const direction = React.useContext(DirectionContext);
2102
+ return {
2103
+ direction,
2104
+ isRTL: direction === 'rtl'
2090
2105
  };
2091
- return /*#__PURE__*/jsxRuntime.jsx(Element, {
2092
- className: className,
2093
- dangerouslySetInnerHTML: {
2094
- __html: createMarkup()
2095
- }
2096
- });
2097
- }
2098
- function stripNodes({
2099
- blockList,
2100
- parsed
2101
- }) {
2102
- if (!parsed) {
2103
- return parsed;
2104
- }
2105
- const walker = parsed.walker();
2106
- for (let event = walker.next(); event != null; event = walker.next()) {
2107
- const {
2108
- node
2109
- } = event;
2110
- if (blockList.includes(node.type) && !event.entering) {
2111
- while (node.firstChild != null) {
2112
- node.insertBefore(node.firstChild);
2113
- }
2114
- node.unlink();
2115
- }
2116
- }
2117
- return parsed;
2118
- }
2119
-
2120
- const allowList = [exports.MarkdownNodeType.STRONG];
2121
- const InlineMarkdown = props => {
2122
- return /*#__PURE__*/jsxRuntime.jsx(Markdown, {
2123
- ...props,
2124
- as: "span",
2125
- allowList: allowList,
2126
- blockList: undefined
2127
- });
2128
- };
2129
- InlineMarkdown.propTypes = {
2130
- children: PropTypes__default.default.string.isRequired,
2131
- className: PropTypes__default.default.string
2132
2106
  };
2133
- InlineMarkdown.defaultProps = {
2134
- className: undefined
2107
+
2108
+ const ObserverParams = {
2109
+ threshold: 0.1
2135
2110
  };
2136
2111
 
2137
- exports.AlertArrowPosition = void 0;
2138
- (function (AlertArrowPosition) {
2139
- AlertArrowPosition["TOP_LEFT"] = "up-left";
2140
- AlertArrowPosition["TOP"] = "up-center";
2141
- AlertArrowPosition["TOP_RIGHT"] = "up-right";
2142
- AlertArrowPosition["BOTTOM_LEFT"] = "down-left";
2143
- AlertArrowPosition["BOTTOM"] = "down-center";
2144
- AlertArrowPosition["BOTTOM_RIGHT"] = "down-right";
2145
- })(exports.AlertArrowPosition || (exports.AlertArrowPosition = {}));
2146
- function resolveType(type) {
2147
- switch (type) {
2148
- case 'success':
2149
- return 'positive';
2150
- case 'info':
2151
- return 'neutral';
2152
- case 'error':
2153
- return 'negative';
2154
- default:
2155
- return type;
2156
- }
2157
- }
2158
- function Alert({
2159
- arrow,
2160
- action,
2161
- children,
2162
- className,
2163
- dismissible,
2164
- icon,
2165
- onDismiss,
2166
- message,
2167
- size,
2168
- title,
2169
- type = 'neutral',
2170
- variant = 'desktop'
2171
- }) {
2172
- React.useEffect(() => {
2173
- if (arrow !== undefined) {
2174
- logActionRequired("Alert component doesn't support 'arrow' anymore, use 'InlineAlert' instead.");
2175
- }
2176
- }, [arrow]);
2177
- React.useEffect(() => {
2178
- if (children !== undefined) {
2179
- logActionRequired("Alert component doesn't support 'children' anymore, use 'message' instead.");
2180
- }
2181
- }, [children]);
2182
- React.useEffect(() => {
2183
- if (dismissible !== undefined) {
2184
- logActionRequired("Alert component doesn't support 'dismissible' anymore, use 'onDismiss' instead.");
2185
- }
2186
- }, [dismissible]);
2187
- React.useEffect(() => {
2188
- if (size !== undefined) {
2189
- logActionRequired("Alert component doesn't support 'size' anymore, please remove that prop.");
2190
- }
2191
- }, [size]);
2192
- const resolvedType = resolveType(type);
2112
+ /**
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
+ };
2193
2142
  React.useEffect(() => {
2194
- if (resolvedType !== type) {
2195
- logActionRequired(`Alert component has deprecated '${type}' value for the 'type' prop. Please use '${resolvedType}' instead.`);
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);
2196
2152
  }
2197
- }, [resolvedType, type]);
2198
- const [shouldFire, setShouldFire] = React.useState(false);
2199
- const closeButtonReference = React.useRef(null);
2200
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
2201
- className: classNames__default.default('alert d-flex', `alert-${resolvedType}`, arrow != null && alertArrowClassNames(arrow), className),
2202
- "data-testid": "alert",
2203
- onTouchStart: () => setShouldFire(true),
2204
- onTouchEnd: event => {
2205
- if (shouldFire && action &&
2206
- // Check if current event is triggered from closeButton
2207
- event.target instanceof Node && closeButtonReference.current && !closeButtonReference.current.contains(event.target)) {
2208
- if (action.target === '_blank') {
2209
- window.top?.open(action.href);
2210
- } else {
2211
- window.top?.location.assign(action.href);
2212
- }
2153
+ return () => {
2154
+ didCancel = true;
2155
+ if (observer) {
2156
+ observer.unobserve(current);
2213
2157
  }
2214
- setShouldFire(false);
2215
- },
2216
- onTouchMove: () => setShouldFire(false),
2217
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2218
- className: classNames__default.default('alert__content', 'd-flex', 'flex-grow-1', variant),
2219
- "data-testid": variant,
2220
- children: [icon ? /*#__PURE__*/jsxRuntime.jsx("div", {
2221
- className: "alert__icon",
2222
- children: icon
2223
- }) : /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
2224
- size: exports.Size.LARGE,
2225
- sentiment: resolvedType
2226
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
2227
- className: "alert__message",
2228
- children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2229
- role: exports.Sentiment.NEGATIVE === resolvedType ? 'alert' : 'status',
2230
- children: [title && /*#__PURE__*/jsxRuntime.jsx(Title, {
2231
- className: "m-b-1",
2232
- type: exports.Typography.TITLE_BODY,
2233
- children: title
2234
- }), /*#__PURE__*/jsxRuntime.jsx(Body, {
2235
- as: "span",
2236
- className: "d-block",
2237
- type: exports.Typography.BODY_LARGE,
2238
- children: children || /*#__PURE__*/jsxRuntime.jsx(InlineMarkdown, {
2239
- children: message
2240
- })
2241
- })]
2242
- }), action && /*#__PURE__*/jsxRuntime.jsx(Link, {
2243
- href: action.href,
2244
- className: "m-t-1",
2245
- "aria-label": action['aria-label'],
2246
- target: action.target,
2247
- type: exports.Typography.LINK_LARGE,
2248
- children: action.text
2249
- })]
2250
- })]
2251
- }), onDismiss && /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2252
- ref: closeButtonReference,
2253
- className: "m-l-2",
2254
- onClick: onDismiss
2255
- })]
2256
- });
2257
- }
2258
- function alertArrowClassNames(arrow) {
2259
- switch (arrow) {
2260
- case 'down-center':
2261
- return 'arrow arrow-bottom arrow-center';
2262
- case 'down-left':
2263
- return 'arrow arrow-bottom arrow-left';
2264
- case 'down-right':
2265
- return 'arrow arrow-bottom arrow-right';
2266
- case 'up-center':
2267
- return 'arrow arrow-center';
2268
- case 'up-right':
2269
- return 'arrow arrow-right';
2270
- case 'up-left':
2271
- default:
2272
- return 'arrow';
2158
+ };
2159
+ }, [elRef]);
2160
+ if (loading === 'eager') {
2161
+ return [false];
2273
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);
2274
2175
  }
2275
2176
 
2276
- // TODO: consider to move this enum into component file once we migrate it on TypeScript or replace with some common enum
2277
- exports.AvatarType = void 0;
2278
- (function (AvatarType) {
2279
- AvatarType["THUMBNAIL"] = "thumbnail";
2280
- AvatarType["ICON"] = "icon";
2281
- AvatarType["EMOJI"] = "emoji";
2282
- AvatarType["INITIALS"] = "initials";
2283
- })(exports.AvatarType || (exports.AvatarType = {}));
2177
+ function useScreenSize(size) {
2178
+ return useMedia(`(min-width: ${size}px)`);
2179
+ }
2284
2180
 
2285
- /*
2286
- * The colors we support generating an Avatar background color from a "seed" for.
2287
- * Changing this array will change the assignment between seeds.
2288
- * Do not change this array.
2181
+ /**
2182
+ * @deprecated Prefer `useScreenSize` instead.
2289
2183
  */
2290
- const avatarColors = ['--color-bright-blue', '--color-bright-yellow', '--color-bright-pink', '--color-bright-orange'];
2291
- /*
2292
- * Takes in a "seed" string and spits out an index for the color we should use.
2293
- * This implementation has been synced across all three clients so that we consistently
2294
- * generate branded avatar colors when rendering a list of Avatars.
2295
- * Do not change this implementation.
2296
- */
2297
- const hashSeed = seed => {
2298
- const base = 31;
2299
- const modulo = avatarColors.length;
2300
- let hashValue = 0;
2301
- let basePow = 1;
2302
- for (let i = 0; i < seed.length; i += 1) {
2303
- hashValue = (hashValue + seed.charCodeAt(i) * basePow) % modulo;
2304
- basePow = basePow * base % modulo;
2305
- }
2306
- return hashValue;
2307
- };
2308
- const getAvatarColorFromSeed = seed => {
2309
- return avatarColors[hashSeed(seed)];
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
+ };
2310
2198
  };
2311
2199
 
2312
- const backwardsCompatibleSize = size => {
2313
- switch (size) {
2314
- case 'sm':
2315
- return 24;
2316
- case 'md':
2317
- return 48;
2318
- case 'lg':
2319
- return 72;
2320
- default:
2321
- return size;
2322
- }
2323
- };
2324
- const Avatar = ({
2325
- backgroundColor = null,
2326
- backgroundColorSeed = null,
2327
- children = null,
2200
+ const EXIT_ANIMATION = 350;
2201
+ const SlidingPanel = /*#__PURE__*/React.forwardRef(({
2202
+ position = 'left',
2203
+ open,
2204
+ showSlidingPanelBorder,
2205
+ slidingPanelPositionFixed,
2328
2206
  className,
2329
- outlined = false,
2330
- size: sizeFromProps = 48,
2331
- theme = exports.Theme.LIGHT,
2332
- type = 'thumbnail'
2333
- }) => {
2334
- const backgroundColorFromSeed = React.useMemo(() => !backgroundColor && backgroundColorSeed ? `var(${getAvatarColorFromSeed(backgroundColorSeed)})` : undefined, [backgroundColor, backgroundColorSeed]);
2335
- const size = backwardsCompatibleSize(sizeFromProps);
2336
- return /*#__PURE__*/jsxRuntime.jsx("div", {
2337
- className: classNames__default.default('tw-avatar', className, `tw-avatar--${size}`, `tw-avatar--${type}`, {
2338
- 'tw-avatar--outlined': outlined,
2339
- 'tw-avatar--branded': Boolean(backgroundColorFromSeed),
2340
- 'np-text-title-body': type === 'initials'
2341
- }),
2342
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
2343
- className: "tw-avatar__content",
2344
- style: {
2345
- backgroundColor: backgroundColor || backgroundColorFromSeed
2346
- },
2347
- children: children
2348
- })
2349
- });
2350
- };
2351
-
2352
- const Badge = ({
2353
- badge,
2354
- className = undefined,
2355
- size = exports.Size.SMALL,
2356
- border = exports.Theme.LIGHT,
2357
- children
2358
- }) => {
2359
- const classes = classNames__default.default('tw-badge', {
2360
- [`tw-badge-border-${border}`]: border,
2361
- [`tw-badge-${size}`]: size
2362
- }, className);
2363
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
2364
- className: classes,
2365
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2366
- className: "tw-badge__children",
2367
- children: children
2368
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
2369
- className: "tw-badge__content",
2370
- children: badge
2371
- })]
2372
- });
2373
- };
2374
-
2375
- const OptionalBadge = ({
2376
- url,
2377
- altText,
2378
- statusIcon,
2379
2207
  children,
2380
2208
  ...rest
2381
- }) => {
2382
- if (url) {
2383
- return /*#__PURE__*/jsxRuntime.jsx(Badge, {
2384
- badge: /*#__PURE__*/jsxRuntime.jsx("img", {
2385
- src: url,
2386
- alt: altText
2387
- }),
2388
- ...rest,
2389
- children: children
2390
- });
2391
- }
2392
- if (statusIcon) {
2393
- return /*#__PURE__*/jsxRuntime.jsx(Badge, {
2394
- badge: /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
2395
- sentiment: statusIcon,
2396
- size: exports.Size.SMALL
2397
- }),
2398
- ...rest,
2399
- children: children
2400
- });
2401
- }
2402
- return /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
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),
2403
2229
  children: children
2404
- });
2405
- };
2406
- const AvatarWrapper = ({
2407
- url,
2408
- profileType,
2409
- profileId,
2410
- badgeUrl,
2411
- badgeAltText,
2412
- badgeStatusIcon,
2413
- name,
2414
- avatarProps,
2415
- badgeProps
2230
+ }));
2231
+ });
2232
+
2233
+ const Drawer = ({
2234
+ children,
2235
+ className,
2236
+ footerContent,
2237
+ headerTitle,
2238
+ onClose,
2239
+ open,
2240
+ position
2416
2241
  }) => {
2417
- const [hasImageLoadError, setImageLoadError] = React.useState(false);
2418
- const isBusinessProfile = profileType === exports.ProfileType.BUSINESS;
2419
- // Reset the errored state when url changes
2420
- React.useEffect(() => setImageLoadError(false), [url]);
2421
- const getAvatarProps = () => {
2422
- if (url && !hasImageLoadError) {
2423
- return {
2424
- type: exports.AvatarType.THUMBNAIL,
2425
- children: /*#__PURE__*/jsxRuntime.jsx("img", {
2426
- src: url,
2427
- alt: "",
2428
- onError: () => setImageLoadError(true)
2429
- }),
2430
- ...avatarProps
2431
- };
2432
- }
2433
- if (profileType) {
2434
- return {
2435
- type: exports.AvatarType.ICON,
2436
- children: isBusinessProfile ? /*#__PURE__*/jsxRuntime.jsx(icons.Briefcase, {
2437
- size: "24"
2438
- }) : /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
2439
- size: "24"
2440
- }),
2441
- ...avatarProps
2442
- };
2443
- }
2444
- if (name) {
2445
- return {
2446
- type: exports.AvatarType.INITIALS,
2447
- children: /*#__PURE__*/jsxRuntime.jsx(jsxRuntime.Fragment, {
2448
- children: getInitials(name)
2449
- }),
2450
- backgroundColorSeed: profileId?.toString(),
2451
- ...avatarProps
2452
- };
2453
- }
2454
- return {
2455
- type: exports.AvatarType.ICON,
2456
- children: /*#__PURE__*/jsxRuntime.jsx(icons.Person, {
2457
- size: "24"
2458
- }),
2459
- ...avatarProps
2460
- };
2461
- };
2462
- return /*#__PURE__*/jsxRuntime.jsx(OptionalBadge, {
2463
- url: badgeUrl,
2464
- altText: badgeAltText,
2465
- statusIcon: badgeStatusIcon,
2466
- ...badgeProps,
2467
- children: /*#__PURE__*/jsxRuntime.jsx(Avatar, {
2468
- size: exports.Size.MEDIUM,
2469
- ...getAvatarProps()
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
+ })
2470
2277
  })
2471
2278
  });
2472
2279
  };
2473
- function getInitials(name) {
2474
- const allInitials = name.split(' ').map(part => part[0]).join('').toUpperCase();
2475
- if (allInitials.length === 1) {
2476
- return allInitials[0];
2477
- }
2478
- return allInitials[0] + allInitials.slice(-1);
2479
- }
2480
-
2481
- const Card$1 = /*#__PURE__*/React.forwardRef((props, reference) => {
2482
- const {
2483
- 'aria-label': ariaLabel,
2484
- as: Element,
2485
- isExpanded,
2486
- title,
2487
- details,
2488
- children,
2489
- onClick,
2490
- icon,
2491
- id,
2492
- className,
2493
- ...rest
2494
- } = props;
2495
- const isOpen = !!(isExpanded && children);
2496
- return /*#__PURE__*/jsxRuntime.jsxs(Element, {
2497
- ref: reference,
2498
- className: classNames__default.default('np-card', className, {
2499
- 'np-card--expanded': isOpen,
2500
- 'np-card--inactive': !children,
2501
- 'np-card--has-icon': !!icon
2502
- }),
2503
- id: id,
2504
- "data-testid": rest['data-testid'],
2505
- children: [/*#__PURE__*/jsxRuntime.jsx(Option$2, {
2506
- "aria-label": ariaLabel,
2507
- as: children ? 'button' : 'div',
2508
- className: classNames__default.default('np-card__button'),
2509
- media: icon,
2510
- title: title,
2511
- content: details,
2512
- showMediaAtAllSizes: true,
2513
- button: children && /*#__PURE__*/jsxRuntime.jsx(Chevron, {
2514
- orientation: isOpen ? exports.Position.TOP : exports.Position.BOTTOM
2515
- }),
2516
- onClick: () => children && onClick(!isExpanded)
2517
- }), /*#__PURE__*/jsxRuntime.jsx("div", {
2518
- className: classNames__default.default('np-card__divider', {
2519
- 'np-card__divider--expanded': isOpen
2520
- })
2521
- }), isOpen && /*#__PURE__*/jsxRuntime.jsx(Body, {
2522
- as: "span",
2523
- type: exports.Typography.BODY_LARGE,
2524
- className: "np-card__content d-block",
2525
- children: children
2526
- })]
2527
- });
2528
- });
2529
- const hasChildren = ({
2530
- children
2531
- }) => children;
2532
- Card$1.propTypes = {
2533
- 'aria-label': PropTypes__default.default.string,
2534
- as: PropTypes__default.default.string,
2535
- isExpanded: requiredIf__default.default(PropTypes__default.default.bool, hasChildren),
2536
- title: PropTypes__default.default.node.isRequired,
2537
- details: PropTypes__default.default.node.isRequired,
2538
- onClick: requiredIf__default.default(PropTypes__default.default.func, hasChildren),
2539
- icon: PropTypes__default.default.node,
2280
+ Drawer.propTypes = {
2281
+ /** The content to appear in the drawer body. */
2540
2282
  children: PropTypes__default.default.node,
2541
- id: PropTypes__default.default.string,
2542
2283
  className: PropTypes__default.default.string,
2543
- 'data-testid': 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'])
2544
2294
  };
2545
- Card$1.defaultProps = {
2546
- 'aria-label': undefined,
2547
- as: 'div',
2295
+ Drawer.defaultProps = {
2548
2296
  children: null,
2549
- id: null,
2550
- className: null,
2551
- 'data-testid': null
2552
- };
2553
- var Card$2 = Card$1;
2554
-
2555
- const CheckboxButton = /*#__PURE__*/React.forwardRef(({
2556
- checked,
2557
- className,
2558
- disabled,
2559
- onChange,
2560
- ...rest
2561
- }, reference) => /*#__PURE__*/jsxRuntime.jsxs("span", {
2562
- className: classNames__default.default('np-checkbox-button', className, disabled && 'disabled'),
2563
- children: [/*#__PURE__*/jsxRuntime.jsx("input", {
2564
- ...rest,
2565
- ref: reference,
2566
- type: "checkbox",
2567
- disabled: disabled,
2568
- checked: checked,
2569
- onChange: onChange
2570
- }), /*#__PURE__*/jsxRuntime.jsx("span", {
2571
- className: "tw-checkbox-button",
2572
- children: /*#__PURE__*/jsxRuntime.jsx("span", {
2573
- className: "tw-checkbox-check"
2574
- })
2575
- })]
2576
- }));
2577
- var CheckboxButton$1 = CheckboxButton;
2578
-
2579
- const Checkbox = ({
2580
- id,
2581
- checked,
2582
- required,
2583
- disabled,
2584
- readOnly,
2585
- label,
2586
- className,
2587
- secondary,
2588
- onChange,
2589
- onFocus,
2590
- onBlur
2591
- }) => {
2592
- const {
2593
- isModern
2594
- } = componentsTheming.useTheme();
2595
- const classList = classNames__default.default('np-checkbox', {
2596
- checkbox: true,
2597
- 'checkbox-lg': secondary,
2598
- disabled: isModern && disabled
2599
- }, className);
2600
- const innerDisabled = disabled || readOnly;
2601
- return /*#__PURE__*/jsxRuntime.jsx("div", {
2602
- id: id,
2603
- className: classList,
2604
- children: /*#__PURE__*/jsxRuntime.jsxs("label", {
2605
- className: classNames__default.default({
2606
- disabled
2607
- }),
2608
- children: [/*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
2609
- className: "p-r-2",
2610
- checked: checked,
2611
- disabled: innerDisabled,
2612
- required: !innerDisabled && required,
2613
- onFocus: onFocus,
2614
- onChange: () => onChange(!checked),
2615
- onBlur: onBlur
2616
- }), /*#__PURE__*/jsxRuntime.jsxs(Body, {
2617
- as: "span",
2618
- className: "np-checkbox__text",
2619
- type: secondary ? exports.Typography.BODY_LARGE_BOLD : exports.Typography.BODY_LARGE,
2620
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
2621
- className: required ? 'has-required' : undefined,
2622
- children: label
2623
- }), secondary && /*#__PURE__*/jsxRuntime.jsx(Body, {
2624
- as: "span",
2625
- className: classNames__default.default({
2626
- secondary: !isModern
2627
- }),
2628
- children: secondary
2629
- })]
2630
- })]
2631
- })
2632
- });
2633
- };
2634
- Checkbox.propTypes = {
2635
- id: PropTypes__default.default.string,
2636
- checked: PropTypes__default.default.bool,
2637
- required: PropTypes__default.default.bool,
2638
- disabled: PropTypes__default.default.bool,
2639
- readOnly: PropTypes__default.default.bool,
2640
- label: PropTypes__default.default.node.isRequired,
2641
- secondary: PropTypes__default.default.string,
2642
- onFocus: PropTypes__default.default.func,
2643
- onChange: PropTypes__default.default.func.isRequired,
2644
- onBlur: PropTypes__default.default.func,
2645
- className: PropTypes__default.default.string
2646
- };
2647
- Checkbox.defaultProps = {
2648
- id: null,
2649
- checked: false,
2650
- required: false,
2651
- disabled: false,
2652
- readOnly: false,
2653
- secondary: null,
2654
- onFocus: null,
2655
- onBlur: null,
2656
- className: undefined
2297
+ className: undefined,
2298
+ footerContent: null,
2299
+ headerTitle: null,
2300
+ onClose: null,
2301
+ open: false,
2302
+ position: exports.Position.RIGHT
2657
2303
  };
2304
+ var Drawer$1 = Drawer;
2658
2305
 
2659
- const CheckboxOption = /*#__PURE__*/React.forwardRef(({
2660
- checked,
2661
- disabled,
2662
- onChange,
2663
- ...rest
2664
- }, reference) => {
2665
- return /*#__PURE__*/jsxRuntime.jsx(Option$2, {
2666
- ...rest,
2667
- ref: reference,
2668
- disabled: disabled,
2669
- button: /*#__PURE__*/jsxRuntime.jsx(CheckboxButton$1, {
2670
- checked: checked,
2671
- disabled: disabled,
2672
- onChange: () => onChange?.(!checked)
2673
- })
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
2313
+ *
2314
+ */
2315
+ const BottomSheet$1 = props => {
2316
+ const bottomSheetReference = React.useRef(null);
2317
+ const topBarReference = React.useRef(null);
2318
+ const contentReference = React.useRef(null);
2319
+ const [pressed, setPressed] = React.useState(false);
2320
+ /**
2321
+ * Used to track `requestAnimationFrame` requests
2322
+ *
2323
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame#return_value
2324
+ */
2325
+ const animationId = React.useRef(0);
2326
+ /**
2327
+ * Difference between initial coordinate ({@link initialYCoordinate})
2328
+ * and new position (when user moves component), it's get calculated on `onTouchMove` and `onMouseMove` events
2329
+ *
2330
+ * @see {@link calculateOffsetAfterMove}
2331
+ */
2332
+ const moveOffset = React.useRef(0);
2333
+ const initialYCoordinate = React.useRef(0);
2334
+ // apply shadow to the bottom of top-bar when scroll over content
2335
+ useConditionalListener({
2336
+ attachListener: props.open && !isServerSide(),
2337
+ callback: () => {
2338
+ if (topBarReference.current !== null) {
2339
+ const {
2340
+ classList
2341
+ } = topBarReference.current;
2342
+ if (!isContentScrollPositionAtTop()) {
2343
+ classList.add('np-bottom-sheet--top-bar--shadow');
2344
+ } else {
2345
+ classList.remove('np-bottom-sheet--top-bar--shadow');
2346
+ }
2347
+ }
2348
+ },
2349
+ eventType: 'scroll',
2350
+ parent: isServerSide() ? undefined : document
2674
2351
  });
2675
- });
2676
-
2677
- const Chip = ({
2678
- label,
2679
- value,
2680
- onRemove,
2681
- onClick,
2682
- onKeyPress,
2683
- className = undefined,
2684
- 'aria-label': ariaLabel,
2685
- 'aria-checked': ariaChecked,
2686
- role,
2687
- closeButton
2688
- }) => {
2689
- const isActionable = onClick || onKeyPress;
2690
- const defaultRole = isActionable ? 'button' : undefined;
2691
- const tabIndex = isActionable ? 0 : -1;
2692
- const {
2693
- isModern
2694
- } = componentsTheming.useTheme();
2695
- const closeButtonReference = React.useRef(null);
2696
- const previousCloseButtonShown = React.useRef();
2697
- React.useEffect(() => {
2698
- if (closeButtonReference.current != null && previousCloseButtonShown.current === false) {
2699
- closeButtonReference.current?.focus();
2352
+ function move(newHeight) {
2353
+ if (bottomSheetReference.current !== null) {
2354
+ bottomSheetReference.current.style.transform = `translateY(${newHeight}px)`;
2700
2355
  }
2701
- previousCloseButtonShown.current = closeButtonReference.current != null;
2702
- }, [onRemove]);
2703
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
2704
- role: role ?? defaultRole,
2705
- tabIndex: tabIndex,
2706
- "aria-label": ariaLabel,
2707
- "aria-checked": ariaChecked,
2708
- className: classNames__default.default('np-chip', 'd-flex', 'align-items-center', 'justify-content-between', onRemove ? 'np-chip--removable' : '', className),
2709
- ...(isActionable && {
2710
- onClick,
2711
- onKeyPress
2712
- }),
2713
- children: [isModern ? /*#__PURE__*/jsxRuntime.jsx(Body, {
2714
- "aria-hidden": !!onRemove,
2715
- type: exports.Typography.BODY_DEFAULT_BOLD,
2716
- children: label
2717
- }) : /*#__PURE__*/jsxRuntime.jsx("span", {
2718
- "aria-hidden": "false",
2719
- className: "np-chip-label",
2720
- children: label
2721
- }), onRemove ? /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2722
- ref: closeButtonReference,
2723
- className: isModern ? `btn-unstyled` : `btn-unstyled m-l-1`,
2724
- "aria-label": closeButton && closeButton['aria-label'],
2725
- size: "sm",
2726
- filled: isModern,
2727
- onClick: onRemove
2728
- }) : null]
2729
- }, value);
2730
- };
2731
-
2732
- var messages$a = reactIntl.defineMessages({
2733
- ariaLabel: {
2734
- id: "neptune.Chips.ariaLabel"
2735
2356
  }
2736
- });
2737
-
2738
- const Chips = ({
2739
- chips,
2740
- onChange,
2741
- selected,
2742
- 'aria-label': ariaLabel,
2743
- className,
2744
- multiple
2745
- }) => {
2746
- const intl = reactIntl.useIntl();
2747
- const isSelected = value => Array.isArray(selected) ? selected.includes(value) : selected === value;
2748
- const handleOnChange = (selectedValue, isCurrentlyEnabled) => {
2749
- onChange({
2750
- isEnabled: !isCurrentlyEnabled,
2751
- selectedValue
2752
- });
2357
+ function close(event) {
2358
+ setPressed(false);
2359
+ moveOffset.current = INITIAL_Y_POSITION;
2360
+ if (bottomSheetReference.current !== null) {
2361
+ bottomSheetReference.current.style.removeProperty('transform');
2362
+ }
2363
+ if (props.onClose) {
2364
+ props.onClose(event);
2365
+ }
2366
+ }
2367
+ const onSwipeStart = event => {
2368
+ initialYCoordinate.current = ('touches' in event ? event.touches[0] : event).clientY;
2369
+ setPressed(true);
2753
2370
  };
2754
- return /*#__PURE__*/jsxRuntime.jsx("div", {
2755
- className: classNames__default.default('np-chips d-flex', className),
2756
- "aria-label": ariaLabel,
2757
- role: !multiple ? 'radiogroup' : undefined,
2758
- children: chips.map(chip => {
2759
- const chipSelected = isSelected(chip.value);
2760
- return /*#__PURE__*/jsxRuntime.jsx(Chip, {
2761
- value: chip.value,
2762
- label: chip.label,
2763
- closeButton: {
2764
- 'aria-label': intl.formatMessage(messages$a.ariaLabel, {
2765
- choice: chip.label
2766
- })
2767
- },
2768
- className: classNames__default.default('text-xs-nowrap', {
2769
- 'np-chip--selected': chipSelected,
2770
- 'p-r-1': multiple && chipSelected
2771
- }),
2772
- ...(multiple && chipSelected ? {
2773
- onRemove: () => handleOnChange(chip.value, chipSelected),
2774
- 'aria-label': chip.label
2775
- } : {
2776
- onClick: () => handleOnChange(chip.value, chipSelected),
2777
- onKeyPress: () => handleOnChange(chip.value, chipSelected),
2778
- role: !multiple ? 'radio' : undefined,
2779
- 'aria-checked': chipSelected
2780
- })
2781
- }, chip.value);
2371
+ const onSwipeMove = event => {
2372
+ if (pressed) {
2373
+ const {
2374
+ clientY
2375
+ } = 'touches' in event ? event.touches[0] : event;
2376
+ const offset = calculateOffsetAfterMove(clientY);
2377
+ // check whether move is to the bottom only and content scroll position is at the top
2378
+ if (offset > INITIAL_Y_POSITION && isContentScrollPositionAtTop()) {
2379
+ moveOffset.current = offset;
2380
+ animationId.current = requestAnimationFrame(() => {
2381
+ if (animationId.current !== undefined && bottomSheetReference.current !== null) {
2382
+ move(offset);
2383
+ }
2384
+ });
2385
+ }
2386
+ }
2387
+ };
2388
+ function onSwipeEnd(event) {
2389
+ // stop moving component
2390
+ cancelAnimationFrame(animationId.current);
2391
+ setPressed(false);
2392
+ // check whether move down is strong enough
2393
+ // and content scroll position is at the top to close the component
2394
+ if (moveOffset.current > MOVE_OFFSET_THRESHOLD && isContentScrollPositionAtTop()) {
2395
+ close(event);
2396
+ }
2397
+ // otherwise move component back to default (initial) position
2398
+ else {
2399
+ move(INITIAL_Y_POSITION);
2400
+ }
2401
+ moveOffset.current = INITIAL_Y_POSITION;
2402
+ }
2403
+ function isContentScrollPositionAtTop() {
2404
+ return contentReference?.current?.scrollTop !== undefined && contentReference.current.scrollTop <= CONTENT_SCROLL_THRESHOLD;
2405
+ }
2406
+ /**
2407
+ * Calculates how hard user moves component,
2408
+ * result value used to determine whether to hide component or re-position to default state
2409
+ *
2410
+ * @param afterMoveYCoordinate
2411
+ */
2412
+ function calculateOffsetAfterMove(afterMoveYCoordinate) {
2413
+ return afterMoveYCoordinate - initialYCoordinate.current;
2414
+ }
2415
+ /**
2416
+ * Set `max-height` for content part (in order to keep it scrollable for content overflow cases) of the component
2417
+ * and ensures space for safe zone (32px) at the top.
2418
+ */
2419
+ function setContentMaxHeight() {
2420
+ const safeZoneHeight = '64px';
2421
+ const topbarHeight = '32px';
2422
+ const windowHight = isServerSide() ? 0 : window.innerHeight;
2423
+ /**
2424
+ * Calculate _real_ height of the screen (taking into account parts of browser interface).
2425
+ *
2426
+ * See https://css-tricks.com/the-trick-to-viewport-units-on-mobile for more details.
2427
+ */
2428
+ const screenHeight = `${windowHight * 0.01 * 100}px`;
2429
+ return {
2430
+ maxHeight: `calc(${screenHeight} - ${safeZoneHeight} - ${topbarHeight})`
2431
+ };
2432
+ }
2433
+ const is400Zoom = useMedia(`(max-width: ${exports.Breakpoint.ZOOM_400}px)`);
2434
+ return is400Zoom ? /*#__PURE__*/jsxRuntime.jsx(Drawer$1, {
2435
+ open: props.open,
2436
+ className: props.className,
2437
+ onClose: close,
2438
+ children: props.children
2439
+ }) : /*#__PURE__*/jsxRuntime.jsx(Dimmer$1, {
2440
+ open: props.open,
2441
+ fadeContentOnEnter: true,
2442
+ fadeContentOnExit: true,
2443
+ onClose: close,
2444
+ children: /*#__PURE__*/jsxRuntime.jsx(SlidingPanel, {
2445
+ ref: bottomSheetReference,
2446
+ open: props.open,
2447
+ position: exports.Position.BOTTOM,
2448
+ className: classNames__default.default('np-bottom-sheet', props.className),
2449
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
2450
+ role: "dialog",
2451
+ "aria-modal": true,
2452
+ onTouchStart: onSwipeStart,
2453
+ onTouchMove: onSwipeMove,
2454
+ onTouchEnd: onSwipeEnd,
2455
+ onMouseDown: onSwipeStart,
2456
+ onMouseMove: onSwipeMove,
2457
+ onMouseUp: onSwipeEnd,
2458
+ children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
2459
+ ref: topBarReference,
2460
+ className: "np-bottom-sheet--top-bar",
2461
+ children: [/*#__PURE__*/jsxRuntime.jsx("div", {
2462
+ className: "np-bottom-sheet--handler"
2463
+ }), /*#__PURE__*/jsxRuntime.jsx(CloseButton, {
2464
+ size: "sm",
2465
+ className: "sr-only np-bottom-sheet--close-btn",
2466
+ onClick: close
2467
+ })]
2468
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
2469
+ ref: contentReference,
2470
+ style: setContentMaxHeight(),
2471
+ className: "np-bottom-sheet--content",
2472
+ children: props.children
2473
+ })]
2474
+ })
2782
2475
  })
2783
2476
  });
2784
2477
  };
2785
2478
 
2786
- const CircularButton = ({
2787
- className,
2788
- children,
2789
- disabled,
2790
- icon,
2791
- priority = exports.Priority.PRIMARY,
2792
- type = exports.ControlType.ACCENT,
2793
- ...rest
2794
- }) => {
2795
- const classes = classNames__default.default('btn np-btn', typeClassMap[type], priorityClassMap[priority]);
2796
- const iconElement = Number(icon.props.size) !== 24 ? /*#__PURE__*/React.cloneElement(icon, {
2797
- size: 24
2798
- }) : icon;
2799
- return /*#__PURE__*/jsxRuntime.jsxs("label", {
2800
- className: classNames__default.default('np-circular-btn', priority, type, disabled && 'disabled', className),
2801
- children: [/*#__PURE__*/jsxRuntime.jsx("input", {
2802
- type: "button",
2803
- "aria-label": children,
2804
- className: classes,
2805
- disabled: disabled,
2806
- ...rest
2807
- }), iconElement, /*#__PURE__*/jsxRuntime.jsx(Body, {
2808
- as: "span",
2809
- className: "np-circular-btn__label",
2810
- type: exports.Typography.BODY_DEFAULT_BOLD,
2811
- children: children
2812
- })]
2813
- });
2814
- };
2815
-
2816
2479
  const Card = ({
2817
2480
  className,
2818
2481
  children = null,
@@ -3325,6 +2988,124 @@ function shouldPropagateOnBlur({
3325
2988
  return blurElementParent !== focusElementParent;
3326
2989
  }
3327
2990
 
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
+
3328
3109
  const ResponsivePanel = /*#__PURE__*/React.forwardRef(({
3329
3110
  anchorRef,
3330
3111
  arrow = false,
@@ -3346,7 +3127,7 @@ const ResponsivePanel = /*#__PURE__*/React.forwardRef(({
3346
3127
  children: children
3347
3128
  }, "bottomSheet");
3348
3129
  }
3349
- return /*#__PURE__*/jsxRuntime.jsx(Panel, {
3130
+ return /*#__PURE__*/jsxRuntime.jsx(Panel$1, {
3350
3131
  ref: reference,
3351
3132
  flip: flip,
3352
3133
  arrow: arrow,
@@ -5244,6 +5025,73 @@ const Field = ({
5244
5025
  });
5245
5026
  };
5246
5027
 
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
+
5247
5095
  const EmptyTransparentImage = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
5248
5096
  const Image = ({
5249
5097
  id,
@@ -9691,6 +9539,19 @@ function RadioOption({
9691
9539
  });
9692
9540
  }
9693
9541
 
9542
+ const Section = ({
9543
+ children,
9544
+ className,
9545
+ withHorizontalPadding = false
9546
+ }) => {
9547
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
9548
+ className: classNames__default.default('np-section', className, {
9549
+ 'np-section--with-horizontal-padding': withHorizontalPadding
9550
+ }),
9551
+ children: children
9552
+ });
9553
+ };
9554
+
9694
9555
  const SegmentedControl = ({
9695
9556
  name,
9696
9557
  value,
@@ -10357,7 +10218,7 @@ function Select({
10357
10218
  children: renderOptionsList({
10358
10219
  className: isModern ? '' : 'p-a-1'
10359
10220
  })
10360
- }) : /*#__PURE__*/jsxRuntime.jsx(Panel, {
10221
+ }) : /*#__PURE__*/jsxRuntime.jsx(Panel$1, {
10361
10222
  open: open,
10362
10223
  flip: false,
10363
10224
  altAxis: true,
@@ -14719,7 +14580,6 @@ exports.Select = Select;
14719
14580
  exports.SelectInput = SelectInput;
14720
14581
  exports.SelectInputOptionContent = SelectInputOptionContent;
14721
14582
  exports.SelectInputTriggerButton = SelectInputTriggerButton;
14722
- exports.SelectOption = SelectOption;
14723
14583
  exports.SlidingPanel = SlidingPanel;
14724
14584
  exports.SnackbarConsumer = SnackbarConsumer;
14725
14585
  exports.SnackbarContext = SnackbarContext;