@transferwise/components 0.0.0-experimental-eaf43c2 → 0.0.0-experimental-6730b89

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 (139) hide show
  1. package/build/avatarLayout/AvatarLayout.js.map +1 -1
  2. package/build/avatarLayout/AvatarLayout.mjs.map +1 -1
  3. package/build/avatarView/AvatarView.js +8 -4
  4. package/build/avatarView/AvatarView.js.map +1 -1
  5. package/build/avatarView/AvatarView.mjs +8 -4
  6. package/build/avatarView/AvatarView.mjs.map +1 -1
  7. package/build/avatarView/{NotificationDot.js → Dot.js} +14 -12
  8. package/build/avatarView/Dot.js.map +1 -0
  9. package/build/avatarView/{NotificationDot.mjs → Dot.mjs} +14 -12
  10. package/build/avatarView/Dot.mjs.map +1 -0
  11. package/build/i18n/en.json +0 -2
  12. package/build/i18n/en.json.js +0 -2
  13. package/build/i18n/en.json.js.map +1 -1
  14. package/build/i18n/en.json.mjs +0 -2
  15. package/build/i18n/en.json.mjs.map +1 -1
  16. package/build/index.js +0 -2
  17. package/build/index.js.map +1 -1
  18. package/build/index.mjs +0 -1
  19. package/build/index.mjs.map +1 -1
  20. package/build/main.css +17 -69
  21. package/build/styles/avatarView/AvatarView.css +17 -11
  22. package/build/styles/avatarView/Dot.css +26 -0
  23. package/build/styles/main.css +17 -69
  24. package/build/types/avatarLayout/AvatarLayout.d.ts +1 -1
  25. package/build/types/avatarLayout/AvatarLayout.d.ts.map +1 -1
  26. package/build/types/avatarView/AvatarView.d.ts +4 -1
  27. package/build/types/avatarView/AvatarView.d.ts.map +1 -1
  28. package/build/types/avatarView/Dot.d.ts +8 -0
  29. package/build/types/avatarView/Dot.d.ts.map +1 -0
  30. package/build/types/index.d.ts +0 -2
  31. package/build/types/index.d.ts.map +1 -1
  32. package/build/types/test-utils/index.d.ts +0 -4
  33. package/build/types/test-utils/index.d.ts.map +1 -1
  34. package/package.json +2 -3
  35. package/src/avatarLayout/AvatarLayout.tsx +1 -1
  36. package/src/avatarView/AvatarView.css +17 -11
  37. package/src/avatarView/AvatarView.less +1 -1
  38. package/src/avatarView/AvatarView.story.tsx +37 -0
  39. package/src/avatarView/AvatarView.tsx +13 -6
  40. package/src/avatarView/Dot.css +26 -0
  41. package/src/avatarView/Dot.less +31 -0
  42. package/src/avatarView/Dot.tsx +42 -0
  43. package/src/i18n/en.json +0 -2
  44. package/src/index.ts +0 -2
  45. package/src/listItem/AvatarView/ListItemAvatarView.story.tsx +69 -2
  46. package/src/main.css +17 -69
  47. package/src/main.less +0 -1
  48. package/src/ssr.spec.tsx +0 -1
  49. package/build/avatarView/NotificationDot.js.map +0 -1
  50. package/build/avatarView/NotificationDot.mjs.map +0 -1
  51. package/build/moneyInputField/AmountInput.js +0 -284
  52. package/build/moneyInputField/AmountInput.js.map +0 -1
  53. package/build/moneyInputField/AmountInput.mjs +0 -282
  54. package/build/moneyInputField/AmountInput.mjs.map +0 -1
  55. package/build/moneyInputField/AnimatedNumber.js +0 -50
  56. package/build/moneyInputField/AnimatedNumber.js.map +0 -1
  57. package/build/moneyInputField/AnimatedNumber.mjs +0 -48
  58. package/build/moneyInputField/AnimatedNumber.mjs.map +0 -1
  59. package/build/moneyInputField/Chevron.js +0 -33
  60. package/build/moneyInputField/Chevron.js.map +0 -1
  61. package/build/moneyInputField/Chevron.mjs +0 -31
  62. package/build/moneyInputField/Chevron.mjs.map +0 -1
  63. package/build/moneyInputField/CurrencySelector.js +0 -160
  64. package/build/moneyInputField/CurrencySelector.js.map +0 -1
  65. package/build/moneyInputField/CurrencySelector.mjs +0 -157
  66. package/build/moneyInputField/CurrencySelector.mjs.map +0 -1
  67. package/build/moneyInputField/MoneyInputField.js +0 -113
  68. package/build/moneyInputField/MoneyInputField.js.map +0 -1
  69. package/build/moneyInputField/MoneyInputField.messages.js +0 -17
  70. package/build/moneyInputField/MoneyInputField.messages.js.map +0 -1
  71. package/build/moneyInputField/MoneyInputField.messages.mjs +0 -13
  72. package/build/moneyInputField/MoneyInputField.messages.mjs.map +0 -1
  73. package/build/moneyInputField/MoneyInputField.mjs +0 -109
  74. package/build/moneyInputField/MoneyInputField.mjs.map +0 -1
  75. package/build/moneyInputField/useFocus.js +0 -37
  76. package/build/moneyInputField/useFocus.js.map +0 -1
  77. package/build/moneyInputField/useFocus.mjs +0 -35
  78. package/build/moneyInputField/useFocus.mjs.map +0 -1
  79. package/build/moneyInputField/useInputStyle.js +0 -71
  80. package/build/moneyInputField/useInputStyle.js.map +0 -1
  81. package/build/moneyInputField/useInputStyle.mjs +0 -69
  82. package/build/moneyInputField/useInputStyle.mjs.map +0 -1
  83. package/build/moneyInputField/utils.js +0 -87
  84. package/build/moneyInputField/utils.js.map +0 -1
  85. package/build/moneyInputField/utils.mjs +0 -78
  86. package/build/moneyInputField/utils.mjs.map +0 -1
  87. package/build/styles/avatarView/NotificationDot.css +0 -20
  88. package/build/styles/moneyInputField/AmountInput.css +0 -32
  89. package/build/styles/moneyInputField/Chevron.css +0 -12
  90. package/build/styles/moneyInputField/CurrencySelector.css +0 -6
  91. package/build/styles/moneyInputField/MoneyInputField.css +0 -58
  92. package/build/types/avatarView/NotificationDot.d.ts +0 -8
  93. package/build/types/avatarView/NotificationDot.d.ts.map +0 -1
  94. package/build/types/moneyInputField/AmountInput.d.ts +0 -13
  95. package/build/types/moneyInputField/AmountInput.d.ts.map +0 -1
  96. package/build/types/moneyInputField/AnimatedNumber.d.ts +0 -9
  97. package/build/types/moneyInputField/AnimatedNumber.d.ts.map +0 -1
  98. package/build/types/moneyInputField/Chevron.d.ts +0 -6
  99. package/build/types/moneyInputField/Chevron.d.ts.map +0 -1
  100. package/build/types/moneyInputField/CurrencySelector.d.ts +0 -30
  101. package/build/types/moneyInputField/CurrencySelector.d.ts.map +0 -1
  102. package/build/types/moneyInputField/MoneyInputField.d.ts +0 -30
  103. package/build/types/moneyInputField/MoneyInputField.d.ts.map +0 -1
  104. package/build/types/moneyInputField/MoneyInputField.messages.d.ts +0 -12
  105. package/build/types/moneyInputField/MoneyInputField.messages.d.ts.map +0 -1
  106. package/build/types/moneyInputField/index.d.ts +0 -3
  107. package/build/types/moneyInputField/index.d.ts.map +0 -1
  108. package/build/types/moneyInputField/useFocus.d.ts +0 -7
  109. package/build/types/moneyInputField/useFocus.d.ts.map +0 -1
  110. package/build/types/moneyInputField/useInputStyle.d.ts +0 -10
  111. package/build/types/moneyInputField/useInputStyle.d.ts.map +0 -1
  112. package/build/types/moneyInputField/useSelectionRange.d.ts +0 -10
  113. package/build/types/moneyInputField/useSelectionRange.d.ts.map +0 -1
  114. package/build/types/moneyInputField/utils.d.ts +0 -22
  115. package/build/types/moneyInputField/utils.d.ts.map +0 -1
  116. package/src/avatarView/NotificationDot.css +0 -20
  117. package/src/avatarView/NotificationDot.less +0 -24
  118. package/src/avatarView/NotificationDot.tsx +0 -35
  119. package/src/moneyInputField/AmountInput.css +0 -32
  120. package/src/moneyInputField/AmountInput.less +0 -43
  121. package/src/moneyInputField/AmountInput.tsx +0 -355
  122. package/src/moneyInputField/AnimatedNumber.tsx +0 -40
  123. package/src/moneyInputField/Chevron.css +0 -12
  124. package/src/moneyInputField/Chevron.less +0 -13
  125. package/src/moneyInputField/Chevron.tsx +0 -35
  126. package/src/moneyInputField/CurrencySelector.css +0 -6
  127. package/src/moneyInputField/CurrencySelector.less +0 -7
  128. package/src/moneyInputField/CurrencySelector.tsx +0 -219
  129. package/src/moneyInputField/MoneyInputField.css +0 -58
  130. package/src/moneyInputField/MoneyInputField.less +0 -13
  131. package/src/moneyInputField/MoneyInputField.messages.ts +0 -13
  132. package/src/moneyInputField/MoneyInputField.story.tsx +0 -188
  133. package/src/moneyInputField/MoneyInputField.tsx +0 -123
  134. package/src/moneyInputField/index.ts +0 -2
  135. package/src/moneyInputField/useFocus.ts +0 -35
  136. package/src/moneyInputField/useInputStyle.ts +0 -85
  137. package/src/moneyInputField/useSelectionRange.ts +0 -23
  138. package/src/moneyInputField/utils.spec.ts +0 -114
  139. package/src/moneyInputField/utils.ts +0 -116
