@transferwise/components 46.123.1 → 46.124.1
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/inputs/SelectInput.js +10 -5
- package/build/inputs/SelectInput.js.map +1 -1
- package/build/inputs/SelectInput.mjs +11 -6
- package/build/inputs/SelectInput.mjs.map +1 -1
- package/build/inputs/_BottomSheet.js +5 -2
- package/build/inputs/_BottomSheet.js.map +1 -1
- package/build/inputs/_BottomSheet.mjs +6 -3
- package/build/inputs/_BottomSheet.mjs.map +1 -1
- package/build/inputs/_Popover.js +2 -0
- package/build/inputs/_Popover.js.map +1 -1
- package/build/inputs/_Popover.mjs +2 -0
- package/build/inputs/_Popover.mjs.map +1 -1
- package/build/main.css +1 -1
- package/build/styles/avatarView/AvatarView.css +1 -1
- package/build/styles/main.css +1 -1
- package/build/types/inputs/SelectInput.d.ts.map +1 -1
- package/build/types/inputs/_BottomSheet.d.ts.map +1 -1
- package/build/types/inputs/_Popover.d.ts.map +1 -1
- package/package.json +6 -5
- package/src/avatarLayout/AvatarLayout.story.tsx +53 -0
- package/src/avatarView/AvatarView.css +1 -1
- package/src/avatarView/AvatarView.less +1 -1
- package/src/avatarView/AvatarView.story.tsx +66 -0
- package/src/inputs/SelectInput.spec.tsx +78 -7
- package/src/inputs/SelectInput.tsx +21 -10
- package/src/inputs/_BottomSheet.tsx +7 -4
- package/src/inputs/_Popover.tsx +2 -0
- package/src/main.css +1 -1
- package/src/moneyInput/MoneyInput.spec.tsx +26 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_Popover.mjs","sources":["../../src/inputs/_Popover.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingPortal,\n offset,\n type Placement,\n shift,\n size as floatingSize,\n useDismiss,\n useFloating,\n useInteractions,\n useRole,\n} from '@floating-ui/react';\nimport { Transition } from '@headlessui/react';\nimport { FocusScope } from '@react-aria/focus';\nimport { ThemeProvider, useTheme } from '@wise/components-theming';\nimport { clsx } from 'clsx';\nimport { useState } from 'react';\n\nimport { PreventScroll } from '../common/preventScroll/PreventScroll';\n\nexport interface PopoverProps {\n placement?: Placement;\n open: boolean;\n renderTrigger: (args: {\n ref: React.RefCallback<Element>;\n getInteractionProps: (customEventHandlers?: React.HTMLProps<Element>) => {\n [key: string]: unknown;\n };\n }) => React.ReactNode;\n title?: string;\n size?: 'md' | 'lg';\n padding?: 'none' | 'md';\n children?: React.ReactNode;\n onClose?: () => void;\n onCloseEnd?: () => void;\n}\n\nconst floatingPadding = 16;\n\nexport function Popover({\n placement,\n open,\n renderTrigger,\n title,\n size = 'md',\n padding = 'md',\n children,\n onClose,\n onCloseEnd,\n}: PopoverProps) {\n const { refs, floatingStyles, context } = useFloating<Element>({\n placement,\n middleware: [\n offset(8),\n flip({ padding: floatingPadding, crossAxis: false }),\n shift(),\n floatingSize({\n padding: floatingPadding,\n apply: ({ elements, rects, availableHeight }) => {\n elements.floating.style.setProperty('--max-height', `${availableHeight}px`);\n elements.floating.style.setProperty('--width', `${rects.reference.width}px`);\n },\n }),\n ],\n whileElementsMounted: autoUpdate,\n open,\n onOpenChange: (value) => {\n if (!value) {\n onClose?.();\n }\n },\n });\n\n const dismiss = useDismiss(context);\n const role = useRole(context);\n const { getReferenceProps, getFloatingProps } = useInteractions([role, dismiss]);\n\n const [floatingKey, setFloatingKey] = useState(0);\n\n const { theme, screenMode } = useTheme();\n\n return (\n <>\n {open ? <PreventScroll /> : null}\n {renderTrigger({\n ref: refs.setReference,\n getInteractionProps: getReferenceProps,\n })}\n\n <FloatingPortal>\n <ThemeProvider theme=\"personal\" screenMode={theme === 'personal' ? screenMode : 'light'}>\n <Transition\n show={open}\n leave=\"transition-opacity\"\n leaveTo=\"opacity-0\"\n beforeEnter={() => {\n setFloatingKey((prev) => prev + 1);\n }}\n afterLeave={onCloseEnd}\n >\n <FocusScope>\n <FloatingFocusManager context={context}>\n <div\n key={floatingKey} // Force inner state invalidation on open\n ref={refs.setFloating}\n className={clsx('np-popover-v2-container', {\n 'np-popover-v2-container--size-md': size === 'md',\n 'np-popover-v2-container--size-lg': size === 'lg',\n })}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n <div\n className={clsx('np-popover-v2', title && 'np-popover-v2--has-title', {\n 'np-popover-v2--padding-md': padding === 'md',\n })}\n >\n {title ? (\n <h2 className=\"np-popover-v2-title np-text-title-body\">{title}</h2>\n ) : null}\n <div className=\"np-popover-v2-content np-text-body-default\">{children}</div>\n </div>\n </div>\n </FloatingFocusManager>\n </FocusScope>\n </Transition>\n </ThemeProvider>\n </FloatingPortal>\n </>\n );\n}\n"],"names":["floatingPadding","Popover","placement","open","renderTrigger","title","size","padding","children","onClose","onCloseEnd","refs","floatingStyles","context","useFloating","middleware","offset","flip","crossAxis","shift","floatingSize","apply","elements","rects","availableHeight","floating","style","setProperty","reference","width","whileElementsMounted","autoUpdate","onOpenChange","value","dismiss","useDismiss","role","useRole","getReferenceProps","getFloatingProps","useInteractions","floatingKey","setFloatingKey","useState","theme","screenMode","useTheme","_jsxs","_Fragment","_jsx","PreventScroll","ref","setReference","getInteractionProps","FloatingPortal","ThemeProvider","Transition","show","leave","leaveTo","beforeEnter","prev","afterLeave","FocusScope","FloatingFocusManager","setFloating","className","clsx"],"mappings":";;;;;;;;;AAuCA,MAAMA,eAAe,GAAG,EAAE;AAEpB,SAAUC,OAAOA,CAAC;EACtBC,SAAS;EACTC,IAAI;EACJC,aAAa;EACbC,KAAK;AACLC,QAAAA,MAAI,GAAG,IAAI;AACXC,EAAAA,OAAO,GAAG,IAAI;EACdC,QAAQ;EACRC,OAAO;AACPC,EAAAA;AAAU,CACG,EAAA;EACb,MAAM;IAAEC,IAAI;IAAEC,cAAc;AAAEC,IAAAA;GAAS,GAAGC,WAAW,CAAU;
|
|
1
|
+
{"version":3,"file":"_Popover.mjs","sources":["../../src/inputs/_Popover.tsx"],"sourcesContent":["import {\n autoUpdate,\n flip,\n FloatingFocusManager,\n FloatingPortal,\n offset,\n type Placement,\n shift,\n size as floatingSize,\n useDismiss,\n useFloating,\n useInteractions,\n useRole,\n} from '@floating-ui/react';\nimport { Transition } from '@headlessui/react';\nimport { FocusScope } from '@react-aria/focus';\nimport { ThemeProvider, useTheme } from '@wise/components-theming';\nimport { clsx } from 'clsx';\nimport { useState } from 'react';\n\nimport { PreventScroll } from '../common/preventScroll/PreventScroll';\n\nexport interface PopoverProps {\n placement?: Placement;\n open: boolean;\n renderTrigger: (args: {\n ref: React.RefCallback<Element>;\n getInteractionProps: (customEventHandlers?: React.HTMLProps<Element>) => {\n [key: string]: unknown;\n };\n }) => React.ReactNode;\n title?: string;\n size?: 'md' | 'lg';\n padding?: 'none' | 'md';\n children?: React.ReactNode;\n onClose?: () => void;\n onCloseEnd?: () => void;\n}\n\nconst floatingPadding = 16;\n\nexport function Popover({\n placement,\n open,\n renderTrigger,\n title,\n size = 'md',\n padding = 'md',\n children,\n onClose,\n onCloseEnd,\n}: PopoverProps) {\n const { refs, floatingStyles, context } = useFloating<Element>({\n strategy: 'fixed',\n placement,\n middleware: [\n offset(8),\n flip({ padding: floatingPadding, crossAxis: false }),\n shift(),\n floatingSize({\n padding: floatingPadding,\n apply: ({ elements, rects, availableHeight }) => {\n elements.floating.style.setProperty('--max-height', `${availableHeight}px`);\n elements.floating.style.setProperty('--width', `${rects.reference.width}px`);\n },\n }),\n ],\n whileElementsMounted: autoUpdate,\n open,\n onOpenChange: (value) => {\n if (!value) {\n onClose?.();\n }\n },\n });\n\n const dismiss = useDismiss(context);\n const role = useRole(context);\n const { getReferenceProps, getFloatingProps } = useInteractions([role, dismiss]);\n\n const [floatingKey, setFloatingKey] = useState(0);\n\n const { theme, screenMode } = useTheme();\n\n return (\n <>\n {open ? <PreventScroll /> : null}\n {renderTrigger({\n ref: refs.setReference,\n getInteractionProps: getReferenceProps,\n })}\n\n <FloatingPortal>\n <ThemeProvider theme=\"personal\" screenMode={theme === 'personal' ? screenMode : 'light'}>\n <Transition\n as=\"div\"\n show={open}\n leave=\"transition-opacity\"\n leaveTo=\"opacity-0\"\n beforeEnter={() => {\n setFloatingKey((prev) => prev + 1);\n }}\n afterLeave={onCloseEnd}\n >\n <FocusScope>\n <FloatingFocusManager context={context}>\n <div\n key={floatingKey} // Force inner state invalidation on open\n ref={refs.setFloating}\n className={clsx('np-popover-v2-container', {\n 'np-popover-v2-container--size-md': size === 'md',\n 'np-popover-v2-container--size-lg': size === 'lg',\n })}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n <div\n className={clsx('np-popover-v2', title && 'np-popover-v2--has-title', {\n 'np-popover-v2--padding-md': padding === 'md',\n })}\n >\n {title ? (\n <h2 className=\"np-popover-v2-title np-text-title-body\">{title}</h2>\n ) : null}\n <div className=\"np-popover-v2-content np-text-body-default\">{children}</div>\n </div>\n </div>\n </FloatingFocusManager>\n </FocusScope>\n </Transition>\n </ThemeProvider>\n </FloatingPortal>\n </>\n );\n}\n"],"names":["floatingPadding","Popover","placement","open","renderTrigger","title","size","padding","children","onClose","onCloseEnd","refs","floatingStyles","context","useFloating","strategy","middleware","offset","flip","crossAxis","shift","floatingSize","apply","elements","rects","availableHeight","floating","style","setProperty","reference","width","whileElementsMounted","autoUpdate","onOpenChange","value","dismiss","useDismiss","role","useRole","getReferenceProps","getFloatingProps","useInteractions","floatingKey","setFloatingKey","useState","theme","screenMode","useTheme","_jsxs","_Fragment","_jsx","PreventScroll","ref","setReference","getInteractionProps","FloatingPortal","ThemeProvider","Transition","as","show","leave","leaveTo","beforeEnter","prev","afterLeave","FocusScope","FloatingFocusManager","setFloating","className","clsx"],"mappings":"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"}
|
package/build/main.css
CHANGED
|
@@ -948,7 +948,7 @@
|
|
|
948
948
|
}
|
|
949
949
|
.np-avatar-view .np-avatar-view-content {
|
|
950
950
|
color: #37517e;
|
|
951
|
-
color: var(--color-content-primary);
|
|
951
|
+
color: var(--color-sentiment-content-primary, var(--color-content-primary));
|
|
952
952
|
}
|
|
953
953
|
.np-avatar-view-interactive {
|
|
954
954
|
cursor: pointer;
|
package/build/styles/main.css
CHANGED
|
@@ -948,7 +948,7 @@
|
|
|
948
948
|
}
|
|
949
949
|
.np-avatar-view .np-avatar-view-content {
|
|
950
950
|
color: #37517e;
|
|
951
|
-
color: var(--color-content-primary);
|
|
951
|
+
color: var(--color-sentiment-content-primary, var(--color-content-primary));
|
|
952
952
|
}
|
|
953
953
|
.np-avatar-view-interactive {
|
|
954
954
|
cursor: pointer;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectInput.d.ts","sourceRoot":"","sources":["../../../src/inputs/SelectInput.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SelectInput.d.ts","sourceRoot":"","sources":["../../../src/inputs/SelectInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/inputs/_BottomSheet.tsx"],"names":[],"mappings":"AAmBA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE;QACrB,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAChC,mBAAmB,EAAE,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK;YACvE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;SACxB,CAAC;KACH,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,aAAa,EACb,KAAK,EACL,eAAe,EACf,OAAc,EACd,QAAQ,EACR,OAAO,EACP,UAAU,GACX,EAAE,gBAAgB,+
|
|
1
|
+
{"version":3,"file":"_BottomSheet.d.ts","sourceRoot":"","sources":["../../../src/inputs/_BottomSheet.tsx"],"names":[],"mappings":"AAmBA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE;QACrB,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAChC,mBAAmB,EAAE,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK;YACvE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;SACxB,CAAC;KACH,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,KAAK,CAAC,gBAAgB,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,aAAa,EACb,KAAK,EACL,eAAe,EACf,OAAc,EACd,QAAQ,EACR,OAAO,EACP,UAAU,GACX,EAAE,gBAAgB,+BA4FlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_Popover.d.ts","sourceRoot":"","sources":["../../../src/inputs/_Popover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EAOf,MAAM,oBAAoB,CAAC;AAS5B,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,EAAE,CAAC,IAAI,EAAE;QACpB,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAChC,mBAAmB,EAAE,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK;YACvE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;SACxB,CAAC;KACH,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAID,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,IAAI,EACJ,aAAa,EACb,KAAK,EACL,IAAW,EACX,OAAc,EACd,QAAQ,EACR,OAAO,EACP,UAAU,GACX,EAAE,YAAY,+
|
|
1
|
+
{"version":3,"file":"_Popover.d.ts","sourceRoot":"","sources":["../../../src/inputs/_Popover.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EAOf,MAAM,oBAAoB,CAAC;AAS5B,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,aAAa,EAAE,CAAC,IAAI,EAAE;QACpB,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAChC,mBAAmB,EAAE,CAAC,mBAAmB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK;YACvE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;SACxB,CAAC;KACH,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAID,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,IAAI,EACJ,aAAa,EACb,KAAK,EACL,IAAW,EACX,OAAc,EACd,QAAQ,EACR,OAAO,EACP,UAAU,GACX,EAAE,YAAY,+BAmFd"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@transferwise/components",
|
|
3
|
-
"version": "46.
|
|
3
|
+
"version": "46.124.1",
|
|
4
4
|
"description": "Neptune React components",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@storybook/react-webpack5": "10.3.0-alpha.0",
|
|
57
57
|
"@testing-library/dom": "^10.4.1",
|
|
58
58
|
"@testing-library/jest-dom": "^6.9.1",
|
|
59
|
-
"@testing-library/react": "^16.3.
|
|
59
|
+
"@testing-library/react": "^16.3.2",
|
|
60
60
|
"@testing-library/user-event": "^14.6.1",
|
|
61
61
|
"@transferwise/icons": "^4.0.2",
|
|
62
62
|
"@tsconfig/recommended": "^1.0.13",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"jest": "^30.2.0",
|
|
79
79
|
"jest-environment-jsdom": "^29.7.0",
|
|
80
80
|
"jest-fetch-mock": "^3.0.3",
|
|
81
|
+
"jsdom-testing-mocks": "^1.16.0",
|
|
81
82
|
"lodash.times": "^4.3.2",
|
|
82
83
|
"react-intl": "^7.1.11",
|
|
83
84
|
"rollup": "^4.54.0",
|
|
@@ -86,9 +87,9 @@
|
|
|
86
87
|
"storybook-addon-tag-badges": "^3.0.4",
|
|
87
88
|
"storybook-addon-test-codegen": "^3.0.1",
|
|
88
89
|
"@transferwise/less-config": "3.1.2",
|
|
90
|
+
"@transferwise/neptune-css": "14.26.1",
|
|
89
91
|
"@wise/components-theming": "1.10.1",
|
|
90
|
-
"@wise/wds-configs": "0.0.0"
|
|
91
|
-
"@transferwise/neptune-css": "14.26.1"
|
|
92
|
+
"@wise/wds-configs": "0.0.0"
|
|
92
93
|
},
|
|
93
94
|
"peerDependencies": {
|
|
94
95
|
"@transferwise/icons": "^3 || ^4",
|
|
@@ -103,7 +104,7 @@
|
|
|
103
104
|
"dependencies": {
|
|
104
105
|
"@babel/runtime": "^7.28.4",
|
|
105
106
|
"@floating-ui/react": "^0.27.16",
|
|
106
|
-
"@headlessui/react": "^
|
|
107
|
+
"@headlessui/react": "^2.2.9",
|
|
107
108
|
"@popperjs/core": "^2.11.8",
|
|
108
109
|
"@react-aria/focus": "^3.21.3",
|
|
109
110
|
"@react-aria/overlays": "^3.31.0",
|
|
@@ -4,6 +4,7 @@ import AvatarLayout, { AvatarLayoutProps } from '.';
|
|
|
4
4
|
import { Freeze, Graph, Plane, Rewards } from '@transferwise/icons';
|
|
5
5
|
import { Flag } from '@wise/art';
|
|
6
6
|
import Body from '../body';
|
|
7
|
+
import SentimentSurface from '../sentimentSurface';
|
|
7
8
|
|
|
8
9
|
export default {
|
|
9
10
|
title: 'Content/AvatarLayout',
|
|
@@ -283,3 +284,55 @@ export const EdgeInstances: Story = {
|
|
|
283
284
|
</div>
|
|
284
285
|
),
|
|
285
286
|
};
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Like [AvatarView](?path=/docs/content-avatarview--docs#sentiment-awareness), `AvatarLayout` is sentiment-aware (note: not all features are supported) and will automatically adjust its colours if wrapped inside the
|
|
290
|
+
* [SentimentSurface](?path=/docs/content-sentimentsurface--docs) component.
|
|
291
|
+
*
|
|
292
|
+
* Features like: `interactive` are not supported.
|
|
293
|
+
* Also `AvatarLayout` isn't supported on `"elevated"` state of `SentimentSurface`.
|
|
294
|
+
*/
|
|
295
|
+
export const SentimentAwareness: Story = {
|
|
296
|
+
parameters: {
|
|
297
|
+
docs: {
|
|
298
|
+
canvas: {
|
|
299
|
+
sourceState: 'hidden',
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
render: (args) => (
|
|
304
|
+
<>
|
|
305
|
+
{(['success', 'warning', 'negative', 'neutral', 'proposition'] as const).map((sentiment) =>
|
|
306
|
+
<SentimentSurface
|
|
307
|
+
key={`${sentiment}-base`}
|
|
308
|
+
sentiment={sentiment}
|
|
309
|
+
emphasis="base"
|
|
310
|
+
className="p-a-1 d-flex"
|
|
311
|
+
style={{ gap: 'var(--size-16)' }}
|
|
312
|
+
>
|
|
313
|
+
<AvatarLayout avatars={[{ asset: <Freeze /> }, { asset: <Freeze /> }]} />
|
|
314
|
+
<AvatarLayout
|
|
315
|
+
orientation="diagonal"
|
|
316
|
+
avatars={[{ asset: <Freeze /> }, { asset: <Freeze /> }]}
|
|
317
|
+
/>
|
|
318
|
+
</SentimentSurface>
|
|
319
|
+
)}
|
|
320
|
+
</>
|
|
321
|
+
),
|
|
322
|
+
decorators: [
|
|
323
|
+
(Story: () => JSX.Element) => (
|
|
324
|
+
<div
|
|
325
|
+
style={{
|
|
326
|
+
width: '100%',
|
|
327
|
+
display: 'grid',
|
|
328
|
+
gridTemplateColumns: 'min-content min-content',
|
|
329
|
+
justifyContent: 'center',
|
|
330
|
+
gap: '1rem',
|
|
331
|
+
maxWidth: '800px',
|
|
332
|
+
}}
|
|
333
|
+
>
|
|
334
|
+
<Story />
|
|
335
|
+
</div>
|
|
336
|
+
),
|
|
337
|
+
],
|
|
338
|
+
};
|
|
@@ -17,12 +17,15 @@ import {
|
|
|
17
17
|
Transport,
|
|
18
18
|
Wallet,
|
|
19
19
|
Water,
|
|
20
|
+
Bank,
|
|
21
|
+
GiftBox,
|
|
20
22
|
} from '@transferwise/icons';
|
|
21
23
|
import AvatarView, { AvatarViewProps } from '.';
|
|
22
24
|
import { Flag } from '@wise/art';
|
|
23
25
|
import { getBrandColorFromSeed, getInitials, ProfileType } from '../common';
|
|
24
26
|
import Display from '../display';
|
|
25
27
|
import Body from '../body';
|
|
28
|
+
import SentimentSurface from '../sentimentSurface';
|
|
26
29
|
|
|
27
30
|
export default {
|
|
28
31
|
title: 'Content/AvatarView',
|
|
@@ -35,6 +38,20 @@ const profileName1 = 'Wolter White';
|
|
|
35
38
|
const profileName2 = 'Tyler Durden';
|
|
36
39
|
const sizes: AvatarViewProps['size'][] = [16, 24, 32, 40, 48, 56, 72];
|
|
37
40
|
|
|
41
|
+
const withComponentGrid = (Story: () => JSX.Element) => (
|
|
42
|
+
<div
|
|
43
|
+
style={{
|
|
44
|
+
width: '100%',
|
|
45
|
+
display: 'flex',
|
|
46
|
+
flexDirection: 'column',
|
|
47
|
+
gap: '1rem',
|
|
48
|
+
maxWidth: '800px',
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
<Story />
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
|
|
38
55
|
export const Selected: Story = {
|
|
39
56
|
render: () => {
|
|
40
57
|
return (
|
|
@@ -420,6 +437,55 @@ export const Profiles: Story = {
|
|
|
420
437
|
},
|
|
421
438
|
};
|
|
422
439
|
|
|
440
|
+
/**
|
|
441
|
+
* `AvatarView` is sentiment-aware (note: not all features are supported) and will automatically adjust its colours if wrapped inside the
|
|
442
|
+
* [SentimentSurface](?path=/docs/content-sentimentsurface--docs) component.
|
|
443
|
+
*
|
|
444
|
+
* Features like `online`, `notification`, `selected`, and `interactive` are not supported.
|
|
445
|
+
* For badge (`<AvatarView badge={}>`) only `flagCode` is supported.
|
|
446
|
+
* Also `AvatarView` isn't supported on `"elevated"` state of `SentimentSurface`.
|
|
447
|
+
*/
|
|
448
|
+
export const SentimentAwareness: Story = {
|
|
449
|
+
parameters: {
|
|
450
|
+
docs: {
|
|
451
|
+
canvas: {
|
|
452
|
+
sourceState: 'hidden',
|
|
453
|
+
},
|
|
454
|
+
source: { type: 'code' },
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
render: () => {
|
|
458
|
+
return (
|
|
459
|
+
<>
|
|
460
|
+
{(['success', 'warning', 'negative', 'neutral', 'proposition'] as const).map((sentiment) => (
|
|
461
|
+
<SentimentSurface
|
|
462
|
+
key={`${sentiment}-base`}
|
|
463
|
+
sentiment={sentiment}
|
|
464
|
+
emphasis="base"
|
|
465
|
+
className="p-a-1 d-flex"
|
|
466
|
+
style={{ gap: 'var(--size-16)' }}
|
|
467
|
+
>
|
|
468
|
+
<AvatarView size={32}>
|
|
469
|
+
<Bank />
|
|
470
|
+
</AvatarView>
|
|
471
|
+
<AvatarView size={32} profileName="John Doe" />
|
|
472
|
+
<AvatarView size={32}>
|
|
473
|
+
<Flag code="JPY" intrinsicSize={32} />
|
|
474
|
+
</AvatarView>
|
|
475
|
+
<AvatarView size={32} badge={sentiment === 'proposition' ? undefined : { status: sentiment }}>
|
|
476
|
+
<Bank />
|
|
477
|
+
</AvatarView>
|
|
478
|
+
<AvatarView size={32} badge={{ flagCode: 'eu' }}>
|
|
479
|
+
<Bank />
|
|
480
|
+
</AvatarView>
|
|
481
|
+
</SentimentSurface>
|
|
482
|
+
))}
|
|
483
|
+
</>
|
|
484
|
+
);
|
|
485
|
+
},
|
|
486
|
+
decorators: [withComponentGrid],
|
|
487
|
+
};
|
|
488
|
+
|
|
423
489
|
export const ProfileBrokenImageFallback: Story = {
|
|
424
490
|
parameters: {
|
|
425
491
|
chromatic: {
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import { screen, waitFor, within } from '@testing-library/react';
|
|
2
2
|
import { userEvent } from '@testing-library/user-event';
|
|
3
|
+
import { mockAnimationsApi } from 'jsdom-testing-mocks';
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
-
render,
|
|
6
|
-
mockMatchMedia,
|
|
7
|
-
mockResizeObserver,
|
|
8
|
-
mockRequestAnimationFrame,
|
|
9
|
-
} from '../test-utils';
|
|
5
|
+
import { render, mockMatchMedia, mockResizeObserver } from '../test-utils';
|
|
10
6
|
|
|
11
7
|
import { SelectInput, type SelectInputOptionItem, type SelectInputProps } from './SelectInput';
|
|
12
8
|
import { Field } from '../field/Field';
|
|
13
9
|
|
|
14
10
|
mockMatchMedia();
|
|
15
11
|
mockResizeObserver();
|
|
16
|
-
|
|
12
|
+
mockAnimationsApi();
|
|
17
13
|
|
|
18
14
|
describe('SelectInput', () => {
|
|
19
15
|
it('renders placeholder', () => {
|
|
@@ -67,6 +63,81 @@ describe('SelectInput', () => {
|
|
|
67
63
|
expect(footer).toHaveTextContent(/‘ur’$/);
|
|
68
64
|
});
|
|
69
65
|
|
|
66
|
+
it('allows navigating the listbox with cursors', async () => {
|
|
67
|
+
render(
|
|
68
|
+
<SelectInput
|
|
69
|
+
items={[
|
|
70
|
+
{ type: 'option', value: 'GBP' },
|
|
71
|
+
{ type: 'option', value: 'EUR' },
|
|
72
|
+
{ type: 'option', value: 'USD' },
|
|
73
|
+
]}
|
|
74
|
+
renderFooter={({ queryNormalized: normalizedQuery }) => (
|
|
75
|
+
<button type="button">Footer button</button>
|
|
76
|
+
)}
|
|
77
|
+
filterable
|
|
78
|
+
/>,
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
// opened the dropbox, with search focused
|
|
82
|
+
await userEvent.tab();
|
|
83
|
+
await userEvent.keyboard(' ');
|
|
84
|
+
expect(screen.getByRole('combobox')).toHaveFocus();
|
|
85
|
+
|
|
86
|
+
// search still focused but listbox can be navigated via keyboard
|
|
87
|
+
await userEvent.keyboard('{ArrowDown}');
|
|
88
|
+
expect(screen.getByRole('combobox')).toHaveFocus();
|
|
89
|
+
expect(screen.getByRole('option', { name: 'EUR' })).toHaveClass(
|
|
90
|
+
'np-select-input-option-container--active',
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// tab moves focus to listbox
|
|
94
|
+
await userEvent.tab();
|
|
95
|
+
expect(screen.getByRole('listbox')).toHaveFocus();
|
|
96
|
+
expect(screen.getByRole('combobox')).not.toHaveFocus();
|
|
97
|
+
|
|
98
|
+
// arrows still navigate within listbox
|
|
99
|
+
await userEvent.keyboard('{ArrowDown}');
|
|
100
|
+
expect(screen.getByRole('option', { name: 'USD' })).toHaveClass(
|
|
101
|
+
'np-select-input-option-container--active',
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// tab moves focus to footer but highlighted option is retained
|
|
105
|
+
await userEvent.tab();
|
|
106
|
+
expect(screen.getByRole('listbox')).not.toHaveFocus();
|
|
107
|
+
expect(screen.getByRole('combobox')).not.toHaveFocus();
|
|
108
|
+
expect(screen.getByText('Footer button')).toHaveFocus();
|
|
109
|
+
expect(screen.getByRole('option', { name: 'USD' })).toHaveClass(
|
|
110
|
+
'np-select-input-option-container--active',
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// shift+tab moves focus back to listbox
|
|
114
|
+
await userEvent.tab({ shift: true });
|
|
115
|
+
expect(screen.getByRole('listbox')).toHaveFocus();
|
|
116
|
+
expect(screen.getByRole('combobox')).not.toHaveFocus();
|
|
117
|
+
expect(screen.getByText('Footer button')).not.toHaveFocus();
|
|
118
|
+
|
|
119
|
+
// previously highlighted option is still active within listbox
|
|
120
|
+
expect(screen.getByRole('option', { name: 'USD' })).toHaveClass(
|
|
121
|
+
'np-select-input-option-container--active',
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// arrows continue to navigate within listbox
|
|
125
|
+
await userEvent.keyboard('{ArrowUp}');
|
|
126
|
+
expect(screen.getByRole('option', { name: 'EUR' })).toHaveClass(
|
|
127
|
+
'np-select-input-option-container--active',
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
// shift+tab moves focus back to search input
|
|
131
|
+
await userEvent.tab({ shift: true });
|
|
132
|
+
expect(screen.getByRole('combobox')).toHaveFocus();
|
|
133
|
+
|
|
134
|
+
// arrows continue to navigate within listbox
|
|
135
|
+
await userEvent.keyboard('{ArrowUp}');
|
|
136
|
+
expect(screen.getByRole('option', { name: 'GBP' })).toHaveClass(
|
|
137
|
+
'np-select-input-option-container--active',
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
|
|
70
141
|
it('shows item selected via mouse', async () => {
|
|
71
142
|
const handleClose = jest.fn();
|
|
72
143
|
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Listbox as ListboxBase,
|
|
3
|
+
ListboxButton,
|
|
4
|
+
ListboxOption,
|
|
5
|
+
ListboxOptions,
|
|
6
|
+
} from '@headlessui/react';
|
|
2
7
|
import { Check, ChevronDown, Cross, CrossCircle } from '@transferwise/icons';
|
|
3
8
|
import { clsx } from 'clsx';
|
|
4
9
|
import mergeProps from 'merge-props';
|
|
@@ -427,8 +432,8 @@ export function SelectInput<T = string, M extends boolean = false>({
|
|
|
427
432
|
<ListboxBase
|
|
428
433
|
name={name}
|
|
429
434
|
multiple={multiple}
|
|
430
|
-
defaultValue={defaultValue}
|
|
431
|
-
value={controlledValue}
|
|
435
|
+
defaultValue={defaultValue as M extends true ? T[] : T}
|
|
436
|
+
value={controlledValue as M extends true ? T[] : T}
|
|
432
437
|
by={compareValues}
|
|
433
438
|
disabled={disabled}
|
|
434
439
|
onChange={
|
|
@@ -576,7 +581,7 @@ export function SelectInputTriggerButton<T extends SelectInputTriggerButtonEleme
|
|
|
576
581
|
);
|
|
577
582
|
|
|
578
583
|
return (
|
|
579
|
-
<
|
|
584
|
+
<ListboxButton
|
|
580
585
|
ref={ref}
|
|
581
586
|
as={PolymorphicWithOverrides}
|
|
582
587
|
role="combobox"
|
|
@@ -617,8 +622,13 @@ const SelectInputOptionsContainer = forwardRef(function SelectInputOptionsContai
|
|
|
617
622
|
return;
|
|
618
623
|
}
|
|
619
624
|
|
|
620
|
-
//
|
|
621
|
-
if (event.key === '
|
|
625
|
+
// Required to make ListBox focusable
|
|
626
|
+
if (event.key === 'Tab') {
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// Prevent absorbing Escape early
|
|
631
|
+
if (event.key === 'Escape') {
|
|
622
632
|
onKeyDown?.({
|
|
623
633
|
...event,
|
|
624
634
|
preventDefault: () => {},
|
|
@@ -817,7 +827,8 @@ function SelectInputOptions<T = string>({
|
|
|
817
827
|
};
|
|
818
828
|
|
|
819
829
|
return (
|
|
820
|
-
<
|
|
830
|
+
<ListboxOptions
|
|
831
|
+
modal
|
|
821
832
|
as={SelectInputOptionsContainer}
|
|
822
833
|
static
|
|
823
834
|
className="np-select-input-options-container"
|
|
@@ -974,7 +985,7 @@ function SelectInputOptions<T = string>({
|
|
|
974
985
|
</footer>
|
|
975
986
|
) : null}
|
|
976
987
|
</section>
|
|
977
|
-
</
|
|
988
|
+
</ListboxOptions>
|
|
978
989
|
);
|
|
979
990
|
}
|
|
980
991
|
|
|
@@ -1083,7 +1094,7 @@ function SelectInputOption<T = string>({ value, disabled, children }: SelectInpu
|
|
|
1083
1094
|
const itemsCount = useContext(SelectInputItemsCountContext);
|
|
1084
1095
|
const itemPosition = useContext(SelectInputItemPositionContext);
|
|
1085
1096
|
return (
|
|
1086
|
-
<
|
|
1097
|
+
<ListboxOption
|
|
1087
1098
|
as="div"
|
|
1088
1099
|
value={value}
|
|
1089
1100
|
aria-setsize={itemsCount}
|
|
@@ -1109,7 +1120,7 @@ function SelectInputOption<T = string>({ value, disabled, children }: SelectInpu
|
|
|
1109
1120
|
/>
|
|
1110
1121
|
</>
|
|
1111
1122
|
)}
|
|
1112
|
-
</
|
|
1123
|
+
</ListboxOption>
|
|
1113
1124
|
);
|
|
1114
1125
|
}
|
|
1115
1126
|
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
useInteractions,
|
|
7
7
|
useRole,
|
|
8
8
|
} from '@floating-ui/react';
|
|
9
|
-
import { Transition } from '@headlessui/react';
|
|
9
|
+
import { Transition, TransitionChild } from '@headlessui/react';
|
|
10
10
|
import { FocusScope } from '@react-aria/focus';
|
|
11
11
|
import { ThemeProvider, useTheme } from '@wise/components-theming';
|
|
12
12
|
import { clsx } from 'clsx';
|
|
@@ -73,6 +73,7 @@ export function BottomSheet({
|
|
|
73
73
|
<FloatingPortal>
|
|
74
74
|
<ThemeProvider theme="personal" screenMode={theme === 'personal' ? screenMode : 'light'}>
|
|
75
75
|
<Transition
|
|
76
|
+
as="div"
|
|
76
77
|
show={open}
|
|
77
78
|
className="np-bottom-sheet-v2-container"
|
|
78
79
|
beforeEnter={() => {
|
|
@@ -80,7 +81,8 @@ export function BottomSheet({
|
|
|
80
81
|
}}
|
|
81
82
|
afterLeave={onCloseEnd}
|
|
82
83
|
>
|
|
83
|
-
<
|
|
84
|
+
<TransitionChild
|
|
85
|
+
as="div"
|
|
84
86
|
className="np-bottom-sheet-v2-backdrop"
|
|
85
87
|
enterFrom="np-bottom-sheet-v2-backdrop--closed"
|
|
86
88
|
leaveTo="np-bottom-sheet-v2-backdrop--closed"
|
|
@@ -92,8 +94,9 @@ export function BottomSheet({
|
|
|
92
94
|
<Fragment
|
|
93
95
|
key={floatingKey} // Force inner state invalidation on open
|
|
94
96
|
>
|
|
95
|
-
<
|
|
97
|
+
<TransitionChild
|
|
96
98
|
ref={refs.setFloating}
|
|
99
|
+
as="div"
|
|
97
100
|
className="np-bottom-sheet-v2-content"
|
|
98
101
|
enterFrom="np-bottom-sheet-v2-content--closed"
|
|
99
102
|
leaveTo="np-bottom-sheet-v2-content--closed"
|
|
@@ -121,7 +124,7 @@ export function BottomSheet({
|
|
|
121
124
|
{children}
|
|
122
125
|
</div>
|
|
123
126
|
</div>
|
|
124
|
-
</
|
|
127
|
+
</TransitionChild>
|
|
125
128
|
</Fragment>
|
|
126
129
|
</FloatingFocusManager>
|
|
127
130
|
</FocusScope>
|
package/src/inputs/_Popover.tsx
CHANGED
|
@@ -51,6 +51,7 @@ export function Popover({
|
|
|
51
51
|
onCloseEnd,
|
|
52
52
|
}: PopoverProps) {
|
|
53
53
|
const { refs, floatingStyles, context } = useFloating<Element>({
|
|
54
|
+
strategy: 'fixed',
|
|
54
55
|
placement,
|
|
55
56
|
middleware: [
|
|
56
57
|
offset(8),
|
|
@@ -92,6 +93,7 @@ export function Popover({
|
|
|
92
93
|
<FloatingPortal>
|
|
93
94
|
<ThemeProvider theme="personal" screenMode={theme === 'personal' ? screenMode : 'light'}>
|
|
94
95
|
<Transition
|
|
96
|
+
as="div"
|
|
95
97
|
show={open}
|
|
96
98
|
leave="transition-opacity"
|
|
97
99
|
leaveTo="opacity-0"
|
package/src/main.css
CHANGED
|
@@ -948,7 +948,7 @@
|
|
|
948
948
|
}
|
|
949
949
|
.np-avatar-view .np-avatar-view-content {
|
|
950
950
|
color: #37517e;
|
|
951
|
-
color: var(--color-content-primary);
|
|
951
|
+
color: var(--color-sentiment-content-primary, var(--color-content-primary));
|
|
952
952
|
}
|
|
953
953
|
.np-avatar-view-interactive {
|
|
954
954
|
cursor: pointer;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
+
import { mockAnimationsApi } from 'jsdom-testing-mocks';
|
|
1
2
|
import {
|
|
2
3
|
mockMatchMedia,
|
|
3
|
-
mockRequestAnimationFrame,
|
|
4
4
|
mockResizeObserver,
|
|
5
5
|
render,
|
|
6
6
|
screen,
|
|
7
7
|
userEvent,
|
|
8
|
+
waitFor,
|
|
9
|
+
within,
|
|
8
10
|
} from '../test-utils';
|
|
9
11
|
|
|
10
12
|
import { MoneyInput, CurrencyItem, CurrencyOptionItem, Field } from '..';
|
|
11
13
|
import { MoneyInputPropsWithInputAttributes } from './MoneyInput';
|
|
12
|
-
import { within } from '@testing-library/react';
|
|
13
14
|
import messages from './MoneyInput.messages';
|
|
14
15
|
|
|
15
16
|
mockMatchMedia();
|
|
16
17
|
mockResizeObserver();
|
|
17
|
-
|
|
18
|
+
mockAnimationsApi();
|
|
18
19
|
|
|
19
20
|
describe('Money Input', () => {
|
|
20
21
|
const popularCurrencies: CurrencyOptionItem[] = [
|
|
@@ -114,12 +115,30 @@ describe('Money Input', () => {
|
|
|
114
115
|
it('calls onCurrencyChange when the user selects a different currency', async () => {
|
|
115
116
|
customRender();
|
|
116
117
|
await openDropdown();
|
|
117
|
-
await userEvent.keyboard('eur
|
|
118
|
-
|
|
118
|
+
await userEvent.keyboard('eur');
|
|
119
|
+
await waitFor(() => {
|
|
120
|
+
expect(screen.getAllByRole('option')).toHaveLength(1);
|
|
121
|
+
});
|
|
122
|
+
await userEvent.keyboard('{Enter}');
|
|
123
|
+
|
|
124
|
+
await waitFor(() => {
|
|
125
|
+
expect(initialProps.onCurrencyChange).toHaveBeenCalledTimes(1);
|
|
126
|
+
});
|
|
119
127
|
expect(initialProps.onCurrencyChange).toHaveBeenCalledWith(popularCurrencies[0]);
|
|
128
|
+
|
|
129
|
+
await waitFor(() => {
|
|
130
|
+
expect(screen.queryByRole('listbox')).not.toBeInTheDocument();
|
|
131
|
+
});
|
|
120
132
|
await openDropdown();
|
|
121
|
-
await userEvent.keyboard('gbp
|
|
122
|
-
|
|
133
|
+
await userEvent.keyboard('gbp');
|
|
134
|
+
await waitFor(() => {
|
|
135
|
+
expect(screen.getAllByRole('option')).toHaveLength(1);
|
|
136
|
+
});
|
|
137
|
+
await userEvent.keyboard('{Enter}');
|
|
138
|
+
|
|
139
|
+
await waitFor(() => {
|
|
140
|
+
expect(initialProps.onCurrencyChange).toHaveBeenCalledTimes(2);
|
|
141
|
+
});
|
|
123
142
|
expect(initialProps.onCurrencyChange).toHaveBeenCalledWith(popularCurrencies[2]);
|
|
124
143
|
});
|
|
125
144
|
|