@transferwise/components 0.0.0-experimental-8b6ee2a → 0.0.0-experimental-335b83d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/build/index.esm.js +669 -13
  2. package/build/index.esm.js.map +1 -1
  3. package/build/index.js +672 -13
  4. package/build/index.js.map +1 -1
  5. package/build/main.css +1 -1
  6. package/build/styles/inputs/Input.css +1 -1
  7. package/build/styles/inputs/InputGroup.css +1 -1
  8. package/build/styles/inputs/SelectInput.css +1 -0
  9. package/build/styles/inputs/TextArea.css +1 -1
  10. package/build/styles/main.css +1 -1
  11. package/build/types/common/hooks/useMedia.d.ts +2 -0
  12. package/build/types/common/hooks/useMedia.d.ts.map +1 -0
  13. package/build/types/common/hooks/useScreenSize.d.ts +3 -0
  14. package/build/types/common/hooks/useScreenSize.d.ts.map +1 -0
  15. package/build/types/common/preventScroll/PreventScroll.d.ts +2 -0
  16. package/build/types/common/preventScroll/PreventScroll.d.ts.map +1 -0
  17. package/build/types/dateLookup/dateTrigger/DateTrigger.messages.d.ts +7 -7
  18. package/build/types/dateLookup/dateTrigger/DateTrigger.messages.d.ts.map +1 -1
  19. package/build/types/index.d.ts +4 -0
  20. package/build/types/index.d.ts.map +1 -1
  21. package/build/types/inputs/Input.d.ts +1 -0
  22. package/build/types/inputs/Input.d.ts.map +1 -1
  23. package/build/types/inputs/SearchInput.d.ts +10 -0
  24. package/build/types/inputs/SearchInput.d.ts.map +1 -0
  25. package/build/types/inputs/SelectInput.d.ts +41 -0
  26. package/build/types/inputs/SelectInput.d.ts.map +1 -0
  27. package/build/types/inputs/_BottomSheet.d.ts +17 -0
  28. package/build/types/inputs/_BottomSheet.d.ts.map +1 -0
  29. package/build/types/inputs/_ButtonInput.d.ts +6 -0
  30. package/build/types/inputs/_ButtonInput.d.ts.map +1 -0
  31. package/build/types/inputs/_Popover.d.ts +18 -0
  32. package/build/types/inputs/_Popover.d.ts.map +1 -0
  33. package/build/types/inputs/_common.d.ts.map +1 -1
  34. package/build/types/utilities/wrapInFragment.d.ts +3 -0
  35. package/build/types/utilities/wrapInFragment.d.ts.map +1 -0
  36. package/package.json +27 -21
  37. package/src/avatar/Avatar.story.tsx +14 -16
  38. package/src/common/hooks/useMedia.ts +15 -0
  39. package/src/common/hooks/useScreenSize.ts +7 -0
  40. package/src/common/preventScroll/PreventScroll.tsx +6 -0
  41. package/src/index.ts +8 -0
  42. package/src/inputs/Input.css +1 -1
  43. package/src/inputs/Input.less +14 -0
  44. package/src/inputs/Input.tsx +6 -2
  45. package/src/inputs/InputGroup.css +1 -1
  46. package/src/inputs/InputGroup.less +6 -1
  47. package/src/inputs/SearchInput.story.tsx +40 -0
  48. package/src/inputs/SearchInput.tsx +35 -0
  49. package/src/inputs/SelectInput.css +1 -0
  50. package/src/inputs/SelectInput.less +183 -0
  51. package/src/inputs/SelectInput.story.tsx +259 -0
  52. package/src/inputs/SelectInput.tsx +565 -0
  53. package/src/inputs/TextArea.css +1 -1
  54. package/src/inputs/TextArea.less +5 -0
  55. package/src/inputs/_BottomSheet.less +107 -0
  56. package/src/inputs/_BottomSheet.tsx +128 -0
  57. package/src/inputs/_ButtonInput.less +7 -0
  58. package/src/inputs/_ButtonInput.tsx +27 -0
  59. package/src/inputs/_Popover.less +38 -0
  60. package/src/inputs/_Popover.tsx +118 -0
  61. package/src/inputs/_common.less +0 -4
  62. package/src/inputs/_common.ts +0 -1
  63. package/src/main.css +1 -1
  64. package/src/main.less +4 -0
  65. package/src/navigationOption/NavigationOption.story.js +5 -3
  66. package/src/radio/Radio.story.js +2 -3
  67. package/src/radioGroup/RadioGroup.story.js +1 -2
  68. package/src/select/searchBox/__snapshots__/SearchBox.spec.js.snap +1 -1
  69. package/src/ssr.spec.js +7 -0
  70. package/src/utilities/wrapInFragment.tsx +3 -0
  71. /package/src/dateLookup/dateTrigger/{DateTrigger.messages.js → DateTrigger.messages.ts} +0 -0