@@ -1,58 +0,0 @@
1
- .wds-amount-input-container {
2
- width: 100%;
3
- }
4
- .wds-amount-input-input-container {
5
- display: flex;
6
- justify-content: right;
7
- width: 100%;
8
- transition: font-size 0.4s cubic-bezier(0.3, 0, 0.1, 1), height 0.4s cubic-bezier(0.3, 0, 0.1, 1), margin-top 0.4s cubic-bezier(0.3, 0, 0.1, 1), color 0.4s ease;
9
- color: var(--color-interactive-primary);
10
- overflow: hidden;
11
- margin-bottom: 0 !important;
12
- }
13
- @media (prefers-reduced-motion: reduce) {
14
- .wds-amount-input-input-container {
15
- transition: none;
16
- }
17
- }
18
- .wds-amount-input-input {
19
- border: none;
20
- outline: none;
21
- flex-grow: 1;
22
- text-align: right;
23
- background-color: transparent;
24
- }
25
- .wds-amount-input-input:focus-visible {
26
- outline: none;
27
- }
28
- .wds-amount-input-placeholder {
29
- flex-grow: 0;
30
- display: flex;
31
- align-items: center;
32
- }
33
- .wds-currency-selector:disabled {
34
- opacity: 1 !important;
35
- cursor: auto !important;
36
- cursor: initial !important;
37
- mix-blend-mode: initial !important;
38
- }
39
- .wds-chevron-container {
40
- width: 32px;
41
- width: var(--size-32);
42
- overflow: hidden;
43
- color: var(--color-interactive-primary);
44
- margin-left: 8px;
45
- margin-left: var(--size-8);
46
- transition: width 0.3s ease;
47
- }
48
- .wds-chevron-hidden {
49
- width: 0;
50
- }
51
- .wds-money-input-field-currency-selector {
52
- flex-shrink: 0;
53
- margin-right: 24px;
54
- margin-right: var(--size-24);
55
- }
56
- .wds-money-input-field-chevron {
57
- transform: translateY(-5%);
58
- }
@@ -1,13 +0,0 @@
1
- @import "./AmountInput.less";
2
- @import "./CurrencySelector.less";
3
- @import "./Chevron.less";
4
-
5
- .wds-money-input-field {
6
- &-currency-selector {
7
- flex-shrink: 0;
8
- margin-right: var(--size-24);
9
- }
10
- &-chevron {
11
- transform: translateY(-5%);
12
- }
13
- }
@@ -1,13 +0,0 @@
1
- import { defineMessages } from 'react-intl';
2
-
3
- export default defineMessages({
4
- currencySelectorSearchPlaceholder: {
5
- id: 'neptune.MoneyInputField.currency.search.placeholder',
6
- defaultMessage: 'Type a currency / country',
7
- },
8
-
9
- currencySelectorSelectCurrency: {
10
- id: 'neptune.MoneyInputField.currency.select.currency',
11
- defaultMessage: 'Select currency',
12
- },
13
- });
@@ -1,188 +0,0 @@
1
- /* eslint-disable jsx-a11y/anchor-is-valid, no-console, jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */
2
- import { Meta } from '@storybook/react-webpack5';
3
- import MoneyInputField, { Props as MoneyInputFieldProps } from './MoneyInputField';
4
- import { lorem10 } from '../test-utils';
5
- import { Sentiment } from '../common';
6
- import Image from '../image';
7
- import Link from '../link';
8
- import Money from '../money';
9
- import React from 'react';
10
-
11
- export default {
12
- title: 'Forms/MoneyInputField',
13
- component: MoneyInputField,
14
- } as Meta;
15
-
16
- const props: MoneyInputFieldProps = {
17
- label: 'You send',
18
- currency: 'GBP',
19
- amount: 1234.56,
20
- onAmountChange: (amount) => {
21
- console.log('Amount changed', amount);
22
- },
23
- currencySelector: {
24
- addons: [
25
- { asset: <Image src="../avatar-square-dude.webp" alt="" /> },
26
- { profileName: 'Test Test' },
27
- ],
28
- options: [
29
- {
30
- title: 'Popular',
31
- currencies: [
32
- { code: 'USD', label: 'US Dollar', keywords: ['dollar', 'us'] },
33
- { code: 'AUD', label: 'Australia Dollar', keywords: ['dollar', 'us'] },
34
- ],
35
- },
36
- {
37
- title: 'Others',
38
- currencies: [
39
- { code: 'GBP', label: 'Pound', keywords: ['british'] },
40
- { code: 'EUR', label: 'Euro', keywords: ['euro'] },
41
- ],
42
- },
43
- ],
44
- onOpen: () => {
45
- console.log('Currency selector opened');
46
- },
47
- onSearchChange: (payload) => {
48
- console.log('Search changed', payload);
49
- },
50
- onChange: (currency) => {
51
- console.log('Currency changed', currency);
52
- },
53
- },
54
- loading: false,
55
- inlinePrompt: { message: lorem10, sentiment: Sentiment.POSITIVE },
56
- showChevron: true,
57
- autoFocus: true,
58
- };
59
-
60
- export const NullAmount = {
61
- args: props,
62
- render: (args: MoneyInputFieldProps) => (
63
- <MoneyInputField
64
- label={args.label}
65
- amount={null}
66
- currency="EUR"
67
- onAmountChange={args.onAmountChange}
68
- />
69
- ),
70
- };
71
-
72
- export const WithInitAmount = {
73
- args: props,
74
- render: (args: MoneyInputFieldProps) => {
75
- const availableBalance = 1500;
76
- return (
77
- <MoneyInputField
78
- label={args.label}
79
- amount={availableBalance}
80
- currency="EUR"
81
- onAmountChange={args.onAmountChange}
82
- />
83
- );
84
- },
85
- };
86
-
87
- export const WithLoading = {
88
- args: props,
89
- render: (args: MoneyInputFieldProps) => {
90
- const availableBalance = 1500;
91
- return (
92
- <MoneyInputField
93
- label={args.label}
94
- amount={availableBalance}
95
- currency="EUR"
96
- loading
97
- onAmountChange={args.onAmountChange}
98
- />
99
- );
100
- },
101
- };
102
-
103
- export const WithoutChevron = {
104
- args: props,
105
- render: (args: MoneyInputFieldProps) => {
106
- const availableBalance = 1500;
107
- return (
108
- <MoneyInputField
109
- label={args.label}
110
- amount={availableBalance}
111
- currency="EUR"
112
- showChevron={false}
113
- onAmountChange={args.onAmountChange}
114
- />
115
- );
116
- },
117
- };
118
-
119
- export const WithCurrencySelector = {
120
- args: props,
121
- render: (args: MoneyInputFieldProps) => {
122
- const availableBalance = 1500;
123
- return (
124
- <MoneyInputField
125
- label={args.label}
126
- amount={availableBalance}
127
- currency="EUR"
128
- currencySelector={args.currencySelector}
129
- onAmountChange={args.onAmountChange}
130
- />
131
- );
132
- },
133
- };
134
-
135
- export const WithInlinePromptNoSentiment = {
136
- args: props,
137
- render: (args: MoneyInputFieldProps) => {
138
- const availableBalance = 1500;
139
- const [sourceAmount, setSourceAmount] = React.useState(args.amount);
140
- return (
141
- <MoneyInputField
142
- label={args.label}
143
- amount={sourceAmount}
144
- currency="EUR"
145
- currencySelector={args.currencySelector}
146
- inlinePrompt={{
147
- message: (
148
- <>
149
- {`Available balance `}
150
- <Link
151
- onClick={() => {
152
- setSourceAmount(availableBalance);
153
- }}
154
- >
155
- <Money amount={availableBalance} currency={args.currency} />
156
- </Link>
157
- </>
158
- ),
159
- }}
160
- onAmountChange={args.onAmountChange}
161
- />
162
- );
163
- },
164
- };
165
-
166
- export const WithInlinePromptSentiment = {
167
- args: props,
168
- render: (args: MoneyInputFieldProps) => {
169
- const availableBalance = 1500;
170
- return (
171
- <MoneyInputField
172
- label={args.label}
173
- amount={availableBalance}
174
- currency="EUR"
175
- currencySelector={args.currencySelector}
176
- inlinePrompt={args.inlinePrompt}
177
- onAmountChange={args.onAmountChange}
178
- />
179
- );
180
- },
181
- };
182
-
183
- export const Autofocus = {
184
- args: props,
185
- render: (args: MoneyInputFieldProps) => (
186
- <MoneyInputField {...args} currency="MXN" inlinePrompt={undefined} />
187
- ),
188
- };
@@ -1,123 +0,0 @@
1
- import { Body, Label } from '..';
2
- import { clsx } from 'clsx';
3
- import { AnimatePresence, motion } from 'framer-motion';
4
- import { useId, type ReactNode } from 'react';
5
-
6
- import { type Props as CurrencySelectorProps, CurrencySelector } from './CurrencySelector';
7
- import { CommonProps } from '../common';
8
- import { AmountInput } from './AmountInput';
9
- import { Chevron } from './Chevron';
10
- import { InlinePrompt, type InlinePromptProps } from '../prompt/InlinePrompt';
11
-
12
- type AmountType = number | null;
13
- export type CurrencyType = string;
14
-
15
- type DefaultCurrencySelectorInstanceType = Pick<
16
- CurrencySelectorProps,
17
- 'addons' | 'options' | 'onChange' | 'onOpen' | 'onSearchChange'
18
- >;
19
- type CustomCurrencySelectorInstanceType = (props: { id: string; labelId: string }) => ReactNode;
20
- type CurrencySelectorType =
21
- | DefaultCurrencySelectorInstanceType
22
- | CustomCurrencySelectorInstanceType;
23
-
24
- export type Props = {
25
- label?: ReactNode;
26
- currencySelector?: CurrencySelectorType;
27
- amount?: AmountType;
28
- currency: CurrencyType;
29
- inlinePrompt?: {
30
- sentiment?: InlinePromptProps['sentiment'];
31
- message: InlinePromptProps['children'];
32
- };
33
- showChevron?: boolean;
34
- autoFocus?: boolean;
35
- loading?: boolean;
36
- onAmountChange: (amount: AmountType) => void;
37
- onFocusChange?: (focused: boolean) => void;
38
- } & CommonProps;
39
-
40
- export default function MoneyInputField({
41
- label,
42
- currency,
43
- currencySelector = { options: [] } as DefaultCurrencySelectorInstanceType,
44
- amount,
45
- onAmountChange,
46
- className,
47
- inlinePrompt,
48
- showChevron,
49
- autoFocus,
50
- loading,
51
- onFocusChange,
52
- }: Props) {
53
- const inputId = useId();
54
- const labelId = useId();
55
- const customAlertId = useId();
56
- const currencyId = useId();
57
-
58
- const selector =
59
- typeof currencySelector === 'function' ? (
60
- currencySelector({ id: currencyId, labelId })
61
- ) : (
62
- <CurrencySelector
63
- id={currencyId}
64
- labelId={labelId}
65
- currency={currency}
66
- {...currencySelector}
67
- />
68
- );
69
-
70
- return (
71
- <div className={clsx('wds-money-input-field', className)}>
72
- <Label id={labelId} htmlFor={inputId} className={clsx('m-b-1', 'font-weight-normal')}>
73
- {label}
74
- </Label>
75
- <div
76
- className={clsx('d-flex')}
77
- role="group"
78
- aria-labelledby={labelId}
79
- {...(inlinePrompt ? { 'aria-describedby': customAlertId } : {})}
80
- >
81
- <div className="wds-money-input-field-currency-selector">{selector}</div>
82
- <AmountInput
83
- id={inputId}
84
- describedById={currencyId}
85
- amount={amount}
86
- currency={currency}
87
- // eslint-disable-next-line jsx-a11y/no-autofocus
88
- autoFocus={autoFocus}
89
- loading={loading}
90
- onChange={onAmountChange}
91
- onFocusChange={onFocusChange}
92
- />
93
- <div className={clsx('d-flex align-items-center', 'wds-money-input-field-chevron')}>
94
- <Chevron shouldShow={Boolean(showChevron)} />
95
- </div>
96
- </div>
97
- <AnimatePresence initial={false}>
98
- {inlinePrompt && (
99
- <div className={clsx('d-flex justify-content-end', inlinePrompt && 'm-t-1')}>
100
- <motion.div
101
- key={customAlertId}
102
- initial={{ opacity: 0, height: 0 }}
103
- animate={{
104
- opacity: 1,
105
- height: 'auto',
106
- transition: { delay: 0.75, duration: 0.3 },
107
- }}
108
- exit={{ opacity: 0, height: 0 }}
109
- >
110
- {inlinePrompt.sentiment ? (
111
- <InlinePrompt id={customAlertId} sentiment={inlinePrompt.sentiment}>
112
- {inlinePrompt.message}
113
- </InlinePrompt>
114
- ) : (
115
- <Body>{inlinePrompt.message}</Body>
116
- )}
117
- </motion.div>
118
- </div>
119
- )}
120
- </AnimatePresence>
121
- </div>
122
- );
123
- }
@@ -1,2 +0,0 @@
1
- export type { Props as MoneyInputFieldProps } from './MoneyInputField';
2
- export { default } from './MoneyInputField';
@@ -1,35 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
-
3
- const focusTimeout = 5 * 1000;
4
-
5
- export const useFocus = () => {
6
- const [focus, setFocus] = useState(false);
7
- const [visualFocus, setVisualFocus] = useState(false);
8
- const [counter, setCounter] = useState(0);
9
-
10
- useEffect(() => {
11
- if (focus) {
12
- const timeout = setTimeout(() => {
13
- setVisualFocus(false);
14
- }, focusTimeout);
15
- return () => clearTimeout(timeout);
16
- }
17
- }, [focus, counter]);
18
-
19
- return {
20
- focus,
21
- setFocus: (value: boolean) => {
22
- setFocus(value);
23
- if (value) {
24
- setVisualFocus(true);
25
- }
26
- // any call to setFocus should reset the timeout, even if the input was already in focus
27
- // updating the counter will trigger the useEffect to reset the timeout
28
- setCounter((prev) => prev + 1);
29
- },
30
- visualFocus,
31
- setVisualFocus: (value: boolean) => {
32
- setVisualFocus(value);
33
- },
34
- };
35
- };
@@ -1,85 +0,0 @@
1
- import { type CSSProperties, useEffect, useLayoutEffect, useState } from 'react';
2
- import { Props as MoneyInputFieldProps } from './MoneyInputField';
3
-
4
- type InputStyleObject = {
5
- value: string;
6
- focus: boolean;
7
- inputElement: HTMLInputElement | null;
8
- } & Pick<MoneyInputFieldProps, 'loading'>;
9
-
10
- export const useInputStyle = ({ value, focus, inputElement, loading }: InputStyleObject) => {
11
- const initialRender = !useTimeout(300);
12
- const inputWidth = useFirstDefinedValue(inputElement?.clientWidth, [inputElement, value]);
13
-
14
- const getStyle = (): CSSProperties => {
15
- const fontSize = getFontSize(value, focus, inputWidth);
16
-
17
- return {
18
- fontSize,
19
- height: fontSize,
20
- // aligns the top of the digit with the currency button
21
- marginTop: fontSize * -0.19,
22
- // if the input loads with a pre-filled value, we don't want to animate the font-size immediately
23
- transition: initialRender ? 'none' : undefined,
24
- color: loading ? 'var(--color-interactive-secondary)' : undefined,
25
- };
26
- };
27
-
28
- const [style, setStyle] = useState(getStyle());
29
-
30
- useLayoutEffect(() => {
31
- setStyle(getStyle());
32
- }, [value, focus, loading, inputWidth]);
33
-
34
- return style;
35
- };
36
-
37
- function getFontSize(inputValue: string, isFocused: boolean, inputWidth: number | undefined) {
38
- const defaultFontSize = 52;
39
- const focusFontSize = 90;
40
- const minimumFontSize = 34;
41
-
42
- let fontSize = isFocused ? focusFontSize : defaultFontSize;
43
-
44
- if (typeof inputWidth === 'undefined') {
45
- return fontSize;
46
- }
47
- const textLength = inputValue.length;
48
- const maxCharactersWithoutShrinking = Math.floor(inputWidth / 40);
49
-
50
- if (textLength > maxCharactersWithoutShrinking) {
51
- const adjustedSize = Math.round((inputWidth / textLength) * 1.9);
52
- fontSize = Math.min(fontSize, adjustedSize);
53
- }
54
-
55
- return Math.max(fontSize, minimumFontSize);
56
- }
57
-
58
- const useFirstDefinedValue = (newValue: number | undefined, dependencies: unknown[]) => {
59
- const [value, setValue] = useState<number | undefined>(newValue);
60
-
61
- useLayoutEffect(() => {
62
- if (typeof newValue !== 'undefined' && typeof value === 'undefined') {
63
- setValue(newValue);
64
- }
65
- // eslint-disable-next-line react-hooks/exhaustive-deps
66
- }, [...dependencies, value]);
67
-
68
- return value;
69
- };
70
-
71
- const useTimeout = (delay: number) => {
72
- const [ready, setReady] = useState(false);
73
-
74
- useEffect(() => {
75
- const timeout = setTimeout(() => {
76
- setReady(true);
77
- }, delay);
78
-
79
- return () => {
80
- clearTimeout(timeout);
81
- };
82
- }, [delay]);
83
-
84
- return ready;
85
- };
@@ -1,23 +0,0 @@
1
- import { type SyntheticEvent, useRef } from 'react';
2
-
3
- export const useSelectionRange = () => {
4
- const selection = useRef<{
5
- selectionStart: number | null;
6
- selectionEnd: number | null;
7
- }>();
8
-
9
- const handleSelect = (e: SyntheticEvent<HTMLInputElement>) => {
10
- const input = e.target as HTMLInputElement;
11
- const { selectionStart, selectionEnd } = input;
12
- selection.current = { selectionStart, selectionEnd };
13
- };
14
- const handleSelectionBlur = () => {
15
- selection.current = undefined;
16
- };
17
-
18
- return {
19
- selection: selection.current,
20
- handleSelect,
21
- handleSelectionBlur,
22
- };
23
- };
@@ -1,114 +0,0 @@
1
- import {
2
- getDecimalSeparator,
3
- getFormattedString,
4
- getGroupSeparator,
5
- getUnformattedNumber,
6
- } from './utils';
7
-
8
- describe('utils', () => {
9
- describe('getDecimalSeparator', () => {
10
- it('gets decimal separator for Spanish', () => {
11
- expect(getDecimalSeparator('EUR', 'es')).toBe(',');
12
- });
13
-
14
- it('gets decimal separator for English', () => {
15
- expect(getDecimalSeparator('EUR', 'en')).toBe('.');
16
- });
17
-
18
- it('gets decimal separator for Spanish in HUF', () => {
19
- expect(getDecimalSeparator('HUF', 'es')).toBe('');
20
- });
21
-
22
- it('gets decimal separator for English in HUF', () => {
23
- expect(getDecimalSeparator('HUF', 'en')).toBe('');
24
- });
25
- });
26
-
27
- describe('getGroupSeparator', () => {
28
- it('gets group separator for Spanish', () => {
29
- expect(getGroupSeparator('EUR', 'es')).toBe('.');
30
- });
31
-
32
- it('gets group separator for English', () => {
33
- expect(getGroupSeparator('EUR', 'en')).toBe(',');
34
- });
35
-
36
- it('gets group separator for French', () => {
37
- expect(getGroupSeparator('EUR', 'fr')).toBe(' ');
38
- });
39
- });
40
-
41
- describe('getUnformattedNumber', () => {
42
- it('can turn a Spanish string into a number', () => {
43
- expect(
44
- getUnformattedNumber({
45
- value: '123.456,00',
46
- currency: 'EUR',
47
- locale: 'es',
48
- }),
49
- ).toBe(123456);
50
- });
51
-
52
- it('can turn a French string into a number', () => {
53
- expect(
54
- getUnformattedNumber({
55
- value: '1 234 567,45',
56
- currency: 'EUR',
57
- locale: 'fr',
58
- }),
59
- ).toBe(1234567.45);
60
- });
61
-
62
- it('can turn a English string into a number', () => {
63
- expect(
64
- getUnformattedNumber({
65
- value: '123,456.78',
66
- currency: 'EUR',
67
- locale: 'en',
68
- }),
69
- ).toBe(123456.78);
70
- });
71
-
72
- it('can turn a Magyar string into a number', () => {
73
- expect(
74
- getUnformattedNumber({
75
- value: '11 000 000',
76
- currency: 'HUF',
77
- locale: 'hu',
78
- }),
79
- ).toBe(11000000);
80
- });
81
- });
82
-
83
- describe('getFormattedString', () => {
84
- it('can turn a number into a Spanish string', () => {
85
- expect(
86
- getFormattedString({
87
- value: 123456.45,
88
- currency: 'EUR',
89
- locale: 'es',
90
- }),
91
- ).toBe('123.456,45');
92
- });
93
-
94
- it('can turn a number into a French string', () => {
95
- expect(
96
- getFormattedString({
97
- value: 1234567.45,
98
- currency: 'EUR',
99
- locale: 'fr',
100
- }),
101
- ).toBe('1 234 567,45');
102
- });
103
-
104
- it('can turn a number into a English string', () => {
105
- expect(
106
- getFormattedString({
107
- value: 123456.78,
108
- currency: 'EUR',
109
- locale: 'en',
110
- }),
111
- ).toBe('123,456.78');
112
- });
113
- });
114
- });