@transferwise/components 46.135.1 → 46.135.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../src/tooltip/Tooltip.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { clsx } from 'clsx';\nimport {\n AriaAttributes,\n PropsWithChildren,\n ReactElement,\n ReactNode,\n cloneElement,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport { usePopper } from 'react-popper';\n\nimport { CommonProps, Position } from '../common';\nimport {\n PositionBottom,\n PositionLeft,\n PositionRight,\n PositionTop,\n} from '../common/propsValues/position';\n\nexport type TooltipProps = PropsWithChildren<{\n position?: PositionTop | PositionRight | PositionBottom | PositionLeft;\n label: ReactNode;\n id?: string;\n}> &\n CommonProps;\n\nconst Tooltip = ({\n position = Position.TOP,\n children = undefined,\n label,\n id,\n className,\n}: TooltipProps) => {\n const [open, setOpen] = useState(false);\n const anchorReference = useRef(null);\n const [arrowElement, setArrowElement] = useState(null);\n const [popperElement, setPopperElement] = useState(null);\n\n const fallbackId = useId();\n const tooltipId = id ?? fallbackId;\n const modifiers = [];\n\n modifiers.push({\n name: 'arrow',\n options: {\n element: arrowElement,\n options: {\n padding: 8, // 8px from the edges of the popper\n },\n },\n });\n // This lets you displace a popper element from its reference element.\n modifiers.push({ name: 'offset', options: { offset: [0, 16] } });\n modifiers.push({\n name: 'flip',\n options: {\n fallbackPlacements: Position.TOP,\n },\n });\n\n const { styles, attributes, forceUpdate } = usePopper(anchorReference.current, popperElement, {\n placement: position,\n modifiers,\n });\n\n // If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),\n // it is most simple just to always position before opening\n useEffect(() => {\n if (open && forceUpdate) {\n forceUpdate();\n }\n }, [open]);\n\n return (\n <span\n ref={anchorReference}\n className=\"tw-tooltip-container\"\n onMouseOver={() => setOpen(true)}\n onFocus={() => setOpen(true)}\n onMouseOut={() => setOpen(false)}\n onBlur={() => setOpen(false)}\n >\n {children\n ? cloneElement(children as ReactElement<Pick<AriaAttributes, 'aria-describedby'>>, {\n 'aria-describedby': `${tooltipId}-tooltip`,\n })\n : null}\n <div\n // @ts-expect-error\n ref={setPopperElement}\n className={clsx(\n 'np-tooltip',\n 'np-panel',\n open ? `np-panel--open np-tooltip--open` : null,\n className,\n )}\n style={{ ...styles.popper }}\n {...attributes.popper}\n aria-hidden={!open}\n role=\"tooltip\"\n id={`${tooltipId}-tooltip`}\n >\n <div className=\"np-panel__content tooltip-inner\">\n {label}\n <div\n // @ts-expect-error\n ref={setArrowElement}\n className={clsx('np-panel__arrow')}\n style={styles.arrow}\n />\n </div>\n </div>\n </span>\n );\n};\n\nexport default Tooltip;\n"],"names":["Tooltip","position","Position","TOP","children","undefined","label","id","className","open","setOpen","useState","anchorReference","useRef","arrowElement","setArrowElement","popperElement","setPopperElement","fallbackId","useId","tooltipId","modifiers","push","name","options","element","padding","offset","fallbackPlacements","styles","attributes","forceUpdate","usePopper","current","placement","useEffect","_jsxs","ref","onMouseOver","onFocus","onMouseOut","onBlur","cloneElement","_jsx","clsx","style","popper","role","arrow"],"mappings":"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"}
1
+ {"version":3,"file":"Tooltip.js","sources":["../../src/tooltip/Tooltip.tsx"],"sourcesContent":["import {\n arrow as arrowMiddleware,\n autoUpdate,\n flip,\n offset,\n useFloating,\n} from '@floating-ui/react';\nimport { clsx } from 'clsx';\nimport {\n AriaAttributes,\n CSSProperties,\n PropsWithChildren,\n ReactElement,\n ReactNode,\n cloneElement,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport { CommonProps, Position } from '../common';\nimport {\n PositionBottom,\n PositionLeft,\n PositionRight,\n PositionTop,\n} from '../common/propsValues/position';\n\nexport type TooltipProps = PropsWithChildren<{\n position?: PositionTop | PositionRight | PositionBottom | PositionLeft;\n label: ReactNode;\n id?: string;\n}> &\n CommonProps;\n\nconst Tooltip = ({\n position = Position.TOP,\n children = undefined,\n label,\n id,\n className,\n}: TooltipProps) => {\n const [open, setOpen] = useState(false);\n const arrowRef = useRef<HTMLDivElement | null>(null);\n\n const fallbackId = useId();\n const tooltipId = id ?? fallbackId;\n\n const { refs, floatingStyles, placement, middlewareData } = useFloating({\n placement: position,\n middleware: [\n offset(16),\n flip({ fallbackPlacements: [Position.TOP] }),\n arrowMiddleware({ element: arrowRef, padding: 8 }),\n ],\n whileElementsMounted: open ? autoUpdate : undefined,\n open,\n });\n\n const arrowStyle: CSSProperties = {\n ...(middlewareData.arrow?.x != null ? { left: middlewareData.arrow.x } : {}),\n ...(middlewareData.arrow?.y != null ? { top: middlewareData.arrow.y } : {}),\n };\n\n return (\n <span\n ref={refs.setReference}\n className=\"tw-tooltip-container\"\n onMouseOver={() => setOpen(true)}\n onFocus={() => setOpen(true)}\n onMouseOut={() => setOpen(false)}\n onBlur={() => setOpen(false)}\n >\n {children\n ? cloneElement(children as ReactElement<Pick<AriaAttributes, 'aria-describedby'>>, {\n 'aria-describedby': `${tooltipId}-tooltip`,\n })\n : null}\n <div\n ref={refs.setFloating}\n className={clsx(\n 'np-tooltip',\n 'np-panel',\n open ? `np-panel--open np-tooltip--open` : null,\n className,\n )}\n style={floatingStyles}\n data-popper-placement={placement}\n aria-hidden={!open}\n role=\"tooltip\"\n id={`${tooltipId}-tooltip`}\n >\n <div className=\"np-panel__content tooltip-inner\">\n {label}\n <div ref={arrowRef} className={clsx('np-panel__arrow')} style={arrowStyle} />\n </div>\n </div>\n </span>\n );\n};\n\nexport default Tooltip;\n"],"names":["Tooltip","position","Position","TOP","children","undefined","label","id","className","open","setOpen","useState","arrowRef","useRef","fallbackId","useId","tooltipId","refs","floatingStyles","placement","middlewareData","useFloating","middleware","offset","flip","fallbackPlacements","arrowMiddleware","element","padding","whileElementsMounted","autoUpdate","arrowStyle","arrow","x","left","y","top","_jsxs","ref","setReference","onMouseOver","onFocus","onMouseOut","onBlur","cloneElement","_jsx","setFloating","clsx","style","role"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
+ import { useFloating, autoUpdate, offset, flip, arrow } from '@floating-ui/react';
1
2
  import { clsx } from 'clsx';
2
- import { useState, useRef, useId, useEffect, cloneElement } from 'react';
3
- import { usePopper } from 'react-popper';
3
+ import { useState, useRef, useId, cloneElement } from 'react';
4
4
  import '../common/theme.mjs';
5
5
  import '../common/direction.mjs';
6
6
  import '../common/propsValues/control.mjs';
@@ -26,7 +26,6 @@ import 'react-intl';
26
26
  import '../common/closeButton/CloseButton.messages.mjs';
27
27
  import { jsxs, jsx } from 'react/jsx-runtime';
28
28
 
29
- /* eslint-disable @typescript-eslint/ban-ts-comment */
30
29
  const Tooltip = ({
31
30
  position = Position.TOP,
32
31
  children = undefined,
@@ -35,51 +34,35 @@ const Tooltip = ({
35
34
  className
36
35
  }) => {
37
36
  const [open, setOpen] = useState(false);
38
- const anchorReference = useRef(null);
39
- const [arrowElement, setArrowElement] = useState(null);
40
- const [popperElement, setPopperElement] = useState(null);
37
+ const arrowRef = useRef(null);
41
38
  const fallbackId = useId();
42
39
  const tooltipId = id ?? fallbackId;
43
- const modifiers = [];
44
- modifiers.push({
45
- name: 'arrow',
46
- options: {
47
- element: arrowElement,
48
- options: {
49
- padding: 8 // 8px from the edges of the popper
50
- }
51
- }
52
- });
53
- // This lets you displace a popper element from its reference element.
54
- modifiers.push({
55
- name: 'offset',
56
- options: {
57
- offset: [0, 16]
58
- }
59
- });
60
- modifiers.push({
61
- name: 'flip',
62
- options: {
63
- fallbackPlacements: Position.TOP
64
- }
65
- });
66
40
  const {
67
- styles,
68
- attributes,
69
- forceUpdate
70
- } = usePopper(anchorReference.current, popperElement, {
41
+ refs,
42
+ floatingStyles,
43
+ placement,
44
+ middlewareData
45
+ } = useFloating({
71
46
  placement: position,
72
- modifiers
47
+ middleware: [offset(16), flip({
48
+ fallbackPlacements: [Position.TOP]
49
+ }), arrow({
50
+ element: arrowRef,
51
+ padding: 8
52
+ })],
53
+ whileElementsMounted: open ? autoUpdate : undefined,
54
+ open
73
55
  });
74
- // If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),
75
- // it is most simple just to always position before opening
76
- useEffect(() => {
77
- if (open && forceUpdate) {
78
- forceUpdate();
79
- }
80
- }, [open]);
56
+ const arrowStyle = {
57
+ ...(middlewareData.arrow?.x != null ? {
58
+ left: middlewareData.arrow.x
59
+ } : {}),
60
+ ...(middlewareData.arrow?.y != null ? {
61
+ top: middlewareData.arrow.y
62
+ } : {})
63
+ };
81
64
  return /*#__PURE__*/jsxs("span", {
82
- ref: anchorReference,
65
+ ref: refs.setReference,
83
66
  className: "tw-tooltip-container",
84
67
  onMouseOver: () => setOpen(true),
85
68
  onFocus: () => setOpen(true),
@@ -88,23 +71,19 @@ const Tooltip = ({
88
71
  children: [children ? /*#__PURE__*/cloneElement(children, {
89
72
  'aria-describedby': `${tooltipId}-tooltip`
90
73
  }) : null, /*#__PURE__*/jsx("div", {
91
- // @ts-expect-error
92
- ref: setPopperElement,
74
+ ref: refs.setFloating,
93
75
  className: clsx('np-tooltip', 'np-panel', open ? `np-panel--open np-tooltip--open` : null, className),
94
- style: {
95
- ...styles.popper
96
- },
97
- ...attributes.popper,
76
+ style: floatingStyles,
77
+ "data-popper-placement": placement,
98
78
  "aria-hidden": !open,
99
79
  role: "tooltip",
100
80
  id: `${tooltipId}-tooltip`,
101
81
  children: /*#__PURE__*/jsxs("div", {
102
82
  className: "np-panel__content tooltip-inner",
103
83
  children: [label, /*#__PURE__*/jsx("div", {
104
- // @ts-expect-error
105
- ref: setArrowElement,
84
+ ref: arrowRef,
106
85
  className: clsx('np-panel__arrow'),
107
- style: styles.arrow
86
+ style: arrowStyle
108
87
  })]
109
88
  })
110
89
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.mjs","sources":["../../src/tooltip/Tooltip.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-ts-comment */\nimport { clsx } from 'clsx';\nimport {\n AriaAttributes,\n PropsWithChildren,\n ReactElement,\n ReactNode,\n cloneElement,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport { usePopper } from 'react-popper';\n\nimport { CommonProps, Position } from '../common';\nimport {\n PositionBottom,\n PositionLeft,\n PositionRight,\n PositionTop,\n} from '../common/propsValues/position';\n\nexport type TooltipProps = PropsWithChildren<{\n position?: PositionTop | PositionRight | PositionBottom | PositionLeft;\n label: ReactNode;\n id?: string;\n}> &\n CommonProps;\n\nconst Tooltip = ({\n position = Position.TOP,\n children = undefined,\n label,\n id,\n className,\n}: TooltipProps) => {\n const [open, setOpen] = useState(false);\n const anchorReference = useRef(null);\n const [arrowElement, setArrowElement] = useState(null);\n const [popperElement, setPopperElement] = useState(null);\n\n const fallbackId = useId();\n const tooltipId = id ?? fallbackId;\n const modifiers = [];\n\n modifiers.push({\n name: 'arrow',\n options: {\n element: arrowElement,\n options: {\n padding: 8, // 8px from the edges of the popper\n },\n },\n });\n // This lets you displace a popper element from its reference element.\n modifiers.push({ name: 'offset', options: { offset: [0, 16] } });\n modifiers.push({\n name: 'flip',\n options: {\n fallbackPlacements: Position.TOP,\n },\n });\n\n const { styles, attributes, forceUpdate } = usePopper(anchorReference.current, popperElement, {\n placement: position,\n modifiers,\n });\n\n // If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),\n // it is most simple just to always position before opening\n useEffect(() => {\n if (open && forceUpdate) {\n forceUpdate();\n }\n }, [open]);\n\n return (\n <span\n ref={anchorReference}\n className=\"tw-tooltip-container\"\n onMouseOver={() => setOpen(true)}\n onFocus={() => setOpen(true)}\n onMouseOut={() => setOpen(false)}\n onBlur={() => setOpen(false)}\n >\n {children\n ? cloneElement(children as ReactElement<Pick<AriaAttributes, 'aria-describedby'>>, {\n 'aria-describedby': `${tooltipId}-tooltip`,\n })\n : null}\n <div\n // @ts-expect-error\n ref={setPopperElement}\n className={clsx(\n 'np-tooltip',\n 'np-panel',\n open ? `np-panel--open np-tooltip--open` : null,\n className,\n )}\n style={{ ...styles.popper }}\n {...attributes.popper}\n aria-hidden={!open}\n role=\"tooltip\"\n id={`${tooltipId}-tooltip`}\n >\n <div className=\"np-panel__content tooltip-inner\">\n {label}\n <div\n // @ts-expect-error\n ref={setArrowElement}\n className={clsx('np-panel__arrow')}\n style={styles.arrow}\n />\n </div>\n </div>\n </span>\n );\n};\n\nexport default Tooltip;\n"],"names":["Tooltip","position","Position","TOP","children","undefined","label","id","className","open","setOpen","useState","anchorReference","useRef","arrowElement","setArrowElement","popperElement","setPopperElement","fallbackId","useId","tooltipId","modifiers","push","name","options","element","padding","offset","fallbackPlacements","styles","attributes","forceUpdate","usePopper","current","placement","useEffect","_jsxs","ref","onMouseOver","onFocus","onMouseOut","onBlur","cloneElement","_jsx","clsx","style","popper","role","arrow"],"mappings":"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"}
1
+ {"version":3,"file":"Tooltip.mjs","sources":["../../src/tooltip/Tooltip.tsx"],"sourcesContent":["import {\n arrow as arrowMiddleware,\n autoUpdate,\n flip,\n offset,\n useFloating,\n} from '@floating-ui/react';\nimport { clsx } from 'clsx';\nimport {\n AriaAttributes,\n CSSProperties,\n PropsWithChildren,\n ReactElement,\n ReactNode,\n cloneElement,\n useId,\n useRef,\n useState,\n} from 'react';\n\nimport { CommonProps, Position } from '../common';\nimport {\n PositionBottom,\n PositionLeft,\n PositionRight,\n PositionTop,\n} from '../common/propsValues/position';\n\nexport type TooltipProps = PropsWithChildren<{\n position?: PositionTop | PositionRight | PositionBottom | PositionLeft;\n label: ReactNode;\n id?: string;\n}> &\n CommonProps;\n\nconst Tooltip = ({\n position = Position.TOP,\n children = undefined,\n label,\n id,\n className,\n}: TooltipProps) => {\n const [open, setOpen] = useState(false);\n const arrowRef = useRef<HTMLDivElement | null>(null);\n\n const fallbackId = useId();\n const tooltipId = id ?? fallbackId;\n\n const { refs, floatingStyles, placement, middlewareData } = useFloating({\n placement: position,\n middleware: [\n offset(16),\n flip({ fallbackPlacements: [Position.TOP] }),\n arrowMiddleware({ element: arrowRef, padding: 8 }),\n ],\n whileElementsMounted: open ? autoUpdate : undefined,\n open,\n });\n\n const arrowStyle: CSSProperties = {\n ...(middlewareData.arrow?.x != null ? { left: middlewareData.arrow.x } : {}),\n ...(middlewareData.arrow?.y != null ? { top: middlewareData.arrow.y } : {}),\n };\n\n return (\n <span\n ref={refs.setReference}\n className=\"tw-tooltip-container\"\n onMouseOver={() => setOpen(true)}\n onFocus={() => setOpen(true)}\n onMouseOut={() => setOpen(false)}\n onBlur={() => setOpen(false)}\n >\n {children\n ? cloneElement(children as ReactElement<Pick<AriaAttributes, 'aria-describedby'>>, {\n 'aria-describedby': `${tooltipId}-tooltip`,\n })\n : null}\n <div\n ref={refs.setFloating}\n className={clsx(\n 'np-tooltip',\n 'np-panel',\n open ? `np-panel--open np-tooltip--open` : null,\n className,\n )}\n style={floatingStyles}\n data-popper-placement={placement}\n aria-hidden={!open}\n role=\"tooltip\"\n id={`${tooltipId}-tooltip`}\n >\n <div className=\"np-panel__content tooltip-inner\">\n {label}\n <div ref={arrowRef} className={clsx('np-panel__arrow')} style={arrowStyle} />\n </div>\n </div>\n </span>\n );\n};\n\nexport default Tooltip;\n"],"names":["Tooltip","position","Position","TOP","children","undefined","label","id","className","open","setOpen","useState","arrowRef","useRef","fallbackId","useId","tooltipId","refs","floatingStyles","placement","middlewareData","useFloating","middleware","offset","flip","fallbackPlacements","arrowMiddleware","element","padding","whileElementsMounted","autoUpdate","arrowStyle","arrow","x","left","y","top","_jsxs","ref","setReference","onMouseOver","onFocus","onMouseOut","onBlur","cloneElement","_jsx","setFloating","clsx","style","role"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../../../src/common/panel/Panel.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EAKf,MAAM,OAAO,CAAC;AAGf,OAAO,EAAY,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAgBxF,MAAM,MAAM,UAAU,GAAG,iBAAiB,CAAC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,cAAc,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,WAAW,CAAC;IACvE,SAAS,EAAE,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC,GACA,cAAc,CAAC,cAAc,CAAC,CAAC;AAEjC,QAAA,MAAM,KAAK;YAZD,OAAO;WACR,OAAO;cACJ,OAAO;WACV,OAAO;cACJ,CAAC,KAAK,EAAE,KAAK,GAAG,cAAc,KAAK,IAAI;eACtC,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,WAAW;eAC3D,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC;kBAC7B,OAAO;qBACJ,OAAO;;;mFAkGxB,CAAC;AAEH,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Panel.d.ts","sourceRoot":"","sources":["../../../../src/common/panel/Panel.tsx"],"names":[],"mappings":"AAWA,OAAO,EAEL,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EAIf,MAAM,OAAO,CAAC;AAEf,OAAO,EAAY,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAgBxF,MAAM,MAAM,UAAU,GAAG,iBAAiB,CAAC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,cAAc,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,EAAE,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,WAAW,CAAC;IACvE,SAAS,EAAE,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC,GACA,cAAc,CAAC,cAAc,CAAC,CAAC;AAEjC,QAAA,MAAM,KAAK;YAZD,OAAO;WACR,OAAO;cACJ,OAAO;WACV,OAAO;cACJ,CAAC,KAAK,EAAE,KAAK,GAAG,cAAc,KAAK,IAAI;eACtC,cAAc,GAAG,YAAY,GAAG,aAAa,GAAG,WAAW;eAC3D,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC;kBAC7B,OAAO;qBACJ,OAAO;;;mFAiGxB,CAAC;AAEH,eAAe,KAAK,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/tooltip/Tooltip.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,iBAAiB,EAEjB,SAAS,EAMV,MAAM,OAAO,CAAC;AAGf,OAAO,EAAE,WAAW,EAAY,MAAM,WAAW,CAAC;AAClD,OAAO,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACZ,MAAM,gCAAgC,CAAC;AAExC,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;IAC3C,QAAQ,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,cAAc,GAAG,YAAY,CAAC;IACvE,KAAK,EAAE,SAAS,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC,GACA,WAAW,CAAC;AAEd,QAAA,MAAM,OAAO,GAAI,+CAMd,YAAY,gCAkFd,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/tooltip/Tooltip.tsx"],"names":[],"mappings":"AAQA,OAAO,EAGL,iBAAiB,EAEjB,SAAS,EAKV,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,WAAW,EAAY,MAAM,WAAW,CAAC;AAClD,OAAO,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACZ,MAAM,gCAAgC,CAAC;AAExC,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;IAC3C,QAAQ,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,cAAc,GAAG,YAAY,CAAC;IACvE,KAAK,EAAE,SAAS,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,CAAC,GACA,WAAW,CAAC;AAEd,QAAA,MAAM,OAAO,GAAI,+CAMd,YAAY,gCA0Dd,CAAC;AAEF,eAAe,OAAO,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transferwise/components",
3
- "version": "46.135.1",
3
+ "version": "46.135.2",
4
4
  "description": "Neptune React components",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -49,11 +49,11 @@
49
49
  "@rollup/plugin-node-resolve": "^16.0.3",
50
50
  "@rollup/plugin-typescript": "^12.3.0",
51
51
  "@rollup/plugin-url": "^8.0.2",
52
- "@storybook/addon-a11y": "^10.3.4",
53
- "@storybook/addon-docs": "^10.3.4",
52
+ "@storybook/addon-a11y": "^10.3.5",
53
+ "@storybook/addon-docs": "^10.3.5",
54
54
  "@storybook/addon-mcp": "^0.4.1",
55
55
  "@storybook/addon-webpack5-compiler-babel": "^4.0.1",
56
- "@storybook/react-webpack5": "^10.3.4",
56
+ "@storybook/react-webpack5": "^10.3.5",
57
57
  "@testing-library/dom": "^10.4.1",
58
58
  "@testing-library/jest-dom": "^6.9.1",
59
59
  "@testing-library/react": "^16.3.2",
@@ -73,7 +73,7 @@
73
73
  "@wise/eslint-config": "^13.3.0",
74
74
  "babel-plugin-formatjs": "^10.5.41",
75
75
  "eslint": "^9.39.4",
76
- "eslint-plugin-storybook": "^10.3.4",
76
+ "eslint-plugin-storybook": "^10.3.5",
77
77
  "gulp": "^5.0.1",
78
78
  "jest": "^30.3.0",
79
79
  "jest-environment-jsdom": "^29.7.0",
@@ -83,7 +83,7 @@
83
83
  "react-intl": "^7.1.14",
84
84
  "rollup": "^4.60.1",
85
85
  "rollup-preserve-directives": "^1.1.3",
86
- "storybook": "^10.3.4",
86
+ "storybook": "^10.3.5",
87
87
  "storybook-addon-tag-badges": "^3.1.0",
88
88
  "storybook-addon-test-codegen": "^3.0.1",
89
89
  "@transferwise/less-config": "3.1.2",
@@ -103,11 +103,11 @@
103
103
  "dependencies": {
104
104
  "@babel/runtime": "^7.29.2",
105
105
  "@floating-ui/react": "^0.27.19",
106
- "@headlessui/react": "^2.2.9",
107
- "@popperjs/core": "^2.11.8",
106
+ "@headlessui/react": "^2.2.10",
108
107
  "@react-aria/focus": "^3.21.5",
109
108
  "@react-aria/overlays": "^3.31.2",
110
109
  "@transferwise/formatting": "^2.14.0",
110
+ "@transferwise/neptune-tokens": "^8.21.0",
111
111
  "@transferwise/neptune-validation": "^3.3.3",
112
112
  "clsx": "^2.1.1",
113
113
  "commonmark": "^0.31.2",
@@ -116,10 +116,8 @@
116
116
  "lodash.clamp": "^4.0.3",
117
117
  "lodash.debounce": "^4.0.8",
118
118
  "merge-props": "^6.0.0",
119
- "react-popper": "^2.3.0",
120
119
  "react-transition-group": "^4.4.5",
121
- "virtua": "^0.48.8",
122
- "@transferwise/neptune-tokens": "^8.21.0"
120
+ "virtua": "^0.48.8"
123
121
  },
124
122
  "publishConfig": {
125
123
  "access": "public",
@@ -1,3 +1,13 @@
1
+ import {
2
+ arrow as arrowMiddleware,
3
+ autoUpdate,
4
+ flip as flipMiddleware,
5
+ offset,
6
+ type Placement,
7
+ shift,
8
+ size as sizeMiddleware,
9
+ useFloating,
10
+ } from '@floating-ui/react';
1
11
  import { clsx } from 'clsx';
2
12
  import {
3
13
  CSSProperties,
@@ -7,21 +17,19 @@ import {
7
17
  SyntheticEvent,
8
18
  forwardRef,
9
19
  useContext,
10
- useEffect,
11
- useState,
20
+ useRef,
12
21
  } from 'react';
13
- import { usePopper } from 'react-popper';
14
22
 
15
23
  import { Position, PositionBottom, PositionLeft, PositionRight, PositionTop } from '..';
16
24
  import Dimmer from '../../dimmer';
17
25
  import { OverlayIdContext } from '../../provider/overlay/OverlayIdProvider';
18
26
 
19
- const POPOVER_OFFSET = [0, 16];
27
+ const POPOVER_OFFSET = 16;
20
28
 
21
29
  // By default the flip positioning explores only the opposite alternative. So if left is passed and there's no enough space
22
30
  // the right one gets chosen. If there's no space on both sides popover goes back to the initially chosen one left.
23
31
  // This mapping forces popover to try the four available positions before going back to the initial chosen one.
24
- const fallbackPlacements = {
32
+ const fallbackPlacements: Record<string, Placement[]> = {
25
33
  [Position.TOP]: [Position.BOTTOM, Position.RIGHT, Position.LEFT],
26
34
  [Position.BOTTOM]: [Position.TOP, Position.RIGHT, Position.LEFT],
27
35
  [Position.LEFT]: [Position.RIGHT, Position.TOP, Position.BOTTOM],
@@ -57,56 +65,57 @@ const Panel = forwardRef<HTMLDivElement, PanelProps>(function Panel(
57
65
  }: PanelProps,
58
66
  reference,
59
67
  ) {
60
- const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null);
61
- const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
68
+ const arrowRef = useRef<HTMLDivElement | null>(null);
69
+
70
+ const middleware = [];
62
71
 
63
- const modifiers = [];
72
+ if (arrow) {
73
+ middleware.push(offset(POPOVER_OFFSET));
74
+ }
75
+
76
+ if (flip && fallbackPlacements[position]) {
77
+ middleware.push(
78
+ flipMiddleware({
79
+ fallbackPlacements: fallbackPlacements[position],
80
+ }),
81
+ );
82
+ }
64
83
 
65
84
  if (altAxis) {
66
- modifiers.push({
67
- // https://popper.js.org/docs/v2/modifiers/prevent-overflow
68
- name: 'preventOverflow',
69
- options: {
70
- altAxis: true,
71
- tether: false,
72
- },
73
- });
85
+ middleware.push(shift());
74
86
  }
75
87
 
76
88
  if (arrow) {
77
- modifiers.push({
78
- name: 'arrow',
79
- options: {
80
- element: arrowElement,
81
- options: {
82
- padding: 8, // 8px from the edges of the popper
83
- },
84
- },
85
- });
86
- // This lets you displace a popper element from its reference element.
87
- modifiers.push({ name: 'offset', options: { offset: POPOVER_OFFSET } });
89
+ middleware.push(arrowMiddleware({ element: arrowRef, padding: 8 }));
88
90
  }
89
- if (flip && fallbackPlacements[position]) {
90
- modifiers.push({
91
- name: 'flip',
92
- options: {
93
- fallbackPlacements: fallbackPlacements[position],
94
- },
95
- });
91
+
92
+ if (considerHeight) {
93
+ middleware.push(
94
+ sizeMiddleware({
95
+ padding: POPOVER_OFFSET,
96
+ apply: ({ elements, availableHeight }) => {
97
+ elements.floating.style.setProperty(
98
+ '--np-panel-available-height',
99
+ `${availableHeight}px`,
100
+ );
101
+ },
102
+ }),
103
+ );
96
104
  }
97
105
 
98
- const { styles, attributes, forceUpdate } = usePopper(anchorRef.current, popperElement, {
106
+ const { refs, floatingStyles, placement, middlewareData } = useFloating({
99
107
  placement: position,
100
- modifiers,
108
+ middleware,
109
+ elements: {
110
+ reference: anchorRef.current,
111
+ },
112
+ whileElementsMounted: open ? autoUpdate : undefined,
101
113
  });
102
114
 
103
- // If the trigger is not visible when the position is calculated, it will be incorrect. Because this can happen repeatedly (on resize for example),
104
- // it is most simple just to always position before opening
105
- useEffect(() => {
106
- if (open && forceUpdate) {
107
- forceUpdate();
108
- }
109
- }, [open]);
115
+ const arrowStyle: CSSProperties = {
116
+ ...(middlewareData.arrow?.x != null ? { left: middlewareData.arrow.x } : {}),
117
+ ...(middlewareData.arrow?.y != null ? { top: middlewareData.arrow.y } : {}),
118
+ };
110
119
 
111
120
  const contentStyle: CSSProperties = {
112
121
  ...(anchorWidth ? { width: anchorRef.current?.clientWidth } : undefined),
@@ -119,18 +128,16 @@ const Panel = forwardRef<HTMLDivElement, PanelProps>(function Panel(
119
128
  <div
120
129
  id={overlayId}
121
130
  {...rest}
122
- ref={setPopperElement}
131
+ ref={refs.setFloating}
123
132
  role="dialog"
124
- style={{ ...styles.popper }}
125
- {...attributes.popper}
133
+ style={floatingStyles}
134
+ data-popper-placement={placement}
126
135
  className={clsx('np-panel', { 'np-panel--open': open }, rest.className)}
127
136
  >
128
137
  <div ref={reference} style={contentStyle} className={clsx('np-panel__content')}>
129
138
  {children}
130
139
  {/* Arrow has to stay inside content to get the same animations as the "dialog" and to get hidden when panel is closed. */}
131
- {arrow && (
132
- <div ref={setArrowElement} className={clsx('np-panel__arrow')} style={styles.arrow} />
133
- )}
140
+ {arrow && <div ref={arrowRef} className={clsx('np-panel__arrow')} style={arrowStyle} />}
134
141
  </div>
135
142
  </div>
136
143
  </Dimmer>
package/src/main.css CHANGED
@@ -31064,8 +31064,8 @@ button.np-link {
31064
31064
  box-shadow: none;
31065
31065
  background: #ffffff;
31066
31066
  background: var(--color-background-elevated);
31067
- border-radius: 24px;
31068
- border-radius: var(--radius-large);
31067
+ border-radius: 32px;
31068
+ border-radius: var(--radius-xlarge);
31069
31069
  }
31070
31070
 
31071
31071
  .tw-modal.in .tw-modal-dialog {
@@ -32728,8 +32728,8 @@ html:not([dir="rtl"]) .np-navigation-option {
32728
32728
  }
32729
32729
 
32730
32730
  .np-dropdown-menu-desktop {
32731
- max-height: 70vh;
32732
32731
  max-height: 70svh;
32732
+ max-height: var(--np-panel-available-height, 70svh);
32733
32733
  min-width: 160px;
32734
32734
  max-width: calc(100vw - 32px);
32735
32735
  }
@@ -32737,6 +32737,7 @@ html:not([dir="rtl"]) .np-navigation-option {
32737
32737
  @media (min-height: 592px) {
32738
32738
  .np-dropdown-menu-desktop {
32739
32739
  max-height: 592px;
32740
+ max-height: var(--np-panel-available-height, 592px);
32740
32741
  }
32741
32742
  }
32742
32743
 
@@ -9,8 +9,8 @@
9
9
  box-shadow: none;
10
10
  background: #ffffff;
11
11
  background: var(--color-background-elevated);
12
- border-radius: 24px;
13
- border-radius: var(--radius-large);
12
+ border-radius: 32px;
13
+ border-radius: var(--radius-xlarge);
14
14
  }
15
15
  .tw-modal.in .tw-modal-dialog {
16
16
  transform: translate(0);
@@ -12,7 +12,7 @@
12
12
  transform: translateY(-25%);
13
13
  box-shadow: none;
14
14
  background: var(--color-background-elevated);
15
- border-radius: var(--radius-large);
15
+ border-radius: var(--radius-xlarge);
16
16
  }
17
17
 
18
18
  &.in {
@@ -123,14 +123,15 @@
123
123
  max-width: calc(100% - 32px);
124
124
  }
125
125
  .np-dropdown-menu-desktop {
126
- max-height: 70vh;
127
126
  max-height: 70svh;
127
+ max-height: var(--np-panel-available-height, 70svh);
128
128
  min-width: 160px;
129
129
  max-width: calc(100vw - 32px);
130
130
  }
131
131
  @media (min-height: 592px) {
132
132
  .np-dropdown-menu-desktop {
133
133
  max-height: 592px;
134
+ max-height: var(--np-panel-available-height, 592px);
134
135
  }
135
136
  }
136
137
  .np-dropdown-menu {
@@ -81,7 +81,7 @@
81
81
 
82
82
  // Override some of Button component styles
83
83
  .btn {
84
- &:not(.disabled,:disabled,.btn-loading) {
84
+ &:not(.disabled, :disabled, .btn-loading) {
85
85
  color: var(--color-content-primary);
86
86
 
87
87
  &:hover {
@@ -108,15 +108,14 @@
108
108
  }
109
109
 
110
110
  .np-dropdown-menu-desktop {
111
- max-height: 70vh;
112
- max-height: 70svh;
111
+ max-height: var(--np-panel-available-height, 70svh);
113
112
  min-width: 160px;
114
113
  max-width: ~"calc(100vw - 32px)";
115
114
  }
116
115
 
117
116
  @media (min-height: 592px) {
118
117
  .np-dropdown-menu-desktop {
119
- max-height: 592px;
118
+ max-height: var(--np-panel-available-height, 592px);
120
119
  }
121
120
  }
122
121
 
@@ -270,7 +269,9 @@
270
269
  /* stylelint-disable-next-line no-duplicate-selectors */
271
270
  .np-select .np-dropdown-toggle {
272
271
  background-color: unset;
273
- transition: background-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
272
+ transition:
273
+ background-color 0.3s ease-in-out,
274
+ box-shadow 0.3s ease-in-out;
274
275
  border: none;
275
276
  box-shadow: inset 0 0 0 1px var(--color-interactive-secondary);
276
277
 
@@ -0,0 +1,59 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-webpack5';
2
+ import { userEvent, within } from 'storybook/test';
3
+ import { useState } from 'react';
4
+
5
+ import { withVariantConfig } from '../../.storybook/helpers';
6
+ import Select, { SelectOptionItem } from './Select';
7
+
8
+ const meta = {
9
+ title: 'Forms/Select/Tests',
10
+ component: Select,
11
+ tags: ['!autodocs', '!manifest'],
12
+ } satisfies Meta<typeof Select>;
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof Select>;
16
+
17
+ const options: SelectOptionItem[] = Array.from({ length: 10 }, (_, i) => ({
18
+ value: i + 1,
19
+ label: `Option ${i + 1}`,
20
+ }));
21
+
22
+ /**
23
+ * Visual regression story: Select placed at the bottom of the viewport so the dropdown
24
+ * flips to the top when opened. The play function opens the dropdown automatically.
25
+ */
26
+ export const DropdownFlipsToTop: Story = {
27
+ render: function Render() {
28
+ const [selected, setSelected] = useState<SelectOptionItem>(options[0]);
29
+ return (
30
+ <div
31
+ style={{
32
+ display: 'flex',
33
+ flexDirection: 'column',
34
+ justifyContent: 'flex-end',
35
+ minHeight: '50vh',
36
+ }}
37
+ >
38
+ <Select
39
+ id="flip-test-select"
40
+ size="md"
41
+ block
42
+ options={options}
43
+ selected={selected}
44
+ onChange={(option) => {
45
+ if (option && 'value' in option) {
46
+ setSelected(option as SelectOptionItem);
47
+ }
48
+ }}
49
+ />
50
+ </div>
51
+ );
52
+ },
53
+ play: async ({ canvasElement }) => {
54
+ const canvas = within(canvasElement);
55
+ const trigger = canvas.getByRole('button', { name: /Option 1/i });
56
+ await userEvent.click(trigger);
57
+ },
58
+ ...withVariantConfig(['default']),
59
+ };
@@ -608,8 +608,8 @@ export default function Select({
608
608
  ) : (
609
609
  <Panel
610
610
  open={open}
611
- flip={false}
612
611
  altAxis
612
+ considerHeight
613
613
  anchorRef={selectReference}
614
614
  anchorWidth={isDropdownAutoWidth}
615
615
  position={dropdownUp ? Position.TOP : Position.BOTTOM}