@@ -0,0 +1,128 @@
1
+ import {
2
+ FloatingFocusManager,
3
+ FloatingPortal,
4
+ useDismiss,
5
+ useFloating,
6
+ useInteractions,
7
+ useRole,
8
+ } from '@floating-ui/react';
9
+ import { Transition } from '@headlessui/react';
10
+ import classNames from 'classnames';
11
+ import { useState } from 'react';
12
+
13
+ import { CloseButton } from '../common/closeButton';
14
+ import { PreventScroll } from '../common/preventScroll/PreventScroll';
15
+ import { Size } from '../common/propsValues/size';
16
+
17
+ export interface BottomSheetProps {
18
+ open: boolean;
19
+ renderTrigger?: (args: {
20
+ ref: React.RefCallback<Element>;
21
+ getInteractionProps: (customEventHandlers?: React.HTMLProps<Element>) => {
22
+ [key: string]: unknown;
23
+ };
24
+ }) => React.ReactNode;
25
+ title?: string;
26
+ initialFocusRef?: React.RefObject<HTMLElement>;
27
+ padding?: 'none' | 'md';
28
+ children?: React.ReactNode;
29
+ onClose?: () => void;
30
+ }
31
+
32
+ export function BottomSheet({
33
+ open,
34
+ renderTrigger,
35
+ title,
36
+ initialFocusRef,
37
+ padding = 'md',
38
+ children,
39
+ onClose,
40
+ }: BottomSheetProps) {
41
+ const { refs, context } = useFloating<Element>({
42
+ open,
43
+ onOpenChange: (value) => {
44
+ if (!value) {
45
+ onClose?.();
46
+ }
47
+ },
48
+ });
49
+
50
+ const dismiss = useDismiss(context, {
51
+ outsidePressEvent: 'mousedown',
52
+ });
53
+ const role = useRole(context);
54
+ const { getReferenceProps, getFloatingProps } = useInteractions([dismiss, role]);
55
+
56
+ const [floatingKey, setFloatingKey] = useState(0);
57
+
58
+ return (
59
+ <>
60
+ {open ? <PreventScroll /> : null}
61
+ {renderTrigger?.({
62
+ ref: refs.setReference,
63
+ getInteractionProps: getReferenceProps,
64
+ })}
65
+
66
+ <FloatingPortal>
67
+ <Transition
68
+ show={open}
69
+ className="np-bottom-sheet-v2-container"
70
+ beforeEnter={() => {
71
+ setFloatingKey((prev) => prev + 1);
72
+ }}
73
+ >
74
+ <Transition.Child
75
+ enter="np-bottom-sheet-v2-backdrop-container--enter"
76
+ enterFrom="np-bottom-sheet-v2-backdrop-container--enter-from"
77
+ leave="np-bottom-sheet-v2-backdrop-container--leave"
78
+ leaveTo="np-bottom-sheet-v2-backdrop-container--leave-to"
79
+ >
80
+ <div className="np-bottom-sheet-v2-backdrop" />
81
+ </Transition.Child>
82
+
83
+ <FloatingFocusManager context={context} initialFocus={initialFocusRef}>
84
+ <div className="np-bottom-sheet-v2">
85
+ <Transition.Child
86
+ className="np-bottom-sheet-v2-content"
87
+ enter="np-bottom-sheet-v2-content--enter"
88
+ enterFrom="np-bottom-sheet-v2-content--enter-from"
89
+ leave="np-bottom-sheet-v2-content--leave"
90
+ leaveTo="np-bottom-sheet-v2-content--leave-to"
91
+ >
92
+ <div
93
+ key={floatingKey} // Force inner state invalidation on open
94
+ ref={refs.setFloating}
95
+ className="np-bottom-sheet-v2-content-inner-container"
96
+ {...getFloatingProps()}
97
+ >
98
+ <div className="np-bottom-sheet-v2-header">
99
+ <CloseButton
100
+ size={Size.SMALL}
101
+ onClick={() => {
102
+ onClose?.();
103
+ }}
104
+ />
105
+ </div>
106
+ <div
107
+ className={classNames(
108
+ 'np-bottom-sheet-v2-content-inner',
109
+ title && 'np-bottom-sheet-v2-content-inner--has-title',
110
+ {
111
+ 'np-bottom-sheet-v2-content-inner--padding-md': padding === 'md',
112
+ },
113
+ )}
114
+ >
115
+ {title ? (
116
+ <h2 className="np-bottom-sheet-v2-title np-text-title-body">{title}</h2>
117
+ ) : null}
118
+ <div className="np-bottom-sheet-v2-body np-text-body-default">{children}</div>
119
+ </div>
120
+ </div>
121
+ </Transition.Child>
122
+ </div>
123
+ </FloatingFocusManager>
124
+ </Transition>
125
+ </FloatingPortal>
126
+ </>
127
+ );
128
+ }
@@ -0,0 +1,7 @@
1
+ .np-button-input {
2
+ display: inline-grid;
3
+ grid-auto-columns: minmax(0, 1fr);
4
+ align-content: center;
5
+ border-radius: var(--size-10);
6
+ text-align: start;
7
+ }
@@ -0,0 +1,27 @@
1
+ import classNames from 'classnames';
2
+ import { forwardRef } from 'react';
3
+
4
+ import { useInputPaddings } from './InputGroup';
5
+ import { formControlClassNameBase } from './_common';
6
+
7
+ export interface ButtonInputProps extends React.ComponentPropsWithRef<'button'> {
8
+ size?: 'sm' | 'md' | 'lg';
9
+ }
10
+
11
+ export const ButtonInput = forwardRef(function ButtonInput(
12
+ { size = 'md', className, style, ...restProps }: ButtonInputProps,
13
+ ref: React.ForwardedRef<HTMLButtonElement>,
14
+ ) {
15
+ const inputPaddings = useInputPaddings();
16
+
17
+ return (
18
+ <button
19
+ ref={ref}
20
+ type="button"
21
+ className={classNames(className, formControlClassNameBase({ size }), 'np-button-input')}
22
+ // eslint-disable-next-line react/forbid-dom-props
23
+ style={{ ...inputPaddings, ...style }}
24
+ {...restProps}
25
+ />
26
+ );
27
+ });
@@ -0,0 +1,38 @@
1
+ .np-popover-v2-container {
2
+ z-index: 10;
3
+ display: flex;
4
+ max-height: var(--max-height);
5
+ width: var(--width);
6
+ min-width: min-content;
7
+ flex-direction: column;
8
+ border-radius: var(--radius-small);
9
+ background-color: var(--color-background-elevated);
10
+ box-shadow: 0 0 40px rgb(69 71 69 / 0.2);
11
+
12
+ &:focus {
13
+ outline: none;
14
+ }
15
+ }
16
+
17
+ .np-popover-v2 {
18
+ display: grid;
19
+ row-gap: var(--size-8);
20
+ overflow-y: auto;
21
+ grid-template-rows: repeat(1, minmax(0, 1fr));
22
+
23
+ &--has-title {
24
+ grid-template-rows: auto 1fr;
25
+ }
26
+
27
+ &--padding-md {
28
+ padding: var(--size-16);
29
+ }
30
+ }
31
+
32
+ .np-popover-v2-title {
33
+ color: var(--color-content-primary);
34
+ }
35
+
36
+ .np-popover-v2-content {
37
+ color: var(--color-content-secondary);
38
+ }
@@ -0,0 +1,118 @@
1
+ import {
2
+ autoUpdate,
3
+ flip,
4
+ FloatingFocusManager,
5
+ FloatingPortal,
6
+ offset,
7
+ shift,
8
+ type Side,
9
+ size,
10
+ useDismiss,
11
+ useFloating,
12
+ useInteractions,
13
+ useRole,
14
+ } from '@floating-ui/react';
15
+ import { Transition } from '@headlessui/react';
16
+ import classNames from 'classnames';
17
+ import { useState } from 'react';
18
+
19
+ import { PreventScroll } from '../common/preventScroll/PreventScroll';
20
+
21
+ export interface PopoverProps {
22
+ placement?: Side;
23
+ open: boolean;
24
+ renderTrigger: (args: {
25
+ ref: React.RefCallback<Element>;
26
+ getInteractionProps: (customEventHandlers?: React.HTMLProps<Element>) => {
27
+ [key: string]: unknown;
28
+ };
29
+ }) => React.ReactNode;
30
+ title?: string;
31
+ padding?: 'none' | 'md';
32
+ children?: React.ReactNode;
33
+ onClose?: () => void;
34
+ }
35
+
36
+ const floatingPadding = 16;
37
+
38
+ export function Popover({
39
+ placement,
40
+ open,
41
+ renderTrigger,
42
+ title,
43
+ padding = 'md',
44
+ children,
45
+ onClose,
46
+ }: PopoverProps) {
47
+ const { refs, floatingStyles, context } = useFloating<Element>({
48
+ placement,
49
+ middleware: [
50
+ offset(8),
51
+ flip({ padding: floatingPadding, crossAxis: false }),
52
+ shift(),
53
+ size({
54
+ padding: floatingPadding,
55
+ apply: ({ elements, rects, availableHeight }) => {
56
+ elements.floating.style.setProperty('--max-height', `${availableHeight}px`);
57
+ elements.floating.style.setProperty('--width', `${rects.reference.width}px`);
58
+ },
59
+ }),
60
+ ],
61
+ whileElementsMounted: autoUpdate,
62
+ open,
63
+ onOpenChange: (value) => {
64
+ if (!value) {
65
+ onClose?.();
66
+ }
67
+ },
68
+ });
69
+
70
+ const dismiss = useDismiss(context, {
71
+ outsidePressEvent: 'mousedown',
72
+ });
73
+ const role = useRole(context);
74
+ const { getReferenceProps, getFloatingProps } = useInteractions([role, dismiss]);
75
+
76
+ const [floatingKey, setFloatingKey] = useState(0);
77
+
78
+ return (
79
+ <>
80
+ {open ? <PreventScroll /> : null}
81
+ {renderTrigger({
82
+ ref: refs.setReference,
83
+ getInteractionProps: getReferenceProps,
84
+ })}
85
+
86
+ <FloatingPortal>
87
+ <FloatingFocusManager context={context}>
88
+ <Transition
89
+ show={open}
90
+ leave="transition-opacity"
91
+ leaveTo="opacity-0"
92
+ beforeEnter={() => {
93
+ setFloatingKey((prev) => prev + 1);
94
+ }}
95
+ >
96
+ <div
97
+ key={floatingKey} // Force inner state invalidation on open
98
+ ref={refs.setFloating}
99
+ className="np-popover-v2-container"
100
+ // eslint-disable-next-line react/forbid-dom-props
101
+ style={floatingStyles}
102
+ {...getFloatingProps()}
103
+ >
104
+ <div
105
+ className={classNames('np-popover-v2', title && 'np-popover-v2--has-title', {
106
+ 'np-popover-v2--padding-md': padding === 'md',
107
+ })}
108
+ >
109
+ {title ? <h2 className="np-popover-v2-title np-text-title-body">{title}</h2> : null}
110
+ <div className="np-popover-v2-content np-text-body-default">{children}</div>
111
+ </div>
112
+ </div>
113
+ </Transition>
114
+ </FloatingFocusManager>
115
+ </FloatingPortal>
116
+ </>
117
+ );
118
+ }
@@ -56,8 +56,4 @@
56
56
  &--size-lg {
57
57
  height: var(--size-72) !important;
58
58
  }
59
-
60
- &--shape-rectangle {
61
- border-radius: var(--radius-small);
62
- }
63
59
  }
@@ -16,6 +16,5 @@ export function formControlClassNameBase({ size = 'auto' }: FormControlPropsBase
16
16
  'np-form-control--size-md np-text-body-large': size === 'md',
17
17
  'np-form-control--size-lg np-text-title-subsection': size === 'lg',
18
18
  },
19
- 'np-form-control--shape-rectangle',
20
19
  );
21
20
  }